hgbook

changeset 1032:a55f319bcc67

Merge with Romain Pelisse
author Bryan O'Sullivan <bos@serpentine.com>
date Sat Jul 10 06:24:49 2010 +0100 (2010-07-10)
parents d6d7136b0f74 2ac31ea48a3d
children 47f3810fd4fd
files it/ch06-collab.xml it/web/index-home.html.in
line diff
     1.1 --- a/.hgignore	Sat Jul 10 06:24:30 2010 +0100
     1.2 +++ b/.hgignore	Sat Jul 10 06:24:49 2010 +0100
     1.3 @@ -25,6 +25,8 @@
     1.4  en/examples/results
     1.5  en/html
     1.6  en/svn
     1.7 +fr/examples/results
     1.8 +fr/html
     1.9  it/examples/results
    1.10  it/html
    1.11  stylesheets/system-xsl
     2.1 --- a/.hgtags	Sat Jul 10 06:24:30 2010 +0100
     2.2 +++ b/.hgtags	Sat Jul 10 06:24:49 2010 +0100
     2.3 @@ -1,2 +1,3 @@
     2.4  18131160f7ee3b81bf39ce2c58f762b8d671cef3 submitted
     2.5  94d2205f02e7c47931db382a3a80553ef01b3913 1st-edition-it
     2.6 +a6b81cd31cfd5da20e0dc629ee65cc4f3b08eb58 french-xdoc-build-fixed
     3.1 --- a/Makefile	Sat Jul 10 06:24:30 2010 +0100
     3.2 +++ b/Makefile	Sat Jul 10 06:24:49 2010 +0100
     3.3 @@ -6,7 +6,7 @@
     3.4  FORMATS=html html-single pdf epub
     3.5  
     3.6  PO_LANGUAGES := zh
     3.7 -DBK_LANGUAGES := en it
     3.8 +DBK_LANGUAGES := en it fr
     3.9  LANGUAGES := $(DBK_LANGUAGES) $(PO_LANGUAGES)
    3.10  
    3.11  UPDATEPO = PERLLIB=$(PO4A_LIB) $(PO4A_HOME)/po4a-updatepo -M UTF-8 \
    3.12 @@ -213,7 +213,11 @@
    3.13  	    stylesheets/$(LINGUA)/fo.xsl \
    3.14  	    fop1.extensions=1
    3.15  
    3.16 -	(cd build/$(LINGUA)/source && $(FOP_HOME)/fop.sh -c $(FOP_HOME)/conf/userconfig.xml hgbook.fo ../pdf/hgbook.pdf)
    3.17 +	if test -r $(FOP_HOME)/conf/userconfig.xml ; then \
    3.18 +		FOP_CONFIG=" -c $(FOP_HOME)/conf/userconfig.xml"; \
    3.19 +	fi 
    3.20 +
    3.21 +	(cd build/$(LINGUA)/source && $(FOP_HOME)/fop.sh ${FOP_CONFIG} hgbook.fo ../pdf/hgbook.pdf)
    3.22  endif
    3.23  
    3.24  $(LINGUA)/figs/%.png: $(LINGUA)/figs/%.svg 
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/fr/00book.xml	Sat Jul 10 06:24:49 2010 +0100
     4.3 @@ -0,0 +1,110 @@
     4.4 +<?xml version="1.0" encoding="UTF-8"?>
     4.5 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
     4.6 +<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
     4.7 + "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd"
     4.8 +[
     4.9 +<!-- Below are references to files in this directory. -->
    4.10 +
    4.11 +<!-- Chapters. -->
    4.12 +
    4.13 +<!ENTITY ch00     SYSTEM "ch00-preface.xml">
    4.14 +<!ENTITY ch01     SYSTEM "ch01-intro.xml">
    4.15 +<!ENTITY ch02     SYSTEM "ch02-tour-basic.xml">
    4.16 +<!ENTITY ch03     SYSTEM "ch03-tour-merge.xml">
    4.17 +<!ENTITY ch04     SYSTEM "ch04-concepts.xml">
    4.18 +<!ENTITY ch05     SYSTEM "ch05-daily.xml">
    4.19 +<!ENTITY ch06     SYSTEM "ch06-collab.xml">
    4.20 +<!ENTITY ch07     SYSTEM "ch07-filenames.xml">
    4.21 +<!ENTITY ch08     SYSTEM "ch08-branch.xml">
    4.22 +<!ENTITY ch09     SYSTEM "ch09-undo.xml">
    4.23 +<!ENTITY ch10     SYSTEM "ch10-hook.xml">
    4.24 +<!ENTITY ch11     SYSTEM "ch11-template.xml">
    4.25 +<!ENTITY ch12     SYSTEM "ch12-mq.xml">
    4.26 +<!ENTITY ch13     SYSTEM "ch13-mq-collab.xml">
    4.27 +<!ENTITY ch14     SYSTEM "ch14-hgext.xml">
    4.28 +<!ENTITY appA     SYSTEM "appA-svn.xml">
    4.29 +<!ENTITY appB     SYSTEM "appB-mq-ref.xml">
    4.30 +<!ENTITY appC     SYSTEM "appC-srcinstall.xml">
    4.31 +<!ENTITY appD     SYSTEM "appD-license.xml">
    4.32 +
    4.33 +<!-- Include our standard shortcuts. -->
    4.34 +
    4.35 +<!ENTITY % SHORTCUTS SYSTEM "book-shortcuts.xml">
    4.36 +%SHORTCUTS;
    4.37 +
    4.38 +<!-- Include automatically and manually generated code snippets. -->
    4.39 +
    4.40 +<!ENTITY % AUTOSNIPPETS SYSTEM "examples/auto-snippets.xml">
    4.41 +%AUTOSNIPPETS;
    4.42 +]>
    4.43 +
    4.44 +<book id="hg">
    4.45 +  <title>Mercurial: The Definitive Guide</title>
    4.46 +  
    4.47 +  <!-- hg parents &#x2d;&#x2d;template '{node|short} ({date|shortdate})' 
    4.48 +  <subtitle>Compiled from 8a1d3f1aff17 (2009-03-10)</subtitle>
    4.49 +  -->
    4.50 +  <subtitle>Compiled from $rev_id$</subtitle>
    4.51 +  <bookinfo>
    4.52 +    <edition>1</edition>
    4.53 +    <isbn>9780596800673</isbn>
    4.54 +    <authorgroup>
    4.55 +      <author>
    4.56 +        <firstname>Bryan</firstname>
    4.57 +        <surname>O'Sullivan</surname>
    4.58 +      </author>
    4.59 +    </authorgroup>
    4.60 +
    4.61 +    <editor>
    4.62 +      <firstname>Mike</firstname>
    4.63 +      <surname>Loukides</surname>
    4.64 +    </editor>
    4.65 +
    4.66 +    <copyright>
    4.67 +      <year>2006</year>
    4.68 +      <year>2007</year>
    4.69 +      <year>2008</year>
    4.70 +      <year>2009</year>
    4.71 +      <holder>Bryan O'Sullivan</holder>
    4.72 +    </copyright>
    4.73 +  </bookinfo>
    4.74 +
    4.75 +  <!-- BEGIN ch00 -->
    4.76 +  &ch00;
    4.77 +  <!-- BEGIN ch01 -->
    4.78 +  &ch01;
    4.79 +  <!-- BEGIN ch02 -->
    4.80 +  &ch02;
    4.81 +  <!-- BEGIN ch03 -->
    4.82 +  &ch03;
    4.83 +  <!-- BEGIN ch04 -->
    4.84 +  &ch04;
    4.85 +  <!-- BEGIN ch05 -->
    4.86 +  &ch05;
    4.87 +  <!-- BEGIN ch06 -->
    4.88 +  &ch06;
    4.89 +  <!-- BEGIN ch07 -->
    4.90 +  &ch07;
    4.91 +  <!-- BEGIN ch08 -->
    4.92 +  &ch08;
    4.93 +  <!-- BEGIN ch09 -->
    4.94 +  &ch09;
    4.95 +  <!-- BEGIN ch10 -->
    4.96 +  &ch10;
    4.97 +  <!-- BEGIN ch11 -->
    4.98 +  &ch11;
    4.99 +  <!-- BEGIN ch12 -->
   4.100 +  &ch12;
   4.101 +  <!-- BEGIN ch13 -->
   4.102 +  &ch13;
   4.103 +  <!-- BEGIN ch14 -->
   4.104 +  &ch14;
   4.105 +  <!-- BEGIN appA -->
   4.106 +  &appA;
   4.107 +  <!-- BEGIN appB -->
   4.108 +  &appB;
   4.109 +  <!-- BEGIN appC -->
   4.110 +  &appC;
   4.111 +  <!-- BEGIN appD -->
   4.112 +  &appD;
   4.113 +</book>
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/fr/Makefile	Sat Jul 10 06:24:49 2010 +0100
     5.3 @@ -0,0 +1,219 @@
     5.4 +# This makefile requires GNU make.
     5.5 +
     5.6 +image-sources := $(wildcard figs/*.dot figs/*.gif figs/*.png figs/*.svg)
     5.7 +
     5.8 +xml-src-files := \
     5.9 +	00book.xml \
    5.10 +	app*.xml \
    5.11 +	ch*.xml
    5.12 +
    5.13 +image-dot := $(filter %.dot,$(image-sources))
    5.14 +image-svg := $(filter %.svg,$(image-sources))
    5.15 +image-oth := $(filter %.gif %.png,$(image-sources))
    5.16 +
    5.17 +obj-web := html
    5.18 +obj-websup := $(obj-web)/support
    5.19 +obj-web-read := $(obj-web)/read
    5.20 +
    5.21 +image-web := \
    5.22 +	$(image-dot:%.dot=$(obj-web-read)/%.png) \
    5.23 +	$(image-svg:%.svg=$(obj-web-read)/%.png) \
    5.24 +	$(image-oth:%=$(obj-web-read)/%)
    5.25 +
    5.26 +example-sources-by-name := \
    5.27 +	backout \
    5.28 +	bisect \
    5.29 +	branching \
    5.30 +	branch-named \
    5.31 +	branch-repo \
    5.32 +	cmdref \
    5.33 +	daily.copy \
    5.34 +	daily.files \
    5.35 +	daily.rename \
    5.36 +	daily.revert \
    5.37 +	extdiff \
    5.38 +	filenames \
    5.39 +	hook.msglen \
    5.40 +	hook.simple \
    5.41 +	issue29 \
    5.42 +	mq.guards \
    5.43 +	mq.qinit-help \
    5.44 +	mq.dodiff \
    5.45 +	mq.id \
    5.46 +	mq.tarball \
    5.47 +	mq.tools \
    5.48 +	mq.tutorial \
    5.49 +	rename.divergent \
    5.50 +	rollback \
    5.51 +	tag \
    5.52 +	template.simple \
    5.53 +	template.svnstyle \
    5.54 +	tour \
    5.55 +	tour-merge-conflict
    5.56 +
    5.57 +example-sources := \
    5.58 +	$(example-sources-by-name:%=examples/%) \
    5.59 +	$(wildcard examples/ch*/*)
    5.60 +
    5.61 +extras-web-base := \
    5.62 +	$(obj-web)/index.html \
    5.63 +	$(obj-web)/robots.txt \
    5.64 +	$(obj-websup)/form-min.js \
    5.65 +	$(obj-websup)/form.js \
    5.66 +	$(obj-websup)/hsbook.js \
    5.67 +	$(obj-websup)/jquery-min.js \
    5.68 +	$(obj-websup)/jquery.js \
    5.69 +	$(obj-websup)/styles.css
    5.70 +
    5.71 +extras-web := $(extras-web-base) $(extras-web-base:%=%.gz)
    5.72 +
    5.73 +xsltproc := xsltproc
    5.74 +xsltproc-opts := --nonet --xinclude --path '$(xml-path)'
    5.75 +
    5.76 +xmllint := xmllint
    5.77 +xmllint-opts := --noout --nonet --valid
    5.78 +
    5.79 +system-xsl-dir := $(firstword $(wildcard \
    5.80 +	/usr/share/sgml/docbook/xsl-stylesheets \
    5.81 +	/usr/share/xml/docbook/stylesheet/nwalsh \
    5.82 +	))
    5.83 +
    5.84 +# Bletcherousness.
    5.85 +
    5.86 +ifneq ($(wildcard /usr/share/sgml/docbook/xml-dtd-4.4-*),)
    5.87 +dtd-dir := $(wildcard /usr/share/sgml/docbook/xml-dtd-4.4-*)
    5.88 +else
    5.89 +ifneq ($(wildcard /usr/share/xml/docbook/schema/dtd/4.4),)
    5.90 +dtd-dir := $(wildcard /usr/share/xml/docbook/schema/dtd/4.4)
    5.91 +else
    5.92 +$(error Do not know where to look for DocBook XML 4.4 DTD)
    5.93 +endif
    5.94 +endif
    5.95 +
    5.96 +ifeq ($(system-xsl-dir),)
    5.97 +$(error add a suitable directory to system-xsl-dir)
    5.98 +endif
    5.99 +
   5.100 +example-prereqs := \
   5.101 +	/usr/bin/merge
   5.102 +
   5.103 +dist-sources := \
   5.104 +	../html/hgicon.png \
   5.105 +	../html/index.html.var \
   5.106 +	../html/index.en.html
   5.107 +
   5.108 +hg = $(shell which hg)
   5.109 +
   5.110 +hg-id = $(shell hg parents --template '{node|short}, dated {date|isodate},\n')
   5.111 +
   5.112 +hg-version = $(shell hg version -q | \
   5.113 +		     sed 's,.*(version \(unknown\|[a-f0-9+]*\)),\1,')
   5.114 +
   5.115 +all: web complete.xml
   5.116 +
   5.117 +../stylesheets/system-xsl: $(system-xsl-dir)
   5.118 +	ln -s $< $@
   5.119 +
   5.120 +web: ../stylesheets/system-xsl websup html
   5.121 +
   5.122 +html: $(obj-web-read)/index.html
   5.123 +
   5.124 +../web/index-read.html.in: ../web/genindex.py $(xml-src-files)
   5.125 +	cd ../web && ./genindex.py
   5.126 +
   5.127 +$(obj-web-read)/index.html: ../stylesheets/system-xsl .validated-00book.xml ../web/index-read.html.in
   5.128 +	xsltproc $(xsltproc-opts) -o $(obj-web-read)/x ../stylesheets/chunk-stylesheet.xsl 00book.xml
   5.129 +	python ../web/texpand.py ../web/index-read.html.in html/read/index.html
   5.130 +	for i in $(obj-web-read)/*.html; do \
   5.131 +	  gzip -9 -c $$i > $$i.gz; \
   5.132 +	done
   5.133 +
   5.134 +websup: $(extras-web) $(image-web)
   5.135 +	mkdir -p $(obj-websup)/figs $(obj-web-read)/figs
   5.136 +	cp ../stylesheets/system-xsl/images/*.png $(obj-websup)/figs
   5.137 +	cp -f ../web/icons/*.png $(obj-websup)/figs
   5.138 +
   5.139 +complete.xml: .validated-00book.xml
   5.140 +	$(xsltproc) $(xsltproc-opts) -o $@ ../stylesheets/dtd-profile.xsl 00book.xml
   5.141 +
   5.142 +all-ids.dat: ../stylesheets/all-ids.xsl $(xml-src-files)
   5.143 +	$(xsltproc) $(xsltproc-opts) -o $@ ../stylesheets/all-ids.xsl 00book.xml
   5.144 +
   5.145 +web: websup
   5.146 +
   5.147 +valid: .validated-00book.xml
   5.148 +
   5.149 +.validated-00book.xml: $(xml-src-files) examples/.run
   5.150 +	$(xmllint) --path '$(dtd-dir):$(xml-path)' $(xmllint-opts) $<
   5.151 +	touch $@
   5.152 +
   5.153 +# Produce 90dpi PNGs for the web.
   5.154 +
   5.155 +$(obj-web-read)/figs/%.png: $(obj-web-read)/figs/%.svg fixsvg
   5.156 +	mkdir -p $(dir $@)
   5.157 +	./fixsvg $<
   5.158 +	inkscape -D -e $@ $<-tmp.svg
   5.159 +	rm $<-tmp.svg
   5.160 +
   5.161 +$(obj-web-read)/figs/%.png: figs/%.svg fixsvg
   5.162 +	mkdir -p $(dir $@)
   5.163 +	./fixsvg $<
   5.164 +	inkscape -D -e $@ $<-tmp.svg
   5.165 +	rm $<-tmp.svg
   5.166 +
   5.167 +$(obj-web-read)/figs/%.gif: figs/%.gif
   5.168 +	cp $< $@
   5.169 +
   5.170 +$(obj-web-read)/figs/%.png: figs/%.png
   5.171 +	cp $< $@
   5.172 +
   5.173 +$(obj-web-read)/figs/%.svg: figs/%.dot
   5.174 +	mkdir -p $(dir $@)
   5.175 +	dot -Tsvg -o $@ $<
   5.176 +
   5.177 +examples: $(example-prereqs) examples/.run
   5.178 +
   5.179 +examples/.run: $(example-sources)
   5.180 +	cd examples && ./run-example -a
   5.181 +
   5.182 +examples/%.run: examples/% examples/run-example
   5.183 +
   5.184 +clean:
   5.185 +	-rm -rf dist html $(image-dot:%.dot=%.pdf) $(image-dot:%.dot=%.png) \
   5.186 +	  $(image-svg:%.svg=%.png) examples/*.{lxo,run} examples/.run
   5.187 +
   5.188 +install: html $(dist-sources)
   5.189 +	rm -rf dist
   5.190 +	mkdir -p dist
   5.191 +	cp html/*.{css,html,png} dist
   5.192 +	cp $(dist-sources) dist
   5.193 +
   5.194 +rsync: install
   5.195 +	rsync -avz --delete dist sp.red-bean.com:public_html/hgbook
   5.196 +
   5.197 +vpath %.css ../web
   5.198 +vpath %.html.in ../web
   5.199 +vpath %.js ../web/javascript
   5.200 +
   5.201 +$(obj-websup)/%.css: %.css
   5.202 +	@mkdir -p $(dir $@)
   5.203 +	cp $< $@
   5.204 +
   5.205 +$(obj-websup)/%.jpg: %.jpg
   5.206 +	@mkdir -p $(dir $@)
   5.207 +	cp $< $@
   5.208 +
   5.209 +$(obj-websup)/%.js: %.js
   5.210 +	@mkdir -p $(dir $@)
   5.211 +	cp $< $@
   5.212 +
   5.213 +$(obj-web)/%: ../web/%
   5.214 +	@mkdir -p $(dir $@)
   5.215 +	cp $< $@
   5.216 +
   5.217 +$(obj-web)/%.html: %.html.in
   5.218 +	@mkdir -p $(dir $@)
   5.219 +	python ../web/texpand.py $< $@
   5.220 +
   5.221 +%.gz: %
   5.222 +	gzip -9 -c $< > $@
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/fr/appA-svn.xml	Sat Jul 10 06:24:49 2010 +0100
     6.3 @@ -0,0 +1,557 @@
     6.4 +
     6.5 +
     6.6 +<appendix id="svn">
     6.7 +  <?dbhtml filename="migrating-to-mercurial.html"?>
     6.8 +<title>Migrer vers Mercurial</title>
     6.9 +
    6.10 +  <para id="x_6e1">Une manière courante de s'essayer à un nouveau
    6.11 +  gestionnaire de révisions est d'expérimenter en migrant un
    6.12 +  projet existant, plutôt que le faire avec un nouveau projet.
    6.13 +  </para>
    6.14 +
    6.15 +  <para id="x_6e2">Dans cette annexe, nous discuterons comment importer
    6.16 +  l'historique d'un projet dans Mercurial, et à quoi faire attention
    6.17 +  si vous êtes habitués à un autre outil de gestion de révisions.
    6.18 +   </para>
    6.19 +
    6.20 +  <sect1>
    6.21 +    <title>Importer l'historique depuis un autre système</title>
    6.22 +
    6.23 +    <para id="x_6e3">Mercurial est livré avec une extension nommée
    6.24 +      <literal>convert</literal>, qui permet d'importer un historique
    6.25 +      depuis les gestionnaire de révisions les plus courants. Au moment de 
    6.26 +      l'écriture de ce livre, il pouvait importer l'historique depuis:
    6.27 +      </para>
    6.28 +    <itemizedlist>
    6.29 +      <listitem>
    6.30 +	<para id="x_6e4">Subversion</para>
    6.31 +      </listitem>
    6.32 +      <listitem>
    6.33 +	<para id="x_6e5">CVS</para>
    6.34 +      </listitem>
    6.35 +      <listitem>
    6.36 +	<para id="x_6e6">git</para>
    6.37 +      </listitem>
    6.38 +      <listitem>
    6.39 +	<para id="x_6e7">Darcs</para>
    6.40 +      </listitem>
    6.41 +      <listitem>
    6.42 +	<para id="x_6e8">Bazaar</para>
    6.43 +      </listitem>
    6.44 +      <listitem>
    6.45 +	<para id="x_6e9">Monotone</para>
    6.46 +      </listitem>
    6.47 +      <listitem>
    6.48 +	<para id="x_6ea">GNU Arch</para>
    6.49 +      </listitem>
    6.50 +      <listitem>
    6.51 +	<para id="x_6eb">Mercurial</para>
    6.52 +      </listitem>
    6.53 +    </itemizedlist>
    6.54 +
    6.55 +    <para id="x_6ec">(Pour savoir pourquoi Mercurial lui même est supporté
    6.56 +    comme source, voir <xref linkend="svn.filemap"/>.)</para>
    6.57 +
    6.58 +    <para id="x_6ed">Vous pouvez activer l'extension de la manière
    6.59 +    habituelle, en éditant votre fichier <filename>~/.hgrc</filename></para>
    6.60 +
    6.61 +    <programlisting>[extensions]
    6.62 +convert =</programlisting>
    6.63 +
    6.64 +    <para id="x_6ee">Ceci rendra la commande <command>hg convert</command>
    6.65 +    disponible. La commande est facile à utiliser. Par exemple, la 
    6.66 +    commande suivante va importer l'historique Subversion du <emphasis
    6.67 +    remap="it">framework</emphasis> de test <quote>Nose Unit</quote> dans Mercurial.
    6.68 +      </para>
    6.69 +
    6.70 +    <screen><prompt>$</prompt> <userinput>hg convert http://python-nose.googlecode.com/svn/trunk</userinput></screen>
    6.71 +
    6.72 +    <para id="x_6ef">L'extension <literal>convert</literal> opère de 
    6.73 +    manière incrémentale. En d'autres mots, après une première exécution de
    6.74 +    la commande <command>hg convert</command>, les exécutions ultérieures
    6.75 +    importeront les révisions ultérieures à l'exécution précédente.
    6.76 +    La conversion incrémentale ne réussira que si
    6.77 +    vous exécutez <command>hg convert</command> dans le même dépôt que vous
    6.78 +    aviez utilisé à l'origine, ceci parce que l'extension <literal>convert</literal> 
    6.79 +    sauvegarde un certain nombre de méta-données privées dans le fichier
    6.80 +    <filename>.hg/shamap</filename> (non versioné) au sein du dépôt cible.
    6.81 +    </para>
    6.82 +
    6.83 +    <para id="x_707">Lorsque vous voulez faire des modifications en utilisant
    6.84 +    Mercurial, le mieux est de faire un clone de l'ensemble de l'arborescence 
    6.85 +    que vous souhaitez convertir, et de laisser l'arborescence d'origine pour
    6.86 +    de futures conversions incrémentales. C'est la manière la plus sûre pour vous laisser
    6.87 +    récupérer et fusionner les modifications futures depuis l'outil de gestion
    6.88 +    de révisions dans votre nouveau dépôt Mercurial.</para>
    6.89 +
    6.90 +    <sect2>
    6.91 +      <title>Convertir plusieurs branches</title>
    6.92 +
    6.93 +      <para id="x_708">La commande <command>hg convert</command> citée 
    6.94 +      ci-dessus convertit seulement l'historique de la <literal>branche
    6.95 +      principale (trunk)</literal> du dépôt Subversion. Si nous utilisons
    6.96 +      à la place l'URL <literal>http://python-nose.googlecode.com/svn</literal>,
    6.97 +      Mercurial va automatiquement détecter la  
    6.98 +      <literal>branche principale (trunk)</literal>, les <literal>étiquettes 
    6.99 +      (tags)</literal>, et les <literal>branches</literal>  que les dépôts
   6.100 +      Subversion utilisent généralement, et les importera chacun dans
   6.101 +      une branche Mercurial distincte.</para>
   6.102 +
   6.103 +      <para id="x_709">Par défaut, chaque branche Subversion importée 
   6.104 +     dans Mercurial se voit attribuer un nom de branche. Une fois la
   6.105 +     conversion achevée, vous pouvez obtenir la liste des noms des branches 
   6.106 +     actives dans le dépôt Mercurial en utilisant la commande
   6.107 +     <command>hg branches -a</command>. Si vous préférez importer les 
   6.108 +     branches Subversion sans noms, ajoutez l'option <option>--config
   6.109 +     convert.hg.usebranches=false</option> à la commande 
   6.110 +     <command>hg convert</command>.</para>
   6.111 +
   6.112 +      <para id="x_70a">Une fois votre arborescence convertie, 
   6.113 +      si vous souhaitez travailler selon la pratique habituelle sous Mercurial
   6.114 +      avec une arborescence qui ne contient qu'une seule branche, vous pouvez cloner
   6.115 +      cette seule branche en utilisant 
   6.116 +      <command>hg clone -r nomdemabranche</command>.</para>
   6.117 +    </sect2>
   6.118 +
   6.119 +    <sect2>
   6.120 +      <title>Associer les noms d'utilisateurs</title>
   6.121 +
   6.122 +      <para id="x_6f0">Certains outils de gestion de révisions
   6.123 +      ne sauvegardent, avec les modifications, que les noms 
   6.124 +      d'utilisateurs raccourcis. Ceux-ci peuvent être difficiles à 
   6.125 +      interpréter. La norme avec Mercurial est de sauvegarder le 
   6.126 +      nom du <emphasis remap="it">committeur</emphasis> et son adresse
   6.127 +      mail, ce qui est beaucoup plus utile pour discuter avec lui
   6.128 +      par la suite.</para>
   6.129 +
   6.130 +      <para id="x_6f1">Si vous convertissez une arborescence depuis
   6.131 +      un gestionnaire de révisions qui utilise seulement les noms
   6.132 +      raccourcis, vous pouvez associer ces noms à des équivalents 
   6.133 +      plus détaillés en passant l'option <option>--authors</option>
   6.134 +      à la commande <command>hg convert</command>. Cette option
   6.135 +      attend un fichier qui contient des entrées sous la forme suivante:
   6.136 +      </para>
   6.137 +
   6.138 +      <programlisting>arist = Aristotle &lt;aristotle@phil.example.gr&gt;
   6.139 +soc = Socrates &lt;socrates@phil.example.gr&gt;</programlisting>
   6.140 +
   6.141 +      <para id="x_6f2">Quand <literal>convert</literal> trouve une
   6.142 +      modification associée au nom <literal>arist</literal> dans le
   6.143 +      dépôt de source, il va utiliser le nom <literal>Aristotle
   6.144 +      &lt;aristotle@phil.example.gr&gt;</literal> dans les révisions
   6.145 +      Mercurial. Si aucune correspondance n'est trouvé, il utilise
   6.146 +      le nom tel quel.</para>
   6.147 +    </sect2>
   6.148 +
   6.149 +    <sect2 id="svn.filemap">
   6.150 +      <title>Nettoyer l'arboresence</title>
   6.151 +
   6.152 +      <para id="x_6f3">Tous les projets n'ont pas un historique parfait.
   6.153 +      Il peut y avoir des répertoires qui n'auraient jamais dû être ajoutés,
   6.154 +      un fichier qui est trop volumineux, ou même une partie de la
   6.155 +      hiérarchie qui devrait être réorganisée.</para>
   6.156 +
   6.157 +      <para id="x_6f4">L'extension <literal>convert</literal> permet
   6.158 +      d'utiliser un <quote>fichier d'association</quote> qui peut 
   6.159 +      réorganiser les fichiers et les répertoires dans un projet lors de
   6.160 +      l'importation de son historique. Ceci est utile non seulement quand vous
   6.161 +      importez l'historique d'un autre gestionnaire de révisions, mais
   6.162 +      aussi pour nettoyer ou réorganiser l'arborescence d'un projet
   6.163 +      Mercurial.</para>
   6.164 +
   6.165 +      <para id="x_6f5">Pour indiquer le fichier d'association, on utilise
   6.166 +      l'option <option>--filemap</option> en lui fournissant un nom de
   6.167 +      fichier. Le fichier d'association contient des lignes de la forme
   6.168 +      suivante :</para>
   6.169 +
   6.170 +      <programlisting># Ceci est un commentaire.
   6.171 +# Les lignes vides sont ignorées.
   6.172 +
   6.173 +include path/to/file
   6.174 +
   6.175 +exclude path/to/file
   6.176 +
   6.177 +rename from/some/path to/some/other/place
   6.178 +</programlisting>
   6.179 +      
   6.180 +      <para id="x_6f6">La directive <literal>include</literal> inclut un
   6.181 +      fichier, ou l'ensemble des fichiers d'un répertoire, dans le dépôt
   6.182 +      de destination. La directive <literal>exclude</literal> omet les
   6.183 +      fichiers ou répertoires du dépôt. Ceci inclut aussi les autres
   6.184 +      fichiers et répertoires qui ne sont pas explicitement inclus.
   6.185 +      La directive <literal>exclude</literal> entraine l'omission
   6.186 +      des fichiers ou répertoires, et autres fichiers qui ne sont pas
   6.187 +      explicitement inclus.</para>
   6.188 +
   6.189 +      <para id="x_6f7">Pour déplacer un fichier ou un répertoire d'un
   6.190 +      emplacement à un autre, utilisez la directive
   6.191 +      <literal>rename</literal>. Si vous avez besoin de déplacer un 
   6.192 +      fichier ou un répertoire depuis un sous répertoire dans la racine
   6.193 +      du dépôt, utilisez <literal>.</literal> comme second argument de 
   6.194 +      la directive <literal>rename</literal>.</para>
   6.195 +    </sect2>
   6.196 +
   6.197 +    <sect2>
   6.198 +      <title>Améliorer les performances de la conversion Subversion</title>
   6.199 +
   6.200 +      <para id="x_70b">Vous aurez souvent besoin de plusieurs essais
   6.201 +      avant d'arriver à la parfaite combinaison de fichier d'association de fichiers,
   6.202 +      de fichier d'association de noms d'utilisateurs et des autres paramètres. Or,
   6.203 +      convertir un dépôt Mercurial via un protocole comme <literal>ssh</literal>
   6.204 +      ou <literal>http</literal> peut être des milliers de fois plus long
   6.205 +      que ce dont le système d'exploitation est en fait capable de faire,
   6.206 +      à cause des latence réseau. Ceci peut rendre la conception de cette
   6.207 +      combinaison parfaite très douloureuse.</para>
   6.208 +
   6.209 +      <para id="x_70c">La commande <ulink
   6.210 +	  url="http://svn.collab.net/repos/svn/trunk/notes/svnsync.txt"><command>svnsync</command></ulink> 
   6.211 +	peut grandement améliorer la vitesse de conversion d'un dépôt
   6.212 +        Subversion. Il s'agit d'un programme de miroir de dépôt Subversion
   6.213 +        en lecture seule. L'idée est de créer un miroir local d'une
   6.214 +        arborescence Subversion, puis de convertir ce miroir en dépôt
   6.215 +        Mercurial.</para>
   6.216 +      
   6.217 +      <para id="x_70d">Supposez que nous voulions convertir le dépôt 
   6.218 +      Subversion du populaire projet Memcached en une arborescence Mercurial.
   6.219 +      Tout d'abord, nous créons un dépôt Subversion local.</para>
   6.220 +
   6.221 +      <screen><prompt>$</prompt> <userinput>svnadmin create memcached-mirror</userinput></screen>
   6.222 +
   6.223 +      <para id="x_70e">Puis, nous allons mettre en place un <quote>hook</quote> Subversion
   6.224 +      dont <command>svnsync</command> a besoin.</para>
   6.225 +
   6.226 +      <screen><prompt>$</prompt> <userinput>echo '#!/bin/sh' > memcached-mirror/hooks/pre-revprop-change</userinput>
   6.227 +<prompt>$</prompt> <userinput>chmod +x memcached-mirror/hooks/pre-revprop-change</userinput></screen>
   6.228 +
   6.229 +      <para id="x_70f">Nous initialisons ensuite <command>svnsync</command> dans ce
   6.230 +      dépôt.</para>
   6.231 +
   6.232 +      <screen><prompt>$</prompt> <userinput>svnsync --init file://`pwd`/memcached-mirror \
   6.233 +  http://code.sixapart.com/svn/memcached</userinput></screen>
   6.234 +
   6.235 +      <para id="x_710">La prochaine étape est de commencer le processus de
   6.236 +      mirroring de <command>svnsync</command>.</para>
   6.237 +
   6.238 +      <screen><prompt>$</prompt> <userinput>svnsync sync file://`pwd`/memcached-mirror</userinput></screen>
   6.239 +
   6.240 +      <para id="x_711">Enfin, nous importons l'historique de notre dépôt
   6.241 +      local Subversion dans Mercurial.</para>
   6.242 +
   6.243 +      <screen><prompt>$</prompt> <userinput>hg convert memcached-mirror</userinput></screen>
   6.244 +      
   6.245 +      <para id="x_712">Nous pouvons utiliser ce processus de manière
   6.246 +      incrémentale, si le dépôt Subversion est toujours en activité.
   6.247 +      Il suffit d'exécuter de nouveau <command>svnsync</command> pour
   6.248 +      récupérer les récentes modifications dans notre miroir, puis <command>hg 
   6.249 +      convert</command>
   6.250 +      les importe dans notre arborescence Mercurial.</para>
   6.251 +
   6.252 +      <para id="x_713">Il y a deux avantages à utiliser un import à deux
   6.253 +      étages comme avec <command>svnsync</command>. Le premier
   6.254 +      est qu'il utilise du code de synchronisation réseau de Subversion 
   6.255 +      plus efficace que la commande <command>hg convert</command>,
   6.256 +      et donc transfère moins de données par le réseau. Le deuxième
   6.257 +      est que l'import depuis un dépôt Subversion local est si rapide que
   6.258 +      vous pouvez peaufiner et réitérer les paramètres de conversion de 
   6.259 +      ce dernier sans souffrir de la qualité de la connexion réseau.</para>
   6.260 +    </sect2>
   6.261 +  </sect1>
   6.262 +
   6.263 +  <sect1>
   6.264 +    <title>Migrer depuis Subversion</title>
   6.265 +
   6.266 +    <para id="x_6f8">Subversion est le système de gestion de versions
   6.267 +    open source le plus populaire aujourd'hui. Bien qu'il y ait des
   6.268 +    différences entre Mercurial et Subversion, faire la transition de
   6.269 +    l'un à l'autre n'est pas très difficile. Les deux disposent en effet 
   6.270 +    de jeux de commandes similaires et d'interfaces similaires.</para>
   6.271 +
   6.272 +    <sect2>
   6.273 +      <title>Différences philosophiques</title>
   6.274 +
   6.275 +      <para id="x_6f9">La différence fondamentale entre Subversion et
   6.276 +      Mercurial est bien évidement que Subversion est centralisé, alors 
   6.277 +      que Mercurial est distribué. Puisque que Mercurial enregistre tout
   6.278 +      l'historique d'un projet sur votre disque dur local, il n'a besoin
   6.279 +      d'effectuer des accès au réseau que lorsque vous voulez
   6.280 +      explicitement communiquer avec un autre dépôt. Subversion, par contre,
   6.281 +      ne conserve que peu d'informations localement, et le client
   6.282 +      doit donc communiquer avec le serveur central pour la
   6.283 +      plupart des opérations communes.</para>
   6.284 +
   6.285 +      <para id="x_6fa">Subversion s'en tire plus ou moins bien sans notion
   6.286 +      de branche réellement bien définie : quelle portion de l'espace de nommage
   6.287 +      du serveur est une branche est une simple question de convention, le
   6.288 +      logiciel n'imposant rien à ce sujet. Mercurial considère
   6.289 +      un dépôt comme un élément de la gestion des branches.</para>
   6.290 +      
   6.291 +      <sect3>
   6.292 +	<title>Portée des commandes</title>
   6.293 +
   6.294 +	<para id="x_6fb">Puisque que Subversion ne sait pas réellement
   6.295 +        quelle partie de son espace de nommage est en fait une branche, il
   6.296 +        traite la plupart des commandes comme des requêtes à exécuter sur le
   6.297 +        répertoire où vous vous situez, et ses sous répertoires. Par exemple,
   6.298 +        si vous exécutez <command>svn log</command>, vous verrez l'historique 
   6.299 +        de la partie de l'arborescence où vous vous situez, et non de la
   6.300 +        hiérarchie entière.</para>
   6.301 +
   6.302 +	<para id="x_6fc">Les commandes de Mercurial ont un comportement
   6.303 +        différent : toutes les commandes s'appliquent à l'ensemble de l'arborescence
   6.304 +        du dépôt. Exécutez la commande <command>hg log</command> et elle vous
   6.305 +        donnera l'historique de l'ensemble de l'arborescence, quel que soit le
   6.306 +        sous-répertoire où vous vous situez. Si
   6.307 +        vous souhaitez obtenir l'historique d'un répertoire ou seulement d'un
   6.308 +        fichier, ajouter simplement le nom de celui-ci à la commande, par
   6.309 +        exemple <command>hg log src</command>.</para>
   6.310 +
   6.311 +	<para id="x_6fd">De ma propre expérience, cette différence dans leur
   6.312 +        comportement par défaut est probablement ce qui risque de vous
   6.313 +        surprendre le plus si vous passez régulièrement d'un outil à l'autre.</para>
   6.314 +      </sect3>
   6.315 +
   6.316 +      <sect3>
   6.317 +	<title>Opération multi utilisateur et sécurité</title>
   6.318 +
   6.319 +	<para id="x_6fe">Avec Subversion, il est normal (bien que légèrement
   6.320 +        désapprouvé) que différentes personnes collaborent sur une seule
   6.321 +        branche. Si Alice et Bob travaillent ensemble, et Alice ajoute ses
   6.322 +        modifications à leur branche partagée, Bob doit alors mettre à jour
   6.323 +        sa vue de la branche avant de pouvoir appliquer un commit.
   6.324 +        Puisqu'il n'a, à ce moment, pas effectué de commit
   6.325 +        des modifications qu'il a faites, il se peut qu'il ne corrompe 
   6.326 +        ou ne perde
   6.327 +        ses modifications pendant ou après la mise à jour.</para>
   6.328 +
   6.329 +	<para id="x_6ff">Mercurial encourage, à l'inverse, un modèle 
   6.330 +        "commit-puis-merge". Avant de récupérer des modifications depuis le 
   6.331 +        serveur, ou avant d'y envoyer les siennes, Bob enregistre ses 
   6.332 +        modifications de manière locale en appliquant un commit. C'est à dire
   6.333 +        que si Alice avait envoyé ses modifications sur le serveur avant
   6.334 +        que Bob n'envoie les siennes, ce dernier ne pourra le faire
   6.335 +        qu'après avoir récupéré et fusionné celles d'Alice avec les siennes. 
   6.336 +        Si Bob fait alors une
   6.337 +        erreur lors de la fusion, il pourra toujours restaurer sa version, pour
   6.338 +        laquelle il avait appliqué le commit.</para>
   6.339 +          
   6.340 +	<para id="x_700">Il est important de souligner qu'il s'agit de la
   6.341 +        manière habituelle de travailler avec ces outils. Subversion propose
   6.342 +        une manière plus sûre de "travailler-dans-votre-propre-branche", mais elle
   6.343 +        est assez complexe pour que, en pratique, elle ne soit que rarement utilisé.
   6.344 +        Mercurial propose de son côté un mode un peu moins sûr, permettant de
   6.345 +        récupérer des modifications par dessus des modifications non
   6.346 +        committées, qui reste toutefois très peu répandu.</para> 
   6.347 +      </sect3>
   6.348 +
   6.349 +      <sect3>
   6.350 +	<title>Publication vs changement locaux</title>
   6.351 +
   6.352 +	<para id="x_701">Une commande Subversion <command>svn
   6.353 +        commit</command> publie immédiatement les modifications sur le
   6.354 +        serveur, où elles peuvent être vu par n'importe qui doté d'un privilège
   6.355 +        de lecture.</para>
   6.356 +
   6.357 +	<para id="x_702">Avec Mercurial, les modifications sont toujours d'abord
   6.358 +        enregistrées localement, et doivent être par la suite transférés par
   6.359 +        la commande <command>hg push</command>.</para>
   6.360 +
   6.361 +	<para id="x_703">Chaque approche a ses avantages et ses inconvénients.
   6.362 +        Le modèle Subversion implique que les modifications soient publiées, et
   6.363 +        donc disponibles immédiatement. D'un autre coté, cela implique aussi
   6.364 +        que, pour pouvoir utiliser le logiciel normalement, un utilisateur doit 
   6.365 +        avoir les droits d'écriture dans le dépôt, et ce privilège n'est pas concédé 
   6.366 +        facilement par la plupart des projets Open Source.</para>
   6.367 +
   6.368 +	<para id="x_704">L'approche de Mercurial permet à quiconque de faire
   6.369 +        un clone du dépôt et d'y ajouter ses modifications sans jamais avoir
   6.370 +        besoin de la permission de quiconque, et l'on peut même publier ses
   6.371 +        modifications et continuer à participer comme on le désire. Toutefois, la
   6.372 +        distinction entre les commits et le transfert de ces derniers présente
   6.373 +        le risque que quelqu'un applique ses modifications par un commit local
   6.374 +        sur son portable et parte se promener pendant quelques jours en ayant
   6.375 +        oublié de les transférer, ce qui peut, dans certains rares cas,
   6.376 +        bloquer temporairement ses collaborateurs.</para>
   6.377 +      </sect3>
   6.378 +    </sect2>
   6.379 +
   6.380 +    <sect2>
   6.381 +      <title>Références des commandes</title>
   6.382 +
   6.383 +      <table>
   6.384 +	<title>Commandes Subversion et leurs équivalents Mercurial</title>
   6.385 +	<tgroup cols="3">
   6.386 +	  <thead>
   6.387 +	    <row>
   6.388 +	      <entry>Subversion</entry>
   6.389 +	      <entry>Mercurial</entry>
   6.390 +	      <entry>Notes</entry>
   6.391 +	    </row>
   6.392 +	  </thead>
   6.393 +	  <tbody>
   6.394 +	    <row>
   6.395 +	      <entry><command>svn add</command></entry>
   6.396 +	      <entry><command>hg add</command></entry>
   6.397 +	      <entry></entry>
   6.398 +	    </row>
   6.399 +	    <row>
   6.400 +	      <entry><command>svn blame</command></entry>
   6.401 +	      <entry><command>hg annotate</command></entry>
   6.402 +	      <entry></entry>
   6.403 +	    </row>
   6.404 +	    <row>
   6.405 +	      <entry><command>svn cat</command></entry>
   6.406 +	      <entry><command>hg cat</command></entry>
   6.407 +	      <entry></entry>
   6.408 +	    </row>
   6.409 +	    <row>
   6.410 +	      <entry><command>svn checkout</command></entry>
   6.411 +	      <entry><command>hg clone</command></entry>
   6.412 +	      <entry></entry>
   6.413 +	    </row>
   6.414 +	    <row>
   6.415 +	      <entry><command>svn cleanup</command></entry>
   6.416 +	      <entry>n/a</entry>
   6.417 +	      <entry>Aucun nettoyage nécessaire.</entry>
   6.418 +	    </row>
   6.419 +	    <row>
   6.420 +	      <entry><command>svn commit</command></entry>
   6.421 +	      <entry><command>hg commit</command>; <command>hg
   6.422 +		  push</command></entry>
   6.423 +	      <entry><command>hg push</command> publie les modifications
   6.424 +              après un commit.</entry>
   6.425 +	    </row>
   6.426 +	    <row>
   6.427 +	      <entry><command>svn copy</command></entry>
   6.428 +	      <entry><command>hg clone</command></entry>
   6.429 +	      <entry>Pour créer une nouvelle branche</entry>
   6.430 +	    </row>
   6.431 +	    <row>
   6.432 +	      <entry><command>svn copy</command></entry>
   6.433 +	      <entry><command>hg copy</command></entry>
   6.434 +	      <entry>Pour copier des fichiers ou des répertoires</entry>
   6.435 +	    </row>
   6.436 +	    <row>
   6.437 +	      <entry><command>svn delete</command> (<command>svn
   6.438 +		  remove</command>)</entry>
   6.439 +	      <entry><command>hg remove</command></entry>
   6.440 +	      <entry></entry>
   6.441 +	    </row>
   6.442 +	    <row>
   6.443 +	      <entry><command>svn diff</command></entry>
   6.444 +	      <entry><command>hg diff</command></entry>
   6.445 +	      <entry></entry>
   6.446 +	    </row>
   6.447 +	    <row>
   6.448 +	      <entry><command>svn export</command></entry>
   6.449 +	      <entry><command>hg archive</command></entry>
   6.450 +	      <entry></entry>
   6.451 +	    </row>
   6.452 +	    <row>
   6.453 +	      <entry><command>svn help</command></entry>
   6.454 +	      <entry><command>hg help</command></entry>
   6.455 +	      <entry></entry>
   6.456 +	    </row>
   6.457 +	    <row>
   6.458 +	      <entry><command>svn import</command></entry>
   6.459 +	      <entry><command>hg addremove</command>; <command>hg
   6.460 +		  commit</command></entry>
   6.461 +	      <entry></entry>
   6.462 +	    </row>
   6.463 +	    <row>
   6.464 +	      <entry><command>svn info</command></entry>
   6.465 +	      <entry><command>hg parents</command></entry>
   6.466 +	      <entry>Affiche la version sur la base de laquelle on travaille</entry>
   6.467 +	    </row>
   6.468 +	    <row>
   6.469 +	      <entry><command>svn info</command></entry>
   6.470 +	      <entry><command>hg showconfig
   6.471 +		  paths.default</command></entry>
   6.472 +	      <entry>Affiche de quelle URL est extrait ce dépôt</entry>
   6.473 +	    </row>
   6.474 +	    <row>
   6.475 +	      <entry><command>svn list</command></entry>
   6.476 +	      <entry><command>hg manifest</command></entry>
   6.477 +	      <entry></entry>
   6.478 +	    </row>
   6.479 +	    <row>
   6.480 +	      <entry><command>svn log</command></entry>
   6.481 +	      <entry><command>hg log</command></entry>
   6.482 +	      <entry></entry>
   6.483 +	    </row>
   6.484 +	    <row>
   6.485 +	      <entry><command>svn merge</command></entry>
   6.486 +	      <entry><command>hg merge</command></entry>
   6.487 +	      <entry></entry>
   6.488 +	    </row>
   6.489 +	    <row>
   6.490 +	      <entry><command>svn mkdir</command></entry>
   6.491 +	      <entry>n/a</entry>
   6.492 +	      <entry>Mercurial ne versionne pas les répertoires</entry>
   6.493 +	    </row>
   6.494 +	    <row>
   6.495 +	      <entry><command>svn move</command> (<command>svn
   6.496 +		  rename</command>)</entry>
   6.497 +	      <entry><command>hg rename</command></entry>
   6.498 +	      <entry></entry>
   6.499 +	    </row>
   6.500 +	    <row>
   6.501 +	      <entry><command>svn resolved</command></entry>
   6.502 +	      <entry><command>hg resolve -m</command></entry>
   6.503 +	      <entry></entry>
   6.504 +	    </row>
   6.505 +	    <row>
   6.506 +	      <entry><command>svn revert</command></entry>
   6.507 +	      <entry><command>hg revert</command></entry>
   6.508 +	      <entry></entry>
   6.509 +	    </row>
   6.510 +	    <row>
   6.511 +	      <entry><command>svn status</command></entry>
   6.512 +	      <entry><command>hg status</command></entry>
   6.513 +	      <entry></entry>
   6.514 +	    </row>
   6.515 +	    <row>
   6.516 +	      <entry><command>svn update</command></entry>
   6.517 +	      <entry><command>hg pull -u</command></entry>
   6.518 +	      <entry></entry>
   6.519 +	    </row>
   6.520 +	  </tbody>
   6.521 +	</tgroup>
   6.522 +      </table>
   6.523 +    </sect2>
   6.524 +  </sect1>
   6.525 +
   6.526 +  <sect1>
   6.527 +    <title>Conseils utiles pour les débutants</title>
   6.528 +
   6.529 +    <para id="x_705">Avec la plupart des gestionnaire de versions, afficher
   6.530 +    un diff associé à une révision peut être assez douloureux. Par exemple,
   6.531 +    avec Subversion, pour voir ce qui a été modifiée dans la révision 104654,
   6.532 +    vous devez saisir <command>svn diff -r104653:104654</command>. Mercurial
   6.533 +    élimine le besoin de saisir l'identifiant d'une révision deux fois dans
   6.534 +    ce cas classique. Pour un simple diff, <command>hg
   6.535 +    export 104654</command> suffit. Pour obtenir une entrée du journal suivie d'un diff,
   6.536 +    <command>hg log -r104654 -p</command>.</para>
   6.537 +
   6.538 +    <para id="x_706">Quand vous exécutez la commande <command>hg status</command>
   6.539 +    sans aucun argument, elle affiche l'état de l'ensemble de l'arborescence,
   6.540 +    avec des chemins relatifs partant de la racine du dépôt. Ceci rend
   6.541 +    difficile de copier un nom de fichier depuis la sortie de la commande
   6.542 +    <command>hg status</command> dans une autre ligne de commande. Si vous
   6.543 +    fournissez un fichier ou un répertoire à la commande <command>hg
   6.544 +    status</command>, elle va afficher les chemins relatif depuis votre
   6.545 +    répertoire courant à la place. Ainsi, pour avoir un état sur l'ensemble
   6.546 +    de l'arborescence à l'aide  de <command>hg status</command>, avec des
   6.547 +    chemins relatifs à votre répertoire courant, et non la racine du dépôt,
   6.548 +    ajoutez la sortie de <command>hg root</command> à la commande
   6.549 +    <command>hg status</command>. Vous pouvez le faire aisément sur un
   6.550 +    système Unix ainsi :</para>
   6.551 +
   6.552 +    <screen><prompt>$</prompt> <userinput>hg status `hg root`</userinput></screen>
   6.553 +  </sect1>
   6.554 +</appendix>
   6.555 +
   6.556 +<!--
   6.557 +local variables: 
   6.558 +sgml-parent-document: ("00book.xml" "book" "appendix")
   6.559 +end:
   6.560 +-->
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/fr/appB-mq-ref.xml	Sat Jul 10 06:24:49 2010 +0100
     7.3 @@ -0,0 +1,563 @@
     7.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
     7.5 +
     7.6 +<appendix id="chap:mqref">
     7.7 +  <?dbhtml filename="mercurial-queues-reference.html"?>
     7.8 +  <title>Mercurial Queues reference</title>
     7.9 +
    7.10 +  <sect1 id="sec:mqref:cmdref">
    7.11 +    <title>MQ command reference</title>
    7.12 +
    7.13 +    <para id="x_5e8">For an overview of the commands provided by MQ, use the
    7.14 +      command <command role="hg-cmd">hg help mq</command>.</para>
    7.15 +
    7.16 +    <sect2>
    7.17 +      <title><command role="hg-ext-mq">qapplied</command>&emdash;print
    7.18 +	applied patches</title>
    7.19 +
    7.20 +      <para id="x_5e9">The <command role="hg-ext-mq">qapplied</command> command
    7.21 +	prints the current stack of applied patches.  Patches are
    7.22 +	printed in oldest-to-newest order, so the last patch in the
    7.23 +	list is the <quote>top</quote> patch.</para>
    7.24 +
    7.25 +    </sect2>
    7.26 +    <sect2>
    7.27 +      <title><command role="hg-ext-mq">qcommit</command>&emdash;commit
    7.28 +	changes in the queue repository</title>
    7.29 +
    7.30 +      <para id="x_5ea">The <command role="hg-ext-mq">qcommit</command> command
    7.31 +	commits any outstanding changes in the <filename
    7.32 +	  role="special" class="directory">.hg/patches</filename>
    7.33 +	repository.  This command only works if the <filename
    7.34 +	  role="special" class="directory">.hg/patches</filename>
    7.35 +	directory is a repository, i.e. you created the directory
    7.36 +	using <command role="hg-cmd">hg qinit <option
    7.37 +	    role="hg-ext-mq-cmd-qinit-opt">-c</option></command> or
    7.38 +	ran <command role="hg-cmd">hg init</command> in the directory
    7.39 +	after running <command
    7.40 +	  role="hg-ext-mq">qinit</command>.</para>
    7.41 +
    7.42 +      <para id="x_5eb">This command is shorthand for <command role="hg-cmd">hg
    7.43 +	  commit --cwd .hg/patches</command>.</para>
    7.44 +    </sect2>
    7.45 +    <sect2>
    7.46 +	<title><command
    7.47 +	  role="hg-ext-mq">qdelete</command>&emdash;delete a patch
    7.48 +	from the <filename role="special">series</filename>
    7.49 +	file</title>
    7.50 +
    7.51 +      <para id="x_5ec">The <command role="hg-ext-mq">qdelete</command> command
    7.52 +	removes the entry for a patch from the <filename
    7.53 +	  role="special">series</filename> file in the <filename
    7.54 +	  role="special" class="directory">.hg/patches</filename>
    7.55 +	directory.  It does not pop the patch if the patch is already
    7.56 +	applied.  By default, it does not delete the patch file; use
    7.57 +	the <option role="hg-ext-mq-cmd-qdel-opt">-f</option> option
    7.58 +	to do that.</para>
    7.59 +
    7.60 +      <para id="x_5ed">Options:</para>
    7.61 +      <itemizedlist>
    7.62 +	<listitem><para id="x_5ee"><option
    7.63 +	      role="hg-ext-mq-cmd-qdel-opt">-f</option>: Delete the
    7.64 +	    patch file.</para>
    7.65 +	</listitem></itemizedlist>
    7.66 +
    7.67 +    </sect2>
    7.68 +    <sect2>
    7.69 +      <title><command role="hg-ext-mq">qdiff</command>&emdash;print a
    7.70 +	diff of the topmost applied patch</title>
    7.71 +
    7.72 +      <para id="x_5ef">The <command role="hg-ext-mq">qdiff</command> command
    7.73 +	prints a diff of the topmost applied patch. It is equivalent
    7.74 +	to <command role="hg-cmd">hg diff -r-2:-1</command>.</para>
    7.75 +
    7.76 +    </sect2>
    7.77 +    <sect2>
    7.78 +      <title><command role="hg-ext-mq">qfold</command>&emdash;move
    7.79 +	applied patches into repository history</title>
    7.80 +
    7.81 +      <para id="x_72d">The <command>hg qfinish</command> command converts the
    7.82 +	specified applied patches into permanent changes by moving
    7.83 +	them out of MQ's control so that they will be treated as
    7.84 +	normal repository history.</para>
    7.85 +    </sect2>
    7.86 +
    7.87 +    <sect2>
    7.88 +      <title><command role="hg-ext-mq">qfold</command>&emdash;merge
    7.89 +	(<quote>fold</quote>) several patches into one</title>
    7.90 +
    7.91 +      <para id="x_5f0">The <command role="hg-ext-mq">qfold</command> command
    7.92 +	merges multiple patches into the topmost applied patch, so
    7.93 +	that the topmost applied patch makes the union of all of the
    7.94 +	changes in the patches in question.</para>
    7.95 +
    7.96 +      <para id="x_5f1">The patches to fold must not be applied; <command
    7.97 +	  role="hg-ext-mq">qfold</command> will exit with an error if
    7.98 +	any is.  The order in which patches are folded is significant;
    7.99 +	<command role="hg-cmd">hg qfold a b</command> means
   7.100 +	<quote>apply the current topmost patch, followed by
   7.101 +	  <literal>a</literal>, followed by
   7.102 +	  <literal>b</literal></quote>.</para>
   7.103 +
   7.104 +      <para id="x_5f2">The comments from the folded patches are appended to the
   7.105 +	comments of the destination patch, with each block of comments
   7.106 +	separated by three asterisk
   7.107 +	(<quote><literal>*</literal></quote>) characters.  Use the
   7.108 +	<option role="hg-ext-mq-cmd-qfold-opt">-e</option> option to
   7.109 +	edit the commit message for the combined patch/changeset after
   7.110 +	the folding has completed.</para>
   7.111 +
   7.112 +      <para id="x_5f3">Options:</para>
   7.113 +      <itemizedlist>
   7.114 +	<listitem><para id="x_5f4"><option
   7.115 +	      role="hg-ext-mq-cmd-qfold-opt">-e</option>: Edit the
   7.116 +	    commit message and patch description for the newly folded
   7.117 +	    patch.</para>
   7.118 +	</listitem>
   7.119 +	<listitem><para id="x_5f5"><option
   7.120 +	      role="hg-ext-mq-cmd-qfold-opt">-l</option>: Use the
   7.121 +	    contents of the given file as the new commit message and
   7.122 +	    patch description for the folded patch.</para>
   7.123 +	</listitem>
   7.124 +	<listitem><para id="x_5f6"><option
   7.125 +	      role="hg-ext-mq-cmd-qfold-opt">-m</option>: Use the
   7.126 +	    given text as the new commit message and patch description
   7.127 +	    for the folded patch.</para>
   7.128 +	</listitem></itemizedlist>
   7.129 +
   7.130 +    </sect2>
   7.131 +    <sect2>
   7.132 +      <title><command
   7.133 +	  role="hg-ext-mq">qheader</command>&emdash;display the
   7.134 +	header/description of a patch</title>
   7.135 +
   7.136 +      <para id="x_5f7">The <command role="hg-ext-mq">qheader</command> command
   7.137 +	prints the header, or description, of a patch.  By default, it
   7.138 +	prints the header of the topmost applied patch. Given an
   7.139 +	argument, it prints the header of the named patch.</para>
   7.140 +
   7.141 +    </sect2>
   7.142 +    <sect2>
   7.143 +      <title><command role="hg-ext-mq">qimport</command>&emdash;import
   7.144 +	a third-party patch into the queue</title>
   7.145 +
   7.146 +      <para id="x_5f8">The <command role="hg-ext-mq">qimport</command> command
   7.147 +	adds an entry for an external patch to the <filename
   7.148 +	  role="special">series</filename> file, and copies the patch
   7.149 +	into the <filename role="special"
   7.150 +	  class="directory">.hg/patches</filename> directory.  It adds
   7.151 +	the entry immediately after the topmost applied patch, but
   7.152 +	does not push the patch.</para>
   7.153 +
   7.154 +      <para id="x_5f9">If the <filename role="special"
   7.155 +	  class="directory">.hg/patches</filename> directory is a
   7.156 +	repository, <command role="hg-ext-mq">qimport</command>
   7.157 +	automatically does an <command role="hg-cmd">hg add</command>
   7.158 +	of the imported patch.</para>
   7.159 +
   7.160 +    </sect2>
   7.161 +    <sect2>
   7.162 +      <title><command role="hg-ext-mq">qinit</command>&emdash;prepare
   7.163 +	a repository to work with MQ</title>
   7.164 +
   7.165 +      <para id="x_5fa">The <command role="hg-ext-mq">qinit</command> command
   7.166 +	prepares a repository to work with MQ.  It creates a directory
   7.167 +	called <filename role="special"
   7.168 +	  class="directory">.hg/patches</filename>.</para>
   7.169 +
   7.170 +      <para id="x_5fb">Options:</para>
   7.171 +      <itemizedlist>
   7.172 +	<listitem><para id="x_5fc"><option
   7.173 +	      role="hg-ext-mq-cmd-qinit-opt">-c</option>: Create
   7.174 +	    <filename role="special"
   7.175 +	      class="directory">.hg/patches</filename> as a repository
   7.176 +	    in its own right.  Also creates a <filename
   7.177 +	      role="special">.hgignore</filename> file that will
   7.178 +	    ignore the <filename role="special">status</filename>
   7.179 +	    file.</para>
   7.180 +	</listitem></itemizedlist>
   7.181 +
   7.182 +      <para id="x_5fd">When the <filename role="special"
   7.183 +	  class="directory">.hg/patches</filename> directory is a
   7.184 +	repository, the <command role="hg-ext-mq">qimport</command>
   7.185 +	and <command role="hg-ext-mq">qnew</command> commands
   7.186 +	automatically <command role="hg-cmd">hg add</command> new
   7.187 +	patches.</para>
   7.188 +
   7.189 +    </sect2>
   7.190 +    <sect2>
   7.191 +      <title><command role="hg-ext-mq">qnew</command>&emdash;create a
   7.192 +	new patch</title>
   7.193 +
   7.194 +      <para id="x_5fe">The <command role="hg-ext-mq">qnew</command> command
   7.195 +	creates a new patch.  It takes one mandatory argument, the
   7.196 +	name to use for the patch file.  The newly created patch is
   7.197 +	created empty by default.  It is added to the <filename
   7.198 +	  role="special">series</filename> file after the current
   7.199 +	topmost applied patch, and is immediately pushed on top of
   7.200 +	that patch.</para>
   7.201 +
   7.202 +      <para id="x_5ff">If <command role="hg-ext-mq">qnew</command> finds modified
   7.203 +	files in the working directory, it will refuse to create a new
   7.204 +	patch unless the <option
   7.205 +	  role="hg-ext-mq-cmd-qnew-opt">-f</option> option is used
   7.206 +	(see below).  This behavior allows you to <command
   7.207 +	  role="hg-ext-mq">qrefresh</command> your topmost applied
   7.208 +	patch before you apply a new patch on top of it.</para>
   7.209 +
   7.210 +      <para id="x_600">Options:</para>
   7.211 +      <itemizedlist>
   7.212 +	<listitem><para id="x_601"><option
   7.213 +	      role="hg-ext-mq-cmd-qnew-opt">-f</option>: Create a new
   7.214 +	    patch if the contents of the working directory are
   7.215 +	    modified.  Any outstanding modifications are added to the
   7.216 +	    newly created patch, so after this command completes, the
   7.217 +	    working directory will no longer be modified.</para>
   7.218 +	</listitem>
   7.219 +	<listitem><para id="x_602"><option
   7.220 +	      role="hg-ext-mq-cmd-qnew-opt">-m</option>: Use the given
   7.221 +	    text as the commit message. This text will be stored at
   7.222 +	    the beginning of the patch file, before the patch
   7.223 +	    data.</para>
   7.224 +	</listitem></itemizedlist>
   7.225 +
   7.226 +    </sect2>
   7.227 +    <sect2>
   7.228 +      <title><command role="hg-ext-mq">qnext</command>&emdash;print
   7.229 +	the name of the next patch</title>
   7.230 +
   7.231 +      <para id="x_603">The <command role="hg-ext-mq">qnext</command> command
   7.232 +	prints the name name of the next patch in the <filename
   7.233 +	  role="special">series</filename> file after the topmost
   7.234 +	applied patch.  This patch will become the topmost applied
   7.235 +	patch if you run <command
   7.236 +	  role="hg-ext-mq">qpush</command>.</para>
   7.237 +
   7.238 +    </sect2>
   7.239 +    <sect2>
   7.240 +      <title><command role="hg-ext-mq">qpop</command>&emdash;pop
   7.241 +	patches off the stack</title>
   7.242 +
   7.243 +      <para id="x_604">The <command role="hg-ext-mq">qpop</command> command
   7.244 +	removes applied patches from the top of the stack of applied
   7.245 +	patches.  By default, it removes only one patch.</para>
   7.246 +
   7.247 +      <para id="x_605">This command removes the changesets that represent the
   7.248 +	popped patches from the repository, and updates the working
   7.249 +	directory to undo the effects of the patches.</para>
   7.250 +
   7.251 +      <para id="x_606">This command takes an optional argument, which it uses as
   7.252 +	the name or index of the patch to pop to.  If given a name, it
   7.253 +	will pop patches until the named patch is the topmost applied
   7.254 +	patch.  If given a number, <command
   7.255 +	  role="hg-ext-mq">qpop</command> treats the number as an
   7.256 +	index into the entries in the series file, counting from zero
   7.257 +	(empty lines and lines containing only comments do not count).
   7.258 +	It pops patches until the patch identified by the given index
   7.259 +	is the topmost applied patch.</para>
   7.260 +
   7.261 +      <para id="x_607">The <command role="hg-ext-mq">qpop</command> command does
   7.262 +	not read or write patches or the <filename
   7.263 +	  role="special">series</filename> file.  It is thus safe to
   7.264 +	<command role="hg-ext-mq">qpop</command> a patch that you have
   7.265 +	removed from the <filename role="special">series</filename>
   7.266 +	file, or a patch that you have renamed or deleted entirely.
   7.267 +	In the latter two cases, use the name of the patch as it was
   7.268 +	when you applied it.</para>
   7.269 +
   7.270 +      <para id="x_608">By default, the <command role="hg-ext-mq">qpop</command>
   7.271 +	command will not pop any patches if the working directory has
   7.272 +	been modified.  You can override this behavior using the
   7.273 +	<option role="hg-ext-mq-cmd-qpop-opt">-f</option> option,
   7.274 +	which reverts all modifications in the working
   7.275 +	directory.</para>
   7.276 +
   7.277 +      <para id="x_609">Options:</para>
   7.278 +      <itemizedlist>
   7.279 +	<listitem><para id="x_60a"><option
   7.280 +	      role="hg-ext-mq-cmd-qpop-opt">-a</option>: Pop all
   7.281 +	    applied patches.  This returns the repository to its state
   7.282 +	    before you applied any patches.</para>
   7.283 +	</listitem>
   7.284 +	<listitem><para id="x_60b"><option
   7.285 +	      role="hg-ext-mq-cmd-qpop-opt">-f</option>: Forcibly
   7.286 +	    revert any modifications to the working directory when
   7.287 +	    popping.</para>
   7.288 +	</listitem>
   7.289 +	<listitem><para id="x_60c"><option
   7.290 +	      role="hg-ext-mq-cmd-qpop-opt">-n</option>: Pop a patch
   7.291 +	    from the named queue.</para>
   7.292 +	</listitem></itemizedlist>
   7.293 +
   7.294 +      <para id="x_60d">The <command role="hg-ext-mq">qpop</command> command
   7.295 +	removes one line from the end of the <filename
   7.296 +	  role="special">status</filename> file for each patch that it
   7.297 +	pops.</para>
   7.298 +
   7.299 +    </sect2>
   7.300 +    <sect2>
   7.301 +      <title><command role="hg-ext-mq">qprev</command>&emdash;print
   7.302 +	the name of the previous patch</title>
   7.303 +
   7.304 +      <para id="x_60e">The <command role="hg-ext-mq">qprev</command> command
   7.305 +	prints the name of the patch in the <filename
   7.306 +	  role="special">series</filename> file that comes before the
   7.307 +	topmost applied patch. This will become the topmost applied
   7.308 +	patch if you run <command
   7.309 +	  role="hg-ext-mq">qpop</command>.</para>
   7.310 +
   7.311 +    </sect2>
   7.312 +    <sect2 id="sec:mqref:cmd:qpush">
   7.313 +      <title><command role="hg-ext-mq">qpush</command>&emdash;push
   7.314 +	patches onto the stack</title>
   7.315 +
   7.316 +      <para id="x_60f">The <command role="hg-ext-mq">qpush</command> command adds
   7.317 +	patches onto the applied stack.  By default, it adds only one
   7.318 +	patch.</para>
   7.319 +
   7.320 +      <para id="x_610">This command creates a new changeset to represent each
   7.321 +	applied patch, and updates the working directory to apply the
   7.322 +	effects of the patches.</para>
   7.323 +
   7.324 +      <para id="x_611">The default data used when creating a changeset are as
   7.325 +	follows:</para>
   7.326 +      <itemizedlist>
   7.327 +	<listitem><para id="x_612">The commit date and time zone are the current
   7.328 +	    date and time zone.  Because these data are used to
   7.329 +	    compute the identity of a changeset, this means that if
   7.330 +	    you <command role="hg-ext-mq">qpop</command> a patch and
   7.331 +	    <command role="hg-ext-mq">qpush</command> it again, the
   7.332 +	    changeset that you push will have a different identity
   7.333 +	    than the changeset you popped.</para>
   7.334 +	</listitem>
   7.335 +	<listitem><para id="x_613">The author is the same as the default used by
   7.336 +	    the <command role="hg-cmd">hg commit</command>
   7.337 +	    command.</para>
   7.338 +	</listitem>
   7.339 +	<listitem><para id="x_614">The commit message is any text from the patch
   7.340 +	    file that comes before the first diff header.  If there is
   7.341 +	    no such text, a default commit message is used that
   7.342 +	    identifies the name of the patch.</para>
   7.343 +	</listitem></itemizedlist>
   7.344 +      <para id="x_615">If a patch contains a Mercurial patch header,
   7.345 +	the information in the patch header overrides these
   7.346 +	defaults.</para>
   7.347 +
   7.348 +      <para id="x_616">Options:</para>
   7.349 +      <itemizedlist>
   7.350 +	<listitem><para id="x_617"><option
   7.351 +	      role="hg-ext-mq-cmd-qpush-opt">-a</option>: Push all
   7.352 +	    unapplied patches from the <filename
   7.353 +	      role="special">series</filename> file until there are
   7.354 +	    none left to push.</para>
   7.355 +	</listitem>
   7.356 +	<listitem><para id="x_618"><option
   7.357 +	      role="hg-ext-mq-cmd-qpush-opt">-l</option>: Add the name
   7.358 +	    of the patch to the end of the commit message.</para>
   7.359 +	</listitem>
   7.360 +	<listitem><para id="x_619"><option
   7.361 +	      role="hg-ext-mq-cmd-qpush-opt">-m</option>: If a patch
   7.362 +	    fails to apply cleanly, use the entry for the patch in
   7.363 +	    another saved queue to compute the parameters for a
   7.364 +	    three-way merge, and perform a three-way merge using the
   7.365 +	    normal Mercurial merge machinery.  Use the resolution of
   7.366 +	    the merge as the new patch content.</para>
   7.367 +	</listitem>
   7.368 +	<listitem><para id="x_61a"><option
   7.369 +	      role="hg-ext-mq-cmd-qpush-opt">-n</option>: Use the
   7.370 +	    named queue if merging while pushing.</para>
   7.371 +	</listitem></itemizedlist>
   7.372 +
   7.373 +      <para id="x_61b">The <command role="hg-ext-mq">qpush</command> command
   7.374 +	reads, but does not modify, the <filename
   7.375 +	  role="special">series</filename> file.  It appends one line
   7.376 +	to the <command role="hg-cmd">hg status</command> file for
   7.377 +	each patch that it pushes.</para>
   7.378 +
   7.379 +    </sect2>
   7.380 +    <sect2>
   7.381 +      <title><command
   7.382 +	  role="hg-ext-mq">qrefresh</command>&emdash;update the
   7.383 +	topmost applied patch</title>
   7.384 +
   7.385 +      <para id="x_61c">The <command role="hg-ext-mq">qrefresh</command> command
   7.386 +	updates the topmost applied patch.  It modifies the patch,
   7.387 +	removes the old changeset that represented the patch, and
   7.388 +	creates a new changeset to represent the modified
   7.389 +	patch.</para>
   7.390 +
   7.391 +      <para id="x_61d">The <command role="hg-ext-mq">qrefresh</command> command
   7.392 +	looks for the following modifications:</para>
   7.393 +      <itemizedlist>
   7.394 +	<listitem><para id="x_61e">Changes to the commit message, i.e. the text
   7.395 +	    before the first diff header in the patch file, are
   7.396 +	    reflected in the new changeset that represents the
   7.397 +	    patch.</para>
   7.398 +	</listitem>
   7.399 +	<listitem><para id="x_61f">Modifications to tracked files in the working
   7.400 +	    directory are added to the patch.</para>
   7.401 +	</listitem>
   7.402 +	<listitem><para id="x_620">Changes to the files tracked using <command
   7.403 +	      role="hg-cmd">hg add</command>, <command
   7.404 +	      role="hg-cmd">hg copy</command>, <command
   7.405 +	      role="hg-cmd">hg remove</command>, or <command
   7.406 +	      role="hg-cmd">hg rename</command>.  Added files and copy
   7.407 +	    and rename destinations are added to the patch, while
   7.408 +	    removed files and rename sources are removed.</para>
   7.409 +	</listitem></itemizedlist>
   7.410 +
   7.411 +      <para id="x_621">Even if <command role="hg-ext-mq">qrefresh</command>
   7.412 +	detects no changes, it still recreates the changeset that
   7.413 +	represents the patch.  This causes the identity of the
   7.414 +	changeset to differ from the previous changeset that
   7.415 +	identified the patch.</para>
   7.416 +
   7.417 +      <para id="x_622">Options:</para>
   7.418 +      <itemizedlist>
   7.419 +	<listitem><para id="x_623"><option
   7.420 +	      role="hg-ext-mq-cmd-qrefresh-opt">-e</option>: Modify
   7.421 +	    the commit and patch description, using the preferred text
   7.422 +	    editor.</para>
   7.423 +	</listitem>
   7.424 +	<listitem><para id="x_624"><option
   7.425 +	      role="hg-ext-mq-cmd-qrefresh-opt">-m</option>: Modify
   7.426 +	    the commit message and patch description, using the given
   7.427 +	    text.</para>
   7.428 +	</listitem>
   7.429 +	<listitem><para id="x_625"><option
   7.430 +	      role="hg-ext-mq-cmd-qrefresh-opt">-l</option>: Modify
   7.431 +	    the commit message and patch description, using text from
   7.432 +	    the given file.</para>
   7.433 +	</listitem></itemizedlist>
   7.434 +
   7.435 +    </sect2>
   7.436 +    <sect2>
   7.437 +      <title><command role="hg-ext-mq">qrename</command>&emdash;rename
   7.438 +	a patch</title>
   7.439 +
   7.440 +      <para id="x_626">The <command role="hg-ext-mq">qrename</command> command
   7.441 +	renames a patch, and changes the entry for the patch in the
   7.442 +	<filename role="special">series</filename> file.</para>
   7.443 +
   7.444 +      <para id="x_627">With a single argument, <command
   7.445 +	  role="hg-ext-mq">qrename</command> renames the topmost
   7.446 +	applied patch.  With two arguments, it renames its first
   7.447 +	argument to its second.</para>
   7.448 +
   7.449 +    </sect2>
   7.450 +    <sect2>
   7.451 +      <title><command role="hg-ext-mq">qseries</command>&emdash;print
   7.452 +	the entire patch series</title>
   7.453 +
   7.454 +      <para id="x_62a">The <command role="hg-ext-mq">qseries</command> command
   7.455 +	prints the entire patch series from the <filename
   7.456 +	  role="special">series</filename> file.  It prints only patch
   7.457 +	names, not empty lines or comments.  It prints in order from
   7.458 +	first to be applied to last.</para>
   7.459 +
   7.460 +    </sect2>
   7.461 +    <sect2>
   7.462 +      <title><command role="hg-ext-mq">qtop</command>&emdash;print the
   7.463 +	name of the current patch</title>
   7.464 +
   7.465 +      <para id="x_62b">The <command role="hg-ext-mq">qtop</command> prints the
   7.466 +	name of the topmost currently applied patch.</para>
   7.467 +
   7.468 +    </sect2>
   7.469 +    <sect2>
   7.470 +      <title><command
   7.471 +	  role="hg-ext-mq">qunapplied</command>&emdash;print patches
   7.472 +	not yet applied</title>
   7.473 +
   7.474 +      <para id="x_62c">The <command role="hg-ext-mq">qunapplied</command> command
   7.475 +	prints the names of patches from the <filename
   7.476 +	  role="special">series</filename> file that are not yet
   7.477 +	applied.  It prints them in order from the next patch that
   7.478 +	will be pushed to the last.</para>
   7.479 +
   7.480 +    </sect2>
   7.481 +    <sect2>
   7.482 +      <title><command role="hg-cmd">hg strip</command>&emdash;remove a
   7.483 +	revision and descendants</title>
   7.484 +
   7.485 +      <para id="x_62d">The <command role="hg-cmd">hg strip</command> command
   7.486 +	removes a revision, and all of its descendants, from the
   7.487 +	repository.  It undoes the effects of the removed revisions
   7.488 +	from the repository, and updates the working directory to the
   7.489 +	first parent of the removed revision.</para>
   7.490 +
   7.491 +      <para id="x_62e">The <command role="hg-cmd">hg strip</command> command
   7.492 +	saves a backup of the removed changesets in a bundle, so that
   7.493 +	they can be reapplied if removed in error.</para>
   7.494 +
   7.495 +      <para id="x_62f">Options:</para>
   7.496 +      <itemizedlist>
   7.497 +	<listitem><para id="x_630"><option role="hg-opt-strip">-b</option>: Save
   7.498 +	    unrelated changesets that are intermixed with the stripped
   7.499 +	    changesets in the backup bundle.</para>
   7.500 +	</listitem>
   7.501 +	<listitem><para id="x_631"><option role="hg-opt-strip">-f</option>: If a
   7.502 +	    branch has multiple heads, remove all heads.</para>
   7.503 +	</listitem>
   7.504 +	<listitem><para id="x_632"><option role="hg-opt-strip">-n</option>: Do
   7.505 +	    not save a backup bundle.</para>
   7.506 +	</listitem></itemizedlist>
   7.507 +
   7.508 +    </sect2>
   7.509 +  </sect1>
   7.510 +  <sect1>
   7.511 +    <title>MQ file reference</title>
   7.512 +
   7.513 +    <sect2>
   7.514 +      <title>The <filename role="special">series</filename>
   7.515 +	file</title>
   7.516 +
   7.517 +      <para id="x_633">The <filename role="special">series</filename> file
   7.518 +	contains a list of the names of all patches that MQ can apply.
   7.519 +	It is represented as a list of names, with one name saved per
   7.520 +	line.  Leading and trailing white space in each line are
   7.521 +	ignored.</para>
   7.522 +
   7.523 +      <para id="x_634">Lines may contain comments.  A comment begins with the
   7.524 +	<quote><literal>#</literal></quote> character, and extends to
   7.525 +	the end of the line.  Empty lines, and lines that contain only
   7.526 +	comments, are ignored.</para>
   7.527 +
   7.528 +      <para id="x_635">You will often need to edit the <filename
   7.529 +	  role="special">series</filename> file by hand, hence the
   7.530 +	support for comments and empty lines noted above.  For
   7.531 +	example, you can comment out a patch temporarily, and <command
   7.532 +	  role="hg-ext-mq">qpush</command> will skip over that patch
   7.533 +	when applying patches.  You can also change the order in which
   7.534 +	patches are applied by reordering their entries in the
   7.535 +	<filename role="special">series</filename> file.</para>
   7.536 +
   7.537 +      <para id="x_636">Placing the <filename role="special">series</filename>
   7.538 +	file under revision control is also supported; it is a good
   7.539 +	idea to place all of the patches that it refers to under
   7.540 +	revision control, as well.  If you create a patch directory
   7.541 +	using the <option role="hg-ext-mq-cmd-qinit-opt">-c</option>
   7.542 +	option to <command role="hg-ext-mq">qinit</command>, this will
   7.543 +	be done for you automatically.</para>
   7.544 +
   7.545 +    </sect2>
   7.546 +    <sect2>
   7.547 +      <title>The <filename role="special">status</filename>
   7.548 +	file</title>
   7.549 +
   7.550 +      <para id="x_637">The <filename role="special">status</filename> file
   7.551 +	contains the names and changeset hashes of all patches that MQ
   7.552 +	currently has applied.  Unlike the <filename
   7.553 +	  role="special">series</filename> file, this file is not
   7.554 +	intended for editing.  You should not place this file under
   7.555 +	revision control, or modify it in any way.  It is used by MQ
   7.556 +	strictly for internal book-keeping.</para>
   7.557 +
   7.558 +    </sect2>
   7.559 +  </sect1>
   7.560 +</appendix>
   7.561 +
   7.562 +<!--
   7.563 +local variables: 
   7.564 +sgml-parent-document: ("00book.xml" "book" "appendix")
   7.565 +end:
   7.566 +-->
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/fr/appC-srcinstall.xml	Sat Jul 10 06:24:49 2010 +0100
     8.3 @@ -0,0 +1,68 @@
     8.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
     8.5 +
     8.6 +<appendix id="chap:srcinstall">
     8.7 +  <?dbhtml filename="installing-mercurial-from-source.html"?>
     8.8 +  <title>Installer Mercurial à partir des sources</title>
     8.9 +
    8.10 +  <sect1 id="sec:srcinstall:unixlike">
    8.11 +    <title>Pour un système Unix ou similaire</title>
    8.12 +
    8.13 +    <para id="x_5e0">Si vous utilisez un système Unix ou similaire, pour lequel
    8.14 +      une version récente de Python (2.3 ou plus) est disponible, l'installation
    8.15 +      de Mercurial à partir des sources est simple.</para>
    8.16 +    <orderedlist>
    8.17 +      <listitem><para id="x_5e1">Téléchargez un paquet récent depuis <ulink
    8.18 +	    url="http://www.selenic.com/mercurial/download">http://www.selenic.com/mercurial/download</ulink>.</para>
    8.19 +      </listitem>
    8.20 +      <listitem><para id="x_5e2">Extrayez le paquet : </para>
    8.21 +	<programlisting>gzip -dc mercurial-MYVERSION.tar.gz | tar xf -</programlisting>
    8.22 +      </listitem>
    8.23 +      <listitem><para id="x_5e3">Allez dans le répertoires où les sources ont
    8.24 +    été extraites et exécutez le script d'installation. Ce dernier compilera
    8.25 +    Mercurial et l'installera dans votre répertoire utilisateur.</para>
    8.26 +	<programlisting>cd mercurial-MYVERSION
    8.27 +python setup.py install --force --home=$HOME</programlisting>
    8.28 +      </listitem>
    8.29 +    </orderedlist>
    8.30 +    <para id="x_5e4">Lorsque l'installation est terminée, Mercurial se
    8.31 +      trouvera dans le répertoire <literal>bin</literal> de votre répertoire
    8.32 +      utilisateur.
    8.33 +      N'oubliez pas de vérifier que ce répertoire se trouve dans la liste
    8.34 +      des répertoires où votre shell recherche les exécutables.</para>
    8.35 +
    8.36 +    <para id="x_5e5">Vous devrez vraisemblablement définir la variable
    8.37 +      d'environnement <envar>PYTHONPATH</envar> de manière à ce que
    8.38 +      l'exécutable de Mercurial puisse trouver le reste des paquets logiciels.
    8.39 +      Par exemple, sur mon ordinateur portable, je dois le définir ainsi:
    8.40 +      <literal>/home/bos/lib/python</literal>. Le chemin exact à utiliser
    8.41 +      dépendra de la manière dont Python aura été construit pour votre 
    8.42 +      système. Il ne devrait pas être difficile de le trouver. En cas de
    8.43 +      doute, lisez le texte généré lors de l'installation ci-dessus, et
    8.44 +      recherchez l'emplacement où le contenu du répertoire
    8.45 +      <literal>mercurial</literal> a été installé.</para>
    8.46 +
    8.47 +  </sect1>
    8.48 +  <sect1>
    8.49 +    <title>Pour Windows</title>
    8.50 +
    8.51 +    <para id="x_5e6">Construire et installer Mercurial sous Windows nécessite
    8.52 +      des outils logiciels divers, une certaine connaissance technique et une
    8.53 +      bonne dose de patience. Je vous <emphasis>déconseille fortement</emphasis> 
    8.54 +      de tenter de le faire si vous êtes un <quote>simple utilisateur</quote>.
    8.55 +      A moins que vous n'ayez l'intention de "hacker" Mercurial, je vous
    8.56 +      suggère d'avoir recours à un paquet d'installation de la version binaire.</para>
    8.57 +
    8.58 +    <para id="x_5e7">Si vous avez vraiment l'intention de construire
    8.59 +      Mercurial à partir des sources sous Windows, suivez les indications pour 
    8.60 +      ce <quote>chemin laborieux</quote> sur le wiki de Mercurial : <ulink
    8.61 +	url="http://www.selenic.com/mercurial/wiki/index.cgi/WindowsInstall">http://www.selenic.com/mercurial/wiki/index.cgi/WindowsInstall</ulink>, 
    8.62 +      et préparez vous à un travail épineux.</para>
    8.63 +
    8.64 +  </sect1>
    8.65 +</appendix>
    8.66 +
    8.67 +<!--
    8.68 +local variables: 
    8.69 +sgml-parent-document: ("00book.xml" "book" "appendix")
    8.70 +end:
    8.71 +-->
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/fr/appD-license.xml	Sat Jul 10 06:24:49 2010 +0100
     9.3 @@ -0,0 +1,179 @@
     9.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
     9.5 +
     9.6 +<appendix id="cha:opl">
     9.7 +  <?dbhtml filename="open-publication-license.html"?>
     9.8 +  <title>Open Publication License</title>
     9.9 +
    9.10 +  <para id="x_638">Version 1.0, 8 June 1999</para>
    9.11 +
    9.12 +  <sect1>
    9.13 +    <title>Requirements on both unmodified and modified
    9.14 +      versions</title>
    9.15 +
    9.16 +    <para id="x_639">The Open Publication works may be reproduced and distributed
    9.17 +      in whole or in part, in any medium physical or electronic,
    9.18 +      provided that the terms of this license are adhered to, and that
    9.19 +      this license or an incorporation of it by reference (with any
    9.20 +      options elected by the author(s) and/or publisher) is displayed
    9.21 +      in the reproduction.</para>
    9.22 +
    9.23 +    <para id="x_63a">Proper form for an incorporation by reference is as
    9.24 +      follows:</para>
    9.25 +
    9.26 +    <blockquote>
    9.27 +      <para id="x_63b">  Copyright (c) <emphasis>year</emphasis> by
    9.28 +	<emphasis>author's name or designee</emphasis>. This material
    9.29 +	may be distributed only subject to the terms and conditions
    9.30 +	set forth in the Open Publication License,
    9.31 +	v<emphasis>x.y</emphasis> or later (the latest version is
    9.32 +	presently available at <ulink
    9.33 +	  url="http://www.opencontent.org/openpub/">http://www.opencontent.org/openpub/</ulink>).</para>
    9.34 +    </blockquote>
    9.35 +
    9.36 +    <para id="x_63c">The reference must be immediately followed with any options
    9.37 +      elected by the author(s) and/or publisher of the document (see
    9.38 +      <xref linkend="sec:opl:options"/>).</para>
    9.39 +
    9.40 +    <para id="x_63d">Commercial redistribution of Open Publication-licensed
    9.41 +      material is permitted.</para>
    9.42 +
    9.43 +    <para id="x_63e">Any publication in standard (paper) book form shall require
    9.44 +      the citation of the original publisher and author. The publisher
    9.45 +      and author's names shall appear on all outer surfaces of the
    9.46 +      book. On all outer surfaces of the book the original publisher's
    9.47 +      name shall be as large as the title of the work and cited as
    9.48 +      possessive with respect to the title.</para>
    9.49 +
    9.50 +  </sect1>
    9.51 +  <sect1>
    9.52 +    <title>Copyright</title>
    9.53 +
    9.54 +    <para id="x_63f">The copyright to each Open Publication is owned by its
    9.55 +      author(s) or designee.</para>
    9.56 +
    9.57 +  </sect1>
    9.58 +  <sect1>
    9.59 +    <title>Scope of license</title>
    9.60 +
    9.61 +    <para id="x_640">The following license terms apply to all Open Publication
    9.62 +      works, unless otherwise explicitly stated in the
    9.63 +      document.</para>
    9.64 +
    9.65 +    <para id="x_641">Mere aggregation of Open Publication works or a portion of
    9.66 +      an Open Publication work with other works or programs on the
    9.67 +      same media shall not cause this license to apply to those other
    9.68 +      works. The aggregate work shall contain a notice specifying the
    9.69 +      inclusion of the Open Publication material and appropriate
    9.70 +      copyright notice.</para>
    9.71 +
    9.72 +    <para id="x_642"><emphasis role="bold">Severability</emphasis>. If any part
    9.73 +      of this license is found to be unenforceable in any
    9.74 +      jurisdiction, the remaining portions of the license remain in
    9.75 +      force.</para>
    9.76 +
    9.77 +    <para id="x_643"><emphasis role="bold">No warranty</emphasis>. Open
    9.78 +      Publication works are licensed and provided <quote>as is</quote>
    9.79 +      without warranty of any kind, express or implied, including, but
    9.80 +      not limited to, the implied warranties of merchantability and
    9.81 +      fitness for a particular purpose or a warranty of
    9.82 +      non-infringement.</para>
    9.83 +
    9.84 +  </sect1>
    9.85 +  <sect1>
    9.86 +    <title>Requirements on modified works</title>
    9.87 +
    9.88 +    <para id="x_644">All modified versions of documents covered by this license,
    9.89 +      including translations, anthologies, compilations and partial
    9.90 +      documents, must meet the following requirements:</para>
    9.91 +
    9.92 +    <orderedlist>
    9.93 +      <listitem><para id="x_645">The modified version must be labeled as
    9.94 +	  such.</para>
    9.95 +      </listitem>
    9.96 +      <listitem><para id="x_646">The person making the modifications must be
    9.97 +	  identified and the modifications dated.</para>
    9.98 +      </listitem>
    9.99 +      <listitem><para id="x_647">Acknowledgement of the original author and
   9.100 +	  publisher if applicable must be retained according to normal
   9.101 +	  academic citation practices.</para>
   9.102 +      </listitem>
   9.103 +      <listitem><para id="x_648">The location of the original unmodified document
   9.104 +	  must be identified.</para>
   9.105 +      </listitem>
   9.106 +      <listitem><para id="x_649">The original author's (or authors') name(s) may
   9.107 +	  not be used to assert or imply endorsement of the resulting
   9.108 +	  document without the original author's (or authors')
   9.109 +	  permission.</para>
   9.110 +      </listitem></orderedlist>
   9.111 +
   9.112 +  </sect1>
   9.113 +  <sect1>
   9.114 +    <title>Good-practice recommendations</title>
   9.115 +
   9.116 +    <para id="x_64a">In addition to the requirements of this license, it is
   9.117 +      requested from and strongly recommended of redistributors
   9.118 +      that:</para>
   9.119 +
   9.120 +    <orderedlist>
   9.121 +      <listitem><para id="x_64b">If you are distributing Open Publication works
   9.122 +	  on hardcopy or CD-ROM, you provide email notification to the
   9.123 +	  authors of your intent to redistribute at least thirty days
   9.124 +	  before your manuscript or media freeze, to give the authors
   9.125 +	  time to provide updated documents. This notification should
   9.126 +	  describe modifications, if any, made to the document.</para>
   9.127 +      </listitem>
   9.128 +      <listitem><para id="x_64c">All substantive modifications (including
   9.129 +	  deletions) be either clearly marked up in the document or
   9.130 +	  else described in an attachment to the document.</para>
   9.131 +      </listitem>
   9.132 +      <listitem><para id="x_64d">Finally, while it is not mandatory under this
   9.133 +	  license, it is considered good form to offer a free copy of
   9.134 +	  any hardcopy and CD-ROM expression of an Open
   9.135 +	  Publication-licensed work to its author(s).</para>
   9.136 +      </listitem></orderedlist>
   9.137 +
   9.138 +  </sect1>
   9.139 +  <sect1 id="sec:opl:options">
   9.140 +    <title>License options</title>
   9.141 +
   9.142 +    <para id="x_64e">The author(s) and/or publisher of an Open
   9.143 +      Publication-licensed document may elect certain options by
   9.144 +      appending language to the reference to or copy of the license.
   9.145 +      These options are considered part of the license instance and
   9.146 +      must be included with the license (or its incorporation by
   9.147 +      reference) in derived works.</para>
   9.148 +
   9.149 +    <orderedlist>
   9.150 +      <listitem><para id="x_64f">To prohibit distribution of substantively
   9.151 +	  modified versions without the explicit permission of the
   9.152 +	  author(s). <quote>Substantive modification</quote> is
   9.153 +	  defined as a change to the semantic content of the document,
   9.154 +	  and excludes mere changes in format or typographical
   9.155 +	  corrections.</para>
   9.156 +      </listitem>
   9.157 +      <listitem><para id="x_650">  To accomplish this, add the phrase
   9.158 +	  <quote>Distribution of substantively modified versions of
   9.159 +	    this document is prohibited without the explicit
   9.160 +	    permission of the copyright holder.</quote> to the license
   9.161 +	  reference or copy.</para>
   9.162 +      </listitem>
   9.163 +      <listitem><para id="x_651">To prohibit any publication of this work or
   9.164 +	  derivative works in whole or in part in standard (paper)
   9.165 +	  book form for commercial purposes is prohibited unless prior
   9.166 +	  permission is obtained from the copyright holder.</para>
   9.167 +      </listitem>
   9.168 +      <listitem><para id="x_652">To accomplish this, add the phrase
   9.169 +	  <quote>Distribution of the work or derivative of the work in
   9.170 +	    any standard (paper) book form is prohibited unless prior
   9.171 +	    permission is obtained from the copyright holder.</quote>
   9.172 +	  to the license reference or copy.</para>
   9.173 +      </listitem></orderedlist>
   9.174 +
   9.175 +  </sect1>
   9.176 +</appendix>
   9.177 +
   9.178 +<!--
   9.179 +local variables: 
   9.180 +sgml-parent-document: ("00book.xml" "book" "appendix")
   9.181 +end:
   9.182 +-->
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/fr/autoid.py	Sat Jul 10 06:24:49 2010 +0100
    10.3 @@ -0,0 +1,47 @@
    10.4 +#!/usr/bin/env python
    10.5 +#
    10.6 +# Add unique ID attributes to para tags.  This script should only be
    10.7 +# run by one person, since otherwise it introduces the possibility of
    10.8 +# chaotic conflicts among tags.
    10.9 +
   10.10 +import glob, os, re, sys
   10.11 +
   10.12 +tagged = re.compile('<para[^>]* id="x_([0-9a-f]+)"[^>]*>', re.M)
   10.13 +untagged = re.compile('<para>')
   10.14 +
   10.15 +names = glob.glob('ch*.xml') + glob.glob('app*.xml')
   10.16 +
   10.17 +# First pass: find the highest-numbered paragraph ID.
   10.18 +
   10.19 +biggest_id = 0
   10.20 +seen = set()
   10.21 +errs = 0
   10.22 +
   10.23 +for name in names:
   10.24 +    for m in tagged.finditer(open(name).read()):
   10.25 +        i = int(m.group(1),16)
   10.26 +        if i in seen:
   10.27 +            print >> sys.stderr, '%s: duplication of ID %s' % (name, i)
   10.28 +            errs += 1
   10.29 +        seen.add(i)
   10.30 +        if i > biggest_id:
   10.31 +            biggest_id = i
   10.32 +
   10.33 +def retag(s):
   10.34 +    global biggest_id
   10.35 +    biggest_id += 1
   10.36 +    return '<para id="x_%x">' % biggest_id
   10.37 +
   10.38 +# Second pass: add IDs to paragraphs that currently lack them.
   10.39 +
   10.40 +for name in names:
   10.41 +    f = open(name).read()
   10.42 +    f1 = untagged.sub(retag, f)
   10.43 +    if f1 != f:
   10.44 +        tmpname = name + '.tmp'
   10.45 +        fp = open(tmpname, 'w')
   10.46 +        fp.write(f1)
   10.47 +        fp.close()
   10.48 +        os.rename(tmpname, name)
   10.49 +
   10.50 +sys.exit(errs)
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/fr/book-shortcuts.xml	Sat Jul 10 06:24:49 2010 +0100
    11.3 @@ -0,0 +1,3 @@
    11.4 +<!-- Please keep the contents of this file sorted. -->
    11.5 +
    11.6 +<!ENTITY emdash "&#8212;">
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/fr/ch00-preface.xml	Sat Jul 10 06:24:49 2010 +0100
    12.3 @@ -0,0 +1,271 @@
    12.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
    12.5 +
    12.6 +<preface id="chap:preface">
    12.7 +  <?dbhtml filename="preface.html"?>
    12.8 +  <title>Préface</title>
    12.9 +
   12.10 +  <sect1>
   12.11 +    <title>Un conte technique</title>
   12.12 +
   12.13 +    <para id="x_72e">Il y a quelques années, quand j'ai voulu expliquer
   12.14 +    pourquoi je pensais que la gestion de révisions distribuée était importante,
   12.15 +    le domaine était encore si nouveau qu'il n'y avait presque aucune 
   12.16 +    littérature publiée pour servir de référence aux personnes intéressées.</para>
   12.17 +
   12.18 +    <para id="x_72f">Bien qu'à cette époque je passais beaucoup de temps
   12.19 +    à travailler sur les entrailles de Mercurial, je me suis mis à la 
   12.20 +    rédaction de ce livre parce que ça me semblait être la manière la plus efficace
   12.21 +    d'aider notre logiciel à toucher un vaste public, toujours avec 
   12.22 +    l'idée que la gestion de révisions devrait être distribuée par nature. J'ai 
   12.23 +    publié ce libre en ligne sous une licence libre pour la même raison : pour 
   12.24 +    diffuser la parole auprès du monde.</para>
   12.25 +
   12.26 +    <para id="x_730">Il y a un rythme familier à un bon livre sur un logiciel 
   12.27 +    qui ressemble de près au fait de conter une histoire : Pourquoi ceci est ? 
   12.28 +    Pourquoi ceci est important ? Comment peut-il m'aider ? Comment m'en 
   12.29 +    servir ? Dans ce livre, j'essaye de répondre à toutes ces questions pour
   12.30 +    la gestion de révisions distribuée en général, et pour Mercurial en 
   12.31 +    particulier.</para>
   12.32 +  </sect1>
   12.33 +    
   12.34 +  <sect1>
   12.35 +    <title>Merci de votre soutien à Mercurial</title>
   12.36 +
   12.37 +    <para id="x_731">En achetant une copie de ce livre, vous soutenez le
   12.38 +    développement et la liberté de Mercurial en particulier, et dans 
   12.39 +    l'Open Source, au logiciel libre en général. O'Reilly Media et 
   12.40 +    moi-même donnons les revenus issus des ventes de ce livre à la
   12.41 +    Software Freedom Conservancy (<ulink
   12.42 +        url="http://www.softwarefreedom.org/">http://www.softwarefreedom.org/</ulink>) 
   12.43 +      qui fournit un support juridique à Mercurial et à de 
   12.44 +      nombreux autres projets Open Source proéminents et de qualité.</para>
   12.45 +  </sect1>
   12.46 +
   12.47 +  <sect1>
   12.48 +    <title>Remerciements</title>
   12.49 +
   12.50 +    <para id="x_732">Ce livre n'aurait pas vu le jour sans les
   12.51 +    efforts de Matt Mackal, l'auteur et le chef du projet Mercurial.
   12.52 +    Il est assisté très efficacement par des centaines de contributeurs
   12.53 +    volontaires à travers le monde.</para>
   12.54 +
   12.55 +    <para id="x_733">Les enfants, Cian et Ruairi, ont toujours été prêt
   12.56 +    à m'aider à me reposer avec de merveilleux et impulsif jeux d'enfants. 
   12.57 +    Je tiens aussi à remercier mon ex-femme, Shannon, pour son soutien.
   12.58 +    </para>
   12.59 +
   12.60 +    <para id="x_734">Mes collègues et amis m'ont aidé et assisté de 
   12.61 +    de nombreuses manières. Cette liste de personnes est forcément très
   12.62 +    incomplète : Stephen Hahn, Karyn Ritter, Bonnie Corwin, James Vasile,
   12.63 +    Matt Norwood, Eben Moglen, Bradley Kuhn, Robert Walsh, Jeremy
   12.64 +    Fitzhardinge, Rachel Chalmers.</para>
   12.65 +
   12.66 +    <para id="x_735">J'ai conçu ce livre de manière ouverte, en publiant
   12.67 +    des brouillons de chapitres du livre sur des site web, au fur et à 
   12.68 +    mesure que je les réalisais. Leurs lecteurs m'ont fait des retours 
   12.69 +    utilisant l'application web que j'avais développée. À la fin de son
   12.70 +    écriture, plus de 100 personnes m'avaient fait des commentaires, 
   12.71 +    un chiffre incroyable quand on considère que ce système de 
   12.72 +    commentaire n'a tourné que dans les deux derniers mois de la 
   12.73 +    rédaction du livre.</para>
   12.74 +
   12.75 +    <para id="x_736">J'aimerais particulièrement remercier les 
   12.76 +    personnes suivantes, dont les commentaires représentent plus
   12.77 +    du tiers de l'ensemble de ces derniers. Je voudrais les 
   12.78 +    remercier pour leurs attentions et efforts à me faire des retours
   12.79 +    très détaillés.</para>
   12.80 +
   12.81 +    <para id="x_737">Martin Geisler, Damien Cassou, Alexey Bakhirkin, Till Plewe,
   12.82 +      Dan Himes, Paul Sargent, Gokberk Hamurcu, Matthijs van der
   12.83 +      Vleuten, Michael Chermside, John Mulligan, Jordi Fita, Jon
   12.84 +      Parise.</para>
   12.85 +
   12.86 +    <para id="x_738">Je souhaite aussi remercier l'aide des personnes
   12.87 +    qui ont découvert des erreurs et fourni des suggestions avisées
   12.88 +    à travers tout le livre.</para>
   12.89 +
   12.90 +    <para id="x_739">Jeremy W. Sherman, Brian Mearns, Vincent Furia, Iwan
   12.91 +      Luijks, Billy Edwards, Andreas Sliwka, Paweł Sołyga, Eric
   12.92 +      Hanchrow, Steve Nicolai, Michał Masłowski, Kevin Fitch, Johan
   12.93 +      Holmberg, Hal Wine, Volker Simonis, Thomas P Jakobsen, Ted
   12.94 +      Stresen-Reuter, Stephen Rasku, Raphael Das Gupta, Ned
   12.95 +      Batchelder, Lou Keeble, Li Linxiao, Kao Cardoso Félix, Joseph
   12.96 +      Wecker, Jon Prescot, Jon Maken, John Yeary, Jason Harris,
   12.97 +      Geoffrey Zheng, Fredrik Jonson, Ed Davies, David Zumbrunnen,
   12.98 +      David Mercer, David Cabana, Ben Karel, Alan Franzoni, Yousry
   12.99 +      Abdallah, Whitney Young, Vinay Sajip, Tom Towle, Tim Ottinger,
  12.100 +      Thomas Schraitle, Tero Saarni, Ted Mielczarek, Svetoslav
  12.101 +      Agafonkin, Shaun Rowland, Rocco Rutte, Polo-Francois Poli,
  12.102 +      Philip Jenvey, Petr Tesałék, Peter R. Annema, Paul Bonser,
  12.103 +      Olivier Scherler, Olivier Fournier, Nick Parker, Nick Fabry,
  12.104 +      Nicholas Guarracino, Mike Driscoll, Mike Coleman, Mietek Bák,
  12.105 +      Michael Maloney, László Nagy, Kent Johnson, Julio Nobrega, Jord
  12.106 +      Fita, Jonathan March, Jonas Nockert, Jim Tittsler, Jeduan
  12.107 +      Cornejo Legorreta, Jan Larres, James Murphy, Henri Wiechers,
  12.108 +      Hagen Möbius, Gábor Farkas, Fabien Engels, Evert Rol, Evan
  12.109 +      Willms, Eduardo Felipe Castegnaro, Dennis Decker Jensen, Deniz
  12.110 +      Dogan, David Smith, Daed Lee, Christine Slotty, Charles Merriam,
  12.111 +      Guillaume Catto, Brian Dorsey, Bob Nystrom, Benoit Boissinot,
  12.112 +      Avi Rosenschein, Andrew Watts, Andrew Donkin, Alexey Rodriguez,
  12.113 +      Ahmed Chaudhary.</para>
  12.114 +  </sect1>
  12.115 +
  12.116 +  <sect1>
  12.117 +    <title>Conventions utilisées dans ce livre</title>
  12.118 +
  12.119 +    <para id="x_73a">Les conventions typographiques suivantes sont utilisées dans ce livre :</para>
  12.120 +
  12.121 +    <variablelist>
  12.122 +      <varlistentry>
  12.123 +        <term>Italique</term>
  12.124 +
  12.125 +        <listitem>
  12.126 +          <para id="x_73b">Indique les termes nouveaux, les URLs, les
  12.127 +            adresses mail, les noms de fichiers et les extensions de
  12.128 +            fichier.</para>
  12.129 +        </listitem>
  12.130 +      </varlistentry>
  12.131 +
  12.132 +      <varlistentry>
  12.133 +        <term><literal>Chasse fixe</literal></term>
  12.134 +
  12.135 +        <listitem>
  12.136 +          <para id="x_73c">Utilisé pour les extraits de code, comme 
  12.137 +          dans les paragraphes pour référer aux éléments du programme,
  12.138 +          tels que les variables ou les noms de fonctions, de bases
  12.139 +          de données, de types de données, de variables d'environnement,
  12.140 +          d'instructions, et de mots clés.</para>
  12.141 +        </listitem>
  12.142 +      </varlistentry>
  12.143 +
  12.144 +      <varlistentry>
  12.145 +        <term><userinput>Taille constante avec gras</userinput></term>
  12.146 +
  12.147 +        <listitem>
  12.148 +          <para id="x_73d">Affiche les commandes ou autres textes qui
  12.149 +          devraient être saisis par l'utilisateur.</para>
  12.150 +        </listitem>
  12.151 +      </varlistentry>
  12.152 +
  12.153 +      <varlistentry>
  12.154 +        <term><replaceable>Chasse fixe avec italique</replaceable></term>
  12.155 +
  12.156 +        <listitem>
  12.157 +          <para id="x_73e">Affiche les textes qui devraient être remplacés 
  12.158 +          par une valeur définie par l'utilisateur ou des valeurs définies
  12.159 +          selon le contexte.</para>
  12.160 +        </listitem>
  12.161 +      </varlistentry>
  12.162 +    </variablelist>
  12.163 +
  12.164 +    <tip>
  12.165 +      <para id="x_73f">Cette icône indique une astuce, une suggestion ou 
  12.166 +      une note d'ordre général.</para>
  12.167 +    </tip>
  12.168 +
  12.169 +    <caution>
  12.170 +      <para id="x_740">Cette icône est un message d'alerte ou de prudence.</para>
  12.171 +    </caution>
  12.172 +  </sect1>
  12.173 +
  12.174 +  <sect1>
  12.175 +    <title>Utiliser les exemples de code</title>
  12.176 +
  12.177 +    <para id="x_741">Ce livre est ici pour vous aider dans votre
  12.178 +    travail. De manière générale, vous pouvez donc utiliser le code
  12.179 +    de ce livre dans vos programmes et votre documentation. Vous
  12.180 +    n'avez pas à nous contacter pour nous demander la permission
  12.181 +    de le faire, à moins que vous ne reproduisiez une partie significative
  12.182 +    du code. Par exemple, écrire un programme qui utilise plusieurs 
  12.183 +    extraits de code du livre ne demande aucune autorisation particulière.
  12.184 +    Vendre ou distribuer un CD-ROM provenant des livres O'Reilly demande
  12.185 +    à l'inverse une autorisation. Répondre à une question en citant ce 
  12.186 +    livre ou ses exemples de code ne demande aucune autorisation préalable.
  12.187 +    Intégrer une grande quantité des codes d'exemples de ce livre dans
  12.188 +    votre propre ouvrage demande une autorisation de notre part.</para>
  12.189 +
  12.190 +    <para id="x_742">Nous apprécions, sans l'exiger, que vous citiez 
  12.191 +    l'ouvrage dans vos écrits l'utilisant, en indiquant le titre, 
  12.192 +    l'auteur, l'éditeur et son ISBN. Par exemple: “<emphasis>Titre du 
  12.193 +    livre</emphasis> par Son Auteur. Copyright 2008 O’Reilly Media, Inc.,
  12.194 +    978-0-596-xxxx-x.”</para>
  12.195 +
  12.196 +    <para id="x_743">Si vous estimez que votre usage des exemples de code
  12.197 +    dépasse le cadre défini ci dessus, n'hésitez pas à nous contacter :
  12.198 +      <email>permissions@oreilly.com</email>.</para>
  12.199 +  </sect1>
  12.200 +
  12.201 +  <sect1>
  12.202 +    <title>Safari® Books Online</title>
  12.203 +
  12.204 +    <note role="safarienabled">
  12.205 +      <para id="x_744">Quand vous voyez l'icône de Safari® Books Online 
  12.206 +      sur la couverture d'un de vos livres techniques préférés, cela signifie
  12.207 +      que le livre est disponible, en ligne, à travers le O’Reilly Network Safari
  12.208 +        Bookshelf.</para>
  12.209 +    </note>
  12.210 +
  12.211 +    <para id="x_745">Safari offre une solution qui est meilleure que
  12.212 +    les e-books. C'est une bibliothèque virtuelle qui vous laisse
  12.213 +    aisément rechercher dans des milliers de livres, mais aussi 
  12.214 +    copier-coller leurs exemples, télécharger des chapitres, et 
  12.215 +    trouver des réponses rapides quand vous avez besoin d'une 
  12.216 +    information précise et à jour. Essayez le gratuitement :
  12.217 +    <ulink role="orm:hideurl:ital"
  12.218 +        url="http://my.safaribooksonline.com/?portal=oreilly">http://my.safaribooksonline.com</ulink>.</para>
  12.219 +  </sect1>
  12.220 +
  12.221 +  <sect1>
  12.222 +    <title>Comment nous contacter</title>
  12.223 +
  12.224 +    <para id="x_746">Merci d'adresser vos commentaires et vos questions
  12.225 +    sur ce livre à son éditeur:</para>
  12.226 +
  12.227 +    <simplelist type="vert">
  12.228 +      <member>O’Reilly Media, Inc.</member>
  12.229 +
  12.230 +      <member>1005 Gravenstein Highway North</member>
  12.231 +
  12.232 +      <member>Sebastopol, CA 95472</member>
  12.233 +
  12.234 +      <member>800-998-9938 (in the United States or Canada)</member>
  12.235 +
  12.236 +      <member>707-829-0515 (international or local)</member>
  12.237 +
  12.238 +      <member>707 829-0104 (fax)</member>
  12.239 +    </simplelist>
  12.240 +
  12.241 +    <para id="x_747">Nous avons une page web pour cet ouvrage, où nous
  12.242 +    publions des errata, des exemples, et encore d'autres informations
  12.243 +    additionnelles. Vous pouvez accéder à cette page par l'URL suivante:
  12.244 +    </para>
  12.245 +
  12.246 +    <simplelist type="vert">
  12.247 +      <member><ulink url="http://www.oreilly.com/catalog/&lt;catalog
  12.248 +          page&gt;"></ulink></member>
  12.249 +    </simplelist>
  12.250 +
  12.251 +    <remark>N'oubliez pas de mettre à jour l'attribut &lt;url&gt; aussi.</remark>
  12.252 +
  12.253 +    <para id="x_748">Pour commenter ou poser des questions techniques 
  12.254 +    sur cet ouvrage, envoyez un email à :</para>
  12.255 +
  12.256 +    <simplelist type="vert">
  12.257 +      <member><email>bookquestions@oreilly.com</email></member>
  12.258 +    </simplelist>
  12.259 +
  12.260 +    <para id="x_749">Pour plus d'informations sur nos livres, nos
  12.261 +    conférences, nos centres d'informations, et le réseau O’Reilly, 
  12.262 +    voyez notre site web :</para>
  12.263 +
  12.264 +    <simplelist type="vert">
  12.265 +      <member><ulink url="http://www.oreilly.com"></ulink></member>
  12.266 +    </simplelist>
  12.267 +  </sect1>
  12.268 +</preface>
  12.269 +
  12.270 +<!--
  12.271 +local variables: 
  12.272 +sgml-parent-document: ("00book.xml" "book" "preface")
  12.273 +end:
  12.274 +-->
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/fr/ch01-intro.xml	Sat Jul 10 06:24:49 2010 +0100
    13.3 @@ -0,0 +1,857 @@
    13.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
    13.5 +
    13.6 +<chapter id="chap:intro">
    13.7 +  <?dbhtml filename="how-did-we-get-here.html"?>
    13.8 +  <title>Comment en est-on arrivé là ?</title>
    13.9 +
   13.10 +<sect1>
   13.11 +<title>À propos de la gestion de révisions. Pourquoi Mercurial ?</title>
   13.12 +
   13.13 +    <para id="x_6d">La gestion de révisions est un processus permettant de gérer différentes
   13.14 +versions de la même information. Dans sa forme la plus simple, c'est
   13.15 +ce que tout le monde fait manuellement : quand vous modifiez
   13.16 +un fichier, vous le sauvegardez sous un nouveau nom contenant un numéro,
   13.17 +à chaque fois plus grand que celui de la version précédente.</para>
   13.18 +
   13.19 +    <para id="x_6e">Ce genre de gestion de révisions manuelle, ne serait-ce que 
   13.20 +        d'un seul fichier, est cependant facilement sujette
   13.21 +aux erreurs, ainsi, depuis longtemps, des logiciels existent pour
   13.22 +résoudre cette problématique. Les premiers outils de gestion de révisions
   13.23 +étaient destinés à aider un seul utilisateur, à automatiser la gestion
   13.24 +des versions d'un seul fichier. Durant les dernières décennies, cette cible
   13.25 +s'est largement agrandie, ils gèrent désormais de multiples fichiers, et
   13.26 +aident un grand nombre de personnes à travailler ensemble. Les outils les
   13.27 +plus modernes n'ont aucune difficulté à gérer plusieurs milliers de
   13.28 +personnes travaillant ensemble sur des projets regroupant plusieurs
   13.29 +centaines de milliers de fichiers.</para>
   13.30 +
   13.31 +    <para id="x_6f">L'arrivée de la gestion de révisions distribuée est
   13.32 +    relativement récente, et, pour le moment, ce nouveau domaine a grandi
   13.33 +    grâce à la volonté des gens d'explorer ces territoires encore inconnus.
   13.34 +    </para>
   13.35 +
   13.36 +    <para id="x_70">J'écris un livre sur la gestion de révisions distribuée
   13.37 +    parce que je pense qu'il s'agit d'un sujet important qui mérite un guide
   13.38 +    de terrain. J'ai choisi d'écrire un livre sur Mercurial car il est
   13.39 +    l'outil le plus facile pour découvrir ce nouveau domaine, tout en étant
   13.40 +    un outil efficace qui répond aux demandes d'environnements réels et
   13.41 +    difficiles, là où d'autres outils de gestion de révisions s'effondrent.</para>
   13.42 +
   13.43 +    <sect2>
   13.44 +      <title>Pourquoi utiliser un gestionnaire de révisions ?</title>
   13.45 +
   13.46 +      <para id="x_71">Il y a de nombreuses raisons pour que vous ou votre équipe souhaitiez
   13.47 +utiliser un outil automatisant la gestion de révisions pour votre projet.</para>
   13.48 +
   13.49 +      <itemizedlist>
   13.50 +	<listitem><para id="x_72">L'outil se chargera de suivre l'évolution de votre projet, sans
   13.51 +que vous ayez à le faire. Pour chaque modification, vous aurez à votre
   13.52 +disposition un journal indiquant <emphasis>qui</emphasis> a fait quoi, <emphasis>pourquoi</emphasis>
   13.53 +il l'a fait, <emphasis>quand</emphasis> il l'a fait, et
   13.54 +<emphasis>ce</emphasis> qu'il a modifié.</para>
   13.55 +</listitem>
   13.56 +<listitem><para id="x_73">Quand vous travaillez avec d'autres personnes, les logiciels de
   13.57 +gestion de révisions facilitent le travail collaboratif. Par exemple, quand
   13.58 +plusieurs personnes font, plus ou moins simultanément, des modifications
   13.59 +incompatibles, le logiciel vous aidera à identifier et à résoudre les conflits.</para>
   13.60 +</listitem>
   13.61 +<listitem><para id="x_74">L'outil vous aidera à réparer vos erreurs. Si vous effectuez un changement
   13.62 +qui se révèle être une erreur, vous pourrez revenir à une version
   13.63 +antérieure d'un fichier ou même d'un ensemble de fichiers. En fait, un outil de
   13.64 +gestion de révisions <emphasis>vraiment</emphasis> efficace vous permettra d'identifier à quel
   13.65 +moment le problème est apparu (voir la section <xref linkend="sec:undo:bisect"/> pour plus
   13.66 +de détails).</para>
   13.67 +</listitem>
   13.68 +<listitem><para id="x_75">L'outil vous permettra aussi de travailler sur plusieurs versions différentes
   13.69 +de votre projet et de gérer l'écart entre chacune.</para>
   13.70 +</listitem></itemizedlist>
   13.71 +<para id="x_76">La plupart de ces raisons ont autant d'importances &emdash;du
   13.72 +  moins en théorie&emdash; que vous travailliez seul sur un projet, ou
   13.73 +  avec une centaine d'autres personnes.
   13.74 +</para>
   13.75 +
   13.76 +<para id="x_77">Une question fondamentale à propos des outils de gestion de
   13.77 +  révisions, qu'il s'agisse du projet d'une personne ou d'une grande équipe, est
   13.78 +  quels sont ses <emphasis>gains</emphasis> par rapport à ses
   13.79 +  <emphasis>coûts</emphasis>. Un outil qui est difficile à utiliser ou à
   13.80 +  comprendre exigera un lourd effort d'adaptation.
   13.81 +</para>
   13.82 +
   13.83 +<para id="x_78">Un projet de cinq mille personnes s'effondrera très
   13.84 +  certainement de lui même sans aucun processus et outil de gestion de
   13.85 +  révisions. Dans ce cas, le coût d'utilisation d'un logiciel de gestion de
   13.86 +  révisions est dérisoire puisque <emphasis>sans</emphasis> celui-ci, l'échec est presque
   13.87 +  garanti.
   13.88 +</para>
   13.89 +
   13.90 +<para id="x_79">D'un autre coté, un <quote>rapide hack</quote> d'une personne
   13.91 +  peut sembler un contexte bien pauvre pour utiliser un outil de gestion de
   13.92 +  révisions, car, bien évidement le coût d'utilisation dépasse le coût total du
   13.93 +  projet. N'est-ce pas ?
   13.94 +</para>
   13.95 +
   13.96 +      <para id="x_7a">Mercurial supporte ces <emphasis>deux</emphasis>
   13.97 +        échelles de travail. Vous pouvez apprendre les bases en quelques
   13.98 +        minutes seulement, et, grâce à sa performance, vous pouvez l'utiliser
   13.99 +        avec facilité sur le plus petit des projets. Cette simplicité
  13.100 +        signifie que vous n'avez pas de concept obscur ou de séquence de
  13.101 +        commandes défiant l'imagination, sans aucune corrélation avec
  13.102 +        ce que vous êtes <emphasis>réellement</emphasis> en train de faire. En même
  13.103 +        temps, ses mêmes performances et sa nature
  13.104 +        <quote>peer-to-peer</quote> vous permettent d'adapter, sans
  13.105 +        difficulté, son utilisation à de très grands projets.
  13.106 +</para>
  13.107 +
  13.108 +      <para id="x_7b">Aucun outil de gestion de révisions ne peut sauver un
  13.109 +        projet mal mené, mais un bon outil peut rendre beaucoup plus fluide
  13.110 +        votre travail.
  13.111 +</para>
  13.112 +
  13.113 +    </sect2>
  13.114 +
  13.115 +    <sect2>
  13.116 +      <title>Les multiples noms de la gestion de source</title>
  13.117 +
  13.118 +      <para id="x_7c">La gestion de source
  13.119 +        <!-- TODO:<footnote><J'ai utilisé systématiquement le terme
  13.120 +            <quote>gestion de révisions</quote> à travers tout l'ouvrage. Ce
  13.121 +            n'est pas forcement la meilleure traduction, et ceci peut rendre
  13.122 +            la lecture un peu lourde, mais je pense que le document y gagne
  13.123 +            en clarté et en précision. -->
  13.124 +        est un domaine tellement large qu'il n'existe pas qu'un seul nom ou
  13.125 +        acronyme pour le désigner. Voici quelques noms ou acronymes que vous
  13.126 +        rencontrerez le plus souvent.
  13.127 +        <!-- TODO:<footnote> J'ai conservé la liste des noms en anglais pour
  13.128 +          des raisons de commodité (ils sont plus <quote>googelable</quote>).
  13.129 +          En outre, j'ai opté  pour conserver l'ensemble des opérations de
  13.130 +          Mercurial (\textit{commit},\textit{push}, \textit{pull},...) en
  13.131 +          anglais, là aussi pour faciliter la lecture d'autres documents en
  13.132 +          anglais, ainsi que l'utilisation de Mercurial. -->
  13.133 +</para>
  13.134 +
  13.135 +<para>:
  13.136 +</para>
  13.137 +
  13.138 +      <itemizedlist>
  13.139 +	<listitem><para id="x_7d">Revision control (RCS)</para></listitem>
  13.140 +	<listitem><para id="x_7e">Software configuration management (SCM), ou
  13.141 +	    configuration management</para></listitem>
  13.142 +	<listitem><para id="x_7f">Source code management</para></listitem>
  13.143 +	<listitem><para id="x_80">Source code control, ou source control</para></listitem>
  13.144 +	<listitem><para id="x_81">Version control (VCS)</para></listitem></itemizedlist>
  13.145 +
  13.146 + <para id="x_82">Certaines personnes prétendent que ces termes ont en fait
  13.147 +   des sens différents mais en pratique ils se recouvrent tellement qu'il n'y
  13.148 +   a pas réellement de manière pertinente de les distinguer. </para>
  13.149 +
  13.150 +    </sect2>
  13.151 +  </sect1>
  13.152 +
  13.153 +  <sect1>
  13.154 +
  13.155 +<title>À propos des exemples dans ce livre</title>
  13.156 +
  13.157 +    <para id="x_84">Ce livre prend une approche non usuelle pour les exemples
  13.158 +      de code. Tous les exemples sont en <quote>live</quote> &emdash; chacun
  13.159 +      est actuellement le résultat d'un script shell qui exécute les
  13.160 +      commandes Mercurial que vous voyez. Chaque fois qu'une image du livre
  13.161 +      est construite à partir des sources, tous les scripts d'exemples sont
  13.162 +      lancés automatiquement, et leurs résultats effectifs sont comparés aux
  13.163 +      résultats attendus.</para>
  13.164 +
  13.165 +    <para id="x_85">L'avantage de cette approche est que les exemples sont
  13.166 +      toujours précis ; ils décrivent <emphasis>exactement</emphasis> la
  13.167 +      comportement de la version de Mercurial qui est mentionnée en entête du
  13.168 +      livre. Si je mets à jour la version de Mercurial que je suis en train de
  13.169 +      documenter, et que la sortie de certaines commandes change, la
  13.170 +      construction du livre échoue.</para>
  13.171 +
  13.172 +    <para id="x_86">
  13.173 +      Il existe un petit désavantage à cette approche qui est que les dates et
  13.174 +      heures que vous verrez dans les exemples tendent à être
  13.175 +      <quote>écrasés</quote> ensemble, dans le sens où elles ne sont pas
  13.176 +      celles qu'elles auraient été si un humain avait tapé les commandes. En
  13.177 +      effet, un humain ne peut pas taper plus d'une commande toutes les quelques
  13.178 +      secondes, avec le temps qui s'écoule, mes scripts d'exemples exécutent
  13.179 +      plusieurs commandes en une seconde.
  13.180 +    </para>
  13.181 +
  13.182 +    <para id="x_87">Comme exemple de ceci, plusieurs commits
  13.183 +      consécutifs dans un exemple peuvent apparaître comme ayant eu lieu
  13.184 +      durant la même seconde.
  13.185 +      Vous pouvez observer le phénomène dans l'exemple <literal
  13.186 +        role="hg-ext">bisect</literal> dans <xref linkend="sec:undo:bisect"/>
  13.187 +    </para>
  13.188 +
  13.189 +    <para id="x_88">Donc, lorsque vous lisez ces exemples, ne prêtez pas trop
  13.190 +      d'importance aux dates et heures que vous voyez dans la sortie des
  13.191 +      commandes. Cependant, <emphasis>soyez</emphasis> confiants que le
  13.192 +      comportement que vous voyez est cohérent et reproductible. 
  13.193 +    </para>
  13.194 +
  13.195 +  </sect1>
  13.196 +
  13.197 +<!-- The next section has disapper from this part of the book. it may be splaced somewhere else... t-->
  13.198 +
  13.199 +  <sect1>
  13.200 +    <title>Tendances de la gestion de révisions</title>
  13.201 +
  13.202 +    <para id="x_89">Il y a eu une tendance évidente dans le développement et
  13.203 +      l'utilisation d'outils de gestion de source depuis les quatre dernières
  13.204 +      décennies, au fur et à mesure que les utilisateurs se sont habitués à
  13.205 +      leur outils et se sont sentis contraints par leurs limitations.
  13.206 +    </para>
  13.207 +
  13.208 +    <para id="x_8a">La première génération commença simplement par gérer un
  13.209 +      fichier unique sur un ordinateur individuel. Cependant, même si ces
  13.210 +      outils présentaient une grande avancée par rapport à la gestion
  13.211 +      manuelle des versions, leur modèle de verrouillage et leur utilisation
  13.212 +      limitée à un seul ordinateur rendaient leur utilisation possible
  13.213 +      uniquement dans une très petite équipe.
  13.214 +    </para>
  13.215 +
  13.216 +    <para id="x_8b">La seconde génération a assoupli ces contraintes en
  13.217 +      adoptant une architecture réseau et centralisée, permettant de gérer
  13.218 +      plusieurs projets entiers en même temps. Alors que les projets
  13.219 +      grandirent en taille, ils rencontrèrent de nouveaux problèmes. Avec les
  13.220 +      clients discutant régulièrement avec le serveur, la montée en charge
  13.221 +      devint un réel problème sur les gros projets. Une connexion réseau peu
  13.222 +      fiable pouvait complètement empêcher les utilisateurs distants de
  13.223 +      dialoguer avec le serveur. Alors que les projets <emphasis
  13.224 +        remap="it">Open Source</emphasis> commencèrent à mettre en place des
  13.225 +      accès en lecture seule disponible anonymement, les utilisateurs sans
  13.226 +      les privilèges de <quote>commit</quote> réalisèrent qu'ils ne pouvaient
  13.227 +      pas utiliser les outils pour collaborer naturellement avec le projet,
  13.228 +      comme ils ne pouvaient pas non plus enregistrer leurs modifications.
  13.229 +    </para>
  13.230 +
  13.231 +    <para id="x_8c">La génération actuelle des outils de gestion de révisions
  13.232 +      est <quote>peer-to-peer</quote> par nature. Tous ces systèmes ont
  13.233 +      abandonné la dépendance à un serveur central, et ont permis à leurs
  13.234 +      utilisateurs de distribuer les données de leur gestion de révisions à qui
  13.235 +      en a besoin. La collaboration à travers Internet a transformé la
  13.236 +      contrainte technologique en une simple question de choix et de
  13.237 +      consensus. Les outils modernes peuvent maintenant fonctionner en mode
  13.238 +      déconnecté sans limite et de manière autonome, la connexion au réseau
  13.239 +      n'étant nécessaire que pour synchroniser les modifications avec les
  13.240 +      autres dépôts.
  13.241 +    </para>
  13.242 +  </sect1>
  13.243 +    
  13.244 +  <sect1>
  13.245 +    <title>Quelques avantages des gestionnaires de révisions distribués</title>
  13.246 +      
  13.247 +    <para id="x_8d">Même si les gestionnaire de révisions distribués sont depuis
  13.248 +      plusieurs années assez robustes et aussi utilisables que leurs
  13.249 +      prédécesseurs, les utilisateurs d'autres outils n'y ont pas encore été
  13.250 +      sensibilisés. Les gestionnaires de révisions distribués se distinguent
  13.251 +      particulièrement de leurs équivalents centralisés de nombreuses
  13.252 +      manières.
  13.253 +    </para>
  13.254 +
  13.255 +    <para id="x_8e">Pour un développeur individuel, ils restent beaucoup plus
  13.256 +      rapides que les outils centralisés. Cela pour une raison simple : un
  13.257 +      outil centralisé doit toujours dialoguer à travers le réseau pour la
  13.258 +      plupart des opérations, car presque toutes les métadonnées sont
  13.259 +      stockées sur la seule copie du serveur central. Un outil distribué
  13.260 +      stocke toute ses métadonnées localement. À tâche égale, effectuer un
  13.261 +      échange avec le réseau ajoute un délai aux outils centralisés. Ne
  13.262 +      sous-estimez pas la valeur d'un outil rapide : vous allez passer
  13.263 +      beaucoup de temps à interagir avec un logiciel de gestion de révisions.
  13.264 +    </para>
  13.265 +
  13.266 +    <para id="x_8f">Les outils distribués sont complètement indépendants des
  13.267 +      aléas de votre serveur, d'autant plus qu'ils répliquent les métadonnées
  13.268 +      à beaucoup d'endroits. Si votre serveur central prend feu, vous avez
  13.269 +      intérêt à ce que les médias de sauvegardes soient fiables, et que votre
  13.270 +      dernier <quote>backup</quote> soit récent et fonctionne sans problème.
  13.271 +      Avec un outil distribué, vous avez autant de <quote>backups</quote> que
  13.272 +      de contributeurs.
  13.273 +    </para>
  13.274 +
  13.275 +    <para id="x_90">En outre, la fiabilité de votre réseau affectera beaucoup
  13.276 +      moins les outils distribués. Vous ne pouvez même pas utiliser un outil
  13.277 +      centralisé sans connexion réseau, à l'exception de quelques commandes,
  13.278 +      très limitées. Avec un outil distribué, si votre connexion réseau tombe
  13.279 +      pendant que vous travaillez, vous pouvez ne même pas vous en rendre
  13.280 +      compte. La seule chose que vous ne serez pas capable de faire sera de
  13.281 +      communiquer avec des dépôts distants, opération somme toute assez rare
  13.282 +      en comparaison des opérations locales. Si vous avez une équipe de
  13.283 +      collaborateurs très dispersée ceci peut être significatif.
  13.284 +    </para>
  13.285 +
  13.286 +    <sect2>
  13.287 +      <title>Avantages pour les projets Open Source</title>
  13.288 +
  13.289 +      <para id="x_91">Si vous prenez goût à un projet <emphasis
  13.290 +          remap="it">Open Source</emphasis> et que vous décidez de commencer
  13.291 +        à toucher à son code, et que le projet utilise un gestionnaire de
  13.292 +        révisions distribué, vous êtes immédiatement un "pair" avec les
  13.293 +        personnes formant le <quote>cœur</quote> du projet. S'ils publient
  13.294 +        leurs dépôts, vous pouvez immédiatement copier leurs historiques de
  13.295 +        projet, faire des modifications, enregistrer votre travail en
  13.296 +        utilisant les mêmes outils qu'eux. Par comparaison avec un outil
  13.297 +        centralisé, vous devez utiliser un logiciel en mode <quote>lecture
  13.298 +          seule</quote> à moins que quelqu'un ne vous donne les privilèges de
  13.299 +        <quote>commit</quote> sur le serveur central. Avant ça, vous ne serez
  13.300 +        pas capable d'enregistrer vos modifications, et vos propres
  13.301 +        modifications risqueront de se corrompre chaque fois que vous
  13.302 +        essayerez de mettre à jour à votre espace de travail avec le serveur
  13.303 +        central.
  13.304 +      </para>
  13.305 +
  13.306 +    <sect3>
  13.307 +      <title>Le non-problème du "fork"</title>
  13.308 +      
  13.309 +      <para id="x_92">Il a été souvent suggéré que les gestionnaires de
  13.310 +        révisions distribués posent un risque pour les projets <emphasis
  13.311 +          remap="it">Open Source</emphasis> car ils facilitent grandement la
  13.312 +        création de <quote>fork</quote>.
  13.313 +        <!--footnote{NdT:Création d'une <ulink url="version alternative du
  13.314 +          logiciel">version alternative du
  13.315 +          logiciel</ulink>{http://fr.wikipedia.org/wiki/Fork#Embranchement_d.27un_projet_informatique}
  13.316 +        -->
  13.317 +        Un <quote>fork</quote> apparait quand il y des divergences d'opinion
  13.318 +        ou d'attitude au sein d'un groupe de développeurs qui aboutissent à
  13.319 +        la décision de ne plus travailler ensemble. Chaque parti s'empare
  13.320 +        d'une copie plus ou moins complète du code source du projet et
  13.321 +        continue dans sa propre direction.
  13.322 +      </para>
  13.323 +
  13.324 +
  13.325 +      <para id="x_93">Parfois ces différents partis décident de se
  13.326 +        réconcilier. Avec un serveur central, l'aspect
  13.327 +        <emphasis>technique</emphasis> de cette réconciliation est un
  13.328 +        processus douloureux, et essentiellement manuel. Vous devez décider
  13.329 +        quelle modification est <quote>la gagnante</quote>, et replacer, par
  13.330 +        un moyen ou un autre, les modifications de l'autre équipe dans
  13.331 +        l'arborescence du projet. Ceci implique généralement la perte d'une
  13.332 +        partie de l'historique d'un des partis, ou même des deux.
  13.333 +      </para>
  13.334 +    
  13.335 +      <para id="x_94">Ce que les outils distribués permettent à ce sujet est
  13.336 +        probablement la <emphasis>meilleure</emphasis> façon de développer un
  13.337 +        projet. Chaque modification que vous effectuez est potentiellement un
  13.338 +        <quote>fork</quote>. La grande force de cette approche est que les
  13.339 +        gestionnaires de révisions distribués doivent être vraiment très
  13.340 +        efficaces pour <emphasis>fusionner (merge)</emphasis>
  13.341 +        <!-- TODO footnote{NdT:j'ai choisi de traduire ici <emphasis
  13.342 +          remap="it">merging</emphasis> par <quote>fusionner</quote> pour des
  13.343 +        raisons de clarté} -->
  13.344 +        des <quote>forks</quote>, car les <quote>forks</quote>, dans ce
  13.345 +        contexte, arrivent tout le temps.
  13.346 +      </para>
  13.347 +      
  13.348 +      <para id="x_95">Si chaque altération que n'importe qui effectue, à tout
  13.349 +        moment, est vue comme un <quote>fork</quote> à fusionner, alors ce
  13.350 +        que le monde de l'<emphasis remap="it">Open Source</emphasis> voit
  13.351 +        comme un <quote>fork</quote> devient <emphasis>uniquement</emphasis>
  13.352 +        une problématique sociale. En fait, les outils de gestions de révisions
  13.353 +        distribués <emphasis>réduisent</emphasis> les chances de
  13.354 +        <quote>fork</quote> :
  13.355 +      </para>
  13.356 +        
  13.357 +      <itemizedlist>
  13.358 +        <listitem>
  13.359 +        <para>Ils éliminent la distinction sociale qu'imposent les outils
  13.360 +          centralisés entre les membres du projets (ceux qui ont accès au
  13.361 +          <quote>commit</quote>) et ceux de l'extérieur (qui ne l'ont
  13.362 +          pas).
  13.363 +        </para>
  13.364 +        <para>Ils rendent plus facile la réconciliation après un
  13.365 +          <quote>fork</quote> social, car tout ce qu'elle implique est une
  13.366 +          simple fusion.
  13.367 +        </para>
  13.368 +        </listitem>
  13.369 +      </itemizedlist>
  13.370 +
  13.371 +      <para id="x_98">Certaines personnes font de la résistance envers les
  13.372 +        gestionnaires de révisions distribués parce qu'ils veulent garder un
  13.373 +        contrôle ferme sur leur projet, et ils pensent que les outils
  13.374 +        centralisés leur fournissent ce contrôle. Néanmoins, si c'est votre
  13.375 +        cas, sachez que si vous publiez votre dépôt CVS ou Subversion de
  13.376 +        manière publique, il existe une quantité d'outils disponibles pour
  13.377 +        récupérer entièrement votre projet et son historique (quoique
  13.378 +        lentement) et le récréer ailleurs, sans votre contrôle. En fait,
  13.379 +        votre contrôle sur votre projet est illusoire, vous ne faites
  13.380 +        qu'interdire à vos collaborateurs de travailler de manière fluide, en
  13.381 +        disposant d'un miroir ou d'un <quote>fork</quote> de votre
  13.382 +        historique.
  13.383 +      </para>
  13.384 +
  13.385 +    </sect3>
  13.386 +    </sect2>
  13.387 +    <sect2>
  13.388 +      <title>Avantages pour les projets commerciaux</title>
  13.389 +
  13.390 +      <para id="x_99">Beaucoup de projets commerciaux sont réalisés par des
  13.391 +        équipes éparpillées à travers le globe. Les contributeurs qui sont
  13.392 +        loin du serveur central devront subir des commandes lentes et même
  13.393 +        parfois peu fiables. Les solutions propriétaires de gestion de révisions
  13.394 +        tentent de palier ce problème avec des réplications de sites distants
  13.395 +        qui sont à la fois coûteuses à mettre en place et lourdes à
  13.396 +        administrer. Un système distribué ne souffre pas de ce genre de
  13.397 +        problèmes. En outre, il est très aisé de mettre en place plusieurs
  13.398 +        serveurs de références, disons un par site, de manière à ce qu'il n'y
  13.399 +        ait pas de communication redondante entre les dépôts, sur une
  13.400 +        connexion longue distance souvent onéreuse.
  13.401 +      </para>
  13.402 +
  13.403 +      <para id="x_9a">Les systèmes de gestion de révisions supportent
  13.404 +        généralement assez mal la montée en charge. Il n'est pas rare pour un
  13.405 +        gestionnaire de révisions centralisé pourtant onéreux de s'effondrer
  13.406 +        sous la charge combinée de quelques dizaines d'utilisateurs concurrents
  13.407 +        seulement. Une fois encore, la réponse à cette problématique est
  13.408 +        généralement encore la mise en place d'un ensemble complexe de
  13.409 +        serveurs synchronisés par un mécanisme de réplication. Dans le cas
  13.410 +        d'un gestionnaire de révisions distribué, la charge du serveur central
  13.411 +        &emdash; si vous en avez un&emdash; est largement inférieure (car
  13.412 +        toutes les données sont déjà répliquées ailleurs), un simple serveur,
  13.413 +        peu onéreux, peut gérer les besoins d'une plus grande équipe, et la
  13.414 +        réplication pour répartir la charge devient le travail d'un simple
  13.415 +        script.
  13.416 +      </para>
  13.417 +
  13.418 +      <para id="x_9b">Si vous avez des employés sur le terrain, en train de
  13.419 +        chercher à résoudre un souci sur le site d'un client, ils
  13.420 +        bénéficieront aussi d'un gestionnaire de révisions distribué. Cet outil
  13.421 +        leur permettra de générer des versions personnalisées, d'essayer
  13.422 +        différentes solutions, en les isolant aisément les unes des autres,
  13.423 +        et de rechercher efficacement à travers l'historique des sources, la
  13.424 +        cause des bugs ou des régressions, tout ceci sans avoir besoin de la
  13.425 +        moindre connexion au réseau de votre société.
  13.426 +      </para>
  13.427 +
  13.428 +    </sect2>
  13.429 +    </sect1>
  13.430 +    <sect1>
  13.431 +      <title>Pourquoi choisir Mercurial?</title>
  13.432 +
  13.433 +      <para id="x_9c">Mercurial a plusieurs caractéristiques qui en font un
  13.434 +        choix particulièrement pertinent pour la gestion de révisions :
  13.435 +      </para>
  13.436 +    <itemizedlist>
  13.437 +      <listitem><para id="x_9d">Il est simple à apprendre et à utiliser.</para></listitem>
  13.438 +      <listitem><para id="x_9e">Il est léger.</para></listitem>
  13.439 +      <listitem><para id="x_9f">Il s'adapte très bien à la charge.</para></listitem>
  13.440 +      <listitem><para id="x_a0">Il se personnalise facilement.</para></listitem>
  13.441 +    </itemizedlist>
  13.442 +
  13.443 +    <para id="x_a1">Si vous êtes déjà familier d'un outil de gestion de
  13.444 +      révisions, vous serez capable de l'utiliser en moins de 5 minutes. Sinon,
  13.445 +      ça ne sera pas beaucoup plus long. Les commandes utilisées par
  13.446 +      Mercurial, comme ses fonctionnalités, sont généralement uniformes et
  13.447 +      cohérentes, et vous pouvez ainsi garder en tête simplement quelques
  13.448 +      règles générales, plutôt que de nombreuses exceptions.
  13.449 +    </para>
  13.450 +
  13.451 +    <para id="x_a2">Sur un petit projet, vous pouvez commencer à travailler
  13.452 +      avec Mercurial en quelques instants. Ajouter des modifications ou des
  13.453 +      branches, transférer ces modifications (localement ou via le réseau),
  13.454 +      et les opérations d'historique ou de statut sont aussi très rapides.
  13.455 +      Mercurial ne vous encombre pas grâce à sa simplicité
  13.456 +      d'utilisation et sa rapidité d'exécution.
  13.457 +    </para>
  13.458 +
  13.459 +    <para id="x_a3">L'utilité de Mercurial ne se limite pas à de petits
  13.460 +      projets : il est aussi utilisé par des projets ayant des centaines ou
  13.461 +      même des milliers de contributeurs, avec plusieurs dizaines de milliers
  13.462 +      de fichiers, et des centaines de méga octets de code source.
  13.463 +    </para>
  13.464 +
  13.465 +    <para id="x_a4">Si les fonctionnalités au cœur de Mercurial ne sont pas
  13.466 +      suffisantes pour vous, il est très aisé d'en construire d'autres.
  13.467 +      Mercurial est adapté à l'utilisation de scripts, et son implémentation
  13.468 +      interne en Python, propre et claire, rend encore plus facile l'ajout de
  13.469 +      fonctionnalités sous forme d'extensions. Il en existe déjà un certain
  13.470 +      nombre de très populaires et très utiles, dont le périmètre va de la
  13.471 +      recherche de bugs à l'amélioration des performances.
  13.472 +    </para>
  13.473 +
  13.474 +  </sect1>
  13.475 +  <sect1>
  13.476 +    <title>Mercurial comparé aux autres outils</title>
  13.477 +
  13.478 +    <para id="x_a5">Avant que vous n'alliez plus loin, comprenez bien que
  13.479 +      cette section reflète mes propres expériences, et elle est donc (j'ose
  13.480 +      le dire) peu objective. Néanmoins, j'ai utilisé les outils de gestion
  13.481 +      de source listés ci dessous, dans la plupart des cas, pendant plusieurs
  13.482 +      années.
  13.483 +    </para>
  13.484 +
  13.485 +    <sect2>
  13.486 +      <title>Subversion</title>
  13.487 +
  13.488 +      <para id="x_a6">Subversion est un des outils de gestion de révisions les
  13.489 +        plus populaire, développé pour remplacer CVS. Il a une
  13.490 +        architecture client/serveur centralisée.
  13.491 +      </para>
  13.492 +
  13.493 +      <para id="x_a7">Subversion et Mercurial ont des noms de commandes très
  13.494 +        similaires pour les mêmes opérations, ainsi si vous êtes familier
  13.495 +        avec l'un, c'est facile d'apprendre l'autre. Ces deux outils sont
  13.496 +        portables sur tous les systèmes d'exploitation populaires.
  13.497 +      </para>
  13.498 +
  13.499 +      <para id="x_a8">Avant la version 1.5, Subversion n'offrait aucune forme
  13.500 +        de support pour les fusions. Lors de l'écriture de ce livre, ses
  13.501 +        capacités de fusion étaient nouvelles, et réputées pour être <ulink
  13.502 +          url="http://svnbook.red-bean.com/nightly/en/svn.branchmerge.advanced.html#svn.branchmerge.advanced.finalword">
  13.503 +          complexes et buguées</ulink>.
  13.504 +      </para>
  13.505 +
  13.506 +      <para id="x_a9">Mercurial dispose d'un avantage substantiel en terme de
  13.507 +        performance par rapport à Subversion sur la plupart des opérations
  13.508 +        que j'ai pu tester. J'ai mesuré une différence de performance allant
  13.509 +        de deux à six fois plus rapide avec le système de stockage de fichier
  13.510 +        local de Subversion 1.4.3 (<emphasis>ra_local</emphasis>), qui est la
  13.511 +        méthode d'accès la plus rapide disponible. Dans un déploiement plus
  13.512 +        réaliste, impliquant un stockage réseau, Subversion serait encore
  13.513 +        plus désavantagé. Parce que la plupart des commandes Subversion
  13.514 +        doivent communiquer avec le serveur et que Subversion n'a pas de
  13.515 +        mécanisme de réplication, la capacité du serveur et la bande passante
  13.516 +        sont devenues des goulots d'étranglement pour les projets de taille
  13.517 +        moyenne ou grande.
  13.518 +      </para>
  13.519 +
  13.520 +      <para id="x_aa">En outre, Subversion implique une surcharge
  13.521 +        substantielle dans le stockage local de certaines données, pour
  13.522 +        éviter des transactions avec le serveur, pour certaines opérations
  13.523 +        communes, telles que la recherche des fichiers modifiés
  13.524 +        (<literal>status</literal>) et l'affichage des modifications par
  13.525 +        rapport à la révision courante (<literal>diff</literal>). En
  13.526 +        conséquence, un répertoire de travail Subversion a souvent la même
  13.527 +        taille, ou est plus grand, qu'un dépôt Mercurial et son espace de
  13.528 +        travail, et ceci bien que le dépôt Mercurial contienne l'intégralité
  13.529 +        de l'historique.
  13.530 +      </para>
  13.531 +
  13.532 +      <para id="x_ab">Subversion est largement supporté par les outils
  13.533 +        tiers. Mercurial est actuellement encore en retrait de ce point de
  13.534 +        vue. L'écart se réduit néanmoins, en effet, certains des outils
  13.535 +        graphiques sont maintenant supérieurs à leurs équivalents Subversion.
  13.536 +        Comme Mercurial, Subversion dispose d'un excellent manuel
  13.537 +        utilisateur.
  13.538 +      </para>
  13.539 +
  13.540 +      <para id="x_ac">Parce que Subversion ne stocke pas l'historique chez
  13.541 +        ses clients, il est parfaitement adapté à la gestion de projets qui
  13.542 +        doivent suivre un ensemble de larges fichiers binaires et opaques. Si
  13.543 +        vous suivez une cinquantaine de versions d'un fichier incompressible
  13.544 +        de 10MB, l'occupation disque coté client d'un projet sous Subversion
  13.545 +        restera à peu près constante. À l'inverse, l'occupation disque du
  13.546 +        même projet sous n'importe lequel des gestionnaires de révisions
  13.547 +        distribués grandira rapidement, proportionnellement aux nombres de
  13.548 +        versions, car les différences entre chaque révision seront très
  13.549 +        grandes.
  13.550 +      </para>
  13.551 +
  13.552 +      <para id="x_ad">En outre, c'est souvent difficile ou, généralement,
  13.553 +        impossible de fusionner des différences dans un fichier binaire. La
  13.554 +        capacité de Subversion de verrouiller des fichiers, pour permettre à
  13.555 +        l'utilisateur d'être le seul à le mettre à jour
  13.556 +        (<quote>commit</quote>) temporairement, est un avantage significatif
  13.557 +        dans un projet doté de beaucoup de fichiers binaires.
  13.558 +      </para>
  13.559 +
  13.560 +      <para id="x_ae">Mercurial peut importer l'historique depuis un dépôt
  13.561 +        Subversion. Il peut aussi exporter l'ensemble des révisions d'un
  13.562 +        projet vers un dépôt Subversion. Ceci rend très facile de
  13.563 +        <quote>prendre la température</quote> et d'utiliser Mercurial et
  13.564 +        Subversion en parallèle, avant de décider de migrer vers Mercurial.
  13.565 +        La conversion de l'historique est incrémentale, donc vous pouvez
  13.566 +        effectuer une conversion initiale, puis de petites additions par la
  13.567 +        suite pour ajouter les nouvelle modifications.
  13.568 +      </para>
  13.569 +
  13.570 +
  13.571 +    </sect2>
  13.572 +    <sect2>
  13.573 +      <title>Git</title>
  13.574 +
  13.575 +      <para id="x_af">Git est un outil de gestion de révisions distribué qui a été
  13.576 +        développé pour gérer le code source de noyau de Linux. Comme
  13.577 +        Mercurial, sa conception initiale a été inspirée par Monotone.
  13.578 +      </para>
  13.579 +
  13.580 +      <para id="x_b0">Git dispose d'un ensemble conséquent de commandes, avec
  13.581 +        plus de 139 commandes individuelles pour la version 1.5.0. Il a aussi
  13.582 +        la réputation d'être difficile à apprendre. Comparé à Git, le point
  13.583 +        fort de Mercurial est clairement sa simplicité.
  13.584 +      </para>
  13.585 +
  13.586 +      <para id="x_b1">En terme de performance, Git est extrêmement rapide.
  13.587 +        Dans la plupart des cas, il est plus rapide que Mercurial, tout du
  13.588 +        moins sur Linux, alors que Mercurial peut être plus performant sur
  13.589 +        d'autres opérations. Néanmoins, sur Windows, les performances et le
  13.590 +        niveau de support général fourni par Git, au moment de l'écriture de
  13.591 +        cet ouvrage, est bien derrière celui de Mercurial.
  13.592 +      </para>
  13.593 +
  13.594 +      <para id="x_b2">Alors que le dépôt Mercurial ne demande aucune
  13.595 +        maintenance, un dépôt Git exige d'exécuter manuellement et
  13.596 +        régulièrement la commande <quote>repacks</quote> sur ses métadonnées.
  13.597 +        Sans ceci, les performances de git se dégradent et la consommation de
  13.598 +        l'espace disque augmente rapidement. Un serveur qui contient
  13.599 +        plusieurs dépôts Git qui ne sont pas régulièrement et fréquemment
  13.600 +        <quote>repacked</quote> deviendra un vrai problème lors des
  13.601 +        <quote>backups</quote> du disque, et il y eu des cas, où un
  13.602 +        <quote>backup</quote> journalier pouvait durer plus de 24 heures. Un
  13.603 +        dépôt fraichement <quote>repacked</quote> sera légèrement plus petit
  13.604 +        qu'un dépôt Mercurial, mais un dépôt non <quote>repacked</quote> est
  13.605 +        beaucoup plus grand.
  13.606 +      </para>
  13.607 +
  13.608 +      <para id="x_b3">Le cœur de Git est écrit en C. La plupart des commandes
  13.609 +        Git sont implémentées sous forme de scripts Shell ou Perl, et la
  13.610 +        qualité de ces scripts varie grandement. J'ai plusieurs fois constaté
  13.611 +        que certains de ces scripts étaient chargés en mémoire aveuglément et
  13.612 +        que la présence d'erreurs pouvait s'avérer fatale.
  13.613 +      </para>
  13.614 +
  13.615 +      <para id="x_b4">Mercurial peut importer l'historique d'un dépôt Git.</para>
  13.616 +
  13.617 +    </sect2>
  13.618 +    <sect2>
  13.619 +      <title>CVS</title>
  13.620 +
  13.621 +      <para id="x_b5">CVS est probablement l'outil de gestion de révisions le
  13.622 +        plus utilisé aujourd'hui dans le monde. À cause de son manque de
  13.623 +        clarté interne, il n'est plus maintenu depuis plusieurs années.
  13.624 +      </para>
  13.625 +
  13.626 +      <para id="x_b6">Il a une architecture client/serveur centralisée. Il ne
  13.627 +        regroupe pas les modifications de fichiers dans une opération de
  13.628 +        <quote>commit</quote> atomique, ce qui permet à ses utilisateurs de
  13.629 +        <quote>casser le <emphasis>build</emphasis></quote> assez facilement :
  13.630 +        une personne peut effectuer une opération de <quote>commit</quote>
  13.631 +        sans problème puis être bloquée par besoin de fusion, avec comme
  13.632 +        conséquence néfaste, que les autres utilisateurs ne récupèreront
  13.633 +        qu'une partie de ses modifications. Ce problème affecte aussi la
  13.634 +        manière de travailler avec l'historique du projet. Si vous voulez
  13.635 +        voir toutes les modifications d'une personne du projet, vous devrez
  13.636 +        injecter manuellement les descriptions et les <emphasis
  13.637 +          remap="it">timestamps</emphasis> des modifications de chacun des
  13.638 +        fichiers impliqués (si vous savez au moins quels sont ces fichiers).
  13.639 +      </para>
  13.640 +
  13.641 +      <para id="x_b7">CVS a une notion étrange des <emphasis
  13.642 +          remap="it">tags</emphasis> et des branches que je n'essayerai même
  13.643 +        pas de décrire ici. Il ne supporte pas bien les opérations de
  13.644 +        renommage d'un fichier ou d'un répertoire, ce qui facilite la
  13.645 +        corruption de son dépôt. Il n'a presque pas pour ainsi dire de
  13.646 +        contrôle de cohérence interne, il est donc pratiquement impossible de
  13.647 +        dire si un dépôt est corrompu ni à quel point. Je ne recommanderai
  13.648 +        pas CVS pour un projet existant ou nouveau.
  13.649 +      </para>
  13.650 +
  13.651 +      <para id="x_b8">Mercurial peut importer l'historique d'un projet CVS.
  13.652 +        Néanmoins, il y a quelques principes à respecter ; ce qui est vrai
  13.653 +        aussi pour les autres outils d'import de projet CVS. À cause de
  13.654 +        l'absence de <quote>commit</quote> atomique et gestion de versions de
  13.655 +        l'arborescence, il n'est pas possible de reconstruire de manière
  13.656 +        précise l'ensemble de l'historique. Un travail de
  13.657 +        <quote>devinette</quote> est donc nécessaire, et les fichiers
  13.658 +        renommés ne sont pas détectés. Parce qu'une bonne part de
  13.659 +        l'administration d'un dépôt CVS est effectuée manuellement, et est
  13.660 +        donc, sujette à erreur, il est courant que les imports CVS
  13.661 +        rencontrent de nombreux problèmes avec les dépôt corrompus (des
  13.662 +        <emphasis remap="it">timestamps</emphasis> de révision complètement
  13.663 +        buggés et des fichiers verrouillés depuis des années sont deux des
  13.664 +        problèmes les moins intéressants dont je me souvienne).
  13.665 +      </para>
  13.666 +
  13.667 +      <para id="x_b9">Mercurial peut importer l'historique depuis un dépôt CVS.
  13.668 +      </para>
  13.669 +
  13.670 +
  13.671 +    </sect2>
  13.672 +    <sect2>
  13.673 +      <title>Outils propriétaires</title>
  13.674 +
  13.675 +      <para id="x_ba">Perforce a une architecture client/serveur centralisée,
  13.676 +        sans aucun mécanisme de mise en cache de données côté client.
  13.677 +        Contrairement à la plupart des outils modernes de gestion de révisions,
  13.678 +        Perforce exige de ses utilisateurs d'exécuter une commande pour
  13.679 +        informer le serveur central de tout fichier qu'ils souhaitent
  13.680 +        modifier.
  13.681 +      </para>
  13.682 +
  13.683 +      <para id="x_bb">Les performances de Perforce sont plutôt bonnes pour
  13.684 +        des petites équipes, mais elles s'effondrent rapidement lorsque le
  13.685 +        nombre d'utilisateurs augmente au delà de quelques dizaines. Des
  13.686 +        installations de Perforce assez larges nécessitent le déploiement de
  13.687 +        proxies pour supporter la montée en charge associée.
  13.688 +      </para>
  13.689 +
  13.690 +    </sect2>
  13.691 +    <sect2>
  13.692 +      <title>Choisir un outil de gestion de révisions</title>
  13.693 +
  13.694 +      <para id="x_bc">À l'exception de CVS, tous les outils listés ci-dessus
  13.695 +        ont des forces qui leurs sont propres et qui correspondent à certaines
  13.696 +        formes de projet. Il n'y a pas un seul meilleur outil de gestion de
  13.697 +        révisions qui correspondrait le mieux à toutes les situations.
  13.698 +      </para>
  13.699 +
  13.700 +      <para id="x_bd">En guise exemple, Subversion est un très bon choix
  13.701 +        lorsqu'on travaille avec beaucoup de fichiers binaires, qui évoluent
  13.702 +        régulièrement, grâce à sa nature centralisée et sa capacité à
  13.703 +        verrouiller des fichiers.
  13.704 +      </para>
  13.705 +
  13.706 +      <para id="x_be">Personnellement, je préfère Mercurial pour sa
  13.707 +        simplicité, ses performances et sa bonne capacité de fusion, et il
  13.708 +        m'a très bien rendu service de plusieurs années maintenant.
  13.709 +      </para>
  13.710 +
  13.711 +    </sect2>
  13.712 +  </sect1>
  13.713 +  <sect1>
  13.714 +    <title>Migrer depuis un outil vers Mercurial</title>
  13.715 +
  13.716 +    <para id="x_bf">Mercurial est livré avec une extension nommée <literal
  13.717 +        role="hg-ext">convert</literal>, qui peut, de manière incrémentale
  13.718 +      importer des révisions depuis différents autres outils de gestion de
  13.719 +      source. Par <quote>incrémental</quote>, j'entends que vous pouvez
  13.720 +      convertir l'historique entier du projet en une seule fois, puis
  13.721 +      relancer l'outil d'import plus tard pour obtenir les modifications
  13.722 +      effectuées depuis votre import initial.
  13.723 +    </para>
  13.724 +
  13.725 +    <para id="x_c0">Les outils de gestion de révisions supportés par <literal
  13.726 +        role="hg-ext">convert</literal> sont :
  13.727 +    </para>
  13.728 +    <itemizedlist>
  13.729 +      <listitem><para id="x_c1">Subversion</para></listitem>
  13.730 +      <listitem><para id="x_c2">CVS</para></listitem>
  13.731 +      <listitem><para id="x_c3">Git</para></listitem>
  13.732 +      <listitem><para id="x_c4">Darcs</para></listitem>
  13.733 +    </itemizedlist>
  13.734 +
  13.735 +    <para id="x_c5">En outre, <literal role="hg-ext">convert</literal> peut
  13.736 +      exporter les modifications depuis Mercurial vers Subversion. Ceci rend
  13.737 +      possible d'essayer Subversion en parallèle avant de choisir une
  13.738 +      solution définitive, sans aucun risque de perte de données.
  13.739 +    </para>
  13.740 +
  13.741 +    <para id="x_c6">La commande <command
  13.742 +        role="hg-ext-conver">convert</command> est très simple à utiliser.
  13.743 +      Simplement, indiquez le chemin ou l'URL du dépôt de source, en lui
  13.744 +      indiquant éventuellement le nom du chemin de destination, et la
  13.745 +      conversion se met en route. Après cet import initial, il suffit de
  13.746 +      relancer la commande encore une fois pour importer les modifications
  13.747 +      effectuées depuis.
  13.748 +    </para>
  13.749 +  </sect1>
  13.750 +
  13.751 +  <sect1>
  13.752 +    <title>Une courte histoire de la gestion de révisions</title>
  13.753 +
  13.754 +    <para id="x_c7">Le plus célèbre des anciens outils de gestion de révisions
  13.755 +      est <emphasis remap="it">SCCS</emphasis> (Source Code Control System)},
  13.756 +      que Marc Rochkind conçu dans les laboratoires de recherche de Bell
  13.757 +      (<emphasis remap="it">Bell Labs</emphasis>), dans le début des années
  13.758 +      70. <emphasis remap="it">SCCS</emphasis> ne fonctionnait que sur des
  13.759 +      fichiers individuels, et obligeait chaque personne travaillant sur le
  13.760 +      projet d'avoir un accès à un répertoire de travail commun, sur le même
  13.761 +      système. Seulement une seule personne pouvait modifier un fichier au
  13.762 +      même moment, ce fonctionnement était assuré par l'utilisation de verrou
  13.763 +      (<quote>lock</quote>). Il était courant que des personnes verrouillent
  13.764 +      des fichiers, et plus tard, oublient de le déverrouiller ; empêchant
  13.765 +      n'importe qui d'autre de travailler sur ces fichiers sans l'aide de
  13.766 +      l'administrateur...
  13.767 +    </para>
  13.768 +
  13.769 +    <para id="x_c8">Walter Tichy a développé une alternative libre à
  13.770 +      <emphasis remap="it">SCCS</emphasis> au début des années 80, qu'il
  13.771 +      nomma <emphasis remap="it">RCS (Revision Control System)</emphasis>.
  13.772 +      Comme <emphasis remap="it">SCCS</emphasis>, <emphasis
  13.773 +        remap="it">RCS</emphasis> demandait aux développeurs de travailler
  13.774 +      sur le même répertoire partagé, et de verrouiller les fichiers pour se
  13.775 +      prémunir de tout conflit issu de modifications concurrentes.
  13.776 +    </para>
  13.777 +
  13.778 +    <para id="x_c9">Un peu plus tard dans les années 1980, Dick Grune utilisa
  13.779 +      <emphasis remap="it">RCS</emphasis> comme une brique de base pour un
  13.780 +      ensemble de scripts <emphasis remap="it">shell</emphasis> qu'il
  13.781 +      intitula cmt, avant de la renommer en <emphasis remap="it">CVS
  13.782 +        (Concurrent Versions System)</emphasis>.  La grande innovation de CVS
  13.783 +      était que les développeurs pouvaient travailler simultanément et
  13.784 +      indépendamment dans leur propre espace de travail. Ces espaces de
  13.785 +      travail privés assuraient que les développeurs ne se marchent pas
  13.786 +      mutuellement sur les pieds, comme c'était souvent le cas avec RCS et
  13.787 +      SCCS. Tous les développeurs disposaient donc de leur copie de tous les
  13.788 +      fichiers du projet, et ils pouvaient donc librement les modifier. Ils
  13.789 +      devaient néanmoins effectuer la <quote>fusion</quote> (<emphasis
  13.790 +        remap="it"><quote>merge</quote></emphasis>) de leurs fichiers, avant
  13.791 +      d'effectuer le <quote>commit</quote> de leurs modifications sur le dépôt
  13.792 +      central.
  13.793 +    </para>
  13.794 +    
  13.795 +    <para id="x_ca">Brian Berliner reprit les scripts de Grune's et les réécrit en C,
  13.796 +      qu'il publia en 1989. Depuis, ce code a été modifié jusqu'à devenir la
  13.797 +      version moderne de CVS. CVS a acquis ainsi la capacité de fonctionner
  13.798 +      en réseau, transformant son architecture en client/serveur.
  13.799 +      L'architecture de CVS est centralisée, seul le serveur a une copie de
  13.800 +      l'historique du projet. L'espace de travail client ne contient qu'une
  13.801 +      copie de la dernière version du projet, et quelques métadonnées pour
  13.802 +      indiquer où le serveur se trouve. CVS a été un grand succès,
  13.803 +      aujourd'hui il est probablement l'outil de gestion de révisions le plus
  13.804 +      utilisé au monde.
  13.805 +    </para>
  13.806 +    
  13.807 +    <para id="x_cb">Au début des années 1990, Sun Microsystems développa un premier
  13.808 +      outil de gestion de révisions distribué, nommé TeamWare. Un espace de
  13.809 +      travail TeamWare contient une copie complète de l'historique du projet.
  13.810 +      TeamWare n'a pas de notion de dépôt central. (CVS utilisait RCS pour le
  13.811 +      stockage de l'historique, TeamWare utilisait SCCS).
  13.812 +    </para>
  13.813 +    
  13.814 +    <para id="x_cc">Alors que les années 1990 avançaient, les utilisateurs ont pris
  13.815 +      conscience d'un certain nombre de problèmes avec CVS. Il enregistrait
  13.816 +      simultanément des modifications sur différents fichiers
  13.817 +      individuellement, au lieu de les regrouper dans une seule opération
  13.818 +      cohérente et atomique. Il ne gère pas bien sa hiérarchie de fichiers, il
  13.819 +      est donc assez aisé de créer le chaos en renommant les fichiers et les
  13.820 +      répertoires. Pire encore, son code source est difficile à lire et à
  13.821 +      maintenir, ce qui augmente largement le <quote>niveau de
  13.822 +        souffrance</quote> associé à la réparation de ces problèmes
  13.823 +      d'architecture de manière prohibitive.
  13.824 +    </para>
  13.825 +    
  13.826 +    <para id="x_cd">En 2001, Jim Blandy et Karl Fogel, deux développeurs qui avaient
  13.827 +      travaillé sur CVS, initièrent un projet pour le remplacer par un outil
  13.828 +      qui aurait une meilleure architecture et un code plus propre. Le
  13.829 +      résultat, Subversion, ne quitte pas le modèle centralisé et
  13.830 +      client/serveur de CVS, mais ajoute les opérations de
  13.831 +      <quote>commit</quote> atomique sur de multiples fichiers, une meilleure
  13.832 +      gestion des espaces de noms, et d'autres fonctionnalités qui en font un
  13.833 +      meilleur outil que CVS. Depuis sa première publication, il est
  13.834 +      rapidement devenu très populaire.
  13.835 +    </para>
  13.836 +    
  13.837 +    <para id="x_ce">Plus ou moins simultanément, Graydon Hoare a commencé sur
  13.838 +      l'ambitieux système de gestion distribuée Monotone. Bien que Monotone
  13.839 +      corrige plusieurs défauts de CVS tout en offrant une architecture
  13.840 +      <quote>peer-to-peer</quote>, il va aussi plus loin que la plupart des
  13.841 +      outils de gestion de révisions de manière assez innovante. Il utilise des
  13.842 +      <quote>hashs</quote> cryptographiques comme identifiants, et il a une
  13.843 +      notion complète de <quote>confiance</quote> du code issu des
  13.844 +      différentes sources.
  13.845 +    </para>
  13.846 +    
  13.847 +    <para id="x_cf">Mercurial est né en 2005. Bien que très influencé par Monotone,
  13.848 +      Mercurial se concentre sur la facilité d'utilisation, les performances
  13.849 +      et la capacité à monter en charge sur de très gros projets.
  13.850 +    </para>
  13.851 +  
  13.852 +  </sect1>
  13.853 +
  13.854 +</chapter>
  13.855 +
  13.856 +<!--
  13.857 +local variables: 
  13.858 +sgml-parent-document: ("00book.xml" "book" "chapter")
  13.859 +end:
  13.860 +-->
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/fr/ch02-tour-basic.xml	Sat Jul 10 06:24:49 2010 +0100
    14.3 @@ -0,0 +1,1018 @@
    14.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
    14.5 +
    14.6 +<chapter id="chap:tour-basic">
    14.7 +  <?dbhtml filename="a-tour-of-mercurial-the-basics.html"?>
    14.8 +  <title>Une rapide présentation de Mercurial : les bases</title>
    14.9 +
   14.10 +  <sect1>
   14.11 +    <title>Installer Mercurial sur votre système</title>
   14.12 +
   14.13 +    <para id="x_1">Des paquetages binaires de Mercurial sont disponibles pour la
   14.14 +      plupart des systèmes d'exploitation, ce qui rend facile l'utilisation
   14.15 +      immédiate de Mercurial sur votre ordinateur.</para>
   14.16 +
   14.17 +    <sect2>
   14.18 +      <title>Windows</title>
   14.19 +
   14.20 +      <para id="x_c">La meilleure version de Mercurial pour Windows est
   14.21 +        TortoiseHg, qui peut être téléchargée ici : <ulink
   14.22 +          url="http://bitbucket.org/tortoisehg/stable/wiki/Home">http://bitbucket.org/tortoisehg/stable/wiki/Home</ulink>.
   14.23 +        Ce logiciel n'a aucune dépendance exterieure ; il fonctionne <quote>et
   14.24 +          c'est tout</quote>. Il fournit aussi bien les outils en ligne de
   14.25 +        commmande qu'une interface graphique.</para>
   14.26 + 
   14.27 +    </sect2>
   14.28 +
   14.29 +    <sect2>
   14.30 +      <title>Mac OS X</title>
   14.31 +  
   14.32 +      <para id="x_a">Lee Cantey publie un installeur de Mercurial pour Mac OS
   14.33 +        X sur <ulink
   14.34 +          url="http://mercurial.berkwood.com">http://mercurial.berkwood.com</ulink>.</para>
   14.35 +    </sect2>
   14.36 +      
   14.37 +    <sect2>
   14.38 +      <title>Linux</title>
   14.39 +
   14.40 +      <para id="x_2">Parce que chaque distribution de Linux a ses propres
   14.41 +        outils de gestion de paquets, politiques et rythmes de
   14.42 +        développements, il est difficile de donner un ensemble
   14.43 +        d'instructions unique pour installer les binaires de Mercurial. La
   14.44 +        version de Mercurial avec laquelle vous vous retrouverez dépendra
   14.45 +        grandement de l'activité de la personne en charge du paquetage pour
   14.46 +        la distribution.</para>
   14.47 +
   14.48 +      <para id="x_3">Pour rester simple, je me concentrerai sur
   14.49 +        l'installation de Mercurial en ligne de commande, sous les
   14.50 +        distributions les plus courantes. La plupart des distributions
   14.51 +        fournissent des gestionnaires graphiques de paquetage qui vous
   14.52 +        permettront d'installer Mercurial en quelques clicks. Le paquetage
   14.53 +        devrait se nommer <literal>mercurial</literal>.</para>
   14.54 +
   14.55 +      <itemizedlist>
   14.56 +        <listitem><para id="x_4">Ubuntu et Debian :</para>
   14.57 +          <programlisting>apt-get install mercurial</programlisting></listitem>
   14.58 +        <listitem><para id="x_5">Fedora :</para>
   14.59 +          <programlisting>yum install mercurial</programlisting></listitem>
   14.60 +        <listitem><para id="x_6">Gentoo :</para>
   14.61 +           <programlisting>emerge mercurial</programlisting></listitem>
   14.62 +        <listitem><para id="x_715">OpenSUSE :</para>
   14.63 +          <programlisting>zypper install
   14.64 +          mercurial</programlisting></listitem>
   14.65 +      </itemizedlist>
   14.66 +
   14.67 +    </sect2>
   14.68 +    <sect2>
   14.69 +      <title>Solaris</title>
   14.70 +
   14.71 +      <para id="x_09">SunFreeWare, à <ulink 
   14.72 +      url="http://www.sunfreeware.com">http://www.sunfreeware.com</ulink>,
   14.73 +      fournit des paquets précompilés pour Mercurial.</para>
   14.74 +    </sect2>
   14.75 +  </sect1>
   14.76 +
   14.77 +  <sect1>
   14.78 +    <title>Commencer à utiliser Mercurial</title>
   14.79 +
   14.80 +    <para id="x_e">Pour commencer, nous utiliserons la commande <command
   14.81 +        role="hg-cmd">hg version</command> pour vérifier si Mercurial est
   14.82 +      installé proprement. L'information de version affichée n'est
   14.83 +      pas réellement importante en soi, c'est surtout de savoir si elles
   14.84 +      s'affichent qui nous intéresse.</para>
   14.85 +
   14.86 +    &interaction.tour.version;
   14.87 +
   14.88 +    <sect2>
   14.89 +      <title>L'aide intégrée</title>
   14.90 +
   14.91 +      <para id="x_f">Mercurial fournit un système d'aide intégré, ce qui est
   14.92 +        inestimable quand vous vous retrouvez coincé à essayer de vous
   14.93 +        rappeler comment lancer une commande. Si vous êtes bloqué, exécutez
   14.94 +        simplement <command role="hg-cmd">hg help</command> ; elle affichera
   14.95 +        une brève liste des commandes, avec une description pour chacune. Si
   14.96 +        vous demandez de l'aide sur une commande spécifique (voir
   14.97 +        ci-dessous), elle affichera des informations plus détaillées.</para>
   14.98 +
   14.99 +      &interaction.tour.help;
  14.100 +
  14.101 +      <para id="x_10">Pour un niveau d'informations encore plus détaillé 
  14.102 +        (ce dont vous aurez rarement besoin), exécutez <command role="hg-cmd">hg 
  14.103 +        help <option role="hg-opt-global">-v</option></command>.  L'option 
  14.104 +        <option role="hg-opt-global">-v</option> est l'abréviation de 
  14.105 +        <option role="hg-opt-global">--verbose</option>, et indique à Mercurial 
  14.106 +        d'afficher plus d'informations que d'habitude.</para>
  14.107 +
  14.108 +     </sect2>
  14.109 +  </sect1>
  14.110 +  <sect1>
  14.111 +    <title>Travailler avec un dépôt</title>
  14.112 +
  14.113 +    <para id="x_11">Avec Mercurial, tout se déroule au sein d'un 
  14.114 +      <emphasis>dépôt</emphasis>. Le dépôt d'un projet contient tous 
  14.115 +      les fichiers qui <quote>appartiennent</quote> au projet.</para>
  14.116 +
  14.117 +    <para id="x_12">Il n'y a rien de particulièrement magique au sujet de 
  14.118 +      ce dépôt, c'est simplement une arborescence sur votre système de fichiers 
  14.119 +      que Mercurial traite de manière spéciale. Vous pouvez renommer ou effacer 
  14.120 +      ce répertoire à n'importe quel moment, en utilisant la ligne de commande 
  14.121 +      ou votre explorateur de fichiers.</para>
  14.122 +
  14.123 +    <sect2>
  14.124 +      <title>Faire une copie locale de votre dépôt</title>
  14.125 +      
  14.126 +      <para id="x_13"><emphasis>Copier</emphasis> un dépôt est juste un 
  14.127 +        peu spécial. Bien que vous puissiez utiliser une commande habituelle de 
  14.128 +        copie pour copier votre dépôt, il vaut mieux utiliser une commande fournie par
  14.129 +        Mercurial. Cette commande est appelée <command role="hg-cmd">hg clone</command>, 
  14.130 +        car elle crée une copie identique à un dépôt existant.</para>
  14.131 +
  14.132 +      &interaction.tour.clone;
  14.133 +
  14.134 +      <para id="x_67c">Un avantage de la commande <command role="hg-cmd">hg
  14.135 +          clone</command> est que, comme nous l'avons vu ci dessus, elle nous
  14.136 +        permet de cloner les dépôts à travers le réseau. Un autre
  14.137 +        est qu'elle se rappelle d'où a été cloné un dépôt, ce qui est utile
  14.138 +        quand on veut mettre à jour le clone.</para>
  14.139 +
  14.140 +      <para id="x_14">Si votre opération de clonage réussit, vous devriez maintenant
  14.141 +        avoir un répertoire local appelé <filename class="directory">hello</filename>. 
  14.142 +        Ce répertoire contiendra quelques fichiers.</para>
  14.143 +
  14.144 +      &interaction.tour.ls;
  14.145 +
  14.146 +      <para id="x_15">Ces fichiers ont le même contenu et historique dans votre dépôt
  14.147 +        qu'ils ont dans le dépôt que vous avez cloné.</para>
  14.148 +
  14.149 +      <para id="x_16">Chaque dépôt Mercurial est complet, autonome et
  14.150 +        indépendant. Il contient sa propre copie privée des fichiers du
  14.151 +        projet et de leur historique. Le clone d'un dépôt se souvient de la
  14.152 +        localisation du dépôt à partir duquel il a été cloné, mais il ne
  14.153 +        communique pas avec ce dernier, ou un autre, à moins que vous ne lui
  14.154 +        demandiez.</para>
  14.155 +
  14.156 +      <para id="x_17">Tout ceci signifie pour le moment que nous
  14.157 +        sommes libres d'expérimenter avec ce dépôt, confiants dans le fait
  14.158 +        qu'il s'agit d'un <quote>bac à sable</quote> qui n'affectera personne
  14.159 +        d'autre.</para>
  14.160 +
  14.161 +    </sect2>  
  14.162 +    <sect2>
  14.163 +      <title>Quel est le contenu d'un dépôt ?</title>
  14.164 +
  14.165 +      <para id="x_18">Prêtons plus attention un instant au contenu d'un dépôt. 
  14.166 +        Nous voyons qu'il contient un répertoire nommé <filename class="directory">.hg
  14.167 +        </filename>. C'est ici que Mercurial conserve toutes ses
  14.168 +        métadonnées.</para>
  14.169 +
  14.170 +      &interaction.tour.ls-a; 
  14.171 +
  14.172 +      <para id="x_19">Le contenu du répertoire <filename class="directory">.hg
  14.173 +        </filename> et ses sous-répertoires sont les seuls propres à Mercurial. 
  14.174 +        Tous les autres fichiers et répertoires dans le dépôt sont à vous, et 
  14.175 +        vous pouvez en faire ce que vous voulez.</para>
  14.176 +
  14.177 +      <para id="x_1a">Pour introduire un peu de terminologie, le répertoire 
  14.178 +        <filename class="directory">.hg</filename> est un <quote>vrai</quote> 
  14.179 +        dépôt, et tous les fichiers et les répertoires qui coexistent avec lui, 
  14.180 +        sont désignés sous le nom <emphasis>espace de travail</emphasis>. Une 
  14.181 +        manière facile de se rappeler cette distinction est de retenir que le 
  14.182 +        <emphasis>dépôt</emphasis> contient l'<emphasis>historique</emphasis>
  14.183 +        de votre projet, alors que l'<emphasis>espace de travail</emphasis> 
  14.184 +        contient un "<emphasis>snapshot</emphasis>"  de votre projet à un certain 
  14.185 +        point de son historique.</para>
  14.186 +
  14.187 +    </sect2>
  14.188 +  </sect1>
  14.189 +  <sect1>
  14.190 +    <title>Une promenade dans l'historique</title>
  14.191 +
  14.192 +    <para id="x_1b">Une des premières choses que vous aurez envie 
  14.193 +      de faire avec un nouveau dépôt, sera de comprendre son historique. 
  14.194 +      La commande <command role="hg-cmd">hg log</command> vous donne une 
  14.195 +      vue de l'historique.</para>
  14.196 +
  14.197 +    &interaction.tour.log;
  14.198 +
  14.199 +    <para id="x_1c">Par défaut, cette commande affiche à l'écran un bref paragraphe pour chaque
  14.200 +      révision enregistrée pour ce projet. Dans la terminologie de Mercurial, nous
  14.201 +      appelons chacun de ces évènements enregistrés un <emphasis>changeset</emphasis>, parce
  14.202 +      qu'il contient un ensemble de modifications sur plusieurs fichiers.</para>
  14.203 +
  14.204 +    <para id="x_1d">La commande <command role="hg-cmd">hg log</command> affiche 
  14.205 +    ainsi ces informations :</para>
  14.206 +
  14.207 +    <itemizedlist>
  14.208 +      <listitem><para id="x_1e"><literal>changeset</literal> : Ce champ contient 
  14.209 +        un nombre, séparé par deux points (:), d'une chaine hexadécimale. Il 
  14.210 +        s'agit en fait d'<emphasis>identifiants</emphasis>  d'un <quote>changeset</quote>. Il y a 
  14.211 +        deux identifiants car le numéro de la révision est plus court et plus 
  14.212 +        facile à saisir qu'une séquence hexadécimale.</para>
  14.213 +      </listitem>
  14.214 +      <listitem><para id="x_1f"><literal>user</literal> : L'identité de la personne 
  14.215 +          qui a créé ce <!--ntd %%% laisser le terme anglais car il sera affiché-->
  14.216 +          <quote>changeset</quote>. C'est un champ libre de forme, mais la plupart du
  14.217 +        temps il contient le nom et l'email de la personne.</para>
  14.218 +      </listitem>
  14.219 +      <listitem><para id="x_20"><literal>date</literal> : La date et l'heure à 
  14.220 +              laquelle le <quote>changeset</quote> a été créé, ainsi que le fuseau horaire dans 
  14.221 +        lequelle il a été créé. (La date et l'heure sont locales à ce
  14.222 +        <quote>fuseau</quote>, elles indiquent donc quelle date et heure il était
  14.223 +        pour la personne qui a créé ce <quote>changeset</quote>.)</para>
  14.224 +      </listitem>
  14.225 +      <listitem><para id="x_21"><literal>summary</literal>: La première ligne du 
  14.226 +              message que le créateur a associé à son <quote>changeset</quote> pour le décrire.</para>
  14.227 +      </listitem>
  14.228 +      <listitem><para id="x_67d">Certains <quote>changesets</quote>, comme le premier de la
  14.229 +        liste ci-dessus ont un champ <literal>tag</literal>. Le tag est une autre
  14.230 +        façon d'identifier un changeset en lui donnant un nom simple à retenir.
  14.231 +        (Le tag nommé <literal>tip</literal> est spécial : il fait toujours
  14.232 +        référence au dernier changement dans le dépôt.)</para></listitem>
  14.233 +    </itemizedlist>
  14.234 +
  14.235 +    <para id="x_22">Par défaut, la commande <command role="hg-cmd">hg log</command> 
  14.236 +      n'affiche qu'un résumé, il manque beaucoup de détails.</para>
  14.237 +
  14.238 +    <para id="x_23">La figure <xref linkend="fig:tour-basic:history"/> fournit une 
  14.239 +      représentation graphique de l'historique du dépôt <filename class="directory">hello
  14.240 +      </filename>, pour voir plus facilement dans quelle direction 
  14.241 +      l'historique se <quote>déroule</quote>. Nous reviendrons régulièrement 
  14.242 +      sur cette représentation dans ce chapitre et ceux qui suivent.</para>
  14.243 +
  14.244 +
  14.245 +    <figure id="fig:tour-basic:history">
  14.246 +      <title>Historique graphique du dépôt <filename
  14.247 +                    class="directory">hello</filename></title>
  14.248 +      <mediaobject>
  14.249 +        <imageobject><imagedata fileref="figs/tour-history.png"/></imageobject>
  14.250 +        <textobject><phrase>XXX add text</phrase></textobject>
  14.251 +      </mediaobject>
  14.252 +    </figure>
  14.253 +
  14.254 +
  14.255 +    <sect2>
  14.256 +      <title>Changesets, révisions, et collaboration</title>
  14.257 +      
  14.258 +      <para id="x_25">Comme l'anglais est réputé pour être un langage maladroit,
  14.259 +        et que l'informatique est la source de bien des erreurs de terminologie
  14.260 +        (pourquoi utiliser un seul terme quand quatre feront l'affaire ?), la
  14.261 +        gestion de révisions a une variété de mots et de phrases qui veulent dire
  14.262 +        la même chose. Si vous discutez d'historique de Mercurial avec d'autres
  14.263 +        personnes, vous constaterez que souvent, le mot <quote>changeset</quote>
  14.264 +        est contracté simplement en <quote>change</quote> ou (à l'écrit)
  14.265 +        <quote>cset</quote>, et même parfois 
  14.266 +        <quote>révision</quote>, abrégé en <quote>rev</quote>.</para>
  14.267 +
  14.268 +      <para id="x_26">Bien que le <emphasis>mot</emphasis> que vous utilisez pour 
  14.269 +        désigner le concept de changeset importe peu, l'<emphasis>identifiant</emphasis> 
  14.270 +        que vous utilisez pour désigner un <emphasis>changeset</emphasis> spécifique 
  14.271 +        a une grande importance. Rappelez vous que le champ <quote>changeset</quote> affiché par la
  14.272 +        commande <command role="hg-cmd">hg log</command> identifie un <quote>changeset</quote> à
  14.273 +        la fois avec un numéro de révision et une séquence hexadécimale.</para>
  14.274 +
  14.275 +      <itemizedlist>
  14.276 +        <listitem><para id="x_27">Le numéro de révision est <emphasis>seulement 
  14.277 +        valable dans ce dépôt</emphasis>,</para></listitem>
  14.278 +        <listitem><para id="x_28">La séquence hexadécimale est un
  14.279 +        <emphasis>identifiant permanent, et invariant</emphasis> qui 
  14.280 +        pourra toujours être associé au <quote>changeset</quote> exact de <emphasis>chaque</emphasis> 
  14.281 +        copie de votre dépôt.</para></listitem></itemizedlist>
  14.282 +
  14.283 +      <para id="x_29">La distinction est importante. Si vous envoyez un email 
  14.284 +         à quelqu'un en parlant de la <quote>révision 33</quote>, il est très 
  14.285 +         probable que sa <quote>révision 33</quote> <emphasis>ne sera pas la même</emphasis> 
  14.286 +         que la votre. La raison de ceci est que le numéro de révision dépend 
  14.287 +         de l'ordre dans lequel les modifications sont arrivées dans le dépôt, 
  14.288 +         et il n'y a aucune garantie que les mêmes changements soient arrivés 
  14.289 +         dans le même ordre dans différents dépôts. Trois modifications
  14.290 +         <literal>a, b, c</literal> peuvent aisément apparaitre dans un dépôt 
  14.291 +         comme <literal>0, 1, 2</literal>, et dans un autre comme <literal>0, 2, 1
  14.292 +         </literal>.</para>
  14.293 +
  14.294 +      <para id="x_2a">Mercurial utilise les numéros de révision uniquement comme des raccourcis
  14.295 +          pratiques. Si vous devez discuter d'un <quote>changeset</quote> avec quelqu'un,
  14.296 +          ou identifer un <quote>changeset</quote> pour une quelconque raison (par exemple,
  14.297 +          un rapport de <quote>bug</quote>), utilisez la séquence hexadécimale.</para>
  14.298 +
  14.299 +    </sect2>
  14.300 +    <sect2>
  14.301 +      <title>Afficher une révision spécifique</title>
  14.302 +
  14.303 +      <para id="x_2b">Pour réduire la sortie de <command role="hg-cmd">hg log
  14.304 +        </command> à une seule révision, utilisez l'option <option role="hg-opt-log">-r
  14.305 +        </option> (ou <option role="hg-opt-log">--rev</option>). Vous pouvez utiliser
  14.306 +        le numéro de révision ou la séquence hexadécimale comme identifiant, et
  14.307 +        demander autant de révisions que vous le souhaitez.</para>
  14.308 +
  14.309 +      &interaction.tour.log-r;
  14.310 +
  14.311 +      <para id="x_2c">Si vous voulez voir l'historique de plusieurs révisions
  14.312 +        sans avoir à les énumérer, vous pouvez utiliser un <emphasis>intervalle
  14.313 +        de numérotation</emphasis> qui vous permet d'exprimer l'idée <quote>je
  14.314 +        veux toutes les révisions entre <literal>abc</literal> et <literal>def</literal>
  14.315 +        inclus</quote>.</para>
  14.316 +
  14.317 +      &interaction.tour.log.range;
  14.318 +
  14.319 +      <para id="x_2d">Mercurial respecte aussi l'ordre dans lequel vous spécifiez
  14.320 +        les révisions, ainsi <command role="hg-cmd">hg log -r 2:4</command>
  14.321 +        affichera <literal>2, 3, 4</literal> alors que <command role="hg-cmd">hg
  14.322 +        log -r 4:2</command> affichera <literal>4, 3, 2</literal>.</para>
  14.323 +
  14.324 +    </sect2>  
  14.325 +    <sect2>
  14.326 +      <title>Informations détaillées</title>
  14.327 +
  14.328 +      <para id="x_2e">Le résumé affiché par <command role="hg-cmd">hg log</command> 
  14.329 +        est suffisant si vous savez déjà ce que vous cherchez. En 
  14.330 +        revanche, vous aurez probablement besoin de voir une description 
  14.331 +        complète du changement, ou une liste des fichiers modifiés si vous 
  14.332 +        cherchez à déterminer qu'un <quote>changeset</quote> est bien celui que vous
  14.333 +        recherchez. L'option <option role="hg-opt-log">-v</option> de la commande <command role="hg-cmd">hg 
  14.334 +        log</command> (ou <option role="hp-opt-global">--verbose</option>) vous 
  14.335 +        donne ces informations supplémentaires.</para>
  14.336 +
  14.337 +      &interaction.tour.log-v;
  14.338 +
  14.339 +      <para id="x_2f">Si vous voulez voir à la fois la description 
  14.340 +        et le contenu d'une modification, ajoutez l'option <option 
  14.341 +        role="hg-opt-log">-p</option> (ou <option role="hg-opt-log">
  14.342 +        --patch</option>). Ceci affiche le contenu d'une modification 
  14.343 +        comme un <emphasis>diff unifié</emphasis>
  14.344 +        <!-- \footnote{NdT: \textit{unified diff}} -->
  14.345 +        (si vous n'avez jamais vu de diff unifié avant, consultez la 
  14.346 +        section <xref linkend="sec:mq:patch"/> pour un rapide 
  14.347 +        survol).</para>
  14.348 +
  14.349 +      &interaction.tour.log-vp;
  14.350 +
  14.351 +      <para id="x_67e">L'option <option role="hg-opt-log">-p</option> est
  14.352 +        incroyablement utile, il est donc important dans s'en rappeler.</para>
  14.353 +
  14.354 +    </sect2>
  14.355 +  </sect1>
  14.356 +  <sect1>
  14.357 +    <title>Tout sur les options de commandes</title>
  14.358 +    
  14.359 +    <para id="x_30">Avant d'aller plus loin sur le fonctionnement 
  14.360 +      des commandes de Mercurial, étudions un moment comment elles 
  14.361 +      fonctionnent de manière générale. Vous trouverez ça probablement 
  14.362 +      utile pour la suite de notre parcours.</para>
  14.363 +
  14.364 +    <para id="x_31">Mercurial utilise une approche directe et cohérente 
  14.365 +      pour interpréter les options que vous passez aux commandes. Il suit une
  14.366 +      convention commune à la plupart des systèmes Unix et Linux modernes.</para>
  14.367 +
  14.368 +    <itemizedlist>
  14.369 +      <listitem><para id="x_32">Chaque option a un nom complet. Par exemple, 
  14.370 +        comme nous l'avons déjà vu, la commande <command role="hg-cmd">hg 
  14.371 +        log</command> accepte l'option <option role="hg-opt-log">--rev
  14.372 +        </option>.</para>
  14.373 +      </listitem>
  14.374 +      <listitem><para id="x_33">La plupart des options disposent de 
  14.375 +        noms abrégés. Aussi, au lieu d'utiliser <option role="hg-opt-log">--rev
  14.376 +        </option>, vous pouvez utiliser <option role="hg-opt-log">-r</option>. 
  14.377 +        (Les options qui n'ont pas de nom abrégé sont généralement 
  14.378 +        rarement utilisées).</para>
  14.379 +      </listitem>
  14.380 +      <listitem><para id="x_34">Les noms complets commencent par deux 
  14.381 +        tirets (par exemple <option role="hg-opt-log">--rev</option>),
  14.382 +        alors que les options courtes commencent avec un seul (par exemple 
  14.383 +        <option role="hg-opt-log">-r</option>).</para>
  14.384 +      </listitem>
  14.385 +     <listitem><para id="x_35">Les noms des options sont cohérents 
  14.386 +       entre les commandes. Par exemple, chaque commande qui accepte 
  14.387 +       un <quote>changeset ID</quote> ou un numéro de révision accepte aussi <option 
  14.388 +       role="hg-opt-log">-r</option> et <option role="hg-opt-log">--rev
  14.389 +       </option> comme arguments.</para>
  14.390 +     </listitem>
  14.391 +   </itemizedlist>
  14.392 +
  14.393 +   <para id="x_36">Dans les exemples de ce livre, j'utilise les noms abrégés 
  14.394 +     plutôt que les noms complets. Ceci est une préférence personnelle, pas 
  14.395 +     une recommandation.</para>
  14.396 +
  14.397 +   <para id="x_37">La plupart des commandes qui affichent une quelconque sortie 
  14.398 +     à l'écran, afficheront davantage avec l'option <option role="hg-opt-global">
  14.399 +     -v</option> (ou <option role="hg-opt-global">--verbose</option>), et
  14.400 +     moins avec l'option <option role="hg-opt-global">-q</option> (ou 
  14.401 +     <option role="hg-opt-global">--quiet</option>).</para>
  14.402 +
  14.403 +    <note>
  14.404 +      <title>Cohérence dans le nom des options</title>
  14.405 +      
  14.406 +      <para id="x_680">Presque toujours, les commandes de Mercurial utilisent
  14.407 +      des noms d'options cohérentes pour se référer à des concepts identiques.
  14.408 +      Par exemple, si une commande concerne les <quote>changesets</quote>, vous les
  14.409 +      identifierez toujours avec l'option <option role="hg-opt-log">-r</option>.
  14.410 +      Cette utilisation cohérente des noms d'options permet de mémoriser plus
  14.411 +      facilement quelles options acceptent une commande.</para>
  14.412 +   </note>
  14.413 +
  14.414 +
  14.415 +  </sect1>
  14.416 +  <sect1>
  14.417 +    <title>Faire et vérifier des modifications</title>
  14.418 +
  14.419 +    <para id="x_38">Maintenant que nous avons une bonne idée des 
  14.420 +      commandes pour consulter l'historique de Mercurial, regardons 
  14.421 +      comment faire des modifications et les examiner.</para>
  14.422 +     
  14.423 +    <para id="x_39">La première chose que nous allons faire est d'isoler notre
  14.424 +      exercice dans un dépôt à part. Nous allons utiliser la commande <command
  14.425 +        role="hg-cmd">hg clone</command>, mais nous n'avons pas besoin de faire
  14.426 +      une copie de dépôt distant. Comme nous avons déjà une copie locale, nous
  14.427 +      pouvons juste faire un clone de celle-ci à la place. C'est beaucoup plus
  14.428 +      rapide que de faire une copie à travers le réseau, et un dépôt cloné
  14.429 +      localement prend également moins d'espace disque<footnote>
  14.430 +      <para id="x_681">L'économie d'espace disque apparait clairement quand les
  14.431 +        dépôts source et destination sont sur le même système de fichier, où, dans
  14.432 +        ce cas, Mercurial utilisera des liens physiques pour effectuer des partages
  14.433 +        copie-lors-des-écritures de ses métadonnées internes. Si cette explication
  14.434 +        ne signifie rien pour vous, ne vous inquiétez pas : tout ceci se passe de
  14.435 +        manière transparente et automatique. Vous n'avez pas du tout besoin de
  14.436 +        comprendre ceci.</para></footnote>.</para>
  14.437 +  
  14.438 +    &interaction.tour.reclone;
  14.439 +
  14.440 +    <para id="x_3a">On notera au passage qu'il est souvent considéré comme
  14.441 +      une bonne pratique de conserver une copie <quote>immaculée</quote>
  14.442 +      du dépôt distant, à partir de laquelle vous pourrez faire des 
  14.443 +      copies locales temporaires pour créer des <quote>bacs à sable</quote> 
  14.444 +      pour chaque tâche sur laquelle vous souhaitez travailler. Ceci 
  14.445 +      vous permet de travailler sur plusieurs choses en parallèle, 
  14.446 +      chacunes isolées les unes des autres en attendant que ces tâches 
  14.447 +      soient finies et que vous soyez prêt à les réintégrer. Parce 
  14.448 +      que les copies locales sont peu coûteuses, il est très rapide 
  14.449 +      de créer ou détruire des dépôts dès que vous n'en avez plus
  14.450 +      besoin.</para>
  14.451 +
  14.452 +    <para id="x_3b">Dans notre dépôt <filename
  14.453 +        class="directory">my-hello</filename>, nous avons un fichier
  14.454 +      <filename>hello.c</filename> qui contient le classique <quote>hello,
  14.455 +        world</quote>.</para>
  14.456 +   
  14.457 +    &interaction.tour.cat1;
  14.458 +
  14.459 +    <para id="x_682">Éditons ce fichier pour qu'il affiche une autre ligne
  14.460 +      sur la sortie standard.</para>
  14.461 +    
  14.462 +    &interaction.tour.cat2;
  14.463 +
  14.464 +    <para id="x_3c">La commande Mercurial <command role="hg-cmd">hg
  14.465 +        status</command> nous dira ce que Mercurial sait des fichiers du
  14.466 +      dépôts.</para>
  14.467 +
  14.468 +    &interaction.tour.status;
  14.469 +
  14.470 +    <para id="x_3d">La commande <command role="hg-cmd">hg status</command>
  14.471 +      n'affichera pas le contenu des fichiers, mais une ligne commençant par
  14.472 +      <quote><literal>M</literal></quote> pour <filename>hello.c</filename>.
  14.473 +      À moins que vous lui demandiez, la commande <command role="hg-cmd">hg
  14.474 +        status</command> n'affichera aucune information sur les fichiers que
  14.475 +      vous n'avez pas modifiés.</para>
  14.476 + 
  14.477 +    <para id="x_3e">Le <quote><literal>M</literal></quote> indique que
  14.478 +      Mercurial a remarqué que nous avons modifié le fichier
  14.479 +      <filename>hello.c</filename>. Nous n'avons pas besoin
  14.480 +      <emphasis>d'informer</emphasis> Mercurial que nous allons modifier un
  14.481 +      fichier avant de commencer à le faire, ou que nous avons modifié un
  14.482 +      fichier après avoir commencé à le faire, il est capable de le découvrir
  14.483 +      tout seul.</para>
  14.484 +
  14.485 +    <para id="x_3f">C'est déjà pratique de savoir que nous avons modifié le
  14.486 +      fichier <filename>hello.c</filename>, mais nous préférerions savoir
  14.487 +      exactement <emphasis>ce que</emphasis> nous avons changé. Pour ceci, nous
  14.488 +      utilisons la commande <command role="hg-cmd">hg diff</command>.</para>
  14.489 +
  14.490 +    &interaction.tour.diff;
  14.491 +
  14.492 +    <tip>
  14.493 +      <title>Comprendre les patches</title>
  14.494 +   
  14.495 +      <para id="x_683">Penser à jeter un oeil à <xref
  14.496 +          linkend="sec:mq:patch"/> si vous n'arrivez pas à lire la sortie
  14.497 +        ci-dessus.</para>
  14.498 +    </tip>
  14.499 +  </sect1>
  14.500 +  <sect1>
  14.501 +    <title>Enregistrer vos modifications dans une nouvelle révision</title>
  14.502 +   
  14.503 +    <para id="x_40">Nous pouvons modifier des fichiers, compiler et tester
  14.504 +      nos modifications, et utiliser les commandes <command role="hg-cmd">hg
  14.505 +        status</command> et <command role="hg-cmd">hg diff</command> pour
  14.506 +      voir les modifications effectuées, jusqu'à ce que nous soyons assez
  14.507 +      satisfaits pour décider d'enregistrer notre travail dans un
  14.508 +      <quote>changeset</quote>.</para>
  14.509 +
  14.510 +    <para id="x_41">La commande <command role="hg-cmd">hg commit</command>
  14.511 +      vous laisse créer une nouvelle révision, nous désignerons généralement
  14.512 +      cette opération par <quote>faire un commit</quote> ou
  14.513 +      <quote>commiter</quote>.</para>
  14.514 +
  14.515 +    <sect2>
  14.516 +    <title>Définir le nom d'utilisateur</title>
  14.517 +
  14.518 +      <para id="x_42">Quand vous exécutez la commande <command
  14.519 +          role="hg-cmd">hg commit</command> pour la première fois, il n'est
  14.520 +        pas garanti qu'elle réussisse du premier coup. En effet, Mercurial
  14.521 +        enregistre votre nom et votre adresse avec chaque modification que
  14.522 +        vous effectuez, de manière à ce que vous soyez capable (ou d'autres
  14.523 +        le soient) de savoir qui a fait telle modification. Mercurial essaye
  14.524 +        automatiquement de découvrir un nom d'utilisateur qui ait un minimum
  14.525 +        de sens pour effectuer l'opération de <quote>commit</quote> avec. Il va essayer
  14.526 +        chacune des méthodes suivantes, dans l'ordre :</para>
  14.527 +
  14.528 +      <orderedlist>
  14.529 +        <listitem><para id="x_43">Si vous spécifiez l'option <option
  14.530 +              role="hg-opt-commit">-u</option> avec la commande <command
  14.531 +              role="hg-cmd">hg commit</command>, suivi d'un nom
  14.532 +            d'utilisateur, ceci aura toujours la priorité sur les autres
  14.533 +            méthodes ci dessous.</para></listitem>
  14.534 +        <listitem><para id="x_44">Si vous avez défini une variable
  14.535 +            d'environnement <envar>HGUSER</envar>, c'est cette valeur qui est
  14.536 +            alors utilisée.</para></listitem>
  14.537 +        <listitem><para id="x_45">Si vous créez un fichier nommé <filename
  14.538 +              role="special">.hgrc</filename> dans votre répertoire
  14.539 +            \textit{home}, avec une entrée <envar
  14.540 +              role="rc-item-ui">username</envar>, c'est la valeur associée
  14.541 +            qui sera utilisée. Pour voir à quoi ressemble le contenu de ce
  14.542 +            fichier regardez la section <xref
  14.543 +              linkend="sec:tour-basic:username"/>
  14.544 +            ci-dessous.</para></listitem>
  14.545 +        <listitem><para id="x_46">Si vous avez défini une variable
  14.546 +            d'environnement <envar>EMAIL</envar> celle ci sera utilisée
  14.547 +            ensuite.</para></listitem>
  14.548 +        <listitem><para id="x_47">Enfin, Mercurial interrogera votre système
  14.549 +            pour trouver votre nom d'utilisateur local ainsi que le nom de la
  14.550 +            machine hôte, et il fabriquera un nom d'utilisateur à partir de
  14.551 +            ces données. Comme il arrive souvent que ce genre de nom soit
  14.552 +            totalement inutile, il vous préviendra en affichant un message
  14.553 +            d'avertissement.</para></listitem>
  14.554 +      </orderedlist>
  14.555 +   
  14.556 +      <para id="x_48">Si tous ces mécanismes échouent, Mercurial n'exécutera
  14.557 +        pas la commande, affichant un message d'erreur. Dans ce cas, il ne
  14.558 +        vous laissera pas effectuer de <quote>commit</quote> tant que vous n'aurez pas
  14.559 +        défini un nom d'utilisateur.</para>
  14.560 +   
  14.561 +      <para id="x_49">Vous devriez penser à utiliser la variable
  14.562 +        d'environement <envar>HGUSER</envar> et l'option <option
  14.563 +          role="hg-opt-commit">-u</option> comme moyen pour
  14.564 +        <emphasis>changer</emphasis> le nom d'utilisateur par défaut. Pour
  14.565 +        une utilisation normale, la manière la plus simple et robuste
  14.566 +        d'opérer est de créer un fichier <filename
  14.567 +          role="special">.hgrc</filename>, voir ci-dessous pour les détails
  14.568 +        à ce sujet.</para>
  14.569 +
  14.570 +      <sect3 id="sec:tour-basic:username">
  14.571 +        <title>Créer un fichier de configuration pour Mercurial</title>
  14.572 +
  14.573 +        <para id="x_4a">Pour définir un nom d'utilisateur, utilisez votre 
  14.574 +          éditeur de texte favori pour créer un fichier <filename 
  14.575 +            role="special">.hgrc</filename> dans votre répertoire home. 
  14.576 +          Mercurial va utiliser ce fichier pour retrouver votre 
  14.577 +          configuration personnelle. Le contenu initial devrait
  14.578 +          ressembler à ceci :</para>
  14.579 +   
  14.580 +        <tip>
  14.581 +          <title><quote>Home directory</quote> sous Windows</title>
  14.582 +   
  14.583 +          <para id="x_716">Quand on parle de répertoire <quote>home</quote>, sur une version
  14.584 +            anglaise d'une installation de Windows, il s'agira habituellement
  14.585 +            d'un répertoire nommée comme votre nom dans <filename>C:\Documents 
  14.586 +              and Settings</filename>. Vous pouvez trouver de quel répertoire
  14.587 +            il s'agit en lançant une fenêtre d'interpréteur de commande et en
  14.588 +            exécutant la commande suivante :</para>
  14.589 +          
  14.590 +          <screen><prompt>C:\</prompt> <userinput>echo
  14.591 +              %UserProfile</userinput></screen>
  14.592 +        </tip>
  14.593 +   
  14.594 +        <programlisting># This is a Mercurial configuration file.
  14.595 +[ui]
  14.596 +username = Firstname Lastname &lt;email.address@domain.net&gt;</programlisting>
  14.597 +
  14.598 +        <para id="x_4b">La ligne avec <literal>[ui]</literal> commence une
  14.599 +          <emphasis>section</emphasis> du fichier de configuration, ainsi la ligne
  14.600 +          <quote><literal>username = ...</literal></quote> signifie <quote>
  14.601 +            définir la valeur de l'élément <literal>username</literal> dans la
  14.602 +            section <literal>ui</literal></quote>. Une section continue jusqu'à ce
  14.603 +          qu'une nouvelle commence, ou que la fin du fichier soit atteinte.
  14.604 +          Mercurial ignore les lignes vides et traite tout texte situé à la suite
  14.605 +          d'un <quote><literal>#</literal></quote> jusqu'à la fin de la ligne
  14.606 +          comme un commentaire.</para>
  14.607 +
  14.608 +      </sect3>
  14.609 +      <sect3>
  14.610 +        <title>Choisir un nom d'utilisateur</title>
  14.611 + 
  14.612 +        <para id="x_4c">Vous pouvez utiliser n'importe quelle valeur 
  14.613 +          pour votre <literal>username</literal>, car cette information 
  14.614 +          est destinée à d'autres personnes et non à être interprétée 
  14.615 +          par Mercurial. La convention que la plupart des personnes
  14.616 +          suivent est d'utiliser leur nom suivie de leur adresse email,
  14.617 +          comme montré ci-dessus :</para>
  14.618 +        <note>
  14.619 +          <para id="x_4d">Le mécanisme interne du serveur web intégré à Mercurial,
  14.620 +            masque les adresses emails, pour rendre plus difficile leurs
  14.621 +            récupérations par les outils utilisés par les spammmers.
  14.622 +            Ceci réduit la probabilité que de recevoir encore plus de
  14.623 +            spam si vous vous publiez un dépôt sur internet.</para>
  14.624 +        </note>
  14.625 +      </sect3>
  14.626 +    </sect2>
  14.627 +    <sect2>
  14.628 +        <title>Rédiger un message de <quote>commit</quote></title>
  14.629 +  
  14.630 +        <para id="x_4e">Lorsqu'on effectue une opération de <quote>commit</quote>, Mercurial
  14.631 +        lance automatiquement un éditeur de texte pour permettre de saisir
  14.632 +        un message qui décrira les modifications effectuées dans cette
  14.633 +        révision. Ce message est nommé le <emphasis>message de commit</emphasis>. 
  14.634 +        Ce sera un enregistrement pour tout lecteur expliquant le pourquoi 
  14.635 +        et le comment de vos modifications, et il sera affiché par la 
  14.636 +        commande <command role="hg-cmd">hg log</command>.</para>
  14.637 + 
  14.638 +      &interaction.tour.commit; 
  14.639 +  
  14.640 +      <para id="x_4f">L'éditeur que la commande <command role="hg-cmd">hg 
  14.641 +          commit</command> déclenche ne contiendra qu'une ligne vide suivi 
  14.642 +        d'un certain nombre de lignes commençant par <quote><literal>HG:
  14.643 +        </literal></quote>.</para>
  14.644 +    
  14.645 +        <programlisting>
  14.646 +    This is where I type my commit comment.
  14.647 +    
  14.648 +    HG: Enter commit message.  Lines beginning with 'HG:' are removed.
  14.649 +    HG: --
  14.650 +    HG: user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
  14.651 +    HG: branch 'default'
  14.652 +    HG: changed hello.c</programlisting>
  14.653 +
  14.654 +
  14.655 +      <para id="x_50">Mercurial ignore les lignes qui commencent 
  14.656 +        avec <quote><literal>HG:</literal></quote>, il ne les 
  14.657 +        utilise que pour nous indiquer quels fichiers modifiés il se
  14.658 +        prépare à <quote>commiter</quote>. Modifier ou effacer ces lignes n'a
  14.659 +        aucune conséquence sur l'opération de <quote>commit</quote>.
  14.660 +      </para>
  14.661 +
  14.662 +    </sect2>
  14.663 +    <sect2>
  14.664 +        <title>Rédiger un message approprié</title>
  14.665 +  
  14.666 +      <para id="x_51">Comme <command role="hg-cmd">hg log</command> n'affiche
  14.667 +          que la première ligne du message de <quote>commit</quote> par défaut, il est souvent
  14.668 +          considéré comme une bonne pratique de rédiger des messages de <quote>commit</quote>
  14.669 +        qui tiennent sur une seule ligne. Voilà un exemple concret de message 
  14.670 +        de <quote>commit</quote> qui <emphasis>ne suit pas</emphasis> cette directive, et
  14.671 +        qui a donc un résumé peu lisible.</para>
  14.672 +
  14.673 +      <programlisting>
  14.674 +changeset:   73:584af0e231be
  14.675 +user:        Censored Person &lt;censored.person@example.org&gt;
  14.676 +date:        Tue Sep 26 21:37:07 2006 -0700
  14.677 +summary:     include buildmeister/commondefs.   Add an exports and install
  14.678 +      </programlisting>
  14.679 +  
  14.680 +      <para id="x_52">À ce sujet, il faut noter qu'il n'existe pas de règle 
  14.681 +        absolue dans ce domaine. Mercurial lui-même n'interprète pas les 
  14.682 +        contenus des messages de <quote>commit</quote>, ainsi votre projet est libre de 
  14.683 +        concevoir différentes politiques de mise en page des messages.</para>
  14.684 +      
  14.685 +      <para id="x_53">Ma préférence personnelle va au message court, mais 
  14.686 +        informatif, qui offre des précisions supplémentaires par rapport à ce 
  14.687 +        que pourrait m'apprendre une commande <command role="hg-cmd">hg log 
  14.688 +          --patch</command>.</para>
  14.689 +      
  14.690 +      <para id="x_55">Si vous exécutez la commande <command role="hg-cmd">hg
  14.691 +          commit</command> sans aucun argument, elle enregistre tous les 
  14.692 +        changements qui ont été fait, et qui sont indiqué par les commandes
  14.693 +        <command role="hg-cmd">hg status</command> et  <command 
  14.694 +          role="hg-cmd">hg diff</command>.</para>
  14.695 +      
  14.696 +      <note>
  14.697 +        <title>Une surprise pour les utilisateurs habitués à Subversion</title>
  14.698 +   
  14.699 +        <para id="x_717">Comme n'importe quel autre commande de Mercurial, si
  14.700 +          vous ne soumettez pas de manière explicite les noms des fichiers à
  14.701 +          <quote>commiter</quote> à la commande <command role="hg-cmd">hg commit</command>, elle
  14.702 +          va travailler sur l'ensemble du répertoire de travail. Soyez conscient
  14.703 +          de ceci si vous venez du monde Subversion ou CVS, car vous pourriez
  14.704 +          vous attendre à ce qu'elle opère uniquement sur le répertoire courant et ses
  14.705 +          sous-répertoires.</para>
  14.706 +      </note>
  14.707 +    </sect2>
  14.708 +    <sect2>
  14.709 +        <title>Annuler un <quote>commit</quote></title>
  14.710 +
  14.711 +      <para id="x_54">Si, en rédigeant le message, vous décidez que 
  14.712 +          finalement vous ne voulez pas effectuer ce <quote>commit</quote>, il suffit 
  14.713 +        de quitter simplement l'éditeur sans sauvegarder. Ceci n'aura aucune 
  14.714 +        conséquence sur le dépôt ou les fichiers du répertoire de 
  14.715 +        travail.</para>
  14.716 +    </sect2>
  14.717 +  
  14.718 +    <sect2>
  14.719 +      <title>Admirer votre travail</title>
  14.720 +  
  14.721 +      <para id="x_56">Une fois que votre <quote>commit</quote> est terminé, vous
  14.722 +        pouvez utiliser la commande <command role="hg-cmd">hg tip</command>
  14.723 +        pour afficher le <quote>changeset</quote> que vous venez de créer. Cette
  14.724 +        commande produit une sortie à l'écran qui est identique à celle du
  14.725 +        <command role="hg-cmd">hg log</command>, mais qui n'affiche que la
  14.726 +        dernière révision du dépôt.</para>
  14.727 + 
  14.728 +      &interaction.tour.tip; 
  14.729 +  
  14.730 +      <para id="x_57">On fait couramment référence à la dernière révision 
  14.731 +        du dépôt comme étant la <emphasis>révision tip</emphasis>, ou plus
  14.732 +        simplement le <emphasis>tip</emphasis>.</para>
  14.733 +  
  14.734 +      <para id="x_684">Au passage, la commande <command role="hg-cmd">hg
  14.735 +          tip</command> accepte la plupart des options qu'accepte 
  14.736 +        <command role="hg-cmd">hg log</command>. Ainsi <option
  14.737 +          role="hg-opt-global">-v</option> ci-dessus implique <quote>soit
  14.738 +          verbeux</quote>, <option role="hg-opt-tip">-p</option>
  14.739 +        veut dire <quote>affiche le patch</quote>. L'utilisation de l'option
  14.740 +        <option role="hg-opt-tip">-p</option> pour afficher un patch est un
  14.741 +        autre exemple de la cohérence des commandes évoquée plus tôt.</para>
  14.742 +
  14.743 +    </sect2>
  14.744 +  </sect1>
  14.745 +  <sect1>
  14.746 +    <title>Partager ses modifications</title>
  14.747 +
  14.748 +    <para id="x_58">Nous avons mentionné plus haut que les dépôts 
  14.749 +      de Mercurial sont autosuffisants. Ce qui signifie que la nouvelle
  14.750 +      révision que vous venez de créer existe seulement dans votre 
  14.751 +      répertoire <filename class="directory">my-hello</filename>. Étudions 
  14.752 +      comment propager cette modification dans d'autres dépôts.</para>
  14.753 +
  14.754 +    <sect2 id="sec:tour:pull">
  14.755 +      <title>Récupérer les modifications d'autres dépôts</title>
  14.756 +
  14.757 +      <para id="x_59">Pour commencer, construisons un clone de notre dépôt 
  14.758 +        <filename class="directory">hello</filename> qui ne contiendra pas 
  14.759 +        le changement que nous venons d'effectuer. Nous l'appellerons notre 
  14.760 +        dépôt temporaire <filename
  14.761 +          class="directory">hello-pull</filename>.</para>
  14.762 + 
  14.763 +      &interaction.tour.clone-pull;
  14.764 + 
  14.765 +      <para id="x_5a">Nous allons utiliser la commande <command
  14.766 +          role="hg-cmd">hg pull</command> pour envoyer les modifications
  14.767 +        depuis <filename class="directory">my-hello</filename> dans <filename
  14.768 +          class="directory">hello-pull</filename>. Néanmoins, récupérer
  14.769 +        aveuglement des modifications depuis un dépôt a quelque chose d'un
  14.770 +        peu effrayant. Mercurial propose donc une commande <command
  14.771 +          role="hg-cmd">hg incoming</command> qui permet de savoir quelles
  14.772 +        modifications la commande <command role="hg-cmd">hg pull</command>
  14.773 +        <emphasis>pourrait</emphasis> entraîner dans notre dépôt, et ceci
  14.774 +        sans effectuer réellement de modification dessus.</para>
  14.775 +
  14.776 +      &interaction.tour.incoming; 
  14.777 +  
  14.778 +      <para id="x_5c">Apporter les modifications rapatriées dans un dépôt se
  14.779 +        résume donc à exécuter la commande <command role="hg-cmd">hg
  14.780 +          pull</command>, et préciser depuis quel dépôt effectuer le <command
  14.781 +          role="hg-cmd">hg pull</command>.</para>
  14.782 +      
  14.783 +      &interaction.tour.pull;
  14.784 +  
  14.785 +      <para id="x_5d">Comme vous le voyez avec une sortie avant et après de la
  14.786 +        commande <command role="hg-cmd">hg tip</command>, nous avons réussi à
  14.787 +        récupérer aisément les modifications dans notre dépôt. Il reste néanmoins
  14.788 +        quelque chose à faire avant de retrouver ces modifications dans l'espace de
  14.789 +        travail.</para>
  14.790 +   
  14.791 +      <tip>
  14.792 +        <title>Récupérer des changements précis</title>
  14.793 +   
  14.794 +        <para id="x_5b">Il est possible à cause du délai entre l'exécution de la
  14.795 +          commande <command role="hg-cmd">hg incoming</command> et l'exécution de
  14.796 +          la commande <command role="hg-cmd">hg pull</command>, que vous ne
  14.797 +          puissiez pas voir toutes les modifications que vous rapporterez d'un
  14.798 +          autre dépôt. Supposons que vous récupériez les modifications d'un dépôt
  14.799 +          situé quelque part sur le réseau. Alors que vous regardez le résultat de
  14.800 +          la commande <command role="hg-cmd">hg incoming</command>, et avant que
  14.801 +          vous ne décidiez de récupérer ces modifications, quelqu'un peut ajouter
  14.802 +          de nouvelles révisions dans le dépôt distant. Ce qui signifie que vous
  14.803 +          récupérez plus de révisions que ce que vous aviez regardées en utilisant
  14.804 +          la commande <command role="hg-cmd">hg incoming</command>.</para>
  14.805 +
  14.806 +        <para id="x_718">Si vous voulez seulement récupérer ce que vous aviez
  14.807 +          vérifié à l'aide de la commande <command role="hg-cmd">hg
  14.808 +            incoming</command>, ou que pour d'autres raisons vous ne souhaitiez
  14.809 +          récupérer qu'un sous ensemble des révisions supplémentaires
  14.810 +          disponibles, indiquez simplement les modifications que vous souhaitez
  14.811 +          récupérer par leurs ID de révision, soit <command>hg pull
  14.812 +            -r7e95bb</command>. </para>
  14.813 +      </tip>
  14.814 +  
  14.815 +    </sect2>
  14.816 +    <sect2>
  14.817 +      <title>Mise à jour de l'espace de travail</title>
  14.818 +  
  14.819 +      <para id="x_5e">Nous avons jusqu'à maintenant grossièrement défini la
  14.820 +        relation entre un dépôt et un espace de travail. La commande <command
  14.821 +          role="hg-cmd">hg pull</command> que nous avons exécutée dans la section 
  14.822 +        <xref linkend="sec:tour:pull"/> a apporté des modifications, que nous
  14.823 +        avons vérifiées, dans notre dépôt, mais il n'y a aucune trace de ces
  14.824 +        modifications dans notre espace de travail. En effet, <command
  14.825 +          role="hg-cmd">hg pull</command> ne touche pas (par défaut) à l'espace
  14.826 +        de travail. C'est la commande <command role="hg-cmd">hg update</command>
  14.827 +        qui s'en charge.</para>
  14.828 + 
  14.829 +      &interaction.tour.update;
  14.830 +  
  14.831 +      <para id="x_5f">Il peut sembler un peu étrange que la commande <command
  14.832 +          role="hg-cmd">hg pull</command> ne mette pas à jour l'espace de travail
  14.833 +        automatiquement. Il y a en fait une très bonne raison à cela : vous
  14.834 +        pouvez utiliser la commande <command role="hg-cmd">hg update</command>
  14.835 +        pour mettre à jour votre espace de travail à l'état dans lequel il était 
  14.836 +        à <emphasis>n'importe quelle révision</emphasis> de l'historique du dépôt. 
  14.837 +        Si vous aviez un espace de travail contenant une ancienne
  14.838 +        révision&emdash;pour chercher l'origine d'un bug, par exemple&emdash;et
  14.839 +        que vous effectuiez un <command role="hg-cmd">hg pull</command> qui
  14.840 +        mettrait à jour automatiquement votre espace de travail, vous ne seriez
  14.841 +        probablement pas très satisfait.</para>
  14.842 +  
  14.843 +      <para id="x_60">Néanmoins, comme les opérations de pull sont très souvent
  14.844 +        suivies d'un update, Mercurial vous permet de combiner les
  14.845 +        deux aisément en passant l'option <option role="hg-opt-pull">-u</option> 
  14.846 +        à la commande <command role="hg-cmd">hg pull</command>.</para>
  14.847 +  
  14.848 +      <para id="x_61">Si vous étudiez de nouveau la sortie de la commande <command
  14.849 +          role="hg-cmd">hg pull</command> dans la section <xref
  14.850 +          linkend="sec:tour:pull"/> quand nous l'avons exécutée sans l'option
  14.851 +        <option role="hg-opt-pull">-u</option>, vous pouvez constater qu'elle a
  14.852 +        affiché un rappel assez utile : vous devez encore effectuer une
  14.853 +        opération pour mettre à jour votre espace de travail.</para>
  14.854 +
  14.855 +      <para id="x_62">Pour découvrir sur quelle révision de l'espace de 
  14.856 +        travail on se trouve, utilisez la commande <command role="hg-cmd">hg
  14.857 +          parents</command>.</para>
  14.858 + 
  14.859 +      &interaction.tour.parents;
  14.860 +   
  14.861 +      <para id="x_63">Si vous regardez de nouveau le dessin <xref
  14.862 +          linkend="fig:tour-basic:history"/>, vous verrez les flèches reliant
  14.863 +        entre elles les révisions. Le nœud d'où la flèche
  14.864 +        <emphasis>part</emphasis> est dans chaque cas un parent,
  14.865 +        et le nœud où la flèche <emphasis>arrive</emphasis> est un
  14.866 +        enfant.</para>
  14.867 +
  14.868 +      <para id="x_64">Pour mettre à jour l'espace de travail d'une révision
  14.869 +          particulière, indiquez un numéro de révision ou un <quote>changeset
  14.870 +              ID</quote> à la commande <command role="hg-cmd">hg update</command>.</para>
  14.871 +  
  14.872 +      &interaction.tour.older;
  14.873 +   
  14.874 +      <para id="x_65">Si vous ne précisez pas de manière explicite de numéro 
  14.875 +        de révision la commande <command role="hg-cmd">hg update</command>
  14.876 +        mettra à jour votre espace de travail avec le contenu de la révison
  14.877 +        <quote>tip</quote>, comme montré dans l'exemple ci-dessus lors du second
  14.878 +        appel à <command role="hg-cmd">hg update</command>.</para>
  14.879 +    
  14.880 +    </sect2>
  14.881 +    <sect2>
  14.882 +      <title>Transférer les modifications vers un autre dépôt</title>
  14.883 +  
  14.884 +      <para id="x_66">Mercurial vous laisse transférer les modifications vers
  14.885 +        un autre dépôt, depuis votre dépôt actuel. Comme dans l'exemple du
  14.886 +        <command role="hg-cmd">hg pull</command> ci-dessus, nous allons créer
  14.887 +        un dépôt temporaire vers lequel transférer nos modifications.</para>
  14.888 +        
  14.889 +      &interaction.tour.clone-push;
  14.890 +  
  14.891 +      <para id="x_67">La commande <command role="hg-cmd">hg outgoing</command>
  14.892 +        nous indique quels changements nous allons transférer vers l'autre
  14.893 +        serveur.</para>
  14.894 + 
  14.895 +      &interaction.tour.outgoing;
  14.896 +  
  14.897 +      <para id="x_68">Et la commande <command role="hg-cmd">hg push</command> 
  14.898 +        effectue réellement le transfert.</para>
  14.899 + 
  14.900 +      &interaction.tour.push;
  14.901 +  
  14.902 +      <para id="x_69">Comme avec <command role="hg-cmd">hg pull</command>, la
  14.903 +        commande <command role="hg-cmd">hg push</command> ne met pas à jour
  14.904 +        le répertoire de travail du dépôt dans lequel il transfère les
  14.905 +        modifications. À l'inverse de <command role="hg-cmd">hg
  14.906 +          pull</command>, <command role="hg-cmd">hg push</command> ne fournit
  14.907 +        pas d'option <literal>-u</literal> pour forcer la mise à jour de
  14.908 +        l'espace de travail cible. Cette asymétrie est délibéré : le dépot
  14.909 +        vers lequel nous transférons peut très bien être un serveur distant
  14.910 +        et partagé par plusieurs personnes. Si nous devions mettre à jour son
  14.911 +        répertoire de travail alors que quelqu'un d'autre travaille dessus,
  14.912 +        nous risquerions de perturber son travail.</para>
  14.913 +  
  14.914 +      <para id="x_6a">Que se passe-t-il lorsque vous essayez de récupérer
  14.915 +        ou de transférer vos modifications et que le dépôt cible a déjà reçu
  14.916 +        ces modifications ? Rien de bien excitant.</para>
  14.917 + 
  14.918 +      &interaction.tour.push.nothing;
  14.919 +  
  14.920 +    </sect2>
  14.921 +  
  14.922 +    <sect2>
  14.923 +      <title>Emplacements par défaut</title>
  14.924 +
  14.925 +      <para id="x_719">Quand nous faisons un clone d'un dépôt, Mercurial
  14.926 +        enregistre l'emplacement du dépôt d'origine dans le fichier
  14.927 +        <filename>.hg/hgrc</filename> de notre nouveau dépôt. Si nous ne
  14.928 +        fournissons pas d'emplacement à la commande <command>hg
  14.929 +          pull</command> ou à la commande <command>hg push</command>, ces
  14.930 +        commandes utiliseront alors cet emplacement comme valeur par défaut.
  14.931 +        Les commandes <command>hg incoming</command> et <command>hg
  14.932 +          outgoing</command> feront de même.</para>
  14.933 +  
  14.934 +      <para id="x_71a">Si vous regardez le fichier
  14.935 +        <filename>.hg/hgrc</filename>, vous constaterez que son contenu
  14.936 +        ressemble à ce qui suit.</para>
  14.937 +  
  14.938 +      <programlisting>[paths]
  14.939 +default = http://www.selenic.com/repo/hg</programlisting>
  14.940 +      
  14.941 +      <para id="x_71b">Il est possible&emdash;et souvent
  14.942 +        pratique&emdash;d'avoir un emplacement par défaut pour les commandes
  14.943 +        <command>hg push</command> et <command>hg outgoing</command>
  14.944 +        différent de celui des commandes <command>hg pull</command> et
  14.945 +        <command>hg incoming</command>. C'est faisable en ajoutant une entrée
  14.946 +        <literal>default-push</literal> à la section
  14.947 +        <literal>[paths]</literal> du <filename>.hg/hgrc</filename>, comme
  14.948 +        suit.</para>
  14.949 +   
  14.950 +      <programlisting>[paths]
  14.951 +default = http://www.selenic.com/repo/hg
  14.952 +default-push = http://hg.example.com/hg</programlisting>
  14.953 +
  14.954 +    </sect2>
  14.955 +    <sect2>
  14.956 +      <title>Partager ses modifications à travers le réseau</title>
  14.957 +  
  14.958 +      <para id="x_6b">Les commandes que nous avons étudiées dans les sections
  14.959 +        précédentes ne sont pas limitées aux dépôts locaux. Chacune fonctionne 
  14.960 +        de la même manière à travers une connexion réseau, il suffit de lui 
  14.961 +        passer une URL à la place d'un chemin de fichier local.</para>
  14.962 + 
  14.963 +      &interaction.tour.outgoing.net;
  14.964 +  
  14.965 +      <para id="x_6c">Dans cet exemple, nous allons voir quels changements 
  14.966 +        nous pourrions transférer vers le dépôt distant, mais le dépôt n'est, 
  14.967 +        de manière tout à fait compréhensible, pas configuré pour accepter 
  14.968 +        des modifications d'utilisateurs anonymes.</para>
  14.969 + 
  14.970 +      &interaction.tour.push.net; 
  14.971 +    
  14.972 +    </sect2>
  14.973 +
  14.974 +  </sect1>
  14.975 +
  14.976 +  <sect1>
  14.977 +    <title>Commencer un nouveau projet</title>
  14.978 +
  14.979 +    <para id="x_71c">Il est tout aussi aisé de commencer un nouveau projet
  14.980 +      que de travailler sur un qui existe déjà. La commande <command>hg
  14.981 +        init</command> crée un nouveau dépôt Mercurial vide.</para>
  14.982 +
  14.983 +    &interaction.ch01-new.init;
  14.984 +
  14.985 +    <para id="x_71d">Ceci crée simplement un répertoire nommé
  14.986 +      <filename>myproject</filename> dans le répertoire courant.</para>
  14.987 +
  14.988 +    &interaction.ch01-new.ls;
  14.989 +
  14.990 +    <para id="x_71e">Nous pouvons dire que <filename>myproject</filename> est
  14.991 +      un dépôt Mercurial car il contient un répertoire
  14.992 +      <filename>.hg</filename>.</para>
  14.993 +
  14.994 +    &interaction.ch01-new.ls2;
  14.995 +
  14.996 +    <para id="x_71f">Si vous voulons ajouter quelques fichiers préexistants
  14.997 +      dans ce dépôt, il suffit de les recopier dans le répertoire de travail,
  14.998 +      et demander à Mercurial de commencer à les suivre en utilisant la
  14.999 +      commande <command>hg add</command>.</para>
 14.1000 +
 14.1001 +    &interaction.ch01-new.add;
 14.1002 +
 14.1003 +    <para id="x_720">Une fois que nous sommes satisfaits de notre projet,
 14.1004 +      nous pouvons commencer à ajouter nos révisions.</para>
 14.1005 +
 14.1006 +    &interaction.ch01-new.commit;
 14.1007 +
 14.1008 +    <para id="x_721">Il ne prend que quelques instants pour commencer à
 14.1009 +      utiliser Mercurial sur un nouveau projet, ce qui fait aussi de ses
 14.1010 +      points forts. Travailler avec une gestion de révision devient très
 14.1011 +      facile, nous pouvons même l'utiliser pour les plus petits projets où
 14.1012 +      nous aurions probablement jamais pensé utiliser un outil aussi
 14.1013 +      complexe.</para>
 14.1014 +  </sect1>
 14.1015 +</chapter>
 14.1016 +
 14.1017 +<!--
 14.1018 +local variables: 
 14.1019 +sgml-parent-document: ("00book.xml" "book" "chapter")
 14.1020 +end:
 14.1021 +-->
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/fr/ch03-tour-merge.xml	Sat Jul 10 06:24:49 2010 +0100
    15.3 @@ -0,0 +1,460 @@
    15.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
    15.5 +
    15.6 +<chapter id="chap:tour-merge">
    15.7 +  <?dbhtml filename="a-tour-of-mercurial-merging-work.html"?>
    15.8 +  <title>Un tour rapide de Mercurial : fusionner les travaux</title>
    15.9 +  
   15.10 +  <para id="x_338">Nous avons maintenant étudié comment cloner un dépôt, effectuer
   15.11 +    des changements dedans, et récupérer ou transférer depuis un
   15.12 +    autre dépôt. La prochaine étape est donc de <emphasis>fusionner</emphasis> les
   15.13 +    modifications de différents dépôts.</para>
   15.14 +
   15.15 +  <sect1>
   15.16 +    <title>Fusionner différents travaux</title>
   15.17 +      <para id="x_339">La fusion est un aspect fondamental lorsqu'on
   15.18 +      travaille avec un gestionnaire de révisions distribué.</para>
   15.19 +
   15.20 +      <itemizedlist>
   15.21 +        <listitem>
   15.22 +          <para id="x_33a">Alice et Bob ont chacun une copie personnelle du dépôt d'un
   15.23 +            projet sur lequel ils collaborent. Alice corrige un bug
   15.24 +            dans son dépôt, et Bob ajoute une nouvelle fonctionnalité dans le
   15.25 +            sien. Ils veulent un dépôt partagé avec à la fois le correctif du
   15.26 +            bug et la nouvelle fonctionnalité.</para>
   15.27 +       </listitem>
   15.28 +       <listitem>
   15.29 +         <para id="x_33b">Je travaille régulièrement sur plusieurs tâches différentes sur
   15.30 +           un seul projet en même temps, chacun isolé dans son propre dépôt.
   15.31 +           Travailler ainsi signifie que je dois régulièrement fusionner une
   15.32 +           partie de mon code avec celui des autres.</para>
   15.33 +       </listitem>
   15.34 +     </itemizedlist>
   15.35 +
   15.36 +     <para id="x_33c">Parce que nous devons fusionner souvent,
   15.37 +       Mercurial rend cette opération facile. Étudions ensemble le déroulement des
   15.38 +       opérations. Nous commencerons encore par faire un clone d'un autre
   15.39 +       dépôt (vous voyez que l'on fait ça tout le temps ?) puis nous ferons 
   15.40 +       quelques modifications dessus.</para>
   15.41 +       
   15.42 +       &interaction.tour.merge.clone;
   15.43 +       
   15.44 +     <para id="x_33d">Nous devrions avoir maintenant deux copies de
   15.45 +       <filename>hello.c</filename> avec des contenus différents. Les
   15.46 +       historiques de ces deux dépôts ont aussi divergés, comme illustré dans
   15.47 +       la figure <xref linkend="fig:tour-merge:sep-repos"/>.</para>
   15.48 +
   15.49 +      &interaction.tour.merge.cat1;
   15.50 +     
   15.51 +     <para id="x_722">Et ici se trouve notre version légèrement différente du
   15.52 +       dépôt.</para>
   15.53 +     
   15.54 +      &interaction.tour.merge.cat2;
   15.55 +     
   15.56 +     <figure id="fig:tour-merge:sep-repos">
   15.57 +       <title>Historique divergeant des dépôts <filename
   15.58 +         class="directory">my-hello</filename> et <filename
   15.59 +         class="directory">my-new-hello</filename>.</title>
   15.60 +       <mediaobject>
   15.61 +         <imageobject><imagedata fileref="figs/tour-merge-sep-repos.png"/></imageobject>
   15.62 +         <textobject><phrase>XXX ajoute un test</phrase></textobject>
   15.63 +       </mediaobject>
   15.64 +     </figure>
   15.65 +
   15.66 +     <para id="x_33f">Nous savons déjà que récupérer les modifications depuis
   15.67 +       notre dépôt <filename class="directory">my-hello</filename> n'aura
   15.68 +       aucun effet sur l'espace de travail.</para>
   15.69 +
   15.70 +      &interaction.tour.merge.pull;
   15.71 +
   15.72 +     <para id="x_340">Néanmoins, la commande <command role="hg-cmd">hg
   15.73 +       pull</command> nous indique quelque chose au sujet des 
   15.74 +       <quote>heads</quote>.</para>
   15.75 +
   15.76 +     <sect2>
   15.77 +         <title>Les révisions <quote>heads</quote></title>
   15.78 +
   15.79 +       <para id="x_341">Rappelez vous que Mercurial enregistre quelle révision
   15.80 +         est le parent de chaque révision. Si une révision a un parent, nous
   15.81 +         l'appelons un enfant <quote>child</quote> ou un descendant de ce parent. Une
   15.82 +         <quote>head</quote> est une révision qui n'a donc pas d'enfant. La révision <quote>tip</quote>
   15.83 +         est donc une <quote>head</quote>, car c'est la révision la plus récente du dépôt
   15.84 +         qui n'a pas d'enfant. Il y a des moments où un dépôt peut contenir
   15.85 +         plusieurs <quote>heads</quote>.</para>
   15.86 +
   15.87 +       <figure id="fig:tour-merge:pull">
   15.88 +           <title>Contenu du dépôt après une récupération (pull) depuis le
   15.89 +           dépôt <filename
   15.90 +           class="directory">my-hello</filename> vers le dépôt <filename
   15.91 +           class="directory">my-new-hello</filename></title>
   15.92 +         <mediaobject>
   15.93 +           <imageobject>
   15.94 +             <imagedata fileref="tour-merge-pull"/>
   15.95 +           </imageobject>
   15.96 +           <textobject><phrase>XXX ajoute un texte</phrase></textobject>
   15.97 +         </mediaobject>
   15.98 +       </figure>
   15.99 +
  15.100 +       <para id="x_343">Dans la figure <xref linkend="fig:tour-merge:pull"/>,
  15.101 +           vous pouvez constater l'effet d'un <quote>pull</quote> depuis le dépôt
  15.102 +         <filename class="directory">my-hello</filename> dans le dépôt
  15.103 +         <filename class="directory">my-new-hello</filename>. L'historique qui
  15.104 +         était déjà présent dans le dépôt <filename
  15.105 +         class="directory">my-new-hello</filename> reste intact, mais une
  15.106 +         nouvelle révision a été ajoutée. En vous reportant à la figure <xref
  15.107 +         linkend="fig:tour-merge:sep-repos"/>, vous pouvez voir que l'
  15.108 +     <emphasis>ID de révision <quote>changeset ID</quote></emphasis> reste le même dans
  15.109 +         le nouveau dépôt, mais que le <emphasis>numéro de
  15.110 +         révision</emphasis> reste le même. (Ceci est un parfait exemple de
  15.111 +         pourquoi il n'est fiable d'utiliser les numéros de révision lorsque
  15.112 +         l'on discute d'un <quote>changeset</quote>.) Vous pouvez voir les <quote>heads</quote>
  15.113 +         présentes dans le dépôt en utilisant la commande <command
  15.114 +         role="hg-cmd">hg heads</command>.</para>
  15.115 +
  15.116 +        &interaction.tour.merge.heads;
  15.117 +      </sect2>
  15.118 +
  15.119 +      <sect2>
  15.120 +        <title>Effectuer la fusion</title>
  15.121 +
  15.122 +        <para id="x_344">Que se passe-t-il quand vous essayez d'utiliser la
  15.123 +          commande <command role="hg-cmd">hg update</command> pour mettre à
  15.124 +          jour votre espace de travail au nouveau <quote>tip</quote> ?</para>
  15.125 +         
  15.126 +         &interaction.tour.merge.update;
  15.127 +
  15.128 +         
  15.129 +        <para id="x_345">Mercurial nous prévient que la commande <command
  15.130 +          role="hg-cmd">hg update</command> n'effectuera pas
  15.131 +          la fusion, il ne veut pas mettre à jour l'espace de travail quand il
  15.132 +          estime que nous pourrions avoir besoin d'une fusion, à moins de lui
  15.133 +          forcer la main. À la place, il faut utiliser la commande <command
  15.134 +          role="hg-cmd">hg merge</command> pour fusionner les deux
  15.135 +          <quote>heads</quote>.
  15.136 +          <!--où se trouve la traduction de
  15.137 +          (Incidentally, forcing the update with <command>hg update
  15.138 +	  -C</command> would revert any uncommitted changes in the
  15.139 +	working directory.)-->
  15.140 +       </para>
  15.141 +
  15.142 +       <para id="x_723">Pour commencer une fusion (merge) entre deux <quote>heads</quote>,
  15.143 +       nous utilisons la commande <command role="hg-cmd">hg merge</command>.</para>
  15.144 +
  15.145 +        &interaction.tour.merge.merge; 
  15.146 +      
  15.147 +       <para id="x_347">Nous résolvons les conflits dans le fichier
  15.148 +         <filename>hello.c</filename>. Ceci met à jour le répertoire de travail
  15.149 +         de sorte qu'il ne contienne les modifications en provenance des
  15.150 +         <emphasis>deux</emphasis> <quote>heads</quote>, ce qui est indiqué par la
  15.151 +         la sortie de la commande <command role="hg-cmd">hg
  15.152 +         parents</command> et le contenu du fichier
  15.153 +         <filename>hello.c</filename>.</para>
  15.154 +
  15.155 +        &interaction.tour.merge.parents;
  15.156 +     </sect2>
  15.157 +
  15.158 +     <sect2>
  15.159 +       <title>Effectuer l'ajout (commit) du résultat de la fusion</title>
  15.160 +
  15.161 +       <para id="x_348">Dès l'instant où vous avez effectué une fusion
  15.162 +         (merge), <command role="hg-cmd">hg parents</command> vous
  15.163 +         affichera deux parents, avant que vous n'exécutiez la commande
  15.164 +         <command role="hg-cmd">hg commit</command> sur le résultat de la
  15.165 +         fusion.</para>
  15.166 +
  15.167 +        &interaction.tour.merge.commit;
  15.168 +
  15.169 +      <para id="x_349">Nous avons maintenant un nouveau tip, remarquez qu'il
  15.170 +        contient <emphasis>à la fois</emphasis> nos anciennes <quote>heads</quote> et leurs
  15.171 +        parents. Ce sont les mêmes révisions que nous avions affichées avec
  15.172 +        la commande <command role="hg-cmd">hg parents</command>.</para>
  15.173 +
  15.174 +       &interaction.tour.merge.tip;
  15.175 +
  15.176 +      <para id="x_34a">Dans la figure <xref linkend="fig:tour-merge:merge"/>,
  15.177 +        vous pouvez voir une représentation de ce qui se passe dans l'espace
  15.178 +        de travail pendant la fusion, et comment ceci affecte le dépôt lors
  15.179 +        du <quote>commit</quote>. Pendant la fusion, l'espace de travail, qui a deux
  15.180 +        révisions (changesets) comme parents, voit ces derniers devenir le parent
  15.181 +        d'une nouvelle révision (changeset).</para>
  15.182 +
  15.183 +      <figure id="fig:tour-merge:merge">
  15.184 +          <title>Répertoire de travail et dépôt pendant une fusion, 
  15.185 +              et le <quote>commit</quote> qui suit</title>
  15.186 +        <mediaobject>
  15.187 +          <imageobject>
  15.188 +            <imagedata fileref="figs/tour-merge-merge.png"/>
  15.189 +          </imageobject>
  15.190 +          <textobject><phrase>XXX ajoute texte</phrase></textobject>
  15.191 +        </mediaobject>
  15.192 +      </figure>
  15.193 +
  15.194 +    </sect2>
  15.195 +  </sect1>
  15.196 +
  15.197 +  <sect1>
  15.198 +    <title>Fusionner les modifications en conflit</title>
  15.199 +
  15.200 +    <para id="x_34b">La plupart des fusions sont assez simples à réaliser, mais 
  15.201 +      parfois vous vous retrouverez à fusionner des fichiers où la modification 
  15.202 +      touche la même portion de code, au sein d'un même fichier. À moins 
  15.203 +      que ces modification ne soient identiques, ceci aboutira à un 
  15.204 +      <emphasis>conflit</emphasis>, et vous devrez décider comment réconcilier 
  15.205 +      les différentes modifications dans un ensemble cohérent.</para>
  15.206 +
  15.207 +    <figure id="fig:tour-merge:conflict">
  15.208 +      <title>Modifications en conflit dans un document</title>
  15.209 +      <mediaobject>
  15.210 +        <imageobject><imagedata fileref="tour-merge-conflict"/></imageobject>
  15.211 +        <textobject><phrase>XXX ajoute texte</phrase></textobject>
  15.212 +      </mediaobject>
  15.213 +    </figure>
  15.214 +
  15.215 +    <para id="x_34d">La figure <xref linkend="fig:tour-merge:conflict"/>
  15.216 +      illustre un cas de modifications conflictuelles dans un document. Nous
  15.217 +      avons commencé avec une version simple de ce fichier, puis nous avons
  15.218 +      ajouté des modifications, pendant que quelqu'un d'autre modifiait le même
  15.219 +      texte. Notre tâche dans la résolution du conflit est de décider à quoi le
  15.220 +      fichier devrait ressembler.</para>
  15.221 +
  15.222 +    <para id="x_34e">Mercurial n'a pas de mécanisme interne pour gérer 
  15.223 +      les conflits. À la place, il exécute un programme externe appelé 
  15.224 +      <command>hgmerge</command>. Il s'agit d'un script shell qui est 
  15.225 +      compris avec Mercurial, vous pouvez le modifier si vous voulez. 
  15.226 +      Ce qu'il fait par défaut est d'essayer de trouver un des différents 
  15.227 +      outils de fusion qui seront probablement installés sur le système. 
  15.228 +      Il commence par les outils totalement automatiques, et s'ils 
  15.229 +      échouent (parce que la résolution du conflit nécessite une
  15.230 +      intervention humaine) ou s'ils sont absents, le script tente
  15.231 +      d'exécuter certains outils graphiques de fusion.</para>
  15.232 +
  15.233 +    <para id="x_34f">Il est aussi possible de demander à Mercurial d'exécuter
  15.234 +      un autre programme ou un autre script en définissant la variable
  15.235 +      d'environnement <envar>HGMERGE</envar> avec le nom
  15.236 +      du programme de votre choix.</para>
  15.237 +
  15.238 +    <sect2>
  15.239 +      <title>Utiliser un outil graphique de fusion</title>
  15.240 +
  15.241 +      <para id="x_350">Mon outil de fusion préféré est
  15.242 +      <command>kdiff3</command>, que j'utilise ici pour illustrer les
  15.243 +        fonctionnalités classiques des outils graphiques de fusion. Vous pouvez
  15.244 +        voir une capture d'écran de l'utilisation de <command>kdiff3</command>
  15.245 +        dans la figure <xref linkend="fig:tour-merge:kdiff3"/>. Cet outil
  15.246 +        effectue une <emphasis>fusion <quote>three-way</quote></emphasis>, car il y a
  15.247 +        trois différentes versions du fichier qui nous intéressent. Le fichier
  15.248 +        découpe la partie supérieure de la fenêtre en trois panneaux :</para>
  15.249 +      <itemizedlist>
  15.250 +        <listitem><para id="x_351">À gauche on trouve la version de
  15.251 +          <emphasis>base</emphasis> du fichier, soit la plus récente version
  15.252 +          des deux versions qu'on souhaite fusionner.</para></listitem>
  15.253 +        <listitem><para id="x_352">Au centre, il y a <quote>notre</quote>
  15.254 +          version du fichier, avec le contenu que nous avons modifié.</para></listitem>
  15.255 +        <listitem><para id="x_353">Sur la droite, on trouve
  15.256 +        <quote>leur</quote> version du fichier, celui qui contient la
  15.257 +        révision que nous souhaitons intégrer.</para>
  15.258 +        </listitem></itemizedlist>
  15.259 +      <para id="x_354">Dans le panneau en dessous, on trouve le
  15.260 +        <emphasis>résultat</emphasis> actuel de notre fusion. Notre tâche
  15.261 +        consiste donc à remplacer tous les textes en rouge,
  15.262 +        qui indiquent des conflits non résolus, avec une fusion manuelle et 
  15.263 +        pertinente de <quote>notre</quote> version et de la <quote>leur</quote>.
  15.264 +      </para>
  15.265 +
  15.266 +      <para id="x_355">Les quatre panneaux sont <emphasis>accrochés ensemble</emphasis>, 
  15.267 +        si nous déroulons les ascenseurs verticalement ou horizontalement dans chacun 
  15.268 +        d'entre eux, les autres sont mis à jour avec la section correspondante dans leurs 
  15.269 +        fichiers respectifs.</para>
  15.270 +
  15.271 +      <figure id="fig:tour-merge:kdiff3">
  15.272 +        <title>Utiliser <command>kdiff3</command> pour fusionner les
  15.273 +          différentes version d'un fichier.</title>
  15.274 +        <mediaobject>
  15.275 +          <imageobject>
  15.276 +            <imagedata width="100%" fileref="figs/kdiff3.png"/></imageobject>
  15.277 +            <textobject>
  15.278 +              <phrase>XXX ajoute texte</phrase>
  15.279 +            </textobject>
  15.280 +          </mediaobject>
  15.281 +       </figure>
  15.282 +
  15.283 +       <para id="x_357">Pour chaque portion de fichier posant problème, nous
  15.284 +         pouvons choisir de résoudre le conflit en utilisant une combinaison de
  15.285 +         touches depuis la version de base, la nôtre, ou la leur. Nous pouvons
  15.286 +         aussi éditer manuellement les fichiers à tout moment, si c'est nécessaire.</para>
  15.287 +
  15.288 +       <para id="x_358">Il y a <emphasis>beaucoup</emphasis> d'outils de
  15.289 +         fusion disponibles, bien trop pour parler de tous ici. Leurs
  15.290 +         disponibilités varient selon les plateformes ainsi que leurs
  15.291 +         avantages et inconvénients. La plupart sont optimisés pour
  15.292 +         la fusion de fichier contenant un texte plat, certains sont spécialisés
  15.293 +         dans un format de fichier précis (généralement XML).</para>
  15.294 +    </sect2>
  15.295 +
  15.296 +    <sect2>
  15.297 +      <title>Un exemple concret</title>
  15.298 +
  15.299 +      <para id="x_359">Dans cet exemple, nous allons reproduire la
  15.300 +        modification de l'historique du fichier de la figure <xref
  15.301 +        linkend="fig:tour-merge:conflict"/> ci-dessus. Commençons par créer
  15.302 +        un dépôt avec une version de base de notre document.</para>
  15.303 +
  15.304 +      &interaction.tour-merge-conflict.wife; 
  15.305 +
  15.306 +      <para id="x_35a">Créons un clone de ce dépôt et effectuons une
  15.307 +        modification dans le fichier.</para>
  15.308 +
  15.309 +      &interaction.tour-merge-conflict.cousin;
  15.310 +      
  15.311 +      <para id="x_35b">Et un autre clone, pour simuler que quelqu'un d'autre effectue une
  15.312 +        modification sur le fichier. (Ceci pour suggérer qu'il n'est pas rare
  15.313 +        de devoir effectuer des fusions (merges) avec vos propres travaux quand
  15.314 +        vous isolez les tâches dans des dépôts distincts. En effet, vous
  15.315 +        aurez alors à trouver et résoudre certains conflits).</para>
  15.316 +
  15.317 +      &interaction.tour-merge-conflict.son;
  15.318 +
  15.319 +      <para id="x_35c">Maintenant que ces deux versions différentes du même fichier sont
  15.320 +        créées, nous allons configurer l'environnement de manière appropriée pour
  15.321 +        exécuter notre fusion (merge).</para>
  15.322 +
  15.323 +      &interaction.tour-merge-conflict.pull;
  15.324 +
  15.325 +      <para id="x_35d">Dans cette exemple, je n'utiliserais pas la commande Mercurial
  15.326 +        habituelle <command>hgmerge</command> pour effectuer la
  15.327 +        fusion (merge), car il me faudrait abandonner ce joli petit exemple automatisé
  15.328 +        pour utiliser un outil graphique. À la place, je vais définir la
  15.329 +        variable d'environnement <envar>HGMERGE</envar> pour indiquer à
  15.330 +        Mercurial d'utiliser la commande non-interactive <command>merge</command>.
  15.331 +        Cette dernière est comprise dans de nombreux systèmes <quote>à la Unix</quote>.
  15.332 +        Si vous exécutez cet exemple depuis votre ordinateur, ne vous
  15.333 +        occupez pas de définir <envar>HGMERGE</envar>.
  15.334 +        <!-- où se trouve la traduction de 
  15.335 +        You'll get dropped into a GUI file
  15.336 +	    merge tool instead, which is much preferable.)-->
  15.337 +        </para>
  15.338 +
  15.339 +     &interaction.tour-merge-conflict.merge; 
  15.340 +
  15.341 +
  15.342 +     <para id="x_35f">Parce que <command>merge</command> ne peut pas résoudre
  15.343 +       les modifications conflictuelles, il laisse des <emphasis>marqueurs de
  15.344 +       différences</emphasis> à l'intérieur du fichier qui a des conflits,
  15.345 +       indiquant clairement quelles lignes sont en conflit, et si elles
  15.346 +       viennent de notre fichier ou du fichier externe.
  15.347 +     </para>
  15.348 +
  15.349 +     <para id="x_360">Mercurial peut distinguer, à la manière dont la
  15.350 +       commande <command>merge</command> se termine, qu'elle n'a pas été
  15.351 +       capable d'effectuer la fusion (merge), alors il nous indique que nous
  15.352 +       devons effectuer de nouveau cette opération. Ceci peut être très utile
  15.353 +       si, par exemple, nous exécutons un outil graphique de fusion et que
  15.354 +       nous le quittons sans nous rendre compte qu'il reste des conflits ou 
  15.355 +       simplement par erreur.</para>
  15.356 +
  15.357 +     <para id="x_361">Si la fusion (merge) automatique ou manuelle échoue, 
  15.358 +       il n'y a rien pour nous empêcher de <quote>corriger le tir</quote> en
  15.359 +       modifiant nous-même les fichiers, et enfin effectuer le <quote>commit</quote> du 
  15.360 +       fichier:</para>
  15.361 +
  15.362 +     &interaction.tour-merge-conflict.commit;
  15.363 +
  15.364 +     <note>
  15.365 +       <title>Où est la commande <command>hg resolve</command> ?</title>
  15.366 +       
  15.367 +       <para id="x_724">La commande <command>hg resolve</command> a été
  15.368 +         introduite dans la version 1.1 de Mercurial, qui a été publiée en
  15.369 +         décembre 2008. Si vous utilisez une version plus anciennne de
  15.370 +         Mercurial (exécutez la command <command>hg version</command> pour en
  15.371 +         avoir le cœur net), cette commande ne sera pas disponible. Si votre
  15.372 +         version de Mercurial est plus ancienne que la 1.1, vous devriez très
  15.373 +         fortement considérer une mise à jour vers une version plus récente avant
  15.374 +         d'essayer de régler des fusions complexes.</para>
  15.375 +       </note>
  15.376 +     </sect2>
  15.377 +   </sect1>
  15.378 +
  15.379 +   <sect1 id="sec:tour-merge:fetch">
  15.380 +       <title>Simplification de la séquence <quote>pull-merge-commit</quote></title>
  15.381 +
  15.382 +     <para id="x_362">La procédure pour effectuer la fusion indiquée
  15.383 +       ci-dessus est simple, mais requiert le lancement de trois commandes à la
  15.384 +       suite.</para>
  15.385 +
  15.386 +     <programlisting>hg pull -u
  15.387 +hg merge
  15.388 +hg commit -m 'Merged remote changes'</programlisting>
  15.389 +
  15.390 +     <para id="x_363">Lors du <quote>commit</quote> final, vous devez également saisir un
  15.391 +       message, qui aura vraisemblablement assez peu d'intérêt.</para>
  15.392 +
  15.393 +     <para id="x_364">Il serait assez sympathique de pouvoir réduire le
  15.394 +       nombre d'opérations nécessaire, si possible. De fait Mercurial est
  15.395 +       fournit avec une extension appelée <literal role="hg-ext">fetch</literal>
  15.396 +       qui fait justement cela.</para>
  15.397 +
  15.398 +     <para id="x_365">Mercurial fournit un mécanisme d'extension flexible qui permet à chacun
  15.399 +       d'étendre ces fonctionnalités, tout en conservant le cœur de Mercurial
  15.400 +       léger et facile à utiliser. Certaines extensions ajoutent de nouvelles
  15.401 +       commandes que vous pouvez utiliser en ligne de commande, alors que
  15.402 +       d'autres travaillent <quote>en coulisse</quote>, par exemple en ajoutant des
  15.403 +       possibilités au serveur.</para>
  15.404 +
  15.405 +     <para id="x_366">L'extension <literal role="hg-ext">fetch</literal>
  15.406 +       ajoute une nouvelle commande nommée, sans surprise, <command
  15.407 +       role="hg-cmd">hg fetch</command>. Cette extension consiste en une
  15.408 +       combinaison de <command role="hg-cmd">hg pull</command>, <command
  15.409 +       role="hg-cmd">hg update</command> et <command role="hg-cmd">hg
  15.410 +       merge</command>. Elle commence par récupérer les modifications d'un
  15.411 +       autre dépôt dans le dépôt courant. Si elle trouve que les
  15.412 +       modifications ajoutent une nouvelle <quote>head</quote>, elle effectue un <quote>merge</quote>,
  15.413 +       et ensuite <quote>commit</quote> le résultat du <quote>merge</quote> avec un message généré
  15.414 +       automatiquement. Si aucune <quote>head</quote> n'a été ajouté, elle met à jour le
  15.415 +       répertoire de travail au niveau de la nouvelle révision <quote>tip</quote>.</para>
  15.416 +     
  15.417 +     <para id="x_367">Activer l'extension <literal
  15.418 +       role="hg-ext">fetch</literal> est facile. Modifiez votre fichier <filename
  15.419 +       role="special">.hgrc</filename>, et soit allez à la section <literal
  15.420 +       role="rc-extensions">extensions</literal> soit créez une section
  15.421 +       <literal role="rc-extensions">extensions</literal>. Ensuite ajoutez
  15.422 +       une ligne qui consiste simplement en <quote>fetch =</quote>.</para>
  15.423 +
  15.424 +     <programlisting>[extensions]
  15.425 +fetch =</programlisting>
  15.426 +
  15.427 +    <para id="x_368">(Normalement, sur la partie droite de
  15.428 +      <quote><literal>=</literal></quote> devrait apparaître le chemin de
  15.429 +      l'extension, mais étant donné que l'extension <literal
  15.430 +      role="hg-ext">fetch</literal> fait partie de la distribution standard,
  15.431 +      Mercurial sait où la trouver.) </para>
  15.432 +
  15.433 +  </sect1>
  15.434 +  
  15.435 +  <sect1>
  15.436 +    <title>Renommer, copier, et fusionner (merge)</title>
  15.437 +
  15.438 +    <para id="x_729">En cours de la vie d'un projet, nous allons souvent 
  15.439 +      vouloir changer la disposition de ses fichiers et de ses répertoires. 
  15.440 +      Ceci peut être aussi simple que de changer le nom d'un seul fichier, 
  15.441 +      et aussi compliqué que de restructurer une hiérarchie entière de fichiers
  15.442 +      au sein du projet.</para>
  15.443 +
  15.444 +    <para id="x_72a">Mercurial permet de faire ce genre de modification de
  15.445 +      manière fluide, à condition de l'informer de ce que nous faisons. Si 
  15.446 +      vous voulez renommer un ficher, vous devriez utiliser la commande
  15.447 +      <command>hg rename</command><footnote>
  15.448 +        <para id="x_72b">Si vous êtes un utilisateur d'Unix, vous serez content
  15.449 +          de savoir que la commande  <command>hg rename</command>
  15.450 +          peut être abrégée en <command>hg mv</command>.</para>
  15.451 +      </footnote> pour changer son nom, ainsi Mercurial peut ensuite prendre
  15.452 +      la bonne décision, plus tard, en cas de fusion (merge).</para>
  15.453 +
  15.454 +    <para id="x_72c">Nous étudierons, en détail, l'utilisation de ces commandes 
  15.455 +     dans le chapitre <xref linkend="chap:daily.copy"/>.</para>
  15.456 +  </sect1>
  15.457 +</chapter>
  15.458 +
  15.459 +<!--
  15.460 +local variables: 
  15.461 +sgml-parent-document: ("00book.xml" "book" "chapter")
  15.462 +end:
  15.463 +-->
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/fr/ch04-concepts.xml	Sat Jul 10 06:24:49 2010 +0100
    16.3 @@ -0,0 +1,776 @@
    16.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
    16.5 +
    16.6 +<chapter id="chap:concepts">
    16.7 +  <?dbhtml filename="behind-the-scenes.html"?>
    16.8 +  <title>Derrière le décor</title>
    16.9 +  
   16.10 +  <para id="x_2e8">À la différence de beaucoup d'outils de gestion de révisions,
   16.11 +    les concepts sur lesquels se base Mercurial sont assez simples pour
   16.12 +    qu'il soit facile de comprendre comment le logiciel fonctionne.
   16.13 +    Bien que leur connaissance ne soit pas indispensable, je trouve utile
   16.14 +    d'avoir un <quote>modèle mental</quote> de ce qui se passe.</para>
   16.15 +
   16.16 +  <para id="x_2e9">En effet, cette compréhension m'apporte la confiance que
   16.17 +    Mercurial a été développé avec soin pour être à la fois
   16.18 +    <emphasis>sûr</emphasis> et <emphasis>efficace</emphasis>. De surcroît,
   16.19 +    s'il m'est facile de garder en tête ce que le logiciel fait lorsque
   16.20 +    j'accomplis des tâches de révision, j'aurai moins de risques d'être
   16.21 +    surpris par son comportement.</para>
   16.22 +
   16.23 +  <para id="x_2ea">Dans ce chapitre, nous décrirons tout d'abord les concepts
   16.24 +    essentiels de l'architecture de Mercurial, pour ensuite discuter quelques
   16.25 +    détails intéressants de son implémentation.</para>
   16.26 +
   16.27 +  <sect1>
   16.28 +    <title>Conservation de l'historique sous Mercurial</title>
   16.29 +    <sect2>
   16.30 +      <title>Suivi de l'historique pour un seul fichier</title>
   16.31 +      
   16.32 +      <para id="x_2eb">Lorsque Mercurial effectue un suivi des modifications
   16.33 +        faites à un fichier, il conserve l'historique pour ce fichier dans un
   16.34 +        <emphasis>filelog</emphasis> sous forme de métadonnées. Chaque entrée
   16.35 +        dans le <quote>filelog</quote> contient assez d'informations pour reconstituer une
   16.36 +        révision du fichier correspondant. Les <quote>filelogs</quote> sont des fichiers
   16.37 +        stockés dans le répertoire  <filename role="special"
   16.38 +            class="directory">.hg/store/data</filename>. Un <quote>filelog</quote> contient
   16.39 +        des informations de deux types : les données de révision, et un index
   16.40 +        pour permettre à Mercurial une recherche efficace d'une révision
   16.41 +        donnée.</para>
   16.42 +
   16.43 +      <para id="x_2ec">Lorsqu'un fichier devient trop gros ou a un long
   16.44 +          historique, son <quote>filelog</quote> se voit stocké dans un fichier de données
   16.45 +        (avec un suffixe <quote><literal>.d</literal></quote>) et un fichier
   16.46 +        index (avec un suffixe<quote><literal>.i</literal></quote>)
   16.47 +        distincts. La relation entre un fichier dans le répertoire de travail
   16.48 +        et le <quote>filelog</quote> couvrant le suivi de son historique dans le dépôt est
   16.49 +        illustré à la figure <xref linkend="fig:concepts:filelog"/>.</para>
   16.50 +
   16.51 +      <figure id="fig:concepts:filelog">
   16.52 +        <title>Relations entre les fichiers dans le répertoire de travail et
   16.53 +            leurs <quote>filelogs</quote> dans le dépôt</title> 
   16.54 +        <mediaobject> <imageobject><imagedata
   16.55 +              fileref="figs/filelog.png"/></imageobject>
   16.56 +          <textobject><phrase>XXX add text</phrase></textobject>
   16.57 +        </mediaobject> </figure>
   16.58 +
   16.59 +    </sect2>
   16.60 +    <sect2>
   16.61 +      <title>Gestion des fichiers suivis</title>
   16.62 +      
   16.63 +      <para id="x_2ee">Mercurial a recours à une structure nommée
   16.64 +        <emphasis>manifest</emphasis> pour rassembler les informations sur
   16.65 +        les fichiers dont il gère le suivi. Chaque entrée dans ce <quote>manifest</quote>
   16.66 +        contient des informations sur les fichiers présents dans une révision
   16.67 +        donnée. Une entrée enregistre la liste des fichiers faisant partie de la
   16.68 +        révision, la version de chaque fichier, et quelques autres
   16.69 +        métadonnées sur ces fichiers.</para>
   16.70 +
   16.71 +    </sect2>
   16.72 +    <sect2>
   16.73 +        <title>Enregistrer les informations des <quote>changesets</quote></title>
   16.74 +
   16.75 +      <para id="x_2ef">Le <emphasis>changelog</emphasis> contient les
   16.76 +          informations sur chaque <quote>changeset</quote>. Chaque révision enregistre qui a
   16.77 +          <quote>committé</quote> un changement, le commentaire du <quote>changeset</quote>, d'autres
   16.78 +          morceaux d'information relatives au <quote>changeset</quote> et la révision du
   16.79 +          <quote>manifest</quote> à utiliser.</para>
   16.80 +
   16.81 +    </sect2>
   16.82 +    <sect2>
   16.83 +      <title>Relations entre les révisions</title>
   16.84 +
   16.85 +      <para id="x_2f0">À l'intérieur d'un <quote>changelog</quote>, d'un <quote>manifest</quote>, ou d'un
   16.86 +          <quote>filelog</quote>, chaque révision enregistre un pointeur vers son parent
   16.87 +        immédiat (ou à ses deux parents s'il s'agit d'une révision
   16.88 +        correspondant à une fusion (merge)). Comme mentionné plus haut, il y
   16.89 +        a aussi des relations entre les révisions <emphasis>à
   16.90 +          travers</emphasis> ces structures, qui sont de nature
   16.91 +        hiérarchique.</para>
   16.92 +
   16.93 +    <para id="x_2f1">Pour chaque <quote>changeset</quote> dans un dépôt, il y a exactement
   16.94 +        une révision stockée dans le <quote>changelog</quote>. Chaque révision du <quote>changelog</quote>
   16.95 +        contient un pointeur vers une unique révision du <quote>manifest</quote>. Une
   16.96 +        révision du <quote>manifest</quote> garde un pointeur vers une unique révision pour
   16.97 +        chaque <quote>filelog</quote> suivi lorsque le <quote>changeset</quote> est créé. Ces relations
   16.98 +        sont illustrées dans <xref linkend="fig:concepts:metadata"/>.</para>
   16.99 +
  16.100 +      <figure id="fig:concepts:metadata">
  16.101 +        <title>Metadata relationships</title>
  16.102 +        <mediaobject> <imageobject><imagedata
  16.103 +              fileref="figs/metadata.png"/></imageobject>
  16.104 +          <textobject><phrase>XXX add text</phrase></textobject> 
  16.105 +        </mediaobject>
  16.106 +      </figure>
  16.107 +
  16.108 +      <para id="x_2f3">Comme l'illustration le montre, il
  16.109 +        <emphasis>n'</emphasis>y a <emphasis>pas</emphasis> de relation
  16.110 +        <quote>un à un</quote> entre les révisions dans un <quote>changelog</quote>,
  16.111 +        <quote>manifest</quote> ou <quote>filelog</quote>. Si un fichier que Mercurial suit n'a pas changé
  16.112 +        entre deux <quote>changesets</quote>, l'entrée pour ce fichier dans les deux
  16.113 +        révisions du <quote>manifest</quote> pointera vers la même révision de son <quote>filelog</quote>
  16.114 +        <footnote> <para id="x_725">Il est possible (bien qu'inhabituel)
  16.115 +                qu'un <quote>manifest</quote> reste le même entre deux <quote>changesets</quote>, auquel cas
  16.116 +                l'entrée du <quote>changelog</quote> pour ces <quote>changesets</quote> pointera vers la même
  16.117 +                révision du <quote>manifest</quote>.</para>
  16.118 +        </footnote>.</para>
  16.119 +
  16.120 +    </sect2>
  16.121 +  </sect1>
  16.122 +  <sect1>
  16.123 +    <title>Stockage sûr et efficace</title>
  16.124 +
  16.125 +    <para id="x_2f4">Les fondements des <quote>changelogs</quote>, des <quote>manifests</quote> et des
  16.126 +        <quote>filelogs</quote> sont fournis par une unique structure appelée le
  16.127 +      <emphasis>revlog</emphasis>.</para>
  16.128 +
  16.129 +    <sect2>
  16.130 +      <title>Stockage efficace</title>
  16.131 +
  16.132 +      <para id="x_2f5">Le <quote>revlog</quote> fournit un stockage efficace des révisions en
  16.133 +        utilisant un mécanisme <emphasis>delta</emphasis>. Au lieu de stocker
  16.134 +        une copie complète d'un fichier à chaque révision, il stocke les
  16.135 +        changements requis pour transformer une révision plus ancienne en une
  16.136 +        nouvelle révision. Pour plusieurs types de données, ces deltas sont
  16.137 +        typiquement une fraction de pourcentage de la taille de la copie
  16.138 +        complète d'un fichier.</para>
  16.139 +
  16.140 +      <para id="x_2f6">Certains systèmes de gestion de révisions obsolètes
  16.141 +        peuvent seulement travailler avec les deltas de fichiers texte. Il
  16.142 +        doivent d'ailleurs stocker les fichiers binaires comme des images
  16.143 +        complètes ou encodées avec une représentation texte, chacune de ces
  16.144 +        approches étant gaspilleuse. Mercurial peut traiter les deltas de
  16.145 +        fichiers avec du contenu binaire arbitraire ; il n'a pas besoin de
  16.146 +        traiter spécialement du texte.</para>
  16.147 +
  16.148 +    </sect2>
  16.149 +    <sect2 id="sec:concepts:txn">
  16.150 +      <title>Opérations sûres</title>
  16.151 +
  16.152 +      <para id="x_2f7">Mercurial <emphasis>empile</emphasis> toujours les
  16.153 +          données à la fin d'un fichier <quote>revlog</quote>. Il ne modifie jamais la section
  16.154 +        d'un fichier après qu'il l'ait écrite. C'est à la fois plus robuste
  16.155 +        et efficace que les schémas qui ont besoin de modifier ou réécrire
  16.156 +        les données.</para>
  16.157 +
  16.158 +      <para id="x_2f8">De plus, Mercurial traite chaque écriture comme la
  16.159 +        partie d'une <emphasis>transaction</emphasis> qui peut comprendre
  16.160 +        plusieurs fichiers. Une transaction est <emphasis>atomique</emphasis>
  16.161 +        : soit la transaction entière réussit et ses effets sont tous
  16.162 +        visibles aux lecteurs en une étape, soit la totalité est annulée.
  16.163 +        Cette garantie de l'atomicité signifie que si vous exécutez deux
  16.164 +        copies de Mercurial, où une lit les données et l'autre les écrit, le
  16.165 +        lecteur ne verra jamais un résultat partiellement écrit qui pourrait
  16.166 +        le perturber.</para>
  16.167 +
  16.168 +      <para id="x_2f9">Le fait que Mercurial ne fasse qu'ajouter aux fichiers
  16.169 +        fait qu'il est facile de fournir cette garantie de transaction. Plus
  16.170 +        les choses sont faites simplement comme ça, plus vous pouvez être
  16.171 +        rassurés qu'elles sont bien faites.</para>
  16.172 +    
  16.173 +    </sect2>
  16.174 +    <sect2>
  16.175 +      <title>Récupération rapide</title>
  16.176 +
  16.177 +      <para id="x_2fa">Mercurial évite habillement un piège commun à tous les
  16.178 +        vieux systèmes de gestion de révisions : le problème de la
  16.179 +        <emphasis>récupération inefficace</emphasis>. La plupart des systèmes
  16.180 +        de gestion de révisions stockent le contenu d'une révision comme une
  16.181 +        série incrémentale de modifications faites à un
  16.182 +        <quote>snapshot</quote>. (Certains basent le <quote>snapshot</quote> sur la plus
  16.183 +        vieille révision, d'autres sur la plus récente.) Pour reconstruire
  16.184 +        une révision spécifique, vous devez d'abord lire le <quote>snapshot</quote>, et
  16.185 +        ensuite toutes les révisions entre le <quote>snapshot</quote> et votre révision
  16.186 +        cible. Plus vous avez d'historique accumulé dans un fichier, plus de
  16.187 +        révisions vous avez à lire, d'où la longueur que cela prend à
  16.188 +        reconstruire une révision particulière.</para>
  16.189 +
  16.190 +      <figure id="fig:concepts:snapshot">
  16.191 +          <title><quote>Snapshot</quote> d'un <quote>revlog</quote>, avec des deltas incrémentaux</title>
  16.192 +        <mediaobject> <imageobject><imagedata
  16.193 +              fileref="figs/snapshot.png"/></imageobject>
  16.194 +          <textobject><phrase>XXX add text</phrase></textobject>
  16.195 +        </mediaobject>
  16.196 +      </figure>
  16.197 +
  16.198 +      <para id="x_2fc">L'innovation que Mercurial apporte à ce problème est
  16.199 +        simple mais efficace. Une fois que la quantité cumulée de deltas
  16.200 +        d'informations stockées depuis le dernier snapshot excède un seuil
  16.201 +        fixé, il stocke un nouveau <quote>snapshot</quote> (compressé bien sûr), plutôt qu'un
  16.202 +        nouveau delta. Ceci rend possible la reconstruction de
  16.203 +        <emphasis>toute</emphasis> révision d'un fichier rapidement. Cette
  16.204 +        approche fonctionne si bien que depuis, elle a été copiée par
  16.205 +        plusieurs autres systèmes de gestion de révisions.</para>
  16.206 +
  16.207 +      <para id="x_2fd"><xref linkend="fig:concepts:snapshot"/> illustre
  16.208 +          l'idée. Dans une entrée d'un fichier d'index de <quote>revlog</quote>, Mercurial
  16.209 +        stocke l'intervalle des entrées depuis le fichier de données qu'il doit
  16.210 +        lire pour reconstruire une révision particulière.</para>
  16.211 +
  16.212 +      <sect3>
  16.213 +        <title>Aparté : l'influence de la compression vidéo</title>
  16.214 +      
  16.215 +        <para id="x_2fe">Si vous êtes familiés de la compression vidéo ou
  16.216 +          avez déjà regardé un programme TV par câble ou par un service
  16.217 +          satellite, vous devez savoir que la plupart des schémas de
  16.218 +          compression vidéo stockent chaque trame de vidéo comme un delta
  16.219 +          vis-à-vis de la trame précédente.</para>
  16.220 +      
  16.221 +        <para id="x_2ff">Mercurial emprunte cette idée pour rendre possible
  16.222 +          la reconstruction d'une révision à partir d'un snapshot et d'un
  16.223 +          petit nombre de deltas.</para>
  16.224 +
  16.225 +      </sect3>
  16.226 +    </sect2>
  16.227 +    <sect2>
  16.228 +      <title>Identification et intégrité forte</title>
  16.229 +
  16.230 +      <para id="x_300">Avec les deltas ou l'information du snapshot, une
  16.231 +        entrée d'un revlog contient un hash cryptographique des données qu'il
  16.232 +        représente. Ceci fait qu'il est difficile de construire les données
  16.233 +        d'une révision, mais facile de détecter une corruption
  16.234 +        accidentelle.</para>
  16.235 +
  16.236 +      <para id="x_301">Les hash fournissent plus qu'un bon moyen de
  16.237 +        vérification contre la corruption ; il sont aussi utilisés comme
  16.238 +        identifiants pour les révisions. Les <quote>hashs</quote> d'identifications d'un
  16.239 +        <quote>changeset</quote> que vous voyez comme utilisateur final proviennent des
  16.240 +        révisions du <quote>changelog</quote>. Bien que les <quote>filelogs</quote> et le <quote>manifest</quote>
  16.241 +        utilisent aussi des <quote>hashs</quote>, Mercurial ne les utilise qu'en
  16.242 +        arrière-plan.</para>
  16.243 +
  16.244 +    <para id="x_302">Mercurial vérifie que les <quote>hashs</quote> sont corrects lorsqu'il
  16.245 +        récupère les révisions de fichiers et lorsqu'il récupère (pull) les
  16.246 +        changements d'un autre dépôt. S'il rencontre un problème d'intégrité,
  16.247 +        il se plaindra et arrêtera tout ce qu'il est en train de faire.</para>
  16.248 +
  16.249 +      <para id="x_303">En plus de l'effet qu'il a sur l'efficacité des
  16.250 +          récupérations, l'utilisation par Mercurial de <quote>snapshots</quote> périodiques
  16.251 +        fait qu'il est plus robuste contre la corruption partielle de
  16.252 +        données. Si un <quote>revlog</quote> devient partiellement corrompu à cause d'une
  16.253 +        erreur matérielle ou d'un bug système, il est souvent possible de
  16.254 +        reconstruire certaines ou la plupart des révisions à partir des
  16.255 +        sections non corrompues du <quote>revlog</quote>, avant et après la section
  16.256 +        corrompue. Ceci ne serait pas possible à partir d'un modèle de
  16.257 +        stockage de deltas seul.</para>
  16.258 +    </sect2>
  16.259 +  </sect1>
  16.260 +
  16.261 +  <sect1>
  16.262 +    <title>Historique des révisions, branches et fusions (merge)</title>
  16.263 +
  16.264 +    <para id="x_304">Chaque entrée dans un <quote>revlog</quote> Mercurial connaît
  16.265 +      l'identité de l'ancêtre immédiat de la révision, habituellement désignée
  16.266 +      comme son <emphasis>parent</emphasis>. En fait, une révision contient
  16.267 +      de la place pour non pas un parent, mais deux. Mercurial utilise un
  16.268 +      <quote>hash</quote> spécial, appelé le <quote>null ID</quote> pour représenter l'idée
  16.269 +      qu'<quote>il n'y a pas de parent ici</quote>. Ce <quote>hash</quote> est simplement
  16.270 +      une chaîne de zéros.</para>
  16.271 +
  16.272 +    <para id="x_305">Dans <xref linkend="fig:concepts:revlog"/>, vous pouvez
  16.273 +        voir un exemple de la structure conceptuelle d'un <quote>revlog</quote>. Les <quote>filelogs</quote>,
  16.274 +        <quote>manifests</quote> et <quote>changelogs</quote> ont tous cette même structure ; ils diffèrent
  16.275 +      simplement dans le type de donnée stockée dans chaque delta ou
  16.276 +      <quote>snapshot</quote>.</para>
  16.277 +
  16.278 +  <para id="x_306">La première révision d'un <quote>revlog</quote> (au bas de l'image) a
  16.279 +      le <quote>null ID</quote> dans chacune de ses cases parent. Pour une révision
  16.280 +      <quote>normale</quote>, sa première case parent contient l'ID de sa
  16.281 +      révision parent et la seconde contient le <quote>null ID</quote>, indiquant que cette
  16.282 +      révision n'a qu'un seul vrai parent. Si deux révisions ont le même
  16.283 +      parent, il s'agit de branches. Une révision qui représente une fusion
  16.284 +      (merge) entre deux branches a deux identifiants de révision normaux
  16.285 +      dans ses cases parents.</para>
  16.286 +
  16.287 +    <figure id="fig:concepts:revlog">
  16.288 +        <title>Le concept de la structure d'un <quote>revlog</quote></title>
  16.289 +      <mediaobject> <imageobject><imagedata
  16.290 +            fileref="figs/revlog.png"/></imageobject> <textobject><phrase>XXX
  16.291 +            add text</phrase></textobject>
  16.292 +      </mediaobject>
  16.293 +    </figure>
  16.294 +
  16.295 +  </sect1>
  16.296 +  <sect1>
  16.297 +    <title>Le répertoire de travail</title>
  16.298 +
  16.299 +    <para id="x_307">Dans un répertoire de travail, Mercurial stocke une image
  16.300 +        des fichiers du dépôt à un <quote>changeset</quote> particulier.</para>
  16.301 +
  16.302 +    <para id="x_308">Le répertoire de travail <quote>sait</quote> quel
  16.303 +        <quote>changeset</quote> il contient. Lorsque vous mettez à jour (update) le
  16.304 +        répertoire de travail à un certain <quote>changeset</quote>, Mercurial regarde la
  16.305 +        révision appropriée du <quote>manifest</quote> pour trouver quels fichiers il suivait
  16.306 +        au moment où le <quote>changeset</quote> a été <quote>committé</quote>, et quelle révision de chaque
  16.307 +      fichier était alors courante. Il recrée ensuite une copie de chacun de
  16.308 +      ces fichiers, avec le même contenu qu'ils avaient lorsque le <quote>changeset</quote>
  16.309 +      a été <quote>committé</quote>.</para>
  16.310 +
  16.311 +    <para id="x_309">La structure spéciale <emphasis>dirstate</emphasis>
  16.312 +      contient la connaissance de Mercurial sur le répertoire de travail.
  16.313 +      Elle est maintenue par un fichier appelé
  16.314 +      <filename>.hg/dirstate</filename> dans un dépôt. Les détails du
  16.315 +      dirstate sont le <quote>changeset</quote> vers lequel le répertoire de travail se met
  16.316 +      à jour (update), et tous les fichiers que Mercurial suit dans le
  16.317 +      répertoire de travail. Il permet aussi à Mercurial de connaître
  16.318 +      rapidement les fichiers modifiés, en enregistrant l'heure de
  16.319 +      dernière modification et la taille de chacun.</para>
  16.320 +
  16.321 +  <para id="x_30a">Puisqu'une révision de <quote>revlog</quote> a des emplacements pour
  16.322 +      deux parents et peut représenter aussi bien une révision normale (avec
  16.323 +      un parent) ou une fusion de deux révisions anciennes, le <quote>dirstate</quote> a des
  16.324 +      emplacements pour deux parents. Lorsque vous utilisez la commande
  16.325 +      <command role="hg-cmd">hg update</command>, le <quote>changeset</quote> que vous
  16.326 +      mettez à jour est stocké dans l'emplacement du <quote>premier
  16.327 +          parent</quote>, et le <quote>null ID</quote> l'est dans le second. Lorsque vous
  16.328 +      utilisez la commande <command role="hg-cmd">hg merge</command> avec un
  16.329 +      autre changeset, le premier parent reste inchangé, et le second est
  16.330 +      rempli avec le <quote>changeset</quote> à partir duquel vous êtes en train de
  16.331 +      fusionner. La commande <command role="hg-cmd">hg parents</command> vous
  16.332 +      donne les parents du dirstate.</para>
  16.333 +
  16.334 +    <sect2>
  16.335 +        <title>Que se passe-t-il lorsque vous <quote>committez</quote></title>
  16.336 +
  16.337 +        <para id="x_30b">Le <quote>dirstate</quote> stocke les informations sur les parents
  16.338 +        pour plus qu'une simple comptabilité. Mercurial utilise les
  16.339 +        parents du <quote>dirstate</quote> comme <emphasis>les parents d'un nouveau
  16.340 +            <quote>changeset</quote></emphasis> lorsque vous <quote>committez</quote>.</para>
  16.341 +
  16.342 +      <figure id="fig:concepts:wdir"> 
  16.343 +        <title>Le répertoire de travail peut avoir deux parents</title>
  16.344 +        <mediaobject>
  16.345 +          <imageobject><imagedata fileref="figs/wdir.png"/></imageobject>
  16.346 +          <textobject><phrase>XXX add text</phrase></textobject></mediaobject>
  16.347 +      </figure>
  16.348 +
  16.349 +      <para id="x_30d"><xref linkend="fig:concepts:wdir"/> montre l'état
  16.350 +          normal d'un répertoire de travail, où il n'y a qu'un seul <quote>changeset</quote>
  16.351 +          comme parent. Ce <quote>changeset</quote> est le <emphasis>tip</emphasis>, le
  16.352 +          <quote>changeset</quote> le plus récent dans le dépôt n'a pas d'enfant.</para>
  16.353 +
  16.354 +      <figure id="fig:concepts:wdir-after-commit">
  16.355 +        <title>Le répertoire de travail gagne de nouveaux parents après un
  16.356 +            <quote>commit</quote></title>
  16.357 +        <mediaobject>
  16.358 +          <imageobject><imagedata
  16.359 +              fileref="figs/wdir-after-commit.png"/></imageobject>
  16.360 +          <textobject><phrase>XXX add text</phrase></textobject>
  16.361 +        </mediaobject>
  16.362 +      </figure>
  16.363 +
  16.364 +      <para id="x_30f">On peut se représenter le répertoire de travail comme
  16.365 +        <quote>le changeset que je vais committer</quote>. Chaque fichier
  16.366 +        que vous demandez à Mercurial d'ajouter, de supprimer, de renommer ou de
  16.367 +        copier va être intégré dans ce changeset, tout comme les
  16.368 +        modifications de n'importe quel fichier que Mercurial est déjà en
  16.369 +        train de suivre ; le nouveau <quote>changeset</quote> aura les mêmes parents que le
  16.370 +        répertoire de travail.</para>
  16.371 +
  16.372 +      <para id="x_310">Après un commit, Mercurial va mettre à jour les
  16.373 +        parents du répertoire de travail, ainsi, le premier parent est l'ID
  16.374 +        du nouveau <quote>changeset</quote>, et le second, le <quote>null ID</quote>. Ceci est illustré dans
  16.375 +        <xref linkend="fig:concepts:wdir-after-commit"/>. Mercurial ne touche
  16.376 +        à aucun des fichiers du répertoire de travail lorsque vous <quote>committez</quote>
  16.377 +        ; il modifie simplement le dirstate pour noter ses nouveaux
  16.378 +        parents.</para>
  16.379 +
  16.380 +    </sect2>
  16.381 +    <sect2>
  16.382 +      <title>Création d'une nouvelle <quote>head</quote></title>
  16.383 +
  16.384 +      <para id="x_311">Il est parfaitement normal de faire un <quote>update</quote> du
  16.385 +          répertoire de travail à un <quote>changeset</quote> autre que le <quote>tip</quote> courant. Par
  16.386 +        exemple, vous pourriez vouloir savoir à quoi votre projet
  16.387 +        ressemblait mardi dernier, ou regarder le <quote>changeset</quote> qui a
  16.388 +        introduit un bug. Dans des cas comme ça, la chose naturelle à faire
  16.389 +        est de faire un <quote>update</quote> du répertoire de travail au <quote>changeset</quote> qui vous
  16.390 +        intéresse, et ensuite d'en examiner les fichiers pour regarder leurs
  16.391 +        contenus comme ils l'étaient lorsque vous avez <quote>committé</quote> ce <quote>changeset</quote>.
  16.392 +        L'effet de ceci est montré dans <xref
  16.393 +          linkend="fig:concepts:wdir-pre-branch"/>.</para>
  16.394 +
  16.395 +      <figure id="fig:concepts:wdir-pre-branch">
  16.396 +          <title>Le répertoire de travail, <quote>updaté</quote> pour un <quote>changeset</quote> plus
  16.397 +        ancien</title>
  16.398 +        <mediaobject> <imageobject><imagedata
  16.399 +              fileref="figs/wdir-pre-branch.png"/></imageobject>
  16.400 +          <textobject><phrase>XXX add text</phrase></textobject>
  16.401 +        </mediaobject>
  16.402 +      </figure>
  16.403 +
  16.404 +      <para id="x_313">En ayant fait un <quote>update</quote> du répertoire de travail vers
  16.405 +          un <quote>changeset</quote> plus ancien, que se passe-t-il si vous faites des
  16.406 +          changements et ensuite <quote>committez</quote> ? Mercurial se comporte comme je
  16.407 +        l'ai fait remarqué plus haut. Les parents du répertoire de travail
  16.408 +        deviennent les parents du nouveau <quote>changeset</quote>. Ce nouveau <quote>changeset</quote> n'a
  16.409 +        pas d'enfant, donc il devient le nouveau <quote>tip</quote>. Le dépôt contient
  16.410 +        maintenant deux <quote>changesets</quote> qui n'ont pas d'enfant ; on appelle ceci
  16.411 +        des <emphasis>heads</emphasis>. Vous pouvez voir la structure que
  16.412 +        cela crée dans <xref linkend="fig:concepts:wdir-branch"/>.</para>
  16.413 +
  16.414 +      <figure id="fig:concepts:wdir-branch">
  16.415 +          <title>Après un <quote>commit</quote> fait pendant la synchronisation avec un ancien
  16.416 +              <quote>changeset</quote></title>
  16.417 +        <mediaobject> <imageobject><imagedata
  16.418 +              fileref="figs/wdir-branch.png"/></imageobject>
  16.419 +          <textobject><phrase>XXX add text</phrase></textobject>
  16.420 +        </mediaobject>
  16.421 +      </figure>
  16.422 +
  16.423 +      <note>
  16.424 +        <para id="x_315">Si vous êtes un nouvel utilisateur de Mercurial, vous devez garder
  16.425 +          à l'esprit une <quote>erreur</quote> commune, qui est d'utiliser la
  16.426 +          commande <command role="hg-cmd">hg pull</command> sans aucune
  16.427 +          option. Par défaut, la commande <command role="hg-cmd">hg
  16.428 +              pull</command> <emphasis>ne fait pas</emphasis> d'<quote>update</quote> sur le
  16.429 +          répertoire de travail, ainsi, vous allez récupérer les nouveaux
  16.430 +          changesets dans votre dépôt, mais le répertoire de travail va
  16.431 +          rester synchronisé au même <quote>changeset</quote> qu'il l'était avant le <quote>pull</quote>.
  16.432 +          Si vous faites des changements et <quote>committez</quote> ensuite, vous allez
  16.433 +          créer une nouvelle <quote>head</quote> puisque votre répertoire de travail n'est
  16.434 +          pas synchronisé au <quote>tip</quote> actuel. Pour combiner les
  16.435 +          opérations d'un <quote>pull</quote> suivi d'un <quote>update</quote>, exécutez <command>hg
  16.436 +            pull -u</command>.</para>
  16.437 +      
  16.438 +        <para id="x_316">Je place le mot <quote>erreur</quote> entre
  16.439 +          guillemets parce que tout ce dont vous avez besoin de faire pour
  16.440 +          rectifier la situation où vous avez créé une nouvelle <quote>head</quote> par
  16.441 +          accident est un <command role="hg-cmd">hg merge</command> suivi
  16.442 +          d'un <command role="hg-cmd">hg commit</command>.  En d'autres mots,
  16.443 +          ceci n'a presque jamais de conséquences négatives ; il s'agit juste
  16.444 +          d'une surprise pour les nouveaux arrivants. Je discuterai d'autres
  16.445 +          moyens d'éviter ce comportement, et pourquoi Mercurial agit de
  16.446 +          cette façon surprenante plus tard.</para>
  16.447 +      </note>
  16.448 +
  16.449 +    </sect2>
  16.450 +    <sect2>
  16.451 +      <title>Fusionner (merge) les changements</title>
  16.452 +
  16.453 +      <para id="x_317">Lorsque vous exécutez la commande <command
  16.454 +          role="hg-cmd">hg merge</command>, Mercurial laisse le premier
  16.455 +        parent du répertoire de travail inchangé et fixe le second au
  16.456 +        <quote>changeset</quote> avec lequel vous fusionnez (merge), comme montré dans <xref
  16.457 +          linkend="fig:concepts:wdir-merge"/>.</para>
  16.458 +
  16.459 +      <figure id="fig:concepts:wdir-merge">
  16.460 +          <title>Fusionner (merge) deux <quote>heads</quote></title>
  16.461 +        <mediaobject>
  16.462 +          <imageobject> <imagedata fileref="figs/wdir-merge.png"/>
  16.463 +        </imageobject> <textobject><phrase>XXX add text</phrase></textobject>
  16.464 +      </mediaobject>
  16.465 +      </figure>
  16.466 +
  16.467 +      <para id="x_319">Mercurial doit aussi modifier le répertoire de
  16.468 +          travail pour fusionner les fichiers gérés dans les deux <quote>changesets</quote>.
  16.469 +        Un peu simplifié, le processus de fusion fonctionne comme ça : pour
  16.470 +        chaque fichier dans le <quote>manifest</quote> de chaque <quote>changeset</quote>.</para>
  16.471 +
  16.472 +      <itemizedlist>
  16.473 +          <listitem><para id="x_31a">Si aucun <quote>changeset</quote> n'a modifié un fichier,
  16.474 +            ne rien faire avec ce fichier.</para> </listitem>
  16.475 +    <listitem><para id="x_31b">Si un <quote>changeset</quote> a modifié un fichier et
  16.476 +            que l'autre ne l'a pas fait, créer une copie modifiée du fichier
  16.477 +            dans le répertoire de travail.</para> </listitem>
  16.478 +    <listitem><para id="x_31c">Si un <quote>changeset</quote> a modifié un fichier, et
  16.479 +            que l'autre ne l'a pas fait (ou l'a supprimé), supprimer le
  16.480 +            fichier du répertoire de travail.</para> </listitem>
  16.481 +    <listitem><para id="x_31d">Si un <quote>changeset</quote> a supprimé un fichier,
  16.482 +            mais que l'autre a modifié le fichier, demander à l'utilisateur
  16.483 +            quoi faire : garder le fichier modifié ou le supprimer ?</para>
  16.484 +        </listitem>
  16.485 +        <listitem><para id="x_31e">Si chacun des <quote>changesets</quote> a modifié un
  16.486 +            fichier, invoquer le programme externe de fusion pour choisir les
  16.487 +            nouveaux contenus pour le fichier fusionné. Ceci peut demander
  16.488 +            une intervention de l'utilisateur.</para></listitem>
  16.489 +    <listitem><para id="x_31f">Si un <quote>changeset</quote> a modifié un fichier, et
  16.490 +            que l'autre a renommé ou copié le fichier, être sûr que les
  16.491 +            changements suivent le nouveau nom du fichier.</para></listitem>
  16.492 +      </itemizedlist>
  16.493 +      
  16.494 +      <para id="x_320">Il y a plus de détails&emdash;fusionner a beaucoup de
  16.495 +        cas épineux&emdash;mais ceux-ci sont des choix plus communs qui sont
  16.496 +        liés à une fusion (merge). Comme vous pouvez le voir, la
  16.497 +        plupart des cas sont entièrement automatiques, et effectivement, la
  16.498 +        plupart des fusions (merge) se terminent automatiquement, sans nécessiter
  16.499 +        votre intervention pour résoudre un conflit.</para>
  16.500 +
  16.501 +      <para id="x_321">Lorsque vous pensez à ce qu'il se passe lorsque vous
  16.502 +          <quote>committez</quote> après un <quote>merge</quote>, une fois encore, le répertoire de travail
  16.503 +        est <quote>le changeset que je suis sur le point de
  16.504 +          committer</quote>. Après que la commande <command role="hg-cmd">hg
  16.505 +          merge</command> soit terminée, le répertoire de travail a deux
  16.506 +        parents ; ceux ci vont devenir les parents du nouveau
  16.507 +        <quote>changeset</quote>.</para>
  16.508 +
  16.509 +      <para id="x_322">Mercurial vous permet d'exécuter de multiples fusions,
  16.510 +          mais vous devez <quote>committer</quote> le résultat de chaque fusion individuellement
  16.511 +        au fur et à mesure. Ceci est nécessaire puisque Mercurial ne stocke
  16.512 +        que deux parents pour chaque révision et le répertoire de travail.
  16.513 +        Alors qu'il serait techniquement faisable de fusionner de multiples
  16.514 +        <quote>changesets</quote> en même temps, Mercurial interdit cela pour être plus simple. Avec
  16.515 +        des fusions multiples, les risques de confusion pour l'utilisateur, de
  16.516 +        mauvaie résolution de conflits, et de pagaille dans les fusions
  16.517 +        augmenteraient de façon intolérable.</para>
  16.518 +
  16.519 +    </sect2>
  16.520 +
  16.521 +    <sect2>
  16.522 +      <title>Fusions et renommages</title>
  16.523 +
  16.524 +      <para id="x_69a">Un nombre surprenant de systèmes de gestion de
  16.525 +        révisions fait peu ou pas attention à un <emphasis>nom</emphasis> de fichier au
  16.526 +        cours du temps. Par exemple, il était habituel que si un fichier
  16.527 +        était renommé d'un coté de la fusion, les changements à partir de
  16.528 +        l'autre coté étaient supprimés silencieusement.</para>
  16.529 +
  16.530 +      <para id="x_69b">Mercurial enregistre les metadata lorsque vous lui
  16.531 +        dites d'exécuter un renommage ou une copie. Il utilise ces metadatas
  16.532 +        durant une fusion pour faire les bonnes choses dans le cas d'un
  16.533 +        <quote>merge</quote>. Par exemple, si je renomme un fichier et que vous l'éditez
  16.534 +        sans le renommer, lorsque l'on fusionne, le fichier sera renommé et
  16.535 +        aura les changements appliqués.</para>
  16.536 +
  16.537 +    </sect2>
  16.538 +  </sect1>
  16.539 +
  16.540 +  <sect1>
  16.541 +    <title>D'autres fonctionnalités intéressantes</title>
  16.542 +
  16.543 +    <para id="x_323">Dans les sections au-dessus, j'ai tenté de mettre
  16.544 +      l'accent sur certains aspects importants du design de Mercurial pour
  16.545 +      illustrer l'attention particulière qui a été portée à la fiabilité et à
  16.546 +      la performance. Cependant, l'attention aux détails ne s'arrête pas ici.
  16.547 +      Il y a de nombreux aspects sur la construction de Mercurial que je
  16.548 +      trouve personnellement intéressants. J'en détaillerai quelques-uns 
  16.549 +      ici, séparément des éléments du <quote>big ticket</quote> ci-dessus,
  16.550 +      ainsi, si vous êtes intéressés, vous pourrez avoir une meilleure idée
  16.551 +      de la quantité d'ingéniosité qu'il y a derrière un système bien
  16.552 +      conçu.</para>
  16.553 +
  16.554 +    <sect2>
  16.555 +      <title>Compression astucieuse</title>
  16.556 +
  16.557 +      <para id="x_324">Lorsque cela est approprié, Mercurial stocke les
  16.558 +          <quote>snapshots</quote> et deltas sous une forme compressée. Il le fait en
  16.559 +          <emphasis>essayant</emphasis> toujours de compresser un <quote>snapshot</quote> ou
  16.560 +        un delta, mais en ne stockant la version compressée que si celle-ci
  16.561 +        est plus petite que la version non compressée.</para>
  16.562 +
  16.563 +      <para id="x_325">Ceci signifie que Mercurial fait <quote>la bonne
  16.564 +          chose</quote> lorsqu'il stocke un fichier dont la forme native est
  16.565 +        compressée, comme une archive <literal>zip</literal> ou une image
  16.566 +        JPEG. Lorsque ces types de fichiers sont compressés une seconde fois,
  16.567 +        le fichier obtenu est habituellement plus gros que la forme
  16.568 +        compressée une seule fois et Mercurial stockera alors le
  16.569 +        <literal>zip</literal> ou JPEG.</para>
  16.570 +
  16.571 +      <para id="x_326">Les deltas entre les révisions d'un fichier compressé
  16.572 +        sont habituellement plus gros que les snapshots du fichier, et
  16.573 +        Mercurial fait à nouveau <quote>la bonne chose</quote> dans ces cas.
  16.574 +        Il trouve qu'un delta dépasse le seuil auquel il devrait stocker un
  16.575 +        <quote>snapshot</quote> complet du fichier, alors il stocke le <quote>snapshot</quote>, en gagnant
  16.576 +        encore de la place en comparaison d'une approche naïve avec un delta
  16.577 +        seulement.</para>
  16.578 +
  16.579 +      <sect3>
  16.580 +        <title>Recompression sur le réseau</title>
  16.581 +      
  16.582 +        <para id="x_327">Lors du stockage des révisions sur le disque,
  16.583 +          Mercurial utilise l'algorithme de compression
  16.584 +          <quote>deflate</quote> (le même que celui utilisé pour le format populaire
  16.585 +          d'archive <literal>zip</literal>), qui est un bon
  16.586 +          compromis entre la vitesse et le taux de compression. Cependant,
  16.587 +          lors de la transmission d'une révision de données par une connexion
  16.588 +          réseau, Mercurial décompresse les données de révision
  16.589 +          compressées.</para>
  16.590 +      
  16.591 +        <para id="x_328">Si la connexion passe par HTTP, Mercurial
  16.592 +          recompresse le flux entier de données en utilisant un algorithme de
  16.593 +          compression qui donne un meilleur taux de compression (l'algorithme
  16.594 +          Burrows-Wheeler utilisé principalement par le logiciel de
  16.595 +          compression <literal>bzip2</literal>). Cette combinaison de
  16.596 +          l'algorithme et de la compression du flux entier (plutôt que pour une
  16.597 +          révision à la fois) réduit substantiellement le nombre de bits qui
  16.598 +          sont transférés, résultant en une performance réseau accrue sur
  16.599 +          la plupart des supports.</para>
  16.600 +      
  16.601 +        <para id="x_329">Si la connexion passe par
  16.602 +          <command>ssh</command>, Mercurial <emphasis>ne</emphasis>
  16.603 +          recompresse <emphasis>pas</emphasis> le flux puisque
  16.604 +          <command>ssh</command> peut déjà le faire par lui-même. Vous pouvez
  16.605 +          demander à Mercurial de toujours utiliser la compression
  16.606 +          <command>ssh</command> en éditant le fichier
  16.607 +          <filename>.hgrc</filename> de votre répertoire personnel comme ci-dessous.
  16.608 +      </para>
  16.609 +      
  16.610 +        <programlisting>[ui]
  16.611 +ssh = ssh -C</programlisting>
  16.612 +
  16.613 +      </sect3>
  16.614 +    </sect2>
  16.615 +    <sect2>
  16.616 +      <title>Ordre de lecture/écriture et atomicité</title>
  16.617 +
  16.618 +      <para id="x_32a">L'histoire ne se résume pas à ajouter à la fin des fichiers
  16.619 +        lorsque l'on cherche à garantir que le lecteur ne verra
  16.620 +        pas qu'une écriture partielle. Si vous relisez <xref
  16.621 +            linkend="fig:concepts:metadata"/>, les révisions dans le <quote>changelog</quote>
  16.622 +        pointent vers les révisions dans le <quote>manifest</quote>, et les révisions du
  16.623 +        <quote>manifest</quote> pointent vers les révisions du <quote>filelog</quote>. Cette hiérarchie est
  16.624 +        délibérée.</para>
  16.625 +
  16.626 +      <para id="x_32b">L'écriture commence par une transaction en écrivant dans
  16.627 +          le <quote>filelog</quote> et dans les données du <quote>manifest</quote>, et n'écrit aucune donnée
  16.628 +        du  <quote>changelog</quote> tant que ce n'est pas terminé. La lecture commence en
  16.629 +        lisant les données du <quote>changelog</quote>, puis les données du <quote>manifest</quote>, et
  16.630 +        enfin les données du <quote>filelog</quote>.</para>
  16.631 +
  16.632 +      <para id="x_32c">Puisque que l'écriture ne finit pas d'écrire les
  16.633 +          données du <quote>filelog</quote> et du <quote>manifest</quote> avant d'écrire dans le <quote>changelog</quote>,
  16.634 +          la lecture ne verra jamais un pointeur vers une révision du <quote>manifest</quote>
  16.635 +          partiellement écrite à partir du <quote>changelog</quote>, et ne lira jamais un
  16.636 +          pointeur vers une révision du <quote>filelog</quote> partiellement écrite dans le
  16.637 +          <quote>manifest</quote>.</para>
  16.638 +
  16.639 +    </sect2>
  16.640 +    <sect2>
  16.641 +      <title>Accès concurrent</title>
  16.642 +
  16.643 +      <para id="x_32d">La garantie de l'ordre de lecture/écriture et
  16.644 +        de l'atomicité signifie que Mercurial n'a jamais besoin de poser de
  16.645 +        <emphasis>lock</emphasis> sur un dépôt lorsqu'il lit des données,
  16.646 +        même si le dépôt est en train d'être écrit au même moment que la
  16.647 +        lecture a lieu. Ceci a un grand impact sur la fiabilité ; vous
  16.648 +        pouvez avoir un nombre arbitraire de processus Mercurial qui lisent
  16.649 +        sans risque les données d'un dépôt en même temps, peu importe s'il
  16.650 +        est en train d'être lu ou non.</para>
  16.651 +
  16.652 +      <para id="x_32e">La nature sans <quote>lock</quote> de la lecture
  16.653 +        signifie que si vous partagez un dépôt sur un système
  16.654 +        multi-utilisateurs, vous n'avez pas besoin de donner aux autres
  16.655 +        utilisateurs locaux la permission d'<emphasis>écrire</emphasis> sur
  16.656 +        votre dépôt pour qu'ils soient capable de faire un clone ou un <quote>pull</quote>
  16.657 +        des changements à partir de celui-ci ; ils ont seulement besoin de la
  16.658 +        permission en <emphasis>lecture</emphasis>. (Il
  16.659 +        <emphasis>ne</emphasis> s'agit <emphasis>pas</emphasis> d'une
  16.660 +        fonctionnalité commune à travers les systèmes de gestion de révisions,
  16.661 +        donc ne prenez pas ça pour argent comptant ! La plupart ont besoin que les
  16.662 +        lecteurs soient capables de mettre un lock sur le dépôt pour y
  16.663 +        accéder en toute sécurité, et ceci demande des permissions en
  16.664 +        écriture, sur au moins un répertoire, ce qui provoque bien sûr toutes
  16.665 +        sortes de problèmes pénibles et agaçants relatifs à la sécurité et à
  16.666 +        l'administration.)</para>
  16.667 +
  16.668 +    <para id="x_32f">Mercurial utilise des <quote>locks</quote> pour assurer qu'un seul
  16.669 +        processus peut écrire dans le dépôt à un moment donné (le mécanisme
  16.670 +        de <quote>lock</quote> est sûr, même sur des systèmes de fichiers qui sont connus
  16.671 +        pour être hostiles aux <quote>locks</quote>, comme NFS). Si un dépôt dispose d'un
  16.672 +        <quote>lock</quote>, un processus qui cherche à écrire va attendre un peu avant de
  16.673 +        retenter pour voir si le dépôt perd son <quote>lock</quote>, mais si le dépôt garde
  16.674 +        trop longtemps son <quote>lock</quote>, le processus qui tente d'écrire va expirer
  16.675 +        (time out) après un moment. Cela veut dire par exemple que vos
  16.676 +        scripts lancés quotidiennement n'attendront pas toujours et boucleront
  16.677 +        si un système plantait sans avertissement, par exemple. (Oui, le
  16.678 +        timeout est configurable, de zéro à l'infini.)</para>
  16.679 +
  16.680 +      <sect3>
  16.681 +          <title>Accès <quote>dirstate</quote> sûr</title>
  16.682 +
  16.683 +	<para id="x_330">Comme avec les données de révision, Mercurial n'utilise pas
  16.684 +        de <quote>lock</quote> pour lire le fichier <quote>dirstate</quote> ; il n'acquiert pas un <quote>lock</quote> pour
  16.685 +    y écrire. Pour empêcher la possibilité de lire une copie partiellement
  16.686 +    écrite du fichier <quote>dirstate</quote>, Mercurial écrit sur un fichier avec un nom
  16.687 +    unique dans le même répertoire que le fichier <quote>dirstate</quote>, ensuite renomme
  16.688 +    le fichier temporaire automatiquement en <filename>dirstate</filename>.
  16.689 +    Le fichier nommé <filename>dirstate</filename> est ainsi garanti d'être
  16.690 +    écrit totalement, et non partiellement.</para>
  16.691 +
  16.692 +      </sect3>
  16.693 +    </sect2>
  16.694 +    <sect2>
  16.695 +      <title>Empêcher les recherches</title>
  16.696 +
  16.697 +      <para id="x_331">L'absence de recherche sur les têtes de disques est
  16.698 +        critique pour la performance de Mercurial, puisque toute recherche
  16.699 +        est beaucoup plus coûteuse comparativement à une grosse opération de
  16.700 +        lecture.</para>
  16.701 +
  16.702 +    <para id="x_332">C'est pour ça, par exemple, que le <quote>dirstate</quote> est stocké
  16.703 +        dans un fichier unique. S'il y avait eu un <quote>dirstate</quote> par répertoire
  16.704 +        que Mercurial suivrait, le disque aurait recherché une fois par
  16.705 +        répertoire. Au lieu de ça, Mercurial lit entièrement un 
  16.706 +        fichier unique, en une étape.</para>
  16.707 +
  16.708 +      <para id="x_333">Mercurial utilise aussi un schéma <quote>copie à
  16.709 +          l'écriture</quote> lorsqu'il clone un dépôt sur un stockage local.
  16.710 +      Au lieu de copier chaque <quote>fichier</quote> revlog depuis l'ancien dépôt vers le
  16.711 +        nouveau dépôt, il crée un <quote>lien physique</quote>, qui est le
  16.712 +        plus court chemin pour dire <quote>Ces deux noms pointent vers le
  16.713 +          même fichier</quote>. Lorsque Mercurial est sur le point d'écrire
  16.714 +        sur l'un des revlogs de ces fichiers, il vérifie si le nombre de noms
  16.715 +        pointant sur ce fichier est plus grand que un. Si c'est le cas, plus
  16.716 +        d'un dépôt utilise le fichier, donc Mercurial crée une nouvelle copie
  16.717 +        du fichier qui est privée à ce dépôt.</para>
  16.718 +
  16.719 +      <para id="x_334">Quelques développeurs de systèmes de gestion de
  16.720 +        révisions ont montré que cette idée de faire une copie privée complète
  16.721 +        d'un fichier n'est pas vraiment efficace au niveau du
  16.722 +        stockage. Bien que ce soit vrai, le stockage est peu onéreux, et
  16.723 +        cette méthode donne la plus grande performance lorsque l'on reporte
  16.724 +        la plupart des journalisations au système d'exploitation. Un schéma
  16.725 +        alternatif réduirait certainement la performance tout en augmentant
  16.726 +        la complexité du logiciel, mais la vitesse et la simplicité sont les
  16.727 +        clefs du <quote>confort</quote> de l'utilisation
  16.728 +        quotidienne.</para>
  16.729 +
  16.730 +    </sect2>
  16.731 +    <sect2>
  16.732 +        <title>Autres contenus du <quote>dirstate</quote></title>
  16.733 +
  16.734 +      <para id="x_335">Puisque Mercurial ne vous force pas à signaler que
  16.735 +          vous modifiez un fichier, il utilise le <quote>dirstate</quote> pour stocker
  16.736 +        certaines informations supplémentaires pour déterminer efficacement
  16.737 +        si vous avez ou non modifié un fichier. Pour chaque fichier du
  16.738 +        répertoire de travail, il stocke l'heure à laquelle il a été modifié,
  16.739 +        ainsi que la taille du fichier à cette heure.</para>
  16.740 +
  16.741 +      <para id="x_336">Lorsque vous faites explicitement un <command
  16.742 +          role="hg-cmd">hg add</command>, <command role="hg-cmd">hg
  16.743 +          remove</command>, <command role="hg-cmd">hg rename</command> ou
  16.744 +        <command role="hg-cmd">hg copy</command> sur des fichiers, Mercurial
  16.745 +        met à jour le <quote>dirstate</quote> afin de savoir que faire lorsque vous
  16.746 +        effectuez un <quote>commit</quote>.</para>
  16.747 +
  16.748 +    <para id="x_337">Le <quote>dirstate</quote> aide Mercurial à vérifier efficacement le
  16.749 +        statut des fichiers dans un dépôt.</para>
  16.750 +
  16.751 +      <itemizedlist>
  16.752 +        <listitem> <para id="x_726"> Lorsque Mercurial vérifie l'état d'un
  16.753 +            fichier du répertoire de travail, il compare d'abord la date de
  16.754 +            dernière modification du fichier avec celle enregistrée dans le
  16.755 +            <quote>dirstate</quote> qui correspond à celle que Mercurial a écrit en dernier sur ce
  16.756 +            fichier. Si la date de dernière modification correspond à la date
  16.757 +            où Mercurial a écrit le fichier, celui ci n'a pas été modifié,
  16.758 +            donc Mercurial n'a pas besoin de revérifier.</para> </listitem>
  16.759 +    <listitem> <para id="x_727"> Si la taille du fichier a changé, celui-ci 
  16.760 +            a été modifié. Si la date de modification a changé mais que la
  16.761 +            taille est restée inchangée, seulement à ce moment là Mercurial
  16.762 +            doit vérifier le contenu du fichier pour savoir s'il a été
  16.763 +            modifié.</para> </listitem>
  16.764 +      </itemizedlist>
  16.765 +
  16.766 +      <para id="x_728">Enregistrer la date de modification et la taille
  16.767 +        réduit grandement le nombre d'opérations de lecture que Mercurial
  16.768 +        doit effectuer lorsque l'on utilise une commande comme <command>hg
  16.769 +          status</command>. Le résultat est un grand gain de
  16.770 +        performance.</para>
  16.771 +    </sect2>
  16.772 +  </sect1>
  16.773 +</chapter>
  16.774 +
  16.775 +<!--
  16.776 +local variables: 
  16.777 +sgml-parent-document: ("00book.xml" "book" "chapter")
  16.778 +end:
  16.779 +-->
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/fr/ch05-daily.xml	Sat Jul 10 06:24:49 2010 +0100
    17.3 @@ -0,0 +1,870 @@
    17.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
    17.5 +
    17.6 +<chapter id="chap:daily">
    17.7 +  <?dbhtml filename="mercurial-in-daily-use.html"?>
    17.8 +  <title>Utilisation quotidienne de Mercurial</title>
    17.9 +
   17.10 +  <sect1>
   17.11 +    <title>Informer Mercurial des fichiers à suivre</title>
   17.12 +
   17.13 +    <para id="x_1a3">Mercurial ne suit pas les fichiers de votre dépôt tant
   17.14 +      que vous ne lui avez pas dit de les gérer. La commande <command
   17.15 +        role="hg-cmd">hg status</command> vous dira quels fichiers sont
   17.16 +      inconnus de Mercurial. Il utilise un
   17.17 +      <quote><literal>?</literal></quote> pour montrer ces fichiers.</para>
   17.18 +
   17.19 +    <para id="x_1a4">Pour informer Mercurial de suivre un fichier, utilisez
   17.20 +      la commande <command role="hg-cmd">hg add</command>. Une fois que vous
   17.21 +      avez ajouté un fichier, la ligne correspondante à ce fichier dans la
   17.22 +      sortie de <command role="hg-cmd">hg status</command> change de
   17.23 +      <quote><literal>?</literal></quote> à
   17.24 +      <quote><literal>A</literal></quote>.</para>
   17.25 +
   17.26 +    &interaction.daily.files.add;
   17.27 +
   17.28 +    <para id="x_1a5">Après avoir exécuté un <command role="hg-cmd">hg
   17.29 +        commit</command>, les fichiers que vous avez ajoutés avant le commit
   17.30 +      ne seront plus listés dans la sortie de <command role="hg-cmd">hg
   17.31 +        status</command>. La raison de ceci est que, par défaut, <command
   17.32 +        role="hg-cmd">hg status</command> ne vous montre que les fichiers
   17.33 +      <quote>intéressants</quote> &emdash;ceux que vous avez (par exemple)
   17.34 +      modifiés, supprimés ou renommés. Si vous avez un dépôt qui contient un
   17.35 +      millier de fichiers, vous ne voudriez certainement que rarement entendre
   17.36 +      parler des fichiers que Mercurial suit, mais qui n'ont pas changés.
   17.37 +      (Vous pouvez quand même avoir cette information, nous y reviendrons
   17.38 +      plus tard.)</para>
   17.39 +
   17.40 +    <para id="x_1a6">Une fois que vous ajoutez un fichier, Mercurial ne fait
   17.41 +      rien du tout avec celui-ci immédiatement. Au lieu de ça, il va prendre
   17.42 +      un "snapshot" de l'état du fichier la prochaine fois que vous
   17.43 +      exécuterez un commit. Il continuera ensuite à suivre les changements
   17.44 +      que vous avez fait au fichier chaque fois que vous committerez, et ce,
   17.45 +      jusqu'à ce que vous supprimiez le fichier.</para>
   17.46 +
   17.47 +    <sect2>
   17.48 +      <title>Nommage des fichiers explicite versus implicite</title>
   17.49 +
   17.50 +      <para id="x_1a7">Un comportement utile que Mercurial possède est que si
   17.51 +        vous passez le nom d'un répertoire à une commande, toute commande
   17.52 +        Mercurial la traitera comme : <quote>Je veux opérer sur chaque fichier
   17.53 +          dans ce répertoire et ses sous-répertoires</quote>.</para>
   17.54 +
   17.55 +      &interaction.daily.files.add-dir;
   17.56 +
   17.57 +      <para id="x_1a8">Remarquez que dans cet exemple, Mercurial affiche le
   17.58 +        nom des fichiers qu'il a ajouté, alors qu'il ne l'a pas fait lorsque
   17.59 +        nous avons ajouté le fichier nommé <filename>myfile.txt</filename>
   17.60 +        dans l'exemple précédent.</para>
   17.61 +
   17.62 +      <para id="x_1a9">Ce qu'il se passe est que dans le premier cas, nous
   17.63 +        avons nommé explicitement le fichier à ajouter sur la ligne de
   17.64 +        commande. Ce que Mercurial suppose dans ce cas est que nous savons ce
   17.65 +        que nous faisons, il n'affiche donc rien en sortie.</para>
   17.66 +
   17.67 +      <para id="x_1aa">Cependant, lorsque nous avons
   17.68 +        <emphasis>implicitement</emphasis> donné les fichiers à l'aide du nom
   17.69 +        d'un répertoire, Mercurial prend l'initiative d'afficher le nom de
   17.70 +        chaque fichier avec lequel il fait quelque chose. Ceci clarifie ce
   17.71 +        qu'il se passe et réduit la probabilité d'une mauvaise surprise
   17.72 +        restée silencieuse. Ce comportement est commun à la plupart des
   17.73 +        commandes Mercurial.</para>
   17.74 +    </sect2>
   17.75 +    <sect2>
   17.76 +      <title>Mercurial suit les fichiers, pas les répertoires</title>
   17.77 +
   17.78 +      <para id="x_1ab">Mercurial ne suit pas les informations sur les
   17.79 +        répertoires. En contrepartie, il suit le chemin vers un fichier. Avant
   17.80 +        de créer un fichier, il crée au préalable les répertoires manquants
   17.81 +        dans le chemin. Après avoir supprimé un fichier, il supprime chaque
   17.82 +        répertoire vide qui apparaît dans le chemin du fichier. Ceci apparaît
   17.83 +        comme une distinction triviale, cependant, cela a une conséquence
   17.84 +        pratique mineure : il n'est pas possible de représenter un répertoire
   17.85 +        totalement vide dans Mercurial.</para>
   17.86 +
   17.87 +      <para id="x_1ac">Les répertoires vides sont rarement utiles. Il existe
   17.88 +        cependant des solutions alternatives et non intrusives que vous
   17.89 +        pouvez utiliser pour obtenir l'effet approprié. Les développeurs de
   17.90 +        Mercurial ont ainsi pensé que la complexité requise pour gérer les
   17.91 +        répertoires n'était pas aussi importante que le bénéfice que cette
   17.92 +        fonctionnalité apporterait.</para>
   17.93 +
   17.94 +      <para id="x_1ad">Si vous avez besoin d'un répertoire vide dans votre
   17.95 +        dépôt, il existe quelques façons d'y arriver. L'une d'elles est de
   17.96 +        créer un répertoire et ensuite, de faire un <command role="hg-cmd">hg
   17.97 +          add</command> sur un fichier <quote>caché</quote> dans ce
   17.98 +        répertoire. Sur les systèmes de type Unix, tout fichier dont le nom
   17.99 +        commence avec un point (<quote><literal>.</literal></quote>) est
  17.100 +        considéré comme caché par la plupart des commandes et outils
  17.101 +        graphiques. Cette approche est illustrée ci-après.</para>
  17.102 +      
  17.103 +      &interaction.daily.files.hidden;
  17.104 +
  17.105 +      <para id="x_1ae">Une autre façon de s'attaquer au besoin d'un
  17.106 +        répertoire vide est de simplement d'en créer un dans vos scripts
  17.107 +        de construction avant qu'ils n'en aient le besoin.</para>
  17.108 +    </sect2>
  17.109 +  </sect1>
  17.110 +
  17.111 +  <sect1>
  17.112 +    <title>Comment arrêter de suivre un fichier</title>
  17.113 +
  17.114 +    <para id="x_1af">Une fois que vous décidez qu'un fichier n'appartient
  17.115 +      plus à votre dépôt, utilisez la commande <command role="hg-cmd">hg
  17.116 +        remove</command>. Ceci supprime le fichier et informe Mercurial
  17.117 +      d'arrêter de le suivre (ce qui prendra effet lors du prochain commit).
  17.118 +      Un fichier supprimé est représenté dans la sortie de la commande
  17.119 +      <command role="hg-cmd">hg status</command> par un
  17.120 +      <quote><literal>R</literal></quote>.</para>
  17.121 +
  17.122 +    &interaction.daily.files.remove;
  17.123 +
  17.124 +    <para id="x_1b0">Après avoir fait un <command role="hg-cmd">hg
  17.125 +        remove</command> sur un fichier, Mercurial ne suivra plus aucun
  17.126 +      changement sur ce fichier, même si vous recréez un fichier avec le même
  17.127 +      nom dans votre répertoire de travail. Si vous recréez un fichier avec le
  17.128 +      même nom et que vous désirez que Mercurial suive ce dernier, faite
  17.129 +      simplement un <command role="hg-cmd">hg add</command> sur celui-ci.
  17.130 +      Mercurial saura alors que le nouveau fichier ne fait pas référence à
  17.131 +      l'ancien fichier qui portait le même nom.</para>
  17.132 +
  17.133 +    <sect2>
  17.134 +      <title>Supprimer un fichier n'affecte pas son historique</title>
  17.135 +
  17.136 +      <para id="x_1b1">Il est important de comprendre que supprimer un fichier
  17.137 +        n'a que deux effets.</para>
  17.138 +
  17.139 +      <itemizedlist>
  17.140 +        <listitem><para id="x_1b2">Il supprime la version actuelle de ce
  17.141 +            fichier du répertoire de travail.</para>
  17.142 +        </listitem>
  17.143 +        <listitem><para id="x_1b3">Il arrête, à partir du prochain commit, le
  17.144 +            suivi de Mercurial sur les changements qui ont lieu sur ce
  17.145 +            fichier.</para>
  17.146 +        </listitem></itemizedlist>
  17.147 +        
  17.148 +      <para id="x_1b4">Supprimer un fichier <emphasis>n'</emphasis>affecte en
  17.149 +        <emphasis>aucun</emphasis> cas l'<emphasis>historique</emphasis> du
  17.150 +        fichier.</para>
  17.151 +
  17.152 +      <para id="x_1b5">Si vous mettez à jour le répertoire de travail à un
  17.153 +        changeset qui a été committé alors que le fichier que vous venez de
  17.154 +        supprimer était encore suivi, ce fichier réapparaîtra dans le
  17.155 +        répertoire de travail, avec le contenu qu'il avait lorsque vous aviez
  17.156 +        committé ce changeset. Si vous mettez à jour (update) le répertoire de
  17.157 +        travail à un changeset ultérieur dans lequel le fichier a été
  17.158 +        supprimé, Mercurial supprimera une nouvelle fois le fichier du
  17.159 +        répertoire de travail.</para>
  17.160 +    </sect2>
  17.161 +
  17.162 +    <sect2>
  17.163 +      <title>Fichiers manquants</title>
  17.164 +
  17.165 +      <para id="x_1b6">Mercurial considère qu'un fichier que vous avez
  17.166 +        supprimé sans utiliser<command role="hg-cmd">hg remove</command>
  17.167 +        comme étant <emphasis>manquant</emphasis>.  Un fichier manquant est
  17.168 +        représenté avec un <quote><literal>!</literal></quote> en sortie de
  17.169 +        <command role="hg-cmd">hg status</command>.
  17.170 +        Les commandes Mercurial ne feront rien avec les fichiers
  17.171 +        manquants.</para>
  17.172 +
  17.173 +      &interaction.daily.files.missing;
  17.174 +
  17.175 +      <para id="x_1b7">Si votre dépôt contient un fichier que <command
  17.176 +          role="hg-cmd">hg status</command> reporte comme manquant, et que
  17.177 +        vous voulez que ce fichier reste supprimé, vous pouvez exécuter
  17.178 +        <command role="hg-cmd">hg remove <option
  17.179 +            role="hg-opt-remove">--after</option></command> à tout moment
  17.180 +        pour dire à Mercurial que vous aviez bien voulu supprimer ce
  17.181 +        fichier.</para>
  17.182 +
  17.183 +      &interaction.daily.files.remove-after;
  17.184 +
  17.185 +      <para id="x_1b8">D'un autre côté, si vous avez supprimé le fichier
  17.186 +        manquant par accident, donnez à la commande <command role="hg-cmd">hg
  17.187 +          revert</command> le nom du fichier à retrouver. Il réapparaitra dans
  17.188 +        sa forme non modifiée.</para>
  17.189 +
  17.190 +      &interaction.daily.files.recover-missing;
  17.191 +    
  17.192 +    </sect2>
  17.193 +
  17.194 +    <sect2>
  17.195 +      <title>Aparté : Pourquoi dire explicitement à Mercurial de supprimer un
  17.196 +      fichier ?</title>
  17.197 +<!-- TODO Choisir une traduction commune à tous les chapitres pour Aside -->
  17.198 +      <para id="x_1b9">Vous pourriez vous demander pourquoi il est nécessaire
  17.199 +        de dire explicitement à Mercurial que vous souhaitez supprimer un
  17.200 +        fichier. Au début du développement de Mercurial, celui ci vous
  17.201 +        laissait pourtant supprimer un fichier sans souci ; Mercurial vous
  17.202 +        aurait automatiquement informé de l'absence du fichier lorsque vous
  17.203 +        auriez lancé un <command role="hg-cmd">hg commit</command> et arrêté
  17.204 +        de le suivre. En pratique, ceci a montré qu'il était trop facile de
  17.205 +        supprimer accidentellement un fichier sans le remarquer.</para>
  17.206 +    </sect2>
  17.207 +
  17.208 +    <sect2>
  17.209 +      <title>Raccourci utile&emdash;ajouter et supprimer des fichiers en une
  17.210 +      seule étape.</title>
  17.211 +
  17.212 +      <para id="x_1ba">Mercurial offre une commande combinée, <command
  17.213 +          role="hg-cmd">hg addremove</command>, qui ajoute les fichiers non
  17.214 +        suivis et marque les fichiers manquants comme supprimés.</para>
  17.215 +
  17.216 +      &interaction.daily.files.addremove;
  17.217 +
  17.218 +      <para id="x_1bb">La commande <command role="hg-cmd">hg commit</command>
  17.219 +        fournit aussi une option <option role="hg-opt-commit">-A</option> qui
  17.220 +        exécute le même ajouter-et-supprimer, immédiatement suivi d'un
  17.221 +        commit.</para>
  17.222 +
  17.223 +      &interaction.daily.files.commit-addremove;
  17.224 +    
  17.225 +    </sect2>
  17.226 +  </sect1>
  17.227 +
  17.228 +  <sect1 id="chap:daily.copy">
  17.229 +    <title>Copier des fichiers</title>
  17.230 +
  17.231 +    <para id="x_1bc">Mercurial fournit une commande <command role="hg-cmd">hg
  17.232 +        copy</command> qui vous permet de faire une nouvelle copie d'un
  17.233 +      fichier. Lorsque vous copiez un fichier en utilisant cette commande,
  17.234 +      Mercurial crée un enregistrement du fait que ce nouveau fichier est une
  17.235 +      copie du fichier originel. Il traite ces fichiers copiés spécialement
  17.236 +      lorsque vous fusionnez (merge) votre travail avec quelqu'un
  17.237 +      d'autre.</para>
  17.238 +
  17.239 +    <sect2>
  17.240 +      <title>Les résultats d'une copie durant une fusion (merge)</title>
  17.241 +
  17.242 +      <para id="x_1bd">Ce qu'il se passe durant une fusion (merge) est que
  17.243 +        les changements <quote>suivent</quote> une copie. Pour illustrer ce
  17.244 +        que cela veut dire de la meilleure façon, créons un exemple. Nous
  17.245 +        allons commencer avec le mini dépôt usuel qui contient un simple
  17.246 +        fichier.</para>
  17.247 +
  17.248 +      &interaction.daily.copy.init;
  17.249 +
  17.250 +      <para id="x_1be">Nous devons faire du travail en parallèle, ainsi,
  17.251 +        nous aurons quelque chose à fusionner (merge). Donc clonons notre
  17.252 +        dépôt.</para>
  17.253 +
  17.254 +      &interaction.daily.copy.clone;
  17.255 +
  17.256 +      <para id="x_1bf">De retour dans notre dépôt initial, utilisons la
  17.257 +        commande <command role="hg-cmd">hg copy</command> pour faire une
  17.258 +        copie du premier fichier que nous avons créé.</para>
  17.259 +
  17.260 +      &interaction.daily.copy.copy;
  17.261 +
  17.262 +      <para id="x_1c0">Si nous regardons ensuite à la sortie de la commande
  17.263 +        <command role="hg-cmd">hg status</command>, les fichiers copiés
  17.264 +        ont l'air de fichiers normalement ajoutés.</para>
  17.265 +
  17.266 +      &interaction.daily.copy.status;
  17.267 +
  17.268 +      <para id="x_1c1">Mais si nous passons l'option <option
  17.269 +          role="hg-opt-status">-C</option> à <command role="hg-cmd">hg
  17.270 +          status</command>, il affiche une autre ligne de sortie : il s'agit
  17.271 +        du fichier <emphasis>source</emphasis> pour notre copie.</para>
  17.272 +
  17.273 +      &interaction.daily.copy.status-copy;
  17.274 +
  17.275 +      <para id="x_1c2">Maintenant, de retour dans le dépôt que nous avons
  17.276 +        cloné, créons un changement en parallèle. Nous allons ajouter une
  17.277 +        ligne de contenu au fichier original qui a été créé.</para>
  17.278 +
  17.279 +      &interaction.daily.copy.other;
  17.280 +
  17.281 +      <para id="x_1c3">Nous avons alors un fichier <filename>file</filename>
  17.282 +        modifié dans ce dépôt. Lorsque nous récupérons (pull) les changements
  17.283 +        depuis le premier répertoire et fusionnons (merge) les deux "heads",
  17.284 +        Mercurial propagera les changements que nous avons faits localement
  17.285 +        au fichier <filename>file</filename> dans sa copie
  17.286 +        <filename>new-file</filename>.</para>
  17.287 +
  17.288 +      &interaction.daily.copy.merge;
  17.289 +    
  17.290 +    </sect2>
  17.291 +    <sect2 id="sec:daily:why-copy">
  17.292 +      <title>Pourquoi les changements devraient-ils suivre les copies ?</title>
  17.293 +
  17.294 +      <para id="x_1c4">Ce comportement&emdash;des changements d'un fichier
  17.295 +        qui se propagent aux copies de ce fichier&emdash;peut sembler
  17.296 +        ésotérique, mais, dans la plupart des cas, c'est fortement
  17.297 +        souhaitable.</para>
  17.298 +
  17.299 +      <para id="x_1c5">Pour commencer, souvenez-vous que cette propagation
  17.300 +        a lieu <emphasis>seulement</emphasis> lors des fusions (merge).
  17.301 +        Donc, si vous faites un	<command role="hg-cmd">hg copy</command> sur
  17.302 +        un fichier, et par la suite modifiez le fichier original durant le
  17.303 +        cours normal de votre travail, rien n'aura lieu.</para>
  17.304 +
  17.305 +      <para id="x_1c6">La deuxième chose à savoir est que les modifications
  17.306 +        ne se propageront à travers une copie que si le changeset à partir
  17.307 +        duquel vous faites une fusion (merge) <emphasis>n'a pas encore
  17.308 +          vu</emphasis> la copie.</para>
  17.309 +          
  17.310 +      <para id="x_1c7">La raison pour laquelle Mercurial fait ainsi est une
  17.311 +        règle. Imaginons que je corrige un important bug dans un fichier source
  17.312 +        et que je commit mes changements. Pendant ce temps, vous avez décidé de
  17.313 +        faire un <command role="hg-cmd">hg copy</command> du fichier dans
  17.314 +        votre dépôt, sans rien savoir au sujet du bug ou à propos de la
  17.315 +        correction. Vous avez alors commencé à "hacker" sur votre copie du
  17.316 +        fichier.</para>
  17.317 +
  17.318 +      <para id="x_1c8">Si vous aviez récupéré (pull) et fusionné (merge) mes
  17.319 +        changements, et que Mercurial <emphasis>n'avait pas</emphasis>
  17.320 +        propagé les changements à travers les copies, votre nouveau fichier
  17.321 +        source contiendrait maintenant le bug, et à moins que vous ne sachiez
  17.322 +        qu'il faille propager la correction du bug à la main, le bug aurait
  17.323 +        <emphasis>subsisté</emphasis> dans votre copie du fichier.</para>
  17.324 +
  17.325 +      <para id="x_1c9">En propageant automatiquement les changements qui
  17.326 +        fixent les bugs à partir du fichier original vers les copies,
  17.327 +        Mercurial prévient ce type de problèmes. À ma connaissance, Mercurial
  17.328 +        est le <emphasis>seul</emphasis> système de gestion de révisions qui
  17.329 +        propage les changements à travers les copies comme ceci.</para>
  17.330 +
  17.331 +      <para id="x_1ca">Une fois que votre historique des changements a un
  17.332 +        enregistrement concernant une copie et qu'une fusion postérieure a
  17.333 +        eu lieu, il n'y a d'habitude pas d'autre besoin de propager les
  17.334 +        changements du fichier originel vers le fichier copié. C'est pourquoi
  17.335 +        Mercurial ne propage les changements à travers les copies qu'à la
  17.336 +        première fusion, et pas après.</para>
  17.337 +    </sect2>
  17.338 +
  17.339 +    <sect2>
  17.340 +      <title>Comment faire des changements qui <emphasis>ne</emphasis>
  17.341 +      suivent <emphasis>pas</emphasis> une copie</title>
  17.342 +
  17.343 +      <para id="x_1cb">Si pour une raison ou une autre, vous décidez que
  17.344 +        cette fonctionnalité de propager automatiquement les changements à
  17.345 +        travers les copies n'est pas pour vous, utilisez simplement la
  17.346 +        commande normale de copie de votre système (sur les systèmes de type
  17.347 +        Unix, il s'agit de <command>cp</command>) pour faire une copie d'un
  17.348 +        fichier. Utilisez ensuite <command role="hg-cmd">hg add</command>
  17.349 +        pour ajouter les nouveaux fichiers à la main. Cependant, avant d'en
  17.350 +        faire ainsi, relisez <xref linkend="sec:daily:why-copy"/>, et faites
  17.351 +        un choix en connaissance de cause comme quoi cette fonctionnalité
  17.352 +        n'est pas appropriée à votre cas spécifique.</para>
  17.353 +
  17.354 +    </sect2>
  17.355 +    <sect2>
  17.356 +      <title>Comportement de la commande <command role="hg-cmd">hg copy</command></title>
  17.357 +
  17.358 +      <para id="x_1cc">Lorsque vous utilisez la commande <command
  17.359 +          role="hg-cmd">hg copy</command>, Mercurial crée une copie de chaque
  17.360 +        fichier source tel qu'il est actuellement dans le répertoire de
  17.361 +        travail. Cela signifie que si vous effectuez des modifications sur un
  17.362 +        fichier, puis faites un <command role="hg-cmd">hg copy</command> sur
  17.363 +        celui-ci sans avoir au préalable committé ces changements, la nouvelle
  17.364 +        copie contiendra aussi les modifications que vous avez fait jusqu'à
  17.365 +        ce point.	(Je trouve ce comportement quelque peu contre intuitif,
  17.366 +        c'est pourquoi j'en fais mention ici.)</para>
  17.367 +      <!-- Vérifier que je n'ai pas fait de contre sens en relisant la
  17.368 +      version anglaise, ce que je comprend ici me paraît un peu bizarre -->
  17.369 +
  17.370 +      <para id="x_1cd">La commande <command role="hg-cmd">hg copy</command>
  17.371 +        agit comme la commande Unix <command>cp</command> (vous pouvez
  17.372 +        utilisez l'alias <command role="hg-cmd">hg cp</command> si vous
  17.373 +        préférez).  Nous devons lui donner deux ou plus arguments où le
  17.374 +        dernier est considéré comme la <emphasis>destination</emphasis>, et
  17.375 +        les autres comme les <emphasis>sources</emphasis>.</para>
  17.376 +
  17.377 +      <para id="x_685">Si vous passez à <command role="hg-cmd">hg
  17.378 +          copy</command> un seul fichier source, et que la destination
  17.379 +        n'existe pas, ceci créera un nouveau fichier avec ce nom.</para>
  17.380 +
  17.381 +      &interaction.daily.copy.simple;
  17.382 +
  17.383 +      <para id="x_1ce">Si la destination est un répertoire, Mercurial copie
  17.384 +        les sources dans ce répertoire.</para>
  17.385 +
  17.386 +      &interaction.daily.copy.dir-dest;
  17.387 +
  17.388 +      <para id="x_1cf">La copie de répertoire est récursive et préserve la
  17.389 +        structure du répertoire source.</para>
  17.390 +
  17.391 +      &interaction.daily.copy.dir-src;
  17.392 +
  17.393 +      <para id="x_1d0">Si la source et la destination sont tous deux des
  17.394 +        répertoires, l'arborescence de la source est recréée dans le
  17.395 +        répertoire destination.</para>
  17.396 +    
  17.397 +      &interaction.daily.copy.dir-src-dest;
  17.398 +
  17.399 +      <para id="x_1d1">Comme avec la commande <command role="hg-cmd">hg
  17.400 +          remove</command>, si vous copiez un fichier manuellement et voulez
  17.401 +        que Mercurial sache qu'il s'agit d'une copie, utilisez simplement
  17.402 +        l'option <option role="hg-opt-copy">--after</option> avec <command
  17.403 +          role="hg-cmd">hg copy</command>.</para>
  17.404 +
  17.405 +      &interaction.daily.copy.after;
  17.406 +    </sect2>
  17.407 +  </sect1>
  17.408 +
  17.409 +  <sect1>
  17.410 +    <title>Renommer les fichiers</title>
  17.411 +
  17.412 +    <para id="x_1d2">Il est plus commun d'avoir besoin de renommer un
  17.413 +      fichier que d'en faire une copie. La raison pour laquelle j'ai discuté
  17.414 +      de la commande <command role="hg-cmd">hg copy</command> avant de parler
  17.415 +      de renommage des fichiers est que Mercurial traite les renommages
  17.416 +      essentiellement comme une copie. Ainsi, savoir comment Mercurial traite
  17.417 +      les copies de fichiers vous informe sur ce que vous êtes en droit
  17.418 +      d'attendre lorsque vous renommez un fichier.</para>
  17.419 +
  17.420 +    <para id="x_1d3">Lorsque vous utilisez la commande <command
  17.421 +        role="hg-cmd">hg rename</command>, Mercurial crée une copie de tous
  17.422 +      les fichiers sources, les supprime et marque ces fichiers comme étant
  17.423 +      supprimés.</para>
  17.424 +
  17.425 +    &interaction.daily.rename.rename;
  17.426 +
  17.427 +    <para id="x_1d4">La commande <command role="hg-cmd">hg status</command>
  17.428 +      montre les nouveaux fichiers comme ajoutés et les fichiers originaux
  17.429 +      comme supprimés.</para>
  17.430 +
  17.431 +    &interaction.daily.rename.status;
  17.432 +
  17.433 +    <para id="x_1d5">À cause du <command role="hg-cmd">hg copy</command>,
  17.434 +      nous devons utiliser l'option <option role="hg-opt-status">-C</option>
  17.435 +      pour la commande <command	role="hg-cmd">hg status</command> afin
  17.436 +      d'observer que le fichier ajouté est bien suivi par Mercurial comme
  17.437 +      étant une copie de l'original maintenant supprimé.</para>
  17.438 +
  17.439 +    &interaction.daily.rename.status-copy;
  17.440 +
  17.441 +    <para id="x_1d6">Comme avec <command role="hg-cmd">hg remove</command> et
  17.442 +      <command role="hg-cmd">hg copy</command>, vous pouvez informer
  17.443 +      Mercurial d'un renommage après coup en utilisant l'option
  17.444 +      <option role="hg-opt-rename">--after</option>. Dans la plupart des autres
  17.445 +      situations, le comportement de la commande <command role="hg-cmd">hg
  17.446 +        rename</command>, et les options qu'elle accepte sont similaires à la
  17.447 +      commande <command role="hg-cmd">hg copy</command>.</para>
  17.448 +
  17.449 +    <para id="x_686">Si vous êtes familier avec la ligne de commande Unix,
  17.450 +      vous serez heureux d'apprendre que la commande <command
  17.451 +        role="hg-cmd">hg rename</command> peut être invoquée par <command
  17.452 +        role="hg-cmd">hg mv</command>.</para>
  17.453 +
  17.454 +    <sect2>
  17.455 +      <title>Renommer les fichiers et fusionner (merge) les changements</title>
  17.456 +
  17.457 +      <para id="x_1d7">Puisque le <quote>rename</quote> de Mercurial est implanté comme un
  17.458 +        <quote>copy-and-remove</quote>, la même propagation des changements a lieu après
  17.459 +        un <quote>rename</quote> qu'après un <quote>copy</quote> lorsque vous fusionnez (merge).</para>
  17.460 +
  17.461 +      <para id="x_1d8">Si je modifie un fichier et que vous le renommez, si
  17.462 +        ensuite nous fusionnons nos changements respectifs, mes modifications
  17.463 +        sur le fichier sous son nom originel seront propagés vers le même
  17.464 +        fichier sous son nouveau nom. (C'est quelque chose que vous pourriez
  17.465 +        espérer voir <quote>fonctionner simplement</quote>, mais tous les
  17.466 +        systèmes de gestion de version ne le font pas.)</para>
  17.467 +
  17.468 +      <para id="x_1d9">Tandis qu'avoir des changements qui suivent une copie
  17.469 +        est une fonctionnalité où vous hocheriez sûrement la tête en disant
  17.470 +        <quote>oui, cela pourrait être utile</quote>, il est clair que les
  17.471 +        voir suivre un renommage est sans aucun doute important. Sans cette
  17.472 +        facilité, il serait vraiment trop facile d'avoir des changements
  17.473 +        qui deviennent orphelins lorsque des fichiers sont renommés.</para>
  17.474 +    </sect2>
  17.475 +
  17.476 +    <sect2>
  17.477 +      <title>Renommages divergeants et fusion (merge)</title>
  17.478 +
  17.479 +      <para id="x_1da">Le cas de noms divergeants a lieu lorsque deux
  17.480 +        développeurs commencent avec un fichier&emdash;appelons le
  17.481 +        <filename>foo</filename>&emdash;dans leurs dépôts respectifs.</para>
  17.482 +
  17.483 +      &interaction.rename.divergent.clone;
  17.484 +
  17.485 +      <para id="x_1db">Anne renomme le fichier en
  17.486 +        <filename>bar</filename>.</para>
  17.487 +
  17.488 +      &interaction.rename.divergent.rename.anne;
  17.489 +
  17.490 +      <para id="x_1dc">Pendant ce temps, Bob le renomme en
  17.491 +        <filename>quux</filename>. (Souvenez-vous que <command
  17.492 +          role="hg-cmd">hg mv</command> est un alias pour <command
  17.493 +          role="hg-cmd">hg rename</command>.)</para>
  17.494 +    
  17.495 +      &interaction.rename.divergent.rename.bob;
  17.496 +
  17.497 +      <para id="x_1dd">J'aime à penser qu'il s'agit d'un conflit puisque
  17.498 +        chaque développeur a exprimé différentes intentions au sujet de ce
  17.499 +        que le nom de ce fichier aurait du être.</para>
  17.500 +
  17.501 +      <para id="x_1de">Que pensez-vous qu'il devrait se produire lorsqu'ils
  17.502 +        fusionnent (merge) leurs travaux ? Le comportement actuel de
  17.503 +        Mercurial est qu'il préserve toujours les <emphasis>deux</emphasis>
  17.504 +        noms lorsqu'il fusionne (merge) des changesets qui contiennent des
  17.505 +        renommages divergeants.</para>
  17.506 +
  17.507 +      &interaction.rename.divergent.merge;
  17.508 +
  17.509 +      <para id="x_1df">Remarquez que bien que Mercurial vous avertisse au
  17.510 +        sujet de la divergeance des renommages, il vous laisse faire quelque
  17.511 +        chose au sujet de la divergence après la fusion (merge).</para>
  17.512 +    </sect2>
  17.513 +
  17.514 +    <sect2>
  17.515 +      <title>Renommages et fusion convergeants</title>
  17.516 +
  17.517 +      <para id="x_1e0">Un autre type de conflit de renommage intervient
  17.518 +        lorsque deux personnes choisissent de renommer différents fichiers
  17.519 +        <emphasis>source</emphasis> vers la même
  17.520 +        <emphasis>destination</emphasis>. Dans ce cas, Mercurial exécute la
  17.521 +        machinerie normale de fusion (merge) et vous guide vers une
  17.522 +        solution convenable.</para>
  17.523 +    </sect2>
  17.524 +
  17.525 +    <sect2>
  17.526 +      <title>Autres cas épineux relatifs aux noms</title>
  17.527 +
  17.528 +      <para id="x_1e1">Mercurial possède un bug de longue date dans lequel il
  17.529 +        échoue à traiter une fusion (merge) où un côté a un fichier avec un
  17.530 +        nom donné, alors que l'autre côté possède un répertoire avec le même nom.
  17.531 +        Ceci est documenté dans l'<ulink role="hg-bug"
  17.532 +          url="http://www.selenic.com/mercurial/bts/issue29">issue
  17.533 +          29</ulink>.</para>
  17.534 +
  17.535 +      &interaction.issue29.go;
  17.536 +
  17.537 +    </sect2>
  17.538 +  </sect1>
  17.539 +  <sect1>
  17.540 +    <title>Récupération d'erreurs</title>
  17.541 +
  17.542 +    <para id="x_1e2">Mercurial possède certaines commandes utiles qui vont
  17.543 +      vous aider à récupérer de certaines erreurs communes.</para>
  17.544 +
  17.545 +    <para id="x_1e3">La commande <command role="hg-cmd">hg revert</command>
  17.546 +      vous permet d'annuler les changements que vous avez faits dans votre
  17.547 +      répertoire de travail. Par exemple, si vous faites un <command
  17.548 +        role="hg-cmd">hg add</command> sur un fichier par accident, exécutez
  17.549 +      juste <command role="hg-cmd">hg revert</command> avec le nom du fichier
  17.550 +      que vous avez ajouté et tandis que le fichier ne sera touché d'une
  17.551 +      quelconque manière, il ne sera plus suivi comme ajouté par Mercurial.
  17.552 +      Vous pouvez aussi utiliser la commande <command role="hg-cmd">hg
  17.553 +        revert</command> pour vous débarrasser de modifications erronées
  17.554 +      apportées à un fichier.</para>
  17.555 +
  17.556 +    <para id="x_1e4">Il est utile de se souvenir que la commande <command
  17.557 +        role="hg-cmd">hg revert</command> est utile pour les modifications
  17.558 +      qui n'ont pas encore été committées. Une fois que vous avez committé un
  17.559 +      changement, si vous décidez qu'il s'agissait d'une erreur, vous pouvez
  17.560 +      toujours faire quelque chose à ce sujet, bien que vos options soient
  17.561 +      un peu plus limitées.</para>
  17.562 +
  17.563 +    <para id="x_1e5">Pour plus d'informations au sujet de la commande
  17.564 +      <command role="hg-cmd">hg revert</command>, et des détails sur comment
  17.565 +      traiter les modifications que vous avez déjà committées, référez vous à
  17.566 +      <xref linkend="chap:undo"/>.</para>
  17.567 +  </sect1>
  17.568 +
  17.569 +  <sect1>
  17.570 +    <title>Traiter avec les fusions (merge) malicieuses</title>
  17.571 +
  17.572 +    <para id="x_687">Dans des projets compliqués ou conséquents, il n'est pas
  17.573 +      rare qu'une fusion (merge) de deux changesets finisse par une migraine.
  17.574 +      Supposez qu'il y ait un gros fichier source qui ait été largement édité de
  17.575 +      chaque coté de la fusion (merge) : ceci va inévitablement résulter en
  17.576 +      conflits, dont certains peuvent prendre plusieurs essais pour s'en
  17.577 +      sortir.</para>
  17.578 +
  17.579 +    <para id="x_688">Développons en un cas simple pour voir comment le gérer.
  17.580 +      Nous allons commencer avec un dépôt contenant un fichier, et le
  17.581 +      cloner deux fois.</para>
  17.582 +
  17.583 +    &interaction.ch04-resolve.init;
  17.584 +
  17.585 +    <para id="x_689">Dans un des clones, nous allons modifier le fichier
  17.586 +      d'une façon.</para>
  17.587 +
  17.588 +    &interaction.ch04-resolve.left;
  17.589 +
  17.590 +    <para id="x_68a">Dans un autre, nous allons modifier le fichier
  17.591 +      différemment.</para>
  17.592 +
  17.593 +    &interaction.ch04-resolve.right;
  17.594 +
  17.595 +    <para id="x_68b">Ensuite, nous allons récupérer (pull) chaque ensemble de
  17.596 +      changement dans notre dépôt original.</para>
  17.597 +
  17.598 +    &interaction.ch04-resolve.pull;
  17.599 +
  17.600 +    <para id="x_68c">Nous nous attendons à ce que notre dépôt contienne deux
  17.601 +      "heads".</para>
  17.602 +
  17.603 +    &interaction.ch04-resolve.heads;
  17.604 +
  17.605 +    <para id="x_68d">Normalement, si nous lançons <command role="hg-cmd">hg
  17.606 +        merge</command> à ce point, il nous renverra vers une interface
  17.607 +      utilisateur qui nous permettra de résoudre manuellement les éditions
  17.608 +      conflictuelles sur le fichier <filename>myfile.txt</filename>.
  17.609 +      Cependant, pour simplifier ici les choses dans la présentation, nous
  17.610 +      aimerions plutôt que la fusion (merge) échoue immédiatement. Voici une
  17.611 +      façon de le faire.</para>
  17.612 +
  17.613 +    &interaction.ch04-resolve.export;
  17.614 +
  17.615 +    <para id="x_68e">Nous avons dit au processus de fusion de Mercurial
  17.616 +      d'exécuter la commande <command>false</command> (qui échoue
  17.617 +      immédiatement, à la demande) s'il détecte une fusion (merge) qu'il ne
  17.618 +      peut pas arranger automatiquement.</para>
  17.619 +
  17.620 +    <para id="x_68f">Si nous appelons maintenant <command role="hg-cmd">hg
  17.621 +        merge</command>, il devrait échouer et reporter une erreur.</para>
  17.622 +
  17.623 +    &interaction.ch04-resolve.merge;
  17.624 +
  17.625 +    <para id="x_690">Même si nous ne remarquons pas qu'une fusion (merge) a
  17.626 +      échoué, Mercurial nous empêchera de committer le résultat d'une fusion
  17.627 +      ratée.</para>
  17.628 +
  17.629 +    &interaction.ch04-resolve.cifail;
  17.630 +
  17.631 +    <para id="x_691">Lorsque <command role="hg-cmd">hg commit</command>
  17.632 +      échoue dans ce cas, il suggère que nous utilisons la commande peu
  17.633 +      connue <command role="hg-cmd">hg resolve</command>. Comme d'habitude,
  17.634 +      <command role="hg-cmd">hg help resolve</command> affichera une aide
  17.635 +      sommaire.</para>
  17.636 +
  17.637 +    <sect2>
  17.638 +      <title>États de résolution des fichiers</title>
  17.639 +      <!-- TODO Vérifier traduction : File resolution states -->
  17.640 +
  17.641 +      <para id="x_692">Lorsqu'une fusion intervient, la plupart des fichiers
  17.642 +        vont, la plupart du temps, rester sans modification. Pour chaque
  17.643 +        fichier sur lequel Mercurial doit faire quelque chose, il suit l'état
  17.644 +        de celui-ci.</para>
  17.645 +
  17.646 +      <itemizedlist>
  17.647 +        <listitem><para id="x_693">Un fichier
  17.648 +            <quote><emphasis>resolved</emphasis></quote> a été fusionné
  17.649 +            (merge) avec succès, que ce soit automatiquement par Mercurial ou
  17.650 +            manuellement par une intervention humaine.</para></listitem>
  17.651 +        <listitem><para id="x_694">Un fichier
  17.652 +            <quote><emphasis>unresolved</emphasis></quote> n'a pas été
  17.653 +            fusionné (merge) correctement et a besoin de plus
  17.654 +            d'attention.</para>
  17.655 +        </listitem>
  17.656 +      </itemizedlist>
  17.657 +
  17.658 +      <para id="x_695">Si Mercurial voit un fichier
  17.659 +        <emphasis>quelconque</emphasis> dans un état
  17.660 +        <quote>unresolved</quote> après une fusion (merge), il considère que
  17.661 +        la fusion (merge) a échoué. Heureusement, nous n'avons pas à
  17.662 +        recommencer la procédure à partir du début.</para>
  17.663 +
  17.664 +      <para id="x_696">L'option <option role="hg-opt-resolve">--list</option>
  17.665 +        ou <option role="hg-opt-resolve">-l</option> passée à <command
  17.666 +          role="hg-cmd">hg resolve</command> liste l'état de chaque fichier
  17.667 +        fusionné (merge).</para>
  17.668 +
  17.669 +      &interaction.ch04-resolve.list;
  17.670 +
  17.671 +      <para id="x_697">En sortie de <command role="hg-cmd">hg
  17.672 +          resolve</command>, un fichier <quote>resolved</quote> est marqué avec un
  17.673 +        <literal>R</literal>, alors qu'un fichier <quote>unresolved</quote> est marqué
  17.674 +        d'un <literal>U</literal>.  S'il existe un fichier listé avec un
  17.675 +        <literal>U</literal>, nous savons qu'essayer de committer le résultat
  17.676 +        de la fusion (merge) échouera.</para>
  17.677 +    </sect2>
  17.678 +
  17.679 +    <sect2>
  17.680 +      <title>Résoudre une fusion de fichier</title>
  17.681 +
  17.682 +      <para id="x_698">Nous avons plusieurs options pour changer l'état d'un
  17.683 +        fichier de <quote>unresolved</quote> à <quote>resolved</quote>.
  17.684 +        Le plus habituel est de relancer
  17.685 +        <command role="hg-cmd">hg resolve</command>. Si nous passons les noms
  17.686 +        des fichiers individuels ou des répertoires, ceci retentera la fusion
  17.687 +        de tous les fichiers présents à cet endroit. Nous pouvons aussi
  17.688 +        passer l'option <option role="hg-opt-resolve">--all</option> ou
  17.689 +        <option role="hg-opt-resolve">-a</option> qui tentera de fusionner
  17.690 +        <emphasis>tous</emphasis> les fichiers <quote>unresolved</quote>.</para>
  17.691 +
  17.692 +      <para id="x_699">Mercurial nous laisse aussi modifier la résolution
  17.693 +        d'un fichier directement. Nous pouvons marquer un fichier <quote>resolved</quote>
  17.694 +        en utilisant l'option <option role="hg-opt-resolve">--mark</option>,
  17.695 +        ou <quote>unresolved</quote> en utilisant l'option <option
  17.696 +          role="hg-opt-resolve">--unmark</option>. Ceci nous autorise à
  17.697 +        nettoyer une fusion particulièrement compliquée à la main, et de
  17.698 +        garder un suivi de nos progrès avec chaque fichier pendant que nous
  17.699 +        avançons.</para>
  17.700 +    </sect2>
  17.701 +  </sect1>
  17.702 +
  17.703 +  <sect1>
  17.704 +    <title>Des <quote>diffs</quote> plus utiles</title>
  17.705 +
  17.706 +    <para id="x_6c7">La sortie par défaut de la commande <command
  17.707 +        role="hg-cmd">hg diff</command> est compatible rétrospectivement avec
  17.708 +      la commande régulière <command>diff</command>, mais ceci a quelques
  17.709 +      inconvénients.</para>
  17.710 +
  17.711 +    <para id="x_6c8">Considérez le cas où nous utilisons <command role="hg-cmd">hg
  17.712 +        rename</command> pour renommer un fichier.</para>
  17.713 +
  17.714 +    &interaction.ch04-diff.rename.basic;
  17.715 +
  17.716 +    <para id="x_6c9">La sortie de <command role="hg-cmd">hg diff</command>
  17.717 +      ci-dessus cache le fait que nous avons simplement renommé un fichier.
  17.718 +      La commande <command role="hg-cmd">hg diff</command> accepte l'option
  17.719 +      <option>--git</option> ou <option>-g</option> pour utiliser un nouveau
  17.720 +      format de diff qui montre ces informations sous une forme plus
  17.721 +      expressive.</para>
  17.722 +
  17.723 +    &interaction.ch04-diff.rename.git;
  17.724 +
  17.725 +    <para id="x_6ca">Cette option peut aussi aider avec le cas qui peut être autrement
  17.726 +      perturbant : un fichier qui apparaît comme étant modifié en accord avec
  17.727 +      <command role="hg-cmd">hg status</command>, mais où <command
  17.728 +        role="hg-cmd">hg diff</command> n'affiche rien. Cette situation peut
  17.729 +      survenir si nous changeons les permissions d'exécution du
  17.730 +      fichier.</para>
  17.731 +
  17.732 +    &interaction.ch04-diff.chmod;
  17.733 +
  17.734 +    <para id="x_6cb">La commande normale <command>diff</command> ne fait pas
  17.735 +      attention aux permissions des fichiers, ce qui explique pourquoi
  17.736 +      <command role="hg-cmd">hg diff</command> n'affiche rien du tout par
  17.737 +      défaut. Si nous lui passons l'option <option>-g</option>, ceci nous
  17.738 +      informe de ce qui s'est vraiment passé.</para>
  17.739 +
  17.740 +    &interaction.ch04-diff.chmod.git;
  17.741 +  </sect1>
  17.742 +
  17.743 +  <sect1>
  17.744 +    <title>Quels fichiers suivre et lesquels éviter</title>
  17.745 +
  17.746 +    <para id="x_6cc">Les systèmes de gestion de révisions sont en général
  17.747 +      meilleurs pour gérer les fichiers textes qui sont écrits par les
  17.748 +      humains, comme le code source, où les fichiers ne changent pas
  17.749 +      énormément d'une révision à l'autre. Certains systèmes de gestion de
  17.750 +      révisions centralisés peuvent aussi traiter très convenablement les
  17.751 +      fichiers binaires, tels que les images bitmap.</para>
  17.752 +
  17.753 +    <para id="x_6cd">Par exemple, une équipe de développement de jeux va
  17.754 +      probablement gérer les deux types : ses codes source et tous ses binaires
  17.755 +      (ex. données géométriques, textures, schémas de cartes) dans un système
  17.756 +      de contrôle de révisions.</para>
  17.757 +    <!-- Vérifier la traduction de map layouts que j'ai traduit par schémas
  17.758 +    de cartes -->
  17.759 +
  17.760 +    <para id="x_6ce">Puisqu'il est d'habitude impossible de fusionner (merge)
  17.761 +      deux modifications conflictuelles sur un fichier binaire, les systèmes
  17.762 +      de version centralisés offrent souvent un mécanisme de verrou (lock) qui
  17.763 +      permet à un utilisateur de dire <quote>Je suis la seule personne qui
  17.764 +        peut éditer ce fichier</quote>.</para>
  17.765 +
  17.766 +    <para id="x_6cf">En comparaison avec un système centralisé, un système
  17.767 +      décentralisé de gestion de révision change certains facteurs qui
  17.768 +      guident les décisions sur quels fichiers gérer et comment.</para>
  17.769 +
  17.770 +    <para id="x_6d0">Par exemple, un système distribué de gestion de révisions
  17.771 +      ne peut pas, par sa nature, offrir un système de verrou (lock) sur les
  17.772 +      fichiers. Il n'y a donc pas de mécanisme inclus pour empêcher deux
  17.773 +      personnes de faire des modifications conflictuelles sur un fichier
  17.774 +      binaire. Si vous avez une équipe où plusieurs personnes peuvent souvent
  17.775 +      éditer un fichier binaire, cela ne serait pas une très bonne idée
  17.776 +      d'utiliser Mercurial &emdash;ou tout autre système distribué de gestion
  17.777 +      de révisions&emdash;pour gérer ces fichiers.</para>
  17.778 +
  17.779 +    <para id="x_6d1">Lorsque vous sauvegardez les modifications sur un
  17.780 +      fichier, Mercurial ne sauvegarde d'habitude que les différences entre
  17.781 +      la version précédente et la version actuelle d'un fichier. Pour la
  17.782 +      plupart des fichiers texte, ceci est très efficace. Cependant, certains
  17.783 +      fichiers (en particulier les fichiers binaires) sont construits d'une
  17.784 +      façon que même un petit changement sur un contenu logique résulte sur
  17.785 +      un changement de la plupart des octets du fichier. Par exemple, les
  17.786 +      fichiers compressés sont particulièrement sujets à ce comportement. Si
  17.787 +      les différences entre deux versions successives d'un fichier sont
  17.788 +      toujours très grandes, Mercurial ne sera pas capable de sauvegarder
  17.789 +      l'historique des révisions sur le fichier très efficacement. Ceci peut
  17.790 +      affecter aussi bien les besoins pour la sauvegarde locale que le temps
  17.791 +      nécessaire à cloner le dépôt.</para>
  17.792 +
  17.793 +    <para id="x_6d2">Pour avoir une idée de comment ceci pourrait vous
  17.794 +      affecter en pratique, supposez que nous voulions que Mercurial gère des
  17.795 +      documents OpenOffice. OpenOffice sauvegarde les documents sur le disque
  17.796 +      comme des fichiers compressés zip. Même le fait d'éditer ces fichiers
  17.797 +      d'une seule lettre, changera les bits de la quasi totalité du fichier
  17.798 +      lorsque vous le sauvegarderez. Maintenant, supposez que ce fichier
  17.799 +      fasse une taille de 2 Mo. Puisque la plupart du fichier change à chaque
  17.800 +      fois que vous sauvegardez, Mercurial aura à sauvegarder tous les 2 Mo du
  17.801 +      fichier à chaque commit, alors que de votre point de vue, il n'y a
  17.802 +      que peu de mots qui changent à chaque fois. Un seul fichier
  17.803 +      souvent édité qui n'est pas bien traité par les hypothèses que Mercurial
  17.804 +      fait sur les sauvegardes peut facilement avoir un effet colossal sur la
  17.805 +      taille du dépôt.</para>
  17.806 +
  17.807 +    <para id="x_6d3">Même pire, si vous et quelqu'un d'autre éditez le même
  17.808 +      document OpenOffice sur lequel vous travaillez, il n'y a pas de façon
  17.809 +      utile pour fusionner votre travail. En fait, il n'y a pas de moyen
  17.810 +      utile de montrer que les différences sont faites à partir de votre
  17.811 +      vision des modifications.</para>
  17.812 +
  17.813 +    <para id="x_6d4">Il y a ainsi quelques recommandations claires sur les
  17.814 +      types de fichiers spécifiques avec lesquels faire très
  17.815 +      attention.</para>
  17.816 +
  17.817 +    <itemizedlist>
  17.818 +      <listitem><para id="x_6d5">Les fichier qui sont très gros et
  17.819 +          incompressibles, comme les images ISO de CD-ROM, sont, par
  17.820 +          construction très gros et les cloner à travers un réseau sera très
  17.821 +          long.</para></listitem>
  17.822 +     <!-- TODO : Trouver une meilleure traduction pour : ISO CD-ROM images, will by
  17.823 +     virtue of sheer size make clones over a network very slow. -->
  17.824 +      <listitem><para id="x_6d6">Les fichiers qui changent beaucoup d'une
  17.825 +          révision à l'autre peuvent être très coûteux à sauvegarder si vous
  17.826 +          les éditez fréquemment, de même que les conflits entre deux éditions
  17.827 +          concurrentes peuvent être difficiles à résoudre.</para>
  17.828 +      </listitem>
  17.829 +    </itemizedlist>
  17.830 +  </sect1>
  17.831 +
  17.832 +  <sect1>
  17.833 +    <title>Sauvegardes et miroirs</title>
  17.834 +
  17.835 +    <para id="x_6d7">Puisque Mercurial maintient une copie complète de
  17.836 +      l'historique de chaque clone, toute personne qui utilise Mercurial pour
  17.837 +      collaborer à un projet peut potentiellement agir comme une source de
  17.838 +      sauvegarde si une catastrophe survenait. Si un dépôt central devient
  17.839 +      indisponible, vous pouvez construire un remplaçant en clonant une copie
  17.840 +      du dépôt à partir d'un des contributeurs en récupérant (pull) tous les
  17.841 +      changements qui n'auraient pas été vus par les autres.</para>
  17.842 +
  17.843 +    <para id="x_6d8">Il est simple d'utiliser Mercurial pour construire des
  17.844 +      serveurs hors site de sauvegarde et des miroirs distants. Initiez une
  17.845 +      tâche périodique (ex. via la commande <command>cron</command>) sur un
  17.846 +      serveur distant pour récupérer (pull) les changements de votre dépôt
  17.847 +      distant chaque heure. Ceci sera difficile seulement dans le cas
  17.848 +      improbable où le nombre des dépôts maîtres que vous maintenez change
  17.849 +      souvent, auquel cas vous aurez besoin de faire un peu de scripting pour
  17.850 +      rafraichir la liste des dépôts à sauvegarder.</para>
  17.851 +
  17.852 +    <para id="x_6d9">Si vous exécutez des sauvegardes traditionnelles de
  17.853 +      votre dépôt maître sur bande ou disque, et que vous voulez sauvegarder
  17.854 +      un dépôt nommé <filename>myrepo</filename>, utilisez la commande
  17.855 +      <command>hg clone -U myrepo myrepo.bak</command> pour créer un clone de
  17.856 +      <filename>myrepo</filename> avant de commencer vos backups.
  17.857 +      L'option <option>-U</option> ne crée pas de répertoire de travail après
  17.858 +      que le clone soit accompli, puisque ceci serait superflu et ferait que
  17.859 +      la sauvegarde prenne plus de temps.</para>
  17.860 +
  17.861 +    <para id="x_6da">Si vous voulez ensuite sauvegarder
  17.862 +      <filename>myrepo.bak</filename> au lieu de <filename>myrepo</filename>,
  17.863 +      vous aurez la garantie d'avoir une image (snapshot) cohérente de
  17.864 +      votre dépôt sur lequel un développeur insomniaque n'enverra (push) pas de
  17.865 +      changements en milieu de sauvegarde.</para>
  17.866 +  </sect1>
  17.867 +</chapter>
  17.868 +
  17.869 +<!--
  17.870 +local variables: 
  17.871 +sgml-parent-document: ("00book.xml" "book" "chapter")
  17.872 +end:
  17.873 +-->
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/fr/ch06-collab.xml	Sat Jul 10 06:24:49 2010 +0100
    18.3 @@ -0,0 +1,1595 @@
    18.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
    18.5 +
    18.6 +<chapter id="cha:collab">
    18.7 +  <?dbhtml filename="collaborating-with-other-people.html"?>
    18.8 +  <title>Collaborer avec d'autres personnes</title>
    18.9 +
   18.10 +  <para id="x_44a">Comme tout outil complètement décentralisé, Mercurial
   18.11 +    n'impose pas de politique sur la façon dont les personnes devraient
   18.12 +    travailler ensemble. Cependant, si vous êtes nouveau dans les systèmes de
   18.13 +    gestion de révisions distribués, cela aide d'avoir des outils et exemples
   18.14 +    en tête lorsque vous réfléchissez à de possibles modèles de
   18.15 +    workflow.</para>
   18.16 +  <!--TODO : workflow peut éventuellement être traduit ici par travail -->
   18.17 +
   18.18 +  <sect1>
   18.19 +    <title>Interface web de Mercurial</title>
   18.20 +
   18.21 +    <para id="x_44b">Mercurial possède une interface web puissante qui
   18.22 +      propose plusieurs fonctions utiles.</para>
   18.23 +
   18.24 +    <para id="x_44c">Pour une utilisation intensive, l'interface web vous
   18.25 +      permet de naviguer dans un ou une collection de dépôt. Vous pouvez voir
   18.26 +      l'historique d'un dépôt, examiner chaque modification (commentaires et
   18.27 +      "diffs"), et voir le contenu de chaque répertoire et fichier. Vous
   18.28 +      pouvez même accéder à une vue de l'historique qui vous donne une vue
   18.29 +      graphique de la relation entre les modifications individuelles et les
   18.30 +      fusions (merge).</para>
   18.31 +
   18.32 +    <para id="x_44d">De plus, pour l'utilisation humaine, l'interface web
   18.33 +      fournit des flux Atom et RSS des changements dans un dépôt. Ceci vous
   18.34 +      permet de <quote>souscrire</quote> à un dépôt en utilisant votre
   18.35 +      lecteur de flux favori, et être automatiquement avertis de l'activité
   18.36 +      dans ce dépôt aussi tôt qu'elle change. Je trouve cette fonctionnalité
   18.37 +      bien plus commode que le modèle qui consiste à souscrire à une mailing
   18.38 +      list à laquelle les avertissements sont envoyés, puisque cela demande
   18.39 +      aucune configuration supplémentaire de la part de la personne qui
   18.40 +      publie un dépôt.</para>
   18.41 +
   18.42 +    <para id="x_44e">L'interface web permet aussi aux utilisateurs distants
   18.43 +      de cloner un dépôt, récupérer (pull) les changement à partir de celui
   18.44 +      ci, et (lorsque le serveur est configuré pour l'autoriser) lui envoyer
   18.45 +      (push) des changements. Le protocole de tunnel HTTP de Mercurial
   18.46 +      compresse agressivement les données, ainsi, il fonctionne efficacement,
   18.47 +      même au-dessus des réseaux avec une faible bande passante.</para>
   18.48 +
   18.49 +    <para id="x_44f">La plus simple façon de démarrer avec l'interface
   18.50 +      utilisateur est d'utiliser votre navigateur web pour visiter un dépôt
   18.51 +      existant, tel que le dépôt principal de Mercurial à l'adresse <ulink
   18.52 +        url="http://www.selenic.com/repo/hg">http://www.selenic.com/repo/hg</ulink>.</para>
   18.53 +
   18.54 +    <para id="x_450">Si vous êtes intéressés pour proposer une interface web
   18.55 +      de vos propres dépôts, il y a plusieurs façons de le faire.</para>
   18.56 +    
   18.57 +    <para id="x_69d">La façon la plus simple et la plus rapide pour commencer
   18.58 +      dans un environnement informel est d'utiliser la commande <command
   18.59 +        role="hg-cmd">hg serve</command> qui est la plus adaptée à un service
   18.60 +      à court terme et <quote>léger</quote>. Référez-vous à <xref
   18.61 +        linkend="sec:collab:serve"/> plus bas pour les détails d'utilisation
   18.62 +      de cette commande.</para>
   18.63 +
   18.64 +    <para id="x_69e">Pour des dépôts dont la durée de vie est plus longue, où
   18.65 +      vous voudriez un service accessible en permanence, il existe plusieurs
   18.66 +      services publics d'hébergement qui sont accessibles. Certains sont
   18.67 +      libres et gratuits pour les projets Open Source, alors que d'autres
   18.68 +      offrent un hébergement commercial et payant. Une liste à jour est
   18.69 +      disponible à l'adresse : <ulink
   18.70 +        url="http://www.selenic.com/mercurial/wiki/index.cgi/MercurialHosting">http://www.selenic.com/mercurial/wiki/index.cgi/MercurialHosting</ulink>.</para>
   18.71 +
   18.72 +    <para id="x_6a0">Si vous préférez héberger vos propres dépôts, Mercurial
   18.73 +      possède un support intégré pour plusieurs technologies populaires
   18.74 +      d'hébergement, plus particulièrement CGI (Common Gateway Interface) et
   18.75 +      WSGI (Web Services Gateway Interface). Référez-vous à <xref
   18.76 +        linkend="sec:collab:cgi"/> pour des détails sur la configuration CGI
   18.77 +      et WSGI.</para>
   18.78 +  </sect1>
   18.79 +
   18.80 +  <sect1>
   18.81 +    <title>Modèles de collaboration</title>
   18.82 +
   18.83 +    <para id="x_451">Avec un outil convenablement flexible, prendre des
   18.84 +      décisions sur les workflows est plus un problème d'ingénierie sociale
   18.85 +      qu'un problème technique. Mercurial impose peu de limitations sur
   18.86 +      la façon dont vous pouvez structurer le flux de travail dans un projet,
   18.87 +      donc, c'est à vous et votre groupe de fixer et vivre avec un modèle qui
   18.88 +      convient à vos besoins particuliers.</para>
   18.89 +
   18.90 +    <sect2>
   18.91 +      <title>Facteurs à garder en tête</title>
   18.92 +
   18.93 +      <para id="x_452">L'aspect le plus important de tout modèle que vous
   18.94 +        devez garder en tête est la façon dont il subvient aux besoins et
   18.95 +        capacités des personnes qui l'utiliseront. Ceci pourrait sembler
   18.96 +        évident en soi ; pourtant, vous ne pouvez pas vous permettre de
   18.97 +        l'oublier à un seul moment.</para>
   18.98 +
   18.99 +      <para id="x_453">Une fois, j'ai mis en place un modèle de workflow qui
  18.100 +        m'apparaissait comme parfait, mais il a causé la consternation et des
  18.101 +        conflits au sein de mon équipe de développement. En dépit de mes
  18.102 +        tentatives pour expliquer pourquoi nous avions besoin d'un ensemble
  18.103 +        complexe de branches, et comment les changements devaient couler
  18.104 +        entre eux, certains membres de l'équipe se révoltèrent. Alors qu'ils
  18.105 +        étaient pourtant des personnes sympathiques, ils ne voulaient pas
  18.106 +        prêter attention aux contraintes sur lesquelles nous étions en train
  18.107 +        d'opérer, ou, face aux conséquences de ces contraintes dans les
  18.108 +        détails du modèle que je préconisais.</para>
  18.109 +
  18.110 +      <para id="x_454">Ne balayez pas les problèmes sociaux ou techniques de
  18.111 +        la main. Quelque soit le schéma que vous établirez, vous devriez
  18.112 +        planifier un protocole pour prévenir, ou rapidement vous relever de
  18.113 +        troubles que vous pouvez anticiper. Par exemple, si vous vous
  18.114 +        attendez à avoir une branche pour les changements pas-pour-release,
  18.115 +        vous devriez penser très tôt à la possibilité qu'une personne
  18.116 +        fusionne (merge) accidentellement ces changements avec une branche de
  18.117 +        release. Vous pouvez empécher ce problème particulier en écrivant un
  18.118 +        hook qui prévient les changements d'être fusionnés à partir d'une
  18.119 +        branche inopportune.</para>
  18.120 +    </sect2>
  18.121 +
  18.122 +    <sect2>
  18.123 +      <title>Anarchie informelle</title>
  18.124 +
  18.125 +      <para id="x_455">Je ne voudrais pas suggérer qu'une approche
  18.126 +        <quote>tout peut arriver</quote> comme quelque chose de durable, mais
  18.127 +        il s'agit d'un modèle qui est simple à saisir et qui fonctionne
  18.128 +        parfaitement dans quelques situations inhabituelles.</para>
  18.129 +
  18.130 +      <para id="x_456">Par exemple, beaucoup de projets ont un groupe distant
  18.131 +        de collaborateurs qui ne se rencontre physiquement que très rarement.
  18.132 +        Certains groupes aiment vaincre l'isolation du travail à distance en
  18.133 +        organisant occasionnellement des <quote>sprints</quote>. Dans un
  18.134 +        sprint, des personnes viennent ensemble dans un même
  18.135 +        endroit (la salle de conférence d'une société, la salle de réunion
  18.136 +        d'un hôtel, ce genre d'endroit) et y passent plusieurs jours, plus ou
  18.137 +        moins enfermés, et hackant intensément sur une poignée de
  18.138 +        projets.</para>
  18.139 +
  18.140 +      <para id="x_457">Un "sprint" ou une session de "hacking" dans un café
  18.141 +        sont les endroits parfaits pour utiliser la commande <command
  18.142 +          role="hg-cmd">hg serve</command> puisque <command role="hg-cmd">hg
  18.143 +          serve</command> n'a pas besoin d'une infrastructure extraordinaire
  18.144 +        de serveurs. Vous pouvez commencer avec la commande <command
  18.145 +          role="hg-cmd">hg serve</command> en quelques instants, en lisant <xref
  18.146 +          linkend="sec:collab:serve"/> plus bas  Ensuite, dites simplement à
  18.147 +        la personne à côté de vous que vous exécutez un serveur, envoyez-lui
  18.148 +        l'URL par un message instantané, et vous avez immédiatement un moyen
  18.149 +        simple et rapide de travailler ensemble. Ils peuvent taper votre URL
  18.150 +        dans leur navigateur web et rapidement revoir vos
  18.151 +        changements ; ou ils peuvent récupérer chez vous un bugfix et le
  18.152 +        vérifier ; ou ils peuvent cloner une branche contenant une nouvelle
  18.153 +        fonctionnalité et la tester.</para>
  18.154 +        
  18.155 +      <para id="x_458">Le charme et le problème en faisant les choses ainsi,
  18.156 +        dans un mode ad-hoc est que seules les personnes qui sont au courant
  18.157 +        de vos changements, et de leur emplacement, peuvent les voir. Une
  18.158 +        telle approche informelle ne passe simplement pas à l'échelle au delà
  18.159 +        d'une poignée de personnes, puisque chacun a besoin de connaître
  18.160 +        <emphasis>n</emphasis> différents dépôts à partir des quels récupérer
  18.161 +        les changements (pull).</para>
  18.162 +    </sect2>
  18.163 +
  18.164 +    <sect2>
  18.165 +      <title>Un simple dépôt central</title>
  18.166 +
  18.167 +      <para id="x_459">Pour de plus petits projets qui migrent depuis un
  18.168 +        outil de gestion de révision centralisé, la façon la
  18.169 +        plus simple de commencer est certainement d'avoir un flux de
  18.170 +        changement à partir d'un unique dépôt central. Il s'agit aussi du
  18.171 +        <quote>composant</quote> pour des schémas de workflow plus
  18.172 +        ambitieux.</para>
  18.173 +
  18.174 +      <para id="x_45a">Les contributeurs commencent par cloner une copie de
  18.175 +        ce dépôt. Ils peuvent récupérer les changements à n'importe quel
  18.176 +        moment où ils en ressentent le besoin, et certains (sûrement tous)
  18.177 +        développeurs ont les persmissions qui leur permettent d'envoyer leurs
  18.178 +        modifications (push) en retour lorsqu'elles sont prêtes pour que les
  18.179 +        autres personnes puissent les voir.</para>
  18.180 +
  18.181 +      <para id="x_45b">Dans ce modèle, il peut encore être sensé pour les
  18.182 +        gens de récupérer les changements directement entre eux, sans passer
  18.183 +        par le dépôt central. Considérez le cas où j'ai un bug
  18.184 +        fix provisoire, mais je m'inquiète de savoir si, dans le cas où je le publiais,
  18.185 +        cela ne casserait pas l'arbre des autres contributeurs s'ils la
  18.186 +        récupèreraient. Pour réduire les dommages potentiels, je peux vous
  18.187 +        demander de cloner mon dépôt dans un dépôt temporaire qui vous
  18.188 +        appartient et de le tester. Ceci nous permet de ne pas publier les
  18.189 +        modification potentiellement dangereuses tant qu'elles n'ont pas
  18.190 +        encore été un peu testées.</para>
  18.191 +
  18.192 +      <para id="x_45c">Si une équipe héberge son propre dépôt dans ce type de
  18.193 +        scénario, les personnes qui utilisent habituellement le protocole
  18.194 +        <command>ssh</command> pour envoyer (push) en toute sécurité leurs
  18.195 +        changements au dépôt central, comme docummenté dans <xref
  18.196 +          linkend="sec:collab:ssh"/>. Il est aussi usuel de publier une copie
  18.197 +        en lecture seule du dépôt sur HTTP comme dans <xref
  18.198 +          linkend="sec:collab:cgi"/>. Publier sur HTTP satisfait le besoin
  18.199 +        des personnes qui n'ont pas d'accès en écriture, et ceux qui veulent
  18.200 +        utiliser leur navigateur web pour explorer l'historique du
  18.201 +        dépôt.</para>
  18.202 +    </sect2>
  18.203 +
  18.204 +    <sect2>
  18.205 +      <title>Un dépôt central hébergé</title>
  18.206 +
  18.207 +      <para id="x_6a1">Une chose magnifique au sujet des services
  18.208 +        d'hébergement comme <ulink
  18.209 +          url="http://bitbucket.org/">Bitbucket</ulink> est qu'ils ne gèrent
  18.210 +        pas uniquement les détails minutieux de la configuration du
  18.211 +        serveur, tels que les comptes utilisateurs, l'authentification, les
  18.212 +        protocoles sécurisés, ils fournissent aussi une infrastructure
  18.213 +        additionnelle pour que ce modèle fonctionne
  18.214 +        bien.</para>
  18.215 +
  18.216 +      <para id="x_6a2">Par exemple, un service d'hébergement bien conçu
  18.217 +        laissera les personnes cloner leurs copies d'un dépôt à l'aide d'un
  18.218 +        simple clic. Ceci laisse les personnes travailler dans des espaces
  18.219 +        séparés et partager leurs changements lorsqu'ils sont prêts.</para>
  18.220 +
  18.221 +      <para id="x_6a3">De plus, un bon service d'hébergement laissera les
  18.222 +        personnes communiquer ensemble, par exemple pour dire <quote>Il y a
  18.223 +          des changements prêts pour toi pour relecture dans cet
  18.224 +          arbre</quote>.</para>
  18.225 +        
  18.226 +    </sect2>
  18.227 +
  18.228 +    <sect2>
  18.229 +      <title>Travailler avec plusieurs branches</title>
  18.230 +
  18.231 +      <para id="x_45d">Les projets d'une taille significative ont tendance à
  18.232 +        avancer sur plusieurs fronts en même temps. Dans le cas de logiciel,
  18.233 +        il est commun qu'un projet sorte périodiquement des releases
  18.234 +        officielles. Une release devrait ensuite aller dans le <quote>mode de
  18.235 +          maintenance</quote> pour un moment après sa première publication ;
  18.236 +        les releases de maintenance tendent à contenir seulement des
  18.237 +        corrections de bugs, et non de nouvelles fonctionnalités. En
  18.238 +        parallèle de ces releases de maintenance, une ou plusieurs futures
  18.239 +        releases doivent être en cours de développement. Les gens utilisent
  18.240 +        en général le mot <quote>branche</quote> pour référer à l'une de ces
  18.241 +        nombreuses directions légèrement différentes dans lesquelles le
  18.242 +        développement évolue.</para>
  18.243 +
  18.244 +      <para id="x_45e">Mercurial est particulièrement bien adapté pour gérer
  18.245 +        plusieurs branches simultanées mais non identiques. Chaque
  18.246 +        <quote>direction de développement</quote> peut vivre dans son propre
  18.247 +        dépôt central, et vous pouvez récupérez les changements de l'un ou
  18.248 +        l'autre lorsque le besoin s'en fait sentir. Parce que les dépôts sont
  18.249 +        indépendant les uns des autres, les modifications instables dans une
  18.250 +        branche de développement n'affecteront jamais une branche stable,
  18.251 +        sauf si quelqu'un fusionne (merge) explicitement ces changements dans
  18.252 +        la branche stable.</para>
  18.253 +
  18.254 +      <para id="x_45f">Voici un exemple sur comment cela peut se passer en
  18.255 +        pratique. Disons que vous avez une <quote>branche principale</quote>
  18.256 +        sur un serveur central.</para>
  18.257 +
  18.258 +      &interaction.branching.init;
  18.259 +
  18.260 +      <para id="x_460">Les contributeurs le clonent, y apportent localement
  18.261 +        des modifications, les testent et envoient (push) en retour leurs
  18.262 +        changements.</para>
  18.263 +
  18.264 +      <para id="x_461">Une fois que la branche principale atteint une étape
  18.265 +        assez importante pour une release, vous pouvez utiliser la commande
  18.266 +        <command role="hg-cmd">hg tag</command> pour donner un nom permanent
  18.267 +        à cette étape de révision.</para>
  18.268 +    
  18.269 +      &interaction.branching.tag;
  18.270 +
  18.271 +      <para id="x_462">Disons que du developpement continue sur la
  18.272 +        branche principale.</para>
  18.273 +
  18.274 +      &interaction.branching.main;
  18.275 +
  18.276 +      <para id="x_463">En utilisant le tag enregistré à l'étape importante,
  18.277 +        les gens qui clonent ce dépôt peuvent à tout moment dans le futur
  18.278 +        utiliser la commande <command role="hg-cmd">hg update</command> pour
  18.279 +        avoir une copie du répertoire de travail exactement comme il était
  18.280 +        lorsque cette révision "tag" a été committée.</para>
  18.281 +
  18.282 +      &interaction.branching.update;
  18.283 +
  18.284 +      <para id="x_464">De plus, immédiatement après que la branche principale
  18.285 +        soit taggée, nous pouvons maintenant cloner la branche principale sur
  18.286 +        le serveur vers une nouvelle branche <quote>stable</quote> sur le
  18.287 +        même serveur.</para>
  18.288 +
  18.289 +      &interaction.branching.clone;
  18.290 +
  18.291 +      <para id="x_465">Si nous avons besoin d'effectuer des modifications à
  18.292 +        la branche stable, nous pouvons alors cloner <emphasis>ce</emphasis>
  18.293 +        dépôt, effectuer nos modifications, committer, et envoyer nos
  18.294 +        changements en retour là bas.</para>
  18.295 +
  18.296 +      &interaction.branching.stable;
  18.297 +
  18.298 +      <para id="x_466">Puisque les dépôts Mercurial sont indépendants, et que
  18.299 +        Mercurial ne déplace pas les changements automatiquement, les
  18.300 +        branches stable et principale sont <emphasis>isolées</emphasis> l'une
  18.301 +        de l'autre. Les changements qui sont faits à la branche principale ne
  18.302 +        <quote>fuient</quote> pas vers la branche stable, et vice
  18.303 +        versa.</para>
  18.304 +
  18.305 +      <para id="x_467">Nous allons souvent avoir envie que toutes nos
  18.306 +        correction de bugs sur la branche stable soient reportées sur la
  18.307 +        branche principale. Plutôt que de réécrire une correction de bug pour
  18.308 +        la branche principale, nous pouvons simplement récupérer (pull) et
  18.309 +        fusionner (merge) les changements de la branche stable vers la
  18.310 +        branche principal, et Mercurial se débrouillera pour rapporter ces
  18.311 +        corrections de bugs pour nous.</para>
  18.312 +
  18.313 +      &interaction.branching.merge;
  18.314 +
  18.315 +      <para id="x_468">La branche principale contiendra toujours des
  18.316 +        changements qui ne sont pas dans la branche stable, mais elle
  18.317 +        contiendra aussi les corrections de bugs de la branche stable. La
  18.318 +        branche stable restera non affectée par ces changements, tant qu'ils
  18.319 +        coulent de la branche stable vers la branche principale, et non dans
  18.320 +        l'autre sens.</para>
  18.321 +    </sect2>
  18.322 +
  18.323 +    <sect2>
  18.324 +      <title>Feature branches</title>
  18.325 +<!-- TODO : Branches de fonctionnalité ? -->
  18.326 +      <para id="x_469">Pour de plus gros projets, une façon efficace de gérer
  18.327 +        les changements est de diviser l'équipe en plus petits groupes. Chaque
  18.328 +        groupe a une branche partagée qui lui est attitrée, clonée à partir
  18.329 +        d'une unique branche <quote>principale</quote> utilisée pour le
  18.330 +        projet entier. Les personnes travaillant sur une branche individuelle
  18.331 +        sont typiquement isolées des développements sur les autres
  18.332 +        branches.</para>
  18.333 +
  18.334 +      <figure id="fig:collab:feature-branches">
  18.335 +        <title>Feature branches</title>
  18.336 +        <mediaobject>
  18.337 +          <imageobject><imagedata width="100%" fileref="figs/feature-branches.png"/></imageobject>
  18.338 +          <textobject><phrase>XXX add text</phrase></textobject>
  18.339 +        </mediaobject>
  18.340 +      </figure>
  18.341 +
  18.342 +      <para id="x_46b">Lorsqu'une fonctionnalité particulière est réputée
  18.343 +        pour être dans une forme adaptée, quelqu'un de l'équipe qui s'en occupe
  18.344 +        récupère les changements (pull) à partir de
  18.345 +        la branche principale vers la branche de cette fonctionnalité,
  18.346 +        fusionne (merge) et renvoie (push) le tout vers la branche
  18.347 +        principale.</para>
  18.348 +    </sect2>
  18.349 +
  18.350 +    <sect2>
  18.351 +      <title>Le train des releases</title>
  18.352 +<!-- J'ai laissé train en traduction à train mais peut être que suite, file,
  18.353 +... sont des mots qui conviennent mieux ? À méditer -->
  18.354 +<!-- Je mettrais "suite" -->
  18.355 +
  18.356 +      <para id="x_46c">Certains projets sont organisés comme un
  18.357 +        <quote>train</quote> élémentaire : une release est planifiée tous les
  18.358 +        quelques mois, et, toutes les fonctionnalités disponibles lorsque le
  18.359 +        <quote>train</quote> est prêt à s'arrêter sont autorisées ici.</para>
  18.360 +
  18.361 +      <para id="x_46d">Ce modèle ressemble à travailler avec des branches de
  18.362 +        fonctionnalités. La différence est que lorsqu'une branche de
  18.363 +        fonctionnalité rate le train, quelqu'un de l'équipe qui travaille sur
  18.364 +        cette fonctionnalité récupère (pull) et fusionne (merge) ce qui a été
  18.365 +        ajouté à la release du train dans la branche de la fonctionnalité,
  18.366 +        puis, l'équipe continue son travail au-dessus de cette release afin
  18.367 +        que leur fonctionnalité puisse être ajoutée à la prochaine
  18.368 +        release.</para>
  18.369 +    </sect2>
  18.370 +
  18.371 +    <sect2>
  18.372 +      <title>Le modèle du noyau Linux</title>
  18.373 +
  18.374 +      <para id="x_46e">Le développement du noyau Linux est doté d'une
  18.375 +        structure hiérarchique superficielle, entourée par un nuage de chaos
  18.376 +        apparent. Parce que la plupart des développeurs Linux utilisent
  18.377 +        <command>git</command>, un outil distribué de gestion de révisions
  18.378 +        avec des capacités similaires à celles de Mercurial, il est utile de
  18.379 +        décrire comment le travail se déroule dans cet environnement ; si
  18.380 +        vous aimez ces idées, l'approche se traduit correctement à travers
  18.381 +        les outils.</para>
  18.382 +
  18.383 +      <para id="x_46f">Au centre de la communauté siège Linus Torvalds, le
  18.384 +        créateur de Linux. Il publie un dépôt unique de sources qui est
  18.385 +        considéré comme faisant <quote>autorité</quote> sur l'arborescence
  18.386 +        par la communauté entière de développeurs. Tout le monde peut cloner
  18.387 +        l'arbre de Linus, mais il ne récupère (pull) pas les changements de n'importe quelle arborescence.</para>
  18.388 +
  18.389 +      <para id="x_470">Linus a plusieurs <quote>lieutenants de
  18.390 +          confiance</quote>. Comme règle générale, il récupère (pull) tous
  18.391 +        les changements qu'ils publient, dans la plupart des cas sans même
  18.392 +        relire ces modifications. Certains de ces lieutenants sont
  18.393 +        généralement autorisés à être <quote>mainteneurs</quote>,
  18.394 +        responsables pour un sous-système spécifique du noyau. Si un 
  18.395 +        hacker du noyau veut apporter des modification au sous-système
  18.396 +        qu'il veut voir intégré à l'arbre de Linus, il doit trouver 
  18.397 +        le mainteneur du sous-système, et lui demander de récupérer ses
  18.398 +        changements. Si le mainteneur relit ses changements et les accepte,
  18.399 +        ils seront transmis à Linus le moment venu.</para>
  18.400 +
  18.401 +      <para id="x_471">Les lieutenants individuels ont leur propre approche
  18.402 +        pour relire, accepter et publier les changements ; et pour décider
  18.403 +        quand les apporter à Linus. De plus, il y a plusieurs branches
  18.404 +        connues que les personnes utilisent pour différentes choses.
  18.405 +        Par exemple, quelques personnes maintiennent des dépôts
  18.406 +        <quote>stables</quote> de leurs versions du noyau, pour lesquels ils
  18.407 +        apportent des corrections critiques lorsque nécessaire. Certains
  18.408 +        mainteneurs publient plusieurs arbres : l'un pour les changements
  18.409 +        expérimentaux, l'un pour les changements qu'ils vont faire remonter,
  18.410 +        etc. D'autres ne publient qu'un unique arbre.</para>
  18.411 +
  18.412 +      <para id="x_472">Ce modèle a deux caractéristiques remarquables. La
  18.413 +        première est qu'il s'agit de <quote>pull seulement</quote>. Vous
  18.414 +        devez demander, convaincre, ou mendier auprès d'un autre développeur
  18.415 +        pour prendre vos modifications, puisqu'il n'y a vraisemblablement pas
  18.416 +        d'arbre où plus d'une personne peut envoyer des changements (push), et
  18.417 +        qu'il n'y a pas de possibilité d'envoyer des changements (push) vers
  18.418 +        un arbre que quelqu'un d'autre contrôle.</para>
  18.419 +
  18.420 +      <para id="x_473">La seconde est que c'est basé sur la réputation et
  18.421 +        l'acclamation. Si vous êtes un inconnu, Linus va probablement ignorer
  18.422 +        vos changements sans même répondre. Cependant, un mainteneur de
  18.423 +        sous-système les relira probablement, et les acceptera sûrement s'ils
  18.424 +        passent ses critères d'acceptation. Plus vous enverrez du
  18.425 +        <quote>bon</quote> code à un mainteneur, et plus celui-ci aura
  18.426 +        confiance en votre jugement et acceptera vos changements. Si vous
  18.427 +        êtes bien connu et maintenez une branche ancienne pour quelque chose
  18.428 +        que Linus n'a pas encore accepté, les gens avec un intérêt similaire
  18.429 +        devraient récupérer vos changements régulièrement pour rester à jour
  18.430 +        vis-à-vis de votre travail.</para>
  18.431 +
  18.432 +      <para id="x_474">La réputation et l'acclamation ne nécessite pas de
  18.433 +        système croisé ou de limites <quote>entre les gens</quote>. Si vous
  18.434 +        êtes respectés mais que vous êtes un hacker spécialisé dans la
  18.435 +        sauvegarde, et que vous tentez de corriger un bug réseau, ce
  18.436 +        changement recevra un examen approfondi de la part du mainteneur
  18.437 +        responsable du réseau comparable à celui d'un total étranger.</para>
  18.438 +
  18.439 +      <para id="x_475">Pour les personnes qui viennent d'un projet dont
  18.440 +        le milieu est plus ordonné, le processus chaotique de
  18.441 +        développement du noyau Linux en comparaison apparaît souvent totalement
  18.442 +        dément. C'est sujet aux caprices d'individus ;
  18.443 +        des personnes font des changements considérables quand ils les
  18.444 +        jugent appropriés ; et l'allure du développement est
  18.445 +        ahurissante. Et pourtant, Linux est un bout de logiciel d'une grande
  18.446 +        réussite et bien considéré.</para>
  18.447 +    </sect2>
  18.448 +
  18.449 +    <sect2>
  18.450 +      <title>Collaboration pull seulement versus pull partagé</title>
  18.451 +
  18.452 +      <para id="x_476">Une source perpétuelle de heurts dans la communauté
  18.453 +        opensource est de savoir si un modèle de développement où les
  18.454 +        personnes ne peuvent que récupérer (pull) les changements d'autres est
  18.455 +        <quote>meilleur</quote> que celui dans lequel de multiples personnes peuvent
  18.456 +        envoyer (push) leurs changements vers un dépôt partagé.</para>
  18.457 +
  18.458 +      <para id="x_477">Typiquement, les partisans du modèle push
  18.459 +        partagé utilisent des outils qui renforcent activement cette
  18.460 +        approche. Si vous utilisez un outil centralisé de gestion de révision
  18.461 +        comme Subversion, il n'y a pas la possibilité de choisir quel modèle
  18.462 +        utiliser : l'outil vous fournit un push partagé, et si vous voulez
  18.463 +        faire quelque chose d'autre, vous avez à changer votre propre
  18.464 +        approche à la base (comme appliquer les patchs manuellement).</para>
  18.465 +
  18.466 +      <para id="x_478">Un bon outil de gestion distribuée de révisions doit
  18.467 +        supporter les deux modèles. Vous et vos collaborateurs pouvez ensuite
  18.468 +        structurer la façon dont vous travaillez ensemble en vous basant sur
  18.469 +        vos besoins et vos préférences, et non sur les contorsions que vos
  18.470 +        outils vous forcent à effectuer.</para>
  18.471 +    </sect2>
  18.472 +    <sect2>
  18.473 +      <title>Lorsque la collaboration rencontre la gestion de branches</title>
  18.474 +
  18.475 +      <para id="x_479">Lorsque vous et votre équipe configurez des dépôts
  18.476 +        partagés et commencez à propager vos changement dans tous les sens
  18.477 +        entre les dépôts locaux et partagés, vous commencez à être face à un
  18.478 +        défi connexe, mais un peu différent : celui de gérer les
  18.479 +        multiples directions vers lesquelles votre équipe pourrait aller au
  18.480 +        même moment. Même si ce sujet est intimement lié à la façon dont
  18.481 +        votre équipe collabore, il est suffisement dense pour mériter un
  18.482 +        traitement à part dans <xref linkend="chap:branch"/>.</para>
  18.483 +    </sect2>
  18.484 +  </sect1>
  18.485 +
  18.486 +  <sect1>
  18.487 +    <title>Le côté technique du partage</title>
  18.488 +
  18.489 +    <para id="x_47a">Le reste de ce chapitre est consacré à la question du
  18.490 +      partage des changements avec vos collaborateurs.</para>
  18.491 +  </sect1>
  18.492 +
  18.493 +  <sect1 id="sec:collab:serve">
  18.494 +    <title>Partage informel avec <command role="hg-cmd">hg
  18.495 +    serve</command></title>
  18.496 +
  18.497 +    <para id="x_47b">La commande <command role="hg-cmd">hg serve</command> de
  18.498 +      Mercurial est magnifiquement conçue pour un environnement de petit
  18.499 +      groupe, soudé et rapide. Elle fournit aussi un très bon moyen d'avoir
  18.500 +      un sentiment de l'utilisation des commandes Meruciral sur un
  18.501 +      réseau.</para>
  18.502 +
  18.503 +    <para id="x_47c">Exécutez <command role="hg-cmd">hg serve</command> à
  18.504 +      l'intérieur d'un dépôt et en moins d'une seconde, cela mettra en place
  18.505 +      un serveur HTTP spécialisé ; qui va accepter les connexions de tout
  18.506 +      client, et servir les données pour ce dépôt jusqu'à ce que vous 
  18.507 +      l'arrêtiez. Toute personne qui connaît l'URL du serveur que vous venez
  18.508 +      de démarrer, peut ensuite utiliser un navigateur web ou Mercurial pour
  18.509 +      lire les données de ce dépôt. Une URL pour une instance exécutée de 
  18.510 +      <command role="hg-cmd">hg serve</command> sur un ordinateur portable
  18.511 +      ressemblera vraisemblablement à
  18.512 +      <literal>http://my-laptop.local:8000/</literal>.</para>
  18.513 +
  18.514 +    <para id="x_47d">La commande <command role="hg-cmd">hg serve</command>
  18.515 +      <emphasis>n'</emphasis>est <emphasis>pas</emphasis> un serveur web
  18.516 +      générique. Il ne peut faire que deux choses : </para>
  18.517 +    <itemizedlist>
  18.518 +      <listitem><para id="x_47e">Autoriser les personnes à explorer
  18.519 +          l'historique du dépôt qu'il rend accessible, à partir d'un
  18.520 +          navigateur web normal.</para>
  18.521 +      </listitem>
  18.522 +      <listitem><para id="x_47f">Discuter à travers le protocole de
  18.523 +          communication de Mercurial, ainsi, les personnes peuvent exécuter <command
  18.524 +            role="hg-cmd">hg clone</command> ou <command role="hg-cmd">hg
  18.525 +            pull</command> sur les changements de ce dépôt.</para>
  18.526 +      </listitem></itemizedlist>
  18.527 +    <para id="x_480">En particulier, <command role="hg-cmd">hg serve</command>
  18.528 +      ne permettra pas aux utilisateurs distants de
  18.529 +      <emphasis>modifier</emphasis> votre dépôt. C'est destiné à une
  18.530 +      utilisation en lecture seule.</para>
  18.531 +
  18.532 +    <para id="x_481">Si vous commencez avec Mercurial, il n'y a rien qui vous
  18.533 +      empêche d'utiliser <command role="hg-cmd">hg serve</command> pour
  18.534 +      publier un dépôt sur votre ordinateur, utilisez ensuite des commandes
  18.535 +      telles que <command role="hg-cmd">hg clone</command>, <command
  18.536 +        role="hg-cmd">hg incoming</command>, et ainsi de suite pour parler à
  18.537 +      ce serveur comme si ce dépôt était hébergé à distance. Ceci peut vous
  18.538 +      aider à rapidement familiarisé avec les commandes sur les dépôts
  18.539 +      hébergés sur un réseau.</para>
  18.540 +
  18.541 +    <sect2>
  18.542 +      <title>Quelques choses à garder à l'esprit</title>
  18.543 +
  18.544 +      <para id="x_482">Puisque il fournit un accès en lecture sans
  18.545 +        authentification à tous les clients, vous devriez utiliser la
  18.546 +        commande <command role="hg-cmd">hg serve</command> dans un
  18.547 +        environnement où vous ne vous inquiétez pas ou vous avez
  18.548 +        tout contrôle sur qui peut avoir accès au réseau et récupérer les
  18.549 +        données de votre dépôt.</para>
  18.550 +
  18.551 +      <para id="x_483">La commande <command role="hg-cmd">hg serve</command>
  18.552 +        ne sait rien sur un quelconque firewall que vous auriez
  18.553 +        installé sur votre système ou réseau. Elle ne peut pas détecter ou
  18.554 +        contrôler votre logiciel de pare-feu. Si d'autre personnes ont la
  18.555 +        possibilité de dialoguer avec une instance de <command
  18.556 +          role="hg-cmd">hg serve</command> la seconde chose que vous devriez
  18.557 +        faire (<emphasis>après</emphasis> être sûr qu'ils utilisent l'URL
  18.558 +        correcte) est de vérifier la configuration de votre firewall.</para>
  18.559 +
  18.560 +      <para id="x_484">Par défaut, <command role="hg-cmd">hg serve</command>
  18.561 +        écoute pour les connexions entrantes sur le port 8000. Si un autre
  18.562 +        processus est déjà en train d'écouter sur le port que vous voulez
  18.563 +        écouter, vous pouvez spécifier un port différent sur lequel écouter à
  18.564 +        l'aide de l'option <option role="hg-opt-serve">-p</option>.</para>
  18.565 +
  18.566 +      <para id="x_485">Normalement, lorsque <command role="hg-cmd">hg
  18.567 +          serve</command> se lance, il n'affiche aucune sortie, ce qui peut
  18.568 +        être un peu énervant. Si vous voulez une confirmation que tout s'est
  18.569 +        déroulé correctement, et connaître l'URL que vous devriez fournir à
  18.570 +        vos collaborateurs, démarrez avec l'option <option
  18.571 +          role="hg-opt-global">-v</option>.</para>
  18.572 +    </sect2>
  18.573 +  </sect1>
  18.574 +
  18.575 +  <sect1 id="sec:collab:ssh">
  18.576 +    <title>Utiliser le protocole Secure Shell (ssh)</title>
  18.577 +
  18.578 +    <para id="x_486">Vous pouvez récupérer (pull) ou envoyer (push) des
  18.579 +      changements de façon sécurisé au dessus d'une connexion utilisant le
  18.580 +      protocole Secure Shell (<literal>ssh</literal>). Pour l'utiliser avec
  18.581 +      succès, vous pourriez avoir à faire un peu de configuration du côté
  18.582 +      client ou serveur.</para>
  18.583 +
  18.584 +    <para id="x_487">Si vous n'êtes pas familiers avec ssh, c'est le nom de
  18.585 +      la commande et d'un protocole réseau qui vous permet d'établir une
  18.586 +      communication sécurisée avec un autre ordinateur. Pour l'utiliser avec
  18.587 +      Mercurial, vous allez configurer un ou plusieurs comptes utilisateurs
  18.588 +      sur un serveur, comme ça, les utilisateurs distants peuvent se connecter et
  18.589 +      exécuter les commandes.</para>
  18.590 +
  18.591 +    <para id="x_488">(Si vous <emphasis>êtes</emphasis> familiers avec ssh,
  18.592 +      vous allez probablement trouver quelques-unes des informations qui
  18.593 +      suivent élémentaires par nature.)</para>
  18.594 +
  18.595 +    <sect2>
  18.596 +      <title>Comment lire et écrire des URLs ssh</title>
  18.597 +
  18.598 +      <para id="x_489">Une URL ssh a tendance à ressembler à ceci :</para>
  18.599 +      <programlisting>ssh://bos@hg.serpentine.com:22/hg/hgbook</programlisting>
  18.600 +      <orderedlist>
  18.601 +        <listitem><para id="x_48a">Le préfixe
  18.602 +            <quote><literal>ssh://</literal></quote> dit à Mercurial
  18.603 +            d'utiliser le protocole ssh.</para>
  18.604 +        </listitem>
  18.605 +        <listitem><para id="x_48b">Le composant
  18.606 +            <quote><literal>bos@</literal></quote> indique que le nom
  18.607 +            d'utilisateur à connecter sur le serveur. Vous pouvez le laisser
  18.608 +            vide si le nom d'utilisateur sur le serveur distant est le même
  18.609 +            que localement.</para>
  18.610 +        </listitem>
  18.611 +        <listitem><para id="x_48c">La partie
  18.612 +            <quote><literal>hg.serpentine.com</literal></quote> donne le nom
  18.613 +            d'hôte du serveur sur lequel se connecter.</para>
  18.614 +        </listitem>
  18.615 +        <listitem><para id="x_48d">Le <quote>:22</quote> identifie le numéro
  18.616 +            de port où se connecter au serveur. Le port par défaut est 22,
  18.617 +            donc vous avez besoin de spécifier ceci que si vous
  18.618 +            <emphasis>n'</emphasis>utilisez <emphasis>pas</emphasis> le port
  18.619 +            22.</para>
  18.620 +        </listitem>
  18.621 +        <listitem><para id="x_48e">Le reste de l'URL est le chemin local du
  18.622 +            dépôt sur le serveur.</para></listitem></orderedlist>
  18.623 +    
  18.624 +      <para id="x_48f">Il y a beaucoup de risque de confusion sur le
  18.625 +        chemin du composant d'une URL ssh puisqu'il n'y a pas de façon
  18.626 +        standard pour les outils de l'interpréter. Certains programmes se
  18.627 +        comportent différemment des autres lorsqu'ils traitent ces chemins. Il
  18.628 +        ne s'agit pas d'une situation idéale, mais ce n'est pas prêt de
  18.629 +        changer. Lisez les prochains paragraphes avec attention.</para>
  18.630 +
  18.631 +      <para id="x_490">Mercurial traite le chemin vers un dépôt sur le
  18.632 +        serveur comme relatif au répertoire personnel de l'utilisateur sur le
  18.633 +        serveur distant. Par exemple, si un utilisateur
  18.634 +        <literal>foo</literal> sur le serveur a un répertoire personnel
  18.635 +        <filename class="directory">/home/foo</filename>, alors l'URL ssh qui
  18.636 +        contient un composant chemin de <filename
  18.637 +          class="directory">bar</filename> réfère en
  18.638 +        <emphasis>réalité</emphasis> au répertoire <filename
  18.639 +          class="directory">/home/foo/bar</filename>.</para>
  18.640 +
  18.641 +      <para id="x_491">Si vous voulez spécifier un chemin relatif au
  18.642 +        répertoire personnel d'un autre utilisateur, vous pouvez préciser un
  18.643 +        chemin qui commence à l'aide du caractère tilde suivi du nom de
  18.644 +        l'utilisateur (appelons le <literal>otheruser</literal>),
  18.645 +        ainsi.</para>
  18.646 +      <programlisting>ssh://server/~otheruser/hg/repo</programlisting>
  18.647 +
  18.648 +      <para id="x_492">Et si vous voulez vraiment spécifier un chemin
  18.649 +        <emphasis>absolu</emphasis> sur le serveur, débutez le composant
  18.650 +        chemin par deux slashs comme dans cet exemple.</para>
  18.651 +      <programlisting>ssh://server//absolute/path</programlisting>
  18.652 +    </sect2>
  18.653 +
  18.654 +    <sect2>
  18.655 +      <title>Trouver un client ssh pour votre système</title>
  18.656 +
  18.657 +      <para id="x_493">La plupart des systèmes du type Unix arrivent avec
  18.658 +        OpenSSH préinstallé. Si vous utilisez un tel système, utilisez
  18.659 +        <literal>which ssh</literal> pour trouver où la commande
  18.660 +        <command>ssh</command> est installée (il s'agit généralement de
  18.661 +        <filename class="directory">/usr/bin</filename>). Dans le cas peu
  18.662 +        probable où il ne serait pas présent, regarder la documentation de
  18.663 +        votre système pour voir comment l'installer.</para>
  18.664 +
  18.665 +      <para id="x_494">Sous Windows, le paquet TortoiseHg est livré avec
  18.666 +        une version de l'excellente commande <command>plink</command> de
  18.667 +        Simon Tatham, et ne devrait pas avoir besoin de plus de
  18.668 +        configuration.</para>
  18.669 +    </sect2>
  18.670 +
  18.671 +    <sect2>
  18.672 +      <title>Créer une paire de clef</title>
  18.673 +
  18.674 +      <para id="x_499">Pour éviter d'avoir à chaque fois taper un mot de
  18.675 +        passe lorsque vous utilisez votre client ssh, je recommande 
  18.676 +        de créer une paire de clefs.</para>
  18.677 +
  18.678 +      <tip>
  18.679 +        <title>Les paires de clefs ne sont pas obligatoires</title>
  18.680 +      
  18.681 +        <para id="x_6a4">Mercurial ne sait rien du tout de l'authentification
  18.682 +          de ssh ou de la paire de clefs. Vous pouvez, si vous le désirez,
  18.683 +          ignorer sans risque cette section et la suivante jusqu'à ce que
  18.684 +          vous soyez fatigué de constamment retaper des mots de passe
  18.685 +          ssh.</para>
  18.686 +      </tip>
  18.687 +
  18.688 +      <itemizedlist>
  18.689 +        <listitem> <para id="x_6a5">Sur un système de type Unix, la commande
  18.690 +            <command>ssh-keygen</command> fera l'affaire.</para></listitem>
  18.691 +        <listitem> <para id="x_6a6">Sous Windows, si vous utilisez
  18.692 +            TortoiseHg, vous devriez avoir besoin de télécharger la commande
  18.693 +            nommée <command>puttygen</command> à partir du <ulink
  18.694 +              url="http://www.chiark.greenend.org.uk/~sgtatham/putty">site
  18.695 +              web de PuTTY</ulink> pour créer une paire de clefs.  Référez-vous
  18.696 +               à <ulink
  18.697 +              url="http://the.earth.li/~sgtatham/putty/0.60/htmldoc/Chapter8.html#pubkey-puttygen">la
  18.698 +              documentation <command>puttygen</command></ulink> pour les
  18.699 +            détails sur l'utilisation de cette commande.</para></listitem>
  18.700 +      </itemizedlist>
  18.701 +
  18.702 +      <para id="x_49a">Lorsque vous créez une paire de clefs, il est
  18.703 +        habituellement <emphasis>hautement</emphasis> recommandé de la
  18.704 +        protéger avec un mot de passe. (Le seul moment où vous pourriez ne
  18.705 +        pas devoir le faire est lorsque vous utilisez le protocole ssh pour
  18.706 +        des tâches automatisées sur un réseau sécurisé.)</para>
  18.707 +
  18.708 +      <para id="x_49b">Le simple fait de créer une paire de clefs n'est
  18.709 +        cependant pas suffisant. Vous aurez besoin d'ajouter la clef publique
  18.710 +        à l'ensemble des clefs autorisées pour tout utilisateur que vous
  18.711 +        utilisez pour vous connecter à distance. Pour les serveurs utilisant
  18.712 +        OpenSSh (la grande majorité), ceci voudra dire d'ajouter la clef
  18.713 +        publique à la liste dans un fichier appelé <filename
  18.714 +          role="special">authorized_keys</filename> dans leur répertoire
  18.715 +        <filename role="special" class="directory">.ssh</filename>.</para>
  18.716 +
  18.717 +      <para id="x_49c">Sur un système de type Unix, votre clef publique aura
  18.718 +        l'extension <filename>.pub</filename>. Si vous utilisez la commande
  18.719 +        <command>puttygen</command> sous Windows, vous pouvez sauvegarder la
  18.720 +        clef publique dans un fichier que vous choisissez ou la copier à
  18.721 +        partir de la fenêtre qui apparait directement dans le fichier
  18.722 +        <filename role="special">authorized_keys</filename>.</para>
  18.723 +    </sect2>
  18.724 +    <sect2>
  18.725 +      <title>Utiliser un agent d'authentification</title>
  18.726 +
  18.727 +      <para id="x_49d">Un agent d'authentification est un démon qui
  18.728 +        enregistre les mots de passe en mémoire (il oublira ainsi les mots de
  18.729 +        passe si vous vous déconnectez et reconnectez). Un client ssh sera averti
  18.730 +        si un tel agent est en fonctionnement, et lui demandera un mot de
  18.731 +        passe. S'il n'y a pas d'agent en fonctionnement, ou si l'agent ne
  18.732 +        connaît pas le mot de passe nécessaire, vous aurez à taper votre mot
  18.733 +        de passe chaque fois que Mercurial tente de communiquer avec un
  18.734 +        serveur en votre nom (ex. lorsque vous faite un pull ou un push 
  18.735 +        de changements).</para>
  18.736 +
  18.737 +      <para id="x_49e">L'inconvénient de sauvegarder les mots de passe dans
  18.738 +        un agent est qu'il est possible pour un attaquant bien préparé de
  18.739 +        retrouver le mot de passe clair, dans certains cas, même si votre
  18.740 +        système a été redémarré. Vous devriez vous faire votre propre
  18.741 +        jugement pour savoir si ce risque est acceptable. Ceci vous exempte
  18.742 +        certainement d'un tas de répétitions.</para>
  18.743 +
  18.744 +      <itemizedlist>
  18.745 +        <listitem> <para id="x_49f">Sur les systèmes de type Unix, l'agent
  18.746 +            est appelé <command>ssh-agent</command>, et est souvent lancé
  18.747 +            automatiquement pour vous lorsque vous vous connectez. Vous aurez
  18.748 +            besoin d'utiliser la commande <command>ssh-add</command> pour
  18.749 +            ajouter des mots de passe à l'entrepôt de l'agent.</para>
  18.750 +        </listitem>
  18.751 +        <listitem>
  18.752 +          <para id="x_6a7">Sous Windows, si vous utilisez TortoiseHg, la
  18.753 +            commande <command>pageant</command> agit comme un agent. Comme
  18.754 +            avec <command>puttygen</command>, vous aurez besoin de <ulink
  18.755 +              url="http://www.chiark.greenend.org.uk/%7Esgtatham/putty/download.html">télécharger
  18.756 +              <command>pageant</command></ulink> à partir du site web de
  18.757 +            PuTTY et lire <ulink
  18.758 +              url="http://the.earth.li/~sgtatham/putty/0.60/htmldoc/Chapter9.html#pageant">sa
  18.759 +              documentation</ulink>.  La commande <command>pageant</command>
  18.760 +            ajoute une icône à votre zone de notification (à droite de la barre
  18.761 +            de tâches) qui vous permettra de
  18.762 +            gérer les mots de passe stockés.</para></listitem>
  18.763 +          <!-- TODO : J'ai traduit system tray par barre des tâches, mais ne
  18.764 +          conaissant pas windows, je ne suis pas sûr du nom réel. A corriger
  18.765 +          le cas échéant ! -->
  18.766 +          <!-- J'ai précisé avec ce que j'ai trouvé sur Wikipedia -->
  18.767 +      </itemizedlist>
  18.768 +    </sect2>
  18.769 +
  18.770 +    <sect2>
  18.771 +      <title>Configurer correctement le serveur</title>
  18.772 +<!-- TODO : comment traduire "passphrase" ? -->
  18.773 +      <para id="x_4a0">Parce que ssh peut être délicat à installer si c'est nouveau pour vous,
  18.774 +      différentes choses peuvent mal se passer. Ajouter Mercurial
  18.775 +      en plus, et il y a beaucoup plus de possibilités pour s'arracher les cheveux.
  18.776 +      La plupart de ces problèmes potentiels apparaissent du côté serveur, non
  18.777 +      du côté client. La bonne nouvelle est qu'une fois que vous avez
  18.778 +      une configuration qui marche, elle continue habituellement de fonctionner
  18.779 +      indéfiniment.</para>
  18.780 +
  18.781 +      <para id="x_4a1">Avant d'essayer de faire communiquer Mercurial avec un serveur ssh,
  18.782 +      il est mieux de s'assurer que vous pouvez d'abord utiliser le
  18.783 +      <command>ssh</command> normal ou la commande <command>putty</command>
  18.784 +      pour communiquer avec le serveur. Si vous vous heurtez a des problèmes en utilisant
  18.785 +      ces commandes directement, Mercurial ne fonctionnera sûrement pas. Pire,
  18.786 +      il cachera le problème sous-jacent. Chaque fois que vous voulez
  18.787 +      déboguer des problèmes de Mercurial liés à ssh, vous devriez d'abord
  18.788 +      vous assurer que les commandes du client ssh fonctionne d'abord,
  18.789 +      <emphasis>avant</emphasis> de vous inquiéter à propos de savoir si 
  18.790 +      il y a un problème avec Mercurial.</para>
  18.791 +
  18.792 +      <para id="x_4a2">La première chose à s'assurer du côté serveur est que
  18.793 +      vous puissiez réellement vous connecter depuis une autre machine. Si vous
  18.794 +      ne pouvez pas utiliser <command>ssh</command> ou <command>putty</command>
  18.795 +      pour vous connecter, le message d'erreur que vous aurez peut vous donner quelques indices
  18.796 +      sur ce qui ne fonctionne pas. Les problèmes les plus courants sont les suivants.</para>
  18.797 +      <itemizedlist>
  18.798 +	<listitem><para id="x_4a3">Si vous avez une erreur <quote>connexion refusée</quote>,
  18.799 +    soit il n'y a pas de démon SSH tournant sur le serveur, soit il est inaccessible à cause
  18.800 +    de la configuration du pare-feu.</para>
  18.801 +	</listitem>
  18.802 +	<listitem><para id="x_4a4">Si vous avez une erreur <quote>no route to host</quote>,
  18.803 +    soit vous avez une adresse incorrecte pour le serveur
  18.804 +    soit un pare-feu sérieusement verrouillé qui ne veut pas du tout reconnaître son existence.</para>
  18.805 +	</listitem>
  18.806 +	<listitem><para id="x_4a5">Si vous avez une erreur <quote>permission denied</quote>,
  18.807 +    vous pouvez avoir mal tapé le nom d'utilisateur sur le serveur,
  18.808 +    ou vous pouvez avoir mal tapé votre passphrase de clé ou 
  18.809 +    le mot de passe d'utilisateur distant.</para>
  18.810 +	</listitem></itemizedlist>
  18.811 +      <para id="x_4a6">En résumé, si vous avez des difficultés pour communiquer avec
  18.812 +      le démon ssh du serveur, d'abord assurez-vous qu'il y en a un en fonctionnement.
  18.813 +      Sur beaucoup de systèmes, il est installé, mais désactivé, par
  18.814 +      défaut. Une fois que c'est fait, vous devriez alors
  18.815 +      vérifier que le pare-feu du serveur est configuré pour permettre
  18.816 +      les connexions entrantes sur le port que le démon ssh écoute
  18.817 +      (habituellement 22). Ne vous inquiétez pas à propos de possibilités plus exotiques
  18.818 +      de mauvaise configuration tant que vous n'avez pas vérifier ces deux premières.</para>
  18.819 +
  18.820 +      <para id="x_4a7">Si vous utilisez un agent d'authentification du côté client
  18.821 +      pour stocker les passphrases de vos clés, vous devriez être capable de 
  18.822 +      vous connecter au serveur sans avoir à entrer une passphrase ou
  18.823 +      un mot de passe. Si vous devez entrer une passphrase, il y a
  18.824 +      quelques coupables possibles.</para>
  18.825 +      <itemizedlist>
  18.826 +	<listitem><para id="x_4a8">Vous pouvez avoir oublié d'utiliser
  18.827 +	    <command>ssh-add</command> ou <command>pageant</command>
  18.828 +	    pour stocker la passphrase.</para>
  18.829 +	</listitem>
  18.830 +	<listitem><para id="x_4a9">Vous pouvez avoir stocké la passphrase
  18.831 +    pour une mauvaise clé.</para>
  18.832 +	</listitem></itemizedlist>
  18.833 +      <para id="x_4aa">Si vous devez entrer le mot de passe d'utilisateur distant,
  18.834 +      il y a quelques autres problèmes possibles à vérifier.</para>
  18.835 +      <itemizedlist>
  18.836 +	<listitem><para id="x_4ab">Soit le répertoire utilisateur ou le
  18.837 +    répertoire <filename role="special" class="directory">.ssh</filename>
  18.838 +    peut avoir des droits trop tolérants. Comme résultat,
  18.839 +    le démon ssh n'aura pas confiance ni ne lira le fichier
  18.840 +	    <filename role="special">authorized_keys</filename>.
  18.841 +        Par exemple, un <quote>group-writable home</quote> ou un répertoire <filename
  18.842 +	      role="special" class="directory">.ssh</filename>
  18.843 +          sera souvent la cause de ce symptôme.</para>
  18.844 +          <!-- TODO : comment traduire "group-writable home" ? -->
  18.845 +	</listitem>
  18.846 +	<listitem><para id="x_4ac">Le fichier <filename
  18.847 +	      role="special">authorized_keys</filename> de l'utilisateur peut avoir
  18.848 +          un problème. Si quelqu'un d'autre que l'utilisateur possède ou peut écrire
  18.849 +          dans ce fichier, le démon ssh n'aura pas confiance ni ne le lira.</para>
  18.850 +	</listitem></itemizedlist>
  18.851 +
  18.852 +      <para id="x_4ad">Dans le monde idéal, vous devriez être capable d'exécuter la 
  18.853 +      commande suivante avec succès, et elle devrait imprimer exactement
  18.854 +      une ligne en sortie, la date et l'heure actuelle.</para>
  18.855 +      <programlisting>ssh myserver date</programlisting>
  18.856 +<!-- TODO : comment traduire "junk" ? -->
  18.857 +      <para id="x_4ae">Si, sur votre serveur, vous avec des scripts de connexion qui
  18.858 +      impriment des bannières ou d'autre "junk" même en fonctionnement non-interactif
  18.859 +      comme ici, vous devriez corriger cela avant de continuer, comme cela elles 
  18.860 +      imprimeront des sorties que si elles fonctionnent en mode interactif.
  18.861 +      Autrement, au minimum, ces bannières encombreront les sorties de Mercurial. 
  18.862 +      Pire, elles pourront potentiellement causer des problèmes avec des commandes
  18.863 +      Mercurial exécutées à distance. Mercurial essaye de détecter et d'ignorer des
  18.864 +      bannières dans des sessions <command>ssh</command> non-interactives, mais il
  18.865 +      n'est pas infaillible. (Si
  18.866 +      vous éditez vos scripts de connexion sur votre serveur, la manière habituelle
  18.867 +      de voir si un script de connexion fonctionne dans un shell interactif
  18.868 +      est de vérifier le code de retour de la commande
  18.869 +	<literal>tty -s</literal>.)</para>
  18.870 +
  18.871 +      <para id="x_4af">Lorsque vous avez vérifié que le bon vieux ssh fonctionne
  18.872 +      avec votre serveur, l'étape suivante est de s'assurer que Mercurial fonctionne
  18.873 +      sur le serveur. La commande suivant devrait fonctionnement correctement :</para>
  18.874 +
  18.875 +      <programlisting>ssh myserver hg version</programlisting>
  18.876 +
  18.877 +      <para id="x_4b0">Si vous voyez un message d'erreur au lieu de la sortie normale de
  18.878 +      <command role="hg-cmd">hg version</command>, c'est habituellement
  18.879 +      parce que vous n'avez pas installé Mercurial dans <filename
  18.880 +	  class="directory">/usr/bin</filename>.  Ne vous inquiétez pas si 
  18.881 +      c'est le cas ; vous n'avez pas besoin de le faire. Mais vous devriez
  18.882 +      vérifiez quelques problèmes possibles.</para>
  18.883 +      <itemizedlist>
  18.884 +	<listitem><para id="x_4b1">Mercurial est-il vraiment installé sur le 
  18.885 +    serveur ? Je sais que cela semble évident, mais cela vaut la peine
  18.886 +    de vérifier !</para>
  18.887 +	</listitem>
  18.888 +	<listitem><para id="x_4b2">Peut-être que le chemin de recherche de votre shell
  18.889 +    (habituellement défini via la variable d'environnement<envar>PATH</envar>)
  18.890 +    est simplement mal configuré.</para>
  18.891 +	</listitem>
  18.892 +	<listitem><para id="x_4b3">Peut-être que votre variable d'environnement
  18.893 +    <envar>PATH</envar> pointe vers l'endroit de l'exécutable
  18.894 +	    <command>hg</command> uniquement si la session est
  18.895 +	    interactive.  Ceci peut arriver si vous mettez le chemin dans 
  18.896 +        le mauvais script de connextion. Regardez la documentation de 
  18.897 +        votre shell pour les détails.</para>
  18.898 +	</listitem>
  18.899 +	<listitem><para id="x_4b4">La variable d'environnement <envar>PYTHONPATH</envar>
  18.900 +    peut devoir contenir le chemin vers les modules Python de Mercurial.
  18.901 +    Elle peut ne pas être définie ; elle peut être incorrecte ; ou elle peut être
  18.902 +    définie que si la connexion est interactive.</para>
  18.903 +	</listitem></itemizedlist>
  18.904 +
  18.905 +      <para id="x_4b5">Si vous pouvez exécuter <command role="hg-cmd">hg version</command>
  18.906 +      sur une connexion ssh, bravo ! Vous avez réglé les problèmes du serveur
  18.907 +      et du client. Vous devriez maintenant être capable d'utiliser Mercurial pour
  18.908 +      accéder à des dépôts hébergés par cet utilisateur sur ce serveur.
  18.909 +      Si vous avez des problèmes avec Mercurial et ssh à ce moment,
  18.910 +      essayer d'utiliser l'option <option role="hg-opt-global">--debug</option>
  18.911 +      pour obtenir une image plus claire de ce qui se passe.</para>
  18.912 +    </sect2>
  18.913 +    <sect2>
  18.914 +      <title>Utilisation de la compression avec ssh</title>
  18.915 +
  18.916 +      <para id="x_4b6">Mercurial ne comprime pas les données quand il utilise
  18.917 +      le protocole ssh, car le protocole ssh peut comprimer de manière transparente
  18.918 +      les données. De plus, le comportement par défaut des clients ssh est de 
  18.919 +	<emphasis>ne pas</emphasis> demander de la compression.</para>
  18.920 +
  18.921 +      <para id="x_4b7">Sur n'importe quel réseau autre qu'un réseau local rapide (même
  18.922 +      un réseau sans fil), utiliser la compression améliore significativement la
  18.923 +      vitesse des opérations réseau de Mercurial. Par exemple, sur un WAN,
  18.924 +      quelqu'un a mesuré que la compression a réduit la durée pour cloner un dépôt
  18.925 +      particulièrement grand de 51 minutes à 17 minutes.</para>
  18.926 +
  18.927 +      <para id="x_4b8">Les deux commandes <command>ssh</command> et <command>plink</command>
  18.928 +	acceptent une option <option role="cmd-opt-ssh">-C</option> qui active
  18.929 +	la compression. Vous pouvez facilement éditer votre <filename
  18.930 +	  role="special">~/.hgrc</filename> pour activer la compression pour
  18.931 +	tous les usages de Mercurial du protocole ssh. Voici comment faire
  18.932 +    pour la commande habituelle <command>ssh</command> sur des systèmes Unix-like,
  18.933 +	par exemple.</para>
  18.934 +      <programlisting>[ui]
  18.935 +ssh = ssh -C</programlisting>
  18.936 +<!-- TODO comment traduire "Unix-like" ? -->
  18.937 +      <para id="x_4b9">Si vous utilisez <command>ssh</command> sur un
  18.938 +	système Unix-like, vous pouvez le configurer pour toujours utiliser
  18.939 +    la compression lors de la connexion avec votre serveur. Pour cela, éditer
  18.940 +    votre fichier <filename role="special">.ssh/config</filename>
  18.941 +	(qui peut ne pas encore exister), comme suit.</para>
  18.942 +
  18.943 +      <programlisting>Host hg
  18.944 +  Compression yes
  18.945 +  HostName hg.example.com</programlisting>
  18.946 +
  18.947 +      <para id="x_4ba">Ceci définit un alias pour le nom d'hôte,
  18.948 +	<literal>hg</literal>. Quand vous utilisez ce nom d'hôte sur la
  18.949 +    ligne de commande <command>ssh</command> ou dans une URL Mercurial en
  18.950 +    protocole <literal>ssh</literal>, 
  18.951 +	<command>ssh</command> se connectera à
  18.952 +	<literal>hg.example.com</literal> et utilisera la compression. Ceci
  18.953 +	vous offre à la fois un nom plus court à taper et la compression,
  18.954 +    chacun est une bonne chose en lui-même.</para>
  18.955 +    </sect2>
  18.956 +  </sect1>
  18.957 +
  18.958 +  <sect1 id="sec:collab:cgi">
  18.959 +    <title>Service sur HTTP grâce à CGI</title>
  18.960 +
  18.961 +    <para id="x_6a8">La manière la plus simple d'héberger un ou plusieurs dépôts de
  18.962 +    manière permanente est d'utiliser un serveur web et le support CGI de Mercurial.
  18.963 +    </para>
  18.964 +
  18.965 +    <para id="x_4bb">En fonction de votre ambition, configurer l'interface CGI
  18.966 +    de Mercurial peut vous prendre de quelques instants à plusieurs heures.</para>
  18.967 +
  18.968 +    <para id="x_4bc">Nous commencerons par le plus simple des exemples, et travailler
  18.969 +    vers une configuration plus complexe. Même pour le cas le plus élémentaire,
  18.970 +    vous devrez certainement lire et modifier la configuration de votre serveur web.</para>
  18.971 +
  18.972 +    <note>
  18.973 +      <title>Grande tolérance à la peine exigée</title>
  18.974 +
  18.975 +      <para id="x_4bd">Configurer un serveur web est une activité complexe,
  18.976 +      délicate, et dépendant fortement du système. Il m'est absolument impossible
  18.977 +      de vous donner les instructions qui couvriront tous les cas que vous
  18.978 +      rencontrerez. Faites comme bon vous semblera en suivant les sections ci-dessous.
  18.979 +      Soyez prêts à faire beaucoup d'erreurs, et à consacrer beaucoup de temps à lire
  18.980 +      les logs d'erreur de votre serveur.</para>
  18.981 +
  18.982 +      <para id="x_6a9">Si vous n'avez pas un estomac solide pour tordre des 
  18.983 +      configurations à maintes reprises, ou un besoin irrésistible d'héberger vos
  18.984 +      propres services, vous pourriez vouloir essayer un des services d'hébergement
  18.985 +      public que j'ai mentionné plus tôt.</para>
  18.986 +    </note>
  18.987 +
  18.988 +    <sect2>
  18.989 +      <title>Liste de contrôle de la configuration du serveur web</title>
  18.990 +
  18.991 +      <para id="x_4be">Avant de continuer, prenez quelques instants pour contrôler
  18.992 +      quelques aspects de l'installation de votre système.</para>
  18.993 +
  18.994 +      <orderedlist>
  18.995 +	<listitem><para id="x_4bf">Avez-vous un serveur web installé ?
  18.996 +    Mac OS X et quelques distributions Linux sont fournis avec
  18.997 +	    Apache, mais beaucoup d'autres systèmes peuvent ne pas avoir de serveur web
  18.998 +        installé.</para>
  18.999 +	</listitem>
 18.1000 +	<listitem><para id="x_4c0">Si vous avez un serveur web installé, fonctionne-t-il
 18.1001 +    réellement ? Sur la plupart des systèmes, même si il y a en un, il sera désactivité
 18.1002 +    par défaut.</para>
 18.1003 +	</listitem>
 18.1004 +	<listitem><para id="x_4c1">Votre serveur est-il configuré pour vous permettre de 
 18.1005 +    faire fonctionner des programmes CGI dans le répertoire où vous prévoyer de le faire ?
 18.1006 +    La plupart des serveurs désactivent explicitement l'aptitude à faire fonctionner des 
 18.1007 +    programmes CGI.</para>
 18.1008 +	</listitem></orderedlist>
 18.1009 +
 18.1010 +      <para id="x_4c2">Si vous n'avez pas de serveur web installé, et n'avez pas 
 18.1011 +      d'expérience solide dans la configuration Apache, vous devriez envisager
 18.1012 +      d'utiliser le serveur web <literal>lighttpd</literal> au lieu
 18.1013 +	d'Apache.  Apache a une réputation bien méritée de configuration baroque et 
 18.1014 +    déroutante. Bien que <literal>lighttpd</literal> ait moins de fonctions
 18.1015 +    qu'Apache, la plupart de celles-ci ne sont pas utiles pour servir
 18.1016 +    des dépôts Mercurial. Et <literal>lighttpd</literal> est incontestablement
 18.1017 +	<emphasis>beaucoup</emphasis> plus facile pour débuter
 18.1018 +    qu'Apache.</para>
 18.1019 +    </sect2>
 18.1020 +
 18.1021 +
 18.1022 +    <sect2>
 18.1023 +      <title>Configuration élémentaire de CGI</title>
 18.1024 +
 18.1025 +      <para id="x_4c3">Sur les systèmes Unix-like, il est habituel pour les utilisateurs d'avoir un
 18.1026 +      sous-répertoire nommé quelque chose comme <filename
 18.1027 +	  class="directory">public_html</filename> dans leur "home
 18.1028 +	directory", à partir duquel ils peuvent servir des pages web. Un fichier
 18.1029 +    appelé <filename>foo</filename> dans ce répertoire sera
 18.1030 +	accessible à une URL de la forme
 18.1031 +	<literal>http://www.example.com/username/foo</literal>.</para>
 18.1032 +
 18.1033 +      <para id="x_4c4">Pour commencer, trouver le script <filename
 18.1034 +	  role="special">hgweb.cgi</filename> qui devrait être
 18.1035 +	présent dans votre installation de Mercurial. Si vous ne pouvez pas trouver
 18.1036 +	rapidement une copie locale sur votre système, téléchargez-le simplement
 18.1037 +    du dépôt maître de Mercurial à <ulink
 18.1038 +	  url="http://www.selenic.com/repo/hg/raw-file/tip/hgweb.cgi">http://www.selenic.com/repo/hg/raw-file/tip/hgweb.cgi</ulink>.</para>
 18.1039 +
 18.1040 +      <para id="x_4c5">Vous devrez copier ce script dans votre répertoire <filename
 18.1041 +	  class="directory">public_html</filename>, et vous assurez qu'il est
 18.1042 +	exécutable.</para>
 18.1043 +      <programlisting>cp .../hgweb.cgi ~/public_html
 18.1044 +chmod 755 ~/public_html/hgweb.cgi</programlisting>
 18.1045 +      <para id="x_4c6">L'argument <literal>755</literal> de
 18.1046 +	<command>chmod</command> est un peu plus général que de rendre
 18.1047 +    le script exécutable: il garantit que le script est
 18.1048 +	exécutable par n'importe qui, et que les permissions d'écriture pour le <quote>group</quote> et les 
 18.1049 +	<quote>other</quote> <emphasis>ne</emphasis> sont 
 18.1050 +	<emphasis>pas</emphasis> définies.  Si vous laissez ces 
 18.1051 +	permissions d'écriture activées, le sous-système <literal>suexec</literal>
 18.1052 +	d'Apache refuserait probablement d'exécuter le script. En fait,
 18.1053 +	<literal>suexec</literal> insiste aussi pour que le
 18.1054 +	<emphasis>répertoire</emphasis> dans lequel le script réside
 18.1055 +	ne soit pas inscriptible par d'autres.</para>
 18.1056 +      <programlisting>chmod 755 ~/public_html</programlisting>
 18.1057 +
 18.1058 +      <sect3 id="sec:collab:wtf">
 18.1059 +	<title>Que pourrait-il <emphasis>éventuellement</emphasis> mal
 18.1060 +	  se passer ?</title>
 18.1061 +
 18.1062 +	<para id="x_4c7">Une fois que vous avez copié le script CGI à sa place,
 18.1063 +      allez dans un navigateur et essayer d'ouvrir l'URL
 18.1064 +      <literal>http://myhostname/~myuser/hgweb.cgi</literal>,
 18.1065 +	  <emphasis>mais</emphasis> attendez-vous à un échec immédiat.
 18.1066 +	  Il y a une forte probabilité que d'essayer de visiter cette URL
 18.1067 +      échouera, et il y a beaucoup de raisons possibles pour cela. En
 18.1068 +      fait, vous devrez probablement trébucher sour pratiquement chacun des
 18.1069 +      erreurs possibles ci-dessous, donc lisez attentivement. Les 
 18.1070 +      problèmes suivants sont tous ceux que j'ai rencontré sur un système
 18.1071 +      tournant Fedora 7, avec une nouvelle installation d'Apache, et un 
 18.1072 +      compte utilisateur que j'avais créé spécialement pour réaliser cet
 18.1073 +      exercice.</para>
 18.1074 +<!-- TODO comment traduire "per-user" ? -->
 18.1075 +	<para id="x_4c8">Votre serveur web peut avoir des répertoires "per-user" désactivés.
 18.1076 +	  Si vous utilisez Apache, cherchez une directive <literal>UserDir
 18.1077 +      </literal>dans votre fichier de configuration. Si il n'y en a pas,
 18.1078 +      les répertoires "per-user" seront désactivés. Si il en existe un,
 18.1079 +      mais que sa valeur est <literal>disabled</literal>, alors
 18.1080 +	  les répertoires "per-user" seront désactivés. Autrement, la
 18.1081 +	  chaîne de caractères après <literal>UserDir</literal> donne le nom du
 18.1082 +	  sous-répertoire qu'Apache regardera dans votre répertoire "home",
 18.1083 +      par exemple<filename
 18.1084 +	    class="directory">public_html</filename>.</para>
 18.1085 +
 18.1086 +	<para id="x_4c9">Vos permissions d'accès de fichier peuvent être trop restrictives.
 18.1087 +	  Le serveur web doit être capable de traverser votre répertoire home
 18.1088 +      et les répertoires sous votre répertoire <filename
 18.1089 +	    class="directory">public_html</filename>, et 
 18.1090 +	  de lire les fichiers sous le dernier aussi. Voici une recette rapide
 18.1091 +      pour vous aider à rendre vos permissions plus adéquates.</para>
 18.1092 +	<programlisting>chmod 755 ~
 18.1093 +find ~/public_html -type d -print0 | xargs -0r chmod 755
 18.1094 +find ~/public_html -type f -print0 | xargs -0r chmod 644</programlisting>
 18.1095 +
 18.1096 +	<para id="x_4ca">L'autre possibilité avec les permissions est que vous
 18.1097 +      pourriez obtenir une fenêtre complètement vide lorsque vous essayez de
 18.1098 +      charger le script. Dans ce cas, c'est probablement que vos permissions
 18.1099 +      d'accès sont <emphasis>trop permissives</emphasis>. Le sous-système
 18.1100 +      <literal>suexec</literal> d'Apache n'exécute pas un script
 18.1101 +	  qui est inscriptible par le groupe ou le monde, par exemple.</para>
 18.1102 +
 18.1103 +	<para id="x_4cb">Votre serveur web peut être configuration pour refuser
 18.1104 +      l'exécution de programmes CGI dans votre répertoire web "per-user".
 18.1105 +      Voici la configuration "per-user" par défaut d'Apache pour mon
 18.1106 +      système Fedora.</para>
 18.1107 +
 18.1108 +	&ch06-apache-config.lst;
 18.1109 +
 18.1110 +	<para id="x_4cc">Si vous trouvez un groupe qui ressemble à
 18.1111 +	  <literal>Directory</literal> dans votre configuration Apache,
 18.1112 +      la directive à regarder est
 18.1113 +	  <literal>Options</literal>. Ajoutez <literal>ExecCGI</literal>
 18.1114 +	  à la fin de cette liste si cela manque, et redémarrer le serveur
 18.1115 +	  web.</para>
 18.1116 +
 18.1117 +	<para id="x_4cd">Si vous trouvez qu'Apache vous donne le texte du script 
 18.1118 +	  CGI au lie de l'exécuter, vous pouvez avoir besoin soit de
 18.1119 +      décommenter (si déjà présent) ou d'ajouter une directive telle que
 18.1120 +      celle-ci.</para>
 18.1121 +	<programlisting>AddHandler cgi-script .cgi</programlisting>
 18.1122 +<!-- TODO comment traduire "system-wide" ? -->
 18.1123 +	<para id="x_4ce">La possibilité suivante est que vous pourriez
 18.1124 +      obtenir une trace coloré Python prétendant qu'il ne peut pas 
 18.1125 +      importer un module relatif à <literal>mercurial</literal>. Ceci est 
 18.1126 +      réellement un progrès ! Le serveur est maintenant capable d'exécuter
 18.1127 +      votre script CGI. Cette erreur arrive probablement si vous exécutez
 18.1128 +      une installation privée de Mercurial, au lieu d'une version
 18.1129 +      "system-wide". Souvenez-vous que le serveur web fait fonctionner
 18.1130 +      le programme CGI sans aucune des variables d'environnement que vous
 18.1131 +      considérez comme certaines dans une session interactive. Si
 18.1132 +      cette erreur vous arrive, éditez une copie de <filename
 18.1133 +	    role="special">hgweb.cgi</filename> et suivez les indications
 18.1134 +        à l'intérieur de celui-ci pour corriger votre variable
 18.1135 +        d'environnement <envar>PYTHONPATH</envar>.</para>
 18.1136 +
 18.1137 +	<para id="x_4cf">Pour finir, vous êtes <emphasis>certain</emphasis>
 18.1138 +      d'avoir une autre trace colorée Python : celle-ci
 18.1139 +	  se plaindra de ne pas pouvoir trouver <filename
 18.1140 +	    class="directory">/path/to/repository</filename>.  Éditez
 18.1141 +	  votre script <filename role="special">hgweb.cgi</filename>
 18.1142 +	  et remplacez la chaîne de caractères <filename
 18.1143 +	    class="directory">/path/to/repository</filename> par le
 18.1144 +	  chemin complet du dépôt que vous voulez servir.</para>
 18.1145 +
 18.1146 +	<para id="x_4d0">À ce moment-là, quand vous essayez de recharger la page,
 18.1147 +      vous devriez avoir une jolie vue HTML de l'historique de votre dépôt.
 18.1148 +      Ouf !</para>
 18.1149 +      </sect3>
 18.1150 +
 18.1151 +      <sect3>
 18.1152 +	<title>Configurer lighttpd</title>
 18.1153 +
 18.1154 +	<para id="x_4d1">Pour être exhaustif dans mes expériences, j'ai essayé
 18.1155 +      de configurer le serveur web <literal>lighttpd</literal> devenu
 18.1156 +      populaire pour servir le même dépôt que celui décrit plus haut
 18.1157 +      avec Apache. J'ai déjà surmonter tous les problèmes décrits avec
 18.1158 +      Apache, beaucoup ne sont pas spécifique à un serveur.
 18.1159 +      Comme résultat, j'étais pratiquement sûr que mes permissions de
 18.1160 +      fichiers et de répertoires étaient bonnes, et que mon script
 18.1161 +      <filename role="special">hgweb.cgi</filename> était correctement
 18.1162 +	  édité.</para>
 18.1163 +
 18.1164 +	<para id="x_4d2">Une fois qu'Apache tournait, avoir 
 18.1165 +	  <literal>lighttpd</literal> pour servir le dépôt était immédiat
 18.1166 +      (en d'autres mots, même si vous essayez d'utiliser
 18.1167 +	  <literal>lighttpd</literal>, vous devriez lire la section
 18.1168 +      Apache). J'ai d'abord dû éditer la section
 18.1169 +	  <literal>mod_access</literal> de son fichier de configuration
 18.1170 +      pour activer <literal>mod_cgi</literal> et
 18.1171 +	  <literal>mod_userdir</literal>, les deux étaient désactivés
 18.1172 +      par défaut sur mon système. J'ai ensuite ajouté quelques lignes à
 18.1173 +      la fin du fichier de configuration, pour ajouter ces modules.</para>
 18.1174 +	<programlisting>userdir.path = "public_html"
 18.1175 +cgi.assign = (".cgi" =&gt; "" )</programlisting>
 18.1176 +	<para id="x_4d3">Un fois ceci fait, <literal>lighttpd</literal> a
 18.1177 +      fonctionné immédiatemment pour moi. Si j'avais configuré
 18.1178 +	  <literal>lighttpd</literal> avant Apache, je serais sans doute
 18.1179 +      tombé dans beaucoup des mêmes problèmes de configuration
 18.1180 +      "system-level" comme j'ai eu avec Apache.  De plus, j'ai
 18.1181 +	  trouvé <literal>lighttpd</literal> être notablemen plus facile à
 18.1182 +	  configurer qu'Apache, même si j'ai utilisé Apache depuis plus
 18.1183 +      d'une décennie, et ceci était ma première expérience avec
 18.1184 +	  <literal>lighttpd</literal>.</para>
 18.1185 +      </sect3>
 18.1186 +    </sect2>
 18.1187 +
 18.1188 +    <sect2>
 18.1189 +      <title>Partager plusieurs dépôts avec un seul script CGI</title>
 18.1190 +
 18.1191 +      <para id="x_4d4">Le script <filename role="special">hgweb.cgi</filename>
 18.1192 +	vous laisse seulement publier un seul dépôt, ce qui est une limitation
 18.1193 +    ennuyeuse. Si vous voulez publier plus d'un dépôt
 18.1194 +    sans "wracking yourself" avec de multiples copies du même
 18.1195 +    script, chacune avec un nom différent, un meilleur choix est d'utiliser
 18.1196 +	le script <filename role="special">hgwebdir.cgi</filename>.</para>
 18.1197 +
 18.1198 +      <para id="x_4d5">La procédure pour configurer <filename
 18.1199 +	  role="special">hgwebdir.cgi</filename> est seulement un peu plus
 18.1200 +	  compliquée que pour <filename
 18.1201 +	  role="special">hgweb.cgi</filename>. D'abord, vous devez obtenir
 18.1202 +	une copie du script. Si vous n'en avez pas une sous la main, vous pouvez
 18.1203 +    télécharger une copie depuis le dépôt maître de Mercurial à <ulink
 18.1204 +	  url="http://www.selenic.com/repo/hg/raw-file/tip/hgwebdir.cgi">http://www.selenic.com/repo/hg/raw-file/tip/hgwebdir.cgi</ulink>.</para>
 18.1205 +
 18.1206 +      <para id="x_4d6">Vous aurez besoin de copier ce script dans votre
 18.1207 +      répertoire <filename class="directory">public_html</filename>, et
 18.1208 +	vous assurer qu'il est exécutable.</para>
 18.1209 +
 18.1210 +      <programlisting>cp .../hgwebdir.cgi ~/public_html
 18.1211 +chmod 755 ~/public_html ~/public_html/hgwebdir.cgi</programlisting>
 18.1212 +
 18.1213 +<!-- TODO comment traduire "out of the way" ? -->
 18.1214 +      <para id="x_4d7">Avec une configuration élémentaire "out of the way", essayez de
 18.1215 +	visiter <literal>http://myhostname/~myuser/hgwebdir.cgi</literal>
 18.1216 +	dans votre navigateur. Il devrait afficher une liste vide
 18.1217 +    de dépôts. Si vous obtenez une fenêtre vide ou un message
 18.1218 +    d'erreur, essayer de parcourir la liste de problèmes 
 18.1219 +    potentiels dans <xref
 18.1220 +	  linkend="sec:collab:wtf"/>.</para>
 18.1221 +
 18.1222 +      <para id="x_4d8">Le script <filename role="special">hgwebdir.cgi</filename>
 18.1223 +	se base sur un fichier de configuration externe. Par défaut,
 18.1224 +    il cherche un fichier nommé <filename
 18.1225 +	  role="special">hgweb.config</filename> dans le même répertoire
 18.1226 +      que lui. Vous devrez créer ce fichier, et le rendre
 18.1227 +      lisible par tout le monde. Le format de ce fichier est semblable à
 18.1228 +      un fichier Windows <quote>ini</quote>, comme compris par un module
 18.1229 +      Python <literal>ConfigParser</literal>
 18.1230 +	<citation>web:configparser</citation>.</para>
 18.1231 +
 18.1232 +      <para id="x_4d9">La façon la plus facile de configurer <filename
 18.1233 +	  role="special">hgwebdir.cgi</filename> est avec une section
 18.1234 +	appellée <literal>collections</literal>.  Ceci publiera automatiquement
 18.1235 +	<emphasis>chaque</emphasis> dépôt sous les répertoires
 18.1236 +	que vous citez. La section devrait ressembler à ceci :</para>
 18.1237 +      <programlisting>[collections]
 18.1238 +/my/root = /my/root</programlisting>
 18.1239 +
 18.1240 +      <para id="x_4da">Mercurial interprète ceci en regardant le nom du répertoire
 18.1241 +	sur la partie <emphasis>droite</emphasis> du signe
 18.1242 +	<quote><literal>=</literal></quote> ; en trouvant les répertoires
 18.1243 +    dans cette hiérarchie de répertoires ; et en utilisant le texte sur la
 18.1244 +    <emphasis>gauche</emphasis> pour retirer le texte correspondant des
 18.1245 +    noms qu'il listera réellement dans l'interface web.
 18.1246 +    Le restant du chemin après que ce "stripping" a été réalisé est 
 18.1247 +    appelé un <quote>chemin virtuel (virtual path)</quote>.</para>
 18.1248 +
 18.1249 +      <para id="x_4db">Étant donné l'exemple ci-dessus, si vous avez un
 18.1250 +      dépôt dont le chemin local est <filename
 18.1251 +	  class="directory">/my/root/this/repo</filename>, le script CGI
 18.1252 +	retirera le début <filename
 18.1253 +	  class="directory">/my/root</filename> du nom, et
 18.1254 +	publiera le dépôt avec un chemin virtuel <filename
 18.1255 +	  class="directory">this/repo</filename>. Si l'URL de base de 
 18.1256 +	notre script CGI est
 18.1257 +	<literal>http://myhostname/~myuser/hgwebdir.cgi</literal>, 
 18.1258 +	l'URL complète URL pour ce dépôt sera
 18.1259 +	<literal>http://myhostname/~myuser/hgwebdir.cgi/this/repo</literal>.</para>
 18.1260 +
 18.1261 +      <para id="x_4dc">Si nous remplaçons<filename
 18.1262 +	  class="directory">/my/root</filename> sur la gauche de
 18.1263 +	cet exemple par <filename
 18.1264 +	  class="directory">/my</filename>, alors <filename
 18.1265 +	  role="special">hgwebdir.cgi</filename> retirera seulement
 18.1266 +	<filename class="directory">/my</filename> du nom du dépôt,
 18.1267 +	et nous donnera comme chemin virtuel <filename
 18.1268 +	  class="directory">root/this/repo</filename> au lieu de
 18.1269 +	<filename class="directory">this/repo</filename>.</para>
 18.1270 +
 18.1271 +      <para id="x_4dd">Le script <filename role="special">hgwebdir.cgi</filename>
 18.1272 +	cherchera récursivement dans chaque répertoire listé dans la 
 18.1273 +    section	<literal>collections</literal> de son fichier de configuration,
 18.1274 +	mais, il <literal>ne</literal> cherchera <literal>pas</literal> recursivement
 18.1275 +    dans les répertoires qu'il trouvera.</para>
 18.1276 +
 18.1277 +      <para id="x_4de">Le mécanisme de <literal>collections</literal> rend facile
 18.1278 +      la publication de plusieurs dépôts de façon <quote>fire and
 18.1279 +	  forget</quote>.  Vous devez seulement installer le script CGI
 18.1280 +	et le fichier de configuration une seule fois.  Après, vous pouvez
 18.1281 +    publier ou "dépublier" un dépôt n'importe quand en le déplaçant simplement
 18.1282 +    dans, ou hors de la hiérarchie de répertoire dans laquelle vous avez
 18.1283 +    indiqué à <filename role="special">hgwebdir.cgi</filename> de
 18.1284 +	regarder.</para>
 18.1285 +
 18.1286 +      <sect3>
 18.1287 +	<title>Spécifier explicitement quels dépôts publier</title>
 18.1288 +
 18.1289 +	<para id="x_4df">En plus du mécanisme de <literal>collections</literal>,
 18.1290 +	  le script <filename
 18.1291 +	    role="special">hgwebdir.cgi</filename> vous permet
 18.1292 +      de publier une liste spécifique de dépôts. Pour cela,
 18.1293 +      créez une section <literal>paths</literal>, avec un contenu de
 18.1294 +      la forme suivante.</para>
 18.1295 +	<programlisting>[paths]
 18.1296 +repo1 = /my/path/to/some/repo
 18.1297 +repo2 = /some/path/to/another</programlisting>
 18.1298 +
 18.1299 +	<para id="x_4e0">Dans ce cas, le chemin virtuel (le composant qui
 18.1300 +    apparaîtra dans une URL) est sur la gauche de chaque
 18.1301 +    définition, tandis que le chemin vers le dépôt est sur la
 18.1302 +    droite. Notez qu'il n'y a pas besoin de relation 
 18.1303 +    entre le chemin virtuel que vous choisissez et
 18.1304 +    l'emplacement d'un dépôt dans votre système de fichiers.</para>
 18.1305 +
 18.1306 +	<para id="x_4e1">Si vous le souhaitez, vous pouvez utiliser
 18.1307 +    les mécanismes de 
 18.1308 +	  <literal>collections</literal> et de <literal>paths</literal>
 18.1309 +	  simultanément dans un seul fichier de configuration.</para>
 18.1310 +
 18.1311 +	<note>
 18.1312 +	  <title>Prendre garde aux chemins virtuels en double</title>
 18.1313 +
 18.1314 +	  <para id="x_4e2">Si plusieurs dépôts ont le même
 18.1315 +      chemin virtuel, <filename
 18.1316 +	      role="special">hgwebdir.cgi</filename> ne signalera pas
 18.1317 +	    d'erreur. Au lieu de cela, il se comportera de façon
 18.1318 +        imprévisible.</para>
 18.1319 +	</note>
 18.1320 +      </sect3>
 18.1321 +    </sect2>
 18.1322 +
 18.1323 +    <sect2>
 18.1324 +      <title>Télécharger des archives de sources</title>
 18.1325 +
 18.1326 +      <para id="x_4e3">L'interface web de Mercurial laisse les utilisateurs télécharger
 18.1327 +      une archive de n'importe quelle révision. Cette archive contiendra une image du
 18.1328 +      répertoire de travail comme pour cette révision, mais il ne contiendra pas
 18.1329 +      une copie des données du dépôt.</para>
 18.1330 +
 18.1331 +      <para id="x_4e4">Par défaut, cette fonctionnalité n'est pas activée. Pour l'activer,
 18.1332 +      vous devrez ajouter un élément <envar
 18.1333 +	  role="rc-item-web">allow_archive</envar> à la section
 18.1334 +	<literal role="rc-web">web</literal> de votre <filename
 18.1335 +	  role="special">~/.hgrc</filename>; voyez plus loin pour des détails.</para>
 18.1336 +    </sect2>
 18.1337 +    <sect2>
 18.1338 +      <title>Options de configuration web</title>
 18.1339 +
 18.1340 +      <para id="x_4e5">Les interfaces web de Mercurial (la commande <command role="hg-cmd">hg
 18.1341 +	  serve</command>, et les scripts <filename
 18.1342 +	  role="special">hgweb.cgi</filename> et <filename
 18.1343 +	  role="special">hgwebdir.cgi</filename>) ont un nombre
 18.1344 +      d'options de configuration que vous pouvez mettre. Celles-ci
 18.1345 +      appartiennent à une section appelée <literal
 18.1346 +	  role="rc-web">web</literal>.</para>
 18.1347 +      <itemizedlist>
 18.1348 +	<listitem><para id="x_4e6"><envar
 18.1349 +	      role="rc-item-web">allow_archive</envar> : détermine
 18.1350 +	    quels mécanismes de téléchargement d'archive (si il y en a) Mercurial
 18.1351 +        accepte. Si vous activez cette fonctionnalité, les utilisateurs de
 18.1352 +        l'interface web seront capable de télécharger une archive de
 18.1353 +        n'importe quelle révision d'un dépôt qu'ils regardent. Pour activer
 18.1354 +        la fonction archive, cet élément doit prendre la forme d'une
 18.1355 +        série de mots pris dans la liste ci-dessous.</para>
 18.1356 +	  <itemizedlist>
 18.1357 +	    <listitem><para id="x_4e7"><literal>bz2</literal>: une
 18.1358 +		archive <command>tar</command>, comprimée en utilisant la
 18.1359 +		compression <literal>bzip2</literal>. Ceci a le meilleur
 18.1360 +        taux de compression, mais utilise le plus de temps processeur sur
 18.1361 +        le serveur.</para>
 18.1362 +	    </listitem>
 18.1363 +	    <listitem><para id="x_4e8"><literal>gz</literal>: une
 18.1364 +		archive <command>tar</command>, comprimée en utilisant la
 18.1365 +		compression <literal>gzip</literal>.</para>
 18.1366 +	    </listitem>
 18.1367 +	    <listitem><para id="x_4e9"><literal>zip</literal>: une
 18.1368 +		archive <command>zip</command>, comprimée en utilisant la
 18.1369 +		compression LZW.  Ce format a le pire taux de compression,
 18.1370 +        mais il est largement utilisé dans le monde Windows.</para>
 18.1371 +	    </listitem>
 18.1372 +	  </itemizedlist>
 18.1373 +	  <para id="x_4ea">Si vous fournissez une liste vide, ou n'avez pas
 18.1374 +      d'entrée <envar role="rc-item-web">allow_archive</envar> du tout,
 18.1375 +      cette fonctionnalité sera désactivée. Voici un exemple de
 18.1376 +      comment activer les trois formats supportés.</para>
 18.1377 +	  <programlisting>[web]
 18.1378 +allow_archive = bz2 gz zip</programlisting>
 18.1379 +	</listitem>
 18.1380 +	<listitem><para id="x_4eb"><envar role="rc-item-web">allowpull</envar>:
 18.1381 +	    Boolean. Détermine si l'interface web permet aux
 18.1382 +        utilisateurs distants de <command role="hg-cmd">hg pull</command>
 18.1383 +	    et <command role="hg-cmd">hg clone</command> ce
 18.1384 +	    dépôt sur HTTP.  Si mis à <literal>no</literal> ou
 18.1385 +	    <literal>false</literal>, seule la partie
 18.1386 +	    <quote>orienté humain</quote> de l'interface web
 18.1387 +        est disponible.</para>
 18.1388 +	</listitem>
 18.1389 +    <!-- TODO comment traduire "free-form" ? -->
 18.1390 +	<listitem><para id="x_4ec"><envar role="rc-item-web">contact</envar>:
 18.1391 +	    String.  Une chaîne de caractères "free-form" (mais de préférence brève)
 18.1392 +	    identifiant la personne ou le groupe responsable du
 18.1393 +        dépôt. Ceci contient souvent le nom et l'adresse électronique
 18.1394 +        d'une personne ou d'une liste de distribution. Il est judicieux de
 18.1395 +        placer cette entrée dans le fichier <filename
 18.1396 +	      role="special">.hg/hgrc</filename> du dépôt, mais il peut être
 18.1397 +        judicieux d'utiliser un <filename
 18.1398 +	      role="special">~/.hgrc</filename> global si chaque dépôt
 18.1399 +          a un seul "mainteneur".</para>
 18.1400 +	</listitem>
 18.1401 +	<listitem><para id="x_4ed"><envar role="rc-item-web">maxchanges</envar>:
 18.1402 +	    Integer.  La valeur maximum par défaut du nombre de changesets à
 18.1403 +        afficher dans une seule page de sortie.</para>
 18.1404 +	</listitem>
 18.1405 +	<listitem><para id="x_4ee"><envar role="rc-item-web">maxfiles</envar>:
 18.1406 +	    Integer.  Le nombre maximum par défaut de fichier modifiés à
 18.1407 +        à afficher dans une seule page de sortie.</para>
 18.1408 +	</listitem>
 18.1409 +	<listitem><para id="x_4ef"><envar role="rc-item-web">stripes</envar>:
 18.1410 +	    Integer.  Si l'interface web affiche alternativement desIf the web interface displays alternating
 18.1411 +	    <quote>rayures</quote> pour rendre plus facile l'alignement visuel
 18.1412 +        des lignes lorsque vous regarder une table, ce nombre contrôle
 18.1413 +        le nombre de lignes dans chaque rayure.</para>
 18.1414 +	</listitem>
 18.1415 +    <!-- TODO comment traduire "template" ? J'ai mis "modèle" mais j'ai un doute. -->
 18.1416 +	<listitem><para id="x_4f0"><envar
 18.1417 +	      role="rc-item-web">style</envar>: Contrôle le "modèle"
 18.1418 +	    que Mercurial utilise pour afficher l'interface web.  Mercurial
 18.1419 +	    est livré avec plusieurs "modèles" web.</para>
 18.1420 +	  <itemizedlist>
 18.1421 +	    <listitem>
 18.1422 +	      <para id="x_6aa"><literal>coal</literal> est monochromatique.</para>
 18.1423 +	    </listitem>
 18.1424 +	    <listitem>
 18.1425 +	      <para id="x_6ab"><literal>gitweb</literal> émule le style visuel
 18.1426 +		de l'interface web de git.</para>
 18.1427 +	    </listitem>
 18.1428 +	    <listitem>
 18.1429 +	      <para id="x_6ac"><literal>monoblue</literal> utilise des bleus et des
 18.1430 +          gris massifs.</para>
 18.1431 +	    </listitem>
 18.1432 +	    <listitem>
 18.1433 +	      <para id="x_6ad"><literal>paper</literal> est le "modèle" par défaut.</para>
 18.1434 +	    </listitem>
 18.1435 +	    <listitem>
 18.1436 +	      <para id="x_6ae"><literal>spartan</literal> a été le "modèle" par défaut
 18.1437 +          durant longtemps.</para>
 18.1438 +	    </listitem>
 18.1439 +	  </itemizedlist>
 18.1440 +	  <para id="x_6af">Vous pouvez aussi spécifiez un "modèle" personnalisé à vous;
 18.1441 +      voyez <xref linkend="chap:template"/> pour des détails. Ici, vous pouvez
 18.1442 +	    voir comment activer le style <literal>gitweb</literal>.</para>
 18.1443 +	  <programlisting>[web]
 18.1444 +style = gitweb</programlisting>
 18.1445 +	</listitem>
 18.1446 +	<listitem><para id="x_4f1"><envar role="rc-item-web">templates</envar>:
 18.1447 +	    Path.  Le répertoire dans lequel chercher les fichiers "modèles".
 18.1448 +        Par défaut, Mercurial cherche dans le répertoire dans lequel
 18.1449 +        il a été installé.</para>
 18.1450 +	</listitem></itemizedlist>
 18.1451 +      <para id="x_4f2">Si vous utilisez <filename
 18.1452 +	  role="special">hgwebdir.cgi</filename>, vous pouvez mettre quelques
 18.1453 +      éléments de configuration dans une section <literal role="rc-web">web</literal>
 18.1454 +	du fichier <filename
 18.1455 +	  role="special">hgweb.config</filename> au lieu d'un fichier
 18.1456 +	<filename role="special">~/.hgrc</filename>, par
 18.1457 +    commodité. Ces éléments sont <envar
 18.1458 +	  role="rc-item-web">motd</envar> et <envar
 18.1459 +	  role="rc-item-web">style</envar>.</para>
 18.1460 +
 18.1461 +      <sect3>
 18.1462 +	<title>Options spécifiques à un dépôt individuel</title>
 18.1463 +
 18.1464 +	<para id="x_4f3">Quelques éléments de configuration <literal role="rc-web">web</literal>
 18.1465 +	  devraient être mis dans <filename
 18.1466 +	    role="special">.hg/hgrc</filename> local à un dépôt, plutôt que dans un
 18.1467 +	  <filename role="special">~/.hgrc</filename> d'utilisateur ou global.</para>
 18.1468 +	<itemizedlist>
 18.1469 +	  <listitem><para id="x_4f4"><envar
 18.1470 +		role="rc-item-web">description</envar>: String.  Une chaîne de
 18.1471 +	      caractères "free-form" (mais de préférence brève) qui décrit
 18.1472 +          le contenu ou le but du dépôt.</para>
 18.1473 +	  </listitem>
 18.1474 +	  <listitem><para id="x_4f5"><envar role="rc-item-web">name</envar>:
 18.1475 +	      String.  Le nom à utiliser pour le dépôt dans l'interface
 18.1476 +          web. Ceci prime sur le nom par défaut, qui est le dernier
 18.1477 +          composant du chemin du dépôt.</para>
 18.1478 +	  </listitem></itemizedlist>
 18.1479 +      </sect3>
 18.1480 +
 18.1481 +      <sect3>
 18.1482 +	<title>Options spécifiques à la commande <command role="hg-cmd">hg
 18.1483 +	    serve</command></title>
 18.1484 +
 18.1485 +	<para id="x_4f6">Certaines entrées dans la section <literal
 18.1486 +	    role="rc-web">web</literal> d'un fichier <filename
 18.1487 +	    role="special">~/.hgrc</filename> sont là seulement pour être utilisée
 18.1488 +        avec la commande <command role="hg-cmd">hg serve</command>.</para>
 18.1489 +	<itemizedlist>
 18.1490 +	  <listitem><para id="x_4f7"><envar role="rc-item-web">accesslog</envar>:
 18.1491 +	      Path.  Le nom d'un fichier dans lequel écrire le "log" d'accès.
 18.1492 +          Par défaut, la commande <command role="hg-cmd">hg
 18.1493 +		serve</command> écrit cette information sur la sortie
 18.1494 +        standard, pas dans un fichier. Les entrées de "log" sont écrites
 18.1495 +        dans le format de fichier standard <quote>combined</quote> utilisé
 18.1496 +        par pratiquement tous les serveurs web.</para>
 18.1497 +	  </listitem>
 18.1498 +	  <listitem><para id="x_4f8"><envar role="rc-item-web">address</envar>:
 18.1499 +	      String.  L'adresse locale sur laquelle le serveur devrait
 18.1500 +          écouter les connexions entrantes. Par défaut, le serveur
 18.1501 +          écoute sur toutes les adresses.</para>
 18.1502 +	  </listitem>
 18.1503 +	  <listitem><para id="x_4f9"><envar role="rc-item-web">errorlog</envar>:
 18.1504 +	      Path.  Le nom d'un fichier dans lequel écrire le "log" d'erreur.
 18.1505 +          Par défaut, la commande <command role="hg-cmd">hg
 18.1506 +		serve</command> écrit cette information sur la sortie erreur,
 18.1507 +        pas dans un fichier.</para>
 18.1508 +	  </listitem>
 18.1509 +	  <listitem><para id="x_4fa"><envar role="rc-item-web">ipv6</envar>:
 18.1510 +	      Boolean.  Si il faut utiliser le protocole IPv6. Par défaut,
 18.1511 +          IPv6 n'est pas utilisé.</para>
 18.1512 +	  </listitem>
 18.1513 +	  <listitem><para id="x_4fb"><envar role="rc-item-web">port</envar>:
 18.1514 +	      Integer.  Le numéro de port TCP sur lequel le serveur devrait
 18.1515 +          écouter. Le numéro de port par défaut utilisé est 8000.</para>
 18.1516 +	  </listitem></itemizedlist>
 18.1517 +      </sect3>
 18.1518 +
 18.1519 +      <sect3>
 18.1520 +	<title>Choisir le bon fichier <filename
 18.1521 +	    role="special">~/.hgrc</filename> auquel ajouter les éléments <literal
 18.1522 +	    role="rc-web">web</literal></title>
 18.1523 +
 18.1524 +	<para id="x_4fc">Il est important de se souvenir qu'un serveur web comme
 18.1525 +      Apache ou <literal>lighttpd</literal> fonctionnera avec un ID utilisateur
 18.1526 +      qui est différent du vôtre. Les scripts CGI fonctionnant sur votre serveur,
 18.1527 +      tels que <filename
 18.1528 +	    role="special">hgweb.cgi</filename>, s'exécuteront habituellement aussi
 18.1529 +        sous un autre ID utilisateur.</para>
 18.1530 +
 18.1531 +	<para id="x_4fd">Si vous ajoutez des éléments <literal role="rc-web">web</literal> à
 18.1532 +    votre propre fichier <filename role="special">~/.hgrc</filename> personnel,
 18.1533 +    les scripts CGI ne pourront pas lire ce fichier
 18.1534 +	  <filename role="special">~/.hgrc</filename>. Ces réglages
 18.1535 +      toucheront donc seulement le comportement de la commande <command
 18.1536 +	    role="hg-cmd">hg serve</command> quand vous l'exécuterez.
 18.1537 +	  Pour faire voir vos réglages aux scripts CGI, soit créez un
 18.1538 +	  fichier <filename role="special">~/.hgrc</filename> dans le répertoire
 18.1539 +      "home" de l'utilisateur qui exécute votre serveur web, soit
 18.1540 +      ajouter ces réglages dans un fichier <filename
 18.1541 +	    role="special">hgrc</filename> "system-wide".</para>
 18.1542 +      </sect3>
 18.1543 +    </sect2>
 18.1544 +  </sect1>
 18.1545 +
 18.1546 +  <sect1>
 18.1547 +    <title>Configuration "system-wide"</title>
 18.1548 +
 18.1549 +    <para id="x_6b0">Sur des systèmes "Unix-like" partagé par plusieurs utilisateurs
 18.1550 +      (tel qu'un serveur où les gens publient des modifications), il est souvent judicieux
 18.1551 +      de définir certains comportement globaux par défaut, tels que le thème à utiliser
 18.1552 +      dans les interfaces web.</para>
 18.1553 +
 18.1554 +    <para id="x_6b1">Si un fichier appelé <filename>/etc/mercurial/hgrc</filename>
 18.1555 +      existe, Mercurial le lira au démarrage et appliquera tous les réglages
 18.1556 +      de configuration qu'il trouve dans ce fichier. Il regardera aussi
 18.1557 +      les fichiers finissant par une extension <literal>.rc</literal> dans un
 18.1558 +      répertoire appelé <filename>/etc/mercurial/hgrc.d</filename>, et
 18.1559 +      appliquera tous les réglages de configuration qu'il trouve dans chacun
 18.1560 +      de ces fichiers.</para>
 18.1561 +
 18.1562 +    <sect2>
 18.1563 +      <title>Rendre Mercurial moins méfiant</title>
 18.1564 +
 18.1565 +      <para id="x_6b2">Une situation dans laquelle un <filename>hgrc</filename>
 18.1566 +	global peut être utile est si des utilisateurs "pullent" des modifications
 18.1567 +    faites par d'autres utilisateurs. Par défaut, Mercurial can be useful is if users are pulling changes owned by other
 18.1568 +	users.  By default, Mercurial ne se fiera pas à la plupart des
 18.1569 +    entrées de configuration dans un fichier <filename>.hg/hgrc</filename>
 18.1570 +	à l'intérieur d'un dépôt qui appartient à un utilisateur différent. Si nous
 18.1571 +    clonons ou "pullons" des modifications d'un tel dépôt, Mercurial
 18.1572 +    affichera un avertissement indiquant qu'il ne fait pas confiance aux 
 18.1573 +	<filename>.hg/hgrc</filename>.</para>
 18.1574 +
 18.1575 +      <para id="x_6b3">Si quelqu'un dans un groupe Unix particulier est dans la même équipe
 18.1576 +      et <emphasis>devrait</emphasis> avoir confiance dans chaque réglage
 18.1577 +      de configuration des autres, ou si nous voulons avoir confiance dans des utilisateurs
 18.1578 +      particuliers, nous pouvons passer outre les défauts sceptiques de Mercurial
 18.1579 +      en créant un fichier <filename>hgrc</filename> "system-wide" tel que celui qui
 18.1580 +    suit ::</para>
 18.1581 +
 18.1582 +    <programlisting># Save this as e.g. /etc/mercurial/hgrc.d/trust.rc
 18.1583 +[trusted]
 18.1584 +# Trust all entries in any hgrc file owned by the "editors" or
 18.1585 +# "www-data" groups.
 18.1586 +groups = editors, www-data
 18.1587 +
 18.1588 +# Trust entries in hgrc files owned by the following users.
 18.1589 +users = apache, bobo
 18.1590 +</programlisting>
 18.1591 +    </sect2>
 18.1592 +  </sect1>
 18.1593 +</chapter>
 18.1594 +<!--
 18.1595 +local variables: 
 18.1596 +sgml-parent-document: ("00book.xml" "book" "chapter")
 18.1597 +end:
 18.1598 +-->
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/fr/ch07-filenames.xml	Sat Jul 10 06:24:49 2010 +0100
    19.3 @@ -0,0 +1,451 @@
    19.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
    19.5 +
    19.6 +<chapter id="chap:names">
    19.7 +  <?dbhtml filename="file-names-and-pattern-matching.html"?>
    19.8 +  <title>File names and pattern matching</title>
    19.9 +
   19.10 +  <para id="x_543">Mercurial provides mechanisms that let you work with file
   19.11 +    names in a consistent and expressive way.</para>
   19.12 +
   19.13 +  <sect1>
   19.14 +    <title>Simple file naming</title>
   19.15 +
   19.16 +    <para id="x_544">Mercurial uses a unified piece of machinery <quote>under the
   19.17 +	hood</quote> to handle file names.  Every command behaves
   19.18 +      uniformly with respect to file names.  The way in which commands
   19.19 +      work with file names is as follows.</para>
   19.20 +
   19.21 +    <para id="x_545">If you explicitly name real files on the command line,
   19.22 +      Mercurial works with exactly those files, as you would expect.
   19.23 +      &interaction.filenames.files;</para>
   19.24 +
   19.25 +    <para id="x_546">When you provide a directory name, Mercurial will interpret
   19.26 +      this as <quote>operate on every file in this directory and its
   19.27 +	subdirectories</quote>. Mercurial traverses the files and
   19.28 +      subdirectories in a directory in alphabetical order.  When it
   19.29 +      encounters a subdirectory, it will traverse that subdirectory
   19.30 +      before continuing with the current directory.</para>
   19.31 +
   19.32 +      &interaction.filenames.dirs;
   19.33 +  </sect1>
   19.34 +
   19.35 +  <sect1>
   19.36 +    <title>Running commands without any file names</title>
   19.37 +
   19.38 +    <para id="x_547">Mercurial's commands that work with file names have useful
   19.39 +      default behaviors when you invoke them without providing any
   19.40 +      file names or patterns.  What kind of behavior you should
   19.41 +      expect depends on what the command does.  Here are a few rules
   19.42 +      of thumb you can use to predict what a command is likely to do
   19.43 +      if you don't give it any names to work with.</para>
   19.44 +    <itemizedlist>
   19.45 +      <listitem><para id="x_548">Most commands will operate on the entire working
   19.46 +	  directory. This is what the <command role="hg-cmd">hg
   19.47 +	    add</command> command does, for example.</para>
   19.48 +      </listitem>
   19.49 +      <listitem><para id="x_549">If the command has effects that are difficult or
   19.50 +	  impossible to reverse, it will force you to explicitly
   19.51 +	  provide at least one name or pattern (see below).  This
   19.52 +	  protects you from accidentally deleting files by running
   19.53 +	  <command role="hg-cmd">hg remove</command> with no
   19.54 +	  arguments, for example.</para>
   19.55 +      </listitem></itemizedlist>
   19.56 +
   19.57 +    <para id="x_54a">It's easy to work around these default behaviors if they
   19.58 +      don't suit you.  If a command normally operates on the whole
   19.59 +      working directory, you can invoke it on just the current
   19.60 +      directory and its subdirectories by giving it the name
   19.61 +      <quote><filename class="directory">.</filename></quote>.</para>
   19.62 +
   19.63 +    &interaction.filenames.wdir-subdir;
   19.64 +
   19.65 +    <para id="x_54b">Along the same lines, some commands normally print file
   19.66 +      names relative to the root of the repository, even if you're
   19.67 +      invoking them from a subdirectory.  Such a command will print
   19.68 +      file names relative to your subdirectory if you give it explicit
   19.69 +      names.  Here, we're going to run <command role="hg-cmd">hg
   19.70 +	status</command> from a subdirectory, and get it to operate on
   19.71 +      the entire working directory while printing file names relative
   19.72 +      to our subdirectory, by passing it the output of the <command
   19.73 +	role="hg-cmd">hg root</command> command.</para>
   19.74 +
   19.75 +      &interaction.filenames.wdir-relname;
   19.76 +  </sect1>
   19.77 +
   19.78 +  <sect1>
   19.79 +    <title>Telling you what's going on</title>
   19.80 +
   19.81 +    <para id="x_54c">The <command role="hg-cmd">hg add</command> example in the
   19.82 +      preceding section illustrates something else that's helpful
   19.83 +      about Mercurial commands.  If a command operates on a file that
   19.84 +      you didn't name explicitly on the command line, it will usually
   19.85 +      print the name of the file, so that you will not be surprised
   19.86 +      what's going on.</para>
   19.87 +
   19.88 +    <para id="x_54d">The principle here is of <emphasis>least
   19.89 +	surprise</emphasis>.  If you've exactly named a file on the
   19.90 +      command line, there's no point in repeating it back at you.  If
   19.91 +      Mercurial is acting on a file <emphasis>implicitly</emphasis>, e.g.
   19.92 +      because you provided no names, or a directory, or a pattern (see
   19.93 +      below), it is safest to tell you what files it's operating on.</para>
   19.94 +
   19.95 +    <para id="x_54e">For commands that behave this way, you can silence them
   19.96 +      using the <option role="hg-opt-global">-q</option> option.  You
   19.97 +      can also get them to print the name of every file, even those
   19.98 +      you've named explicitly, using the <option
   19.99 +	role="hg-opt-global">-v</option> option.</para>
  19.100 +  </sect1>
  19.101 +
  19.102 +  <sect1>
  19.103 +    <title>Using patterns to identify files</title>
  19.104 +
  19.105 +    <para id="x_54f">In addition to working with file and directory names,
  19.106 +      Mercurial lets you use <emphasis>patterns</emphasis> to identify
  19.107 +      files.  Mercurial's pattern handling is expressive.</para>
  19.108 +
  19.109 +    <para id="x_550">On Unix-like systems (Linux, MacOS, etc.), the job of
  19.110 +      matching file names to patterns normally falls to the shell.  On
  19.111 +      these systems, you must explicitly tell Mercurial that a name is
  19.112 +      a pattern.  On Windows, the shell does not expand patterns, so
  19.113 +      Mercurial will automatically identify names that are patterns,
  19.114 +      and expand them for you.</para>
  19.115 +
  19.116 +    <para id="x_551">To provide a pattern in place of a regular name on the
  19.117 +      command line, the mechanism is simple:</para>
  19.118 +    <programlisting>syntax:patternbody</programlisting>
  19.119 +    <para id="x_552">That is, a pattern is identified by a short text string that
  19.120 +      says what kind of pattern this is, followed by a colon, followed
  19.121 +      by the actual pattern.</para>
  19.122 +
  19.123 +    <para id="x_553">Mercurial supports two kinds of pattern syntax.  The most
  19.124 +      frequently used is called <literal>glob</literal>; this is the
  19.125 +      same kind of pattern matching used by the Unix shell, and should
  19.126 +      be familiar to Windows command prompt users, too.</para>
  19.127 +
  19.128 +    <para id="x_554">When Mercurial does automatic pattern matching on Windows,
  19.129 +      it uses <literal>glob</literal> syntax.  You can thus omit the
  19.130 +      <quote><literal>glob:</literal></quote> prefix on Windows, but
  19.131 +      it's safe to use it, too.</para>
  19.132 +
  19.133 +    <para id="x_555">The <literal>re</literal> syntax is more powerful; it lets
  19.134 +      you specify patterns using regular expressions, also known as
  19.135 +      regexps.</para>
  19.136 +
  19.137 +    <para id="x_556">By the way, in the examples that follow, notice that I'm
  19.138 +      careful to wrap all of my patterns in quote characters, so that
  19.139 +      they won't get expanded by the shell before Mercurial sees
  19.140 +      them.</para>
  19.141 +
  19.142 +    <sect2>
  19.143 +      <title>Shell-style <literal>glob</literal> patterns</title>
  19.144 +
  19.145 +      <para id="x_557">This is an overview of the kinds of patterns you can use
  19.146 +	when you're matching on glob patterns.</para>
  19.147 +
  19.148 +      <para id="x_558">The <quote><literal>*</literal></quote> character matches
  19.149 +	any string, within a single directory.</para>
  19.150 +
  19.151 +      &interaction.filenames.glob.star;
  19.152 +
  19.153 +      <para id="x_559">The <quote><literal>**</literal></quote> pattern matches
  19.154 +	any string, and crosses directory boundaries.  It's not a
  19.155 +	standard Unix glob token, but it's accepted by several popular
  19.156 +	Unix shells, and is very useful.</para>
  19.157 +
  19.158 +      &interaction.filenames.glob.starstar;
  19.159 +
  19.160 +      <para id="x_55a">The <quote><literal>?</literal></quote> pattern matches
  19.161 +	any single character.</para>
  19.162 +
  19.163 +      &interaction.filenames.glob.question;
  19.164 +
  19.165 +      <para id="x_55b">The <quote><literal>[</literal></quote> character begins a
  19.166 +	<emphasis>character class</emphasis>.  This matches any single
  19.167 +	character within the class.  The class ends with a
  19.168 +	<quote><literal>]</literal></quote> character.  A class may
  19.169 +	contain multiple <emphasis>range</emphasis>s of the form
  19.170 +	<quote><literal>a-f</literal></quote>, which is shorthand for
  19.171 +	<quote><literal>abcdef</literal></quote>.</para>
  19.172 +
  19.173 +	&interaction.filenames.glob.range;
  19.174 +
  19.175 +      <para id="x_55c">If the first character after the
  19.176 +	<quote><literal>[</literal></quote> in a character class is a
  19.177 +	<quote><literal>!</literal></quote>, it
  19.178 +	<emphasis>negates</emphasis> the class, making it match any
  19.179 +	single character not in the class.</para>
  19.180 +
  19.181 +      <para id="x_55d">A <quote><literal>{</literal></quote> begins a group of
  19.182 +	subpatterns, where the whole group matches if any subpattern
  19.183 +	in the group matches.  The <quote><literal>,</literal></quote>
  19.184 +	character separates subpatterns, and
  19.185 +	<quote><literal>}</literal></quote> ends the group.</para>
  19.186 +
  19.187 +      &interaction.filenames.glob.group;
  19.188 +
  19.189 +      <sect3>
  19.190 +	<title>Watch out!</title>
  19.191 +
  19.192 +	<para id="x_55e">Don't forget that if you want to match a pattern in any
  19.193 +	  directory, you should not be using the
  19.194 +	  <quote><literal>*</literal></quote> match-any token, as this
  19.195 +	  will only match within one directory.  Instead, use the
  19.196 +	  <quote><literal>**</literal></quote> token.  This small
  19.197 +	  example illustrates the difference between the two.</para>
  19.198 +
  19.199 +	  &interaction.filenames.glob.star-starstar;
  19.200 +      </sect3>
  19.201 +    </sect2>
  19.202 +
  19.203 +    <sect2>
  19.204 +      <title>Regular expression matching with <literal>re</literal>
  19.205 +	patterns</title>
  19.206 +
  19.207 +      <para id="x_55f">Mercurial accepts the same regular expression syntax as
  19.208 +	the Python programming language (it uses Python's regexp
  19.209 +	engine internally). This is based on the Perl language's
  19.210 +	regexp syntax, which is the most popular dialect in use (it's
  19.211 +	also used in Java, for example).</para>
  19.212 +
  19.213 +      <para id="x_560">I won't discuss Mercurial's regexp dialect in any detail
  19.214 +	here, as regexps are not often used.  Perl-style regexps are
  19.215 +	in any case already exhaustively documented on a multitude of
  19.216 +	web sites, and in many books.  Instead, I will focus here on a
  19.217 +	few things you should know if you find yourself needing to use
  19.218 +	regexps with Mercurial.</para>
  19.219 +
  19.220 +      <para id="x_561">A regexp is matched against an entire file name, relative
  19.221 +	to the root of the repository.  In other words, even if you're
  19.222 +	already in subbdirectory <filename
  19.223 +	  class="directory">foo</filename>, if you want to match files
  19.224 +	under this directory, your pattern must start with
  19.225 +	<quote><literal>foo/</literal></quote>.</para>
  19.226 +
  19.227 +      <para id="x_562">One thing to note, if you're familiar with Perl-style
  19.228 +	regexps, is that Mercurial's are <emphasis>rooted</emphasis>.
  19.229 +	That is, a regexp starts matching against the beginning of a
  19.230 +	string; it doesn't look for a match anywhere within the
  19.231 +	string.  To match anywhere in a string, start your pattern
  19.232 +	with <quote><literal>.*</literal></quote>.</para>
  19.233 +    </sect2>
  19.234 +  </sect1>
  19.235 +
  19.236 +  <sect1>
  19.237 +    <title>Filtering files</title>
  19.238 +
  19.239 +    <para id="x_563">Not only does Mercurial give you a variety of ways to
  19.240 +      specify files; it lets you further winnow those files using
  19.241 +      <emphasis>filters</emphasis>.  Commands that work with file
  19.242 +      names accept two filtering options.</para>
  19.243 +    <itemizedlist>
  19.244 +      <listitem><para id="x_564"><option role="hg-opt-global">-I</option>, or
  19.245 +	  <option role="hg-opt-global">--include</option>, lets you
  19.246 +	  specify a pattern that file names must match in order to be
  19.247 +	  processed.</para>
  19.248 +      </listitem>
  19.249 +      <listitem><para id="x_565"><option role="hg-opt-global">-X</option>, or
  19.250 +	  <option role="hg-opt-global">--exclude</option>, gives you a
  19.251 +	  way to <emphasis>avoid</emphasis> processing files, if they
  19.252 +	  match this pattern.</para>
  19.253 +      </listitem></itemizedlist>
  19.254 +    <para id="x_566">You can provide multiple <option
  19.255 +	role="hg-opt-global">-I</option> and <option
  19.256 +	role="hg-opt-global">-X</option> options on the command line,
  19.257 +      and intermix them as you please.  Mercurial interprets the
  19.258 +      patterns you provide using glob syntax by default (but you can
  19.259 +      use regexps if you need to).</para>
  19.260 +
  19.261 +    <para id="x_567">You can read a <option role="hg-opt-global">-I</option>
  19.262 +      filter as <quote>process only the files that match this
  19.263 +	filter</quote>.</para>
  19.264 +
  19.265 +    &interaction.filenames.filter.include;
  19.266 +
  19.267 +    <para id="x_568">The <option role="hg-opt-global">-X</option> filter is best
  19.268 +      read as <quote>process only the files that don't match this
  19.269 +	pattern</quote>.</para>
  19.270 +
  19.271 +    &interaction.filenames.filter.exclude;
  19.272 +  </sect1>
  19.273 +
  19.274 +  <sect1>
  19.275 +    <title>Permanently ignoring unwanted files and directories</title>
  19.276 +
  19.277 +    <para id="x_569">When you create a new repository, the chances are
  19.278 +      that over time it will grow to contain files that ought to
  19.279 +      <emphasis>not</emphasis> be managed by Mercurial, but which you
  19.280 +      don't want to see listed every time you run <command>hg
  19.281 +	status</command>.  For instance, <quote>build products</quote>
  19.282 +      are files that are created as part of a build but which should
  19.283 +      not be managed by a revision control system.  The most common
  19.284 +      build products are output files produced by software tools such
  19.285 +      as compilers.  As another example, many text editors litter a
  19.286 +      directory with lock files, temporary working files, and backup
  19.287 +      files, which it also makes no sense to manage.</para>
  19.288 +
  19.289 +    <para id="x_6b4">To have Mercurial permanently ignore such files, create a
  19.290 +      file named <filename>.hgignore</filename> in the root of your
  19.291 +      repository.  You <emphasis>should</emphasis> <command>hg
  19.292 +      add</command> this file so that it gets tracked with the rest of
  19.293 +      your repository contents, since your collaborators will probably
  19.294 +      find it useful too.</para>
  19.295 +
  19.296 +    <para id="x_6b5">By default, the <filename>.hgignore</filename> file should
  19.297 +      contain a list of regular expressions, one per line.  Empty
  19.298 +      lines are skipped. Most people prefer to describe the files they
  19.299 +      want to ignore using the <quote>glob</quote> syntax that we
  19.300 +      described above, so a typical <filename>.hgignore</filename>
  19.301 +      file will start with this directive:</para>
  19.302 +
  19.303 +    <programlisting>syntax: glob</programlisting>
  19.304 +
  19.305 +    <para id="x_6b6">This tells Mercurial to interpret the lines that follow as
  19.306 +      glob patterns, not regular expressions.</para>
  19.307 +
  19.308 +    <para id="x_6b7">Here is a typical-looking <filename>.hgignore</filename>
  19.309 +      file.</para>
  19.310 +
  19.311 +    <programlisting>syntax: glob
  19.312 +# This line is a comment, and will be skipped.
  19.313 +# Empty lines are skipped too.
  19.314 +
  19.315 +# Backup files left behind by the Emacs editor.
  19.316 +*~
  19.317 +
  19.318 +# Lock files used by the Emacs editor.
  19.319 +# Notice that the "#" character is quoted with a backslash.
  19.320 +# This prevents it from being interpreted as starting a comment.
  19.321 +.\#*
  19.322 +
  19.323 +# Temporary files used by the vim editor.
  19.324 +.*.swp
  19.325 +
  19.326 +# A hidden file created by the Mac OS X Finder.
  19.327 +.DS_Store
  19.328 +</programlisting>
  19.329 +  </sect1>
  19.330 +
  19.331 +  <sect1 id="sec:names:case">
  19.332 +    <title>Case sensitivity</title>
  19.333 +
  19.334 +    <para id="x_56a">If you're working in a mixed development environment that
  19.335 +      contains both Linux (or other Unix) systems and Macs or Windows
  19.336 +      systems, you should keep in the back of your mind the knowledge
  19.337 +      that they treat the case (<quote>N</quote> versus
  19.338 +      <quote>n</quote>) of file names in incompatible ways.  This is
  19.339 +      not very likely to affect you, and it's easy to deal with if it
  19.340 +      does, but it could surprise you if you don't know about
  19.341 +      it.</para>
  19.342 +
  19.343 +    <para id="x_56b">Operating systems and filesystems differ in the way they
  19.344 +      handle the <emphasis>case</emphasis> of characters in file and
  19.345 +      directory names.  There are three common ways to handle case in
  19.346 +      names.</para>
  19.347 +    <itemizedlist>
  19.348 +      <listitem><para id="x_56c">Completely case insensitive.  Uppercase and
  19.349 +	  lowercase versions of a letter are treated as identical,
  19.350 +	  both when creating a file and during subsequent accesses.
  19.351 +	  This is common on older DOS-based systems.</para>
  19.352 +      </listitem>
  19.353 +      <listitem><para id="x_56d">Case preserving, but insensitive.  When a file
  19.354 +	  or directory is created, the case of its name is stored, and
  19.355 +	  can be retrieved and displayed by the operating system.
  19.356 +	  When an existing file is being looked up, its case is
  19.357 +	  ignored.  This is the standard arrangement on Windows and
  19.358 +	  MacOS.  The names <filename>foo</filename> and
  19.359 +	  <filename>FoO</filename> identify the same file.  This
  19.360 +	  treatment of uppercase and lowercase letters as
  19.361 +	  interchangeable is also referred to as <emphasis>case
  19.362 +	    folding</emphasis>.</para>
  19.363 +      </listitem>
  19.364 +      <listitem><para id="x_56e">Case sensitive.  The case of a name
  19.365 +	  is significant at all times. The names
  19.366 +	  <filename>foo</filename> and <filename>FoO</filename>
  19.367 +	  identify different files.  This is the way Linux and Unix
  19.368 +	  systems normally work.</para>
  19.369 +      </listitem></itemizedlist>
  19.370 +
  19.371 +    <para id="x_56f">On Unix-like systems, it is possible to have any or all of
  19.372 +      the above ways of handling case in action at once.  For example,
  19.373 +      if you use a USB thumb drive formatted with a FAT32 filesystem
  19.374 +      on a Linux system, Linux will handle names on that filesystem in
  19.375 +      a case preserving, but insensitive, way.</para>
  19.376 +
  19.377 +    <sect2>
  19.378 +      <title>Safe, portable repository storage</title>
  19.379 +
  19.380 +      <para id="x_570">Mercurial's repository storage mechanism is <emphasis>case
  19.381 +	  safe</emphasis>.  It translates file names so that they can
  19.382 +	be safely stored on both case sensitive and case insensitive
  19.383 +	filesystems.  This means that you can use normal file copying
  19.384 +	tools to transfer a Mercurial repository onto, for example, a
  19.385 +	USB thumb drive, and safely move that drive and repository
  19.386 +	back and forth between a Mac, a PC running Windows, and a
  19.387 +	Linux box.</para>
  19.388 +
  19.389 +    </sect2>
  19.390 +    <sect2>
  19.391 +      <title>Detecting case conflicts</title>
  19.392 +
  19.393 +      <para id="x_571">When operating in the working directory, Mercurial honours
  19.394 +	the naming policy of the filesystem where the working
  19.395 +	directory is located.  If the filesystem is case preserving,
  19.396 +	but insensitive, Mercurial will treat names that differ only
  19.397 +	in case as the same.</para>
  19.398 +
  19.399 +      <para id="x_572">An important aspect of this approach is that it is
  19.400 +	possible to commit a changeset on a case sensitive (typically
  19.401 +	Linux or Unix) filesystem that will cause trouble for users on
  19.402 +	case insensitive (usually Windows and MacOS) users.  If a
  19.403 +	Linux user commits changes to two files, one named
  19.404 +	<filename>myfile.c</filename> and the other named
  19.405 +	<filename>MyFile.C</filename>, they will be stored correctly
  19.406 +	in the repository.  And in the working directories of other
  19.407 +	Linux users, they will be correctly represented as separate
  19.408 +	files.</para>
  19.409 +
  19.410 +      <para id="x_573">If a Windows or Mac user pulls this change, they will not
  19.411 +	initially have a problem, because Mercurial's repository
  19.412 +	storage mechanism is case safe.  However, once they try to
  19.413 +	<command role="hg-cmd">hg update</command> the working
  19.414 +	directory to that changeset, or <command role="hg-cmd">hg
  19.415 +	  merge</command> with that changeset, Mercurial will spot the
  19.416 +	conflict between the two file names that the filesystem would
  19.417 +	treat as the same, and forbid the update or merge from
  19.418 +	occurring.</para>
  19.419 +    </sect2>
  19.420 +
  19.421 +    <sect2>
  19.422 +      <title>Fixing a case conflict</title>
  19.423 +
  19.424 +      <para id="x_574">If you are using Windows or a Mac in a mixed environment
  19.425 +	where some of your collaborators are using Linux or Unix, and
  19.426 +	Mercurial reports a case folding conflict when you try to
  19.427 +	<command role="hg-cmd">hg update</command> or <command
  19.428 +	  role="hg-cmd">hg merge</command>, the procedure to fix the
  19.429 +	problem is simple.</para>
  19.430 +
  19.431 +      <para id="x_575">Just find a nearby Linux or Unix box, clone the problem
  19.432 +	repository onto it, and use Mercurial's <command
  19.433 +	  role="hg-cmd">hg rename</command> command to change the
  19.434 +	names of any offending files or directories so that they will
  19.435 +	no longer cause case folding conflicts.  Commit this change,
  19.436 +	<command role="hg-cmd">hg pull</command> or <command
  19.437 +	  role="hg-cmd">hg push</command> it across to your Windows or
  19.438 +	MacOS system, and <command role="hg-cmd">hg update</command>
  19.439 +	to the revision with the non-conflicting names.</para>
  19.440 +
  19.441 +      <para id="x_576">The changeset with case-conflicting names will remain in
  19.442 +	your project's history, and you still won't be able to
  19.443 +	<command role="hg-cmd">hg update</command> your working
  19.444 +	directory to that changeset on a Windows or MacOS system, but
  19.445 +	you can continue development unimpeded.</para>
  19.446 +    </sect2>
  19.447 +  </sect1>
  19.448 +</chapter>
  19.449 +
  19.450 +<!--
  19.451 +local variables: 
  19.452 +sgml-parent-document: ("00book.xml" "book" "chapter")
  19.453 +end:
  19.454 +-->
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/fr/ch08-branch.xml	Sat Jul 10 06:24:49 2010 +0100
    20.3 @@ -0,0 +1,533 @@
    20.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
    20.5 +
    20.6 +<chapter id="chap:branch">
    20.7 +  <?dbhtml filename="managing-releases-and-branchy-development.html"?>
    20.8 +  <title>Managing releases and branchy development</title>
    20.9 +
   20.10 +  <para id="x_369">Mercurial provides several mechanisms for you to manage a
   20.11 +    project that is making progress on multiple fronts at once.  To
   20.12 +    understand these mechanisms, let's first take a brief look at a
   20.13 +    fairly normal software project structure.</para>
   20.14 +
   20.15 +  <para id="x_36a">Many software projects issue periodic <quote>major</quote>
   20.16 +    releases that contain substantial new features.  In parallel, they
   20.17 +    may issue <quote>minor</quote> releases.  These are usually
   20.18 +    identical to the major releases off which they're based, but with
   20.19 +    a few bugs fixed.</para>
   20.20 +
   20.21 +  <para id="x_36b">In this chapter, we'll start by talking about how to keep
   20.22 +    records of project milestones such as releases.  We'll then
   20.23 +    continue on to talk about the flow of work between different
   20.24 +    phases of a project, and how Mercurial can help you to isolate and
   20.25 +    manage this work.</para>
   20.26 +
   20.27 +  <sect1>
   20.28 +    <title>Giving a persistent name to a revision</title>
   20.29 +
   20.30 +    <para id="x_36c">Once you decide that you'd like to call a particular
   20.31 +      revision a <quote>release</quote>, it's a good idea to record
   20.32 +      the identity of that revision. This will let you reproduce that
   20.33 +      release at a later date, for whatever purpose you might need at
   20.34 +      the time (reproducing a bug, porting to a new platform, etc).
   20.35 +      &interaction.tag.init;</para>
   20.36 +
   20.37 +    <para id="x_36d">Mercurial lets you give a permanent name to any revision
   20.38 +      using the <command role="hg-cmd">hg tag</command> command.  Not
   20.39 +      surprisingly, these names are called <quote>tags</quote>.</para>
   20.40 +
   20.41 +    &interaction.tag.tag;
   20.42 +
   20.43 +    <para id="x_36e">A tag is nothing more than a <quote>symbolic name</quote>
   20.44 +      for a revision.  Tags exist purely for your convenience, so that
   20.45 +      you have a handy permanent way to refer to a revision; Mercurial
   20.46 +      doesn't interpret the tag names you use in any way.  Neither
   20.47 +      does Mercurial place any restrictions on the name of a tag,
   20.48 +      beyond a few that are necessary to ensure that a tag can be
   20.49 +      parsed unambiguously.  A tag name cannot contain any of the
   20.50 +      following characters:</para>
   20.51 +    <itemizedlist>
   20.52 +      <listitem><para id="x_36f">Colon (ASCII 58,
   20.53 +	  <quote><literal>:</literal></quote>)</para>
   20.54 +      </listitem>
   20.55 +      <listitem><para id="x_370">Carriage return (ASCII 13,
   20.56 +	  <quote><literal>\r</literal></quote>)</para>
   20.57 +      </listitem>
   20.58 +      <listitem><para id="x_371">Newline (ASCII 10,
   20.59 +	  <quote><literal>\n</literal></quote>)</para>
   20.60 +      </listitem></itemizedlist>
   20.61 +
   20.62 +    <para id="x_372">You can use the <command role="hg-cmd">hg tags</command>
   20.63 +      command to display the tags present in your repository.  In the
   20.64 +      output, each tagged revision is identified first by its name,
   20.65 +      then by revision number, and finally by the unique hash of the
   20.66 +      revision.</para>
   20.67 +
   20.68 +    &interaction.tag.tags;
   20.69 +
   20.70 +    <para id="x_373">Notice that <literal>tip</literal> is listed in the output
   20.71 +      of <command role="hg-cmd">hg tags</command>.  The
   20.72 +      <literal>tip</literal> tag is a special <quote>floating</quote>
   20.73 +      tag, which always identifies the newest revision in the
   20.74 +      repository.</para>
   20.75 +
   20.76 +    <para id="x_374">In the output of the <command role="hg-cmd">hg
   20.77 +	tags</command> command, tags are listed in reverse order, by
   20.78 +      revision number.  This usually means that recent tags are listed
   20.79 +      before older tags.  It also means that <literal>tip</literal> is
   20.80 +      always going to be the first tag listed in the output of
   20.81 +      <command role="hg-cmd">hg tags</command>.</para>
   20.82 +
   20.83 +    <para id="x_375">When you run <command role="hg-cmd">hg log</command>, if it
   20.84 +      displays a revision that has tags associated with it, it will
   20.85 +      print those tags.</para>
   20.86 +
   20.87 +    &interaction.tag.log;
   20.88 +
   20.89 +    <para id="x_376">Any time you need to provide a revision ID to a Mercurial
   20.90 +      command, the command will accept a tag name in its place.
   20.91 +      Internally, Mercurial will translate your tag name into the
   20.92 +      corresponding revision ID, then use that.</para>
   20.93 +
   20.94 +    &interaction.tag.log.v1.0;
   20.95 +
   20.96 +    <para id="x_377">There's no limit on the number of tags you can have in a
   20.97 +      repository, or on the number of tags that a single revision can
   20.98 +      have.  As a practical matter, it's not a great idea to have
   20.99 +      <quote>too many</quote> (a number which will vary from project
  20.100 +      to project), simply because tags are supposed to help you to
  20.101 +      find revisions.  If you have lots of tags, the ease of using
  20.102 +      them to identify revisions diminishes rapidly.</para>
  20.103 +
  20.104 +    <para id="x_378">For example, if your project has milestones as frequent as
  20.105 +      every few days, it's perfectly reasonable to tag each one of
  20.106 +      those.  But if you have a continuous build system that makes
  20.107 +      sure every revision can be built cleanly, you'd be introducing a
  20.108 +      lot of noise if you were to tag every clean build.  Instead, you
  20.109 +      could tag failed builds (on the assumption that they're rare!),
  20.110 +      or simply not use tags to track buildability.</para>
  20.111 +
  20.112 +    <para id="x_379">If you want to remove a tag that you no longer want, use
  20.113 +      <command role="hg-cmd">hg tag --remove</command>.</para>
  20.114 +
  20.115 +    &interaction.tag.remove;
  20.116 +
  20.117 +    <para id="x_37a">You can also modify a tag at any time, so that it identifies
  20.118 +      a different revision, by simply issuing a new <command
  20.119 +	role="hg-cmd">hg tag</command> command. You'll have to use the
  20.120 +      <option role="hg-opt-tag">-f</option> option to tell Mercurial
  20.121 +      that you <emphasis>really</emphasis> want to update the
  20.122 +      tag.</para>
  20.123 +
  20.124 +    &interaction.tag.replace;
  20.125 +
  20.126 +    <para id="x_37b">There will still be a permanent record of the previous
  20.127 +      identity of the tag, but Mercurial will no longer use it.
  20.128 +      There's thus no penalty to tagging the wrong revision; all you
  20.129 +      have to do is turn around and tag the correct revision once you
  20.130 +      discover your error.</para>
  20.131 +
  20.132 +    <para id="x_37c">Mercurial stores tags in a normal revision-controlled file
  20.133 +      in your repository.  If you've created any tags, you'll find
  20.134 +      them in a file in the root of your repository named <filename
  20.135 +	role="special">.hgtags</filename>.  When you run the <command
  20.136 +	role="hg-cmd">hg tag</command> command, Mercurial modifies
  20.137 +      this file, then automatically commits the change to it.  This
  20.138 +      means that every time you run <command role="hg-cmd">hg
  20.139 +	tag</command>, you'll see a corresponding changeset in the
  20.140 +      output of <command role="hg-cmd">hg log</command>.</para>
  20.141 +
  20.142 +    &interaction.tag.tip;
  20.143 +
  20.144 +    <sect2>
  20.145 +      <title>Handling tag conflicts during a merge</title>
  20.146 +
  20.147 +      <para id="x_37d">You won't often need to care about the <filename
  20.148 +	  role="special">.hgtags</filename> file, but it sometimes
  20.149 +	makes its presence known during a merge.  The format of the
  20.150 +	file is simple: it consists of a series of lines.  Each line
  20.151 +	starts with a changeset hash, followed by a space, followed by
  20.152 +	the name of a tag.</para>
  20.153 +
  20.154 +      <para id="x_37e">If you're resolving a conflict in the <filename
  20.155 +	  role="special">.hgtags</filename> file during a merge,
  20.156 +	there's one twist to modifying the <filename
  20.157 +	  role="special">.hgtags</filename> file: when Mercurial is
  20.158 +	parsing the tags in a repository, it
  20.159 +	<emphasis>never</emphasis> reads the working copy of the
  20.160 +	<filename role="special">.hgtags</filename> file.  Instead, it
  20.161 +	reads the <emphasis>most recently committed</emphasis>
  20.162 +	revision of the file.</para>
  20.163 +
  20.164 +      <para id="x_37f">An unfortunate consequence of this design is that you
  20.165 +	can't actually verify that your merged <filename
  20.166 +	  role="special">.hgtags</filename> file is correct until
  20.167 +	<emphasis>after</emphasis> you've committed a change.  So if
  20.168 +	you find yourself resolving a conflict on <filename
  20.169 +	  role="special">.hgtags</filename> during a merge, be sure to
  20.170 +	run <command role="hg-cmd">hg tags</command> after you commit.
  20.171 +	If it finds an error in the <filename
  20.172 +	  role="special">.hgtags</filename> file, it will report the
  20.173 +	location of the error, which you can then fix and commit.  You
  20.174 +	should then run <command role="hg-cmd">hg tags</command>
  20.175 +	again, just to be sure that your fix is correct.</para>
  20.176 +    </sect2>
  20.177 +
  20.178 +    <sect2>
  20.179 +      <title>Tags and cloning</title>
  20.180 +
  20.181 +      <para id="x_380">You may have noticed that the <command role="hg-cmd">hg
  20.182 +	  clone</command> command has a <option
  20.183 +	  role="hg-opt-clone">-r</option> option that lets you clone
  20.184 +	an exact copy of the repository as of a particular changeset.
  20.185 +	The new clone will not contain any project history that comes
  20.186 +	after the revision you specified.  This has an interaction
  20.187 +	with tags that can surprise the unwary.</para>
  20.188 +
  20.189 +      <para id="x_381">Recall that a tag is stored as a revision to
  20.190 +	the <filename role="special">.hgtags</filename> file. When you
  20.191 +	create a tag, the changeset in which its recorded refers to an
  20.192 +	older changeset.  When you run <command role="hg-cmd">hg clone
  20.193 +	  -r foo</command> to clone a repository as of tag
  20.194 +	<literal>foo</literal>, the new clone <emphasis>will not
  20.195 +	  contain any revision newer than the one the tag refers to,
  20.196 +	  including the revision where the tag was created</emphasis>.
  20.197 +	The result is that you'll get exactly the right subset of the
  20.198 +	project's history in the new repository, but
  20.199 +	<emphasis>not</emphasis> the tag you might have
  20.200 +	expected.</para>
  20.201 +    </sect2>
  20.202 +
  20.203 +    <sect2>
  20.204 +      <title>When permanent tags are too much</title>
  20.205 +
  20.206 +      <para id="x_382">Since Mercurial's tags are revision controlled and carried
  20.207 +	around with a project's history, everyone you work with will
  20.208 +	see the tags you create.  But giving names to revisions has
  20.209 +	uses beyond simply noting that revision
  20.210 +	<literal>4237e45506ee</literal> is really
  20.211 +	<literal>v2.0.2</literal>.  If you're trying to track down a
  20.212 +	subtle bug, you might want a tag to remind you of something
  20.213 +	like <quote>Anne saw the symptoms with this
  20.214 +	  revision</quote>.</para>
  20.215 +
  20.216 +      <para id="x_383">For cases like this, what you might want to use are
  20.217 +	<emphasis>local</emphasis> tags. You can create a local tag
  20.218 +	with the <option role="hg-opt-tag">-l</option> option to the
  20.219 +	<command role="hg-cmd">hg tag</command> command.  This will
  20.220 +	store the tag in a file called <filename
  20.221 +	  role="special">.hg/localtags</filename>.  Unlike <filename
  20.222 +	  role="special">.hgtags</filename>, <filename
  20.223 +	  role="special">.hg/localtags</filename> is not revision
  20.224 +	controlled.  Any tags you create using <option
  20.225 +	  role="hg-opt-tag">-l</option> remain strictly local to the
  20.226 +	repository you're currently working in.</para>
  20.227 +    </sect2>
  20.228 +  </sect1>
  20.229 +
  20.230 +  <sect1>
  20.231 +    <title>The flow of changes&emdash;big picture vs. little</title>
  20.232 +
  20.233 +    <para id="x_384">To return to the outline I sketched at the
  20.234 +      beginning of the chapter, let's think about a project that has
  20.235 +      multiple concurrent pieces of work under development at
  20.236 +      once.</para>
  20.237 +
  20.238 +    <para id="x_385">There might be a push for a new <quote>main</quote> release;
  20.239 +      a new minor bugfix release to the last main release; and an
  20.240 +      unexpected <quote>hot fix</quote> to an old release that is now
  20.241 +      in maintenance mode.</para>
  20.242 +
  20.243 +    <para id="x_386">The usual way people refer to these different concurrent
  20.244 +      directions of development is as <quote>branches</quote>.
  20.245 +      However, we've already seen numerous times that Mercurial treats
  20.246 +      <emphasis>all of history</emphasis> as a series of branches and
  20.247 +      merges.  Really, what we have here is two ideas that are
  20.248 +      peripherally related, but which happen to share a name.</para>
  20.249 +    <itemizedlist>
  20.250 +      <listitem><para id="x_387"><quote>Big picture</quote> branches represent
  20.251 +	  the sweep of a project's evolution; people give them names,
  20.252 +	  and talk about them in conversation.</para>
  20.253 +      </listitem>
  20.254 +      <listitem><para id="x_388"><quote>Little picture</quote> branches are
  20.255 +	  artefacts of the day-to-day activity of developing and
  20.256 +	  merging changes.  They expose the narrative of how the code
  20.257 +	  was developed.</para>
  20.258 +      </listitem></itemizedlist>
  20.259 +  </sect1>
  20.260 +
  20.261 +  <sect1>
  20.262 +    <title>Managing big-picture branches in repositories</title>
  20.263 +
  20.264 +    <para id="x_389">The easiest way to isolate a <quote>big picture</quote>
  20.265 +      branch in Mercurial is in a dedicated repository.  If you have
  20.266 +      an existing shared repository&emdash;let's call it
  20.267 +      <literal>myproject</literal>&emdash;that reaches a
  20.268 +      <quote>1.0</quote> milestone, you can start to prepare for
  20.269 +      future maintenance releases on top of version 1.0 by tagging the
  20.270 +      revision from which you prepared the 1.0 release.</para>
  20.271 +
  20.272 +    &interaction.branch-repo.tag;
  20.273 +
  20.274 +    <para id="x_38a">You can then clone a new shared
  20.275 +      <literal>myproject-1.0.1</literal> repository as of that
  20.276 +      tag.</para>
  20.277 +
  20.278 +    &interaction.branch-repo.clone;
  20.279 +
  20.280 +    <para id="x_38b">Afterwards, if someone needs to work on a bug fix that ought
  20.281 +      to go into an upcoming 1.0.1 minor release, they clone the
  20.282 +      <literal>myproject-1.0.1</literal> repository, make their
  20.283 +      changes, and push them back.</para>
  20.284 +
  20.285 +    &interaction.branch-repo.bugfix;
  20.286 +
  20.287 +    <para id="x_38c">Meanwhile, development for
  20.288 +      the next major release can continue, isolated and unabated, in
  20.289 +      the <literal>myproject</literal> repository.</para>
  20.290 +
  20.291 +    &interaction.branch-repo.new;
  20.292 +  </sect1>
  20.293 +
  20.294 +  <sect1>
  20.295 +    <title>Don't repeat yourself: merging across branches</title>
  20.296 +
  20.297 +    <para id="x_38d">In many cases, if you have a bug to fix on a maintenance
  20.298 +      branch, the chances are good that the bug exists on your
  20.299 +      project's main branch (and possibly other maintenance branches,
  20.300 +      too).  It's a rare developer who wants to fix the same bug
  20.301 +      multiple times, so let's look at a few ways that Mercurial can
  20.302 +      help you to manage these bugfixes without duplicating your
  20.303 +      work.</para>
  20.304 +
  20.305 +    <para id="x_38e">In the simplest instance, all you need to do is pull changes
  20.306 +      from your maintenance branch into your local clone of the target
  20.307 +      branch.</para>
  20.308 +
  20.309 +    &interaction.branch-repo.pull;
  20.310 +
  20.311 +    <para id="x_38f">You'll then need to merge the heads of the two branches, and
  20.312 +      push back to the main branch.</para>
  20.313 +
  20.314 +    &interaction.branch-repo.merge;
  20.315 +  </sect1>
  20.316 +
  20.317 +  <sect1>
  20.318 +    <title>Naming branches within one repository</title>
  20.319 +
  20.320 +    <para id="x_390">In most instances, isolating branches in repositories is the
  20.321 +      right approach.  Its simplicity makes it easy to understand; and
  20.322 +      so it's hard to make mistakes.  There's a one-to-one
  20.323 +      relationship between branches you're working in and directories
  20.324 +      on your system.  This lets you use normal (non-Mercurial-aware)
  20.325 +      tools to work on files within a branch/repository.</para>
  20.326 +
  20.327 +    <para id="x_391">If you're more in the <quote>power user</quote> category
  20.328 +      (<emphasis>and</emphasis> your collaborators are too), there is
  20.329 +      an alternative way of handling branches that you can consider.
  20.330 +      I've already mentioned the human-level distinction between
  20.331 +      <quote>small picture</quote> and <quote>big picture</quote>
  20.332 +      branches.  While Mercurial works with multiple <quote>small
  20.333 +	picture</quote> branches in a repository all the time (for
  20.334 +      example after you pull changes in, but before you merge them),
  20.335 +      it can <emphasis>also</emphasis> work with multiple <quote>big
  20.336 +	picture</quote> branches.</para>
  20.337 +
  20.338 +    <para id="x_392">The key to working this way is that Mercurial lets you
  20.339 +      assign a persistent <emphasis>name</emphasis> to a branch.
  20.340 +      There always exists a branch named <literal>default</literal>.
  20.341 +      Even before you start naming branches yourself, you can find
  20.342 +      traces of the <literal>default</literal> branch if you look for
  20.343 +      them.</para>
  20.344 +
  20.345 +    <para id="x_393">As an example, when you run the <command role="hg-cmd">hg
  20.346 +	commit</command> command, and it pops up your editor so that
  20.347 +      you can enter a commit message, look for a line that contains
  20.348 +      the text <quote><literal>HG: branch default</literal></quote> at
  20.349 +      the bottom. This is telling you that your commit will occur on
  20.350 +      the branch named <literal>default</literal>.</para>
  20.351 +
  20.352 +    <para id="x_394">To start working with named branches, use the <command
  20.353 +	role="hg-cmd">hg branches</command> command.  This command
  20.354 +      lists the named branches already present in your repository,
  20.355 +      telling you which changeset is the tip of each.</para>
  20.356 +
  20.357 +    &interaction.branch-named.branches;
  20.358 +
  20.359 +    <para id="x_395">Since you haven't created any named branches yet, the only
  20.360 +      one that exists is <literal>default</literal>.</para>
  20.361 +
  20.362 +    <para id="x_396">To find out what the <quote>current</quote> branch is, run
  20.363 +      the <command role="hg-cmd">hg branch</command> command, giving
  20.364 +      it no arguments.  This tells you what branch the parent of the
  20.365 +      current changeset is on.</para>
  20.366 +
  20.367 +    &interaction.branch-named.branch;
  20.368 +
  20.369 +    <para id="x_397">To create a new branch, run the <command role="hg-cmd">hg
  20.370 +	branch</command> command again.  This time, give it one
  20.371 +      argument: the name of the branch you want to create.</para>
  20.372 +
  20.373 +    &interaction.branch-named.create;
  20.374 +
  20.375 +    <para id="x_398">After you've created a branch, you might wonder what effect
  20.376 +      the <command role="hg-cmd">hg branch</command> command has had.
  20.377 +      What do the <command role="hg-cmd">hg status</command> and
  20.378 +      <command role="hg-cmd">hg tip</command> commands report?</para>
  20.379 +
  20.380 +    &interaction.branch-named.status;
  20.381 +
  20.382 +    <para id="x_399">Nothing has changed in the
  20.383 +      working directory, and there's been no new history created.  As
  20.384 +      this suggests, running the <command role="hg-cmd">hg
  20.385 +	branch</command> command has no permanent effect; it only
  20.386 +      tells Mercurial what branch name to use the
  20.387 +      <emphasis>next</emphasis> time you commit a changeset.</para>
  20.388 +
  20.389 +    <para id="x_39a">When you commit a change, Mercurial records the name of the
  20.390 +      branch on which you committed.  Once you've switched from the
  20.391 +      <literal>default</literal> branch to another and committed,
  20.392 +      you'll see the name of the new branch show up in the output of
  20.393 +      <command role="hg-cmd">hg log</command>, <command
  20.394 +	role="hg-cmd">hg tip</command>, and other commands that
  20.395 +      display the same kind of output.</para>
  20.396 +
  20.397 +    &interaction.branch-named.commit;
  20.398 +
  20.399 +    <para id="x_39b">The <command role="hg-cmd">hg log</command>-like commands
  20.400 +      will print the branch name of every changeset that's not on the
  20.401 +      <literal>default</literal> branch.  As a result, if you never
  20.402 +      use named branches, you'll never see this information.</para>
  20.403 +
  20.404 +    <para id="x_39c">Once you've named a branch and committed a change with that
  20.405 +      name, every subsequent commit that descends from that change
  20.406 +      will inherit the same branch name.  You can change the name of a
  20.407 +      branch at any time, using the <command role="hg-cmd">hg
  20.408 +	branch</command> command.</para>
  20.409 +
  20.410 +    &interaction.branch-named.rebranch;
  20.411 +
  20.412 +    <para id="x_39d">In practice, this is something you won't do very often, as
  20.413 +      branch names tend to have fairly long lifetimes.  (This isn't a
  20.414 +      rule, just an observation.)</para>
  20.415 +  </sect1>
  20.416 +
  20.417 +  <sect1>
  20.418 +    <title>Dealing with multiple named branches in a
  20.419 +      repository</title>
  20.420 +
  20.421 +    <para id="x_39e">If you have more than one named branch in a repository,
  20.422 +      Mercurial will remember the branch that your working directory
  20.423 +      is on when you start a command like <command role="hg-cmd">hg
  20.424 +	update</command> or <command role="hg-cmd">hg pull
  20.425 +	-u</command>.  It will update the working directory to the tip
  20.426 +      of this branch, no matter what the <quote>repo-wide</quote> tip
  20.427 +      is.  To update to a revision that's on a different named branch,
  20.428 +      you may need to use the <option role="hg-opt-update">-C</option>
  20.429 +      option to <command role="hg-cmd">hg update</command>.</para>
  20.430 +
  20.431 +    <para id="x_39f">This behavior is a little subtle, so let's see it in
  20.432 +      action.  First, let's remind ourselves what branch we're
  20.433 +      currently on, and what branches are in our repository.</para>
  20.434 +
  20.435 +    &interaction.branch-named.parents;
  20.436 +
  20.437 +    <para id="x_3a0">We're on the <literal>bar</literal> branch, but there also
  20.438 +      exists an older <command role="hg-cmd">hg foo</command>
  20.439 +      branch.</para>
  20.440 +
  20.441 +    <para id="x_3a1">We can <command role="hg-cmd">hg update</command> back and
  20.442 +      forth between the tips of the <literal>foo</literal> and
  20.443 +      <literal>bar</literal> branches without needing to use the
  20.444 +      <option role="hg-opt-update">-C</option> option, because this
  20.445 +      only involves going backwards and forwards linearly through our
  20.446 +      change history.</para>
  20.447 +
  20.448 +    &interaction.branch-named.update-switchy;
  20.449 +
  20.450 +    <para id="x_3a2">If we go back to the <literal>foo</literal> branch and then
  20.451 +      run <command role="hg-cmd">hg update</command>, it will keep us
  20.452 +      on <literal>foo</literal>, not move us to the tip of
  20.453 +      <literal>bar</literal>.</para>
  20.454 +
  20.455 +    &interaction.branch-named.update-nothing;
  20.456 +
  20.457 +    <para id="x_3a3">Committing a new change on the <literal>foo</literal> branch
  20.458 +      introduces a new head.</para>
  20.459 +
  20.460 +    &interaction.branch-named.foo-commit;
  20.461 +  </sect1>
  20.462 +
  20.463 +  <sect1>
  20.464 +    <title>Branch names and merging</title>
  20.465 +
  20.466 +    <para id="x_3a4">As you've probably noticed, merges in Mercurial are not
  20.467 +      symmetrical. Let's say our repository has two heads, 17 and 23.
  20.468 +      If I <command role="hg-cmd">hg update</command> to 17 and then
  20.469 +      <command role="hg-cmd">hg merge</command> with 23, Mercurial
  20.470 +      records 17 as the first parent of the merge, and 23 as the
  20.471 +      second.  Whereas if I <command role="hg-cmd">hg update</command>
  20.472 +      to 23 and then <command role="hg-cmd">hg merge</command> with
  20.473 +      17, it records 23 as the first parent, and 17 as the
  20.474 +      second.</para>
  20.475 +
  20.476 +    <para id="x_3a5">This affects Mercurial's choice of branch name when you
  20.477 +      merge.  After a merge, Mercurial will retain the branch name of
  20.478 +      the first parent when you commit the result of the merge.  If
  20.479 +      your first parent's branch name is <literal>foo</literal>, and
  20.480 +      you merge with <literal>bar</literal>, the branch name will
  20.481 +      still be <literal>foo</literal> after you merge.</para>
  20.482 +
  20.483 +    <para id="x_3a6">It's not unusual for a repository to contain multiple heads,
  20.484 +      each with the same branch name.  Let's say I'm working on the
  20.485 +      <literal>foo</literal> branch, and so are you.  We commit
  20.486 +      different changes; I pull your changes; I now have two heads,
  20.487 +      each claiming to be on the <literal>foo</literal> branch.  The
  20.488 +      result of a merge will be a single head on the
  20.489 +      <literal>foo</literal> branch, as you might hope.</para>
  20.490 +
  20.491 +    <para id="x_3a7">But if I'm working on the <literal>bar</literal> branch, and
  20.492 +      I merge work from the <literal>foo</literal> branch, the result
  20.493 +      will remain on the <literal>bar</literal> branch.</para>
  20.494 +
  20.495 +    &interaction.branch-named.merge;
  20.496 +
  20.497 +    <para id="x_3a8">To give a more concrete example, if I'm working on the
  20.498 +      <literal>bleeding-edge</literal> branch, and I want to bring in
  20.499 +      the latest fixes from the <literal>stable</literal> branch,
  20.500 +      Mercurial will choose the <quote>right</quote>
  20.501 +      (<literal>bleeding-edge</literal>) branch name when I pull and
  20.502 +      merge from <literal>stable</literal>.</para>
  20.503 +  </sect1>
  20.504 +
  20.505 +  <sect1>
  20.506 +    <title>Branch naming is generally useful</title>
  20.507 +
  20.508 +    <para id="x_3a9">You shouldn't think of named branches as applicable only to
  20.509 +      situations where you have multiple long-lived branches
  20.510 +      cohabiting in a single repository.  They're very useful even in
  20.511 +      the one-branch-per-repository case.</para>
  20.512 +
  20.513 +    <para id="x_3aa">In the simplest case, giving a name to each branch gives you
  20.514 +      a permanent record of which branch a changeset originated on.
  20.515 +      This gives you more context when you're trying to follow the
  20.516 +      history of a long-lived branchy project.</para>
  20.517 +
  20.518 +    <para id="x_3ab">If you're working with shared repositories, you can set up a
  20.519 +      <literal role="hook">pretxnchangegroup</literal> hook on each
  20.520 +      that will block incoming changes that have the
  20.521 +      <quote>wrong</quote> branch name.  This provides a simple, but
  20.522 +      effective, defence against people accidentally pushing changes
  20.523 +      from a <quote>bleeding edge</quote> branch to a
  20.524 +      <quote>stable</quote> branch.  Such a hook might look like this
  20.525 +      inside the shared repo's <filename role="special">
  20.526 +	/.hgrc</filename>.</para>
  20.527 +    <programlisting>[hooks]
  20.528 +pretxnchangegroup.branch = hg heads --template '{branches} ' | grep mybranch</programlisting>
  20.529 +  </sect1>
  20.530 +</chapter>
  20.531 +
  20.532 +<!--
  20.533 +local variables: 
  20.534 +sgml-parent-document: ("00book.xml" "book" "chapter")
  20.535 +end:
  20.536 +-->
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/fr/ch09-undo.xml	Sat Jul 10 06:24:49 2010 +0100
    21.3 @@ -0,0 +1,1201 @@
    21.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
    21.5 +
    21.6 +<chapter id="chap:undo">
    21.7 +  <?dbhtml filename="finding-and-fixing-mistakes.html"?>
    21.8 +  <title>Finding and fixing mistakes</title>
    21.9 +
   21.10 +  <para id="x_d2">To err might be human, but to really handle the consequences
   21.11 +    well takes a top-notch revision control system.  In this chapter,
   21.12 +    we'll discuss some of the techniques you can use when you find
   21.13 +    that a problem has crept into your project.  Mercurial has some
   21.14 +    highly capable features that will help you to isolate the sources
   21.15 +    of problems, and to handle them appropriately.</para>
   21.16 +
   21.17 +  <sect1>
   21.18 +    <title>Erasing local history</title>
   21.19 +
   21.20 +    <sect2>
   21.21 +      <title>The accidental commit</title>
   21.22 +
   21.23 +      <para id="x_d3">I have the occasional but persistent problem of typing
   21.24 +	rather more quickly than I can think, which sometimes results
   21.25 +	in me committing a changeset that is either incomplete or
   21.26 +	plain wrong.  In my case, the usual kind of incomplete
   21.27 +	changeset is one in which I've created a new source file, but
   21.28 +	forgotten to <command role="hg-cmd">hg add</command> it.  A
   21.29 +	<quote>plain wrong</quote> changeset is not as common, but no
   21.30 +	less annoying.</para>
   21.31 +
   21.32 +    </sect2>
   21.33 +    <sect2 id="sec:undo:rollback">
   21.34 +      <title>Rolling back a transaction</title>
   21.35 +
   21.36 +      <para id="x_d4">In <xref linkend="sec:concepts:txn"/>, I
   21.37 +	mentioned that Mercurial treats each modification of a
   21.38 +	repository as a <emphasis>transaction</emphasis>.  Every time
   21.39 +	you commit a changeset or pull changes from another
   21.40 +	repository, Mercurial remembers what you did.  You can undo,
   21.41 +	or <emphasis>roll back</emphasis>, exactly one of these
   21.42 +	actions using the <command role="hg-cmd">hg rollback</command>
   21.43 +	command.  (See <xref linkend="sec:undo:rollback-after-push"/>
   21.44 +	for an important caveat about the use of this command.)</para>
   21.45 +
   21.46 +      <para id="x_d5">Here's a mistake that I often find myself making:
   21.47 +	committing a change in which I've created a new file, but
   21.48 +	forgotten to <command role="hg-cmd">hg add</command>
   21.49 +	it.</para>
   21.50 +
   21.51 +      &interaction.rollback.commit;
   21.52 +
   21.53 +      <para id="x_d6">Looking at the output of <command role="hg-cmd">hg
   21.54 +	  status</command> after the commit immediately confirms the
   21.55 +	error.</para>
   21.56 +
   21.57 +      &interaction.rollback.status;
   21.58 +
   21.59 +      <para id="x_d7">The commit captured the changes to the file
   21.60 +	<filename>a</filename>, but not the new file
   21.61 +	<filename>b</filename>.  If I were to push this changeset to a
   21.62 +	repository that I shared with a colleague, the chances are
   21.63 +	high that something in <filename>a</filename> would refer to
   21.64 +	<filename>b</filename>, which would not be present in their
   21.65 +	repository when they pulled my changes.  I would thus become
   21.66 +	the object of some indignation.</para>
   21.67 +
   21.68 +      <para id="x_d8">However, luck is with me&emdash;I've caught my error
   21.69 +	before I pushed the changeset.  I use the <command
   21.70 +	  role="hg-cmd">hg rollback</command> command, and Mercurial
   21.71 +	makes that last changeset vanish.</para>
   21.72 +
   21.73 +      &interaction.rollback.rollback;
   21.74 +
   21.75 +      <para id="x_d9">Notice that the changeset is no longer present in the
   21.76 +	repository's history, and the working directory once again
   21.77 +	thinks that the file <filename>a</filename> is modified.  The
   21.78 +	commit and rollback have left the working directory exactly as
   21.79 +	it was prior to the commit; the changeset has been completely
   21.80 +	erased.  I can now safely <command role="hg-cmd">hg
   21.81 +	  add</command> the file <filename>b</filename>, and rerun my
   21.82 +	commit.</para>
   21.83 +
   21.84 +      &interaction.rollback.add;
   21.85 +
   21.86 +    </sect2>
   21.87 +    <sect2>
   21.88 +      <title>The erroneous pull</title>
   21.89 +
   21.90 +      <para id="x_da">It's common practice with Mercurial to maintain separate
   21.91 +	development branches of a project in different repositories.
   21.92 +	Your development team might have one shared repository for
   21.93 +	your project's <quote>0.9</quote> release, and another,
   21.94 +	containing different changes, for the <quote>1.0</quote>
   21.95 +	release.</para>
   21.96 +
   21.97 +      <para id="x_db">Given this, you can imagine that the consequences could be
   21.98 +	messy if you had a local <quote>0.9</quote> repository, and
   21.99 +	accidentally pulled changes from the shared <quote>1.0</quote>
  21.100 +	repository into it.  At worst, you could be paying
  21.101 +	insufficient attention, and push those changes into the shared
  21.102 +	<quote>0.9</quote> tree, confusing your entire team (but don't
  21.103 +	worry, we'll return to this horror scenario later).  However,
  21.104 +	it's more likely that you'll notice immediately, because
  21.105 +	Mercurial will display the URL it's pulling from, or you will
  21.106 +	see it pull a suspiciously large number of changes into the
  21.107 +	repository.</para>
  21.108 +
  21.109 +      <para id="x_dc">The <command role="hg-cmd">hg rollback</command> command
  21.110 +	will work nicely to expunge all of the changesets that you
  21.111 +	just pulled.  Mercurial groups all changes from one <command
  21.112 +	  role="hg-cmd">hg pull</command> into a single transaction,
  21.113 +	so one <command role="hg-cmd">hg rollback</command> is all you
  21.114 +	need to undo this mistake.</para>
  21.115 +
  21.116 +    </sect2>
  21.117 +    <sect2 id="sec:undo:rollback-after-push">
  21.118 +      <title>Rolling back is useless once you've pushed</title>
  21.119 +
  21.120 +      <para id="x_dd">The value of the <command role="hg-cmd">hg
  21.121 +	  rollback</command> command drops to zero once you've pushed
  21.122 +	your changes to another repository.  Rolling back a change
  21.123 +	makes it disappear entirely, but <emphasis>only</emphasis> in
  21.124 +	the repository in which you perform the <command
  21.125 +	  role="hg-cmd">hg rollback</command>.  Because a rollback
  21.126 +	eliminates history, there's no way for the disappearance of a
  21.127 +	change to propagate between repositories.</para>
  21.128 +
  21.129 +      <para id="x_de">If you've pushed a change to another
  21.130 +	repository&emdash;particularly if it's a shared
  21.131 +	repository&emdash;it has essentially <quote>escaped into the
  21.132 +	  wild,</quote> and you'll have to recover from your mistake
  21.133 +	in a different way.  If you push a changeset somewhere, then
  21.134 +	roll it back, then pull from the repository you pushed to, the
  21.135 +	changeset you thought you'd gotten rid of will simply reappear
  21.136 +	in your repository.</para>
  21.137 +
  21.138 +      <para id="x_df">(If you absolutely know for sure that the change
  21.139 +	you want to roll back is the most recent change in the
  21.140 +	repository that you pushed to, <emphasis>and</emphasis> you
  21.141 +	know that nobody else could have pulled it from that
  21.142 +	repository, you can roll back the changeset there, too, but
  21.143 +	you really should not expect this to work reliably.  Sooner or
  21.144 +	later a change really will make it into a repository that you
  21.145 +	don't directly control (or have forgotten about), and come
  21.146 +	back to bite you.)</para>
  21.147 +
  21.148 +    </sect2>
  21.149 +    <sect2>
  21.150 +      <title>You can only roll back once</title>
  21.151 +
  21.152 +      <para id="x_e0">Mercurial stores exactly one transaction in its
  21.153 +	transaction log; that transaction is the most recent one that
  21.154 +	occurred in the repository. This means that you can only roll
  21.155 +	back one transaction.  If you expect to be able to roll back
  21.156 +	one transaction, then its predecessor, this is not the
  21.157 +	behavior you will get.</para>
  21.158 +
  21.159 +      &interaction.rollback.twice;
  21.160 +
  21.161 +      <para id="x_e1">Once you've rolled back one transaction in a repository,
  21.162 +	you can't roll back again in that repository until you perform
  21.163 +	another commit or pull.</para>
  21.164 +
  21.165 +    </sect2>
  21.166 +  </sect1>
  21.167 +  <sect1>
  21.168 +    <title>Reverting the mistaken change</title>
  21.169 +
  21.170 +    <para id="x_e2">If you make a modification to a file, and decide that you
  21.171 +      really didn't want to change the file at all, and you haven't
  21.172 +      yet committed your changes, the <command role="hg-cmd">hg
  21.173 +	revert</command> command is the one you'll need.  It looks at
  21.174 +      the changeset that's the parent of the working directory, and
  21.175 +      restores the contents of the file to their state as of that
  21.176 +      changeset. (That's a long-winded way of saying that, in the
  21.177 +      normal case, it undoes your modifications.)</para>
  21.178 +
  21.179 +    <para id="x_e3">Let's illustrate how the <command role="hg-cmd">hg
  21.180 +	revert</command> command works with yet another small example.
  21.181 +      We'll begin by modifying a file that Mercurial is already
  21.182 +      tracking.</para>
  21.183 +
  21.184 +    &interaction.daily.revert.modify;
  21.185 +
  21.186 +    <para id="x_e4">If we don't
  21.187 +      want that change, we can simply <command role="hg-cmd">hg
  21.188 +	revert</command> the file.</para>
  21.189 +
  21.190 +      &interaction.daily.revert.unmodify;
  21.191 +
  21.192 +    <para id="x_e5">The <command role="hg-cmd">hg revert</command> command
  21.193 +      provides us with an extra degree of safety by saving our
  21.194 +      modified file with a <filename>.orig</filename>
  21.195 +      extension.</para>
  21.196 +
  21.197 +    &interaction.daily.revert.status;
  21.198 +
  21.199 +    <tip>
  21.200 +      <title>Be careful with <filename>.orig</filename> files</title>
  21.201 +
  21.202 +      <para id="x_6b8">It's extremely unlikely that you are either using
  21.203 +	Mercurial to manage files with <filename>.orig</filename>
  21.204 +	extensions or that you even care about the contents of such
  21.205 +	files.  Just in case, though, it's useful to remember that
  21.206 +	<command role="hg-cmd">hg revert</command> will
  21.207 +	unconditionally overwrite an existing file with a
  21.208 +	<filename>.orig</filename> extension. For instance, if you
  21.209 +	already have a file named <filename>foo.orig</filename> when
  21.210 +	you revert <filename>foo</filename>, the contents of
  21.211 +	<filename>foo.orig</filename> will be clobbered.</para>
  21.212 +    </tip>
  21.213 +
  21.214 +    <para id="x_e6">Here is a summary of the cases that the <command
  21.215 +	role="hg-cmd">hg revert</command> command can deal with.  We
  21.216 +      will describe each of these in more detail in the section that
  21.217 +      follows.</para>
  21.218 +    <itemizedlist>
  21.219 +      <listitem><para id="x_e7">If you modify a file, it will restore the file
  21.220 +	  to its unmodified state.</para>
  21.221 +      </listitem>
  21.222 +      <listitem><para id="x_e8">If you <command role="hg-cmd">hg add</command> a
  21.223 +	  file, it will undo the <quote>added</quote> state of the
  21.224 +	  file, but leave the file itself untouched.</para>
  21.225 +      </listitem>
  21.226 +      <listitem><para id="x_e9">If you delete a file without telling Mercurial,
  21.227 +	  it will restore the file to its unmodified contents.</para>
  21.228 +      </listitem>
  21.229 +      <listitem><para id="x_ea">If you use the <command role="hg-cmd">hg
  21.230 +	    remove</command> command to remove a file, it will undo
  21.231 +	  the <quote>removed</quote> state of the file, and restore
  21.232 +	  the file to its unmodified contents.</para>
  21.233 +      </listitem></itemizedlist>
  21.234 +
  21.235 +    <sect2 id="sec:undo:mgmt">
  21.236 +      <title>File management errors</title>
  21.237 +
  21.238 +      <para id="x_eb">The <command role="hg-cmd">hg revert</command> command is
  21.239 +	useful for more than just modified files.  It lets you reverse
  21.240 +	the results of all of Mercurial's file management
  21.241 +	commands&emdash;<command role="hg-cmd">hg add</command>,
  21.242 +	<command role="hg-cmd">hg remove</command>, and so on.</para>
  21.243 +
  21.244 +      <para id="x_ec">If you <command role="hg-cmd">hg add</command> a file,
  21.245 +	then decide that in fact you don't want Mercurial to track it,
  21.246 +	use <command role="hg-cmd">hg revert</command> to undo the
  21.247 +	add.  Don't worry; Mercurial will not modify the file in any
  21.248 +	way.  It will just <quote>unmark</quote> the file.</para>
  21.249 +
  21.250 +      &interaction.daily.revert.add;
  21.251 +
  21.252 +      <para id="x_ed">Similarly, if you ask Mercurial to <command
  21.253 +	  role="hg-cmd">hg remove</command> a file, you can use
  21.254 +	<command role="hg-cmd">hg revert</command> to restore it to
  21.255 +	the contents it had as of the parent of the working directory.
  21.256 +	&interaction.daily.revert.remove; This works just as
  21.257 +	well for a file that you deleted by hand, without telling
  21.258 +	Mercurial (recall that in Mercurial terminology, this kind of
  21.259 +	file is called <quote>missing</quote>).</para>
  21.260 +
  21.261 +      &interaction.daily.revert.missing;
  21.262 +
  21.263 +      <para id="x_ee">If you revert a <command role="hg-cmd">hg copy</command>,
  21.264 +	the copied-to file remains in your working directory
  21.265 +	afterwards, untracked.  Since a copy doesn't affect the
  21.266 +	copied-from file in any way, Mercurial doesn't do anything
  21.267 +	with the copied-from file.</para>
  21.268 +
  21.269 +      &interaction.daily.revert.copy;
  21.270 +    </sect2>
  21.271 +  </sect1>
  21.272 +
  21.273 +  <sect1>
  21.274 +    <title>Dealing with committed changes</title>
  21.275 +
  21.276 +    <para id="x_f5">Consider a case where you have committed a change
  21.277 +      <emphasis>a</emphasis>, and another change
  21.278 +      <emphasis>b</emphasis> on top of it; you then realise that
  21.279 +      change <emphasis>a</emphasis> was incorrect.  Mercurial lets you
  21.280 +      <quote>back out</quote> an entire changeset automatically, and
  21.281 +      building blocks that let you reverse part of a changeset by
  21.282 +      hand.</para>
  21.283 +
  21.284 +    <para id="x_f6">Before you read this section, here's something to
  21.285 +      keep in mind: the <command role="hg-cmd">hg backout</command>
  21.286 +      command undoes the effect of a change by
  21.287 +      <emphasis>adding</emphasis> to your repository's history, not by
  21.288 +      modifying or erasing it.  It's the right tool to use if you're
  21.289 +      fixing bugs, but not if you're trying to undo some change that
  21.290 +      has catastrophic consequences.  To deal with those, see
  21.291 +      <xref linkend="sec:undo:aaaiiieee"/>.</para>
  21.292 +
  21.293 +    <sect2>
  21.294 +      <title>Backing out a changeset</title>
  21.295 +
  21.296 +      <para id="x_f7">The <command role="hg-cmd">hg backout</command> command
  21.297 +	lets you <quote>undo</quote> the effects of an entire
  21.298 +	changeset in an automated fashion.  Because Mercurial's
  21.299 +	history is immutable, this command <emphasis>does
  21.300 +	  not</emphasis> get rid of the changeset you want to undo.
  21.301 +	Instead, it creates a new changeset that
  21.302 +	<emphasis>reverses</emphasis> the effect of the to-be-undone
  21.303 +	changeset.</para>
  21.304 +
  21.305 +      <para id="x_f8">The operation of the <command role="hg-cmd">hg
  21.306 +	  backout</command> command is a little intricate, so let's
  21.307 +	illustrate it with some examples.  First, we'll create a
  21.308 +	repository with some simple changes.</para>
  21.309 +
  21.310 +      &interaction.backout.init;
  21.311 +
  21.312 +      <para id="x_f9">The <command role="hg-cmd">hg backout</command> command
  21.313 +	takes a single changeset ID as its argument; this is the
  21.314 +	changeset to back out.  Normally, <command role="hg-cmd">hg
  21.315 +	  backout</command> will drop you into a text editor to write
  21.316 +	a commit message, so you can record why you're backing the
  21.317 +	change out.  In this example, we provide a commit message on
  21.318 +	the command line using the <option
  21.319 +	  role="hg-opt-backout">-m</option> option.</para>
  21.320 +
  21.321 +    </sect2>
  21.322 +    <sect2>
  21.323 +      <title>Backing out the tip changeset</title>
  21.324 +
  21.325 +      <para id="x_fa">We're going to start by backing out the last changeset we
  21.326 +	committed.</para>
  21.327 +
  21.328 +      &interaction.backout.simple;
  21.329 +
  21.330 +      <para id="x_fb">You can see that the second line from
  21.331 +	<filename>myfile</filename> is no longer present.  Taking a
  21.332 +	look at the output of <command role="hg-cmd">hg log</command>
  21.333 +	gives us an idea of what the <command role="hg-cmd">hg
  21.334 +	  backout</command> command has done.
  21.335 +	&interaction.backout.simple.log; Notice that the new changeset
  21.336 +	that <command role="hg-cmd">hg backout</command> has created
  21.337 +	is a child of the changeset we backed out.  It's easier to see
  21.338 +	this in <xref linkend="fig:undo:backout"/>, which presents a
  21.339 +	graphical view of the change history.  As you can see, the
  21.340 +	history is nice and linear.</para>
  21.341 +
  21.342 +      <figure id="fig:undo:backout">
  21.343 +	<title>Backing out a change using the <command
  21.344 +	    role="hg-cmd">hg backout</command> command</title>
  21.345 +	<mediaobject>
  21.346 +	  <imageobject><imagedata fileref="figs/undo-simple.png"/></imageobject>
  21.347 +	  <textobject><phrase>XXX add text</phrase></textobject>
  21.348 +	</mediaobject>
  21.349 +      </figure>
  21.350 +
  21.351 +    </sect2>
  21.352 +    <sect2>
  21.353 +      <title>Backing out a non-tip change</title>
  21.354 +
  21.355 +      <para id="x_fd">If you want to back out a change other than the last one
  21.356 +	you committed, pass the <option
  21.357 +	  role="hg-opt-backout">--merge</option> option to the
  21.358 +	<command role="hg-cmd">hg backout</command> command.</para>
  21.359 +
  21.360 +      &interaction.backout.non-tip.clone;
  21.361 +
  21.362 +      <para id="x_fe">This makes backing out any changeset a
  21.363 +	<quote>one-shot</quote> operation that's usually simple and
  21.364 +	fast.</para>
  21.365 +
  21.366 +      &interaction.backout.non-tip.backout;
  21.367 +
  21.368 +      <para id="x_ff">If you take a look at the contents of
  21.369 +	<filename>myfile</filename> after the backout finishes, you'll
  21.370 +	see that the first and third changes are present, but not the
  21.371 +	second.</para>
  21.372 +
  21.373 +      &interaction.backout.non-tip.cat;
  21.374 +
  21.375 +      <para id="x_100">As the graphical history in <xref
  21.376 +	  linkend="fig:undo:backout-non-tip"/> illustrates, Mercurial
  21.377 +	still commits one change in this kind of situation (the
  21.378 +	box-shaped node is the ones that Mercurial commits
  21.379 +	automatically), but the revision graph now looks different.
  21.380 +	Before Mercurial begins the backout process, it first
  21.381 +	remembers what the current parent of the working directory is.
  21.382 +	It then backs out the target changeset, and commits that as a
  21.383 +	changeset.  Finally, it merges back to the previous parent of
  21.384 +	the working directory, but notice that it <emphasis>does not
  21.385 +	  commit</emphasis> the result of the merge.  The repository
  21.386 +	now contains two heads, and the working directory is in a
  21.387 +	merge state.</para>
  21.388 +
  21.389 +      <figure id="fig:undo:backout-non-tip">
  21.390 +	<title>Automated backout of a non-tip change using the
  21.391 +	  <command role="hg-cmd">hg backout</command> command</title>
  21.392 +	<mediaobject>
  21.393 +	  <imageobject><imagedata fileref="figs/undo-non-tip.png"/></imageobject>
  21.394 +	  <textobject><phrase>XXX add text</phrase></textobject>
  21.395 +	</mediaobject>
  21.396 +      </figure>
  21.397 +
  21.398 +      <para id="x_103">The result is that you end up <quote>back where you
  21.399 +	  were</quote>, only with some extra history that undoes the
  21.400 +	effect of the changeset you wanted to back out.</para>
  21.401 +
  21.402 +      <para id="x_6b9">You might wonder why Mercurial does not commit the result
  21.403 +	of the merge that it performed.  The reason lies in Mercurial
  21.404 +	behaving conservatively: a merge naturally has more scope for
  21.405 +	error than simply undoing the effect of the tip changeset,
  21.406 +	so your work will be safest if you first inspect (and test!)
  21.407 +	the result of the merge, <emphasis>then</emphasis> commit
  21.408 +	it.</para>
  21.409 +
  21.410 +      <sect3>
  21.411 +	<title>Always use the <option
  21.412 +	    role="hg-opt-backout">--merge</option> option</title>
  21.413 +
  21.414 +	<para id="x_104">In fact, since the <option
  21.415 +	    role="hg-opt-backout">--merge</option> option will do the
  21.416 +	  <quote>right thing</quote> whether or not the changeset
  21.417 +	  you're backing out is the tip (i.e. it won't try to merge if
  21.418 +	  it's backing out the tip, since there's no need), you should
  21.419 +	  <emphasis>always</emphasis> use this option when you run the
  21.420 +	  <command role="hg-cmd">hg backout</command> command.</para>
  21.421 +
  21.422 +      </sect3>
  21.423 +    </sect2>
  21.424 +    <sect2>
  21.425 +      <title>Gaining more control of the backout process</title>
  21.426 +
  21.427 +      <para id="x_105">While I've recommended that you always use the <option
  21.428 +	  role="hg-opt-backout">--merge</option> option when backing
  21.429 +	out a change, the <command role="hg-cmd">hg backout</command>
  21.430 +	command lets you decide how to merge a backout changeset.
  21.431 +	Taking control of the backout process by hand is something you
  21.432 +	will rarely need to do, but it can be useful to understand
  21.433 +	what the <command role="hg-cmd">hg backout</command> command
  21.434 +	is doing for you automatically.  To illustrate this, let's
  21.435 +	clone our first repository, but omit the backout change that
  21.436 +	it contains.</para>
  21.437 +
  21.438 +      &interaction.backout.manual.clone;
  21.439 +
  21.440 +      <para id="x_106">As with our
  21.441 +	earlier example, We'll commit a third changeset, then back out
  21.442 +	its parent, and see what happens.</para>
  21.443 +
  21.444 +      &interaction.backout.manual.backout;
  21.445 +
  21.446 +      <para id="x_107">Our new changeset is again a descendant of the changeset
  21.447 +	we backout out; it's thus a new head, <emphasis>not</emphasis>
  21.448 +	a descendant of the changeset that was the tip.  The <command
  21.449 +	  role="hg-cmd">hg backout</command> command was quite
  21.450 +	explicit in telling us this.</para>
  21.451 +
  21.452 +      &interaction.backout.manual.log;
  21.453 +
  21.454 +      <para id="x_108">Again, it's easier to see what has happened by looking at
  21.455 +	a graph of the revision history, in <xref
  21.456 +	  linkend="fig:undo:backout-manual"/>.  This makes it clear
  21.457 +	that when we use <command role="hg-cmd">hg backout</command>
  21.458 +	to back out a change other than the tip, Mercurial adds a new
  21.459 +	head to the repository (the change it committed is
  21.460 +	box-shaped).</para>
  21.461 +
  21.462 +      <figure id="fig:undo:backout-manual">
  21.463 +	<title>Backing out a change using the <command
  21.464 +	    role="hg-cmd">hg backout</command> command</title>
  21.465 +	<mediaobject>
  21.466 +	  <imageobject><imagedata fileref="figs/undo-manual.png"/></imageobject>
  21.467 +	  <textobject><phrase>XXX add text</phrase></textobject>
  21.468 +	</mediaobject>
  21.469 +      </figure>
  21.470 +
  21.471 +      <para id="x_10a">After the <command role="hg-cmd">hg backout</command>
  21.472 +	command has completed, it leaves the new
  21.473 +	<quote>backout</quote> changeset as the parent of the working
  21.474 +	directory.</para>
  21.475 +
  21.476 +      &interaction.backout.manual.parents;
  21.477 +
  21.478 +      <para id="x_10b">Now we have two isolated sets of changes.</para>
  21.479 +
  21.480 +      &interaction.backout.manual.heads;
  21.481 +
  21.482 +      <para id="x_10c">Let's think about what we expect to see as the contents of
  21.483 +	<filename>myfile</filename> now.  The first change should be
  21.484 +	present, because we've never backed it out.  The second change
  21.485 +	should be missing, as that's the change we backed out.  Since
  21.486 +	the history graph shows the third change as a separate head,
  21.487 +	we <emphasis>don't</emphasis> expect to see the third change
  21.488 +	present in <filename>myfile</filename>.</para>
  21.489 +
  21.490 +      &interaction.backout.manual.cat;
  21.491 +
  21.492 +      <para id="x_10d">To get the third change back into the file, we just do a
  21.493 +	normal merge of our two heads.</para>
  21.494 +
  21.495 +      &interaction.backout.manual.merge;
  21.496 +
  21.497 +      <para id="x_10e">Afterwards, the graphical history of our
  21.498 +	repository looks like
  21.499 +	<xref linkend="fig:undo:backout-manual-merge"/>.</para>
  21.500 +
  21.501 +      <figure id="fig:undo:backout-manual-merge">
  21.502 +	<title>Manually merging a backout change</title>
  21.503 +	<mediaobject>
  21.504 +	  <imageobject><imagedata fileref="figs/undo-manual-merge.png"/></imageobject>
  21.505 +	  <textobject><phrase>XXX add text</phrase></textobject>
  21.506 +	</mediaobject>
  21.507 +      </figure>
  21.508 +
  21.509 +    </sect2>
  21.510 +    <sect2>
  21.511 +      <title>Why <command role="hg-cmd">hg backout</command> works as
  21.512 +	it does</title>
  21.513 +
  21.514 +      <para id="x_110">Here's a brief description of how the <command
  21.515 +	  role="hg-cmd">hg backout</command> command works.</para>
  21.516 +      <orderedlist>
  21.517 +	<listitem><para id="x_111">It ensures that the working directory is
  21.518 +	    <quote>clean</quote>, i.e. that the output of <command
  21.519 +	      role="hg-cmd">hg status</command> would be empty.</para>
  21.520 +	</listitem>
  21.521 +	<listitem><para id="x_112">It remembers the current parent of the working
  21.522 +	    directory.  Let's call this changeset
  21.523 +	    <literal>orig</literal>.</para>
  21.524 +	</listitem>
  21.525 +	<listitem><para id="x_113">It does the equivalent of a <command
  21.526 +	      role="hg-cmd">hg update</command> to sync the working
  21.527 +	    directory to the changeset you want to back out.  Let's
  21.528 +	    call this changeset <literal>backout</literal>.</para>
  21.529 +	</listitem>
  21.530 +	<listitem><para id="x_114">It finds the parent of that changeset.  Let's
  21.531 +	    call that changeset <literal>parent</literal>.</para>
  21.532 +	</listitem>
  21.533 +	<listitem><para id="x_115">For each file that the
  21.534 +	    <literal>backout</literal> changeset affected, it does the
  21.535 +	    equivalent of a <command role="hg-cmd">hg revert -r
  21.536 +	      parent</command> on that file, to restore it to the
  21.537 +	    contents it had before that changeset was
  21.538 +	    committed.</para>
  21.539 +	</listitem>
  21.540 +	<listitem><para id="x_116">It commits the result as a new changeset.
  21.541 +	    This changeset has <literal>backout</literal> as its
  21.542 +	    parent.</para>
  21.543 +	</listitem>
  21.544 +	<listitem><para id="x_117">If you specify <option
  21.545 +	      role="hg-opt-backout">--merge</option> on the command
  21.546 +	    line, it merges with <literal>orig</literal>, and commits
  21.547 +	    the result of the merge.</para>
  21.548 +	</listitem></orderedlist>
  21.549 +
  21.550 +      <para id="x_118">An alternative way to implement the <command
  21.551 +	  role="hg-cmd">hg backout</command> command would be to
  21.552 +	<command role="hg-cmd">hg export</command> the
  21.553 +	to-be-backed-out changeset as a diff, then use the <option
  21.554 +	  role="cmd-opt-patch">--reverse</option> option to the
  21.555 +	<command>patch</command> command to reverse the effect of the
  21.556 +	change without fiddling with the working directory.  This
  21.557 +	sounds much simpler, but it would not work nearly as
  21.558 +	well.</para>
  21.559 +
  21.560 +      <para id="x_119">The reason that <command role="hg-cmd">hg
  21.561 +	  backout</command> does an update, a commit, a merge, and
  21.562 +	another commit is to give the merge machinery the best chance
  21.563 +	to do a good job when dealing with all the changes
  21.564 +	<emphasis>between</emphasis> the change you're backing out and
  21.565 +	the current tip.</para>
  21.566 +
  21.567 +      <para id="x_11a">If you're backing out a changeset that's 100 revisions
  21.568 +	back in your project's history, the chances that the
  21.569 +	<command>patch</command> command will be able to apply a
  21.570 +	reverse diff cleanly are not good, because intervening changes
  21.571 +	are likely to have <quote>broken the context</quote> that
  21.572 +	<command>patch</command> uses to determine whether it can
  21.573 +	apply a patch (if this sounds like gibberish, see <xref
  21.574 +	  linkend="sec:mq:patch"/> for a
  21.575 +	discussion of the <command>patch</command> command).  Also,
  21.576 +	Mercurial's merge machinery will handle files and directories
  21.577 +	being renamed, permission changes, and modifications to binary
  21.578 +	files, none of which <command>patch</command> can deal
  21.579 +	with.</para>
  21.580 +
  21.581 +    </sect2>
  21.582 +  </sect1>
  21.583 +  <sect1 id="sec:undo:aaaiiieee">
  21.584 +    <title>Changes that should never have been</title>
  21.585 +
  21.586 +    <para id="x_11b">Most of the time, the <command role="hg-cmd">hg
  21.587 +	backout</command> command is exactly what you need if you want
  21.588 +      to undo the effects of a change.  It leaves a permanent record
  21.589 +      of exactly what you did, both when committing the original
  21.590 +      changeset and when you cleaned up after it.</para>
  21.591 +
  21.592 +    <para id="x_11c">On rare occasions, though, you may find that you've
  21.593 +      committed a change that really should not be present in the
  21.594 +      repository at all.  For example, it would be very unusual, and
  21.595 +      usually considered a mistake, to commit a software project's
  21.596 +      object files as well as its source files.  Object files have
  21.597 +      almost no intrinsic value, and they're <emphasis>big</emphasis>,
  21.598 +      so they increase the size of the repository and the amount of
  21.599 +      time it takes to clone or pull changes.</para>
  21.600 +
  21.601 +    <para id="x_11d">Before I discuss the options that you have if you commit a
  21.602 +      <quote>brown paper bag</quote> change (the kind that's so bad
  21.603 +      that you want to pull a brown paper bag over your head), let me
  21.604 +      first discuss some approaches that probably won't work.</para>
  21.605 +
  21.606 +    <para id="x_11e">Since Mercurial treats history as
  21.607 +      accumulative&emdash;every change builds on top of all changes
  21.608 +      that preceded it&emdash;you generally can't just make disastrous
  21.609 +      changes disappear.  The one exception is when you've just
  21.610 +      committed a change, and it hasn't been pushed or pulled into
  21.611 +      another repository.  That's when you can safely use the <command
  21.612 +	role="hg-cmd">hg rollback</command> command, as I detailed in
  21.613 +      <xref linkend="sec:undo:rollback"/>.</para>
  21.614 +
  21.615 +    <para id="x_11f">After you've pushed a bad change to another repository, you
  21.616 +      <emphasis>could</emphasis> still use <command role="hg-cmd">hg
  21.617 +	rollback</command> to make your local copy of the change
  21.618 +      disappear, but it won't have the consequences you want.  The
  21.619 +      change will still be present in the remote repository, so it
  21.620 +      will reappear in your local repository the next time you
  21.621 +      pull.</para>
  21.622 +
  21.623 +    <para id="x_120">If a situation like this arises, and you know which
  21.624 +      repositories your bad change has propagated into, you can
  21.625 +      <emphasis>try</emphasis> to get rid of the change from
  21.626 +      <emphasis>every</emphasis> one of those repositories.  This is,
  21.627 +      of course, not a satisfactory solution: if you miss even a
  21.628 +      single repository while you're expunging, the change is still
  21.629 +      <quote>in the wild</quote>, and could propagate further.</para>
  21.630 +
  21.631 +    <para id="x_121">If you've committed one or more changes
  21.632 +      <emphasis>after</emphasis> the change that you'd like to see
  21.633 +      disappear, your options are further reduced. Mercurial doesn't
  21.634 +      provide a way to <quote>punch a hole</quote> in history, leaving
  21.635 +      changesets intact.</para>
  21.636 +
  21.637 +    <sect2>
  21.638 +      <title>Backing out a merge</title>
  21.639 +
  21.640 +      <para id="x_6ba">Since merges are often complicated, it is not unheard of
  21.641 +	for a merge to be mangled badly, but committed erroneously.
  21.642 +	Mercurial provides an important safeguard against bad merges
  21.643 +	by refusing to commit unresolved files, but human ingenuity
  21.644 +	guarantees that it is still possible to mess a merge up and
  21.645 +	commit it.</para>
  21.646 +
  21.647 +      <para id="x_6bb">Given a bad merge that has been committed, usually the
  21.648 +	best way to approach it is to simply try to repair the damage
  21.649 +	by hand.  A complete disaster that cannot be easily fixed up
  21.650 +	by hand ought to be very rare, but the <command
  21.651 +	  role="hg-cmd">hg backout</command> command may help in
  21.652 +	making the cleanup easier. It offers a <option
  21.653 +	  role="hg-opt-backout">--parent</option> option, which lets
  21.654 +	you specify which parent to revert to when backing out a
  21.655 +	merge.</para>
  21.656 +
  21.657 +      <figure id="fig:undo:bad-merge-1">
  21.658 +	<title>A bad merge</title>
  21.659 +	<mediaobject>
  21.660 +	  <imageobject><imagedata fileref="figs/bad-merge-1.png"/></imageobject>
  21.661 +	  <textobject><phrase>XXX add text</phrase></textobject>
  21.662 +	</mediaobject>
  21.663 +      </figure>
  21.664 +
  21.665 +      <para id="x_6bc">Suppose we have a revision graph like that in <xref
  21.666 +	  linkend="fig:undo:bad-merge-1"/>.  What we'd like is to
  21.667 +	<emphasis>redo</emphasis> the merge of revisions 2 and
  21.668 +	3.</para>
  21.669 +
  21.670 +      <para id="x_6bd">One way to do so would be as follows.</para>
  21.671 +
  21.672 +      <orderedlist>
  21.673 +	<listitem>
  21.674 +	  <para id="x_6be">Call <command role="hg-cmd">hg backout --rev=4
  21.675 +	      --parent=2</command>.  This tells <command
  21.676 +	      role="hg-cmd">hg backout</command> to back out revision
  21.677 +	    4, which is the bad merge, and to when deciding which
  21.678 +	    revision to prefer, to choose parent 2, one of the parents
  21.679 +	    of the merge.  The effect can be seen in <xref
  21.680 +	      linkend="fig:undo:bad-merge-2"/>.</para>
  21.681 +	  <figure id="fig:undo:bad-merge-2">
  21.682 +	    <title>Backing out the merge, favoring one parent</title>
  21.683 +	    <mediaobject>
  21.684 +	      <imageobject><imagedata fileref="figs/bad-merge-2.png"/></imageobject>
  21.685 +	      <textobject><phrase>XXX add text</phrase></textobject>
  21.686 +	    </mediaobject>
  21.687 +	  </figure>
  21.688 +	</listitem>
  21.689 +
  21.690 +	<listitem>
  21.691 +	  <para id="x_6bf">Call <command role="hg-cmd">hg backout --rev=4
  21.692 +	      --parent=3</command>.  This tells <command
  21.693 +	      role="hg-cmd">hg backout</command> to back out revision
  21.694 +	    4 again, but this time to choose parent 3, the other
  21.695 +	    parent of the merge.  The result is visible in <xref
  21.696 +	    linkend="fig:undo:bad-merge-3"/>, in which the repository
  21.697 +	    now contains three heads.</para>
  21.698 +	  <figure id="fig:undo:bad-merge-3">
  21.699 +	    <title>Backing out the merge, favoring the other
  21.700 +	      parent</title>
  21.701 +	    <mediaobject>
  21.702 +	      <imageobject><imagedata fileref="figs/bad-merge-3.png"/></imageobject>
  21.703 +	      <textobject><phrase>XXX add text</phrase></textobject>
  21.704 +	    </mediaobject>
  21.705 +	  </figure>
  21.706 +	</listitem>
  21.707 +
  21.708 +	<listitem>
  21.709 +	  <para id="x_6c0">Redo the bad merge by merging the two backout heads,
  21.710 +	    which reduces the number of heads in the repository to
  21.711 +	    two, as can be seen in <xref
  21.712 +	      linkend="fig:undo:bad-merge-4"/>.</para>
  21.713 +	  <figure id="fig:undo:bad-merge-4">
  21.714 +	    <title>Merging the backouts</title>
  21.715 +	    <mediaobject>
  21.716 +	      <imageobject><imagedata fileref="figs/bad-merge-4.png"/></imageobject>
  21.717 +	      <textobject><phrase>XXX add text</phrase></textobject>
  21.718 +	    </mediaobject>
  21.719 +	  </figure>
  21.720 +	</listitem>
  21.721 +
  21.722 +	<listitem>
  21.723 +	  <para id="x_6c1">Merge with the commit that was made after the bad
  21.724 +	    merge, as shown in <xref
  21.725 +	      linkend="fig:undo:bad-merge-5"/>.</para>
  21.726 +	  <figure id="fig:undo:bad-merge-5">
  21.727 +	    <title>Merging the backouts</title>
  21.728 +	    <mediaobject>
  21.729 +	      <imageobject><imagedata fileref="figs/bad-merge-5.png"/></imageobject>
  21.730 +	      <textobject><phrase>XXX add text</phrase></textobject>
  21.731 +	    </mediaobject>
  21.732 +	  </figure>
  21.733 +	</listitem>
  21.734 +      </orderedlist>
  21.735 +    </sect2>
  21.736 +
  21.737 +    <sect2>
  21.738 +      <title>Protect yourself from <quote>escaped</quote>
  21.739 +	changes</title>
  21.740 +
  21.741 +      <para id="x_123">If you've committed some changes to your local repository
  21.742 +	and they've been pushed or pulled somewhere else, this isn't
  21.743 +	necessarily a disaster.  You can protect yourself ahead of
  21.744 +	time against some classes of bad changeset.  This is
  21.745 +	particularly easy if your team usually pulls changes from a
  21.746 +	central repository.</para>
  21.747 +
  21.748 +      <para id="x_124">By configuring some hooks on that repository to validate
  21.749 +	incoming changesets (see chapter <xref linkend="chap:hook"/>),
  21.750 +	you can
  21.751 +	automatically prevent some kinds of bad changeset from being
  21.752 +	pushed to the central repository at all.  With such a
  21.753 +	configuration in place, some kinds of bad changeset will
  21.754 +	naturally tend to <quote>die out</quote> because they can't
  21.755 +	propagate into the central repository.  Better yet, this
  21.756 +	happens without any need for explicit intervention.</para>
  21.757 +
  21.758 +      <para id="x_125">For instance, an incoming change hook that
  21.759 +	verifies that a changeset will actually compile can prevent
  21.760 +	people from inadvertently <quote>breaking the
  21.761 +	  build</quote>.</para>
  21.762 +    </sect2>
  21.763 +
  21.764 +    <sect2>
  21.765 +      <title>What to do about sensitive changes that escape</title>
  21.766 +
  21.767 +      <para id="x_6c2">Even a carefully run project can suffer an unfortunate
  21.768 +	event such as the committing and uncontrolled propagation of a
  21.769 +	file that contains important passwords.</para>
  21.770 +
  21.771 +      <para id="x_6c3">If something like this happens to you, and the information
  21.772 +	that gets accidentally propagated is truly sensitive, your
  21.773 +	first step should be to mitigate the effect of the leak
  21.774 +	without trying to control the leak itself. If you are not 100%
  21.775 +	certain that you know exactly who could have seen the changes,
  21.776 +	you should immediately change passwords, cancel credit cards,
  21.777 +	or find some other way to make sure that the information that
  21.778 +	has leaked is no longer useful.  In other words, assume that
  21.779 +	the change has propagated far and wide, and that there's
  21.780 +	nothing more you can do.</para>
  21.781 +
  21.782 +      <para id="x_6c4">You might hope that there would be mechanisms you could
  21.783 +	use to either figure out who has seen a change or to erase the
  21.784 +	change permanently everywhere, but there are good reasons why
  21.785 +	these are not possible.</para>
  21.786 +
  21.787 +      <para id="x_6c5">Mercurial does not provide an audit trail of who has
  21.788 +	pulled changes from a repository, because it is usually either
  21.789 +	impossible to record such information or trivial to spoof it.
  21.790 +	In a multi-user or networked environment, you should thus be
  21.791 +	extremely skeptical of yourself if you think that you have
  21.792 +	identified every place that a sensitive changeset has
  21.793 +	propagated to.  Don't forget that people can and will send
  21.794 +	bundles by email, have their backup software save data
  21.795 +	offsite, carry repositories on USB sticks, and find other
  21.796 +	completely innocent ways to confound your attempts to track
  21.797 +	down every copy of a problematic change.</para>
  21.798 +
  21.799 +      <para id="x_6c6">Mercurial also does not provide a way to make a file or
  21.800 +	changeset completely disappear from history, because there is
  21.801 +	no way to enforce its disappearance; someone could easily
  21.802 +	modify their copy of Mercurial to ignore such directives. In
  21.803 +	addition, even if Mercurial provided such a capability,
  21.804 +	someone who simply hadn't pulled a <quote>make this file
  21.805 +	  disappear</quote> changeset wouldn't be affected by it, nor
  21.806 +	would web crawlers visiting at the wrong time, disk backups,
  21.807 +	or other mechanisms.  Indeed, no distributed revision control
  21.808 +	system can make data reliably vanish. Providing the illusion
  21.809 +	of such control could easily give a false sense of security,
  21.810 +	and be worse than not providing it at all.</para>
  21.811 +    </sect2>
  21.812 +  </sect1>
  21.813 +
  21.814 +  <sect1 id="sec:undo:bisect">
  21.815 +    <title>Finding the source of a bug</title>
  21.816 +
  21.817 +    <para id="x_126">While it's all very well to be able to back out a changeset
  21.818 +      that introduced a bug, this requires that you know which
  21.819 +      changeset to back out.  Mercurial provides an invaluable
  21.820 +      command, called <command role="hg-cmd">hg bisect</command>, that
  21.821 +      helps you to automate this process and accomplish it very
  21.822 +      efficiently.</para>
  21.823 +
  21.824 +    <para id="x_127">The idea behind the <command role="hg-cmd">hg
  21.825 +	bisect</command> command is that a changeset has introduced
  21.826 +      some change of behavior that you can identify with a simple
  21.827 +      pass/fail test.  You don't know which piece of code introduced the
  21.828 +      change, but you know how to test for the presence of the bug.
  21.829 +      The <command role="hg-cmd">hg bisect</command> command uses your
  21.830 +      test to direct its search for the changeset that introduced the
  21.831 +      code that caused the bug.</para>
  21.832 +
  21.833 +    <para id="x_128">Here are a few scenarios to help you understand how you
  21.834 +      might apply this command.</para>
  21.835 +    <itemizedlist>
  21.836 +      <listitem><para id="x_129">The most recent version of your software has a
  21.837 +	  bug that you remember wasn't present a few weeks ago, but
  21.838 +	  you don't know when it was introduced.  Here, your binary
  21.839 +	  test checks for the presence of that bug.</para>
  21.840 +      </listitem>
  21.841 +      <listitem><para id="x_12a">You fixed a bug in a rush, and now it's time to
  21.842 +	  close the entry in your team's bug database.  The bug
  21.843 +	  database requires a changeset ID when you close an entry,
  21.844 +	  but you don't remember which changeset you fixed the bug in.
  21.845 +	  Once again, your binary test checks for the presence of the
  21.846 +	  bug.</para>
  21.847 +      </listitem>
  21.848 +      <listitem><para id="x_12b">Your software works correctly, but runs 15%
  21.849 +	  slower than the last time you measured it.  You want to know
  21.850 +	  which changeset introduced the performance regression.  In
  21.851 +	  this case, your binary test measures the performance of your
  21.852 +	  software, to see whether it's <quote>fast</quote> or
  21.853 +	  <quote>slow</quote>.</para>
  21.854 +      </listitem>
  21.855 +      <listitem><para id="x_12c">The sizes of the components of your project that
  21.856 +	  you ship exploded recently, and you suspect that something
  21.857 +	  changed in the way you build your project.</para>
  21.858 +      </listitem></itemizedlist>
  21.859 +
  21.860 +    <para id="x_12d">From these examples, it should be clear that the <command
  21.861 +	role="hg-cmd">hg bisect</command> command is not useful only
  21.862 +      for finding the sources of bugs.  You can use it to find any
  21.863 +      <quote>emergent property</quote> of a repository (anything that
  21.864 +      you can't find from a simple text search of the files in the
  21.865 +      tree) for which you can write a binary test.</para>
  21.866 +
  21.867 +    <para id="x_12e">We'll introduce a little bit of terminology here, just to
  21.868 +      make it clear which parts of the search process are your
  21.869 +      responsibility, and which are Mercurial's.  A
  21.870 +      <emphasis>test</emphasis> is something that
  21.871 +      <emphasis>you</emphasis> run when <command role="hg-cmd">hg
  21.872 +	bisect</command> chooses a changeset.  A
  21.873 +      <emphasis>probe</emphasis> is what <command role="hg-cmd">hg
  21.874 +	bisect</command> runs to tell whether a revision is good.
  21.875 +      Finally, we'll use the word <quote>bisect</quote>, as both a
  21.876 +      noun and a verb, to stand in for the phrase <quote>search using
  21.877 +	the <command role="hg-cmd">hg bisect</command>
  21.878 +	command</quote>.</para>
  21.879 +
  21.880 +    <para id="x_12f">One simple way to automate the searching process would be
  21.881 +      simply to probe every changeset.  However, this scales poorly.
  21.882 +      If it took ten minutes to test a single changeset, and you had
  21.883 +      10,000 changesets in your repository, the exhaustive approach
  21.884 +      would take on average 35 <emphasis>days</emphasis> to find the
  21.885 +      changeset that introduced a bug.  Even if you knew that the bug
  21.886 +      was introduced by one of the last 500 changesets, and limited
  21.887 +      your search to those, you'd still be looking at over 40 hours to
  21.888 +      find the changeset that introduced your bug.</para>
  21.889 +
  21.890 +    <para id="x_130">What the <command role="hg-cmd">hg bisect</command> command
  21.891 +      does is use its knowledge of the <quote>shape</quote> of your
  21.892 +      project's revision history to perform a search in time
  21.893 +      proportional to the <emphasis>logarithm</emphasis> of the number
  21.894 +      of changesets to check (the kind of search it performs is called
  21.895 +      a dichotomic search).  With this approach, searching through
  21.896 +      10,000 changesets will take less than three hours, even at ten
  21.897 +      minutes per test (the search will require about 14 tests).
  21.898 +      Limit your search to the last hundred changesets, and it will
  21.899 +      take only about an hour (roughly seven tests).</para>
  21.900 +
  21.901 +    <para id="x_131">The <command role="hg-cmd">hg bisect</command> command is
  21.902 +      aware of the <quote>branchy</quote> nature of a Mercurial
  21.903 +      project's revision history, so it has no problems dealing with
  21.904 +      branches, merges, or multiple heads in a repository.  It can
  21.905 +      prune entire branches of history with a single probe, which is
  21.906 +      how it operates so efficiently.</para>
  21.907 +
  21.908 +    <sect2>
  21.909 +      <title>Using the <command role="hg-cmd">hg bisect</command>
  21.910 +	command</title>
  21.911 +
  21.912 +      <para id="x_132">Here's an example of <command role="hg-cmd">hg
  21.913 +	  bisect</command> in action.</para>
  21.914 +
  21.915 +      <note>
  21.916 +	<para id="x_133">  In versions 0.9.5 and earlier of Mercurial, <command
  21.917 +	    role="hg-cmd">hg bisect</command> was not a core command:
  21.918 +	  it was distributed with Mercurial as an extension. This
  21.919 +	  section describes the built-in command, not the old
  21.920 +	  extension.</para>
  21.921 +      </note>
  21.922 +
  21.923 +      <para id="x_134">Now let's create a repository, so that we can try out the
  21.924 +	<command role="hg-cmd">hg bisect</command> command in
  21.925 +	isolation.</para>
  21.926 +
  21.927 +      &interaction.bisect.init;
  21.928 +
  21.929 +      <para id="x_135">We'll simulate a project that has a bug in it in a
  21.930 +	simple-minded way: create trivial changes in a loop, and
  21.931 +	nominate one specific change that will have the
  21.932 +	<quote>bug</quote>.  This loop creates 35 changesets, each
  21.933 +	adding a single file to the repository. We'll represent our
  21.934 +	<quote>bug</quote> with a file that contains the text <quote>i
  21.935 +	  have a gub</quote>.</para>
  21.936 +
  21.937 +      &interaction.bisect.commits;
  21.938 +
  21.939 +      <para id="x_136">The next thing that we'd like to do is figure out how to
  21.940 +	use the <command role="hg-cmd">hg bisect</command> command.
  21.941 +	We can use Mercurial's normal built-in help mechanism for
  21.942 +	this.</para>
  21.943 +
  21.944 +      &interaction.bisect.help;
  21.945 +
  21.946 +      <para id="x_137">The <command role="hg-cmd">hg bisect</command> command
  21.947 +	works in steps.  Each step proceeds as follows.</para>
  21.948 +      <orderedlist>
  21.949 +	<listitem><para id="x_138">You run your binary test.</para>
  21.950 +	  <itemizedlist>
  21.951 +	    <listitem><para id="x_139">If the test succeeded, you tell <command
  21.952 +		  role="hg-cmd">hg bisect</command> by running the
  21.953 +		<command role="hg-cmd">hg bisect --good</command>
  21.954 +		command.</para>
  21.955 +	    </listitem>
  21.956 +	    <listitem><para id="x_13a">If it failed, run the <command
  21.957 +		  role="hg-cmd">hg bisect --bad</command>
  21.958 +		command.</para></listitem></itemizedlist>
  21.959 +	</listitem>
  21.960 +	<listitem><para id="x_13b">The command uses your information to decide
  21.961 +	    which changeset to test next.</para>
  21.962 +	</listitem>
  21.963 +	<listitem><para id="x_13c">It updates the working directory to that
  21.964 +	    changeset, and the process begins again.</para>
  21.965 +	</listitem></orderedlist>
  21.966 +      <para id="x_13d">The process ends when <command role="hg-cmd">hg
  21.967 +	  bisect</command> identifies a unique changeset that marks
  21.968 +	the point where your test transitioned from
  21.969 +	<quote>succeeding</quote> to <quote>failing</quote>.</para>
  21.970 +
  21.971 +      <para id="x_13e">To start the search, we must run the <command
  21.972 +	  role="hg-cmd">hg bisect --reset</command> command.</para>
  21.973 +
  21.974 +      &interaction.bisect.search.init;
  21.975 +
  21.976 +      <para id="x_13f">In our case, the binary test we use is simple: we check to
  21.977 +	see if any file in the repository contains the string <quote>i
  21.978 +	  have a gub</quote>.  If it does, this changeset contains the
  21.979 +	change that <quote>caused the bug</quote>.  By convention, a
  21.980 +	changeset that has the property we're searching for is
  21.981 +	<quote>bad</quote>, while one that doesn't is
  21.982 +	<quote>good</quote>.</para>
  21.983 +
  21.984 +      <para id="x_140">Most of the time, the revision to which the working
  21.985 +	directory is synced (usually the tip) already exhibits the
  21.986 +	problem introduced by the buggy change, so we'll mark it as
  21.987 +	<quote>bad</quote>.</para>
  21.988 +
  21.989 +      &interaction.bisect.search.bad-init;
  21.990 +
  21.991 +      <para id="x_141">Our next task is to nominate a changeset that we know
  21.992 +	<emphasis>doesn't</emphasis> have the bug; the <command
  21.993 +	  role="hg-cmd">hg bisect</command> command will
  21.994 +	<quote>bracket</quote> its search between the first pair of
  21.995 +	good and bad changesets.  In our case, we know that revision
  21.996 +	10 didn't have the bug.  (I'll have more words about choosing
  21.997 +	the first <quote>good</quote> changeset later.)</para>
  21.998 +
  21.999 +      &interaction.bisect.search.good-init;
 21.1000 +
 21.1001 +      <para id="x_142">Notice that this command printed some output.</para>
 21.1002 +      <itemizedlist>
 21.1003 +	<listitem><para id="x_143">It told us how many changesets it must
 21.1004 +	    consider before it can identify the one that introduced
 21.1005 +	    the bug, and how many tests that will require.</para>
 21.1006 +	</listitem>
 21.1007 +	<listitem><para id="x_144">It updated the working directory to the next
 21.1008 +	    changeset to test, and told us which changeset it's
 21.1009 +	    testing.</para>
 21.1010 +	</listitem></itemizedlist>
 21.1011 +
 21.1012 +      <para id="x_145">We now run our test in the working directory.  We use the
 21.1013 +	<command>grep</command> command to see if our
 21.1014 +	<quote>bad</quote> file is present in the working directory.
 21.1015 +	If it is, this revision is bad; if not, this revision is good.
 21.1016 +	&interaction.bisect.search.step1;</para>
 21.1017 +
 21.1018 +      <para id="x_146">This test looks like a perfect candidate for automation,
 21.1019 +	so let's turn it into a shell function.</para>
 21.1020 +      &interaction.bisect.search.mytest;
 21.1021 +
 21.1022 +      <para id="x_147">We can now run an entire test step with a single command,
 21.1023 +	<literal>mytest</literal>.</para>
 21.1024 +
 21.1025 +      &interaction.bisect.search.step2;
 21.1026 +
 21.1027 +      <para id="x_148">A few more invocations of our canned test step command,
 21.1028 +	and we're done.</para>
 21.1029 +
 21.1030 +      &interaction.bisect.search.rest;
 21.1031 +
 21.1032 +      <para id="x_149">Even though we had 40 changesets to search through, the
 21.1033 +	<command role="hg-cmd">hg bisect</command> command let us find
 21.1034 +	the changeset that introduced our <quote>bug</quote> with only
 21.1035 +	five tests.  Because the number of tests that the <command
 21.1036 +	  role="hg-cmd">hg bisect</command> command performs grows
 21.1037 +	logarithmically with the number of changesets to search, the
 21.1038 +	advantage that it has over the <quote>brute force</quote>
 21.1039 +	search approach increases with every changeset you add.</para>
 21.1040 +
 21.1041 +    </sect2>
 21.1042 +    <sect2>
 21.1043 +      <title>Cleaning up after your search</title>
 21.1044 +
 21.1045 +      <para id="x_14a">When you're finished using the <command role="hg-cmd">hg
 21.1046 +	  bisect</command> command in a repository, you can use the
 21.1047 +	<command role="hg-cmd">hg bisect --reset</command> command to
 21.1048 +	drop the information it was using to drive your search.  The
 21.1049 +	command doesn't use much space, so it doesn't matter if you
 21.1050 +	forget to run this command.  However, <command
 21.1051 +	  role="hg-cmd">hg bisect</command> won't let you start a new
 21.1052 +	search in that repository until you do a <command
 21.1053 +	  role="hg-cmd">hg bisect --reset</command>.</para>
 21.1054 +
 21.1055 +      &interaction.bisect.search.reset;
 21.1056 +
 21.1057 +    </sect2>
 21.1058 +  </sect1>
 21.1059 +  <sect1>
 21.1060 +    <title>Tips for finding bugs effectively</title>
 21.1061 +
 21.1062 +    <sect2>
 21.1063 +      <title>Give consistent input</title>
 21.1064 +
 21.1065 +      <para id="x_14b">The <command role="hg-cmd">hg bisect</command> command
 21.1066 +	requires that you correctly report the result of every test
 21.1067 +	you perform.  If you tell it that a test failed when it really
 21.1068 +	succeeded, it <emphasis>might</emphasis> be able to detect the
 21.1069 +	inconsistency.  If it can identify an inconsistency in your
 21.1070 +	reports, it will tell you that a particular changeset is both
 21.1071 +	good and bad. However, it can't do this perfectly; it's about
 21.1072 +	as likely to report the wrong changeset as the source of the
 21.1073 +	bug.</para>
 21.1074 +
 21.1075 +    </sect2>
 21.1076 +    <sect2>
 21.1077 +      <title>Automate as much as possible</title>
 21.1078 +
 21.1079 +      <para id="x_14c">When I started using the <command role="hg-cmd">hg
 21.1080 +	  bisect</command> command, I tried a few times to run my
 21.1081 +	tests by hand, on the command line.  This is an approach that
 21.1082 +	I, at least, am not suited to.  After a few tries, I found
 21.1083 +	that I was making enough mistakes that I was having to restart
 21.1084 +	my searches several times before finally getting correct
 21.1085 +	results.</para>
 21.1086 +
 21.1087 +      <para id="x_14d">My initial problems with driving the <command
 21.1088 +	  role="hg-cmd">hg bisect</command> command by hand occurred
 21.1089 +	even with simple searches on small repositories; if the
 21.1090 +	problem you're looking for is more subtle, or the number of
 21.1091 +	tests that <command role="hg-cmd">hg bisect</command> must
 21.1092 +	perform increases, the likelihood of operator error ruining
 21.1093 +	the search is much higher.  Once I started automating my
 21.1094 +	tests, I had much better results.</para>
 21.1095 +
 21.1096 +      <para id="x_14e">The key to automated testing is twofold:</para>
 21.1097 +      <itemizedlist>
 21.1098 +	<listitem><para id="x_14f">always test for the same symptom, and</para>
 21.1099 +	</listitem>
 21.1100 +	<listitem><para id="x_150">always feed consistent input to the <command
 21.1101 +	      role="hg-cmd">hg bisect</command> command.</para>
 21.1102 +	</listitem></itemizedlist>
 21.1103 +      <para id="x_151">In my tutorial example above, the <command>grep</command>
 21.1104 +	command tests for the symptom, and the <literal>if</literal>
 21.1105 +	statement takes the result of this check and ensures that we
 21.1106 +	always feed the same input to the <command role="hg-cmd">hg
 21.1107 +	  bisect</command> command.  The <literal>mytest</literal>
 21.1108 +	function marries these together in a reproducible way, so that
 21.1109 +	every test is uniform and consistent.</para>
 21.1110 +
 21.1111 +    </sect2>
 21.1112 +    <sect2>
 21.1113 +      <title>Check your results</title>
 21.1114 +
 21.1115 +      <para id="x_152">Because the output of a <command role="hg-cmd">hg
 21.1116 +	  bisect</command> search is only as good as the input you
 21.1117 +	give it, don't take the changeset it reports as the absolute
 21.1118 +	truth.  A simple way to cross-check its report is to manually
 21.1119 +	run your test at each of the following changesets:</para>
 21.1120 +      <itemizedlist>
 21.1121 +	<listitem><para id="x_153">The changeset that it reports as the first bad
 21.1122 +	    revision.  Your test should still report this as
 21.1123 +	    bad.</para>
 21.1124 +	</listitem>
 21.1125 +	<listitem><para id="x_154">The parent of that changeset (either parent,
 21.1126 +	    if it's a merge). Your test should report this changeset
 21.1127 +	    as good.</para>
 21.1128 +	</listitem>
 21.1129 +	<listitem><para id="x_155">A child of that changeset.  Your test should
 21.1130 +	    report this changeset as bad.</para>
 21.1131 +	</listitem></itemizedlist>
 21.1132 +
 21.1133 +    </sect2>
 21.1134 +    <sect2>
 21.1135 +      <title>Beware interference between bugs</title>
 21.1136 +
 21.1137 +      <para id="x_156">It's possible that your search for one bug could be
 21.1138 +	disrupted by the presence of another.  For example, let's say
 21.1139 +	your software crashes at revision 100, and worked correctly at
 21.1140 +	revision 50.  Unknown to you, someone else introduced a
 21.1141 +	different crashing bug at revision 60, and fixed it at
 21.1142 +	revision 80.  This could distort your results in one of
 21.1143 +	several ways.</para>
 21.1144 +
 21.1145 +      <para id="x_157">It is possible that this other bug completely
 21.1146 +	<quote>masks</quote> yours, which is to say that it occurs
 21.1147 +	before your bug has a chance to manifest itself.  If you can't
 21.1148 +	avoid that other bug (for example, it prevents your project
 21.1149 +	from building), and so can't tell whether your bug is present
 21.1150 +	in a particular changeset, the <command role="hg-cmd">hg
 21.1151 +	  bisect</command> command cannot help you directly.  Instead,
 21.1152 +	you can mark a changeset as untested by running <command
 21.1153 +	  role="hg-cmd">hg bisect --skip</command>.</para>
 21.1154 +
 21.1155 +      <para id="x_158">A different problem could arise if your test for a bug's
 21.1156 +	presence is not specific enough.  If you check for <quote>my
 21.1157 +	  program crashes</quote>, then both your crashing bug and an
 21.1158 +	unrelated crashing bug that masks it will look like the same
 21.1159 +	thing, and mislead <command role="hg-cmd">hg
 21.1160 +	  bisect</command>.</para>
 21.1161 +
 21.1162 +      <para id="x_159">Another useful situation in which to use <command
 21.1163 +	  role="hg-cmd">hg bisect --skip</command> is if you can't
 21.1164 +	test a revision because your project was in a broken and hence
 21.1165 +	untestable state at that revision, perhaps because someone
 21.1166 +	checked in a change that prevented the project from
 21.1167 +	building.</para>
 21.1168 +
 21.1169 +    </sect2>
 21.1170 +    <sect2>
 21.1171 +      <title>Bracket your search lazily</title>
 21.1172 +
 21.1173 +      <para id="x_15a">Choosing the first <quote>good</quote> and
 21.1174 +	<quote>bad</quote> changesets that will mark the end points of
 21.1175 +	your search is often easy, but it bears a little discussion
 21.1176 +	nevertheless.  From the perspective of <command
 21.1177 +	  role="hg-cmd">hg bisect</command>, the <quote>newest</quote>
 21.1178 +	changeset is conventionally <quote>bad</quote>, and the older
 21.1179 +	changeset is <quote>good</quote>.</para>
 21.1180 +
 21.1181 +      <para id="x_15b">If you're having trouble remembering when a suitable
 21.1182 +	<quote>good</quote> change was, so that you can tell <command
 21.1183 +	  role="hg-cmd">hg bisect</command>, you could do worse than
 21.1184 +	testing changesets at random.  Just remember to eliminate
 21.1185 +	contenders that can't possibly exhibit the bug (perhaps
 21.1186 +	because the feature with the bug isn't present yet) and those
 21.1187 +	where another problem masks the bug (as I discussed
 21.1188 +	above).</para>
 21.1189 +
 21.1190 +      <para id="x_15c">Even if you end up <quote>early</quote> by thousands of
 21.1191 +	changesets or months of history, you will only add a handful
 21.1192 +	of tests to the total number that <command role="hg-cmd">hg
 21.1193 +	  bisect</command> must perform, thanks to its logarithmic
 21.1194 +	behavior.</para>
 21.1195 +
 21.1196 +    </sect2>
 21.1197 +  </sect1>
 21.1198 +</chapter>
 21.1199 +
 21.1200 +<!--
 21.1201 +local variables: 
 21.1202 +sgml-parent-document: ("00book.xml" "book" "chapter")
 21.1203 +end:
 21.1204 +-->
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/fr/ch10-hook.xml	Sat Jul 10 06:24:49 2010 +0100
    22.3 @@ -0,0 +1,1928 @@
    22.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
    22.5 +
    22.6 +<chapter id="chap:hook">
    22.7 +  <?dbhtml filename="handling-repository-events-with-hooks.html"?>
    22.8 +  <title>Handling repository events with hooks</title>
    22.9 +
   22.10 +  <para id="x_1e6">Mercurial offers a powerful mechanism to let you perform
   22.11 +    automated actions in response to events that occur in a
   22.12 +    repository.  In some cases, you can even control Mercurial's
   22.13 +    response to those events.</para>
   22.14 +
   22.15 +  <para id="x_1e7">The name Mercurial uses for one of these actions is a
   22.16 +    <emphasis>hook</emphasis>. Hooks are called
   22.17 +    <quote>triggers</quote> in some revision control systems, but the
   22.18 +    two names refer to the same idea.</para>
   22.19 +
   22.20 +  <sect1>
   22.21 +    <title>An overview of hooks in Mercurial</title>
   22.22 +
   22.23 +    <para id="x_1e8">Here is a brief list of the hooks that Mercurial
   22.24 +      supports. We will revisit each of these hooks in more detail
   22.25 +      later, in <xref linkend="sec:hook:ref"/>.</para>
   22.26 +
   22.27 +    <para id="x_1f6">Each of the hooks whose description begins with the word
   22.28 +      <quote>Controlling</quote> has the ability to determine whether
   22.29 +      an activity can proceed.  If the hook succeeds, the activity may
   22.30 +      proceed; if it fails, the activity is either not permitted or
   22.31 +      undone, depending on the hook.</para>
   22.32 +
   22.33 +    <itemizedlist>
   22.34 +      <listitem><para id="x_1e9"><literal role="hook">changegroup</literal>: This
   22.35 +	  is run after a group of changesets has been brought into the
   22.36 +	  repository from elsewhere.</para>
   22.37 +      </listitem>
   22.38 +      <listitem><para id="x_1ea"><literal role="hook">commit</literal>: This is
   22.39 +	  run after a new changeset has been created in the local
   22.40 +	  repository.</para>
   22.41 +      </listitem>
   22.42 +      <listitem><para id="x_1eb"><literal role="hook">incoming</literal>: This is
   22.43 +	  run once for each new changeset that is brought into the
   22.44 +	  repository from elsewhere.  Notice the difference from
   22.45 +	  <literal role="hook">changegroup</literal>, which is run
   22.46 +	  once per <emphasis>group</emphasis> of changesets brought
   22.47 +	  in.</para>
   22.48 +      </listitem>
   22.49 +      <listitem><para id="x_1ec"><literal role="hook">outgoing</literal>: This is
   22.50 +	  run after a group of changesets has been transmitted from
   22.51 +	  this repository.</para>
   22.52 +      </listitem>
   22.53 +      <listitem><para id="x_1ed"><literal role="hook">prechangegroup</literal>:
   22.54 +	  This is run before starting to bring a group of changesets
   22.55 +	  into the repository.
   22.56 +	</para>
   22.57 +      </listitem>
   22.58 +      <listitem><para id="x_1ee"><literal role="hook">precommit</literal>:
   22.59 +	  Controlling. This is run before starting a commit.
   22.60 +	</para>
   22.61 +      </listitem>
   22.62 +      <listitem><para id="x_1ef"><literal role="hook">preoutgoing</literal>:
   22.63 +	  Controlling. This is run before starting to transmit a group
   22.64 +	  of changesets from this repository.
   22.65 +	</para>
   22.66 +      </listitem>
   22.67 +      <listitem><para id="x_1f0"><literal role="hook">pretag</literal>:
   22.68 +	  Controlling. This is run before creating a tag.
   22.69 +	</para>
   22.70 +      </listitem>
   22.71 +      <listitem><para id="x_1f1"><literal
   22.72 +	    role="hook">pretxnchangegroup</literal>: Controlling. This
   22.73 +	  is run after a group of changesets has been brought into the
   22.74 +	  local repository from another, but before the transaction
   22.75 +	  completes that will make the changes permanent in the
   22.76 +	  repository.
   22.77 +	</para>
   22.78 +      </listitem>
   22.79 +      <listitem><para id="x_1f2"><literal role="hook">pretxncommit</literal>:
   22.80 +	  Controlling. This is run after a new changeset has been
   22.81 +	  created in the local repository, but before the transaction
   22.82 +	  completes that will make it permanent.
   22.83 +	</para>
   22.84 +      </listitem>
   22.85 +      <listitem><para id="x_1f3"><literal role="hook">preupdate</literal>:
   22.86 +	  Controlling. This is run before starting an update or merge
   22.87 +	  of the working directory.
   22.88 +	</para>
   22.89 +      </listitem>
   22.90 +      <listitem><para id="x_1f4"><literal role="hook">tag</literal>: This is run
   22.91 +	  after a tag is created.
   22.92 +	</para>
   22.93 +      </listitem>
   22.94 +      <listitem><para id="x_1f5"><literal role="hook">update</literal>: This is
   22.95 +	  run after an update or merge of the working directory has
   22.96 +	  finished.
   22.97 +	</para>
   22.98 +      </listitem></itemizedlist>
   22.99 +
  22.100 +  </sect1>
  22.101 +  <sect1>
  22.102 +    <title>Hooks and security</title>
  22.103 +
  22.104 +    <sect2>
  22.105 +      <title>Hooks are run with your privileges</title>
  22.106 +
  22.107 +      <para id="x_1f7">When you run a Mercurial command in a repository, and the
  22.108 +	command causes a hook to run, that hook runs on
  22.109 +	<emphasis>your</emphasis> system, under
  22.110 +	<emphasis>your</emphasis> user account, with
  22.111 +	<emphasis>your</emphasis> privilege level.  Since hooks are
  22.112 +	arbitrary pieces of executable code, you should treat them
  22.113 +	with an appropriate level of suspicion.  Do not install a hook
  22.114 +	unless you are confident that you know who created it and what
  22.115 +	it does.
  22.116 +      </para>
  22.117 +
  22.118 +      <para id="x_1f8">In some cases, you may be exposed to hooks that you did
  22.119 +	not install yourself.  If you work with Mercurial on an
  22.120 +	unfamiliar system, Mercurial will run hooks defined in that
  22.121 +	system's global <filename role="special">~/.hgrc</filename>
  22.122 +	file.
  22.123 +      </para>
  22.124 +
  22.125 +      <para id="x_1f9">If you are working with a repository owned by another
  22.126 +	user, Mercurial can run hooks defined in that user's
  22.127 +	repository, but it will still run them as <quote>you</quote>.
  22.128 +	For example, if you <command role="hg-cmd">hg pull</command>
  22.129 +	from that repository, and its <filename
  22.130 +	  role="special">.hg/hgrc</filename> defines a local <literal
  22.131 +	  role="hook">outgoing</literal> hook, that hook will run
  22.132 +	under your user account, even though you don't own that
  22.133 +	repository.
  22.134 +      </para>
  22.135 +
  22.136 +      <note>
  22.137 +	<para id="x_1fa">  This only applies if you are pulling from a repository
  22.138 +	  on a local or network filesystem.  If you're pulling over
  22.139 +	  http or ssh, any <literal role="hook">outgoing</literal>
  22.140 +	  hook will run under whatever account is executing the server
  22.141 +	  process, on the server.
  22.142 +	</para>
  22.143 +      </note>
  22.144 +
  22.145 +      <para id="x_1fb">To see what hooks are defined in a repository,
  22.146 +	use the <command role="hg-cmd">hg showconfig hooks</command>
  22.147 +	command.  If you are working in one repository, but talking to
  22.148 +	another that you do not own (e.g. using <command
  22.149 +	  role="hg-cmd">hg pull</command> or <command role="hg-cmd">hg
  22.150 +	  incoming</command>), remember that it is the other
  22.151 +	repository's hooks you should be checking, not your own.
  22.152 +      </para>
  22.153 +    </sect2>
  22.154 +
  22.155 +    <sect2>
  22.156 +      <title>Hooks do not propagate</title>
  22.157 +
  22.158 +      <para id="x_1fc">In Mercurial, hooks are not revision controlled, and do
  22.159 +	not propagate when you clone, or pull from, a repository.  The
  22.160 +	reason for this is simple: a hook is a completely arbitrary
  22.161 +	piece of executable code.  It runs under your user identity,
  22.162 +	with your privilege level, on your machine.
  22.163 +      </para>
  22.164 +
  22.165 +      <para id="x_1fd">It would be extremely reckless for any distributed
  22.166 +	revision control system to implement revision-controlled
  22.167 +	hooks, as this would offer an easily exploitable way to
  22.168 +	subvert the accounts of users of the revision control system.
  22.169 +      </para>
  22.170 +
  22.171 +      <para id="x_1fe">Since Mercurial does not propagate hooks, if you are
  22.172 +	collaborating with other people on a common project, you
  22.173 +	should not assume that they are using the same Mercurial hooks
  22.174 +	as you are, or that theirs are correctly configured.  You
  22.175 +	should document the hooks you expect people to use.
  22.176 +      </para>
  22.177 +
  22.178 +      <para id="x_1ff">In a corporate intranet, this is somewhat easier to
  22.179 +	control, as you can for example provide a
  22.180 +	<quote>standard</quote> installation of Mercurial on an NFS
  22.181 +	filesystem, and use a site-wide <filename role="special">~/.hgrc</filename> file to define hooks that all users will
  22.182 +	see.  However, this too has its limits; see below.
  22.183 +      </para>
  22.184 +    </sect2>
  22.185 +
  22.186 +    <sect2>
  22.187 +      <title>Hooks can be overridden</title>
  22.188 +
  22.189 +      <para id="x_200">Mercurial allows you to override a hook definition by
  22.190 +	redefining the hook.  You can disable it by setting its value
  22.191 +	to the empty string, or change its behavior as you wish.
  22.192 +      </para>
  22.193 +
  22.194 +      <para id="x_201">If you deploy a system- or site-wide <filename
  22.195 +	  role="special">~/.hgrc</filename> file that defines some
  22.196 +	hooks, you should thus understand that your users can disable
  22.197 +	or override those hooks.
  22.198 +      </para>
  22.199 +    </sect2>
  22.200 +
  22.201 +    <sect2>
  22.202 +      <title>Ensuring that critical hooks are run</title>
  22.203 +
  22.204 +      <para id="x_202">Sometimes you may want to enforce a policy that you do not
  22.205 +	want others to be able to work around.  For example, you may
  22.206 +	have a requirement that every changeset must pass a rigorous
  22.207 +	set of tests.  Defining this requirement via a hook in a
  22.208 +	site-wide <filename role="special">~/.hgrc</filename> won't
  22.209 +	work for remote users on laptops, and of course local users
  22.210 +	can subvert it at will by overriding the hook.
  22.211 +      </para>
  22.212 +
  22.213 +      <para id="x_203">Instead, you can set up your policies for use of Mercurial
  22.214 +	so that people are expected to propagate changes through a
  22.215 +	well-known <quote>canonical</quote> server that you have
  22.216 +	locked down and configured appropriately.
  22.217 +      </para>
  22.218 +
  22.219 +      <para id="x_204">One way to do this is via a combination of social
  22.220 +	engineering and technology.  Set up a restricted-access
  22.221 +	account; users can push changes over the network to
  22.222 +	repositories managed by this account, but they cannot log into
  22.223 +	the account and run normal shell commands.  In this scenario,
  22.224 +	a user can commit a changeset that contains any old garbage
  22.225 +	they want.
  22.226 +      </para>
  22.227 +
  22.228 +      <para id="x_205">When someone pushes a changeset to the server that
  22.229 +	everyone pulls from, the server will test the changeset before
  22.230 +	it accepts it as permanent, and reject it if it fails to pass
  22.231 +	the test suite.  If people only pull changes from this
  22.232 +	filtering server, it will serve to ensure that all changes
  22.233 +	that people pull have been automatically vetted.
  22.234 +      </para>
  22.235 +
  22.236 +    </sect2>
  22.237 +  </sect1>
  22.238 +
  22.239 +  <sect1 id="sec:hook:simple">
  22.240 +    <title>A short tutorial on using hooks</title>
  22.241 +
  22.242 +    <para id="x_212">It is easy to write a Mercurial hook.  Let's start with a
  22.243 +      hook that runs when you finish a <command role="hg-cmd">hg
  22.244 +	commit</command>, and simply prints the hash of the changeset
  22.245 +      you just created.  The hook is called <literal
  22.246 +	role="hook">commit</literal>.
  22.247 +    </para>
  22.248 +
  22.249 +    <para id="x_213">All hooks follow the pattern in this example.</para>
  22.250 +
  22.251 +&interaction.hook.simple.init;
  22.252 +
  22.253 +    <para id="x_214">You add an entry to the <literal
  22.254 +	role="rc-hooks">hooks</literal> section of your <filename
  22.255 +	role="special">~/.hgrc</filename>.  On the left is the name of
  22.256 +      the event to trigger on; on the right is the action to take.  As
  22.257 +      you can see, you can run an arbitrary shell command in a hook.
  22.258 +      Mercurial passes extra information to the hook using environment
  22.259 +      variables (look for <envar>HG_NODE</envar> in the example).
  22.260 +    </para>
  22.261 +
  22.262 +    <sect2>
  22.263 +      <title>Performing multiple actions per event</title>
  22.264 +
  22.265 +      <para id="x_215">Quite often, you will want to define more than one hook
  22.266 +	for a particular kind of event, as shown below.</para>
  22.267 +
  22.268 +&interaction.hook.simple.ext;
  22.269 +
  22.270 +      <para id="x_216">Mercurial lets you do this by adding an
  22.271 +	<emphasis>extension</emphasis> to the end of a hook's name.
  22.272 +	You extend a hook's name by giving the name of the hook,
  22.273 +	followed by a full stop (the
  22.274 +	<quote><literal>.</literal></quote> character), followed by
  22.275 +	some more text of your choosing.  For example, Mercurial will
  22.276 +	run both <literal>commit.foo</literal> and
  22.277 +	<literal>commit.bar</literal> when the
  22.278 +	<literal>commit</literal> event occurs.
  22.279 +      </para>
  22.280 +
  22.281 +      <para id="x_217">To give a well-defined order of execution when there are
  22.282 +	multiple hooks defined for an event, Mercurial sorts hooks by
  22.283 +	extension, and executes the hook commands in this sorted
  22.284 +	order.  In the above example, it will execute
  22.285 +	<literal>commit.bar</literal> before
  22.286 +	<literal>commit.foo</literal>, and <literal>commit</literal>
  22.287 +	before both.
  22.288 +      </para>
  22.289 +
  22.290 +      <para id="x_218">It is a good idea to use a somewhat descriptive
  22.291 +	extension when you define a new hook.  This will help you to
  22.292 +	remember what the hook was for.  If the hook fails, you'll get
  22.293 +	an error message that contains the hook name and extension, so
  22.294 +	using a descriptive extension could give you an immediate hint
  22.295 +	as to why the hook failed (see <xref
  22.296 +	  linkend="sec:hook:perm"/> for an example).
  22.297 +      </para>
  22.298 +
  22.299 +    </sect2>
  22.300 +    <sect2 id="sec:hook:perm">
  22.301 +      <title>Controlling whether an activity can proceed</title>
  22.302 +
  22.303 +      <para id="x_219">In our earlier examples, we used the <literal
  22.304 +	  role="hook">commit</literal> hook, which is run after a
  22.305 +	commit has completed.  This is one of several Mercurial hooks
  22.306 +	that run after an activity finishes.  Such hooks have no way
  22.307 +	of influencing the activity itself.
  22.308 +      </para>
  22.309 +
  22.310 +      <para id="x_21a">Mercurial defines a number of events that occur before an
  22.311 +	activity starts; or after it starts, but before it finishes.
  22.312 +	Hooks that trigger on these events have the added ability to
  22.313 +	choose whether the activity can continue, or will abort.
  22.314 +      </para>
  22.315 +
  22.316 +      <para id="x_21b">The <literal role="hook">pretxncommit</literal> hook runs
  22.317 +	after a commit has all but completed.  In other words, the
  22.318 +	metadata representing the changeset has been written out to
  22.319 +	disk, but the transaction has not yet been allowed to
  22.320 +	complete.  The <literal role="hook">pretxncommit</literal>
  22.321 +	hook has the ability to decide whether the transaction can
  22.322 +	complete, or must be rolled back.
  22.323 +      </para>
  22.324 +
  22.325 +      <para id="x_21c">If the <literal role="hook">pretxncommit</literal> hook
  22.326 +	exits with a status code of zero, the transaction is allowed
  22.327 +	to complete; the commit finishes; and the <literal
  22.328 +	  role="hook">commit</literal> hook is run.  If the <literal
  22.329 +	  role="hook">pretxncommit</literal> hook exits with a
  22.330 +	non-zero status code, the transaction is rolled back; the
  22.331 +	metadata representing the changeset is erased; and the
  22.332 +	<literal role="hook">commit</literal> hook is not run.
  22.333 +      </para>
  22.334 +
  22.335 +&interaction.hook.simple.pretxncommit;
  22.336 +
  22.337 +      <para id="x_21d">The hook in the example above checks that a commit comment
  22.338 +	contains a bug ID.  If it does, the commit can complete.  If
  22.339 +	not, the commit is rolled back.
  22.340 +      </para>
  22.341 +
  22.342 +    </sect2>
  22.343 +  </sect1>
  22.344 +  <sect1>
  22.345 +    <title>Writing your own hooks</title>
  22.346 +
  22.347 +    <para id="x_21e">When you are writing a hook, you might find it useful to run
  22.348 +      Mercurial either with the <option
  22.349 +	role="hg-opt-global">-v</option> option, or the <envar
  22.350 +	role="rc-item-ui">verbose</envar> config item set to
  22.351 +      <quote>true</quote>.  When you do so, Mercurial will print a
  22.352 +      message before it calls each hook.
  22.353 +    </para>
  22.354 +
  22.355 +    <sect2 id="sec:hook:lang">
  22.356 +      <title>Choosing how your hook should run</title>
  22.357 +
  22.358 +      <para id="x_21f">You can write a hook either as a normal
  22.359 +	program&emdash;typically a shell script&emdash;or as a Python
  22.360 +	function that is executed within the Mercurial process.
  22.361 +      </para>
  22.362 +
  22.363 +      <para id="x_220">Writing a hook as an external program has the advantage
  22.364 +	that it requires no knowledge of Mercurial's internals.  You
  22.365 +	can call normal Mercurial commands to get any added
  22.366 +	information you need.  The trade-off is that external hooks
  22.367 +	are slower than in-process hooks.
  22.368 +      </para>
  22.369 +
  22.370 +      <para id="x_221">An in-process Python hook has complete access to the
  22.371 +	Mercurial API, and does not <quote>shell out</quote> to
  22.372 +	another process, so it is inherently faster than an external
  22.373 +	hook.  It is also easier to obtain much of the information
  22.374 +	that a hook requires by using the Mercurial API than by
  22.375 +	running Mercurial commands.
  22.376 +      </para>
  22.377 +
  22.378 +      <para id="x_222">If you are comfortable with Python, or require high
  22.379 +	performance, writing your hooks in Python may be a good
  22.380 +	choice.  However, when you have a straightforward hook to
  22.381 +	write and you don't need to care about performance (probably
  22.382 +	the majority of hooks), a shell script is perfectly fine.
  22.383 +      </para>
  22.384 +
  22.385 +    </sect2>
  22.386 +    <sect2 id="sec:hook:param">
  22.387 +      <title>Hook parameters</title>
  22.388 +
  22.389 +      <para id="x_223">Mercurial calls each hook with a set of well-defined
  22.390 +	parameters.  In Python, a parameter is passed as a keyword
  22.391 +	argument to your hook function.  For an external program, a
  22.392 +	parameter is passed as an environment variable.
  22.393 +      </para>
  22.394 +
  22.395 +      <para id="x_224">Whether your hook is written in Python or as a shell
  22.396 +	script, the hook-specific parameter names and values will be
  22.397 +	the same.  A boolean parameter will be represented as a
  22.398 +	boolean value in Python, but as the number 1 (for
  22.399 +	<quote>true</quote>) or 0 (for <quote>false</quote>) as an
  22.400 +	environment variable for an external hook.  If a hook
  22.401 +	parameter is named <literal>foo</literal>, the keyword
  22.402 +	argument for a Python hook will also be named
  22.403 +	<literal>foo</literal>, while the environment variable for an
  22.404 +	external hook will be named <literal>HG_FOO</literal>.
  22.405 +      </para>
  22.406 +    </sect2>
  22.407 +
  22.408 +    <sect2>
  22.409 +      <title>Hook return values and activity control</title>
  22.410 +
  22.411 +      <para id="x_225">A hook that executes successfully must exit with a status
  22.412 +	of zero if external, or return boolean <quote>false</quote> if
  22.413 +	in-process.  Failure is indicated with a non-zero exit status
  22.414 +	from an external hook, or an in-process hook returning boolean
  22.415 +	<quote>true</quote>.  If an in-process hook raises an
  22.416 +	exception, the hook is considered to have failed.
  22.417 +      </para>
  22.418 +
  22.419 +      <para id="x_226">For a hook that controls whether an activity can proceed,
  22.420 +	zero/false means <quote>allow</quote>, while
  22.421 +	non-zero/true/exception means <quote>deny</quote>.
  22.422 +      </para>
  22.423 +    </sect2>
  22.424 +
  22.425 +    <sect2>
  22.426 +      <title>Writing an external hook</title>
  22.427 +
  22.428 +      <para id="x_227">When you define an external hook in your <filename
  22.429 +	  role="special">~/.hgrc</filename> and the hook is run, its
  22.430 +	value is passed to your shell, which interprets it.  This
  22.431 +	means that you can use normal shell constructs in the body of
  22.432 +	the hook.
  22.433 +      </para>
  22.434 +
  22.435 +      <para id="x_228">An executable hook is always run with its current
  22.436 +	directory set to a repository's root directory.
  22.437 +      </para>
  22.438 +
  22.439 +      <para id="x_229">Each hook parameter is passed in as an environment
  22.440 +	variable; the name is upper-cased, and prefixed with the
  22.441 +	string <quote><literal>HG_</literal></quote>.
  22.442 +      </para>
  22.443 +
  22.444 +      <para id="x_22a">With the exception of hook parameters, Mercurial does not
  22.445 +	set or modify any environment variables when running a hook.
  22.446 +	This is useful to remember if you are writing a site-wide hook
  22.447 +	that may be run by a number of different users with differing
  22.448 +	environment variables set. In multi-user situations, you
  22.449 +	should not rely on environment variables being set to the
  22.450 +	values you have in your environment when testing the hook.
  22.451 +      </para>
  22.452 +    </sect2>
  22.453 +
  22.454 +    <sect2>
  22.455 +      <title>Telling Mercurial to use an in-process hook</title>
  22.456 +
  22.457 +      <para id="x_22b">The <filename role="special">~/.hgrc</filename> syntax
  22.458 +	for defining an in-process hook is slightly different than for
  22.459 +	an executable hook.  The value of the hook must start with the
  22.460 +	text <quote><literal>python:</literal></quote>, and continue
  22.461 +	with the fully-qualified name of a callable object to use as
  22.462 +	the hook's value.
  22.463 +      </para>
  22.464 +
  22.465 +      <para id="x_22c">The module in which a hook lives is automatically imported
  22.466 +	when a hook is run.  So long as you have the module name and
  22.467 +	<envar>PYTHONPATH</envar> right, it should <quote>just
  22.468 +	  work</quote>.
  22.469 +      </para>
  22.470 +
  22.471 +      <para id="x_22d">The following <filename role="special">~/.hgrc</filename>
  22.472 +	example snippet illustrates the syntax and meaning of the
  22.473 +	notions we just described.
  22.474 +      </para>
  22.475 +      <programlisting>[hooks]
  22.476 +commit.example = python:mymodule.submodule.myhook</programlisting>
  22.477 +      <para id="x_22e">When Mercurial runs the <literal>commit.example</literal>
  22.478 +	hook, it imports <literal>mymodule.submodule</literal>, looks
  22.479 +	for the callable object named <literal>myhook</literal>, and
  22.480 +	calls it.
  22.481 +      </para>
  22.482 +    </sect2>
  22.483 +
  22.484 +    <sect2>
  22.485 +      <title>Writing an in-process hook</title>
  22.486 +
  22.487 +      <para id="x_22f">The simplest in-process hook does nothing, but illustrates
  22.488 +	the basic shape of the hook API:
  22.489 +      </para>
  22.490 +      <programlisting>def myhook(ui, repo, **kwargs):
  22.491 +    pass</programlisting>
  22.492 +      <para id="x_230">The first argument to a Python hook is always a <literal
  22.493 +	  role="py-mod-mercurial.ui">ui</literal> object.  The second
  22.494 +	is a repository object; at the moment, it is always an
  22.495 +	instance of <literal
  22.496 +	  role="py-mod-mercurial.localrepo">localrepository</literal>.
  22.497 +	Following these two arguments are other keyword arguments.
  22.498 +	Which ones are passed in depends on the hook being called, but
  22.499 +	a hook can ignore arguments it doesn't care about by dropping
  22.500 +	them into a keyword argument dict, as with
  22.501 +	<literal>**kwargs</literal> above.
  22.502 +      </para>
  22.503 +
  22.504 +    </sect2>
  22.505 +  </sect1>
  22.506 +  <sect1>
  22.507 +    <title>Some hook examples</title>
  22.508 +
  22.509 +    <sect2>
  22.510 +      <title>Writing meaningful commit messages</title>
  22.511 +
  22.512 +      <para id="x_231">It's hard to imagine a useful commit message being very
  22.513 +	short. The simple <literal role="hook">pretxncommit</literal>
  22.514 +	hook of the example below will prevent you from committing a
  22.515 +	changeset with a message that is less than ten bytes long.
  22.516 +      </para>
  22.517 +
  22.518 +&interaction.hook.msglen.go;
  22.519 +    </sect2>
  22.520 +
  22.521 +    <sect2>
  22.522 +      <title>Checking for trailing whitespace</title>
  22.523 +
  22.524 +      <para id="x_232">An interesting use of a commit-related hook is to help you
  22.525 +	to write cleaner code.  A simple example of <quote>cleaner
  22.526 +	  code</quote> is the dictum that a change should not add any
  22.527 +	new lines of text that contain <quote>trailing
  22.528 +	  whitespace</quote>.  Trailing whitespace is a series of
  22.529 +	space and tab characters at the end of a line of text.  In
  22.530 +	most cases, trailing whitespace is unnecessary, invisible
  22.531 +	noise, but it is occasionally problematic, and people often
  22.532 +	prefer to get rid of it.
  22.533 +      </para>
  22.534 +
  22.535 +      <para id="x_233">You can use either the <literal
  22.536 +	  role="hook">precommit</literal> or <literal
  22.537 +	  role="hook">pretxncommit</literal> hook to tell whether you
  22.538 +	have a trailing whitespace problem.  If you use the <literal
  22.539 +	  role="hook">precommit</literal> hook, the hook will not know
  22.540 +	which files you are committing, so it will have to check every
  22.541 +	modified file in the repository for trailing white space.  If
  22.542 +	you want to commit a change to just the file
  22.543 +	<filename>foo</filename>, but the file
  22.544 +	<filename>bar</filename> contains trailing whitespace, doing a
  22.545 +	check in the <literal role="hook">precommit</literal> hook
  22.546 +	will prevent you from committing <filename>foo</filename> due
  22.547 +	to the problem with <filename>bar</filename>.  This doesn't
  22.548 +	seem right.
  22.549 +      </para>
  22.550 +
  22.551 +      <para id="x_234">Should you choose the <literal
  22.552 +	  role="hook">pretxncommit</literal> hook, the check won't
  22.553 +	occur until just before the transaction for the commit
  22.554 +	completes.  This will allow you to check for problems only the
  22.555 +	exact files that are being committed.  However, if you entered
  22.556 +	the commit message interactively and the hook fails, the
  22.557 +	transaction will roll back; you'll have to re-enter the commit
  22.558 +	message after you fix the trailing whitespace and run <command
  22.559 +	  role="hg-cmd">hg commit</command> again.
  22.560 +      </para>
  22.561 +
  22.562 +      &interaction.ch09-hook.ws.simple;
  22.563 +
  22.564 +      <para id="x_235">In this example, we introduce a simple <literal
  22.565 +	  role="hook">pretxncommit</literal> hook that checks for
  22.566 +	trailing whitespace.  This hook is short, but not very
  22.567 +	helpful.  It exits with an error status if a change adds a
  22.568 +	line with trailing whitespace to any file, but does not print
  22.569 +	any information that might help us to identify the offending
  22.570 +	file or line.  It also has the nice property of not paying
  22.571 +	attention to unmodified lines; only lines that introduce new
  22.572 +	trailing whitespace cause problems.
  22.573 +      </para>
  22.574 +
  22.575 +      &ch09-check_whitespace.py.lst;
  22.576 +
  22.577 +      <para id="x_236">The above version is much more complex, but also more
  22.578 +	useful.  It parses a unified diff to see if any lines add
  22.579 +	trailing whitespace, and prints the name of the file and the
  22.580 +	line number of each such occurrence.  Even better, if the
  22.581 +	change adds trailing whitespace, this hook saves the commit
  22.582 +	comment and prints the name of the save file before exiting
  22.583 +	and telling Mercurial to roll the transaction back, so you can
  22.584 +	use the <option role="hg-opt-commit">-l filename</option>
  22.585 +	option to <command role="hg-cmd">hg commit</command> to reuse
  22.586 +	the saved commit message once you've corrected the problem.
  22.587 +      </para>
  22.588 +
  22.589 +      &interaction.ch09-hook.ws.better;
  22.590 +
  22.591 +      <para id="x_237">As a final aside, note in the example above the
  22.592 +	use of <command>sed</command>'s in-place editing feature to
  22.593 +	get rid of trailing whitespace from a file.  This is concise
  22.594 +	and useful enough that I will reproduce it here (using
  22.595 +	<command>perl</command> for good measure).</para>
  22.596 +      <programlisting>perl -pi -e 's,\s+$,,' filename</programlisting>
  22.597 +
  22.598 +    </sect2>
  22.599 +  </sect1>
  22.600 +  <sect1>
  22.601 +    <title>Bundled hooks</title>
  22.602 +
  22.603 +    <para id="x_238">Mercurial ships with several bundled hooks.  You can find
  22.604 +      them in the <filename class="directory">hgext</filename>
  22.605 +      directory of a Mercurial source tree.  If you are using a
  22.606 +      Mercurial binary package, the hooks will be located in the
  22.607 +      <filename class="directory">hgext</filename> directory of
  22.608 +      wherever your package installer put Mercurial.
  22.609 +    </para>
  22.610 +
  22.611 +    <sect2>
  22.612 +      <title><literal role="hg-ext">acl</literal>&emdash;access
  22.613 +	control for parts of a repository</title>
  22.614 +
  22.615 +      <para id="x_239">The <literal role="hg-ext">acl</literal> extension lets
  22.616 +	you control which remote users are allowed to push changesets
  22.617 +	to a networked server.  You can protect any portion of a
  22.618 +	repository (including the entire repo), so that a specific
  22.619 +	remote user can push changes that do not affect the protected
  22.620 +	portion.
  22.621 +      </para>
  22.622 +
  22.623 +      <para id="x_23a">This extension implements access control based on the
  22.624 +	identity of the user performing a push,
  22.625 +	<emphasis>not</emphasis> on who committed the changesets
  22.626 +	they're pushing.  It makes sense to use this hook only if you
  22.627 +	have a locked-down server environment that authenticates
  22.628 +	remote users, and you want to be sure that only specific users
  22.629 +	are allowed to push changes to that server.
  22.630 +      </para>
  22.631 +
  22.632 +      <sect3>
  22.633 +	<title>Configuring the <literal role="hook">acl</literal>
  22.634 +	  hook</title>
  22.635 +
  22.636 +	<para id="x_23b">In order to manage incoming changesets, the <literal
  22.637 +	    role="hg-ext">acl</literal> hook must be used as a
  22.638 +	  <literal role="hook">pretxnchangegroup</literal> hook.  This
  22.639 +	  lets it see which files are modified by each incoming
  22.640 +	  changeset, and roll back a group of changesets if they
  22.641 +	  modify <quote>forbidden</quote> files.  Example:
  22.642 +	</para>
  22.643 +	<programlisting>[hooks]
  22.644 +pretxnchangegroup.acl = python:hgext.acl.hook</programlisting>
  22.645 +
  22.646 +	<para id="x_23c">The <literal role="hg-ext">acl</literal> extension is
  22.647 +	  configured using three sections.
  22.648 +	</para>
  22.649 +
  22.650 +	<para id="x_23d">The <literal role="rc-acl">acl</literal> section has
  22.651 +	  only one entry, <envar role="rc-item-acl">sources</envar>,
  22.652 +	  which lists the sources of incoming changesets that the hook
  22.653 +	  should pay attention to.  You don't normally need to
  22.654 +	  configure this section.
  22.655 +	</para>
  22.656 +	<itemizedlist>
  22.657 +	  <listitem><para id="x_23e"><envar role="rc-item-acl">serve</envar>:
  22.658 +	      Control incoming changesets that are arriving from a
  22.659 +	      remote repository over http or ssh.  This is the default
  22.660 +	      value of <envar role="rc-item-acl">sources</envar>, and
  22.661 +	      usually the only setting you'll need for this
  22.662 +	      configuration item.
  22.663 +	    </para>
  22.664 +	  </listitem>
  22.665 +	  <listitem><para id="x_23f"><envar role="rc-item-acl">pull</envar>:
  22.666 +	      Control incoming changesets that are arriving via a pull
  22.667 +	      from a local repository.
  22.668 +	    </para>
  22.669 +	  </listitem>
  22.670 +	  <listitem><para id="x_240"><envar role="rc-item-acl">push</envar>:
  22.671 +	      Control incoming changesets that are arriving via a push
  22.672 +	      from a local repository.
  22.673 +	    </para>
  22.674 +	  </listitem>
  22.675 +	  <listitem><para id="x_241"><envar role="rc-item-acl">bundle</envar>:
  22.676 +	      Control incoming changesets that are arriving from
  22.677 +	      another repository via a bundle.
  22.678 +	    </para>
  22.679 +	  </listitem></itemizedlist>
  22.680 +
  22.681 +	<para id="x_242">The <literal role="rc-acl.allow">acl.allow</literal>
  22.682 +	  section controls the users that are allowed to add
  22.683 +	  changesets to the repository.  If this section is not
  22.684 +	  present, all users that are not explicitly denied are
  22.685 +	  allowed.  If this section is present, all users that are not
  22.686 +	  explicitly allowed are denied (so an empty section means
  22.687 +	  that all users are denied).
  22.688 +	</para>
  22.689 +
  22.690 +	<para id="x_243">The <literal role="rc-acl.deny">acl.deny</literal>
  22.691 +	  section determines which users are denied from adding
  22.692 +	  changesets to the repository.  If this section is not
  22.693 +	  present or is empty, no users are denied.
  22.694 +	</para>
  22.695 +
  22.696 +	<para id="x_244">The syntaxes for the <literal
  22.697 +	    role="rc-acl.allow">acl.allow</literal> and <literal
  22.698 +	    role="rc-acl.deny">acl.deny</literal> sections are
  22.699 +	  identical.  On the left of each entry is a glob pattern that
  22.700 +	  matches files or directories, relative to the root of the
  22.701 +	  repository; on the right, a user name.
  22.702 +	</para>
  22.703 +
  22.704 +	<para id="x_245">In the following example, the user
  22.705 +	  <literal>docwriter</literal> can only push changes to the
  22.706 +	  <filename class="directory">docs</filename> subtree of the
  22.707 +	  repository, while <literal>intern</literal> can push changes
  22.708 +	  to any file or directory except <filename
  22.709 +	    class="directory">source/sensitive</filename>.
  22.710 +	</para>
  22.711 +	<programlisting>[acl.allow]
  22.712 +docs/** = docwriter
  22.713 +[acl.deny]
  22.714 +source/sensitive/** = intern</programlisting>
  22.715 +
  22.716 +      </sect3>
  22.717 +      <sect3>
  22.718 +	<title>Testing and troubleshooting</title>
  22.719 +
  22.720 +	<para id="x_246">If you want to test the <literal
  22.721 +	    role="hg-ext">acl</literal> hook, run it with Mercurial's
  22.722 +	  debugging output enabled.  Since you'll probably be running
  22.723 +	  it on a server where it's not convenient (or sometimes
  22.724 +	  possible) to pass in the <option
  22.725 +	    role="hg-opt-global">--debug</option> option, don't forget
  22.726 +	  that you can enable debugging output in your <filename
  22.727 +	    role="special">~/.hgrc</filename>:
  22.728 +	</para>
  22.729 +	<programlisting>[ui]
  22.730 +debug = true</programlisting>
  22.731 +	<para id="x_247">With this enabled, the <literal
  22.732 +	    role="hg-ext">acl</literal> hook will print enough
  22.733 +	  information to let you figure out why it is allowing or
  22.734 +	  forbidding pushes from specific users.
  22.735 +	</para>
  22.736 +
  22.737 +      </sect3>    </sect2>
  22.738 +
  22.739 +    <sect2>
  22.740 +      <title><literal
  22.741 +	  role="hg-ext">bugzilla</literal>&emdash;integration with
  22.742 +	Bugzilla</title>
  22.743 +
  22.744 +      <para id="x_248">The <literal role="hg-ext">bugzilla</literal> extension
  22.745 +	adds a comment to a Bugzilla bug whenever it finds a reference
  22.746 +	to that bug ID in a commit comment.  You can install this hook
  22.747 +	on a shared server, so that any time a remote user pushes
  22.748 +	changes to this server, the hook gets run.
  22.749 +      </para>
  22.750 +
  22.751 +      <para id="x_249">It adds a comment to the bug that looks like this (you can
  22.752 +	configure the contents of the comment&emdash;see below):
  22.753 +      </para>
  22.754 +      <programlisting>Changeset aad8b264143a, made by Joe User
  22.755 +	&lt;joe.user@domain.com&gt; in the frobnitz repository, refers
  22.756 +	to this bug. For complete details, see
  22.757 +	http://hg.domain.com/frobnitz?cmd=changeset;node=aad8b264143a
  22.758 +	Changeset description: Fix bug 10483 by guarding against some
  22.759 +	NULL pointers</programlisting>
  22.760 +      <para id="x_24a">The value of this hook is that it automates the process of
  22.761 +	updating a bug any time a changeset refers to it.  If you
  22.762 +	configure the hook properly, it makes it easy for people to
  22.763 +	browse straight from a Bugzilla bug to a changeset that refers
  22.764 +	to that bug.
  22.765 +      </para>
  22.766 +
  22.767 +      <para id="x_24b">You can use the code in this hook as a starting point for
  22.768 +	some more exotic Bugzilla integration recipes.  Here are a few
  22.769 +	possibilities:
  22.770 +      </para>
  22.771 +      <itemizedlist>
  22.772 +	<listitem><para id="x_24c">Require that every changeset pushed to the
  22.773 +	    server have a valid bug ID in its commit comment.  In this
  22.774 +	    case, you'd want to configure the hook as a <literal
  22.775 +	      role="hook">pretxncommit</literal> hook.  This would
  22.776 +	    allow the hook to reject changes that didn't contain bug
  22.777 +	    IDs.
  22.778 +	  </para>
  22.779 +	</listitem>
  22.780 +	<listitem><para id="x_24d">Allow incoming changesets to automatically
  22.781 +	    modify the <emphasis>state</emphasis> of a bug, as well as
  22.782 +	    simply adding a comment.  For example, the hook could
  22.783 +	    recognise the string <quote>fixed bug 31337</quote> as
  22.784 +	    indicating that it should update the state of bug 31337 to
  22.785 +	    <quote>requires testing</quote>.
  22.786 +	  </para>
  22.787 +	</listitem></itemizedlist>
  22.788 +
  22.789 +      <sect3 id="sec:hook:bugzilla:config">
  22.790 +	<title>Configuring the <literal role="hook">bugzilla</literal>
  22.791 +	  hook</title>
  22.792 +
  22.793 +	<para id="x_24e">You should configure this hook in your server's
  22.794 +	  <filename role="special">~/.hgrc</filename> as an <literal
  22.795 +	    role="hook">incoming</literal> hook, for example as
  22.796 +	  follows:
  22.797 +	</para>
  22.798 +	<programlisting>[hooks]
  22.799 +incoming.bugzilla = python:hgext.bugzilla.hook</programlisting>
  22.800 +
  22.801 +	<para id="x_24f">Because of the specialised nature of this hook, and
  22.802 +	  because Bugzilla was not written with this kind of
  22.803 +	  integration in mind, configuring this hook is a somewhat
  22.804 +	  involved process.
  22.805 +	</para>
  22.806 +
  22.807 +	<para id="x_250">Before you begin, you must install the MySQL bindings
  22.808 +	  for Python on the host(s) where you'll be running the hook.
  22.809 +	  If this is not available as a binary package for your
  22.810 +	  system, you can download it from
  22.811 +	  <citation>web:mysql-python</citation>.
  22.812 +	</para>
  22.813 +
  22.814 +	<para id="x_251">Configuration information for this hook lives in the
  22.815 +	  <literal role="rc-bugzilla">bugzilla</literal> section of
  22.816 +	  your <filename role="special">~/.hgrc</filename>.
  22.817 +	</para>
  22.818 +	<itemizedlist>
  22.819 +	  <listitem><para id="x_252"><envar
  22.820 +		role="rc-item-bugzilla">version</envar>: The version
  22.821 +	      of Bugzilla installed on the server.  The database
  22.822 +	      schema that Bugzilla uses changes occasionally, so this
  22.823 +	      hook has to know exactly which schema to use.</para>
  22.824 +	  </listitem>
  22.825 +	  <listitem><para id="x_253"><envar role="rc-item-bugzilla">host</envar>:
  22.826 +	      The hostname of the MySQL server that stores your
  22.827 +	      Bugzilla data.  The database must be configured to allow
  22.828 +	      connections from whatever host you are running the
  22.829 +	      <literal role="hook">bugzilla</literal> hook on.
  22.830 +	    </para>
  22.831 +	  </listitem>
  22.832 +	  <listitem><para id="x_254"><envar role="rc-item-bugzilla">user</envar>:
  22.833 +	      The username with which to connect to the MySQL server.
  22.834 +	      The database must be configured to allow this user to
  22.835 +	      connect from whatever host you are running the <literal
  22.836 +		role="hook">bugzilla</literal> hook on.  This user
  22.837 +	      must be able to access and modify Bugzilla tables.  The
  22.838 +	      default value of this item is <literal>bugs</literal>,
  22.839 +	      which is the standard name of the Bugzilla user in a
  22.840 +	      MySQL database.
  22.841 +	    </para>
  22.842 +	  </listitem>
  22.843 +	  <listitem><para id="x_255"><envar
  22.844 +		role="rc-item-bugzilla">password</envar>: The MySQL
  22.845 +	      password for the user you configured above.  This is
  22.846 +	      stored as plain text, so you should make sure that
  22.847 +	      unauthorised users cannot read the <filename
  22.848 +		role="special">~/.hgrc</filename> file where you
  22.849 +	      store this information.
  22.850 +	    </para>
  22.851 +	  </listitem>
  22.852 +	  <listitem><para id="x_256"><envar role="rc-item-bugzilla">db</envar>:
  22.853 +	      The name of the Bugzilla database on the MySQL server.
  22.854 +	      The default value of this item is
  22.855 +	      <literal>bugs</literal>, which is the standard name of
  22.856 +	      the MySQL database where Bugzilla stores its data.
  22.857 +	    </para>
  22.858 +	  </listitem>
  22.859 +	  <listitem><para id="x_257"><envar
  22.860 +		role="rc-item-bugzilla">notify</envar>: If you want
  22.861 +	      Bugzilla to send out a notification email to subscribers
  22.862 +	      after this hook has added a comment to a bug, you will
  22.863 +	      need this hook to run a command whenever it updates the
  22.864 +	      database.  The command to run depends on where you have
  22.865 +	      installed Bugzilla, but it will typically look something
  22.866 +	      like this, if you have Bugzilla installed in <filename
  22.867 +		class="directory">/var/www/html/bugzilla</filename>:
  22.868 +	    </para>
  22.869 +	    <programlisting>cd /var/www/html/bugzilla &amp;&amp;
  22.870 +	      ./processmail %s nobody@nowhere.com</programlisting>
  22.871 +	  </listitem>
  22.872 +	  <listitem><para id="x_258">  The Bugzilla
  22.873 +	      <literal>processmail</literal> program expects to be
  22.874 +	      given a bug ID (the hook replaces
  22.875 +	      <quote><literal>%s</literal></quote> with the bug ID)
  22.876 +	      and an email address.  It also expects to be able to
  22.877 +	      write to some files in the directory that it runs in.
  22.878 +	      If Bugzilla and this hook are not installed on the same
  22.879 +	      machine, you will need to find a way to run
  22.880 +	      <literal>processmail</literal> on the server where
  22.881 +	      Bugzilla is installed.
  22.882 +	    </para>
  22.883 +	  </listitem></itemizedlist>
  22.884 +
  22.885 +      </sect3>
  22.886 +      <sect3>
  22.887 +	<title>Mapping committer names to Bugzilla user names</title>
  22.888 +
  22.889 +	<para id="x_259">By default, the <literal
  22.890 +	    role="hg-ext">bugzilla</literal> hook tries to use the
  22.891 +	  email address of a changeset's committer as the Bugzilla
  22.892 +	  user name with which to update a bug.  If this does not suit
  22.893 +	  your needs, you can map committer email addresses to
  22.894 +	  Bugzilla user names using a <literal
  22.895 +	    role="rc-usermap">usermap</literal> section.
  22.896 +	</para>
  22.897 +
  22.898 +	<para id="x_25a">Each item in the <literal
  22.899 +	    role="rc-usermap">usermap</literal> section contains an
  22.900 +	  email address on the left, and a Bugzilla user name on the
  22.901 +	  right.
  22.902 +	</para>
  22.903 +	<programlisting>[usermap]
  22.904 +jane.user@example.com = jane</programlisting>
  22.905 +	<para id="x_25b">You can either keep the <literal
  22.906 +	    role="rc-usermap">usermap</literal> data in a normal
  22.907 +	  <filename role="special">~/.hgrc</filename>, or tell the
  22.908 +	  <literal role="hg-ext">bugzilla</literal> hook to read the
  22.909 +	  information from an external <filename>usermap</filename>
  22.910 +	  file.  In the latter case, you can store
  22.911 +	  <filename>usermap</filename> data by itself in (for example)
  22.912 +	  a user-modifiable repository.  This makes it possible to let
  22.913 +	  your users maintain their own <envar
  22.914 +	    role="rc-item-bugzilla">usermap</envar> entries.  The main
  22.915 +	  <filename role="special">~/.hgrc</filename> file might look
  22.916 +	  like this:
  22.917 +	</para>
  22.918 +	<programlisting># regular hgrc file refers to external usermap file
  22.919 +[bugzilla]
  22.920 +usermap = /home/hg/repos/userdata/bugzilla-usermap.conf</programlisting>
  22.921 +	<para id="x_25c">While the <filename>usermap</filename> file that it
  22.922 +	  refers to might look like this:
  22.923 +	</para>
  22.924 +	<programlisting># bugzilla-usermap.conf - inside a hg repository
  22.925 +[usermap] stephanie@example.com = steph</programlisting>
  22.926 +
  22.927 +      </sect3>
  22.928 +      <sect3>
  22.929 +	<title>Configuring the text that gets added to a bug</title>
  22.930 +
  22.931 +	<para id="x_25d">You can configure the text that this hook adds as a
  22.932 +	  comment; you specify it in the form of a Mercurial template.
  22.933 +	  Several <filename role="special">~/.hgrc</filename> entries
  22.934 +	  (still in the <literal role="rc-bugzilla">bugzilla</literal>
  22.935 +	  section) control this behavior.
  22.936 +	</para>
  22.937 +	<itemizedlist>
  22.938 +	  <listitem><para id="x_25e"><literal>strip</literal>: The number of
  22.939 +	      leading path elements to strip from a repository's path
  22.940 +	      name to construct a partial path for a URL. For example,
  22.941 +	      if the repositories on your server live under <filename
  22.942 +		class="directory">/home/hg/repos</filename>, and you
  22.943 +	      have a repository whose path is <filename
  22.944 +		class="directory">/home/hg/repos/app/tests</filename>,
  22.945 +	      then setting <literal>strip</literal> to
  22.946 +	      <literal>4</literal> will give a partial path of
  22.947 +	      <filename class="directory">app/tests</filename>.  The
  22.948 +	      hook will make this partial path available when
  22.949 +	      expanding a template, as <literal>webroot</literal>.
  22.950 +	    </para>
  22.951 +	  </listitem>
  22.952 +	  <listitem><para id="x_25f"><literal>template</literal>: The text of the
  22.953 +	      template to use.  In addition to the usual
  22.954 +	      changeset-related variables, this template can use
  22.955 +	      <literal>hgweb</literal> (the value of the
  22.956 +	      <literal>hgweb</literal> configuration item above) and
  22.957 +	      <literal>webroot</literal> (the path constructed using
  22.958 +	      <literal>strip</literal> above).
  22.959 +	    </para>
  22.960 +	  </listitem></itemizedlist>
  22.961 +
  22.962 +	<para id="x_260">In addition, you can add a <envar
  22.963 +	    role="rc-item-web">baseurl</envar> item to the <literal
  22.964 +	    role="rc-web">web</literal> section of your <filename
  22.965 +	    role="special">~/.hgrc</filename>.  The <literal
  22.966 +	    role="hg-ext">bugzilla</literal> hook will make this
  22.967 +	  available when expanding a template, as the base string to
  22.968 +	  use when constructing a URL that will let users browse from
  22.969 +	  a Bugzilla comment to view a changeset.  Example:
  22.970 +	</para>
  22.971 +	<programlisting>[web]
  22.972 +baseurl = http://hg.domain.com/</programlisting>
  22.973 +
  22.974 +	<para id="x_261">Here is an example set of <literal
  22.975 +	    role="hg-ext">bugzilla</literal> hook config information.
  22.976 +	</para>
  22.977 +
  22.978 +	&ch10-bugzilla-config.lst;
  22.979 +
  22.980 +      </sect3>
  22.981 +      <sect3>
  22.982 +	<title>Testing and troubleshooting</title>
  22.983 +
  22.984 +	<para id="x_262">The most common problems with configuring the <literal
  22.985 +	    role="hg-ext">bugzilla</literal> hook relate to running
  22.986 +	  Bugzilla's <filename>processmail</filename> script and
  22.987 +	  mapping committer names to user names.
  22.988 +	</para>
  22.989 +
  22.990 +	<para id="x_263">Recall from <xref
  22.991 +	    linkend="sec:hook:bugzilla:config"/> above that the user
  22.992 +	  that runs the Mercurial process on the server is also the
  22.993 +	  one that will run the <filename>processmail</filename>
  22.994 +	  script.  The <filename>processmail</filename> script
  22.995 +	  sometimes causes Bugzilla to write to files in its
  22.996 +	  configuration directory, and Bugzilla's configuration files
  22.997 +	  are usually owned by the user that your web server runs
  22.998 +	  under.
  22.999 +	</para>
 22.1000 +
 22.1001 +	<para id="x_264">You can cause <filename>processmail</filename> to be run
 22.1002 +	  with the suitable user's identity using the
 22.1003 +	  <command>sudo</command> command.  Here is an example entry
 22.1004 +	  for a <filename>sudoers</filename> file.
 22.1005 +	</para>
 22.1006 +	<programlisting>hg_user = (httpd_user)
 22.1007 +NOPASSWD: /var/www/html/bugzilla/processmail-wrapper %s</programlisting>
 22.1008 +	<para id="x_265">This allows the <literal>hg_user</literal> user to run a
 22.1009 +	  <filename>processmail-wrapper</filename> program under the
 22.1010 +	  identity of <literal>httpd_user</literal>.
 22.1011 +	</para>
 22.1012 +
 22.1013 +	<para id="x_266">This indirection through a wrapper script is necessary,
 22.1014 +	  because <filename>processmail</filename> expects to be run
 22.1015 +	  with its current directory set to wherever you installed
 22.1016 +	  Bugzilla; you can't specify that kind of constraint in a
 22.1017 +	  <filename>sudoers</filename> file.  The contents of the
 22.1018 +	  wrapper script are simple:
 22.1019 +	</para>
 22.1020 +	<programlisting>#!/bin/sh
 22.1021 +cd `dirname $0` &amp;&amp; ./processmail "$1" nobody@example.com</programlisting>
 22.1022 +	<para id="x_267">It doesn't seem to matter what email address you pass to
 22.1023 +	  <filename>processmail</filename>.
 22.1024 +	</para>
 22.1025 +
 22.1026 +	<para id="x_268">If your <literal role="rc-usermap">usermap</literal> is
 22.1027 +	  not set up correctly, users will see an error message from
 22.1028 +	  the <literal role="hg-ext">bugzilla</literal> hook when they
 22.1029 +	  push changes to the server.  The error message will look
 22.1030 +	  like this:
 22.1031 +	</para>
 22.1032 +	<programlisting>cannot find bugzilla user id for john.q.public@example.com</programlisting>
 22.1033 +	<para id="x_269">What this means is that the committer's address,
 22.1034 +	  <literal>john.q.public@example.com</literal>, is not a valid
 22.1035 +	  Bugzilla user name, nor does it have an entry in your
 22.1036 +	  <literal role="rc-usermap">usermap</literal> that maps it to
 22.1037 +	  a valid Bugzilla user name.
 22.1038 +	</para>
 22.1039 +
 22.1040 +      </sect3>    </sect2>
 22.1041 +
 22.1042 +    <sect2>
 22.1043 +      <title><literal role="hg-ext">notify</literal>&emdash;send email
 22.1044 +	notifications</title>
 22.1045 +
 22.1046 +      <para id="x_26a">Although Mercurial's built-in web server provides RSS
 22.1047 +	feeds of changes in every repository, many people prefer to
 22.1048 +	receive change notifications via email.  The <literal
 22.1049 +	  role="hg-ext">notify</literal> hook lets you send out
 22.1050 +	notifications to a set of email addresses whenever changesets
 22.1051 +	arrive that those subscribers are interested in.
 22.1052 +      </para>
 22.1053 +
 22.1054 +      <para id="x_26b">As with the <literal role="hg-ext">bugzilla</literal>
 22.1055 +	hook, the <literal role="hg-ext">notify</literal> hook is
 22.1056 +	template-driven, so you can customise the contents of the
 22.1057 +	notification messages that it sends.
 22.1058 +      </para>
 22.1059 +
 22.1060 +      <para id="x_26c">By default, the <literal role="hg-ext">notify</literal>
 22.1061 +	hook includes a diff of every changeset that it sends out; you
 22.1062 +	can limit the size of the diff, or turn this feature off
 22.1063 +	entirely.  It is useful for letting subscribers review changes
 22.1064 +	immediately, rather than clicking to follow a URL.
 22.1065 +      </para>
 22.1066 +
 22.1067 +      <sect3>
 22.1068 +	<title>Configuring the <literal role="hg-ext">notify</literal>
 22.1069 +	  hook</title>
 22.1070 +
 22.1071 +	<para id="x_26d">You can set up the <literal
 22.1072 +	    role="hg-ext">notify</literal> hook to send one email
 22.1073 +	  message per incoming changeset, or one per incoming group of
 22.1074 +	  changesets (all those that arrived in a single pull or
 22.1075 +	  push).
 22.1076 +	</para>
 22.1077 +	<programlisting>[hooks]
 22.1078 +# send one email per group of changes
 22.1079 +changegroup.notify = python:hgext.notify.hook
 22.1080 +# send one email per change
 22.1081 +incoming.notify = python:hgext.notify.hook</programlisting>
 22.1082 +
 22.1083 +	<para id="x_26e">Configuration information for this hook lives in the
 22.1084 +	  <literal role="rc-notify">notify</literal> section of a
 22.1085 +	  <filename role="special">~/.hgrc</filename> file.
 22.1086 +	</para>
 22.1087 +	<itemizedlist>
 22.1088 +	  <listitem><para id="x_26f"><envar role="rc-item-notify">test</envar>:
 22.1089 +	      By default, this hook does not send out email at all;
 22.1090 +	      instead, it prints the message that it
 22.1091 +	      <emphasis>would</emphasis> send.  Set this item to
 22.1092 +	      <literal>false</literal> to allow email to be sent. The
 22.1093 +	      reason that sending of email is turned off by default is
 22.1094 +	      that it takes several tries to configure this extension
 22.1095 +	      exactly as you would like, and it would be bad form to
 22.1096 +	      spam subscribers with a number of <quote>broken</quote>
 22.1097 +	      notifications while you debug your configuration.
 22.1098 +	    </para>
 22.1099 +	  </listitem>
 22.1100 +	  <listitem><para id="x_270"><envar role="rc-item-notify">config</envar>:
 22.1101 +	      The path to a configuration file that contains
 22.1102 +	      subscription information.  This is kept separate from
 22.1103 +	      the main <filename role="special">~/.hgrc</filename> so
 22.1104 +	      that you can maintain it in a repository of its own.
 22.1105 +	      People can then clone that repository, update their
 22.1106 +	      subscriptions, and push the changes back to your server.
 22.1107 +	    </para>
 22.1108 +	  </listitem>
 22.1109 +	  <listitem><para id="x_271"><envar role="rc-item-notify">strip</envar>:
 22.1110 +	      The number of leading path separator characters to strip
 22.1111 +	      from a repository's path, when deciding whether a
 22.1112 +	      repository has subscribers.  For example, if the
 22.1113 +	      repositories on your server live in <filename
 22.1114 +		class="directory">/home/hg/repos</filename>, and
 22.1115 +	      <literal role="hg-ext">notify</literal> is considering a
 22.1116 +	      repository named <filename
 22.1117 +		class="directory">/home/hg/repos/shared/test</filename>, 
 22.1118 +	      setting <envar role="rc-item-notify">strip</envar> to
 22.1119 +	      <literal>4</literal> will cause <literal
 22.1120 +		role="hg-ext">notify</literal> to trim the path it
 22.1121 +	      considers down to <filename
 22.1122 +		class="directory">shared/test</filename>, and it will
 22.1123 +	      match subscribers against that.
 22.1124 +	    </para>
 22.1125 +	  </listitem>
 22.1126 +	  <listitem><para id="x_272"><envar
 22.1127 +		role="rc-item-notify">template</envar>: The template
 22.1128 +	      text to use when sending messages.  This specifies both
 22.1129 +	      the contents of the message header and its body.
 22.1130 +	    </para>
 22.1131 +	  </listitem>
 22.1132 +	  <listitem><para id="x_273"><envar
 22.1133 +		role="rc-item-notify">maxdiff</envar>: The maximum
 22.1134 +	      number of lines of diff data to append to the end of a
 22.1135 +	      message.  If a diff is longer than this, it is
 22.1136 +	      truncated.  By default, this is set to 300.  Set this to
 22.1137 +	      <literal>0</literal> to omit diffs from notification
 22.1138 +	      emails.
 22.1139 +	    </para>
 22.1140 +	  </listitem>
 22.1141 +	  <listitem><para id="x_274"><envar
 22.1142 +		role="rc-item-notify">sources</envar>: A list of
 22.1143 +	      sources of changesets to consider.  This lets you limit
 22.1144 +	      <literal role="hg-ext">notify</literal> to only sending
 22.1145 +	      out email about changes that remote users pushed into
 22.1146 +	      this repository via a server, for example.  See 
 22.1147 +	      <xref linkend="sec:hook:sources"/> for the sources you
 22.1148 +	      can specify here.
 22.1149 +	    </para>
 22.1150 +	  </listitem></itemizedlist>
 22.1151 +
 22.1152 +	<para id="x_275">If you set the <envar role="rc-item-web">baseurl</envar>
 22.1153 +	  item in the <literal role="rc-web">web</literal> section,
 22.1154 +	  you can use it in a template; it will be available as
 22.1155 +	  <literal>webroot</literal>.
 22.1156 +	</para>
 22.1157 +
 22.1158 +	<para id="x_276">Here is an example set of <literal
 22.1159 +	    role="hg-ext">notify</literal> configuration information.
 22.1160 +	</para>
 22.1161 +
 22.1162 +	&ch10-notify-config.lst;
 22.1163 +
 22.1164 +	<para id="x_277">This will produce a message that looks like the
 22.1165 +	  following:
 22.1166 +	</para>
 22.1167 +
 22.1168 +	&ch10-notify-config-mail.lst;
 22.1169 +
 22.1170 +      </sect3>
 22.1171 +      <sect3>
 22.1172 +	<title>Testing and troubleshooting</title>
 22.1173 +
 22.1174 +	<para id="x_278">Do not forget that by default, the <literal
 22.1175 +		role="hg-ext">notify</literal> extension <emphasis>will not
 22.1176 +	  send any mail</emphasis> until you explicitly configure it to do so,
 22.1177 +	  by setting <envar role="rc-item-notify">test</envar> to
 22.1178 +	  <literal>false</literal>.  Until you do that, it simply
 22.1179 +	  prints the message it <emphasis>would</emphasis> send.
 22.1180 +	</para>
 22.1181 +
 22.1182 +      </sect3>
 22.1183 +    </sect2>
 22.1184 +  </sect1>
 22.1185 +  <sect1 id="sec:hook:ref">
 22.1186 +    <title>Information for writers of hooks</title>
 22.1187 +
 22.1188 +    <sect2>
 22.1189 +      <title>In-process hook execution</title>
 22.1190 +
 22.1191 +      <para id="x_279">An in-process hook is called with arguments of the
 22.1192 +	following form:
 22.1193 +      </para>
 22.1194 +      <programlisting>def myhook(ui, repo, **kwargs): pass</programlisting>
 22.1195 +      <para id="x_27a">The <literal>ui</literal> parameter is a <literal
 22.1196 +	  role="py-mod-mercurial.ui">ui</literal> object. The
 22.1197 +	<literal>repo</literal> parameter is a <literal
 22.1198 +	  role="py-mod-mercurial.localrepo">localrepository</literal>
 22.1199 +	object.  The names and values of the
 22.1200 +	<literal>**kwargs</literal> parameters depend on the hook
 22.1201 +	being invoked, with the following common features:
 22.1202 +      </para>
 22.1203 +      <itemizedlist>
 22.1204 +	<listitem><para id="x_27b">If a parameter is named
 22.1205 +	    <literal>node</literal> or <literal>parentN</literal>, it
 22.1206 +	    will contain a hexadecimal changeset ID. The empty string
 22.1207 +	    is used to represent <quote>null changeset ID</quote>
 22.1208 +	    instead of a string of zeroes.
 22.1209 +	  </para>
 22.1210 +	</listitem>
 22.1211 +	<listitem><para id="x_27c">If a parameter is named
 22.1212 +	    <literal>url</literal>, it will contain the URL of a
 22.1213 +	    remote repository, if that can be determined.
 22.1214 +	  </para>
 22.1215 +	</listitem>
 22.1216 +	<listitem><para id="x_27d">Boolean-valued parameters are represented as
 22.1217 +	    Python <literal>bool</literal> objects.
 22.1218 +	  </para>
 22.1219 +	</listitem></itemizedlist>
 22.1220 +
 22.1221 +      <para id="x_27e">An in-process hook is called without a change to the
 22.1222 +	process's working directory (unlike external hooks, which are
 22.1223 +	run in the root of the repository).  It must not change the
 22.1224 +	process's working directory, or it will cause any calls it
 22.1225 +	makes into the Mercurial API to fail.
 22.1226 +      </para>
 22.1227 +
 22.1228 +      <para id="x_27f">If a hook returns a boolean <quote>false</quote> value, it
 22.1229 +	is considered to have succeeded.  If it returns a boolean
 22.1230 +	<quote>true</quote> value or raises an exception, it is
 22.1231 +	considered to have failed.  A useful way to think of the
 22.1232 +	calling convention is <quote>tell me if you fail</quote>.
 22.1233 +      </para>
 22.1234 +
 22.1235 +      <para id="x_280">Note that changeset IDs are passed into Python hooks as
 22.1236 +	hexadecimal strings, not the binary hashes that Mercurial's
 22.1237 +	APIs normally use.  To convert a hash from hex to binary, use
 22.1238 +	the <literal>bin</literal> function.
 22.1239 +      </para>
 22.1240 +    </sect2>
 22.1241 +
 22.1242 +    <sect2>
 22.1243 +      <title>External hook execution</title>
 22.1244 +
 22.1245 +      <para id="x_281">An external hook is passed to the shell of the user
 22.1246 +	running Mercurial. Features of that shell, such as variable
 22.1247 +	substitution and command redirection, are available.  The hook
 22.1248 +	is run in the root directory of the repository (unlike
 22.1249 +	in-process hooks, which are run in the same directory that
 22.1250 +	Mercurial was run in).
 22.1251 +      </para>
 22.1252 +
 22.1253 +      <para id="x_282">Hook parameters are passed to the hook as environment
 22.1254 +	variables.  Each environment variable's name is converted in
 22.1255 +	upper case and prefixed with the string
 22.1256 +	<quote><literal>HG_</literal></quote>.  For example, if the
 22.1257 +	name of a parameter is <quote><literal>node</literal></quote>,
 22.1258 +	the name of the environment variable representing that
 22.1259 +	parameter will be <quote><literal>HG_NODE</literal></quote>.
 22.1260 +      </para>
 22.1261 +
 22.1262 +      <para id="x_283">A boolean parameter is represented as the string
 22.1263 +	<quote><literal>1</literal></quote> for <quote>true</quote>,
 22.1264 +	<quote><literal>0</literal></quote> for <quote>false</quote>.
 22.1265 +	If an environment variable is named <envar>HG_NODE</envar>,
 22.1266 +	<envar>HG_PARENT1</envar> or <envar>HG_PARENT2</envar>, it
 22.1267 +	contains a changeset ID represented as a hexadecimal string.
 22.1268 +	The empty string is used to represent <quote>null changeset
 22.1269 +	  ID</quote> instead of a string of zeroes.  If an environment
 22.1270 +	variable is named <envar>HG_URL</envar>, it will contain the
 22.1271 +	URL of a remote repository, if that can be determined.
 22.1272 +      </para>
 22.1273 +
 22.1274 +      <para id="x_284">If a hook exits with a status of zero, it is considered to
 22.1275 +	have succeeded.  If it exits with a non-zero status, it is
 22.1276 +	considered to have failed.
 22.1277 +      </para>
 22.1278 +    </sect2>
 22.1279 +
 22.1280 +    <sect2>
 22.1281 +      <title>Finding out where changesets come from</title>
 22.1282 +
 22.1283 +      <para id="x_285">A hook that involves the transfer of changesets between a
 22.1284 +	local repository and another may be able to find out
 22.1285 +	information about the <quote>far side</quote>.  Mercurial
 22.1286 +	knows <emphasis>how</emphasis> changes are being transferred,
 22.1287 +	and in many cases <emphasis>where</emphasis> they are being
 22.1288 +	transferred to or from.
 22.1289 +      </para>
 22.1290 +
 22.1291 +      <sect3 id="sec:hook:sources">
 22.1292 +	<title>Sources of changesets</title>
 22.1293 +
 22.1294 +	<para id="x_286">Mercurial will tell a hook what means are, or were, used
 22.1295 +	  to transfer changesets between repositories.  This is
 22.1296 +	  provided by Mercurial in a Python parameter named
 22.1297 +	  <literal>source</literal>, or an environment variable named
 22.1298 +	  <envar>HG_SOURCE</envar>.
 22.1299 +	</para>
 22.1300 +
 22.1301 +	<itemizedlist>
 22.1302 +	  <listitem><para id="x_287"><literal>serve</literal>: Changesets are
 22.1303 +	      transferred to or from a remote repository over http or
 22.1304 +	      ssh.
 22.1305 +	    </para>
 22.1306 +	  </listitem>
 22.1307 +	  <listitem><para id="x_288"><literal>pull</literal>: Changesets are
 22.1308 +	      being transferred via a pull from one repository into
 22.1309 +	      another.
 22.1310 +	    </para>
 22.1311 +	  </listitem>
 22.1312 +	  <listitem><para id="x_289"><literal>push</literal>: Changesets are
 22.1313 +	      being transferred via a push from one repository into
 22.1314 +	      another.
 22.1315 +	    </para>
 22.1316 +	  </listitem>
 22.1317 +	  <listitem><para id="x_28a"><literal>bundle</literal>: Changesets are
 22.1318 +	      being transferred to or from a bundle.
 22.1319 +	    </para>
 22.1320 +	  </listitem></itemizedlist>
 22.1321 +      </sect3>
 22.1322 +
 22.1323 +      <sect3 id="sec:hook:url">
 22.1324 +	<title>Where changes are going&emdash;remote repository
 22.1325 +	  URLs</title>
 22.1326 +
 22.1327 +	<para id="x_28b">When possible, Mercurial will tell a hook the location
 22.1328 +	  of the <quote>far side</quote> of an activity that transfers
 22.1329 +	  changeset data between repositories.  This is provided by
 22.1330 +	  Mercurial in a Python parameter named
 22.1331 +	  <literal>url</literal>, or an environment variable named
 22.1332 +	  <envar>HG_URL</envar>.
 22.1333 +	</para>
 22.1334 +
 22.1335 +	<para id="x_28c">This information is not always known.  If a hook is
 22.1336 +	  invoked in a repository that is being served via http or
 22.1337 +	  ssh, Mercurial cannot tell where the remote repository is,
 22.1338 +	  but it may know where the client is connecting from.  In
 22.1339 +	  such cases, the URL will take one of the following forms:
 22.1340 +	</para>
 22.1341 +	<itemizedlist>
 22.1342 +	  <listitem><para id="x_28d"><literal>remote:ssh:1.2.3.4</literal>&emdash;remote 
 22.1343 +	      ssh client, at the IP address
 22.1344 +	      <literal>1.2.3.4</literal>.
 22.1345 +	    </para>
 22.1346 +	  </listitem>
 22.1347 +	  <listitem><para id="x_28e"><literal>remote:http:1.2.3.4</literal>&emdash;remote 
 22.1348 +	      http client, at the IP address
 22.1349 +	      <literal>1.2.3.4</literal>.  If the client is using SSL,
 22.1350 +	      this will be of the form
 22.1351 +	      <literal>remote:https:1.2.3.4</literal>.
 22.1352 +	    </para>
 22.1353 +	  </listitem>
 22.1354 +	  <listitem><para id="x_28f">Empty&emdash;no information could be
 22.1355 +	      discovered about the remote client.
 22.1356 +	    </para>
 22.1357 +	  </listitem></itemizedlist>
 22.1358 +      </sect3>
 22.1359 +    </sect2>
 22.1360 +  </sect1>
 22.1361 +  <sect1>
 22.1362 +    <title>Hook reference</title>
 22.1363 +
 22.1364 +    <sect2 id="sec:hook:changegroup">
 22.1365 +      <title><literal role="hook">changegroup</literal>&emdash;after
 22.1366 +	remote changesets added</title>
 22.1367 +
 22.1368 +      <para id="x_290">This hook is run after a group of pre-existing changesets
 22.1369 +	has been added to the repository, for example via a <command
 22.1370 +	  role="hg-cmd">hg pull</command> or <command role="hg-cmd">hg
 22.1371 +	  unbundle</command>.  This hook is run once per operation
 22.1372 +	that added one or more changesets.  This is in contrast to the
 22.1373 +	<literal role="hook">incoming</literal> hook, which is run
 22.1374 +	once per changeset, regardless of whether the changesets
 22.1375 +	arrive in a group.
 22.1376 +      </para>
 22.1377 +
 22.1378 +      <para id="x_291">Some possible uses for this hook include kicking off an
 22.1379 +	automated build or test of the added changesets, updating a
 22.1380 +	bug database, or notifying subscribers that a repository
 22.1381 +	contains new changes.
 22.1382 +      </para>
 22.1383 +
 22.1384 +      <para id="x_292">Parameters to this hook:
 22.1385 +      </para>
 22.1386 +      <itemizedlist>
 22.1387 +	<listitem><para id="x_293"><literal>node</literal>: A changeset ID.  The
 22.1388 +	    changeset ID of the first changeset in the group that was
 22.1389 +	    added.  All changesets between this and
 22.1390 +	    <literal role="tag">tip</literal>, inclusive, were added by a single
 22.1391 +	    <command role="hg-cmd">hg pull</command>, <command
 22.1392 +	      role="hg-cmd">hg push</command> or <command
 22.1393 +	      role="hg-cmd">hg unbundle</command>.
 22.1394 +	  </para>
 22.1395 +	</listitem>
 22.1396 +	<listitem><para id="x_294"><literal>source</literal>: A
 22.1397 +	    string.  The source of these changes.  See <xref
 22.1398 +	      linkend="sec:hook:sources"/> for details.
 22.1399 +	  </para>
 22.1400 +	</listitem>
 22.1401 +	<listitem><para id="x_295"><literal>url</literal>: A URL.  The
 22.1402 +	    location of the remote repository, if known.  See <xref
 22.1403 +	      linkend="sec:hook:url"/> for more information.
 22.1404 +	  </para>
 22.1405 +	</listitem></itemizedlist>
 22.1406 +
 22.1407 +      <para id="x_296">See also: <literal
 22.1408 +	  role="hook">incoming</literal> (<xref
 22.1409 +	  linkend="sec:hook:incoming"/>), <literal
 22.1410 +	  role="hook">prechangegroup</literal> (<xref
 22.1411 +	  linkend="sec:hook:prechangegroup"/>), <literal
 22.1412 +	  role="hook">pretxnchangegroup</literal> (<xref
 22.1413 +	  linkend="sec:hook:pretxnchangegroup"/>)
 22.1414 +      </para>
 22.1415 +    </sect2>
 22.1416 +
 22.1417 +    <sect2 id="sec:hook:commit">
 22.1418 +      <title><literal role="hook">commit</literal>&emdash;after a new
 22.1419 +	changeset is created</title>
 22.1420 +
 22.1421 +      <para id="x_297">This hook is run after a new changeset has been created.
 22.1422 +      </para>
 22.1423 +
 22.1424 +      <para id="x_298">Parameters to this hook:
 22.1425 +      </para>
 22.1426 +      <itemizedlist>
 22.1427 +	<listitem><para id="x_299"><literal>node</literal>: A changeset ID.  The
 22.1428 +	    changeset ID of the newly committed changeset.
 22.1429 +	  </para>
 22.1430 +	</listitem>
 22.1431 +	<listitem><para id="x_29a"><literal>parent1</literal>: A changeset ID.
 22.1432 +	    The changeset ID of the first parent of the newly
 22.1433 +	    committed changeset.
 22.1434 +	  </para>
 22.1435 +	</listitem>
 22.1436 +	<listitem><para id="x_29b"><literal>parent2</literal>: A changeset ID.
 22.1437 +	    The changeset ID of the second parent of the newly
 22.1438 +	    committed changeset.
 22.1439 +	  </para>
 22.1440 +	</listitem></itemizedlist>
 22.1441 +
 22.1442 +      <para id="x_29c">See also: <literal
 22.1443 +	  role="hook">precommit</literal> (<xref
 22.1444 +	  linkend="sec:hook:precommit"/>), <literal
 22.1445 +	  role="hook">pretxncommit</literal> (<xref
 22.1446 +	  linkend="sec:hook:pretxncommit"/>)
 22.1447 +      </para>
 22.1448 +    </sect2>
 22.1449 +
 22.1450 +    <sect2 id="sec:hook:incoming">
 22.1451 +      <title><literal role="hook">incoming</literal>&emdash;after one
 22.1452 +	remote changeset is added</title>
 22.1453 +
 22.1454 +      <para id="x_29d">This hook is run after a pre-existing changeset has been
 22.1455 +	added to the repository, for example via a <command
 22.1456 +	  role="hg-cmd">hg push</command>.  If a group of changesets
 22.1457 +	was added in a single operation, this hook is called once for
 22.1458 +	each added changeset.
 22.1459 +      </para>
 22.1460 +
 22.1461 +      <para id="x_29e">You can use this hook for the same purposes as
 22.1462 +	the <literal role="hook">changegroup</literal> hook (<xref
 22.1463 +	  linkend="sec:hook:changegroup"/>); it's simply more
 22.1464 +	convenient sometimes to run a hook once per group of
 22.1465 +	changesets, while other times it's handier once per changeset.
 22.1466 +      </para>
 22.1467 +
 22.1468 +      <para id="x_29f">Parameters to this hook:
 22.1469 +      </para>
 22.1470 +      <itemizedlist>
 22.1471 +	<listitem><para id="x_2a0"><literal>node</literal>: A changeset ID.  The
 22.1472 +	    ID of the newly added changeset.
 22.1473 +	  </para>
 22.1474 +	</listitem>
 22.1475 +	<listitem><para id="x_2a1"><literal>source</literal>: A
 22.1476 +	    string.  The source of these changes.  See <xref
 22.1477 +	      linkend="sec:hook:sources"/> for details.
 22.1478 +	  </para>
 22.1479 +	</listitem>
 22.1480 +	<listitem><para id="x_2a2"><literal>url</literal>: A URL.  The
 22.1481 +	    location of the remote repository, if known.  See <xref
 22.1482 +	      linkend="sec:hook:url"/> for more information.
 22.1483 +	  </para>
 22.1484 +	</listitem></itemizedlist>
 22.1485 +
 22.1486 +      <para id="x_2a3">See also: <literal
 22.1487 +	  role="hook">changegroup</literal> (<xref
 22.1488 +	  linkend="sec:hook:changegroup"/>) <literal
 22.1489 +	  role="hook">prechangegroup</literal> (<xref
 22.1490 +	  linkend="sec:hook:prechangegroup"/>), <literal
 22.1491 +	  role="hook">pretxnchangegroup</literal> (<xref
 22.1492 +	  linkend="sec:hook:pretxnchangegroup"/>)
 22.1493 +      </para>
 22.1494 +    </sect2>
 22.1495 +
 22.1496 +    <sect2 id="sec:hook:outgoing">
 22.1497 +      <title><literal role="hook">outgoing</literal>&emdash;after
 22.1498 +	changesets are propagated</title>
 22.1499 +
 22.1500 +      <para id="x_2a4">This hook is run after a group of changesets has been
 22.1501 +	propagated out of this repository, for example by a <command
 22.1502 +	  role="hg-cmd">hg push</command> or <command role="hg-cmd">hg
 22.1503 +	  bundle</command> command.
 22.1504 +      </para>
 22.1505 +
 22.1506 +      <para id="x_2a5">One possible use for this hook is to notify administrators
 22.1507 +	that changes have been pulled.
 22.1508 +      </para>
 22.1509 +
 22.1510 +      <para id="x_2a6">Parameters to this hook:
 22.1511 +      </para>
 22.1512 +      <itemizedlist>
 22.1513 +	<listitem><para id="x_2a7"><literal>node</literal>: A changeset ID.  The
 22.1514 +	    changeset ID of the first changeset of the group that was
 22.1515 +	    sent.
 22.1516 +	  </para>
 22.1517 +	</listitem>
 22.1518 +	<listitem><para id="x_2a8"><literal>source</literal>: A string.  The
 22.1519 +	    source of the of the operation (see <xref
 22.1520 +	      linkend="sec:hook:sources"/>).  If a remote
 22.1521 +	    client pulled changes from this repository,
 22.1522 +	    <literal>source</literal> will be
 22.1523 +	    <literal>serve</literal>.  If the client that obtained
 22.1524 +	    changes from this repository was local,
 22.1525 +	    <literal>source</literal> will be
 22.1526 +	    <literal>bundle</literal>, <literal>pull</literal>, or
 22.1527 +	    <literal>push</literal>, depending on the operation the
 22.1528 +	    client performed.
 22.1529 +	  </para>
 22.1530 +	</listitem>
 22.1531 +	<listitem><para id="x_2a9"><literal>url</literal>: A URL.  The
 22.1532 +	    location of the remote repository, if known.  See <xref
 22.1533 +	      linkend="sec:hook:url"/> for more information.
 22.1534 +	  </para>
 22.1535 +	</listitem></itemizedlist>
 22.1536 +
 22.1537 +      <para id="x_2aa">See also: <literal
 22.1538 +	  role="hook">preoutgoing</literal> (<xref
 22.1539 +	  linkend="sec:hook:preoutgoing"/>)
 22.1540 +      </para>
 22.1541 +    </sect2>
 22.1542 +
 22.1543 +    <sect2 id="sec:hook:prechangegroup">
 22.1544 +      <title><literal
 22.1545 +	  role="hook">prechangegroup</literal>&emdash;before starting
 22.1546 +	to add remote changesets</title>
 22.1547 +
 22.1548 +      <para id="x_2ab">This controlling hook is run before Mercurial begins to
 22.1549 +	add a group of changesets from another repository.
 22.1550 +      </para>
 22.1551 +
 22.1552 +      <para id="x_2ac">This hook does not have any information about the
 22.1553 +	changesets to be added, because it is run before transmission
 22.1554 +	of those changesets is allowed to begin.  If this hook fails,
 22.1555 +	the changesets will not be transmitted.
 22.1556 +      </para>
 22.1557 +
 22.1558 +      <para id="x_2ad">One use for this hook is to prevent external changes from
 22.1559 +	being added to a repository.  For example, you could use this
 22.1560 +	to <quote>freeze</quote> a server-hosted branch temporarily or
 22.1561 +	permanently so that users cannot push to it, while still
 22.1562 +	allowing a local administrator to modify the repository.
 22.1563 +      </para>
 22.1564 +
 22.1565 +      <para id="x_2ae">Parameters to this hook:
 22.1566 +      </para>
 22.1567 +      <itemizedlist>
 22.1568 +	<listitem><para id="x_2af"><literal>source</literal>: A string.  The
 22.1569 +	    source of these changes.  See <xref
 22.1570 +	      linkend="sec:hook:sources"/> for details.
 22.1571 +	  </para>
 22.1572 +	</listitem>
 22.1573 +	<listitem><para id="x_2b0"><literal>url</literal>: A URL.  The
 22.1574 +	    location of the remote repository, if known.  See <xref
 22.1575 +	      linkend="sec:hook:url"/> for more information.
 22.1576 +	  </para>
 22.1577 +	</listitem></itemizedlist>
 22.1578 +
 22.1579 +      <para id="x_2b1">See also: <literal
 22.1580 +	  role="hook">changegroup</literal> (<xref
 22.1581 +	  linkend="sec:hook:changegroup"/>), <literal
 22.1582 +	  role="hook">incoming</literal> (<xref
 22.1583 +	  linkend="sec:hook:incoming"/>), <literal
 22.1584 +	  role="hook">pretxnchangegroup</literal> (<xref
 22.1585 +	  linkend="sec:hook:pretxnchangegroup"/>)
 22.1586 +      </para>
 22.1587 +    </sect2>
 22.1588 +
 22.1589 +    <sect2 id="sec:hook:precommit">
 22.1590 +      <title><literal role="hook">precommit</literal>&emdash;before
 22.1591 +	starting to commit a changeset</title>
 22.1592 +
 22.1593 +      <para id="x_2b2">This hook is run before Mercurial begins to commit a new
 22.1594 +	changeset. It is run before Mercurial has any of the metadata
 22.1595 +	for the commit, such as the files to be committed, the commit
 22.1596 +	message, or the commit date.
 22.1597 +      </para>
 22.1598 +
 22.1599 +      <para id="x_2b3">One use for this hook is to disable the ability to commit
 22.1600 +	new changesets, while still allowing incoming changesets.
 22.1601 +	Another is to run a build or test, and only allow the commit
 22.1602 +	to begin if the build or test succeeds.
 22.1603 +      </para>
 22.1604 +
 22.1605 +      <para id="x_2b4">Parameters to this hook:
 22.1606 +      </para>
 22.1607 +      <itemizedlist>
 22.1608 +	<listitem><para id="x_2b5"><literal>parent1</literal>: A changeset ID.
 22.1609 +	    The changeset ID of the first parent of the working
 22.1610 +	    directory.
 22.1611 +	  </para>
 22.1612 +	</listitem>
 22.1613 +	<listitem><para id="x_2b6"><literal>parent2</literal>: A changeset ID.
 22.1614 +	    The changeset ID of the second parent of the working
 22.1615 +	    directory.
 22.1616 +	  </para>
 22.1617 +	</listitem></itemizedlist>
 22.1618 +      <para id="x_2b7">If the commit proceeds, the parents of the working
 22.1619 +	directory will become the parents of the new changeset.
 22.1620 +      </para>
 22.1621 +
 22.1622 +      <para id="x_2b8">See also: <literal role="hook">commit</literal>
 22.1623 +	(<xref linkend="sec:hook:commit"/>), <literal
 22.1624 +	  role="hook">pretxncommit</literal> (<xref
 22.1625 +	  linkend="sec:hook:pretxncommit"/>)
 22.1626 +      </para>
 22.1627 +    </sect2>
 22.1628 +
 22.1629 +    <sect2 id="sec:hook:preoutgoing">
 22.1630 +      <title><literal role="hook">preoutgoing</literal>&emdash;before
 22.1631 +	starting to propagate changesets</title>
 22.1632 +
 22.1633 +      <para id="x_2b9">This hook is invoked before Mercurial knows the identities
 22.1634 +	of the changesets to be transmitted.
 22.1635 +      </para>
 22.1636 +
 22.1637 +      <para id="x_2ba">One use for this hook is to prevent changes from being
 22.1638 +	transmitted to another repository.
 22.1639 +      </para>
 22.1640 +
 22.1641 +      <para id="x_2bb">Parameters to this hook:
 22.1642 +      </para>
 22.1643 +      <itemizedlist>
 22.1644 +	<listitem><para id="x_2bc"><literal>source</literal>: A
 22.1645 +	    string.  The source of the operation that is attempting to
 22.1646 +	    obtain changes from this repository (see <xref
 22.1647 +	      linkend="sec:hook:sources"/>).  See the documentation
 22.1648 +	    for the <literal>source</literal> parameter to the
 22.1649 +	    <literal role="hook">outgoing</literal> hook, in
 22.1650 +	    <xref linkend="sec:hook:outgoing"/>, for possible values
 22.1651 +	    of this parameter.
 22.1652 +	  </para>
 22.1653 +	</listitem>
 22.1654 +	<listitem><para id="x_2bd"><literal>url</literal>: A URL.  The
 22.1655 +	    location of the remote repository, if known.  See <xref
 22.1656 +	      linkend="sec:hook:url"/> for more information.
 22.1657 +	  </para>
 22.1658 +	</listitem></itemizedlist>
 22.1659 +
 22.1660 +      <para id="x_2be">See also: <literal
 22.1661 +	  role="hook">outgoing</literal> (<xref
 22.1662 +	  linkend="sec:hook:outgoing"/>)
 22.1663 +      </para>
 22.1664 +    </sect2>
 22.1665 +
 22.1666 +    <sect2 id="sec:hook:pretag">
 22.1667 +      <title><literal role="hook">pretag</literal>&emdash;before
 22.1668 +	tagging a changeset</title>
 22.1669 +
 22.1670 +      <para id="x_2bf">This controlling hook is run before a tag is created.  If
 22.1671 +	the hook succeeds, creation of the tag proceeds.  If the hook
 22.1672 +	fails, the tag is not created.
 22.1673 +      </para>
 22.1674 +
 22.1675 +      <para id="x_2c0">Parameters to this hook:
 22.1676 +      </para>
 22.1677 +      <itemizedlist>
 22.1678 +	<listitem><para id="x_2c1"><literal>local</literal>: A boolean.  Whether
 22.1679 +	    the tag is local to this repository instance (i.e. stored
 22.1680 +	    in <filename role="special">.hg/localtags</filename>) or
 22.1681 +	    managed by Mercurial (stored in <filename
 22.1682 +	      role="special">.hgtags</filename>).
 22.1683 +	  </para>
 22.1684 +	</listitem>
 22.1685 +	<listitem><para id="x_2c2"><literal>node</literal>: A changeset ID.  The
 22.1686 +	    ID of the changeset to be tagged.
 22.1687 +	  </para>
 22.1688 +	</listitem>
 22.1689 +	<listitem><para id="x_2c3"><literal>tag</literal>: A string.  The name of
 22.1690 +	    the tag to be created.
 22.1691 +	  </para>
 22.1692 +	</listitem></itemizedlist>
 22.1693 +
 22.1694 +      <para id="x_2c4">If the tag to be created is
 22.1695 +	revision-controlled, the <literal
 22.1696 +	  role="hook">precommit</literal> and <literal
 22.1697 +	  role="hook">pretxncommit</literal> hooks (<xref
 22.1698 +	  linkend="sec:hook:commit"/> and <xref
 22.1699 +	  linkend="sec:hook:pretxncommit"/>) will also be run.
 22.1700 +      </para>
 22.1701 +
 22.1702 +      <para id="x_2c5">See also: <literal role="hook">tag</literal>
 22.1703 +	(<xref linkend="sec:hook:tag"/>)
 22.1704 +      </para>
 22.1705 +    </sect2>
 22.1706 +
 22.1707 +    <sect2 id="sec:hook:pretxnchangegroup">
 22.1708 +      <title><literal
 22.1709 +	  role="hook">pretxnchangegroup</literal>&emdash;before
 22.1710 +	completing addition of remote changesets</title>
 22.1711 +
 22.1712 +      <para id="x_2c6">This controlling hook is run before a
 22.1713 +	transaction&emdash;that manages the addition of a group of new
 22.1714 +	changesets from outside the repository&emdash;completes.  If
 22.1715 +	the hook succeeds, the transaction completes, and all of the
 22.1716 +	changesets become permanent within this repository.  If the
 22.1717 +	hook fails, the transaction is rolled back, and the data for
 22.1718 +	the changesets is erased.
 22.1719 +      </para>
 22.1720 +
 22.1721 +      <para id="x_2c7">This hook can access the metadata associated with the
 22.1722 +	almost-added changesets, but it should not do anything
 22.1723 +	permanent with this data. It must also not modify the working
 22.1724 +	directory.
 22.1725 +      </para>
 22.1726 +
 22.1727 +      <para id="x_2c8">While this hook is running, if other Mercurial processes
 22.1728 +	access this repository, they will be able to see the
 22.1729 +	almost-added changesets as if they are permanent.  This may
 22.1730 +	lead to race conditions if you do not take steps to avoid
 22.1731 +	them.
 22.1732 +      </para>
 22.1733 +
 22.1734 +      <para id="x_2c9">This hook can be used to automatically vet a group of
 22.1735 +	changesets.  If the hook fails, all of the changesets are
 22.1736 +	<quote>rejected</quote> when the transaction rolls back.
 22.1737 +      </para>
 22.1738 +
 22.1739 +      <para id="x_2ca">Parameters to this hook:
 22.1740 +      </para>
 22.1741 +      <itemizedlist>
 22.1742 +	<listitem><para id="x_2cb"><literal>node</literal>: A changeset ID.  The
 22.1743 +	    changeset ID of the first changeset in the group that was
 22.1744 +	    added.  All changesets between this and
 22.1745 +	    <literal role="tag">tip</literal>,
 22.1746 +	    inclusive, were added by a single <command
 22.1747 +	      role="hg-cmd">hg pull</command>, <command
 22.1748 +	      role="hg-cmd">hg push</command> or <command
 22.1749 +	      role="hg-cmd">hg unbundle</command>.
 22.1750 +	  </para>
 22.1751 +	</listitem>
 22.1752 +	<listitem><para id="x_2cc"><literal>source</literal>: A
 22.1753 +	    string.  The source of these changes.  See <xref
 22.1754 +	      linkend="sec:hook:sources"/> for details.
 22.1755 +	  </para>
 22.1756 +	</listitem>
 22.1757 +	<listitem><para id="x_2cd"><literal>url</literal>: A URL.  The
 22.1758 +	    location of the remote repository, if known.  See <xref
 22.1759 +	      linkend="sec:hook:url"/> for more information.
 22.1760 +	  </para>
 22.1761 +	</listitem></itemizedlist>
 22.1762 +
 22.1763 +      <para id="x_2ce">See also: <literal
 22.1764 +	  role="hook">changegroup</literal> (<xref
 22.1765 +	  linkend="sec:hook:changegroup"/>), <literal
 22.1766 +	  role="hook">incoming</literal> (<xref
 22.1767 +	  linkend="sec:hook:incoming"/>), <literal
 22.1768 +	  role="hook">prechangegroup</literal> (<xref
 22.1769 +	  linkend="sec:hook:prechangegroup"/>)
 22.1770 +      </para>
 22.1771 +    </sect2>
 22.1772 +
 22.1773 +    <sect2 id="sec:hook:pretxncommit">
 22.1774 +      <title><literal role="hook">pretxncommit</literal>&emdash;before
 22.1775 +	completing commit of new changeset</title>
 22.1776 +
 22.1777 +      <para id="x_2cf">This controlling hook is run before a
 22.1778 +	transaction&emdash;that manages a new commit&emdash;completes.
 22.1779 +	If the hook succeeds, the transaction completes and the
 22.1780 +	changeset becomes permanent within this repository.  If the
 22.1781 +	hook fails, the transaction is rolled back, and the commit
 22.1782 +	data is erased.
 22.1783 +      </para>
 22.1784 +
 22.1785 +      <para id="x_2d0">This hook can access the metadata associated with the
 22.1786 +	almost-new changeset, but it should not do anything permanent
 22.1787 +	with this data.  It must also not modify the working
 22.1788 +	directory.
 22.1789 +      </para>
 22.1790 +
 22.1791 +      <para id="x_2d1">While this hook is running, if other Mercurial processes
 22.1792 +	access this repository, they will be able to see the
 22.1793 +	almost-new changeset as if it is permanent.  This may lead to
 22.1794 +	race conditions if you do not take steps to avoid them.
 22.1795 +      </para>
 22.1796 +
 22.1797 +      <para id="x_2d2">Parameters to this hook:</para>
 22.1798 +
 22.1799 +      <itemizedlist>
 22.1800 +	<listitem><para id="x_2d3"><literal>node</literal>: A changeset ID.  The
 22.1801 +	    changeset ID of the newly committed changeset.
 22.1802 +	  </para>
 22.1803 +	</listitem>
 22.1804 +	<listitem><para id="x_2d4"><literal>parent1</literal>: A changeset ID.
 22.1805 +	    The changeset ID of the first parent of the newly
 22.1806 +	    committed changeset.
 22.1807 +	  </para>
 22.1808 +	</listitem>
 22.1809 +	<listitem><para id="x_2d5"><literal>parent2</literal>: A changeset ID.
 22.1810 +	    The changeset ID of the second parent of the newly
 22.1811 +	    committed changeset.
 22.1812 +	  </para>
 22.1813 +	</listitem></itemizedlist>
 22.1814 +
 22.1815 +      <para id="x_2d6">See also: <literal
 22.1816 +	  role="hook">precommit</literal> (<xref
 22.1817 +	  linkend="sec:hook:precommit"/>)
 22.1818 +      </para>
 22.1819 +    </sect2>
 22.1820 +
 22.1821 +    <sect2 id="sec:hook:preupdate">
 22.1822 +      <title><literal role="hook">preupdate</literal>&emdash;before
 22.1823 +	updating or merging working directory</title>
 22.1824 +
 22.1825 +      <para id="x_2d7">This controlling hook is run before an update
 22.1826 +	or merge of the working directory begins.  It is run only if
 22.1827 +	Mercurial's normal pre-update checks determine that the update
 22.1828 +	or merge can proceed.  If the hook succeeds, the update or
 22.1829 +	merge may proceed; if it fails, the update or merge does not
 22.1830 +	start.
 22.1831 +      </para>
 22.1832 +
 22.1833 +      <para id="x_2d8">Parameters to this hook:
 22.1834 +      </para>
 22.1835 +      <itemizedlist>
 22.1836 +	<listitem><para id="x_2d9"><literal>parent1</literal>: A
 22.1837 +	    changeset ID. The ID of the parent that the working
 22.1838 +	    directory is to be updated to.  If the working directory
 22.1839 +	    is being merged, it will not change this parent.
 22.1840 +	  </para>
 22.1841 +	</listitem>
 22.1842 +	<listitem><para id="x_2da"><literal>parent2</literal>: A
 22.1843 +	    changeset ID. Only set if the working directory is being
 22.1844 +	    merged.  The ID of the revision that the working directory
 22.1845 +	    is being merged with.
 22.1846 +	  </para>
 22.1847 +	</listitem></itemizedlist>
 22.1848 +
 22.1849 +      <para id="x_2db">See also: <literal role="hook">update</literal>
 22.1850 +	(<xref linkend="sec:hook:update"/>)</para>
 22.1851 +    </sect2>
 22.1852 +
 22.1853 +    <sect2 id="sec:hook:tag">
 22.1854 +      <title><literal role="hook">tag</literal>&emdash;after tagging a
 22.1855 +	changeset</title>
 22.1856 +
 22.1857 +      <para id="x_2dc">This hook is run after a tag has been created.
 22.1858 +      </para>
 22.1859 +
 22.1860 +      <para id="x_2dd">Parameters to this hook:
 22.1861 +      </para>
 22.1862 +      <itemizedlist>
 22.1863 +	<listitem><para id="x_2de"><literal>local</literal>: A boolean.  Whether
 22.1864 +	    the new tag is local to this repository instance (i.e.
 22.1865 +	    stored in <filename
 22.1866 +	      role="special">.hg/localtags</filename>) or managed by
 22.1867 +	    Mercurial (stored in <filename
 22.1868 +	      role="special">.hgtags</filename>).
 22.1869 +	  </para>
 22.1870 +	</listitem>
 22.1871 +	<listitem><para id="x_2df"><literal>node</literal>: A changeset ID.  The
 22.1872 +	    ID of the changeset that was tagged.
 22.1873 +	  </para>
 22.1874 +	</listitem>
 22.1875 +	<listitem><para id="x_2e0"><literal>tag</literal>: A string.  The name of
 22.1876 +	    the tag that was created.
 22.1877 +	  </para>
 22.1878 +	</listitem></itemizedlist>
 22.1879 +
 22.1880 +      <para id="x_2e1">If the created tag is revision-controlled, the <literal
 22.1881 +	  role="hook">commit</literal> hook (section <xref
 22.1882 +	  linkend="sec:hook:commit"/>) is run before this hook.
 22.1883 +      </para>
 22.1884 +
 22.1885 +      <para id="x_2e2">See also: <literal role="hook">pretag</literal>
 22.1886 +	(<xref linkend="sec:hook:pretag"/>)
 22.1887 +      </para>
 22.1888 +    </sect2>
 22.1889 +
 22.1890 +    <sect2 id="sec:hook:update">
 22.1891 +      <title><literal role="hook">update</literal>&emdash;after
 22.1892 +	updating or merging working directory</title>
 22.1893 +
 22.1894 +      <para id="x_2e3">This hook is run after an update or merge of the working
 22.1895 +	directory completes.  Since a merge can fail (if the external
 22.1896 +	<command>hgmerge</command> command fails to resolve conflicts
 22.1897 +	in a file), this hook communicates whether the update or merge
 22.1898 +	completed cleanly.
 22.1899 +      </para>
 22.1900 +
 22.1901 +      <itemizedlist>
 22.1902 +	<listitem><para id="x_2e4"><literal>error</literal>: A boolean.
 22.1903 +	    Indicates whether the update or merge completed
 22.1904 +	    successfully.
 22.1905 +	  </para>
 22.1906 +	</listitem>
 22.1907 +	<listitem><para id="x_2e5"><literal>parent1</literal>: A changeset ID.
 22.1908 +	    The ID of the parent that the working directory was
 22.1909 +	    updated to.  If the working directory was merged, it will
 22.1910 +	    not have changed this parent.
 22.1911 +	  </para>
 22.1912 +	</listitem>
 22.1913 +	<listitem><para id="x_2e6"><literal>parent2</literal>: A changeset ID.
 22.1914 +	    Only set if the working directory was merged.  The ID of
 22.1915 +	    the revision that the working directory was merged with.
 22.1916 +	  </para>
 22.1917 +	</listitem></itemizedlist>
 22.1918 +
 22.1919 +      <para id="x_2e7">See also: <literal role="hook">preupdate</literal>
 22.1920 +	(<xref linkend="sec:hook:preupdate"/>)
 22.1921 +      </para>
 22.1922 +
 22.1923 +    </sect2>
 22.1924 +  </sect1>
 22.1925 +</chapter>
 22.1926 +
 22.1927 +<!--
 22.1928 +local variables: 
 22.1929 +sgml-parent-document: ("00book.xml" "book" "chapter")
 22.1930 +end:
 22.1931 +-->
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/fr/ch11-template.xml	Sat Jul 10 06:24:49 2010 +0100
    23.3 @@ -0,0 +1,685 @@
    23.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
    23.5 +
    23.6 +<chapter id="chap:template">
    23.7 +  <?dbhtml filename="customizing-the-output-of-mercurial.html"?>
    23.8 +  <title>Customizing the output of Mercurial</title>
    23.9 +
   23.10 +  <para id="x_578">Mercurial provides a powerful mechanism to let you control how
   23.11 +    it displays information.  The mechanism is based on templates.
   23.12 +    You can use templates to generate specific output for a single
   23.13 +    command, or to customize the entire appearance of the built-in web
   23.14 +    interface.</para>
   23.15 +
   23.16 +  <sect1 id="sec:style">
   23.17 +    <title>Using precanned output styles</title>
   23.18 +
   23.19 +    <para id="x_579">Packaged with Mercurial are some output styles that you can
   23.20 +      use immediately.  A style is simply a precanned template that
   23.21 +      someone wrote and installed somewhere that Mercurial can
   23.22 +      find.</para>
   23.23 +
   23.24 +    <para id="x_57a">Before we take a look at Mercurial's bundled styles, let's
   23.25 +      review its normal output.</para>
   23.26 +
   23.27 +    &interaction.template.simple.normal;
   23.28 +
   23.29 +    <para id="x_57b">This is somewhat informative, but it takes up a lot of
   23.30 +      space&emdash;five lines of output per changeset.  The
   23.31 +      <literal>compact</literal> style reduces this to three lines,
   23.32 +      presented in a sparse manner.</para>
   23.33 +
   23.34 +    &interaction.template.simple.compact;
   23.35 +
   23.36 +    <para id="x_57c">The <literal>changelog</literal> style hints at the
   23.37 +      expressive power of Mercurial's templating engine.  This style
   23.38 +      attempts to follow the GNU Project's changelog
   23.39 +      guidelines<citation>web:changelog</citation>.</para>
   23.40 +
   23.41 +    &interaction.template.simple.changelog;
   23.42 +
   23.43 +    <para id="x_57d">You will not be shocked to learn that Mercurial's default
   23.44 +      output style is named <literal>default</literal>.</para>
   23.45 +
   23.46 +    <sect2>
   23.47 +      <title>Setting a default style</title>
   23.48 +
   23.49 +      <para id="x_57e">You can modify the output style that Mercurial will use
   23.50 +	for every command by editing your <filename
   23.51 +	  role="special">~/.hgrc</filename> file, naming the style
   23.52 +	you would prefer to use.</para>
   23.53 +
   23.54 +      <programlisting>[ui]
   23.55 +style = compact</programlisting>
   23.56 +
   23.57 +      <para id="x_57f">If you write a style of your own, you can use it by either
   23.58 +	providing the path to your style file, or copying your style
   23.59 +	file into a location where Mercurial can find it (typically
   23.60 +	the <literal>templates</literal> subdirectory of your
   23.61 +	Mercurial install directory).</para>
   23.62 +    </sect2>
   23.63 +  </sect1>
   23.64 +
   23.65 +  <sect1>
   23.66 +    <title>Commands that support styles and templates</title>
   23.67 +
   23.68 +    <para id="x_580">All of Mercurial's
   23.69 +      <quote><literal>log</literal>-like</quote> commands let you use
   23.70 +      styles and templates: <command role="hg-cmd">hg
   23.71 +	incoming</command>, <command role="hg-cmd">hg log</command>,
   23.72 +      <command role="hg-cmd">hg outgoing</command>, and <command
   23.73 +	role="hg-cmd">hg tip</command>.</para>
   23.74 +
   23.75 +    <para id="x_581">As I write this manual, these are so far the only commands
   23.76 +      that support styles and templates.  Since these are the most
   23.77 +      important commands that need customizable output, there has been
   23.78 +      little pressure from the Mercurial user community to add style
   23.79 +      and template support to other commands.</para>
   23.80 +  </sect1>
   23.81 +
   23.82 +  <sect1>
   23.83 +    <title>The basics of templating</title>
   23.84 +
   23.85 +    <para id="x_582">At its simplest, a Mercurial template is a piece of text.
   23.86 +      Some of the text never changes, while other parts are
   23.87 +      <emphasis>expanded</emphasis>, or replaced with new text, when
   23.88 +      necessary.</para>
   23.89 +
   23.90 +    <para id="x_583">Before we continue, let's look again at a simple example of
   23.91 +      Mercurial's normal output.</para>
   23.92 +
   23.93 +    &interaction.template.simple.normal;
   23.94 +
   23.95 +    <para id="x_584">Now, let's run the same command, but using a template to
   23.96 +      change its output.</para>
   23.97 +
   23.98 +    &interaction.template.simple.simplest;
   23.99 +
  23.100 +    <para id="x_585">The example above illustrates the simplest possible
  23.101 +      template; it's just a piece of static text, printed once for
  23.102 +      each changeset.  The <option
  23.103 +	role="hg-opt-log">--template</option> option to the <command
  23.104 +	role="hg-cmd">hg log</command> command tells Mercurial to use
  23.105 +      the given text as the template when printing each
  23.106 +      changeset.</para>
  23.107 +
  23.108 +    <para id="x_586">Notice that the template string above ends with the text
  23.109 +      <quote><literal>\n</literal></quote>.  This is an
  23.110 +      <emphasis>escape sequence</emphasis>, telling Mercurial to print
  23.111 +      a newline at the end of each template item.  If you omit this
  23.112 +      newline, Mercurial will run each piece of output together.  See
  23.113 +      <xref linkend="sec:template:escape"/> for more details
  23.114 +      of escape sequences.</para>
  23.115 +
  23.116 +    <para id="x_587">A template that prints a fixed string of text all the time
  23.117 +      isn't very useful; let's try something a bit more
  23.118 +      complex.</para>
  23.119 +
  23.120 +    &interaction.template.simple.simplesub;
  23.121 +
  23.122 +    <para id="x_588">As you can see, the string
  23.123 +      <quote><literal>{desc}</literal></quote> in the template has
  23.124 +      been replaced in the output with the description of each
  23.125 +      changeset.  Every time Mercurial finds text enclosed in curly
  23.126 +      braces (<quote><literal>{</literal></quote> and
  23.127 +      <quote><literal>}</literal></quote>), it will try to replace the
  23.128 +      braces and text with the expansion of whatever is inside.  To
  23.129 +      print a literal curly brace, you must escape it, as described in
  23.130 +      <xref linkend="sec:template:escape"/>.</para>
  23.131 +  </sect1>
  23.132 +
  23.133 +  <sect1 id="sec:template:keyword">
  23.134 +    <title>Common template keywords</title>
  23.135 +
  23.136 +    <para id="x_589">You can start writing simple templates immediately using the
  23.137 +      keywords below.</para>
  23.138 +
  23.139 +    <itemizedlist>
  23.140 +      <listitem><para id="x_58a"><literal
  23.141 +	    role="template-keyword">author</literal>: String.  The
  23.142 +	  unmodified author of the changeset.</para>
  23.143 +      </listitem>
  23.144 +      <listitem><para id="x_58b"><literal
  23.145 +	    role="template-keyword">branches</literal>: String.  The
  23.146 +	  name of the branch on which the changeset was committed.
  23.147 +	  Will be empty if the branch name was
  23.148 +	  <literal>default</literal>.</para>
  23.149 +      </listitem>
  23.150 +      <listitem><para id="x_58c"><literal role="template-keyword">date</literal>:
  23.151 +	  Date information.  The date when the changeset was
  23.152 +	  committed.  This is <emphasis>not</emphasis> human-readable;
  23.153 +	  you must pass it through a filter that will render it
  23.154 +	  appropriately.  See <xref
  23.155 +	    linkend="sec:template:filter"/> for more information
  23.156 +	  on filters. The date is expressed as a pair of numbers.  The
  23.157 +	  first number is a Unix UTC timestamp (seconds since January
  23.158 +	  1, 1970); the second is the offset of the committer's
  23.159 +	  timezone from UTC, in seconds.</para>
  23.160 +      </listitem>
  23.161 +      <listitem><para id="x_58d"><literal role="template-keyword">desc</literal>:
  23.162 +	  String.  The text of the changeset description.</para>
  23.163 +      </listitem>
  23.164 +      <listitem><para id="x_58e"><literal
  23.165 +	    role="template-keyword">files</literal>: List of strings.
  23.166 +	  All files modified, added, or removed by this
  23.167 +	  changeset.</para>
  23.168 +      </listitem>
  23.169 +      <listitem><para id="x_58f"><literal
  23.170 +	    role="template-keyword">file_adds</literal>: List of
  23.171 +	  strings.  Files added by this changeset.</para>
  23.172 +      </listitem>
  23.173 +      <listitem><para id="x_590"><literal
  23.174 +	    role="template-keyword">file_dels</literal>: List of
  23.175 +	  strings.  Files removed by this changeset.</para>
  23.176 +      </listitem>
  23.177 +      <listitem><para id="x_591"><literal role="template-keyword">node</literal>:
  23.178 +	  String.  The changeset identification hash, as a
  23.179 +	  40-character hexadecimal string.</para>
  23.180 +      </listitem>
  23.181 +      <listitem><para id="x_592"><literal
  23.182 +	    role="template-keyword">parents</literal>: List of
  23.183 +	  strings.  The parents of the changeset.</para>
  23.184 +      </listitem>
  23.185 +      <listitem><para id="x_593"><literal role="template-keyword">rev</literal>:
  23.186 +	  Integer.  The repository-local changeset revision
  23.187 +	  number.</para>
  23.188 +      </listitem>
  23.189 +      <listitem><para id="x_594"><literal role="template-keyword">tags</literal>:
  23.190 +	  List of strings.  Any tags associated with the
  23.191 +	  changeset.</para>
  23.192 +      </listitem>
  23.193 +    </itemizedlist>
  23.194 +
  23.195 +    <para id="x_595">A few simple experiments will show us what to expect when we
  23.196 +      use these keywords; you can see the results below.</para>
  23.197 +
  23.198 +    &interaction.template.simple.keywords;
  23.199 +
  23.200 +    <para id="x_596">As we noted above, the date keyword does not produce
  23.201 +      human-readable output, so we must treat it specially.  This
  23.202 +      involves using a <emphasis>filter</emphasis>, about which more
  23.203 +      in <xref linkend="sec:template:filter"/>.</para>
  23.204 +
  23.205 +    &interaction.template.simple.datekeyword;
  23.206 +  </sect1>
  23.207 +
  23.208 +  <sect1 id="sec:template:escape">
  23.209 +    <title>Escape sequences</title>
  23.210 +
  23.211 +    <para id="x_597">Mercurial's templating engine recognises the most commonly
  23.212 +      used escape sequences in strings.  When it sees a backslash
  23.213 +      (<quote><literal>\</literal></quote>) character, it looks at the
  23.214 +      following character and substitutes the two characters with a
  23.215 +      single replacement, as described below.</para>
  23.216 +
  23.217 +    <itemizedlist>
  23.218 +      <listitem><para id="x_598"><literal>\</literal>:
  23.219 +	  Backslash, <quote><literal>\</literal></quote>, ASCII
  23.220 +	  134.</para>
  23.221 +      </listitem>
  23.222 +      <listitem><para id="x_599"><literal>\n</literal>: Newline,
  23.223 +	  ASCII 12.</para>
  23.224 +      </listitem>
  23.225 +      <listitem><para id="x_59a"><literal>\r</literal>: Carriage
  23.226 +	  return, ASCII 15.</para>
  23.227 +      </listitem>
  23.228 +      <listitem><para id="x_59b"><literal>\t</literal>: Tab, ASCII
  23.229 +	  11.</para>
  23.230 +      </listitem>
  23.231 +      <listitem><para id="x_59c"><literal>\v</literal>: Vertical
  23.232 +	  tab, ASCII 13.</para>
  23.233 +      </listitem>
  23.234 +      <listitem><para id="x_59d"><literal>\{</literal>: Open curly
  23.235 +	  brace, <quote><literal>{</literal></quote>, ASCII
  23.236 +	  173.</para>
  23.237 +      </listitem>
  23.238 +      <listitem><para id="x_59e"><literal>\}</literal>: Close curly
  23.239 +	  brace, <quote><literal>}</literal></quote>, ASCII
  23.240 +	  175.</para>
  23.241 +      </listitem></itemizedlist>
  23.242 +
  23.243 +    <para id="x_59f">As indicated above, if you want the expansion of a template
  23.244 +      to contain a literal <quote><literal>\</literal></quote>,
  23.245 +      <quote><literal>{</literal></quote>, or
  23.246 +      <quote><literal>{</literal></quote> character, you must escape
  23.247 +      it.</para>
  23.248 +  </sect1>
  23.249 +
  23.250 +  <sect1 id="sec:template:filter">
  23.251 +    <title>Filtering keywords to change their results</title>
  23.252 +
  23.253 +    <para id="x_5a0">Some of the results of template expansion are not
  23.254 +      immediately easy to use.  Mercurial lets you specify an optional
  23.255 +      chain of <emphasis>filters</emphasis> to modify the result of
  23.256 +      expanding a keyword.  You have already seen a common filter,
  23.257 +      <literal role="template-kw-filt-date">isodate</literal>, in
  23.258 +      action above, to make a date readable.</para>
  23.259 +
  23.260 +    <para id="x_5a1">Below is a list of the most commonly used filters that
  23.261 +      Mercurial supports.  While some filters can be applied to any
  23.262 +      text, others can only be used in specific circumstances.  The
  23.263 +      name of each filter is followed first by an indication of where
  23.264 +      it can be used, then a description of its effect.</para>
  23.265 +
  23.266 +    <itemizedlist>
  23.267 +      <listitem><para id="x_5a2"><literal
  23.268 +	    role="template-filter">addbreaks</literal>: Any text. Add
  23.269 +	  an XHTML <quote><literal>&lt;br/&gt;</literal></quote> tag
  23.270 +	  before the end of every line except the last.  For example,
  23.271 +	  <quote><literal>foo\nbar</literal></quote> becomes
  23.272 +	  <quote><literal>foo&lt;br/&gt;\nbar</literal></quote>.</para>
  23.273 +      </listitem>
  23.274 +      <listitem><para id="x_5a3"><literal
  23.275 +	    role="template-kw-filt-date">age</literal>: <literal
  23.276 +	    role="template-keyword">date</literal> keyword.  Render
  23.277 +	  the age of the date, relative to the current time.  Yields a
  23.278 +	  string like <quote><literal>10
  23.279 +	      minutes</literal></quote>.</para>
  23.280 +      </listitem>
  23.281 +      <listitem><para id="x_5a4"><literal
  23.282 +	    role="template-filter">basename</literal>: Any text, but
  23.283 +	  most useful for the <literal
  23.284 +	    role="template-keyword">files</literal> keyword and its
  23.285 +	  relatives.  Treat the text as a path, and return the
  23.286 +	  basename. For example,
  23.287 +	  <quote><literal>foo/bar/baz</literal></quote> becomes
  23.288 +	  <quote><literal>baz</literal></quote>.</para>
  23.289 +      </listitem>
  23.290 +      <listitem><para id="x_5a5"><literal
  23.291 +	    role="template-kw-filt-date">date</literal>: <literal
  23.292 +	    role="template-keyword">date</literal> keyword.  Render a
  23.293 +	  date in a similar format to the Unix <literal
  23.294 +	    role="template-keyword">date</literal> command, but with
  23.295 +	  timezone included.  Yields a string like <quote><literal>Mon
  23.296 +	      Sep 04 15:13:13 2006 -0700</literal></quote>.</para>
  23.297 +      </listitem>
  23.298 +      <listitem><para id="x_5a6"><literal
  23.299 +	    role="template-kw-filt-author">domain</literal>: Any text,
  23.300 +	  but most useful for the <literal
  23.301 +	    role="template-keyword">author</literal> keyword.  Finds
  23.302 +	  the first string that looks like an email address, and
  23.303 +	  extract just the domain component.  For example,
  23.304 +	  <quote><literal>Bryan O'Sullivan
  23.305 +	      &lt;bos@serpentine.com&gt;</literal></quote> becomes
  23.306 +	  <quote><literal>serpentine.com</literal></quote>.</para>
  23.307 +      </listitem>
  23.308 +      <listitem><para id="x_5a7"><literal
  23.309 +	    role="template-kw-filt-author">email</literal>: Any text,
  23.310 +	  but most useful for the <literal
  23.311 +	    role="template-keyword">author</literal> keyword.  Extract
  23.312 +	  the first string that looks like an email address.  For
  23.313 +	  example, <quote><literal>Bryan O'Sullivan
  23.314 +	      &lt;bos@serpentine.com&gt;</literal></quote> becomes
  23.315 +	  <quote><literal>bos@serpentine.com</literal></quote>.</para>
  23.316 +      </listitem>
  23.317 +      <listitem><para id="x_5a8"><literal
  23.318 +	    role="template-filter">escape</literal>: Any text.
  23.319 +	  Replace the special XML/XHTML characters
  23.320 +	  <quote><literal>&amp;</literal></quote>,
  23.321 +	  <quote><literal>&lt;</literal></quote> and
  23.322 +	  <quote><literal>&gt;</literal></quote> with XML
  23.323 +	  entities.</para>
  23.324 +      </listitem>
  23.325 +      <listitem><para id="x_5a9"><literal
  23.326 +	    role="template-filter">fill68</literal>: Any text.  Wrap
  23.327 +	  the text to fit in 68 columns.  This is useful before you
  23.328 +	  pass text through the <literal
  23.329 +	    role="template-filter">tabindent</literal> filter, and
  23.330 +	  still want it to fit in an 80-column fixed-font
  23.331 +	  window.</para>
  23.332 +      </listitem>
  23.333 +      <listitem><para id="x_5aa"><literal
  23.334 +	    role="template-filter">fill76</literal>: Any text.  Wrap
  23.335 +	  the text to fit in 76 columns.</para>
  23.336 +      </listitem>
  23.337 +      <listitem><para id="x_5ab"><literal
  23.338 +	    role="template-filter">firstline</literal>: Any text.
  23.339 +	  Yield the first line of text, without any trailing
  23.340 +	  newlines.</para>
  23.341 +      </listitem>
  23.342 +      <listitem><para id="x_5ac"><literal
  23.343 +	    role="template-kw-filt-date">hgdate</literal>: <literal
  23.344 +	    role="template-keyword">date</literal> keyword.  Render
  23.345 +	  the date as a pair of readable numbers.  Yields a string
  23.346 +	  like <quote><literal>1157407993
  23.347 +	      25200</literal></quote>.</para>
  23.348 +      </listitem>
  23.349 +      <listitem><para id="x_5ad"><literal
  23.350 +	    role="template-kw-filt-date">isodate</literal>: <literal
  23.351 +	    role="template-keyword">date</literal> keyword.  Render
  23.352 +	  the date as a text string in ISO 8601 format.  Yields a
  23.353 +	  string like <quote><literal>2006-09-04 15:13:13
  23.354 +	      -0700</literal></quote>.</para>
  23.355 +      </listitem>
  23.356 +      <listitem><para id="x_5ae"><literal
  23.357 +	    role="template-filter">obfuscate</literal>: Any text, but
  23.358 +	  most useful for the <literal
  23.359 +	    role="template-keyword">author</literal> keyword.  Yield
  23.360 +	  the input text rendered as a sequence of XML entities.  This
  23.361 +	  helps to defeat some particularly stupid screen-scraping
  23.362 +	  email harvesting spambots.</para>
  23.363 +      </listitem>
  23.364 +      <listitem><para id="x_5af"><literal
  23.365 +	    role="template-kw-filt-author">person</literal>: Any text,
  23.366 +	  but most useful for the <literal
  23.367 +	    role="template-keyword">author</literal> keyword.  Yield
  23.368 +	  the text before an email address. For example,
  23.369 +	  <quote><literal>Bryan O'Sullivan
  23.370 +	      &lt;bos@serpentine.com&gt;</literal></quote> becomes
  23.371 +	  <quote><literal>Bryan O'Sullivan</literal></quote>.</para>
  23.372 +      </listitem>
  23.373 +      <listitem><para id="x_5b0"><literal
  23.374 +	    role="template-kw-filt-date">rfc822date</literal>:
  23.375 +	  <literal role="template-keyword">date</literal> keyword.
  23.376 +	  Render a date using the same format used in email headers.
  23.377 +	  Yields a string like <quote><literal>Mon, 04 Sep 2006
  23.378 +	      15:13:13 -0700</literal></quote>.</para>
  23.379 +      </listitem>
  23.380 +      <listitem><para id="x_5b1"><literal
  23.381 +	    role="template-kw-filt-node">short</literal>: Changeset
  23.382 +	  hash.  Yield the short form of a changeset hash, i.e. a
  23.383 +	  12-character hexadecimal string.</para>
  23.384 +      </listitem>
  23.385 +      <listitem><para id="x_5b2"><literal
  23.386 +	    role="template-kw-filt-date">shortdate</literal>: <literal
  23.387 +	    role="template-keyword">date</literal> keyword.  Render
  23.388 +	  the year, month, and day of the date.  Yields a string like
  23.389 +	  <quote><literal>2006-09-04</literal></quote>.</para>
  23.390 +      </listitem>
  23.391 +      <listitem><para id="x_5b3"><literal role="template-filter">strip</literal>:
  23.392 +	  Any text.  Strip all leading and trailing whitespace from
  23.393 +	  the string.</para>
  23.394 +      </listitem>
  23.395 +      <listitem><para id="x_5b4"><literal
  23.396 +	    role="template-filter">tabindent</literal>: Any text.
  23.397 +	  Yield the text, with every line except the first starting
  23.398 +	  with a tab character.</para>
  23.399 +      </listitem>
  23.400 +      <listitem><para id="x_5b5"><literal
  23.401 +	    role="template-filter">urlescape</literal>: Any text.
  23.402 +	  Escape all characters that are considered
  23.403 +	  <quote>special</quote> by URL parsers.  For example,
  23.404 +	  <literal>foo bar</literal> becomes
  23.405 +	  <literal>foo%20bar</literal>.</para>
  23.406 +      </listitem>
  23.407 +      <listitem><para id="x_5b6"><literal
  23.408 +	    role="template-kw-filt-author">user</literal>: Any text,
  23.409 +	  but most useful for the <literal
  23.410 +	    role="template-keyword">author</literal> keyword.  Return
  23.411 +	  the <quote>user</quote> portion of an email address.  For
  23.412 +	  example, <quote><literal>Bryan O'Sullivan
  23.413 +	      &lt;bos@serpentine.com&gt;</literal></quote> becomes
  23.414 +	  <quote><literal>bos</literal></quote>.</para>
  23.415 +      </listitem>
  23.416 +    </itemizedlist>
  23.417 +
  23.418 +    &interaction.template.simple.manyfilters;
  23.419 +
  23.420 +    <note>
  23.421 +      <para id="x_5b7">  If you try to apply a filter to a piece of data that it
  23.422 +	cannot process, Mercurial will fail and print a Python
  23.423 +	exception.  For example, trying to run the output of the
  23.424 +	<literal role="template-keyword">desc</literal> keyword into
  23.425 +	the <literal role="template-kw-filt-date">isodate</literal>
  23.426 +	filter is not a good idea.</para>
  23.427 +    </note>
  23.428 +
  23.429 +    <sect2>
  23.430 +      <title>Combining filters</title>
  23.431 +
  23.432 +      <para id="x_5b8">It is easy to combine filters to yield output in the form
  23.433 +	you would like.  The following chain of filters tidies up a
  23.434 +	description, then makes sure that it fits cleanly into 68
  23.435 +	columns, then indents it by a further 8 characters (at least
  23.436 +	on Unix-like systems, where a tab is conventionally 8
  23.437 +	characters wide).</para>
  23.438 +
  23.439 +      &interaction.template.simple.combine;
  23.440 +
  23.441 +      <para id="x_5b9">Note the use of <quote><literal>\t</literal></quote> (a
  23.442 +	tab character) in the template to force the first line to be
  23.443 +	indented; this is necessary since <literal
  23.444 +	  role="template-keyword">tabindent</literal> indents all
  23.445 +	lines <emphasis>except</emphasis> the first.</para>
  23.446 +
  23.447 +      <para id="x_5ba">Keep in mind that the order of filters in a chain is
  23.448 +	significant.  The first filter is applied to the result of the
  23.449 +	keyword; the second to the result of the first filter; and so
  23.450 +	on.  For example, using <literal>fill68|tabindent</literal>
  23.451 +	gives very different results from
  23.452 +	<literal>tabindent|fill68</literal>.</para>
  23.453 +    </sect2>
  23.454 +  </sect1>
  23.455 +
  23.456 +  <sect1>
  23.457 +    <title>From templates to styles</title>
  23.458 +
  23.459 +    <para id="x_5bb">A command line template provides a quick and simple way to
  23.460 +      format some output.  Templates can become verbose, though, and
  23.461 +      it's useful to be able to give a template a name.  A style file
  23.462 +      is a template with a name, stored in a file.</para>
  23.463 +
  23.464 +    <para id="x_5bc">More than that, using a style file unlocks the power of
  23.465 +      Mercurial's templating engine in ways that are not possible
  23.466 +      using the command line <option
  23.467 +	role="hg-opt-log">--template</option> option.</para>
  23.468 +
  23.469 +    <sect2>
  23.470 +      <title>The simplest of style files</title>
  23.471 +
  23.472 +      <para id="x_5bd">Our simple style file contains just one line:</para>
  23.473 +
  23.474 +      &interaction.template.simple.rev;
  23.475 +
  23.476 +      <para id="x_5be">This tells Mercurial, <quote>if you're printing a
  23.477 +	  changeset, use the text on the right as the
  23.478 +	  template</quote>.</para>
  23.479 +    </sect2>
  23.480 +
  23.481 +    <sect2>
  23.482 +      <title>Style file syntax</title>
  23.483 +
  23.484 +      <para id="x_5bf">The syntax rules for a style file are simple.</para>
  23.485 +
  23.486 +      <itemizedlist>
  23.487 +	<listitem><para id="x_5c0">The file is processed one line at a
  23.488 +	    time.</para>
  23.489 +	</listitem>
  23.490 +	<listitem><para id="x_5c1">Leading and trailing white space are
  23.491 +	    ignored.</para>
  23.492 +	</listitem>
  23.493 +	<listitem><para id="x_5c2">Empty lines are skipped.</para>
  23.494 +	</listitem>
  23.495 +	<listitem><para id="x_5c3">If a line starts with either of the characters
  23.496 +	    <quote><literal>#</literal></quote> or
  23.497 +	    <quote><literal>;</literal></quote>, the entire line is
  23.498 +	    treated as a comment, and skipped as if empty.</para>
  23.499 +	</listitem>
  23.500 +	<listitem><para id="x_5c4">A line starts with a keyword.  This must start
  23.501 +	    with an alphabetic character or underscore, and can
  23.502 +	    subsequently contain any alphanumeric character or
  23.503 +	    underscore.  (In regexp notation, a keyword must match
  23.504 +	    <literal>[A-Za-z_][A-Za-z0-9_]*</literal>.)</para>
  23.505 +	</listitem>
  23.506 +	<listitem><para id="x_5c5">The next element must be an
  23.507 +	    <quote><literal>=</literal></quote> character, which can
  23.508 +	    be preceded or followed by an arbitrary amount of white
  23.509 +	    space.</para>
  23.510 +	</listitem>
  23.511 +	<listitem><para id="x_5c6">If the rest of the line starts and ends with
  23.512 +	    matching quote characters (either single or double quote),
  23.513 +	    it is treated as a template body.</para>
  23.514 +	</listitem>
  23.515 +	<listitem><para id="x_5c7">If the rest of the line <emphasis>does
  23.516 +	      not</emphasis> start with a quote character, it is
  23.517 +	    treated as the name of a file; the contents of this file
  23.518 +	    will be read and used as a template body.</para>
  23.519 +	</listitem></itemizedlist>
  23.520 +    </sect2>
  23.521 +  </sect1>
  23.522 +
  23.523 +  <sect1>
  23.524 +    <title>Style files by example</title>
  23.525 +
  23.526 +    <para id="x_5c8">To illustrate how to write a style file, we will construct a
  23.527 +      few by example.  Rather than provide a complete style file and
  23.528 +      walk through it, we'll mirror the usual process of developing a
  23.529 +      style file by starting with something very simple, and walking
  23.530 +      through a series of successively more complete examples.</para>
  23.531 +
  23.532 +    <sect2>
  23.533 +      <title>Identifying mistakes in style files</title>
  23.534 +
  23.535 +      <para id="x_5c9">If Mercurial encounters a problem in a style file you are
  23.536 +	working on, it prints a terse error message that, once you
  23.537 +	figure out what it means, is actually quite useful.</para>
  23.538 +
  23.539 +&interaction.template.svnstyle.syntax.input;
  23.540 +
  23.541 +      <para id="x_5ca">Notice that <filename>broken.style</filename> attempts to
  23.542 +	define a <literal>changeset</literal> keyword, but forgets to
  23.543 +	give any content for it. When instructed to use this style
  23.544 +	file, Mercurial promptly complains.</para>
  23.545 +
  23.546 +      &interaction.template.svnstyle.syntax.error;
  23.547 +
  23.548 +      <para id="x_5cb">This error message looks intimidating, but it is not too
  23.549 +	hard to follow.</para>
  23.550 +
  23.551 +      <itemizedlist>
  23.552 +	<listitem><para id="x_5cc">The first component is simply Mercurial's way
  23.553 +	    of saying <quote>I am giving up</quote>.</para>
  23.554 +	  <programlisting>___abort___: broken.style:1: parse error</programlisting>
  23.555 +	</listitem>
  23.556 +	<listitem><para id="x_5cd">Next comes the name of the style file that
  23.557 +	    contains the error.</para>
  23.558 +	  <programlisting>abort: ___broken.style___:1: parse error</programlisting>
  23.559 +	</listitem>
  23.560 +	<listitem><para id="x_5ce">Following the file name is the line number
  23.561 +	    where the error was encountered.</para>
  23.562 +	  <programlisting>abort: broken.style:___1___: parse error</programlisting>
  23.563 +	</listitem>
  23.564 +	<listitem><para id="x_5cf">Finally, a description of what went
  23.565 +	    wrong.</para>
  23.566 +	  <programlisting>abort: broken.style:1: ___parse error___</programlisting>
  23.567 +	</listitem>
  23.568 +	<listitem><para id="x_5d0">The description of the problem is not always
  23.569 +	    clear (as in this case), but even when it is cryptic, it
  23.570 +	    is almost always trivial to visually inspect the offending
  23.571 +	    line in the style file and see what is wrong.</para>
  23.572 +	</listitem>
  23.573 +      </itemizedlist>
  23.574 +    </sect2>
  23.575 +
  23.576 +    <sect2>
  23.577 +      <title>Uniquely identifying a repository</title>
  23.578 +
  23.579 +      <para id="x_5d1">If you would like to be able to identify a Mercurial
  23.580 +	repository <quote>fairly uniquely</quote> using a short string
  23.581 +	as an identifier, you can use the first revision in the
  23.582 +	repository.</para>
  23.583 +
  23.584 +      &interaction.template.svnstyle.id;
  23.585 +
  23.586 +      <para id="x_5d2">This is likely to be unique, and so it is
  23.587 +	useful in many cases.  There are a few caveats.</para>
  23.588 +      <itemizedlist>
  23.589 +	<listitem><para id="x_5d3">It will not work in a completely empty
  23.590 +	    repository, because such a repository does not have a
  23.591 +	    revision zero.</para>
  23.592 +	</listitem>
  23.593 +	<listitem><para id="x_5d4">Neither will it work in the (extremely rare)
  23.594 +	    case where a repository is a merge of two or more formerly
  23.595 +	    independent repositories, and you still have those
  23.596 +	    repositories around.</para>
  23.597 +	</listitem></itemizedlist>
  23.598 +      <para id="x_5d5">Here are some uses to which you could put this
  23.599 +	identifier:</para>
  23.600 +      <itemizedlist>
  23.601 +	<listitem><para id="x_5d6">As a key into a table for a database that
  23.602 +	    manages repositories on a server.</para>
  23.603 +	</listitem>
  23.604 +	<listitem><para id="x_5d7">As half of a {<emphasis>repository
  23.605 +	      ID</emphasis>, <emphasis>revision ID</emphasis>} tuple.
  23.606 +	    Save this information away when you run an automated build
  23.607 +	    or other activity, so that you can <quote>replay</quote>
  23.608 +	    the build later if necessary.</para>
  23.609 +	</listitem>
  23.610 +      </itemizedlist>
  23.611 +    </sect2>
  23.612 +
  23.613 +    <sect2>
  23.614 +      <title>Listing files on multiple lines</title>
  23.615 +
  23.616 +      <para id="x_714">Suppose we want to list the files changed by a changeset,
  23.617 +	one per line, with a little indentation before each file
  23.618 +	name.</para>
  23.619 +
  23.620 +      &interaction.ch10-multiline.go;
  23.621 +    </sect2>
  23.622 +
  23.623 +    <sect2>
  23.624 +      <title>Mimicking Subversion's output</title>
  23.625 +
  23.626 +      <para id="x_5d8">Let's try to emulate the default output format used by
  23.627 +	another revision control tool, Subversion.</para>
  23.628 +
  23.629 +      &interaction.template.svnstyle.short;
  23.630 +
  23.631 +      <para id="x_5d9">Since Subversion's output style is fairly simple, it is
  23.632 +	easy to copy-and-paste a hunk of its output into a file, and
  23.633 +	replace the text produced above by Subversion with the
  23.634 +	template values we'd like to see expanded.</para>
  23.635 +
  23.636 +      &interaction.template.svnstyle.template;
  23.637 +
  23.638 +      <para id="x_5da">There are a few small ways in which this template deviates
  23.639 +	from the output produced by Subversion.</para>
  23.640 +      <itemizedlist>
  23.641 +	<listitem><para id="x_5db">Subversion prints a <quote>readable</quote>
  23.642 +	    date (the <quote><literal>Wed, 27 Sep 2006</literal></quote> in the
  23.643 +	    example output above) in parentheses.  Mercurial's
  23.644 +	    templating engine does not provide a way to display a date
  23.645 +	    in this format without also printing the time and time
  23.646 +	    zone.</para>
  23.647 +	</listitem>
  23.648 +	<listitem><para id="x_5dc">We emulate Subversion's printing of
  23.649 +	    <quote>separator</quote> lines full of
  23.650 +	    <quote><literal>-</literal></quote> characters by ending
  23.651 +	    the template with such a line. We use the templating
  23.652 +	    engine's <literal role="template-keyword">header</literal>
  23.653 +	    keyword to print a separator line as the first line of
  23.654 +	    output (see below), thus achieving similar output to
  23.655 +	    Subversion.</para>
  23.656 +	</listitem>
  23.657 +	<listitem><para id="x_5dd">Subversion's output includes a count in the
  23.658 +	    header of the number of lines in the commit message.  We
  23.659 +	    cannot replicate this in Mercurial; the templating engine
  23.660 +	    does not currently provide a filter that counts the number
  23.661 +	    of lines the template generates.</para>
  23.662 +	</listitem></itemizedlist>
  23.663 +      <para id="x_5de">It took me no more than a minute or two of work to replace
  23.664 +	literal text from an example of Subversion's output with some
  23.665 +	keywords and filters to give the template above.  The style
  23.666 +	file simply refers to the template.</para>
  23.667 +
  23.668 +      &interaction.template.svnstyle.style;
  23.669 +
  23.670 +      <para id="x_5df">We could have included the text of the template file
  23.671 +	directly in the style file by enclosing it in quotes and
  23.672 +	replacing the newlines with
  23.673 +	<quote><literal>\n</literal></quote> sequences, but it would
  23.674 +	have made the style file too difficult to read.  Readability
  23.675 +	is a good guide when you're trying to decide whether some text
  23.676 +	belongs in a style file, or in a template file that the style
  23.677 +	file points to.  If the style file will look too big or
  23.678 +	cluttered if you insert a literal piece of text, drop it into
  23.679 +	a template instead.</para>
  23.680 +    </sect2>
  23.681 +  </sect1>
  23.682 +</chapter>
  23.683 +
  23.684 +<!--
  23.685 +local variables: 
  23.686 +sgml-parent-document: ("00book.xml" "book" "chapter")
  23.687 +end:
  23.688 +-->
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/fr/ch12-mq.xml	Sat Jul 10 06:24:49 2010 +0100
    24.3 @@ -0,0 +1,1368 @@
    24.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
    24.5 +
    24.6 +<chapter id="chap:mq">
    24.7 +  <?dbhtml filename="managing-change-with-mercurial-queues.html"?>
    24.8 +  <title>Managing change with Mercurial Queues</title>
    24.9 +
   24.10 +  <sect1 id="sec:mq:patch-mgmt">
   24.11 +    <title>The patch management problem</title>
   24.12 +
   24.13 +    <para id="x_3ac">Here is a common scenario: you need to install a software
   24.14 +      package from source, but you find a bug that you must fix in the
   24.15 +      source before you can start using the package.  You make your
   24.16 +      changes, forget about the package for a while, and a few months
   24.17 +      later you need to upgrade to a newer version of the package.  If
   24.18 +      the newer version of the package still has the bug, you must
   24.19 +      extract your fix from the older source tree and apply it against
   24.20 +      the newer version.  This is a tedious task, and it's easy to
   24.21 +      make mistakes.</para>
   24.22 +
   24.23 +    <para id="x_3ad">This is a simple case of the <quote>patch management</quote>
   24.24 +      problem.  You have an <quote>upstream</quote> source tree that
   24.25 +      you can't change; you need to make some local changes on top of
   24.26 +      the upstream tree; and you'd like to be able to keep those
   24.27 +      changes separate, so that you can apply them to newer versions
   24.28 +      of the upstream source.</para>
   24.29 +
   24.30 +    <para id="x_3ae">The patch management problem arises in many situations.
   24.31 +      Probably the most visible is that a user of an open source
   24.32 +      software project will contribute a bug fix or new feature to the
   24.33 +      project's maintainers in the form of a patch.</para>
   24.34 +
   24.35 +    <para id="x_3af">Distributors of operating systems that include open source
   24.36 +      software often need to make changes to the packages they
   24.37 +      distribute so that they will build properly in their
   24.38 +      environments.</para>
   24.39 +
   24.40 +    <para id="x_3b0">When you have few changes to maintain, it is easy to manage
   24.41 +      a single patch using the standard <command>diff</command> and
   24.42 +      <command>patch</command> programs (see <xref
   24.43 +	linkend="sec:mq:patch"/> for a discussion of these
   24.44 +      tools). Once the number of changes grows, it starts to make
   24.45 +      sense to maintain patches as discrete <quote>chunks of
   24.46 +	work,</quote> so that for example a single patch will contain
   24.47 +      only one bug fix (the patch might modify several files, but it's
   24.48 +      doing <quote>only one thing</quote>), and you may have a number
   24.49 +      of such patches for different bugs you need fixed and local
   24.50 +      changes you require.  In this situation, if you submit a bug fix
   24.51 +      patch to the upstream maintainers of a package and they include
   24.52 +      your fix in a subsequent release, you can simply drop that
   24.53 +      single patch when you're updating to the newer release.</para>
   24.54 +
   24.55 +    <para id="x_3b1">Maintaining a single patch against an upstream tree is a
   24.56 +      little tedious and error-prone, but not difficult.  However, the
   24.57 +      complexity of the problem grows rapidly as the number of patches
   24.58 +      you have to maintain increases.  With more than a tiny number of
   24.59 +      patches in hand, understanding which ones you have applied and
   24.60 +      maintaining them moves from messy to overwhelming.</para>
   24.61 +
   24.62 +    <para id="x_3b2">Fortunately, Mercurial includes a powerful extension,
   24.63 +      Mercurial Queues (or simply <quote>MQ</quote>), that massively
   24.64 +      simplifies the patch management problem.</para>
   24.65 +
   24.66 +  </sect1>
   24.67 +  <sect1 id="sec:mq:history">
   24.68 +    <title>The prehistory of Mercurial Queues</title>
   24.69 +
   24.70 +    <para id="x_3b3">During the late 1990s, several Linux kernel developers
   24.71 +      started to maintain <quote>patch series</quote> that modified
   24.72 +      the behavior of the Linux kernel.  Some of these series were
   24.73 +      focused on stability, some on feature coverage, and others were
   24.74 +      more speculative.</para>
   24.75 +
   24.76 +    <para id="x_3b4">The sizes of these patch series grew rapidly.  In 2002,
   24.77 +      Andrew Morton published some shell scripts he had been using to
   24.78 +      automate the task of managing his patch queues.  Andrew was
   24.79 +      successfully using these scripts to manage hundreds (sometimes
   24.80 +      thousands) of patches on top of the Linux kernel.</para>
   24.81 +
   24.82 +    <sect2 id="sec:mq:quilt">
   24.83 +      <title>A patchwork quilt</title>
   24.84 +
   24.85 +      <para id="x_3b5">In early 2003, Andreas Gruenbacher and Martin Quinson
   24.86 +	borrowed the approach of Andrew's scripts and published a tool
   24.87 +	called <quote>patchwork quilt</quote>
   24.88 +	<citation>web:quilt</citation>, or simply <quote>quilt</quote>
   24.89 +	(see <citation>gruenbacher:2005</citation> for a paper
   24.90 +	describing it).  Because quilt substantially automated patch
   24.91 +	management, it rapidly gained a large following among open
   24.92 +	source software developers.</para>
   24.93 +
   24.94 +      <para id="x_3b6">Quilt manages a <emphasis>stack of patches</emphasis> on
   24.95 +	top of a directory tree. To begin, you tell quilt to manage a
   24.96 +	directory tree, and tell it which files you want to manage; it
   24.97 +	stores away the names and contents of those files.  To fix a
   24.98 +	bug, you create a new patch (using a single command), edit the
   24.99 +	files you need to fix, then <quote>refresh</quote> the
  24.100 +	patch.</para>
  24.101 +
  24.102 +      <para id="x_3b7">The refresh step causes quilt to scan the directory tree;
  24.103 +	it updates the patch with all of the changes you have made.
  24.104 +	You can create another patch on top of the first, which will
  24.105 +	track the changes required to modify the tree from <quote>tree
  24.106 +	  with one patch applied</quote> to <quote>tree with two
  24.107 +	  patches applied</quote>.</para>
  24.108 +
  24.109 +      <para id="x_3b8">You can <emphasis>change</emphasis> which patches are
  24.110 +	applied to the tree.  If you <quote>pop</quote> a patch, the
  24.111 +	changes made by that patch will vanish from the directory
  24.112 +	tree.  Quilt remembers which patches you have popped, though,
  24.113 +	so you can <quote>push</quote> a popped patch again, and the
  24.114 +	directory tree will be restored to contain the modifications
  24.115 +	in the patch.  Most importantly, you can run the
  24.116 +	<quote>refresh</quote> command at any time, and the topmost
  24.117 +	applied patch will be updated.  This means that you can, at
  24.118 +	any time, change both which patches are applied and what
  24.119 +	modifications those patches make.</para>
  24.120 +
  24.121 +      <para id="x_3b9">Quilt knows nothing about revision control tools, so it
  24.122 +	works equally well on top of an unpacked tarball or a
  24.123 +	Subversion working copy.</para>
  24.124 +    </sect2>
  24.125 +
  24.126 +    <sect2 id="sec:mq:quilt-mq">
  24.127 +      <title>From patchwork quilt to Mercurial Queues</title>
  24.128 +
  24.129 +      <para id="x_3ba">In mid-2005, Chris Mason took the features of quilt and
  24.130 +	wrote an extension that he called Mercurial Queues, which
  24.131 +	added quilt-like behavior to Mercurial.</para>
  24.132 +
  24.133 +      <para id="x_3bb">The key difference between quilt and MQ is that quilt
  24.134 +	knows nothing about revision control systems, while MQ is
  24.135 +	<emphasis>integrated</emphasis> into Mercurial.  Each patch
  24.136 +	that you push is represented as a Mercurial changeset.  Pop a
  24.137 +	patch, and the changeset goes away.</para>
  24.138 +
  24.139 +      <para id="x_3bc">Because quilt does not care about revision control tools,
  24.140 +	it is still a tremendously useful piece of software to know
  24.141 +	about for situations where you cannot use Mercurial and
  24.142 +	MQ.</para>
  24.143 +
  24.144 +    </sect2>
  24.145 +  </sect1>
  24.146 +  <sect1>
  24.147 +    <title>The huge advantage of MQ</title>
  24.148 +
  24.149 +    <para id="x_3bd">I cannot overstate the value that MQ offers through the
  24.150 +      unification of patches and revision control.</para>
  24.151 +
  24.152 +    <para id="x_3be">A major reason that patches have persisted in the free
  24.153 +      software and open source world&emdash;in spite of the
  24.154 +      availability of increasingly capable revision control tools over
  24.155 +      the years&emdash;is the <emphasis>agility</emphasis> they
  24.156 +      offer.</para>
  24.157 +
  24.158 +    <para id="x_3bf">Traditional revision control tools make a permanent,
  24.159 +      irreversible record of everything that you do.  While this has
  24.160 +      great value, it's also somewhat stifling.  If you want to
  24.161 +      perform a wild-eyed experiment, you have to be careful in how
  24.162 +      you go about it, or you risk leaving unneeded&emdash;or worse,
  24.163 +      misleading or destabilising&emdash;traces of your missteps and
  24.164 +      errors in the permanent revision record.</para>
  24.165 +
  24.166 +    <para id="x_3c0">By contrast, MQ's marriage of distributed revision control
  24.167 +      with patches makes it much easier to isolate your work.  Your
  24.168 +      patches live on top of normal revision history, and you can make
  24.169 +      them disappear or reappear at will.  If you don't like a patch,
  24.170 +      you can drop it.  If a patch isn't quite as you want it to be,
  24.171 +      simply fix it&emdash;as many times as you need to, until you
  24.172 +      have refined it into the form you desire.</para>
  24.173 +
  24.174 +    <para id="x_3c1">As an example, the integration of patches with revision
  24.175 +      control makes understanding patches and debugging their
  24.176 +      effects&emdash;and their interplay with the code they're based
  24.177 +      on&emdash;<emphasis>enormously</emphasis> easier. Since every
  24.178 +      applied patch has an associated changeset, you can give <command
  24.179 +	role="hg-cmd">hg log</command> a file name to see which
  24.180 +      changesets and patches affected the file.  You can use the
  24.181 +      <command role="hg-cmd">hg bisect</command> command to
  24.182 +      binary-search through all changesets and applied patches to see
  24.183 +      where a bug got introduced or fixed.  You can use the <command
  24.184 +	role="hg-cmd">hg annotate</command> command to see which
  24.185 +      changeset or patch modified a particular line of a source file.
  24.186 +      And so on.</para>
  24.187 +  </sect1>
  24.188 +
  24.189 +  <sect1 id="sec:mq:patch">
  24.190 +    <title>Understanding patches</title>
  24.191 +
  24.192 +    <para id="x_3c2">Because MQ doesn't hide its patch-oriented nature, it is
  24.193 +      helpful to understand what patches are, and a little about the
  24.194 +      tools that work with them.</para>
  24.195 +
  24.196 +    <para id="x_3c3">The traditional Unix <command>diff</command> command
  24.197 +      compares two files, and prints a list of differences between
  24.198 +      them. The <command>patch</command> command understands these
  24.199 +      differences as <emphasis>modifications</emphasis> to make to a
  24.200 +      file.  Take a look below for a simple example of these commands
  24.201 +      in action.</para>
  24.202 +
  24.203 +      &interaction.mq.dodiff.diff;
  24.204 +
  24.205 +    <para id="x_3c4">The type of file that <command>diff</command> generates (and
  24.206 +      <command>patch</command> takes as input) is called a
  24.207 +      <quote>patch</quote> or a <quote>diff</quote>; there is no
  24.208 +      difference between a patch and a diff.  (We'll use the term
  24.209 +      <quote>patch</quote>, since it's more commonly used.)</para>
  24.210 +
  24.211 +    <para id="x_3c5">A patch file can start with arbitrary text; the
  24.212 +      <command>patch</command> command ignores this text, but MQ uses
  24.213 +      it as the commit message when creating changesets.  To find the
  24.214 +      beginning of the patch content, <command>patch</command>
  24.215 +      searches for the first line that starts with the string
  24.216 +      <quote><literal>diff -</literal></quote>.</para>
  24.217 +
  24.218 +    <para id="x_3c6">MQ works with <emphasis>unified</emphasis> diffs
  24.219 +      (<command>patch</command> can accept several other diff formats,
  24.220 +      but MQ doesn't).  A unified diff contains two kinds of header.
  24.221 +      The <emphasis>file header</emphasis> describes the file being
  24.222 +      modified; it contains the name of the file to modify.  When
  24.223 +      <command>patch</command> sees a new file header, it looks for a
  24.224 +      file with that name to start modifying.</para>
  24.225 +
  24.226 +    <para id="x_3c7">After the file header comes a series of
  24.227 +      <emphasis>hunks</emphasis>.  Each hunk starts with a header;
  24.228 +      this identifies the range of line numbers within the file that
  24.229 +      the hunk should modify.  Following the header, a hunk starts and
  24.230 +      ends with a few (usually three) lines of text from the
  24.231 +      unmodified file; these are called the
  24.232 +      <emphasis>context</emphasis> for the hunk.  If there's only a
  24.233 +      small amount of context between successive hunks,
  24.234 +      <command>diff</command> doesn't print a new hunk header; it just
  24.235 +      runs the hunks together, with a few lines of context between
  24.236 +      modifications.</para>
  24.237 +
  24.238 +    <para id="x_3c8">Each line of context begins with a space character.  Within
  24.239 +      the hunk, a line that begins with
  24.240 +      <quote><literal>-</literal></quote> means <quote>remove this
  24.241 +	line,</quote> while a line that begins with
  24.242 +      <quote><literal>+</literal></quote> means <quote>insert this
  24.243 +	line.</quote>  For example, a line that is modified is
  24.244 +      represented by one deletion and one insertion.</para>
  24.245 +
  24.246 +    <para id="x_3c9">We will return to some of the more subtle aspects of patches
  24.247 +      later (in <xref linkend="sec:mq:adv-patch"/>), but you
  24.248 +      should have
  24.249 +      enough information now to use MQ.</para>
  24.250 +  </sect1>
  24.251 +
  24.252 +  <sect1 id="sec:mq:start">
  24.253 +    <title>Getting started with Mercurial Queues</title>
  24.254 +
  24.255 +    <para id="x_3ca">Because MQ is implemented as an extension, you must
  24.256 +      explicitly enable before you can use it.  (You don't need to
  24.257 +      download anything; MQ ships with the standard Mercurial
  24.258 +      distribution.)  To enable MQ, edit your <filename
  24.259 +	role="home">~/.hgrc</filename> file, and add the lines
  24.260 +      below.</para>
  24.261 +
  24.262 +    <programlisting>[extensions]
  24.263 +hgext.mq =</programlisting>
  24.264 +
  24.265 +    <para id="x_3cb">Once the extension is enabled, it will make a number of new
  24.266 +      commands available.  To verify that the extension is working,
  24.267 +      you can use <command role="hg-cmd">hg help</command> to see if
  24.268 +      the <command role="hg-ext-mq">qinit</command> command is now
  24.269 +      available.</para>
  24.270 +
  24.271 +    &interaction.mq.qinit-help.help;
  24.272 +
  24.273 +    <para id="x_3cc">You can use MQ with <emphasis>any</emphasis> Mercurial
  24.274 +      repository, and its commands only operate within that
  24.275 +      repository.  To get started, simply prepare the repository using
  24.276 +      the <command role="hg-ext-mq">qinit</command> command.</para>
  24.277 +
  24.278 +    &interaction.mq.tutorial.qinit;
  24.279 +
  24.280 +    <para id="x_3cd">This command creates an empty directory called <filename
  24.281 +	role="special" class="directory">.hg/patches</filename>, where
  24.282 +      MQ will keep its metadata.  As with many Mercurial commands, the
  24.283 +      <command role="hg-ext-mq">qinit</command> command prints nothing
  24.284 +      if it succeeds.</para>
  24.285 +
  24.286 +    <sect2>
  24.287 +      <title>Creating a new patch</title>
  24.288 +
  24.289 +      <para id="x_3ce">To begin work on a new patch, use the <command
  24.290 +	  role="hg-ext-mq">qnew</command> command.  This command takes
  24.291 +	one argument, the name of the patch to create.</para>
  24.292 +
  24.293 +      <para id="x_3cf">MQ will use this as the name of an actual file in the
  24.294 +	<filename role="special"
  24.295 +	  class="directory">.hg/patches</filename> directory, as you
  24.296 +	can see below.</para>
  24.297 +
  24.298 +      &interaction.mq.tutorial.qnew;
  24.299 +
  24.300 +      <para id="x_3d0">Also newly present in the <filename role="special"
  24.301 +	  class="directory">.hg/patches</filename> directory are two
  24.302 +	other files, <filename role="special">series</filename> and
  24.303 +	<filename role="special">status</filename>.  The <filename
  24.304 +	  role="special">series</filename> file lists all of the
  24.305 +	patches that MQ knows about for this repository, with one
  24.306 +	patch per line.  Mercurial uses the <filename
  24.307 +	  role="special">status</filename> file for internal
  24.308 +	book-keeping; it tracks all of the patches that MQ has
  24.309 +	<emphasis>applied</emphasis> in this repository.</para>
  24.310 +
  24.311 +      <note>
  24.312 +	<para id="x_3d1">  You may sometimes want to edit the <filename
  24.313 +	    role="special">series</filename> file by hand; for
  24.314 +	  example, to change the sequence in which some patches are
  24.315 +	  applied.  However, manually editing the <filename
  24.316 +	    role="special">status</filename> file is almost always a
  24.317 +	  bad idea, as it's easy to corrupt MQ's idea of what is
  24.318 +	  happening.</para>
  24.319 +      </note>
  24.320 +
  24.321 +      <para id="x_3d2">Once you have created your new patch, you can edit files
  24.322 +	in the working directory as you usually would.  All of the
  24.323 +	normal Mercurial commands, such as <command role="hg-cmd">hg
  24.324 +	  diff</command> and <command role="hg-cmd">hg
  24.325 +	  annotate</command>, work exactly as they did before.</para>
  24.326 +    </sect2>
  24.327 +
  24.328 +    <sect2>
  24.329 +      <title>Refreshing a patch</title>
  24.330 +
  24.331 +      <para id="x_3d3">When you reach a point where you want to save your work,
  24.332 +	use the <command role="hg-ext-mq">qrefresh</command> command
  24.333 +	to update the patch you are working on.</para>
  24.334 +
  24.335 +      &interaction.mq.tutorial.qrefresh;
  24.336 +
  24.337 +      <para id="x_3d4">This command folds the changes you have made in the
  24.338 +	working directory into your patch, and updates its
  24.339 +	corresponding changeset to contain those changes.</para>
  24.340 +
  24.341 +      <para id="x_3d5">You can run <command role="hg-ext-mq">qrefresh</command>
  24.342 +	as often as you like, so it's a good way to
  24.343 +	<quote>checkpoint</quote> your work.  Refresh your patch at an
  24.344 +	opportune time; try an experiment; and if the experiment
  24.345 +	doesn't work out, <command role="hg-cmd">hg revert</command>
  24.346 +	your modifications back to the last time you refreshed.</para>
  24.347 +
  24.348 +      &interaction.mq.tutorial.qrefresh2;
  24.349 +    </sect2>
  24.350 +
  24.351 +    <sect2>
  24.352 +      <title>Stacking and tracking patches</title>
  24.353 +
  24.354 +      <para id="x_3d6">Once you have finished working on a patch, or need to work
  24.355 +	on another, you can use the <command
  24.356 +	  role="hg-ext-mq">qnew</command> command again to create a
  24.357 +	new patch. Mercurial will apply this patch on top of your
  24.358 +	existing patch.</para>
  24.359 +
  24.360 +      &interaction.mq.tutorial.qnew2;
  24.361 +
  24.362 +      <para id="x_3d7">Notice that the patch contains the changes in our prior
  24.363 +	patch as part of its context (you can see this more clearly in
  24.364 +	the output of <command role="hg-cmd">hg
  24.365 +	  annotate</command>).</para>
  24.366 +
  24.367 +      <para id="x_3d8">So far, with the exception of <command
  24.368 +	  role="hg-ext-mq">qnew</command> and <command
  24.369 +	  role="hg-ext-mq">qrefresh</command>, we've been careful to
  24.370 +	only use regular Mercurial commands.  However, MQ provides
  24.371 +	many commands that are easier to use when you are thinking
  24.372 +	about patches, as illustrated below.</para>
  24.373 +
  24.374 +      &interaction.mq.tutorial.qseries;
  24.375 +
  24.376 +      <itemizedlist>
  24.377 +	<listitem><para id="x_3d9">The <command
  24.378 +	      role="hg-ext-mq">qseries</command> command lists every
  24.379 +	    patch that MQ knows about in this repository, from oldest
  24.380 +	    to newest (most recently
  24.381 +	    <emphasis>created</emphasis>).</para>
  24.382 +	</listitem>
  24.383 +	<listitem><para id="x_3da">The <command
  24.384 +	      role="hg-ext-mq">qapplied</command> command lists every
  24.385 +	    patch that MQ has <emphasis>applied</emphasis> in this
  24.386 +	    repository, again from oldest to newest (most recently
  24.387 +	    applied).</para>
  24.388 +	</listitem></itemizedlist>
  24.389 +    </sect2>
  24.390 +
  24.391 +    <sect2>
  24.392 +      <title>Manipulating the patch stack</title>
  24.393 +
  24.394 +      <para id="x_3db">The previous discussion implied that there must be a
  24.395 +	difference between <quote>known</quote> and
  24.396 +	<quote>applied</quote> patches, and there is.  MQ can manage a
  24.397 +	patch without it being applied in the repository.</para>
  24.398 +
  24.399 +      <para id="x_3dc">An <emphasis>applied</emphasis> patch has a corresponding
  24.400 +	changeset in the repository, and the effects of the patch and
  24.401 +	changeset are visible in the working directory.  You can undo
  24.402 +	the application of a patch using the <command
  24.403 +	  role="hg-ext-mq">qpop</command> command.  MQ still
  24.404 +	<emphasis>knows about</emphasis>, or manages, a popped patch,
  24.405 +	but the patch no longer has a corresponding changeset in the
  24.406 +	repository, and the working directory does not contain the
  24.407 +	changes made by the patch.  <xref
  24.408 +	  linkend="fig:mq:stack"/> illustrates
  24.409 +	the difference between applied and tracked patches.</para>
  24.410 +
  24.411 +      <figure id="fig:mq:stack">
  24.412 +	<title>Applied and unapplied patches in the MQ patch
  24.413 +	  stack</title>
  24.414 +	<mediaobject>
  24.415 +	  <imageobject><imagedata fileref="figs/mq-stack.png"/></imageobject>
  24.416 +	  <textobject><phrase>XXX add text</phrase></textobject>
  24.417 +	</mediaobject>
  24.418 +      </figure>
  24.419 +
  24.420 +      <para id="x_3de">You can reapply an unapplied, or popped, patch using the
  24.421 +	<command role="hg-ext-mq">qpush</command> command.  This
  24.422 +	creates a new changeset to correspond to the patch, and the
  24.423 +	patch's changes once again become present in the working
  24.424 +	directory.  See below for examples of <command
  24.425 +	  role="hg-ext-mq">qpop</command> and <command
  24.426 +	  role="hg-ext-mq">qpush</command> in action.</para>
  24.427 +
  24.428 +      &interaction.mq.tutorial.qpop;
  24.429 +
  24.430 +      <para id="x_3df">Notice that once we have popped a patch or two patches,
  24.431 +	the output of <command role="hg-ext-mq">qseries</command>
  24.432 +	remains the same, while that of <command
  24.433 +	  role="hg-ext-mq">qapplied</command> has changed.</para>
  24.434 +
  24.435 +    </sect2>
  24.436 +
  24.437 +    <sect2>
  24.438 +      <title>Pushing and popping many patches</title>
  24.439 +
  24.440 +      <para id="x_3e0">While <command role="hg-ext-mq">qpush</command> and
  24.441 +	<command role="hg-ext-mq">qpop</command> each operate on a
  24.442 +	single patch at a time by default, you can push and pop many
  24.443 +	patches in one go.  The <option
  24.444 +	  role="hg-ext-mq-cmd-qpush-opt">-a</option> option to
  24.445 +	<command role="hg-ext-mq">qpush</command> causes it to push
  24.446 +	all unapplied patches, while the <option
  24.447 +	  role="hg-ext-mq-cmd-qpop-opt">-a</option> option to <command
  24.448 +	  role="hg-ext-mq">qpop</command> causes it to pop all applied
  24.449 +	patches.  (For some more ways to push and pop many patches,
  24.450 +	see <xref linkend="sec:mq:perf"/> below.)</para>
  24.451 +
  24.452 +      &interaction.mq.tutorial.qpush-a;
  24.453 +    </sect2>
  24.454 +
  24.455 +    <sect2>
  24.456 +      <title>Safety checks, and overriding them</title>
  24.457 +
  24.458 +      <para id="x_3e1">Several MQ commands check the working directory before
  24.459 +	they do anything, and fail if they find any modifications.
  24.460 +	They do this to ensure that you won't lose any changes that
  24.461 +	you have made, but not yet incorporated into a patch.  The
  24.462 +	example below illustrates this; the <command
  24.463 +	  role="hg-ext-mq">qnew</command> command will not create a
  24.464 +	new patch if there are outstanding changes, caused in this
  24.465 +	case by the <command role="hg-cmd">hg add</command> of
  24.466 +	<filename>file3</filename>.</para>
  24.467 +
  24.468 +      &interaction.mq.tutorial.add;
  24.469 +
  24.470 +      <para id="x_3e2">Commands that check the working directory all take an
  24.471 +	<quote>I know what I'm doing</quote> option, which is always
  24.472 +	named <option>-f</option>.  The exact meaning of
  24.473 +	<option>-f</option> depends on the command.  For example,
  24.474 +	<command role="hg-cmd">hg qnew <option
  24.475 +	    role="hg-ext-mq-cmd-qnew-opt">-f</option></command>
  24.476 +	will incorporate any outstanding changes into the new patch it
  24.477 +	creates, but <command role="hg-cmd">hg qpop <option
  24.478 +	    role="hg-ext-mq-cmd-qpop-opt">-f</option></command>
  24.479 +	will revert modifications to any files affected by the patch
  24.480 +	that it is popping.  Be sure to read the documentation for a
  24.481 +	command's <option>-f</option> option before you use it!</para>
  24.482 +    </sect2>
  24.483 +
  24.484 +    <sect2>
  24.485 +      <title>Working on several patches at once</title>
  24.486 +
  24.487 +      <para id="x_3e3">The <command role="hg-ext-mq">qrefresh</command> command
  24.488 +	always refreshes the <emphasis>topmost</emphasis> applied
  24.489 +	patch.  This means that you can suspend work on one patch (by
  24.490 +	refreshing it), pop or push to make a different patch the top,
  24.491 +	and work on <emphasis>that</emphasis> patch for a
  24.492 +	while.</para>
  24.493 +
  24.494 +      <para id="x_3e4">Here's an example that illustrates how you can use this
  24.495 +	ability. Let's say you're developing a new feature as two
  24.496 +	patches.  The first is a change to the core of your software,
  24.497 +	and the second&emdash;layered on top of the
  24.498 +	first&emdash;changes the user interface to use the code you
  24.499 +	just added to the core.  If you notice a bug in the core while
  24.500 +	you're working on the UI patch, it's easy to fix the core.
  24.501 +	Simply <command role="hg-ext-mq">qrefresh</command> the UI
  24.502 +	patch to save your in-progress changes, and <command
  24.503 +	  role="hg-ext-mq">qpop</command> down to the core patch.  Fix
  24.504 +	the core bug, <command role="hg-ext-mq">qrefresh</command> the
  24.505 +	core patch, and <command role="hg-ext-mq">qpush</command> back
  24.506 +	to the UI patch to continue where you left off.</para>
  24.507 +    </sect2>
  24.508 +  </sect1>
  24.509 +
  24.510 +  <sect1 id="sec:mq:adv-patch">
  24.511 +    <title>More about patches</title>
  24.512 +
  24.513 +    <para id="x_3e5">MQ uses the GNU <command>patch</command> command to apply
  24.514 +      patches, so it's helpful to know a few more detailed aspects of
  24.515 +      how <command>patch</command> works, and about patches
  24.516 +      themselves.</para>
  24.517 +
  24.518 +    <sect2>
  24.519 +      <title>The strip count</title>
  24.520 +
  24.521 +      <para id="x_3e6">If you look at the file headers in a patch, you will
  24.522 +	notice that the pathnames usually have an extra component on
  24.523 +	the front that isn't present in the actual path name.  This is
  24.524 +	a holdover from the way that people used to generate patches
  24.525 +	(people still do this, but it's somewhat rare with modern
  24.526 +	revision control tools).</para>
  24.527 +
  24.528 +      <para id="x_3e7">Alice would unpack a tarball, edit her files, then decide
  24.529 +	that she wanted to create a patch.  So she'd rename her
  24.530 +	working directory, unpack the tarball again (hence the need
  24.531 +	for the rename), and use the <option
  24.532 +	  role="cmd-opt-diff">-r</option> and <option
  24.533 +	  role="cmd-opt-diff">-N</option> options to
  24.534 +	<command>diff</command> to recursively generate a patch
  24.535 +	between the unmodified directory and the modified one.  The
  24.536 +	result would be that the name of the unmodified directory
  24.537 +	would be at the front of the left-hand path in every file
  24.538 +	header, and the name of the modified directory would be at the
  24.539 +	front of the right-hand path.</para>
  24.540 +
  24.541 +      <para id="x_3e8">Since someone receiving a patch from the Alices of the net
  24.542 +	would be unlikely to have unmodified and modified directories
  24.543 +	with exactly the same names, the <command>patch</command>
  24.544 +	command has a <option role="cmd-opt-patch">-p</option> option
  24.545 +	that indicates the number of leading path name components to
  24.546 +	strip when trying to apply a patch.  This number is called the
  24.547 +	<emphasis>strip count</emphasis>.</para>
  24.548 +
  24.549 +      <para id="x_3e9">An option of <quote><literal>-p1</literal></quote> means
  24.550 +	<quote>use a strip count of one</quote>.  If
  24.551 +	<command>patch</command> sees a file name
  24.552 +	<filename>foo/bar/baz</filename> in a file header, it will
  24.553 +	strip <filename>foo</filename> and try to patch a file named
  24.554 +	<filename>bar/baz</filename>.  (Strictly speaking, the strip
  24.555 +	count refers to the number of <emphasis>path
  24.556 +	  separators</emphasis> (and the components that go with them
  24.557 +	) to strip.  A strip count of one will turn
  24.558 +	<filename>foo/bar</filename> into <filename>bar</filename>,
  24.559 +	but <filename>/foo/bar</filename> (notice the extra leading
  24.560 +	slash) into <filename>foo/bar</filename>.)</para>
  24.561 +
  24.562 +      <para id="x_3ea">The <quote>standard</quote> strip count for patches is
  24.563 +	one; almost all patches contain one leading path name
  24.564 +	component that needs to be stripped. Mercurial's <command
  24.565 +	  role="hg-cmd">hg diff</command> command generates path names
  24.566 +	in this form, and the <command role="hg-cmd">hg
  24.567 +	  import</command> command and MQ expect patches to have a
  24.568 +	strip count of one.</para>
  24.569 +
  24.570 +      <para id="x_3eb">If you receive a patch from someone that you want to add
  24.571 +	to your patch queue, and the patch needs a strip count other
  24.572 +	than one, you cannot just <command
  24.573 +	  role="hg-ext-mq">qimport</command> the patch, because
  24.574 +	<command role="hg-ext-mq">qimport</command> does not yet have
  24.575 +	a <literal>-p</literal> option (see <ulink role="hg-bug"
  24.576 +	  url="http://www.selenic.com/mercurial/bts/issue311">issue
  24.577 +	  311</ulink>).  Your best bet is to <command
  24.578 +	  role="hg-ext-mq">qnew</command> a patch of your own, then
  24.579 +	use <command>patch -pN</command> to apply their patch,
  24.580 +	followed by <command role="hg-cmd">hg addremove</command> to
  24.581 +	pick up any files added or removed by the patch, followed by
  24.582 +	<command role="hg-ext-mq">hg qrefresh</command>. This
  24.583 +	complexity may become unnecessary; see <ulink role="hg-bug"
  24.584 +	  url="http://www.selenic.com/mercurial/bts/issue311">issue
  24.585 +	  311</ulink> for details.
  24.586 +      </para>
  24.587 +    </sect2>
  24.588 +
  24.589 +    <sect2>
  24.590 +      <title>Strategies for applying a patch</title>
  24.591 +
  24.592 +      <para id="x_3ec">When <command>patch</command> applies a hunk, it tries a
  24.593 +	handful of successively less accurate strategies to try to
  24.594 +	make the hunk apply. This falling-back technique often makes
  24.595 +	it possible to take a patch that was generated against an old
  24.596 +	version of a file, and apply it against a newer version of
  24.597 +	that file.</para>
  24.598 +
  24.599 +      <para id="x_3ed">First, <command>patch</command> tries an exact match,
  24.600 +	where the line numbers, the context, and the text to be
  24.601 +	modified must apply exactly.  If it cannot make an exact
  24.602 +	match, it tries to find an exact match for the context,
  24.603 +	without honouring the line numbering information.  If this
  24.604 +	succeeds, it prints a line of output saying that the hunk was
  24.605 +	applied, but at some <emphasis>offset</emphasis> from the
  24.606 +	original line number.</para>
  24.607 +
  24.608 +      <para id="x_3ee">If a context-only match fails, <command>patch</command>
  24.609 +	removes the first and last lines of the context, and tries a
  24.610 +	<emphasis>reduced</emphasis> context-only match.  If the hunk
  24.611 +	with reduced context succeeds, it prints a message saying that
  24.612 +	it applied the hunk with a <emphasis>fuzz factor</emphasis>
  24.613 +	(the number after the fuzz factor indicates how many lines of
  24.614 +	context <command>patch</command> had to trim before the patch
  24.615 +	applied).</para>
  24.616 +
  24.617 +      <para id="x_3ef">When neither of these techniques works,
  24.618 +	<command>patch</command> prints a message saying that the hunk
  24.619 +	in question was rejected.  It saves rejected hunks (also
  24.620 +	simply called <quote>rejects</quote>) to a file with the same
  24.621 +	name, and an added <filename role="special">.rej</filename>
  24.622 +	extension.  It also saves an unmodified copy of the file with
  24.623 +	a <filename role="special">.orig</filename> extension; the
  24.624 +	copy of the file without any extensions will contain any
  24.625 +	changes made by hunks that <emphasis>did</emphasis> apply
  24.626 +	cleanly.  If you have a patch that modifies
  24.627 +	<filename>foo</filename> with six hunks, and one of them fails
  24.628 +	to apply, you will have: an unmodified
  24.629 +	<filename>foo.orig</filename>, a <filename>foo.rej</filename>
  24.630 +	containing one hunk, and <filename>foo</filename>, containing
  24.631 +	the changes made by the five successful hunks.</para>
  24.632 +    </sect2>
  24.633 +
  24.634 +    <sect2>
  24.635 +      <title>Some quirks of patch representation</title>
  24.636 +
  24.637 +      <para id="x_3f0">There are a few useful things to know about how
  24.638 +	<command>patch</command> works with files.</para>
  24.639 +      <itemizedlist>
  24.640 +	<listitem><para id="x_3f1">This should already be obvious, but
  24.641 +	    <command>patch</command> cannot handle binary
  24.642 +	    files.</para>
  24.643 +	</listitem>
  24.644 +	<listitem><para id="x_3f2">Neither does it care about the executable bit;
  24.645 +	    it creates new files as readable, but not
  24.646 +	    executable.</para>
  24.647 +	</listitem>
  24.648 +	<listitem><para id="x_3f3"><command>patch</command> treats the removal of
  24.649 +	    a file as a diff between the file to be removed and the
  24.650 +	    empty file.  So your idea of <quote>I deleted this
  24.651 +	      file</quote> looks like <quote>every line of this file
  24.652 +	      was deleted</quote> in a patch.</para>
  24.653 +	</listitem>
  24.654 +	<listitem><para id="x_3f4">It treats the addition of a file as a diff
  24.655 +	    between the empty file and the file to be added.  So in a
  24.656 +	    patch, your idea of <quote>I added this file</quote> looks
  24.657 +	    like <quote>every line of this file was
  24.658 +	      added</quote>.</para>
  24.659 +	</listitem>
  24.660 +	<listitem><para id="x_3f5">It treats a renamed file as the removal of the
  24.661 +	    old name, and the addition of the new name.  This means
  24.662 +	    that renamed files have a big footprint in patches.  (Note
  24.663 +	    also that Mercurial does not currently try to infer when
  24.664 +	    files have been renamed or copied in a patch.)</para>
  24.665 +	</listitem>
  24.666 +	<listitem><para id="x_3f6"><command>patch</command> cannot represent
  24.667 +	    empty files, so you cannot use a patch to represent the
  24.668 +	    notion <quote>I added this empty file to the
  24.669 +	      tree</quote>.</para>
  24.670 +	</listitem></itemizedlist>
  24.671 +    </sect2>
  24.672 +
  24.673 +    <sect2>
  24.674 +      <title>Beware the fuzz</title>
  24.675 +
  24.676 +      <para id="x_3f7">While applying a hunk at an offset, or with a fuzz factor,
  24.677 +	will often be completely successful, these inexact techniques
  24.678 +	naturally leave open the possibility of corrupting the patched
  24.679 +	file.  The most common cases typically involve applying a
  24.680 +	patch twice, or at an incorrect location in the file.  If
  24.681 +	<command>patch</command> or <command
  24.682 +	  role="hg-ext-mq">qpush</command> ever mentions an offset or
  24.683 +	fuzz factor, you should make sure that the modified files are
  24.684 +	correct afterwards.</para>
  24.685 +
  24.686 +      <para id="x_3f8">It's often a good idea to refresh a patch that has applied
  24.687 +	with an offset or fuzz factor; refreshing the patch generates
  24.688 +	new context information that will make it apply cleanly.  I
  24.689 +	say <quote>often,</quote> not <quote>always,</quote> because
  24.690 +	sometimes refreshing a patch will make it fail to apply
  24.691 +	against a different revision of the underlying files.  In some
  24.692 +	cases, such as when you're maintaining a patch that must sit
  24.693 +	on top of multiple versions of a source tree, it's acceptable
  24.694 +	to have a patch apply with some fuzz, provided you've verified
  24.695 +	the results of the patching process in such cases.</para>
  24.696 +    </sect2>
  24.697 +
  24.698 +    <sect2>
  24.699 +      <title>Handling rejection</title>
  24.700 +
  24.701 +      <para id="x_3f9">If <command role="hg-ext-mq">qpush</command> fails to
  24.702 +	apply a patch, it will print an error message and exit.  If it
  24.703 +	has left <filename role="special">.rej</filename> files
  24.704 +	behind, it is usually best to fix up the rejected hunks before
  24.705 +	you push more patches or do any further work.</para>
  24.706 +
  24.707 +      <para id="x_3fa">If your patch <emphasis>used to</emphasis> apply cleanly,
  24.708 +	and no longer does because you've changed the underlying code
  24.709 +	that your patches are based on, Mercurial Queues can help; see
  24.710 +	<xref linkend="sec:mq:merge"/> for details.</para>
  24.711 +
  24.712 +      <para id="x_3fb">Unfortunately, there aren't any great techniques for
  24.713 +	dealing with rejected hunks.  Most often, you'll need to view
  24.714 +	the <filename role="special">.rej</filename> file and edit the
  24.715 +	target file, applying the rejected hunks by hand.</para>
  24.716 +
  24.717 +      <para id="x_3fd">A Linux kernel hacker, Chris Mason (the author
  24.718 +	of Mercurial Queues), wrote a tool called
  24.719 +	<command>mpatch</command> (<ulink
  24.720 +	  url="http://oss.oracle.com/~mason/mpatch/">http://oss.oracle.com/~mason/mpatch/</ulink>), 
  24.721 +	which takes a simple approach to automating the application of
  24.722 +	hunks rejected by <command>patch</command>.  The
  24.723 +	<command>mpatch</command> command can help with four common
  24.724 +	reasons that a hunk may be rejected:</para>
  24.725 +
  24.726 +      <itemizedlist>
  24.727 +	<listitem><para id="x_3fe">The context in the middle of a hunk has
  24.728 +	    changed.</para>
  24.729 +	</listitem>
  24.730 +	<listitem><para id="x_3ff">A hunk is missing some context at the
  24.731 +	    beginning or end.</para>
  24.732 +	</listitem>
  24.733 +	<listitem><para id="x_400">A large hunk might apply better&emdash;either
  24.734 +	    entirely or in part&emdash;if it was broken up into
  24.735 +	    smaller hunks.</para>
  24.736 +	</listitem>
  24.737 +	<listitem><para id="x_401">A hunk removes lines with slightly different
  24.738 +	    content than those currently present in the file.</para>
  24.739 +	</listitem></itemizedlist>
  24.740 +
  24.741 +      <para id="x_402">If you use <command>mpatch</command>, you
  24.742 +	should be doubly careful to check your results when you're
  24.743 +	done.  In fact, <command>mpatch</command> enforces this method
  24.744 +	of double-checking the tool's output, by automatically
  24.745 +	dropping you into a merge program when it has done its job, so
  24.746 +	that you can verify its work and finish off any remaining
  24.747 +	merges.</para>
  24.748 +    </sect2>
  24.749 +  </sect1>
  24.750 +
  24.751 +  <sect1>
  24.752 +    <title>More on patch management</title>
  24.753 +
  24.754 +    <para id="x_6db">As you grow familiar with MQ, you will find yourself wanting
  24.755 +      to perform other kinds of patch management operations.</para>
  24.756 +
  24.757 +    <sect2>
  24.758 +      <title>Deleting unwanted patches</title>
  24.759 +
  24.760 +      <para id="x_6dc">If you want to get rid of a patch, use the <command
  24.761 +	  role="hg-ext-mq">hg qdelete</command> command to delete the
  24.762 +	patch file and remove its entry from the patch series.  If you
  24.763 +	try to delete a patch that is still applied, <command
  24.764 +	  role="hg-ext-mq">hg qdelete</command> will refuse.</para>
  24.765 +
  24.766 +      &interaction.ch11-qdelete.go;
  24.767 +    </sect2>
  24.768 +
  24.769 +    <sect2>
  24.770 +      <title>Converting to and from permanent revisions</title>
  24.771 +
  24.772 +      <para id="x_6dd">Once you're done working on a patch and want to
  24.773 +      turn it into a permanent changeset, use the <command
  24.774 +      role="hg-ext-mq">hg qfinish</command> command. Pass a revision
  24.775 +      to the command to identify the patch that you want to turn into
  24.776 +      a regular changeset; this patch must already be applied.</para>
  24.777 +
  24.778 +      &interaction.ch11-qdelete.convert;
  24.779 +
  24.780 +      <para id="x_6e0">The <command role="hg-ext-mq">hg qfinish</command> command
  24.781 +        accepts an <option>--all</option> or <option>-a</option>
  24.782 +        option, which turns all applied patches into regular
  24.783 +        changesets.</para>
  24.784 +
  24.785 +      <para id="x_6de">It is also possible to turn an existing changeset into a
  24.786 +	patch, by passing the <option>-r</option> option to <command
  24.787 +	  role="hg-ext-mq">hg qimport</command>.</para>
  24.788 +
  24.789 +      &interaction.ch11-qdelete.import;
  24.790 +
  24.791 +      <para id="x_6df">Note that it only makes sense to convert a changeset into
  24.792 +	a patch if you have not propagated that changeset into any
  24.793 +	other repositories.  The imported changeset's ID will change
  24.794 +	every time you refresh the patch, which will make Mercurial
  24.795 +	treat it as unrelated to the original changeset if you have
  24.796 +	pushed it somewhere else.</para>
  24.797 +    </sect2>
  24.798 +  </sect1>
  24.799 +
  24.800 +  <sect1 id="sec:mq:perf">
  24.801 +    <title>Getting the best performance out of MQ</title>
  24.802 +
  24.803 +    <para id="x_403">MQ is very efficient at handling a large number
  24.804 +      of patches. I ran some performance experiments in mid-2006 for a
  24.805 +      talk that I gave at the 2006 EuroPython conference (on modern
  24.806 +      hardware, you should expect better performance than you'll see
  24.807 +      below).  I used as my data set the Linux 2.6.17-mm1 patch
  24.808 +      series, which consists of 1,738 patches. I applied these on top
  24.809 +      of a Linux kernel repository containing all 27,472 revisions
  24.810 +      between Linux 2.6.12-rc2 and Linux 2.6.17.</para>
  24.811 +
  24.812 +    <para id="x_404">On my old, slow laptop, I was able to <command
  24.813 +	role="hg-cmd">hg qpush <option
  24.814 +	  role="hg-ext-mq-cmd-qpush-opt">-a</option></command> all
  24.815 +      1,738 patches in 3.5 minutes, and <command role="hg-cmd">hg qpop
  24.816 +	<option role="hg-ext-mq-cmd-qpop-opt">-a</option></command>
  24.817 +      them all in 30 seconds.  (On a newer laptop, the time to push
  24.818 +      all patches dropped to two minutes.)  I could <command
  24.819 +	role="hg-ext-mq">qrefresh</command> one of the biggest patches
  24.820 +      (which made 22,779 lines of changes to 287 files) in 6.6
  24.821 +      seconds.</para>
  24.822 +
  24.823 +    <para id="x_405">Clearly, MQ is well suited to working in large trees, but
  24.824 +      there are a few tricks you can use to get the best performance
  24.825 +      of it.</para>
  24.826 +
  24.827 +    <para id="x_406">First of all, try to <quote>batch</quote> operations
  24.828 +      together.  Every time you run <command
  24.829 +	role="hg-ext-mq">qpush</command> or <command
  24.830 +	role="hg-ext-mq">qpop</command>, these commands scan the
  24.831 +      working directory once to make sure you haven't made some
  24.832 +      changes and then forgotten to run <command
  24.833 +	role="hg-ext-mq">qrefresh</command>.  On a small tree, the
  24.834 +      time that this scan takes is unnoticeable.  However, on a
  24.835 +      medium-sized tree (containing tens of thousands of files), it
  24.836 +      can take a second or more.</para>
  24.837 +
  24.838 +    <para id="x_407">The <command role="hg-ext-mq">qpush</command> and <command
  24.839 +	role="hg-ext-mq">qpop</command> commands allow you to push and
  24.840 +      pop multiple patches at a time.  You can identify the
  24.841 +      <quote>destination patch</quote> that you want to end up at.
  24.842 +      When you <command role="hg-ext-mq">qpush</command> with a
  24.843 +      destination specified, it will push patches until that patch is
  24.844 +      at the top of the applied stack.  When you <command
  24.845 +	role="hg-ext-mq">qpop</command> to a destination, MQ will pop
  24.846 +      patches until the destination patch is at the top.</para>
  24.847 +
  24.848 +    <para id="x_408">You can identify a destination patch using either the name
  24.849 +      of the patch, or by number.  If you use numeric addressing,
  24.850 +      patches are counted from zero; this means that the first patch
  24.851 +      is zero, the second is one, and so on.</para>
  24.852 +  </sect1>
  24.853 +
  24.854 +  <sect1 id="sec:mq:merge">
  24.855 +    <title>Updating your patches when the underlying code
  24.856 +      changes</title>
  24.857 +
  24.858 +    <para id="x_409">It's common to have a stack of patches on top of an
  24.859 +      underlying repository that you don't modify directly.  If you're
  24.860 +      working on changes to third-party code, or on a feature that is
  24.861 +      taking longer to develop than the rate of change of the code
  24.862 +      beneath, you will often need to sync up with the underlying
  24.863 +      code, and fix up any hunks in your patches that no longer apply.
  24.864 +      This is called <emphasis>rebasing</emphasis> your patch
  24.865 +      series.</para>
  24.866 +
  24.867 +    <para id="x_40a">The simplest way to do this is to <command role="hg-cmd">hg
  24.868 +	qpop <option role="hg-ext-mq-cmd-qpop-opt">hg
  24.869 +	  -a</option></command> your patches, then <command
  24.870 +	role="hg-cmd">hg pull</command> changes into the underlying
  24.871 +      repository, and finally <command role="hg-cmd">hg qpush <option
  24.872 +	  role="hg-ext-mq-cmd-qpop-opt">-a</option></command> your
  24.873 +      patches again.  MQ will stop pushing any time it runs across a
  24.874 +      patch that fails to apply during conflicts, allowing you to fix
  24.875 +      your conflicts, <command role="hg-ext-mq">qrefresh</command> the
  24.876 +      affected patch, and continue pushing until you have fixed your
  24.877 +      entire stack.</para>
  24.878 +
  24.879 +    <para id="x_40b">This approach is easy to use and works well if you don't
  24.880 +      expect changes to the underlying code to affect how well your
  24.881 +      patches apply. If your patch stack touches code that is modified
  24.882 +      frequently or invasively in the underlying repository, however,
  24.883 +      fixing up rejected hunks by hand quickly becomes
  24.884 +      tiresome.</para>
  24.885 +
  24.886 +    <para id="x_40c">It's possible to partially automate the rebasing process.
  24.887 +      If your patches apply cleanly against some revision of the
  24.888 +      underlying repo, MQ can use this information to help you to
  24.889 +      resolve conflicts between your patches and a different
  24.890 +      revision.</para>
  24.891 +
  24.892 +    <para id="x_40d">The process is a little involved.</para>
  24.893 +    <orderedlist>
  24.894 +      <listitem><para id="x_40e">To begin, <command role="hg-cmd">hg qpush
  24.895 +	    -a</command> all of your patches on top of the revision
  24.896 +	  where you know that they apply cleanly.</para>
  24.897 +      </listitem>
  24.898 +      <listitem><para id="x_40f">Save a backup copy of your patch directory using
  24.899 +	  <command role="hg-cmd">hg qsave <option
  24.900 +	      role="hg-ext-mq-cmd-qsave-opt">hg -e</option> <option
  24.901 +	      role="hg-ext-mq-cmd-qsave-opt">hg -c</option></command>.
  24.902 +	  This prints the name of the directory that it has saved the
  24.903 +	  patches in.  It will save the patches to a directory called
  24.904 +	  <filename role="special"
  24.905 +	    class="directory">.hg/patches.N</filename>, where
  24.906 +	  <literal>N</literal> is a small integer.  It also commits a
  24.907 +	  <quote>save changeset</quote> on top of your applied
  24.908 +	  patches; this is for internal book-keeping, and records the
  24.909 +	  states of the <filename role="special">series</filename> and
  24.910 +	  <filename role="special">status</filename> files.</para>
  24.911 +      </listitem>
  24.912 +      <listitem><para id="x_410">Use <command role="hg-cmd">hg pull</command> to
  24.913 +	  bring new changes into the underlying repository.  (Don't
  24.914 +	  run <command role="hg-cmd">hg pull -u</command>; see below
  24.915 +	  for why.)</para>
  24.916 +      </listitem>
  24.917 +      <listitem><para id="x_411">Update to the new tip revision, using <command
  24.918 +	    role="hg-cmd">hg update <option
  24.919 +	      role="hg-opt-update">-C</option></command> to override
  24.920 +	  the patches you have pushed.</para>
  24.921 +      </listitem>
  24.922 +      <listitem><para id="x_412">Merge all patches using <command>hg qpush -m
  24.923 +	    -a</command>.  The <option
  24.924 +	    role="hg-ext-mq-cmd-qpush-opt">-m</option> option to
  24.925 +	  <command role="hg-ext-mq">qpush</command> tells MQ to
  24.926 +	  perform a three-way merge if the patch fails to
  24.927 +	  apply.</para>
  24.928 +      </listitem></orderedlist>
  24.929 +
  24.930 +    <para id="x_413">During the <command role="hg-cmd">hg qpush <option
  24.931 +	  role="hg-ext-mq-cmd-qpush-opt">hg -m</option></command>,
  24.932 +      each patch in the <filename role="special">series</filename>
  24.933 +      file is applied normally.  If a patch applies with fuzz or
  24.934 +      rejects, MQ looks at the queue you <command
  24.935 +	role="hg-ext-mq">qsave</command>d, and performs a three-way
  24.936 +      merge with the corresponding changeset.  This merge uses
  24.937 +      Mercurial's normal merge machinery, so it may pop up a GUI merge
  24.938 +      tool to help you to resolve problems.</para>
  24.939 +
  24.940 +    <para id="x_414">When you finish resolving the effects of a patch, MQ
  24.941 +      refreshes your patch based on the result of the merge.</para>
  24.942 +
  24.943 +    <para id="x_415">At the end of this process, your repository will have one
  24.944 +      extra head from the old patch queue, and a copy of the old patch
  24.945 +      queue will be in <filename role="special"
  24.946 +	class="directory">.hg/patches.N</filename>. You can remove the
  24.947 +      extra head using <command role="hg-cmd">hg qpop -a -n
  24.948 +	patches.N</command> or <command role="hg-cmd">hg
  24.949 +	strip</command>.  You can delete <filename role="special"
  24.950 +	class="directory">.hg/patches.N</filename> once you are sure
  24.951 +      that you no longer need it as a backup.</para>
  24.952 +  </sect1>
  24.953 +
  24.954 +  <sect1>
  24.955 +    <title>Identifying patches</title>
  24.956 +
  24.957 +    <para id="x_416">MQ commands that work with patches let you refer to a patch
  24.958 +      either by using its name or by a number.  By name is obvious
  24.959 +      enough; pass the name <filename>foo.patch</filename> to <command
  24.960 +	role="hg-ext-mq">qpush</command>, for example, and it will
  24.961 +      push patches until <filename>foo.patch</filename> is
  24.962 +      applied.</para>
  24.963 +
  24.964 +    <para id="x_417">As a shortcut, you can refer to a patch using both a name
  24.965 +      and a numeric offset; <literal>foo.patch-2</literal> means
  24.966 +      <quote>two patches before <literal>foo.patch</literal></quote>,
  24.967 +      while <literal>bar.patch+4</literal> means <quote>four patches
  24.968 +	after <literal>bar.patch</literal></quote>.</para>
  24.969 +
  24.970 +    <para id="x_418">Referring to a patch by index isn't much different.  The
  24.971 +      first patch printed in the output of <command
  24.972 +	role="hg-ext-mq">qseries</command> is patch zero (yes, it's
  24.973 +      one of those start-at-zero counting systems); the second is
  24.974 +      patch one; and so on.</para>
  24.975 +
  24.976 +    <para id="x_419">MQ also makes it easy to work with patches when you are
  24.977 +      using normal Mercurial commands.  Every command that accepts a
  24.978 +      changeset ID will also accept the name of an applied patch.  MQ
  24.979 +      augments the tags normally in the repository with an eponymous
  24.980 +      one for each applied patch.  In addition, the special tags
  24.981 +      <literal role="tag">qbase</literal> and
  24.982 +      <literal role="tag">qtip</literal> identify
  24.983 +      the <quote>bottom-most</quote> and topmost applied patches,
  24.984 +      respectively.</para>
  24.985 +
  24.986 +    <para id="x_41a">These additions to Mercurial's normal tagging capabilities
  24.987 +      make dealing with patches even more of a breeze.</para>
  24.988 +    <itemizedlist>
  24.989 +      <listitem><para id="x_41b">Want to patchbomb a mailing list with your
  24.990 +	  latest series of changes?</para>
  24.991 +	<programlisting>hg email qbase:qtip</programlisting>
  24.992 +	<para id="x_41c">  (Don't know what <quote>patchbombing</quote> is?  See
  24.993 +	  <xref linkend="sec:hgext:patchbomb"/>.)</para>
  24.994 +      </listitem>
  24.995 +      <listitem><para id="x_41d">Need to see all of the patches since
  24.996 +	  <literal>foo.patch</literal> that have touched files in a
  24.997 +	  subdirectory of your tree?</para>
  24.998 +	<programlisting>hg log -r foo.patch:qtip subdir</programlisting>
  24.999 +      </listitem>
 24.1000 +    </itemizedlist>
 24.1001 +
 24.1002 +    <para id="x_41e">Because MQ makes the names of patches available to the rest
 24.1003 +      of Mercurial through its normal internal tag machinery, you
 24.1004 +      don't need to type in the entire name of a patch when you want
 24.1005 +      to identify it by name.</para>
 24.1006 +
 24.1007 +    <para id="x_41f">Another nice consequence of representing patch names as tags
 24.1008 +      is that when you run the <command role="hg-cmd">hg log</command>
 24.1009 +      command, it will display a patch's name as a tag, simply as part
 24.1010 +      of its normal output.  This makes it easy to visually
 24.1011 +      distinguish applied patches from underlying
 24.1012 +      <quote>normal</quote> revisions.  The following example shows a
 24.1013 +      few normal Mercurial commands in use with applied
 24.1014 +      patches.</para>
 24.1015 +
 24.1016 +    &interaction.mq.id.output;
 24.1017 +  </sect1>
 24.1018 +
 24.1019 +  <sect1>
 24.1020 +    <title>Useful things to know about</title>
 24.1021 +
 24.1022 +    <para id="x_420">There are a number of aspects of MQ usage that don't fit
 24.1023 +      tidily into sections of their own, but that are good to know.
 24.1024 +      Here they are, in one place.</para>
 24.1025 +
 24.1026 +    <itemizedlist>
 24.1027 +      <listitem><para id="x_421">Normally, when you <command
 24.1028 +	    role="hg-ext-mq">qpop</command> a patch and <command
 24.1029 +	    role="hg-ext-mq">qpush</command> it again, the changeset
 24.1030 +	  that represents the patch after the pop/push will have a
 24.1031 +	  <emphasis>different identity</emphasis> than the changeset
 24.1032 +	  that represented the hash beforehand.  See <xref
 24.1033 +	    linkend="sec:mqref:cmd:qpush"/> for
 24.1034 +	  information as to why this is.</para>
 24.1035 +      </listitem>
 24.1036 +      <listitem><para id="x_422">It's not a good idea to <command
 24.1037 +	    role="hg-cmd">hg merge</command> changes from another
 24.1038 +	  branch with a patch changeset, at least if you want to
 24.1039 +	  maintain the <quote>patchiness</quote> of that changeset and
 24.1040 +	  changesets below it on the patch stack.  If you try to do
 24.1041 +	  this, it will appear to succeed, but MQ will become
 24.1042 +	  confused.</para>
 24.1043 +      </listitem></itemizedlist>
 24.1044 +  </sect1>
 24.1045 +
 24.1046 +  <sect1 id="sec:mq:repo">
 24.1047 +    <title>Managing patches in a repository</title>
 24.1048 +
 24.1049 +    <para id="x_423">Because MQ's <filename role="special"
 24.1050 +	class="directory">.hg/patches</filename> directory resides
 24.1051 +      outside a Mercurial repository's working directory, the
 24.1052 +      <quote>underlying</quote> Mercurial repository knows nothing
 24.1053 +      about the management or presence of patches.</para>
 24.1054 +
 24.1055 +    <para id="x_424">This presents the interesting possibility of managing the
 24.1056 +      contents of the patch directory as a Mercurial repository in its
 24.1057 +      own right.  This can be a useful way to work.  For example, you
 24.1058 +      can work on a patch for a while, <command
 24.1059 +	role="hg-ext-mq">qrefresh</command> it, then <command
 24.1060 +	role="hg-cmd">hg commit</command> the current state of the
 24.1061 +      patch.  This lets you <quote>roll back</quote> to that version
 24.1062 +      of the patch later on.</para>
 24.1063 +
 24.1064 +    <para id="x_425">You can then share different versions of the same patch
 24.1065 +      stack among multiple underlying repositories.  I use this when I
 24.1066 +      am developing a Linux kernel feature.  I have a pristine copy of
 24.1067 +      my kernel sources for each of several CPU architectures, and a
 24.1068 +      cloned repository under each that contains the patches I am
 24.1069 +      working on.  When I want to test a change on a different
 24.1070 +      architecture, I push my current patches to the patch repository
 24.1071 +      associated with that kernel tree, pop and push all of my
 24.1072 +      patches, and build and test that kernel.</para>
 24.1073 +
 24.1074 +    <para id="x_426">Managing patches in a repository makes it possible for
 24.1075 +      multiple developers to work on the same patch series without
 24.1076 +      colliding with each other, all on top of an underlying source
 24.1077 +      base that they may or may not control.</para>
 24.1078 +
 24.1079 +    <sect2>
 24.1080 +      <title>MQ support for patch repositories</title>
 24.1081 +
 24.1082 +      <para id="x_427">MQ helps you to work with the <filename role="special"
 24.1083 +	  class="directory">.hg/patches</filename> directory as a
 24.1084 +	repository; when you prepare a repository for working with
 24.1085 +	patches using <command role="hg-ext-mq">qinit</command>, you
 24.1086 +	can pass the <option role="hg-ext-mq-cmd-qinit-opt">hg
 24.1087 +	  -c</option> option to create the <filename role="special"
 24.1088 +	  class="directory">.hg/patches</filename> directory as a
 24.1089 +	Mercurial repository.</para>
 24.1090 +
 24.1091 +      <note>
 24.1092 +	<para id="x_428">  If you forget to use the <option
 24.1093 +	    role="hg-ext-mq-cmd-qinit-opt">hg -c</option> option, you
 24.1094 +	  can simply go into the <filename role="special"
 24.1095 +	    class="directory">.hg/patches</filename> directory at any
 24.1096 +	  time and run <command role="hg-cmd">hg init</command>.
 24.1097 +	  Don't forget to add an entry for the <filename
 24.1098 +	    role="special">status</filename> file to the <filename
 24.1099 +	    role="special">.hgignore</filename> file, though</para>
 24.1100 +
 24.1101 +	<para id="x_429">  (<command role="hg-cmd">hg qinit <option
 24.1102 +	      role="hg-ext-mq-cmd-qinit-opt">hg -c</option></command>
 24.1103 +	  does this for you automatically); you
 24.1104 +	  <emphasis>really</emphasis> don't want to manage the
 24.1105 +	  <filename role="special">status</filename> file.</para>
 24.1106 +      </note>
 24.1107 +
 24.1108 +      <para id="x_42a">As a convenience, if MQ notices that the <filename
 24.1109 +	  class="directory">.hg/patches</filename> directory is a
 24.1110 +	repository, it will automatically <command role="hg-cmd">hg
 24.1111 +	  add</command> every patch that you create and import.</para>
 24.1112 +
 24.1113 +      <para id="x_42b">MQ provides a shortcut command, <command
 24.1114 +	  role="hg-ext-mq">qcommit</command>, that runs <command
 24.1115 +	  role="hg-cmd">hg commit</command> in the <filename
 24.1116 +	  role="special" class="directory">.hg/patches</filename>
 24.1117 +	directory.  This saves some bothersome typing.</para>
 24.1118 +
 24.1119 +      <para id="x_42c">Finally, as a convenience to manage the patch directory,
 24.1120 +	you can define the alias <command>mq</command> on Unix
 24.1121 +	systems. For example, on Linux systems using the
 24.1122 +	<command>bash</command> shell, you can include the following
 24.1123 +	snippet in your <filename
 24.1124 +	  role="home">~/.bashrc</filename>.</para>
 24.1125 +
 24.1126 +      <programlisting>alias mq=`hg -R $(hg root)/.hg/patches'</programlisting>
 24.1127 +
 24.1128 +      <para id="x_42d">You can then issue commands of the form <command>mq
 24.1129 +	  pull</command> from the main repository.</para>
 24.1130 +    </sect2>
 24.1131 +
 24.1132 +    <sect2>
 24.1133 +      <title>A few things to watch out for</title>
 24.1134 +
 24.1135 +      <para id="x_42e">MQ's support for working with a repository full of patches
 24.1136 +	is limited in a few small respects.</para>
 24.1137 +
 24.1138 +      <para id="x_42f">MQ cannot automatically detect changes that you make to
 24.1139 +	the patch directory.  If you <command role="hg-cmd">hg
 24.1140 +	  pull</command>, manually edit, or <command role="hg-cmd">hg
 24.1141 +	  update</command> changes to patches or the <filename
 24.1142 +	  role="special">series</filename> file, you will have to
 24.1143 +	<command role="hg-cmd">hg qpop <option
 24.1144 +	    role="hg-ext-mq-cmd-qpop-opt">-a</option></command> and
 24.1145 +	then <command role="hg-cmd">hg qpush <option
 24.1146 +	    role="hg-ext-mq-cmd-qpush-opt">-a</option></command> in
 24.1147 +	the underlying repository to see those changes show up there.
 24.1148 +	If you forget to do this, you can confuse MQ's idea of which
 24.1149 +	patches are applied.</para>
 24.1150 +
 24.1151 +    </sect2>
 24.1152 +  </sect1>
 24.1153 +  <sect1 id="sec:mq:tools">
 24.1154 +    <title>Third party tools for working with patches</title>
 24.1155 +
 24.1156 +    <para id="x_430">Once you've been working with patches for a while, you'll
 24.1157 +      find yourself hungry for tools that will help you to understand
 24.1158 +      and manipulate the patches you're dealing with.</para>
 24.1159 +
 24.1160 +    <para id="x_431">The <command>diffstat</command> command
 24.1161 +      <citation>web:diffstat</citation> generates a histogram of the
 24.1162 +      modifications made to each file in a patch.  It provides a good
 24.1163 +      way to <quote>get a sense of</quote> a patch&emdash;which files
 24.1164 +      it affects, and how much change it introduces to each file and
 24.1165 +      as a whole.  (I find that it's a good idea to use
 24.1166 +      <command>diffstat</command>'s <option
 24.1167 +	role="cmd-opt-diffstat">-p</option> option as a matter of
 24.1168 +      course, as otherwise it will try to do clever things with
 24.1169 +      prefixes of file names that inevitably confuse at least
 24.1170 +      me.)</para>
 24.1171 +
 24.1172 +&interaction.mq.tools.tools;
 24.1173 +
 24.1174 +    <para id="x_432">The <literal role="package">patchutils</literal> package
 24.1175 +      <citation>web:patchutils</citation> is invaluable. It provides a
 24.1176 +      set of small utilities that follow the <quote>Unix
 24.1177 +	philosophy;</quote> each does one useful thing with a patch.
 24.1178 +      The <literal role="package">patchutils</literal> command I use
 24.1179 +      most is <command>filterdiff</command>, which extracts subsets
 24.1180 +      from a patch file.  For example, given a patch that modifies
 24.1181 +      hundreds of files across dozens of directories, a single
 24.1182 +      invocation of <command>filterdiff</command> can generate a
 24.1183 +      smaller patch that only touches files whose names match a
 24.1184 +      particular glob pattern.  See <xref
 24.1185 +	linkend="mq-collab:tips:interdiff"/> for another
 24.1186 +      example.</para>
 24.1187 +
 24.1188 +  </sect1>
 24.1189 +  <sect1>
 24.1190 +    <title>Good ways to work with patches</title>
 24.1191 +
 24.1192 +    <para id="x_433">Whether you are working on a patch series to submit to a
 24.1193 +      free software or open source project, or a series that you
 24.1194 +      intend to treat as a sequence of regular changesets when you're
 24.1195 +      done, you can use some simple techniques to keep your work well
 24.1196 +      organized.</para>
 24.1197 +
 24.1198 +    <para id="x_434">Give your patches descriptive names.  A good name for a
 24.1199 +      patch might be <filename>rework-device-alloc.patch</filename>,
 24.1200 +      because it will immediately give you a hint what the purpose of
 24.1201 +      the patch is.  Long names shouldn't be a problem; you won't be
 24.1202 +      typing the names often, but you <emphasis>will</emphasis> be
 24.1203 +      running commands like <command
 24.1204 +	role="hg-ext-mq">qapplied</command> and <command
 24.1205 +	role="hg-ext-mq">qtop</command> over and over. Good naming
 24.1206 +      becomes especially important when you have a number of patches
 24.1207 +      to work with, or if you are juggling a number of different tasks
 24.1208 +      and your patches only get a fraction of your attention.</para>
 24.1209 +
 24.1210 +    <para id="x_435">Be aware of what patch you're working on.  Use the <command
 24.1211 +	role="hg-ext-mq">qtop</command> command and skim over the text
 24.1212 +      of your patches frequently&emdash;for example, using <command
 24.1213 +	role="hg-cmd">hg tip <option
 24.1214 +	  role="hg-opt-tip">-p</option></command>)&emdash;to be sure
 24.1215 +      of where you stand.  I have several times worked on and <command
 24.1216 +	role="hg-ext-mq">qrefresh</command>ed a patch other than the
 24.1217 +      one I intended, and it's often tricky to migrate changes into
 24.1218 +      the right patch after making them in the wrong one.</para>
 24.1219 +
 24.1220 +    <para id="x_436">For this reason, it is very much worth investing a little
 24.1221 +      time to learn how to use some of the third-party tools I
 24.1222 +      described in <xref linkend="sec:mq:tools"/>,
 24.1223 +      particularly
 24.1224 +      <command>diffstat</command> and <command>filterdiff</command>.
 24.1225 +      The former will give you a quick idea of what changes your patch
 24.1226 +      is making, while the latter makes it easy to splice hunks
 24.1227 +      selectively out of one patch and into another.</para>
 24.1228 +
 24.1229 +  </sect1>
 24.1230 +  <sect1>
 24.1231 +    <title>MQ cookbook</title>
 24.1232 +
 24.1233 +    <sect2>
 24.1234 +      <title>Manage <quote>trivial</quote> patches</title>
 24.1235 +
 24.1236 +      <para id="x_437">Because the overhead of dropping files into a new
 24.1237 +	Mercurial repository is so low, it makes a lot of sense to
 24.1238 +	manage patches this way even if you simply want to make a few
 24.1239 +	changes to a source tarball that you downloaded.</para>
 24.1240 +
 24.1241 +      <para id="x_438">Begin by downloading and unpacking the source tarball, and
 24.1242 +	turning it into a Mercurial repository.</para>
 24.1243 +
 24.1244 +      &interaction.mq.tarball.download;
 24.1245 +
 24.1246 +      <para id="x_439">Continue by creating a patch stack and making your
 24.1247 +	changes.</para>
 24.1248 +
 24.1249 +      &interaction.mq.tarball.qinit;
 24.1250 +
 24.1251 +      <para id="x_43a">Let's say a few weeks or months pass, and your package
 24.1252 +	author releases a new version.  First, bring their changes
 24.1253 +	into the repository.</para>
 24.1254 +
 24.1255 +      &interaction.mq.tarball.newsource;
 24.1256 +
 24.1257 +      <para id="x_43b">The pipeline starting with <command role="hg-cmd">hg
 24.1258 +	  locate</command> above deletes all files in the working
 24.1259 +	directory, so that <command role="hg-cmd">hg
 24.1260 +	  commit</command>'s <option
 24.1261 +	  role="hg-opt-commit">--addremove</option> option can
 24.1262 +	actually tell which files have really been removed in the
 24.1263 +	newer version of the source.</para>
 24.1264 +
 24.1265 +      <para id="x_43c">Finally, you can apply your patches on top of the new
 24.1266 +	tree.</para>
 24.1267 +
 24.1268 +      &interaction.mq.tarball.repush;
 24.1269 +    </sect2>
 24.1270 +
 24.1271 +    <sect2 id="sec:mq:combine">
 24.1272 +      <title>Combining entire patches</title>
 24.1273 +
 24.1274 +      <para id="x_43d">MQ provides a command, <command
 24.1275 +	  role="hg-ext-mq">qfold</command> that lets you combine
 24.1276 +	entire patches.  This <quote>folds</quote> the patches you
 24.1277 +	name, in the order you name them, into the topmost applied
 24.1278 +	patch, and concatenates their descriptions onto the end of its
 24.1279 +	description.  The patches that you fold must be unapplied
 24.1280 +	before you fold them.</para>
 24.1281 +
 24.1282 +      <para id="x_43e">The order in which you fold patches matters.  If your
 24.1283 +	topmost applied patch is <literal>foo</literal>, and you
 24.1284 +	<command role="hg-ext-mq">qfold</command>
 24.1285 +	<literal>bar</literal> and <literal>quux</literal> into it,
 24.1286 +	you will end up with a patch that has the same effect as if
 24.1287 +	you applied first <literal>foo</literal>, then
 24.1288 +	<literal>bar</literal>, followed by
 24.1289 +	<literal>quux</literal>.</para>
 24.1290 +    </sect2>
 24.1291 +
 24.1292 +    <sect2>
 24.1293 +      <title>Merging part of one patch into another</title>
 24.1294 +
 24.1295 +      <para id="x_43f">Merging <emphasis>part</emphasis> of one patch into
 24.1296 +	another is more difficult than combining entire
 24.1297 +	patches.</para>
 24.1298 +
 24.1299 +      <para id="x_440">If you want to move changes to entire files, you can use
 24.1300 +	<command>filterdiff</command>'s <option
 24.1301 +	  role="cmd-opt-filterdiff">-i</option> and <option
 24.1302 +	  role="cmd-opt-filterdiff">-x</option> options to choose the
 24.1303 +	modifications to snip out of one patch, concatenating its
 24.1304 +	output onto the end of the patch you want to merge into.  You
 24.1305 +	usually won't need to modify the patch you've merged the
 24.1306 +	changes from.  Instead, MQ will report some rejected hunks
 24.1307 +	when you <command role="hg-ext-mq">qpush</command> it (from
 24.1308 +	the hunks you moved into the other patch), and you can simply
 24.1309 +	<command role="hg-ext-mq">qrefresh</command> the patch to drop
 24.1310 +	the duplicate hunks.</para>
 24.1311 +
 24.1312 +      <para id="x_441">If you have a patch that has multiple hunks modifying a
 24.1313 +	file, and you only want to move a few of those hunks, the job
 24.1314 +	becomes more messy, but you can still partly automate it.  Use
 24.1315 +	<command>lsdiff -nvv</command> to print some metadata about
 24.1316 +	the patch.</para>
 24.1317 +
 24.1318 +      &interaction.mq.tools.lsdiff;
 24.1319 +
 24.1320 +      <para id="x_442">This command prints three different kinds of
 24.1321 +	number:</para>
 24.1322 +      <itemizedlist>
 24.1323 +	<listitem><para id="x_443">(in the first column) a <emphasis>file
 24.1324 +	      number</emphasis> to identify each file modified in the
 24.1325 +	    patch;</para>
 24.1326 +	</listitem>
 24.1327 +	<listitem><para id="x_444">(on the next line, indented) the line number
 24.1328 +	    within a modified file where a hunk starts; and</para>
 24.1329 +	</listitem>
 24.1330 +	<listitem><para id="x_445">(on the same line) a <emphasis>hunk
 24.1331 +	      number</emphasis> to identify that hunk.</para>
 24.1332 +	</listitem></itemizedlist>
 24.1333 +
 24.1334 +      <para id="x_446">You'll have to use some visual inspection, and reading of
 24.1335 +	the patch, to identify the file and hunk numbers you'll want,
 24.1336 +	but you can then pass them to to
 24.1337 +	<command>filterdiff</command>'s <option
 24.1338 +	  role="cmd-opt-filterdiff">--files</option> and <option
 24.1339 +	  role="cmd-opt-filterdiff">--hunks</option> options, to
 24.1340 +	select exactly the file and hunk you want to extract.</para>
 24.1341 +
 24.1342 +      <para id="x_447">Once you have this hunk, you can concatenate it onto the
 24.1343 +	end of your destination patch and continue with the remainder
 24.1344 +	of <xref linkend="sec:mq:combine"/>.</para>
 24.1345 +
 24.1346 +    </sect2>
 24.1347 +  </sect1>
 24.1348 +  <sect1>
 24.1349 +    <title>Differences between quilt and MQ</title>
 24.1350 +
 24.1351 +    <para id="x_448">If you are already familiar with quilt, MQ provides a
 24.1352 +      similar command set.  There are a few differences in the way
 24.1353 +      that it works.</para>
 24.1354 +
 24.1355 +    <para id="x_449">You will already have noticed that most quilt commands have
 24.1356 +      MQ counterparts that simply begin with a
 24.1357 +      <quote><literal>q</literal></quote>.  The exceptions are quilt's
 24.1358 +      <literal>add</literal> and <literal>remove</literal> commands,
 24.1359 +      the counterparts for which are the normal Mercurial <command
 24.1360 +	role="hg-cmd">hg add</command> and <command role="hg-cmd">hg
 24.1361 +	remove</command> commands.  There is no MQ equivalent of the
 24.1362 +      quilt <literal>edit</literal> command.</para>
 24.1363 +
 24.1364 +  </sect1>
 24.1365 +</chapter>
 24.1366 +
 24.1367 +<!--
 24.1368 +local variables: 
 24.1369 +sgml-parent-document: ("00book.xml" "book" "chapter")
 24.1370 +end:
 24.1371 +-->
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/fr/ch13-mq-collab.xml	Sat Jul 10 06:24:49 2010 +0100
    25.3 @@ -0,0 +1,525 @@
    25.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
    25.5 +
    25.6 +<chapter id="chap:mq-collab">
    25.7 +  <?dbhtml filename="advanced-uses-of-mercurial-queues.html"?>
    25.8 +  <title>Advanced uses of Mercurial Queues</title>
    25.9 +
   25.10 +  <para id="x_15d">While it's easy to pick up straightforward uses of Mercurial
   25.11 +    Queues, use of a little discipline and some of MQ's less
   25.12 +    frequently used capabilities makes it possible to work in
   25.13 +    complicated development environments.</para>
   25.14 +
   25.15 +  <para id="x_15e">In this chapter, I will use as an example a technique I have
   25.16 +    used to manage the development of an Infiniband device driver for
   25.17 +    the Linux kernel.  The driver in question is large (at least as
   25.18 +    drivers go), with 25,000 lines of code spread across 35 source
   25.19 +    files.  It is maintained by a small team of developers.</para>
   25.20 +
   25.21 +  <para id="x_15f">While much of the material in this chapter is specific to
   25.22 +    Linux, the same principles apply to any code base for which you're
   25.23 +    not the primary owner, and upon which you need to do a lot of
   25.24 +    development.</para>
   25.25 +
   25.26 +  <sect1>
   25.27 +    <title>The problem of many targets</title>
   25.28 +
   25.29 +    <para id="x_160">The Linux kernel changes rapidly, and has never been
   25.30 +      internally stable; developers frequently make drastic changes
   25.31 +      between releases. This means that a version of the driver that
   25.32 +      works well with a particular released version of the kernel will
   25.33 +      not even <emphasis>compile</emphasis> correctly against,
   25.34 +      typically, any other version.</para>
   25.35 +
   25.36 +    <para id="x_161">To maintain a driver, we have to keep a number of distinct
   25.37 +      versions of Linux in mind.</para>
   25.38 +    <itemizedlist>
   25.39 +      <listitem><para id="x_162">One target is the main Linux kernel development
   25.40 +	  tree. Maintenance of the code is in this case partly shared
   25.41 +	  by other developers in the kernel community, who make
   25.42 +	  <quote>drive-by</quote> modifications to the driver as they
   25.43 +	  develop and refine kernel subsystems.</para>
   25.44 +      </listitem>
   25.45 +      <listitem><para id="x_163">We also maintain a number of
   25.46 +	  <quote>backports</quote> to older versions of the Linux
   25.47 +	  kernel, to support the needs of customers who are running
   25.48 +	  older Linux distributions that do not incorporate our
   25.49 +	  drivers.  (To <emphasis>backport</emphasis> a piece of code
   25.50 +	  is to modify it to work in an older version of its target
   25.51 +	  environment than the version it was developed for.)</para>
   25.52 +      </listitem>
   25.53 +      <listitem><para id="x_164">Finally, we make software releases on a schedule
   25.54 +	  that is necessarily not aligned with those used by Linux
   25.55 +	  distributors and kernel developers, so that we can deliver
   25.56 +	  new features to customers without forcing them to upgrade
   25.57 +	  their entire kernels or distributions.</para>
   25.58 +      </listitem></itemizedlist>
   25.59 +
   25.60 +    <sect2>
   25.61 +      <title>Tempting approaches that don't work well</title>
   25.62 +
   25.63 +      <para id="x_165">There are two <quote>standard</quote> ways to maintain a
   25.64 +	piece of software that has to target many different
   25.65 +	environments.</para>
   25.66 +
   25.67 +      <para id="x_166">The first is to maintain a number of branches, each
   25.68 +	intended for a single target.  The trouble with this approach
   25.69 +	is that you must maintain iron discipline in the flow of
   25.70 +	changes between repositories. A new feature or bug fix must
   25.71 +	start life in a <quote>pristine</quote> repository, then
   25.72 +	percolate out to every backport repository.  Backport changes
   25.73 +	are more limited in the branches they should propagate to; a
   25.74 +	backport change that is applied to a branch where it doesn't
   25.75 +	belong will probably stop the driver from compiling.</para>
   25.76 +
   25.77 +      <para id="x_167">The second is to maintain a single source tree filled with
   25.78 +	conditional statements that turn chunks of code on or off
   25.79 +	depending on the intended target.  Because these
   25.80 +	<quote>ifdefs</quote> are not allowed in the Linux kernel
   25.81 +	tree, a manual or automatic process must be followed to strip
   25.82 +	them out and yield a clean tree.  A code base maintained in
   25.83 +	this fashion rapidly becomes a rat's nest of conditional
   25.84 +	blocks that are difficult to understand and maintain.</para>
   25.85 +
   25.86 +      <para id="x_168">Neither of these approaches is well suited to a situation
   25.87 +	where you don't <quote>own</quote> the canonical copy of a
   25.88 +	source tree.  In the case of a Linux driver that is
   25.89 +	distributed with the standard kernel, Linus's tree contains
   25.90 +	the copy of the code that will be treated by the world as
   25.91 +	canonical.  The upstream version of <quote>my</quote> driver
   25.92 +	can be modified by people I don't know, without me even
   25.93 +	finding out about it until after the changes show up in
   25.94 +	Linus's tree.</para>
   25.95 +
   25.96 +      <para id="x_169">These approaches have the added weakness of making it
   25.97 +	difficult to generate well-formed patches to submit
   25.98 +	upstream.</para>
   25.99 +
  25.100 +      <para id="x_16a">In principle, Mercurial Queues seems like a good candidate
  25.101 +	to manage a development scenario such as the above.  While
  25.102 +	this is indeed the case, MQ contains a few added features that
  25.103 +	make the job more pleasant.</para>
  25.104 +
  25.105 +    </sect2>
  25.106 +  </sect1>
  25.107 +  <sect1>
  25.108 +    <title>Conditionally applying patches with guards</title>
  25.109 +
  25.110 +    <para id="x_16b">Perhaps the best way to maintain sanity with so many targets
  25.111 +      is to be able to choose specific patches to apply for a given
  25.112 +      situation.  MQ provides a feature called <quote>guards</quote>
  25.113 +      (which originates with quilt's <literal>guards</literal>
  25.114 +      command) that does just this.  To start off, let's create a
  25.115 +      simple repository for experimenting in.</para>
  25.116 +
  25.117 +    &interaction.mq.guards.init;
  25.118 +
  25.119 +    <para id="x_16c">This gives us a tiny repository that contains two patches
  25.120 +      that don't have any dependencies on each other, because they
  25.121 +      touch different files.</para>
  25.122 +
  25.123 +    <para id="x_16d">The idea behind conditional application is that you can
  25.124 +      <quote>tag</quote> a patch with a <emphasis>guard</emphasis>,
  25.125 +      which is simply a text string of your choosing, then tell MQ to
  25.126 +      select specific guards to use when applying patches.  MQ will
  25.127 +      then either apply, or skip over, a guarded patch, depending on
  25.128 +      the guards that you have selected.</para>
  25.129 +
  25.130 +    <para id="x_16e">A patch can have an arbitrary number of guards; each one is
  25.131 +      <emphasis>positive</emphasis> (<quote>apply this patch if this
  25.132 +	guard is selected</quote>) or <emphasis>negative</emphasis>
  25.133 +      (<quote>skip this patch if this guard is selected</quote>).  A
  25.134 +      patch with no guards is always applied.</para>
  25.135 +
  25.136 +  </sect1>
  25.137 +  <sect1>
  25.138 +    <title>Controlling the guards on a patch</title>
  25.139 +
  25.140 +    <para id="x_16f">The <command role="hg-ext-mq">qguard</command> command lets
  25.141 +      you determine which guards should apply to a patch, or display
  25.142 +      the guards that are already in effect. Without any arguments, it
  25.143 +      displays the guards on the current topmost patch.</para>
  25.144 +
  25.145 +      &interaction.mq.guards.qguard;
  25.146 +
  25.147 +    <para id="x_170">To set a positive guard on a patch, prefix the name of the
  25.148 +      guard with a <quote><literal>+</literal></quote>.</para>
  25.149 +
  25.150 +      &interaction.mq.guards.qguard.pos;
  25.151 +
  25.152 +    <para id="x_171">To set a negative guard
  25.153 +      on a patch, prefix the name of the guard with a
  25.154 +      <quote><literal>-</literal></quote>.</para>
  25.155 +
  25.156 +    &interaction.mq.guards.qguard.neg;
  25.157 +
  25.158 +    <para id="x_74a">Notice that we prefixed the arguments to the <command>hg
  25.159 +	qguard</command> command with a <literal>--</literal> here, so
  25.160 +      that Mercurial would not interpret the text
  25.161 +      <literal>-quux</literal> as an option.</para>
  25.162 +
  25.163 +    <note>
  25.164 +      <title>Setting vs. modifying</title>
  25.165 +
  25.166 +      <para id="x_172">  The <command role="hg-ext-mq">qguard</command> command
  25.167 +	<emphasis>sets</emphasis> the guards on a patch; it doesn't
  25.168 +	<emphasis>modify</emphasis> them.  What this means is that if
  25.169 +	you run <command role="hg-cmd">hg qguard +a +b</command> on a
  25.170 +	patch, then <command role="hg-cmd">hg qguard +c</command> on
  25.171 +	the same patch, the <emphasis>only</emphasis> guard that will
  25.172 +	be set on it afterwards is <literal>+c</literal>.</para>
  25.173 +    </note>
  25.174 +
  25.175 +    <para id="x_173">Mercurial stores guards in the <filename
  25.176 +	role="special">series</filename> file; the form in which they
  25.177 +      are stored is easy both to understand and to edit by hand. (In
  25.178 +      other words, you don't have to use the <command
  25.179 +	role="hg-ext-mq">qguard</command> command if you don't want
  25.180 +      to; it's okay to simply edit the <filename
  25.181 +	role="special">series</filename> file.)</para>
  25.182 +
  25.183 +    &interaction.mq.guards.series;
  25.184 +
  25.185 +  </sect1>
  25.186 +  <sect1>
  25.187 +    <title>Selecting the guards to use</title>
  25.188 +
  25.189 +    <para id="x_174">The <command role="hg-ext-mq">qselect</command> command
  25.190 +      determines which guards are active at a given time.  The effect
  25.191 +      of this is to determine which patches MQ will apply the next
  25.192 +      time you run <command role="hg-ext-mq">qpush</command>.  It has
  25.193 +      no other effect; in particular, it doesn't do anything to
  25.194 +      patches that are already applied.</para>
  25.195 +
  25.196 +    <para id="x_175">With no arguments, the <command
  25.197 +	role="hg-ext-mq">qselect</command> command lists the guards
  25.198 +      currently in effect, one per line of output.  Each argument is
  25.199 +      treated as the name of a guard to apply.</para>
  25.200 +
  25.201 +      &interaction.mq.guards.qselect.foo;
  25.202 +
  25.203 +    <para id="x_176">In case you're interested, the currently selected guards are
  25.204 +      stored in the <filename role="special">guards</filename> file.</para>
  25.205 +
  25.206 +    &interaction.mq.guards.qselect.cat;
  25.207 +
  25.208 +    <para id="x_177">We can see the effect the selected guards have when we run
  25.209 +      <command role="hg-ext-mq">qpush</command>.</para>
  25.210 +
  25.211 +    &interaction.mq.guards.qselect.qpush;
  25.212 +
  25.213 +    <para id="x_178">A guard cannot start with a
  25.214 +      <quote><literal>+</literal></quote> or
  25.215 +      <quote><literal>-</literal></quote> character.  The name of a
  25.216 +      guard must not contain white space, but most other characters
  25.217 +      are acceptable.  If you try to use a guard with an invalid name,
  25.218 +      MQ will complain:</para>
  25.219 +
  25.220 +    &interaction.mq.guards.qselect.error;
  25.221 +      
  25.222 +    <para id="x_179">Changing the selected guards changes the patches that are
  25.223 +      applied.</para>
  25.224 +
  25.225 +    &interaction.mq.guards.qselect.quux;
  25.226 +
  25.227 +    <para id="x_17a">You can see in the example below that negative guards take
  25.228 +      precedence over positive guards.</para>
  25.229 +
  25.230 +    &interaction.mq.guards.qselect.foobar;
  25.231 +
  25.232 +  </sect1>
  25.233 +  <sect1>
  25.234 +    <title>MQ's rules for applying patches</title>
  25.235 +
  25.236 +    <para id="x_17b">The rules that MQ uses when deciding whether to apply a
  25.237 +      patch are as follows.</para>
  25.238 +    <itemizedlist>
  25.239 +      <listitem><para id="x_17c">A patch that has no guards is always
  25.240 +	  applied.</para>
  25.241 +      </listitem>
  25.242 +      <listitem><para id="x_17d">If the patch has any negative guard that matches
  25.243 +	  any currently selected guard, the patch is skipped.</para>
  25.244 +      </listitem>
  25.245 +      <listitem><para id="x_17e">If the patch has any positive guard that matches
  25.246 +	  any currently selected guard, the patch is applied.</para>
  25.247 +      </listitem>
  25.248 +      <listitem><para id="x_17f">If the patch has positive or negative guards,
  25.249 +	  but none matches any currently selected guard, the patch is
  25.250 +	  skipped.</para>
  25.251 +      </listitem></itemizedlist>
  25.252 +
  25.253 +  </sect1>
  25.254 +  <sect1>
  25.255 +    <title>Trimming the work environment</title>
  25.256 +
  25.257 +    <para id="x_180">In working on the device driver I mentioned earlier, I don't
  25.258 +      apply the patches to a normal Linux kernel tree.  Instead, I use
  25.259 +      a repository that contains only a snapshot of the source files
  25.260 +      and headers that are relevant to Infiniband development.  This
  25.261 +      repository is 1% the size of a kernel repository, so it's easier
  25.262 +      to work with.</para>
  25.263 +
  25.264 +    <para id="x_181">I then choose a <quote>base</quote> version on top of which
  25.265 +      the patches are applied.  This is a snapshot of the Linux kernel
  25.266 +      tree as of a revision of my choosing.  When I take the snapshot,
  25.267 +      I record the changeset ID from the kernel repository in the
  25.268 +      commit message.  Since the snapshot preserves the
  25.269 +      <quote>shape</quote> and content of the relevant parts of the
  25.270 +      kernel tree, I can apply my patches on top of either my tiny
  25.271 +      repository or a normal kernel tree.</para>
  25.272 +
  25.273 +    <para id="x_182">Normally, the base tree atop which the patches apply should
  25.274 +      be a snapshot of a very recent upstream tree.  This best
  25.275 +      facilitates the development of patches that can easily be
  25.276 +      submitted upstream with few or no modifications.</para>
  25.277 +
  25.278 +  </sect1>
  25.279 +  <sect1>
  25.280 +    <title>Dividing up the <filename role="special">series</filename>
  25.281 +      file</title>
  25.282 +
  25.283 +    <para id="x_183">I categorise the patches in the <filename
  25.284 +	role="special">series</filename> file into a number of logical
  25.285 +      groups.  Each section of like patches begins with a block of
  25.286 +      comments that describes the purpose of the patches that
  25.287 +      follow.</para>
  25.288 +
  25.289 +    <para id="x_184">The sequence of patch groups that I maintain follows.  The
  25.290 +      ordering of these groups is important; I'll describe why after I
  25.291 +      introduce the groups.</para>
  25.292 +    <itemizedlist>
  25.293 +      <listitem><para id="x_185">The <quote>accepted</quote> group.  Patches that
  25.294 +	  the development team has submitted to the maintainer of the
  25.295 +	  Infiniband subsystem, and which he has accepted, but which
  25.296 +	  are not present in the snapshot that the tiny repository is
  25.297 +	  based on.  These are <quote>read only</quote> patches,
  25.298 +	  present only to transform the tree into a similar state as
  25.299 +	  it is in the upstream maintainer's repository.</para>
  25.300 +      </listitem>
  25.301 +      <listitem><para id="x_186">The <quote>rework</quote> group.  Patches that I
  25.302 +	  have submitted, but that the upstream maintainer has
  25.303 +	  requested modifications to before he will accept
  25.304 +	  them.</para>
  25.305 +      </listitem>
  25.306 +      <listitem><para id="x_187">The <quote>pending</quote> group.  Patches that
  25.307 +	  I have not yet submitted to the upstream maintainer, but
  25.308 +	  which we have finished working on. These will be <quote>read
  25.309 +	    only</quote> for a while.  If the upstream maintainer
  25.310 +	  accepts them upon submission, I'll move them to the end of
  25.311 +	  the <quote>accepted</quote> group.  If he requests that I
  25.312 +	  modify any, I'll move them to the beginning of the
  25.313 +	  <quote>rework</quote> group.</para>
  25.314 +      </listitem>
  25.315 +      <listitem><para id="x_188">The <quote>in progress</quote> group.  Patches
  25.316 +	  that are actively being developed, and should not be
  25.317 +	  submitted anywhere yet.</para>
  25.318 +      </listitem>
  25.319 +      <listitem><para id="x_189">The <quote>backport</quote> group.  Patches that
  25.320 +	  adapt the source tree to older versions of the kernel
  25.321 +	  tree.</para>
  25.322 +      </listitem>
  25.323 +      <listitem><para id="x_18a">The <quote>do not ship</quote> group.  Patches
  25.324 +	  that for some reason should never be submitted upstream.
  25.325 +	  For example, one such patch might change embedded driver
  25.326 +	  identification strings to make it easier to distinguish, in
  25.327 +	  the field, between an out-of-tree version of the driver and
  25.328 +	  a version shipped by a distribution vendor.</para>
  25.329 +      </listitem></itemizedlist>
  25.330 +
  25.331 +    <para id="x_18b">Now to return to the reasons for ordering groups of patches
  25.332 +      in this way.  We would like the lowest patches in the stack to
  25.333 +      be as stable as possible, so that we will not need to rework
  25.334 +      higher patches due to changes in context.  Putting patches that
  25.335 +      will never be changed first in the <filename
  25.336 +	role="special">series</filename> file serves this
  25.337 +      purpose.</para>
  25.338 +
  25.339 +    <para id="x_18c">We would also like the patches that we know we'll need to
  25.340 +      modify to be applied on top of a source tree that resembles the
  25.341 +      upstream tree as closely as possible.  This is why we keep
  25.342 +      accepted patches around for a while.</para>
  25.343 +
  25.344 +    <para id="x_18d">The <quote>backport</quote> and <quote>do not ship</quote>
  25.345 +      patches float at the end of the <filename
  25.346 +	role="special">series</filename> file.  The backport patches
  25.347 +      must be applied on top of all other patches, and the <quote>do
  25.348 +	not ship</quote> patches might as well stay out of harm's
  25.349 +      way.</para>
  25.350 +
  25.351 +  </sect1>
  25.352 +  <sect1>
  25.353 +    <title>Maintaining the patch series</title>
  25.354 +
  25.355 +    <para id="x_18e">In my work, I use a number of guards to control which
  25.356 +      patches are to be applied.</para>
  25.357 +
  25.358 +    <itemizedlist>
  25.359 +      <listitem><para id="x_18f"><quote>Accepted</quote> patches are guarded with
  25.360 +	  <literal>accepted</literal>.  I enable this guard most of
  25.361 +	  the time.  When I'm applying the patches on top of a tree
  25.362 +	  where the patches are already present, I can turn this patch
  25.363 +	  off, and the patches that follow it will apply
  25.364 +	  cleanly.</para>
  25.365 +      </listitem>
  25.366 +      <listitem><para id="x_190">Patches that are <quote>finished</quote>, but
  25.367 +	  not yet submitted, have no guards.  If I'm applying the
  25.368 +	  patch stack to a copy of the upstream tree, I don't need to
  25.369 +	  enable any guards in order to get a reasonably safe source
  25.370 +	  tree.</para>
  25.371 +      </listitem>
  25.372 +      <listitem><para id="x_191">Those patches that need reworking before being
  25.373 +	  resubmitted are guarded with
  25.374 +	  <literal>rework</literal>.</para>
  25.375 +      </listitem>
  25.376 +      <listitem><para id="x_192">For those patches that are still under
  25.377 +	  development, I use <literal>devel</literal>.</para>
  25.378 +      </listitem>
  25.379 +      <listitem><para id="x_193">A backport patch may have several guards, one
  25.380 +	  for each version of the kernel to which it applies.  For
  25.381 +	  example, a patch that backports a piece of code to 2.6.9
  25.382 +	  will have a <literal>2.6.9</literal> guard.</para>
  25.383 +      </listitem></itemizedlist>
  25.384 +    <para id="x_194">This variety of guards gives me considerable flexibility in
  25.385 +      determining what kind of source tree I want to end up with.  For
  25.386 +      most situations, the selection of appropriate guards is
  25.387 +      automated during the build process, but I can manually tune the
  25.388 +      guards to use for less common circumstances.</para>
  25.389 +
  25.390 +    <sect2>
  25.391 +      <title>The art of writing backport patches</title>
  25.392 +
  25.393 +      <para id="x_195">Using MQ, writing a backport patch is a simple process.
  25.394 +	All such a patch has to do is modify a piece of code that uses
  25.395 +	a kernel feature not present in the older version of the
  25.396 +	kernel, so that the driver continues to work correctly under
  25.397 +	that older version.</para>
  25.398 +
  25.399 +      <para id="x_196">A useful goal when writing a good backport patch is to
  25.400 +	make your code look as if it was written for the older version
  25.401 +	of the kernel you're targeting.  The less obtrusive the patch,
  25.402 +	the easier it will be to understand and maintain.  If you're
  25.403 +	writing a collection of backport patches to avoid the
  25.404 +	<quote>rat's nest</quote> effect of lots of
  25.405 +	<literal>#ifdef</literal>s (hunks of source code that are only
  25.406 +	used conditionally) in your code, don't introduce
  25.407 +	version-dependent <literal>#ifdef</literal>s into the patches.
  25.408 +	Instead, write several patches, each of which makes
  25.409 +	unconditional changes, and control their application using
  25.410 +	guards.</para>
  25.411 +
  25.412 +      <para id="x_197">There are two reasons to divide backport patches into a
  25.413 +	distinct group, away from the <quote>regular</quote> patches
  25.414 +	whose effects they modify. The first is that intermingling the
  25.415 +	two makes it more difficult to use a tool like the <literal
  25.416 +	  role="hg-ext">patchbomb</literal> extension to automate the
  25.417 +	process of submitting the patches to an upstream maintainer.
  25.418 +	The second is that a backport patch could perturb the context
  25.419 +	in which a subsequent regular patch is applied, making it
  25.420 +	impossible to apply the regular patch cleanly
  25.421 +	<emphasis>without</emphasis> the earlier backport patch
  25.422 +	already being applied.</para>
  25.423 +
  25.424 +    </sect2>
  25.425 +  </sect1>
  25.426 +  <sect1>
  25.427 +    <title>Useful tips for developing with MQ</title>
  25.428 +
  25.429 +    <sect2>
  25.430 +      <title>Organising patches in directories</title>
  25.431 +
  25.432 +      <para id="x_198">If you're working on a substantial project with MQ, it's
  25.433 +	not difficult to accumulate a large number of patches.  For
  25.434 +	example, I have one patch repository that contains over 250
  25.435 +	patches.</para>
  25.436 +
  25.437 +      <para id="x_199">If you can group these patches into separate logical
  25.438 +	categories, you can if you like store them in different
  25.439 +	directories; MQ has no problems with patch names that contain
  25.440 +	path separators.</para>
  25.441 +
  25.442 +    </sect2>
  25.443 +    <sect2 id="mq-collab:tips:interdiff">
  25.444 +      <title>Viewing the history of a patch</title>
  25.445 +
  25.446 +      <para id="x_19a">If you're developing a set of patches over a long time,
  25.447 +	it's a good idea to maintain them in a repository, as
  25.448 +	discussed in <xref linkend="sec:mq:repo"/>.  If you do
  25.449 +	so, you'll quickly
  25.450 +	discover that using the <command role="hg-cmd">hg
  25.451 +	  diff</command> command to look at the history of changes to
  25.452 +	a patch is unworkable.  This is in part because you're looking
  25.453 +	at the second derivative of the real code (a diff of a diff),
  25.454 +	but also because MQ adds noise to the process by modifying
  25.455 +	time stamps and directory names when it updates a
  25.456 +	patch.</para>
  25.457 +
  25.458 +      <para id="x_19b">However, you can use the <literal
  25.459 +	  role="hg-ext">extdiff</literal> extension, which is bundled
  25.460 +	with Mercurial, to turn a diff of two versions of a patch into
  25.461 +	something readable.  To do this, you will need a third-party
  25.462 +	package called <literal role="package">patchutils</literal>
  25.463 +	<citation>web:patchutils</citation>.  This provides a command
  25.464 +	named <command>interdiff</command>, which shows the
  25.465 +	differences between two diffs as a diff.  Used on two versions
  25.466 +	of the same diff, it generates a diff that represents the diff
  25.467 +	from the first to the second version.</para>
  25.468 +
  25.469 +      <para id="x_19c">You can enable the <literal
  25.470 +	  role="hg-ext">extdiff</literal> extension in the usual way,
  25.471 +	by adding a line to the <literal
  25.472 +	  role="rc-extensions">extensions</literal> section of your
  25.473 +	<filename role="special">~/.hgrc</filename>.</para>
  25.474 +      <programlisting>[extensions]
  25.475 +extdiff =</programlisting>
  25.476 +      <para id="x_19d">The <command>interdiff</command> command expects to be
  25.477 +	passed the names of two files, but the <literal
  25.478 +	  role="hg-ext">extdiff</literal> extension passes the program
  25.479 +	it runs a pair of directories, each of which can contain an
  25.480 +	arbitrary number of files.  We thus need a small program that
  25.481 +	will run <command>interdiff</command> on each pair of files in
  25.482 +	these two directories.  This program is available as <filename
  25.483 +	  role="special">hg-interdiff</filename> in the <filename
  25.484 +	  class="directory">examples</filename> directory of the
  25.485 +	source code repository that accompanies this book. <!--
  25.486 +	&example.hg-interdiff; --></para>
  25.487 +
  25.488 +      <para id="x_19e">With the <filename role="special">hg-interdiff</filename>
  25.489 +	program in your shell's search path, you can run it as
  25.490 +	follows, from inside an MQ patch directory:</para>
  25.491 +      <programlisting>hg extdiff -p hg-interdiff -r A:B my-change.patch</programlisting>
  25.492 +      <para id="x_19f">Since you'll probably want to use this long-winded command
  25.493 +	a lot, you can get <literal role="hg-ext">hgext</literal> to
  25.494 +	make it available as a normal Mercurial command, again by
  25.495 +	editing your <filename
  25.496 +	  role="special">~/.hgrc</filename>.</para>
  25.497 +      <programlisting>[extdiff]
  25.498 +cmd.interdiff = hg-interdiff</programlisting>
  25.499 +      <para id="x_1a0">This directs <literal role="hg-ext">hgext</literal> to
  25.500 +	make an <literal>interdiff</literal> command available, so you
  25.501 +	can now shorten the previous invocation of <command
  25.502 +	  role="hg-ext-extdiff">extdiff</command> to something a
  25.503 +	little more wieldy.</para>
  25.504 +      <programlisting>hg interdiff -r A:B my-change.patch</programlisting>
  25.505 +
  25.506 +      <note>
  25.507 +	<para id="x_1a1">  The <command>interdiff</command> command works well
  25.508 +	  only if the underlying files against which versions of a
  25.509 +	  patch are generated remain the same.  If you create a patch,
  25.510 +	  modify the underlying files, and then regenerate the patch,
  25.511 +	  <command>interdiff</command> may not produce useful
  25.512 +	  output.</para>
  25.513 +      </note>
  25.514 +
  25.515 +      <para id="x_1a2">The <literal role="hg-ext">extdiff</literal> extension is
  25.516 +	useful for more than merely improving the presentation of MQ
  25.517 +	patches.  To read more about it, go to <xref
  25.518 +	  linkend="sec:hgext:extdiff"/>.</para>
  25.519 +
  25.520 +    </sect2>
  25.521 +  </sect1>
  25.522 +</chapter>
  25.523 +
  25.524 +<!--
  25.525 +local variables: 
  25.526 +sgml-parent-document: ("00book.xml" "book" "chapter")
  25.527 +end:
  25.528 +-->
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/fr/ch14-hgext.xml	Sat Jul 10 06:24:49 2010 +0100
    26.3 @@ -0,0 +1,554 @@
    26.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
    26.5 +
    26.6 +<chapter id="chap:hgext">
    26.7 +  <?dbhtml filename="adding-functionality-with-extensions.html"?>
    26.8 +  <title>Adding functionality with extensions</title>
    26.9 +
   26.10 +  <para id="x_4fe">While the core of Mercurial is quite complete from a
   26.11 +    functionality standpoint, it's deliberately shorn of fancy
   26.12 +    features.  This approach of preserving simplicity keeps the
   26.13 +    software easy to deal with for both maintainers and users.</para>
   26.14 +
   26.15 +  <para id="x_4ff">However, Mercurial doesn't box you in with an inflexible
   26.16 +    command set: you can add features to it as
   26.17 +    <emphasis>extensions</emphasis> (sometimes known as
   26.18 +    <emphasis>plugins</emphasis>).  We've already discussed a few of
   26.19 +    these extensions in earlier chapters.</para>
   26.20 +  <itemizedlist>
   26.21 +    <listitem><para id="x_500"><xref linkend="sec:tour-merge:fetch"/>
   26.22 +	covers the <literal role="hg-ext">fetch</literal> extension;
   26.23 +	this combines pulling new changes and merging them with local
   26.24 +	changes into a single command, <command
   26.25 +	  role="hg-ext-fetch">fetch</command>.</para>
   26.26 +    </listitem>
   26.27 +    <listitem><para id="x_501">In <xref linkend="chap:hook"/>, we covered
   26.28 +	several extensions that are useful for hook-related
   26.29 +	functionality: <literal role="hg-ext">acl</literal> adds
   26.30 +	access control lists; <literal
   26.31 +	  role="hg-ext">bugzilla</literal> adds integration with the
   26.32 +	Bugzilla bug tracking system; and <literal
   26.33 +	  role="hg-ext">notify</literal> sends notification emails on
   26.34 +	new changes.</para>
   26.35 +    </listitem>
   26.36 +    <listitem><para id="x_502">The Mercurial Queues patch management extension is
   26.37 +	so invaluable that it merits two chapters and an appendix all
   26.38 +	to itself. <xref linkend="chap:mq"/> covers the
   26.39 +	basics; <xref
   26.40 +	  linkend="chap:mq-collab"/> discusses advanced topics;
   26.41 +	and <xref linkend="chap:mqref"/> goes into detail on
   26.42 +	each
   26.43 +	command.</para>
   26.44 +    </listitem></itemizedlist>
   26.45 +
   26.46 +  <para id="x_503">In this chapter, we'll cover some of the other extensions that
   26.47 +    are available for Mercurial, and briefly touch on some of the
   26.48 +    machinery you'll need to know about if you want to write an
   26.49 +    extension of your own.</para>
   26.50 +  <itemizedlist>
   26.51 +    <listitem><para id="x_504">In <xref linkend="sec:hgext:inotify"/>,
   26.52 +	we'll discuss the possibility of <emphasis>huge</emphasis>
   26.53 +	performance improvements using the <literal
   26.54 +	  role="hg-ext">inotify</literal> extension.</para>
   26.55 +    </listitem></itemizedlist>
   26.56 +
   26.57 +  <sect1 id="sec:hgext:inotify">
   26.58 +    <title>Improve performance with the <literal
   26.59 +	role="hg-ext">inotify</literal> extension</title>
   26.60 +
   26.61 +    <para id="x_505">Are you interested in having some of the most common
   26.62 +      Mercurial operations run as much as a hundred times faster?
   26.63 +      Read on!</para>
   26.64 +
   26.65 +    <para id="x_506">Mercurial has great performance under normal circumstances.
   26.66 +      For example, when you run the <command role="hg-cmd">hg
   26.67 +	status</command> command, Mercurial has to scan almost every
   26.68 +      directory and file in your repository so that it can display
   26.69 +      file status.  Many other Mercurial commands need to do the same
   26.70 +      work behind the scenes; for example, the <command
   26.71 +	role="hg-cmd">hg diff</command> command uses the status
   26.72 +      machinery to avoid doing an expensive comparison operation on
   26.73 +      files that obviously haven't changed.</para>
   26.74 +
   26.75 +    <para id="x_507">Because obtaining file status is crucial to good
   26.76 +      performance, the authors of Mercurial have optimised this code
   26.77 +      to within an inch of its life.  However, there's no avoiding the
   26.78 +      fact that when you run <command role="hg-cmd">hg
   26.79 +	status</command>, Mercurial is going to have to perform at
   26.80 +      least one expensive system call for each managed file to
   26.81 +      determine whether it's changed since the last time Mercurial
   26.82 +      checked.  For a sufficiently large repository, this can take a
   26.83 +      long time.</para>
   26.84 +
   26.85 +    <para id="x_508">To put a number on the magnitude of this effect, I created a
   26.86 +      repository containing 150,000 managed files.  I timed <command
   26.87 +	role="hg-cmd">hg status</command> as taking ten seconds to
   26.88 +      run, even when <emphasis>none</emphasis> of those files had been
   26.89 +      modified.</para>
   26.90 +
   26.91 +    <para id="x_509">Many modern operating systems contain a file notification
   26.92 +      facility. If a program signs up to an appropriate service, the
   26.93 +      operating system will notify it every time a file of interest is
   26.94 +      created, modified, or deleted.  On Linux systems, the kernel
   26.95 +      component that does this is called
   26.96 +      <literal>inotify</literal>.</para>
   26.97 +
   26.98 +    <para id="x_50a">Mercurial's <literal role="hg-ext">inotify</literal>
   26.99 +      extension talks to the kernel's <literal>inotify</literal>
  26.100 +      component to optimise <command role="hg-cmd">hg status</command>
  26.101 +      commands.  The extension has two components.  A daemon sits in
  26.102 +      the background and receives notifications from the
  26.103 +      <literal>inotify</literal> subsystem.  It also listens for
  26.104 +      connections from a regular Mercurial command.  The extension
  26.105 +      modifies Mercurial's behavior so that instead of scanning the
  26.106 +      filesystem, it queries the daemon.  Since the daemon has perfect
  26.107 +      information about the state of the repository, it can respond
  26.108 +      with a result instantaneously, avoiding the need to scan every
  26.109 +      directory and file in the repository.</para>
  26.110 +
  26.111 +    <para id="x_50b">Recall the ten seconds that I measured plain Mercurial as
  26.112 +      taking to run <command role="hg-cmd">hg status</command> on a
  26.113 +      150,000 file repository.  With the <literal
  26.114 +	role="hg-ext">inotify</literal> extension enabled, the time
  26.115 +      dropped to 0.1 seconds, a factor of <emphasis>one
  26.116 +	hundred</emphasis> faster.</para>
  26.117 +
  26.118 +    <para id="x_50c">Before we continue, please pay attention to some
  26.119 +      caveats.</para>
  26.120 +    <itemizedlist>
  26.121 +      <listitem><para id="x_50d">The <literal role="hg-ext">inotify</literal>
  26.122 +	  extension is Linux-specific.  Because it interfaces directly
  26.123 +	  to the Linux kernel's <literal>inotify</literal> subsystem,
  26.124 +	  it does not work on other operating systems.</para>
  26.125 +      </listitem>
  26.126 +      <listitem><para id="x_50e">It should work on any Linux distribution that
  26.127 +	  was released after early 2005.  Older distributions are
  26.128 +	  likely to have a kernel that lacks
  26.129 +	  <literal>inotify</literal>, or a version of
  26.130 +	  <literal>glibc</literal> that does not have the necessary
  26.131 +	  interfacing support.</para>
  26.132 +      </listitem>
  26.133 +      <listitem><para id="x_50f">Not all filesystems are suitable for use with
  26.134 +	  the <literal role="hg-ext">inotify</literal> extension.
  26.135 +	  Network filesystems such as NFS are a non-starter, for
  26.136 +	  example, particularly if you're running Mercurial on several
  26.137 +	  systems, all mounting the same network filesystem.  The
  26.138 +	  kernel's <literal>inotify</literal> system has no way of
  26.139 +	  knowing about changes made on another system.  Most local
  26.140 +	  filesystems (e.g. ext3, XFS, ReiserFS) should work
  26.141 +	  fine.</para>
  26.142 +      </listitem></itemizedlist>
  26.143 +
  26.144 +    <para id="x_510">The <literal role="hg-ext">inotify</literal> extension is
  26.145 +      not yet shipped with Mercurial as of May 2007, so it's a little
  26.146 +      more involved to set up than other extensions.  But the
  26.147 +      performance improvement is worth it!</para>
  26.148 +
  26.149 +    <para id="x_511">The extension currently comes in two parts: a set of patches
  26.150 +      to the Mercurial source code, and a library of Python bindings
  26.151 +      to the <literal>inotify</literal> subsystem.</para>
  26.152 +    <note>
  26.153 +      <para id="x_512">  There are <emphasis>two</emphasis> Python
  26.154 +	<literal>inotify</literal> binding libraries.  One of them is
  26.155 +	called <literal>pyinotify</literal>, and is packaged by some
  26.156 +	Linux distributions as <literal>python-inotify</literal>.
  26.157 +	This is <emphasis>not</emphasis> the one you'll need, as it is
  26.158 +	too buggy and inefficient to be practical.</para>
  26.159 +    </note>
  26.160 +    <para id="x_513">To get going, it's best to already have a functioning copy
  26.161 +      of Mercurial installed.</para>
  26.162 +    <note>
  26.163 +      <para id="x_514">  If you follow the instructions below, you'll be
  26.164 +	<emphasis>replacing</emphasis> and overwriting any existing
  26.165 +	installation of Mercurial that you might already have, using
  26.166 +	the latest <quote>bleeding edge</quote> Mercurial code. Don't
  26.167 +	say you weren't warned!</para>
  26.168 +    </note>
  26.169 +    <orderedlist>
  26.170 +      <listitem><para id="x_515">Clone the Python <literal>inotify</literal>
  26.171 +	  binding repository.  Build and install it.</para>
  26.172 +	<programlisting>hg clone http://hg.kublai.com/python/inotify
  26.173 +cd inotify
  26.174 +python setup.py build --force
  26.175 +sudo python setup.py install --skip-build</programlisting>
  26.176 +      </listitem>
  26.177 +      <listitem><para id="x_516">Clone the <filename
  26.178 +	    class="directory">crew</filename> Mercurial repository.
  26.179 +	  Clone the <literal role="hg-ext">inotify</literal> patch
  26.180 +	  repository so that Mercurial Queues will be able to apply
  26.181 +	  patches to your cope of the <filename
  26.182 +	    class="directory">crew</filename> repository.</para>
  26.183 +	<programlisting>hg clone http://hg.intevation.org/mercurial/crew
  26.184 +hg clone crew inotify
  26.185 +hg clone http://hg.kublai.com/mercurial/patches/inotify inotify/.hg/patches</programlisting>
  26.186 +      </listitem>
  26.187 +      <listitem><para id="x_517">Make sure that you have the Mercurial Queues
  26.188 +	  extension, <literal role="hg-ext">mq</literal>, enabled.  If
  26.189 +	  you've never used MQ, read <xref
  26.190 +	    linkend="sec:mq:start"/> to get started
  26.191 +	  quickly.</para>
  26.192 +      </listitem>
  26.193 +      <listitem><para id="x_518">Go into the <filename
  26.194 +	    class="directory">inotify</filename> repo, and apply all
  26.195 +	  of the <literal role="hg-ext">inotify</literal> patches
  26.196 +	  using the <option role="hg-ext-mq-cmd-qpush-opt">hg
  26.197 +	    -a</option> option to the <command
  26.198 +	    role="hg-ext-mq">qpush</command> command.</para>
  26.199 +	<programlisting>cd inotify
  26.200 +hg qpush -a</programlisting>
  26.201 +      </listitem>
  26.202 +      <listitem><para id="x_519">  If you get an error message from <command
  26.203 +	    role="hg-ext-mq">qpush</command>, you should not continue.
  26.204 +	  Instead, ask for help.</para>
  26.205 +      </listitem>
  26.206 +      <listitem><para id="x_51a">Build and install the patched version of
  26.207 +	  Mercurial.</para>
  26.208 +	<programlisting>python setup.py build --force
  26.209 +sudo python setup.py install --skip-build</programlisting>
  26.210 +      </listitem>
  26.211 +    </orderedlist>
  26.212 +    <para id="x_51b">Once you've build a suitably patched version of Mercurial,
  26.213 +      all you need to do to enable the <literal
  26.214 +	role="hg-ext">inotify</literal> extension is add an entry to
  26.215 +      your <filename role="special">~/.hgrc</filename>.</para>
  26.216 +    <programlisting>[extensions] inotify =</programlisting>
  26.217 +    <para id="x_51c">When the <literal role="hg-ext">inotify</literal> extension
  26.218 +      is enabled, Mercurial will automatically and transparently start
  26.219 +      the status daemon the first time you run a command that needs
  26.220 +      status in a repository.  It runs one status daemon per
  26.221 +      repository.</para>
  26.222 +
  26.223 +    <para id="x_51d">The status daemon is started silently, and runs in the
  26.224 +      background.  If you look at a list of running processes after
  26.225 +      you've enabled the <literal role="hg-ext">inotify</literal>
  26.226 +      extension and run a few commands in different repositories,
  26.227 +      you'll thus see a few <literal>hg</literal> processes sitting
  26.228 +      around, waiting for updates from the kernel and queries from
  26.229 +      Mercurial.</para>
  26.230 +
  26.231 +    <para id="x_51e">The first time you run a Mercurial command in a repository
  26.232 +      when you have the <literal role="hg-ext">inotify</literal>
  26.233 +      extension enabled, it will run with about the same performance
  26.234 +      as a normal Mercurial command.  This is because the status
  26.235 +      daemon needs to perform a normal status scan so that it has a
  26.236 +      baseline against which to apply later updates from the kernel.
  26.237 +      However, <emphasis>every</emphasis> subsequent command that does
  26.238 +      any kind of status check should be noticeably faster on
  26.239 +      repositories of even fairly modest size.  Better yet, the bigger
  26.240 +      your repository is, the greater a performance advantage you'll
  26.241 +      see.  The <literal role="hg-ext">inotify</literal> daemon makes
  26.242 +      status operations almost instantaneous on repositories of all
  26.243 +      sizes!</para>
  26.244 +
  26.245 +    <para id="x_51f">If you like, you can manually start a status daemon using
  26.246 +      the <command role="hg-ext-inotify">inserve</command> command.
  26.247 +      This gives you slightly finer control over how the daemon ought
  26.248 +      to run.  This command will of course only be available when the
  26.249 +      <literal role="hg-ext">inotify</literal> extension is
  26.250 +      enabled.</para>
  26.251 +
  26.252 +    <para id="x_520">When you're using the <literal
  26.253 +	role="hg-ext">inotify</literal> extension, you should notice
  26.254 +      <emphasis>no difference at all</emphasis> in Mercurial's
  26.255 +      behavior, with the sole exception of status-related commands
  26.256 +      running a whole lot faster than they used to.  You should
  26.257 +      specifically expect that commands will not print different
  26.258 +      output; neither should they give different results. If either of
  26.259 +      these situations occurs, please report a bug.</para>
  26.260 +
  26.261 +  </sect1>
  26.262 +  <sect1 id="sec:hgext:extdiff">
  26.263 +    <title>Flexible diff support with the <literal
  26.264 +	role="hg-ext">extdiff</literal> extension</title>
  26.265 +
  26.266 +    <para id="x_521">Mercurial's built-in <command role="hg-cmd">hg
  26.267 +	diff</command> command outputs plaintext unified diffs.</para>
  26.268 +
  26.269 +    &interaction.extdiff.diff;
  26.270 +
  26.271 +    <para id="x_522">If you would like to use an external tool to display
  26.272 +      modifications, you'll want to use the <literal
  26.273 +	role="hg-ext">extdiff</literal> extension.  This will let you
  26.274 +      use, for example, a graphical diff tool.</para>
  26.275 +
  26.276 +    <para id="x_523">The <literal role="hg-ext">extdiff</literal> extension is
  26.277 +      bundled with Mercurial, so it's easy to set up.  In the <literal
  26.278 +	role="rc-extensions">extensions</literal> section of your
  26.279 +      <filename role="special">~/.hgrc</filename>, simply add a
  26.280 +      one-line entry to enable the extension.</para>
  26.281 +    <programlisting>[extensions]
  26.282 +extdiff =</programlisting>
  26.283 +    <para id="x_524">This introduces a command named <command
  26.284 +	role="hg-ext-extdiff">extdiff</command>, which by default uses
  26.285 +      your system's <command>diff</command> command to generate a
  26.286 +      unified diff in the same form as the built-in <command
  26.287 +	role="hg-cmd">hg diff</command> command.</para>
  26.288 +    
  26.289 +    &interaction.extdiff.extdiff;
  26.290 +
  26.291 +    <para id="x_525">The result won't be exactly the same as with the built-in
  26.292 +      <command role="hg-cmd">hg diff</command> variations, because the
  26.293 +      output of <command>diff</command> varies from one system to
  26.294 +      another, even when passed the same options.</para>
  26.295 +
  26.296 +    <para id="x_526">As the <quote><literal>making snapshot</literal></quote>
  26.297 +      lines of output above imply, the <command
  26.298 +	role="hg-ext-extdiff">extdiff</command> command works by
  26.299 +      creating two snapshots of your source tree.  The first snapshot
  26.300 +      is of the source revision; the second, of the target revision or
  26.301 +      working directory.  The <command
  26.302 +	role="hg-ext-extdiff">extdiff</command> command generates
  26.303 +      these snapshots in a temporary directory, passes the name of
  26.304 +      each directory to an external diff viewer, then deletes the
  26.305 +      temporary directory.  For efficiency, it only snapshots the
  26.306 +      directories and files that have changed between the two
  26.307 +      revisions.</para>
  26.308 +
  26.309 +    <para id="x_527">Snapshot directory names have the same base name as your
  26.310 +      repository. If your repository path is <filename
  26.311 +	class="directory">/quux/bar/foo</filename>, then <filename
  26.312 +	class="directory">foo</filename> will be the name of each
  26.313 +      snapshot directory.  Each snapshot directory name has its
  26.314 +      changeset ID appended, if appropriate.  If a snapshot is of
  26.315 +      revision <literal>a631aca1083f</literal>, the directory will be
  26.316 +      named <filename class="directory">foo.a631aca1083f</filename>.
  26.317 +      A snapshot of the working directory won't have a changeset ID
  26.318 +      appended, so it would just be <filename
  26.319 +	class="directory">foo</filename> in this example.  To see what
  26.320 +      this looks like in practice, look again at the <command
  26.321 +	role="hg-ext-extdiff">extdiff</command> example above.  Notice
  26.322 +      that the diff has the snapshot directory names embedded in its
  26.323 +      header.</para>
  26.324 +
  26.325 +    <para id="x_528">The <command role="hg-ext-extdiff">extdiff</command> command
  26.326 +      accepts two important options. The <option
  26.327 +	role="hg-ext-extdiff-cmd-extdiff-opt">hg -p</option> option
  26.328 +      lets you choose a program to view differences with, instead of
  26.329 +      <command>diff</command>.  With the <option
  26.330 +	role="hg-ext-extdiff-cmd-extdiff-opt">hg -o</option> option,
  26.331 +      you can change the options that <command
  26.332 +	role="hg-ext-extdiff">extdiff</command> passes to the program
  26.333 +      (by default, these options are
  26.334 +      <quote><literal>-Npru</literal></quote>, which only make sense
  26.335 +      if you're running <command>diff</command>).  In other respects,
  26.336 +      the <command role="hg-ext-extdiff">extdiff</command> command
  26.337 +      acts similarly to the built-in <command role="hg-cmd">hg
  26.338 +	diff</command> command: you use the same option names, syntax,
  26.339 +      and arguments to specify the revisions you want, the files you
  26.340 +      want, and so on.</para>
  26.341 +
  26.342 +    <para id="x_529">As an example, here's how to run the normal system
  26.343 +      <command>diff</command> command, getting it to generate context
  26.344 +      diffs (using the <option role="cmd-opt-diff">-c</option> option)
  26.345 +      instead of unified diffs, and five lines of context instead of
  26.346 +      the default three (passing <literal>5</literal> as the argument
  26.347 +      to the <option role="cmd-opt-diff">-C</option> option).</para>
  26.348 +
  26.349 +      &interaction.extdiff.extdiff-ctx;
  26.350 +
  26.351 +    <para id="x_52a">Launching a visual diff tool is just as easy.  Here's how to
  26.352 +      launch the <command>kdiff3</command> viewer.</para>
  26.353 +    <programlisting>hg extdiff -p kdiff3 -o</programlisting>
  26.354 +
  26.355 +    <para id="x_52b">If your diff viewing command can't deal with directories,
  26.356 +      you can easily work around this with a little scripting.  For an
  26.357 +      example of such scripting in action with the <literal
  26.358 +	role="hg-ext">mq</literal> extension and the
  26.359 +      <command>interdiff</command> command, see <xref
  26.360 +	linkend="mq-collab:tips:interdiff"/>.</para>
  26.361 +
  26.362 +    <sect2>
  26.363 +      <title>Defining command aliases</title>
  26.364 +
  26.365 +      <para id="x_52c">It can be cumbersome to remember the options to both the
  26.366 +	<command role="hg-ext-extdiff">extdiff</command> command and
  26.367 +	the diff viewer you want to use, so the <literal
  26.368 +	  role="hg-ext">extdiff</literal> extension lets you define
  26.369 +	<emphasis>new</emphasis> commands that will invoke your diff
  26.370 +	viewer with exactly the right options.</para>
  26.371 +
  26.372 +      <para id="x_52d">All you need to do is edit your <filename
  26.373 +	  role="special">~/.hgrc</filename>, and add a section named
  26.374 +	<literal role="rc-extdiff">extdiff</literal>.  Inside this
  26.375 +	section, you can define multiple commands.  Here's how to add
  26.376 +	a <literal>kdiff3</literal> command.  Once you've defined
  26.377 +	this, you can type <quote><literal>hg kdiff3</literal></quote>
  26.378 +	and the <literal role="hg-ext">extdiff</literal> extension
  26.379 +	will run <command>kdiff3</command> for you.</para>
  26.380 +      <programlisting>[extdiff]
  26.381 +cmd.kdiff3 =</programlisting>
  26.382 +      <para id="x_52e">If you leave the right hand side of the definition empty,
  26.383 +	as above, the <literal role="hg-ext">extdiff</literal>
  26.384 +	extension uses the name of the command you defined as the name
  26.385 +	of the external program to run.  But these names don't have to
  26.386 +	be the same.  Here, we define a command named
  26.387 +	<quote><literal>hg wibble</literal></quote>, which runs
  26.388 +	<command>kdiff3</command>.</para>
  26.389 +      <programlisting>[extdiff]
  26.390 + cmd.wibble = kdiff3</programlisting>
  26.391 +
  26.392 +      <para id="x_52f">You can also specify the default options that you want to
  26.393 +	invoke your diff viewing program with.  The prefix to use is
  26.394 +	<quote><literal>opts.</literal></quote>, followed by the name
  26.395 +	of the command to which the options apply.  This example
  26.396 +	defines a <quote><literal>hg vimdiff</literal></quote> command
  26.397 +	that runs the <command>vim</command> editor's
  26.398 +	<literal>DirDiff</literal> extension.</para>
  26.399 +      <programlisting>[extdiff]
  26.400 + cmd.vimdiff = vim
  26.401 +opts.vimdiff = -f '+next' '+execute "DirDiff" argv(0) argv(1)'</programlisting>
  26.402 +
  26.403 +    </sect2>
  26.404 +  </sect1>
  26.405 +  <sect1 id="sec:hgext:transplant">
  26.406 +    <title>Cherrypicking changes with the <literal
  26.407 +	role="hg-ext">transplant</literal> extension</title>
  26.408 +
  26.409 +    <para id="x_530">Need to have a long chat with Brendan about this.</para>
  26.410 +
  26.411 +  </sect1>
  26.412 +  <sect1 id="sec:hgext:patchbomb">
  26.413 +    <title>Send changes via email with the <literal
  26.414 +	role="hg-ext">patchbomb</literal> extension</title>
  26.415 +
  26.416 +    <para id="x_531">Many projects have a culture of <quote>change
  26.417 +	review</quote>, in which people send their modifications to a
  26.418 +      mailing list for others to read and comment on before they
  26.419 +      commit the final version to a shared repository.  Some projects
  26.420 +      have people who act as gatekeepers; they apply changes from
  26.421 +      other people to a repository to which those others don't have
  26.422 +      access.</para>
  26.423 +
  26.424 +    <para id="x_532">Mercurial makes it easy to send changes over email for
  26.425 +      review or application, via its <literal
  26.426 +	role="hg-ext">patchbomb</literal> extension.  The extension is
  26.427 +      so named because changes are formatted as patches, and it's usual
  26.428 +      to send one changeset per email message.  Sending a long series
  26.429 +      of changes by email is thus much like <quote>bombing</quote> the
  26.430 +      recipient's inbox, hence <quote>patchbomb</quote>.</para>
  26.431 +
  26.432 +    <para id="x_533">As usual, the basic configuration of the <literal
  26.433 +	role="hg-ext">patchbomb</literal> extension takes just one or
  26.434 +      two lines in your <filename role="special">
  26.435 +	/.hgrc</filename>.</para>
  26.436 +    <programlisting>[extensions]
  26.437 +patchbomb =</programlisting>
  26.438 +    <para id="x_534">Once you've enabled the extension, you will have a new
  26.439 +      command available, named <command
  26.440 +	role="hg-ext-patchbomb">email</command>.</para>
  26.441 +
  26.442 +    <para id="x_535">The safest and best way to invoke the <command
  26.443 +	role="hg-ext-patchbomb">email</command> command is to
  26.444 +      <emphasis>always</emphasis> run it first with the <option
  26.445 +	role="hg-ext-patchbomb-cmd-email-opt">hg -n</option> option.
  26.446 +      This will show you what the command <emphasis>would</emphasis>
  26.447 +      send, without actually sending anything.  Once you've had a
  26.448 +      quick glance over the changes and verified that you are sending
  26.449 +      the right ones, you can rerun the same command, with the <option
  26.450 +	role="hg-ext-patchbomb-cmd-email-opt">hg -n</option> option
  26.451 +      removed.</para>
  26.452 +
  26.453 +    <para id="x_536">The <command role="hg-ext-patchbomb">email</command> command
  26.454 +      accepts the same kind of revision syntax as every other
  26.455 +      Mercurial command.  For example, this command will send every
  26.456 +      revision between 7 and <literal>tip</literal>, inclusive.</para>
  26.457 +    <programlisting>hg email -n 7:tip</programlisting>
  26.458 +    <para id="x_537">You can also specify a <emphasis>repository</emphasis> to
  26.459 +      compare with.  If you provide a repository but no revisions, the
  26.460 +      <command role="hg-ext-patchbomb">email</command> command will
  26.461 +      send all revisions in the local repository that are not present
  26.462 +      in the remote repository.  If you additionally specify revisions
  26.463 +      or a branch name (the latter using the <option
  26.464 +	role="hg-ext-patchbomb-cmd-email-opt">hg -b</option> option),
  26.465 +      this will constrain the revisions sent.</para>
  26.466 +
  26.467 +    <para id="x_538">It's perfectly safe to run the <command
  26.468 +	role="hg-ext-patchbomb">email</command> command without the
  26.469 +      names of the people you want to send to: if you do this, it will
  26.470 +      just prompt you for those values interactively.  (If you're
  26.471 +      using a Linux or Unix-like system, you should have enhanced
  26.472 +      <literal>readline</literal>-style editing capabilities when
  26.473 +      entering those headers, too, which is useful.)</para>
  26.474 +
  26.475 +    <para id="x_539">When you are sending just one revision, the <command
  26.476 +	role="hg-ext-patchbomb">email</command> command will by
  26.477 +      default use the first line of the changeset description as the
  26.478 +      subject of the single email message it sends.</para>
  26.479 +
  26.480 +    <para id="x_53a">If you send multiple revisions, the <command
  26.481 +	role="hg-ext-patchbomb">email</command> command will usually
  26.482 +      send one message per changeset.  It will preface the series with
  26.483 +      an introductory message, in which you should describe the
  26.484 +      purpose of the series of changes you're sending.</para>
  26.485 +
  26.486 +    <sect2>
  26.487 +      <title>Changing the behavior of patchbombs</title>
  26.488 +
  26.489 +      <para id="x_53b">Not every project has exactly the same conventions for
  26.490 +	sending changes in email; the <literal
  26.491 +	  role="hg-ext">patchbomb</literal> extension tries to
  26.492 +	accommodate a number of variations through command line
  26.493 +	options.</para>
  26.494 +      <itemizedlist>
  26.495 +	<listitem><para id="x_53c">You can write a subject for the introductory
  26.496 +	    message on the command line using the <option
  26.497 +	      role="hg-ext-patchbomb-cmd-email-opt">hg -s</option>
  26.498 +	    option.  This takes one argument, the text of the subject
  26.499 +	    to use.</para>
  26.500 +	</listitem>
  26.501 +	<listitem><para id="x_53d">To change the email address from which the
  26.502 +	    messages originate, use the <option
  26.503 +	      role="hg-ext-patchbomb-cmd-email-opt">hg -f</option>
  26.504 +	    option.  This takes one argument, the email address to
  26.505 +	    use.</para>
  26.506 +	</listitem>
  26.507 +	<listitem><para id="x_53e">The default behavior is to send unified diffs
  26.508 +	    (see <xref linkend="sec:mq:patch"/> for a
  26.509 +	    description of the
  26.510 +	    format), one per message.  You can send a binary bundle
  26.511 +	    instead with the <option
  26.512 +	      role="hg-ext-patchbomb-cmd-email-opt">hg -b</option>
  26.513 +	    option.</para>
  26.514 +	</listitem>
  26.515 +	<listitem><para id="x_53f">Unified diffs are normally prefaced with a
  26.516 +	    metadata header.  You can omit this, and send unadorned
  26.517 +	    diffs, with the <option
  26.518 +	      role="hg-ext-patchbomb-cmd-email-opt">hg
  26.519 +	      --plain</option> option.</para>
  26.520 +	</listitem>
  26.521 +	<listitem><para id="x_540">Diffs are normally sent <quote>inline</quote>,
  26.522 +	    in the same body part as the description of a patch.  This
  26.523 +	    makes it easiest for the largest number of readers to
  26.524 +	    quote and respond to parts of a diff, as some mail clients
  26.525 +	    will only quote the first MIME body part in a message. If
  26.526 +	    you'd prefer to send the description and the diff in
  26.527 +	    separate body parts, use the <option
  26.528 +	      role="hg-ext-patchbomb-cmd-email-opt">hg -a</option>
  26.529 +	    option.</para>
  26.530 +	</listitem>
  26.531 +	<listitem><para id="x_541">Instead of sending mail messages, you can
  26.532 +	    write them to an <literal>mbox</literal>-format mail
  26.533 +	    folder using the <option
  26.534 +	      role="hg-ext-patchbomb-cmd-email-opt">hg -m</option>
  26.535 +	    option.  That option takes one argument, the name of the
  26.536 +	    file to write to.</para>
  26.537 +	</listitem>
  26.538 +	<listitem><para id="x_542">If you would like to add a
  26.539 +	    <command>diffstat</command>-format summary to each patch,
  26.540 +	    and one to the introductory message, use the <option
  26.541 +	      role="hg-ext-patchbomb-cmd-email-opt">hg -d</option>
  26.542 +	    option.  The <command>diffstat</command> command displays
  26.543 +	    a table containing the name of each file patched, the
  26.544 +	    number of lines affected, and a histogram showing how much
  26.545 +	    each file is modified.  This gives readers a qualitative
  26.546 +	    glance at how complex a patch is.</para>
  26.547 +	</listitem></itemizedlist>
  26.548 +
  26.549 +    </sect2>
  26.550 +  </sect1>
  26.551 +</chapter>
  26.552 +
  26.553 +<!--
  26.554 +local variables: 
  26.555 +sgml-parent-document: ("00book.xml" "book" "chapter")
  26.556 +end:
  26.557 +-->
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/fr/cmdref.py	Sat Jul 10 06:24:49 2010 +0100
    27.3 @@ -0,0 +1,156 @@
    27.4 +#!/usr/bin/env python
    27.5 +
    27.6 +import getopt
    27.7 +import itertools
    27.8 +import os
    27.9 +import re
   27.10 +import sys
   27.11 +
   27.12 +def usage(exitcode):
   27.13 +    print >> sys.stderr, ('usage: %s [-H|--hidden] hg_repo' % 
   27.14 +                          os.path.basename(sys.argv[0]))
   27.15 +    sys.exit(exitcode)
   27.16 +
   27.17 +try:
   27.18 +    opts, args = getopt.getopt(sys.argv[1:], 'AHh?', ['all', 'help', 'hidden'])
   27.19 +    opt_all = False
   27.20 +    opt_hidden = False
   27.21 +    for o, a in opts:
   27.22 +        if o in ('-h', '-?', '--help'):
   27.23 +            usage(0)
   27.24 +        if o in ('-A', '--all'):
   27.25 +            opt_all = True
   27.26 +        if o in ('-H', '--hidden'):
   27.27 +            opt_hidden = True
   27.28 +except getopt.GetoptError, err:
   27.29 +    print >> sys.stderr, 'error:', err
   27.30 +    usage(1)
   27.31 +
   27.32 +try:
   27.33 +    hg_repo, ltx_file = args
   27.34 +except ValueError:
   27.35 +    usage(1)
   27.36 +
   27.37 +if not os.path.isfile(os.path.join(hg_repo, 'mercurial', 'commands.py')):
   27.38 +    print >> sys.stderr, ('error: %r does not contain mercurial code' %
   27.39 +                          hg_repo)
   27.40 +    sys.exit(1)
   27.41 +
   27.42 +sys.path.insert(0, hg_repo)
   27.43 +
   27.44 +from mercurial import commands
   27.45 +
   27.46 +def get_commands():
   27.47 +    seen = {}
   27.48 +    for name, info in sorted(commands.table.iteritems()):
   27.49 +        aliases = name.split('|', 1)
   27.50 +        name = aliases.pop(0).lstrip('^')
   27.51 +        function, options, synopsis = info
   27.52 +        seen[name] = {}
   27.53 +        for shortopt, longopt, arg, desc in options:
   27.54 +            seen[name][longopt] = shortopt
   27.55 +    return seen
   27.56 +
   27.57 +def cmd_filter((name, aliases, options)):
   27.58 +    if opt_all:
   27.59 +        return True
   27.60 +    if opt_hidden:
   27.61 +        return name.startswith('debug')
   27.62 +    return not name.startswith('debug')
   27.63 +
   27.64 +def scan(ltx_file):
   27.65 +    cmdref_re = re.compile(r'^\\cmdref{(?P<cmd>\w+)}')
   27.66 +    optref_re = re.compile(r'^\\l?optref{(?P<cmd>\w+)}'
   27.67 +                           r'(?:{(?P<short>[^}])})?'
   27.68 +                           r'{(?P<long>[^}]+)}')
   27.69 +
   27.70 +    seen = {}
   27.71 +    locs = {}
   27.72 +    for lnum, line in enumerate(open(ltx_file)):
   27.73 +        m = cmdref_re.match(line)
   27.74 +        if m:
   27.75 +            d = m.groupdict()
   27.76 +            cmd = d['cmd']
   27.77 +            seen[cmd] = {}
   27.78 +            locs[cmd] = lnum + 1
   27.79 +            continue
   27.80 +        m = optref_re.match(line)
   27.81 +        if m:
   27.82 +            d = m.groupdict()
   27.83 +            seen[d['cmd']][d['long']] = d['short']
   27.84 +            continue
   27.85 +    return seen, locs
   27.86 +    
   27.87 +documented, locs = scan(ltx_file)
   27.88 +known = get_commands()
   27.89 +
   27.90 +doc_set = set(documented)
   27.91 +known_set = set(known)
   27.92 +
   27.93 +errors = 0
   27.94 +
   27.95 +for nonexistent in sorted(doc_set.difference(known_set)):
   27.96 +    print >> sys.stderr, ('%s:%d: %r command does not exist' %
   27.97 +                          (ltx_file, locs[nonexistent], nonexistent))
   27.98 +    errors += 1
   27.99 +
  27.100 +def optcmp(a, b):
  27.101 +    la, sa = a
  27.102 +    lb, sb = b
  27.103 +    sc = cmp(sa, sb)
  27.104 +    if sc:
  27.105 +        return sc
  27.106 +    return cmp(la, lb)
  27.107 +
  27.108 +for cmd in doc_set.intersection(known_set):
  27.109 +    doc_opts = documented[cmd]
  27.110 +    known_opts = known[cmd]
  27.111 +    
  27.112 +    do_set = set(doc_opts)
  27.113 +    ko_set = set(known_opts)
  27.114 +
  27.115 +    for nonexistent in sorted(do_set.difference(ko_set)):
  27.116 +        print >> sys.stderr, ('%s:%d: %r option to %r command does not exist' %
  27.117 +                              (ltx_file, locs[cmd], nonexistent, cmd))
  27.118 +        errors += 1
  27.119 +
  27.120 +    def mycmp(la, lb):
  27.121 +        sa = known_opts[la]
  27.122 +        sb = known_opts[lb]
  27.123 +        return optcmp((la, sa), (lb, sb))
  27.124 +
  27.125 +    for undocumented in sorted(ko_set.difference(do_set), cmp=mycmp):
  27.126 +        print >> sys.stderr, ('%s:%d: %r option to %r command not documented' %
  27.127 +                              (ltx_file, locs[cmd], undocumented, cmd))
  27.128 +        shortopt = known_opts[undocumented]
  27.129 +        if shortopt:
  27.130 +            print '\optref{%s}{%s}{%s}' % (cmd, shortopt, undocumented)
  27.131 +        else:
  27.132 +            print '\loptref{%s}{%s}' % (cmd, undocumented)
  27.133 +        errors += 1
  27.134 +    sys.stdout.flush()
  27.135 +
  27.136 +if errors:
  27.137 +    sys.exit(1)
  27.138 +
  27.139 +sorted_locs = sorted(locs.iteritems(), key=lambda x:x[1])
  27.140 +
  27.141 +def next_loc(cmd):
  27.142 +    for i, (name, loc) in enumerate(sorted_locs):
  27.143 +        if name >= cmd:
  27.144 +            return sorted_locs[i-1][1] + 1
  27.145 +    return loc
  27.146 +
  27.147 +for undocumented in sorted(known_set.difference(doc_set)):
  27.148 +    print >> sys.stderr, ('%s:%d: %r command not documented' %
  27.149 +                          (ltx_file, next_loc(undocumented), undocumented))
  27.150 +    print '\cmdref{%s}' % undocumented
  27.151 +    for longopt, shortopt in sorted(known[undocumented].items(), cmp=optcmp):
  27.152 +        if shortopt:
  27.153 +            print '\optref{%s}{%s}{%s}' % (undocumented, shortopt, longopt)
  27.154 +        else:
  27.155 +            print '\loptref{%s}{%s}' % (undocumented, longopt)
  27.156 +    sys.stdout.flush()
  27.157 +    errors += 1
  27.158 +
  27.159 +sys.exit(errors and 1 or 0)
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/fr/complete.xml	Sat Jul 10 06:24:49 2010 +0100
    28.3 @@ -0,0 +1,16711 @@
    28.4 +<?xml version="1.0"?>
    28.5 +
    28.6 +<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
    28.7 + "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
    28.8 +  <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
    28.9 +<book id="hg">
   28.10 +  <title>Mercurial: The Definitive Guide</title>
   28.11 +  
   28.12 +  <!-- hg parents &#x2d;&#x2d;template '{node|short} ({date|shortdate})' 
   28.13 +  <subtitle>Compiled from 8a1d3f1aff17 (2009-03-10)</subtitle>
   28.14 +  -->
   28.15 +  <subtitle>Compiled from $rev_id$</subtitle>
   28.16 +  <bookinfo>
   28.17 +    <edition>1</edition>
   28.18 +    <isbn>9780596800673</isbn>
   28.19 +    <authorgroup>
   28.20 +      <author>
   28.21 +        <firstname>Bryan</firstname>
   28.22 +        <surname>O'Sullivan</surname>
   28.23 +      </author>
   28.24 +    </authorgroup>
   28.25 +
   28.26 +    <editor>
   28.27 +      <firstname>Mike</firstname>
   28.28 +      <surname>Loukides</surname>
   28.29 +    </editor>
   28.30 +
   28.31 +    <copyright>
   28.32 +      <year>2006</year>
   28.33 +      <year>2007</year>
   28.34 +      <year>2008</year>
   28.35 +      <year>2009</year>
   28.36 +      <holder>Bryan O'Sullivan</holder>
   28.37 +    </copyright>
   28.38 +  </bookinfo>
   28.39 +
   28.40 +  <!-- BEGIN ch00 -->
   28.41 +  <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
   28.42 +
   28.43 +<preface id="chap:preface">
   28.44 +  <?dbhtml filename="preface.html"?>
   28.45 +  <title>Preface</title>
   28.46 +
   28.47 +  <sect1>
   28.48 +    <title>Un conte technique</title>
   28.49 +
   28.50 +    <para id="x_72e">Il y a quelques années, quand j'ai voulu expliqué
   28.51 +    pourquoi je pensais que le gestion de révision distribuée est importante,
   28.52 +    le domaine était encore si nouveau qu'il n'y avait presque aucune 
   28.53 +    littérature publiée pour servir de référence aux personnes intéressées.</para>
   28.54 +
   28.55 +    <para id="x_72f">Bien qu'à cette époque je passais beaucoup de temps
   28.56 +    à travailler sur les entrailles de Mercurial, je me suis mis à la 
   28.57 +    rédaction de ce livre parce qu'il me semblait la manière la plus efficace
   28.58 +    d'aider notre logiciel à atteindre un vaste auditoire, toujours avec 
   28.59 +    l'idée que la gestion de révision devrait être distribuée par nature. J'ai 
   28.60 +    publié ce libre en ligne sous une licence libre pour la même raison : pour 
   28.61 +    diffuser la parole auprès du monde.</para>
   28.62 +
   28.63 +    <para id="x_730">Il y a un rythme familier à un bon livre sur un logiciel 
   28.64 +    qui ressemble de près au fait de conter une histoire : Pourquoi ceci est ? 
   28.65 +    Pourquoi ceci est important ? Comment peut il m'aider ? Comment m'en 
   28.66 +    servir ? Dans ce livre, j'essaye de répondre à toutes ces questions pour
   28.67 +    la gestion de révision distribuée en général, et pour Mercurial en 
   28.68 +    particulier.</para>
   28.69 +  </sect1>
   28.70 +    
   28.71 +  <sect1>
   28.72 +    <title>Merci de votre soutien à Mercurial</title>
   28.73 +
   28.74 +    <para id="x_731">En achetant une copie de ce livre, vous soutenez le
   28.75 +    développement et la liberté de Mercurial en particulier, et dans 
   28.76 +    l'Open Source, au logiciel libre en général. O'Reilly Media et 
   28.77 +    moi-même donnons les revenus issus des ventes de ce livre à la
   28.78 +    Software Freedom Conservancy (<ulink url="http://www.softwarefreedom.org/">http://www.softwarefreedom.org/</ulink>) 
   28.79 +      qui fournit un support juridique à Mercurial et à de 
   28.80 +      nombreux autres projets Open Source proéminents et de qualité.</para>
   28.81 +  </sect1>
   28.82 +
   28.83 +  <sect1>
   28.84 +    <title>Remerciements</title>
   28.85 +
   28.86 +    <para id="x_732">Ce livre n'aurait pas vu le jour sans les
   28.87 +    efforts de Matt Mackal, l'auteur et le chef du projet Mercurial.
   28.88 +    Il est assisté très efficacement par des centaines de contributeurs
   28.89 +    volontaires à travers le monde.</para>
   28.90 +
   28.91 +    <para id="x_733">Les enfants, Cian et Ruairi, ont toujours été prêt
   28.92 +    à m'aider à me reposer avec de merveilleux et impulsif jeux d'enfants. 
   28.93 +    Je tiens aussi à remercier mon ex-femme, Shannon, pour son soutien.
   28.94 +    </para>
   28.95 +
   28.96 +    <para id="x_734">Mes collègues et amis m'ont aidé et assisté de 
   28.97 +    de nombreuses manières. Cette liste de personne est nécessaire mais très
   28.98 +    incomplète : Stephen Hahn, Karyn Ritter, Bonnie Corwin, James Vasile,
   28.99 +    Matt Norwood, Eben Moglen, Bradley Kuhn, Robert Walsh, Jeremy
  28.100 +    Fitzhardinge, Rachel Chalmers.</para>
  28.101 +
  28.102 +    <para id="x_735">J'ai conçu ce livre de manière ouverte, en publiant
  28.103 +    des brouillons des chapitres du livre sur des site web, au fur et à 
  28.104 +    mesure que je les réalisais. Leurs lecteurs m'ont fait des retours 
  28.105 +    utilisant l'application web que j'avais développée. A la fin de sa
  28.106 +    conception, plus de 100 personnes m'avaient fait des commentaires, 
  28.107 +    un chiffre incroyable quand l'on considère que ce système de 
  28.108 +    commentaire n'a tourné que dans les deux derniers mois de la 
  28.109 +    rédaction du livre.</para>
  28.110 +
  28.111 +    <para id="x_736">J'aimerais particulièrement remercier les 
  28.112 +    personnes suivantes, dont les commentaires représentent plus
  28.113 +    d'un tiers de l'ensemble de ces derniers. Je voudrais les 
  28.114 +    remercier pour leur attention et effort à me faire des retours
  28.115 +    très détaillés.</para>
  28.116 +
  28.117 +    <para id="x_737">Martin Geisler, Damien Cassou, Alexey Bakhirkin, Till Plewe,
  28.118 +      Dan Himes, Paul Sargent, Gokberk Hamurcu, Matthijs van der
  28.119 +      Vleuten, Michael Chermside, John Mulligan, Jordi Fita, Jon
  28.120 +      Parise.</para>
  28.121 +
  28.122 +    <para id="x_738">Je souhaite aussi remercier l'aide des personnes
  28.123 +    qui ont découvert des erreurs et fournit des suggestions avisées
  28.124 +    à travers tout le livre.</para>
  28.125 +
  28.126 +    <para id="x_739">Jeremy W. Sherman, Brian Mearns, Vincent Furia, Iwan
  28.127 +      Luijks, Billy Edwards, Andreas Sliwka, Paweł Sołyga, Eric
  28.128 +      Hanchrow, Steve Nicolai, Michał Masłowski, Kevin Fitch, Johan
  28.129 +      Holmberg, Hal Wine, Volker Simonis, Thomas P Jakobsen, Ted
  28.130 +      Stresen-Reuter, Stephen Rasku, Raphael Das Gupta, Ned
  28.131 +      Batchelder, Lou Keeble, Li Linxiao, Kao Cardoso Félix, Joseph
  28.132 +      Wecker, Jon Prescot, Jon Maken, John Yeary, Jason Harris,
  28.133 +      Geoffrey Zheng, Fredrik Jonson, Ed Davies, David Zumbrunnen,
  28.134 +      David Mercer, David Cabana, Ben Karel, Alan Franzoni, Yousry
  28.135 +      Abdallah, Whitney Young, Vinay Sajip, Tom Towle, Tim Ottinger,
  28.136 +      Thomas Schraitle, Tero Saarni, Ted Mielczarek, Svetoslav
  28.137 +      Agafonkin, Shaun Rowland, Rocco Rutte, Polo-Francois Poli,
  28.138 +      Philip Jenvey, Petr Tesałék, Peter R. Annema, Paul Bonser,
  28.139 +      Olivier Scherler, Olivier Fournier, Nick Parker, Nick Fabry,
  28.140 +      Nicholas Guarracino, Mike Driscoll, Mike Coleman, Mietek Bák,
  28.141 +      Michael Maloney, László Nagy, Kent Johnson, Julio Nobrega, Jord
  28.142 +      Fita, Jonathan March, Jonas Nockert, Jim Tittsler, Jeduan
  28.143 +      Cornejo Legorreta, Jan Larres, James Murphy, Henri Wiechers,
  28.144 +      Hagen Möbius, Gábor Farkas, Fabien Engels, Evert Rol, Evan
  28.145 +      Willms, Eduardo Felipe Castegnaro, Dennis Decker Jensen, Deniz
  28.146 +      Dogan, David Smith, Daed Lee, Christine Slotty, Charles Merriam,
  28.147 +      Guillaume Catto, Brian Dorsey, Bob Nystrom, Benoit Boissinot,
  28.148 +      Avi Rosenschein, Andrew Watts, Andrew Donkin, Alexey Rodriguez,
  28.149 +      Ahmed Chaudhary.</para>
  28.150 +  </sect1>
  28.151 +
  28.152 +  <sect1>
  28.153 +    <title>Conventions utilisées dans ce livre</title>
  28.154 +
  28.155 +    <para id="x_73a">Les conventions typographiques suivantes sont utilisées dans ce livre :</para>
  28.156 +
  28.157 +    <variablelist>
  28.158 +      <varlistentry>
  28.159 +        <term>Italique</term>
  28.160 +
  28.161 +        <listitem>
  28.162 +          <para id="x_73b">Indique les termes nouveaux, les URLs, les
  28.163 +            adresses mail, les noms de fichiers et les extensions de
  28.164 +            fichier.</para>
  28.165 +        </listitem>
  28.166 +      </varlistentry>
  28.167 +
  28.168 +      <varlistentry>
  28.169 +        <term><literal moreinfo="none">Taille constante</literal></term>
  28.170 +
  28.171 +        <listitem>
  28.172 +          <para id="x_73c">Utilisé pour les extraits de code, comme 
  28.173 +          dans les paragraphes pour référer aux éléments du programme,
  28.174 +          tels que les variables ou les noms de fonctions, de bases
  28.175 +          de données, de types de données, de variables d'environnement,
  28.176 +          d'instructions, et de mots clés.</para>
  28.177 +        </listitem>
  28.178 +      </varlistentry>
  28.179 +
  28.180 +      <varlistentry>
  28.181 +        <term><userinput moreinfo="none">Taille constante avec gras</userinput></term>
  28.182 +
  28.183 +        <listitem>
  28.184 +          <para id="x_73d">Afficher les commandes ou autres textes qui
  28.185 +          devraient être saisis par l'utilisateur.</para>
  28.186 +        </listitem>
  28.187 +      </varlistentry>
  28.188 +
  28.189 +      <varlistentry>
  28.190 +        <term><replaceable>Constante avec italique</replaceable></term>
  28.191 +
  28.192 +        <listitem>
  28.193 +          <para id="x_73e">Affiche les textes qui devraient être remplacés 
  28.194 +          par une valeur définie par l'utilisateur ou des valeurs définies
  28.195 +          selon le contexte.</para>
  28.196 +        </listitem>
  28.197 +      </varlistentry>
  28.198 +    </variablelist>
  28.199 +
  28.200 +    <tip>
  28.201 +      <para id="x_73f">Cette icône indique une astuce, une suggestion ou 
  28.202 +      une note d'ordre général.</para>
  28.203 +    </tip>
  28.204 +
  28.205 +    <caution>
  28.206 +      <para id="x_740">Cette icône est un message d'alerte ou de prudence.</para>
  28.207 +    </caution>
  28.208 +  </sect1>
  28.209 +
  28.210 +  <sect1>
  28.211 +    <title>Utiliser les exemples de code</title>
  28.212 +
  28.213 +    <para id="x_741">Ce livre est ici pour vous aider dans votre
  28.214 +    travail. De manière générale, vous pouvez donc utiliser le code
  28.215 +    de ce livre dans vos programmes et votre documentation. Vous
  28.216 +    n'avez pas à nous contacter pour nous demander la permission
  28.217 +    de le faire, à moins que vous ne reproduisiez une partie significative
  28.218 +    du code. Par exemple, écrire un programme qui utilise plusieurs 
  28.219 +    extraits de code du livre ne demande aucune autorisation particulière.
  28.220 +    Vendre ou distribuer un CD-ROM provenant des livres O'Reilly demande
  28.221 +    à l'inverse une autorisation. Répondre à une question en citant ce 
  28.222 +    livre ou ses exemples de code ne demande aucune autorisation préalable.
  28.223 +    Intégrer une grande quantité des codes d'exemples de ce livre dans
  28.224 +    votre propre ouvrage demande une autorisation de notre part.</para>
  28.225 +
  28.226 +    <para id="x_742">Nous apprécions, sans l'exiger, que vous citiez 
  28.227 +    l'ouvrage dans vos écrits l'utilisant, en indiquant le titre, 
  28.228 +    l'auteur, l'éditeur et son ISBN. Par exemple: “<emphasis>Titre du 
  28.229 +    livre</emphasis> par Son Auteur. Copyright 2008 O’Reilly Media, Inc.,
  28.230 +    978-0-596-xxxx-x.”</para>
  28.231 +
  28.232 +    <para id="x_743">Si vous estimez que votre usage des exemples de code
  28.233 +    dépasse le cadre défini ci dessus, n'hésitez pas à nous contacter :
  28.234 +      <email>permissions@oreilly.com</email>.</para>
  28.235 +  </sect1>
  28.236 +
  28.237 +  <sect1>
  28.238 +    <title>Safari® Books Online</title>
  28.239 +
  28.240 +    <note role="safarienabled">
  28.241 +      <para id="x_744">Quand vous voyez l'icône de Safari® Books Online 
  28.242 +      sur la couverture d'un de vos livres techniques préférés, cela signifie
  28.243 +      que le livre est disponible, en ligne, à travers le O’Reilly Network Safari
  28.244 +        Bookshelf.</para>
  28.245 +    </note>
  28.246 +
  28.247 +    <para id="x_745">Safari offre une solution qui est meilleure que
  28.248 +    les e-books. C'est une bibliothèque virtuelle qui vous laisse
  28.249 +    aisément rechercher dans des milliers de livres, mais aussi 
  28.250 +    copier-coller leurs exemples, télécharger des chapitres, et 
  28.251 +    trouver des réponses rapides quand vous avez besoin d'une 
  28.252 +    information précise et à jour. Essayez le gratuitement :
  28.253 +    <ulink role="orm:hideurl:ital" url="http://my.safaribooksonline.com/?portal=oreilly">http://my.safaribooksonline.com</ulink>.</para>
  28.254 +  </sect1>
  28.255 +
  28.256 +  <sect1>
  28.257 +    <title>Comment nous contacter</title>
  28.258 +
  28.259 +    <para id="x_746">Merci d'adresser vos commentaires et vos questions
  28.260 +    sur ce livre à son éditeur:</para>
  28.261 +
  28.262 +    <simplelist type="vert">
  28.263 +      <member>O’Reilly Media, Inc.</member>
  28.264 +
  28.265 +      <member>1005 Gravenstein Highway North</member>
  28.266 +
  28.267 +      <member>Sebastopol, CA 95472</member>
  28.268 +
  28.269 +      <member>800-998-9938 (in the United States or Canada)</member>
  28.270 +
  28.271 +      <member>707-829-0515 (international or local)</member>
  28.272 +
  28.273 +      <member>707 829-0104 (fax)</member>
  28.274 +    </simplelist>
  28.275 +
  28.276 +    <para id="x_747">Nous avons une page web pour cet ouvrage, où nous
  28.277 +    publions des errata, des exemples, et encore d'autres informations
  28.278 +    additionnelles. Vous pouvez accéder à cette page par l'URL suivante:
  28.279 +    </para>
  28.280 +
  28.281 +    <simplelist type="vert">
  28.282 +      <member><ulink url="http://www.oreilly.com/catalog/&lt;catalog           page&gt;"/></member>
  28.283 +    </simplelist>
  28.284 +
  28.285 +    <remark>N'oubliez pas de mettre à jour l'attribut &lt;url&gt; aussi.</remark>
  28.286 +
  28.287 +    <para id="x_748">Pour commenter ou poser des questions techniques 
  28.288 +    sur cet ouvrage, envoyez un email à :</para>
  28.289 +
  28.290 +    <simplelist type="vert">
  28.291 +      <member><email>bookquestions@oreilly.com</email></member>
  28.292 +    </simplelist>
  28.293 +
  28.294 +    <para id="x_749">Pour plus d'informations sur nos livres, nos
  28.295 +    conférences, nos centres d'informations, et le réseau O’Reilly, 
  28.296 +    voyez notre site web :</para>
  28.297 +
  28.298 +    <simplelist type="vert">
  28.299 +      <member><ulink url="http://www.oreilly.com"/></member>
  28.300 +    </simplelist>
  28.301 +  </sect1>
  28.302 +</preface>
  28.303 +
  28.304 +<!--
  28.305 +local variables: 
  28.306 +sgml-parent-document: ("00book.xml" "book" "preface")
  28.307 +end:
  28.308 +-->
  28.309 +
  28.310 +  <!-- BEGIN ch01 -->
  28.311 +  <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
  28.312 +
  28.313 +<chapter id="chap:intro">
  28.314 +  <?dbhtml filename="how-did-we-get-here.html"?>
  28.315 +  <title>Comment en est on arrivé là ?</title>
  28.316 +
  28.317 +<sect1>
  28.318 +<title>À propos de la gestion source</title>
  28.319 +
  28.320 +    <para id="x_6d">La gestion de sources est un processus permettant de gérer différentes
  28.321 +versions de la même information. Dans sa forme la plus simple, c'est
  28.322 +ce que tout le monde fait manuellement : quand vous modifiez
  28.323 +un fichier, vous le sauvegardez sous un nouveau nom contenant un numéro,
  28.324 +à chaque fois plus grand que celui de la version précédente.</para>
  28.325 +
  28.326 +    <para id="x_6e">Ce genre de gestion de version manuelle est cependant facilement sujette
  28.327 +aux erreurs, ainsi, depuis longtemps, des logiciels existent pour
  28.328 +résoudre cette problématique. Les premiers outils de gestion de sources
  28.329 +étaient destinés à aider un seul utilisateur, à automatiser la gestion
  28.330 +des versions d'un seul fichier. Dans les dernières décades, cette cible
  28.331 +s'est largement agrandie, ils gèrent désormais de multiples fichiers, et
  28.332 +aident un grand nombre de personnes à travailler ensemble. Les outils les
  28.333 +plus modernes n'ont aucune difficulté à gérer plusieurs milliers de
  28.334 +personnes travaillant ensemble sur des projets regroupant plusieurs
  28.335 +centaines de milliers de fichiers.</para>
  28.336 +
  28.337 +    <para id="x_6f">L'arrivée de la gestion de révision distribuée est
  28.338 +    relativement récente, et, pour le moment, ce nouveau domaine a grandi
  28.339 +    grâce à la volonté des gens d'explorer ces territoires encore inconnus.
  28.340 +    </para>
  28.341 +
  28.342 +    <para id="x_70">J'écris un livre sur la gestion de révision distribuée
  28.343 +    parce que je pense qu'il s'agit d'un sujet important qui mérite un guide
  28.344 +    du terrain. J'ai choisi d'écrire un livre sur Mercurial car il est
  28.345 +    l'outil le plus facile pour découvrir ce nouveau domaine, tout en étant
  28.346 +    un outil efficace qui répond aux demandes d'environnements réels et
  28.347 +    difficiles, là où d'autres outils de gestions de versions s'effondrent.</para>
  28.348 +
  28.349 +    <sect2>
  28.350 +      <title>Pourquoi utiliser un gestionnaire de source ?</title>
  28.351 +
  28.352 +      <para id="x_71">Il y a de nombreuses raisons pour que vous ou votre équipe souhaitiez
  28.353 +utiliser un outil automatisant la gestion de version pour votre projet.</para>
  28.354 +
  28.355 +      <itemizedlist>
  28.356 +	<listitem><para id="x_72">L'outil se chargera de suivre l'évolution de votre projet, sans
  28.357 +que vous ayez à le faire. Pour chaque modification, vous aurez à votre
  28.358 +disposition un journal indiquant <emphasis>qui</emphasis> a fait quoi, <emphasis>pourquoi</emphasis>
  28.359 +il l'a fait, <emphasis>quand</emphasis> il l'a fait, et
  28.360 +<emphasis>ce</emphasis> qu'il a modifié.</para>
  28.361 +</listitem>
  28.362 +<listitem><para id="x_73">Quand vous travaillez avec d'autres personnes, les logiciels de
  28.363 +gestion de source facilitent le travail collaboratif. Par exemple, quand
  28.364 +plusieurs personnes font, plus ou moins simultanément, des modifications
  28.365 +incompatibles, le logiciel vous aidera à identifier et à résoudre les conflits.</para>
  28.366 +</listitem>
  28.367 +<listitem><para id="x_74">L'outil vous aidera à réparer vos erreurs. Si vous effectuez un changement
  28.368 +qui se révèle être une erreur, vous pourrez revenir à une version
  28.369 +antérieure d'un fichier ou même d'un ensemble de fichiers. En fait, un outil de
  28.370 +gestion de source <emphasis>vraiment</emphasis> efficace vous permettra d'identifier à quel
  28.371 +moment le problème est apparu (voir la section <xref linkend="sec:undo:bisect"/> pour plus
  28.372 +de détails).</para>
  28.373 +</listitem>
  28.374 +<listitem><para id="x_75">L'outil vous permettra aussi de travailler sur plusieurs versions différentes
  28.375 +de votre projet et de gérer l'écart entre chacune.</para>
  28.376 +</listitem></itemizedlist>
  28.377 +<para id="x_76">La plupart de ces raisons ont autant d'importances —du
  28.378 +  moins en théorie— que vous travailliez sur un projet pour vous, ou
  28.379 +  avec une centaine d'autres personnes.
  28.380 +</para>
  28.381 +
  28.382 +<para id="x_77">Une question fondamentale à propos des outils de gestion de
  28.383 +  source, qu'il s'agisse du projet d'une personne ou d'une grande équipe, est
  28.384 +  quels sont ses <emphasis>avantages</emphasis> par rapport à ses
  28.385 +  <emphasis>coûts</emphasis>. Un outil qui est difficile à utiliser ou à
  28.386 +  comprendre exigera un lourd effort d'adaptation.
  28.387 +</para>
  28.388 +
  28.389 +<para id="x_78">)Un projet de cinq milles personnes s'effondrera très
  28.390 +  certainement de lui même sans aucun processus et outil de gestion de
  28.391 +  source. Dans ce cas, le coût d'utilisation d'un logiciel de gestion de
  28.392 +  source est dérisoire puisque <emphasis>sans</emphasis>, l'échec est presque
  28.393 +  garanti.
  28.394 +</para>
  28.395 +
  28.396 +<para id="x_79">D'un autre coté, un <quote>rapide hack</quote> d'une personne
  28.397 +  peut sembler un contexte bien pauvre pour utiliser un outil de gestion de
  28.398 +  source, car, bien évidement le coût d'utilisation dépasse le coût total du
  28.399 +  projet. N'est ce pas ?
  28.400 +</para>
  28.401 +
  28.402 +      <para id="x_7a">Mercurial supporte ces <emphasis>deux</emphasis>
  28.403 +        échelles de travail. Vous pouvez apprendre les bases en quelques
  28.404 +        minutes seulement, et, grâce à sa performance, vous pouvez l'utiliser
  28.405 +        avec facilité sur le plus petit des projets. Cette simplicité
  28.406 +        signifie que vous n'avez pas de concept obscurs ou de séquence de
  28.407 +        commandes défiant l'imagination, sans aucune corrélation avec
  28.408 +        <emphasis>ce que vous êtes entrain de faire</emphasis>. En même
  28.409 +        temps, ces mêmes performances et sa nature
  28.410 +        <quote>peer-to-peer</quote> vous permettent d'adapter, sans
  28.411 +        difficulté, son utilisation à de très grands projets.
  28.412 +</para>
  28.413 +
  28.414 +      <para id="x_7b">Aucun outil de gestion de source ne peut sauver un
  28.415 +        projet mal mené, mais un bon outil peut rendre beaucoup plus fluide
  28.416 +        votre travail.
  28.417 +</para>
  28.418 +
  28.419 +    </sect2>
  28.420 +
  28.421 +    <sect2>
  28.422 +      <title>Les multiples noms de la gestion de source</title>
  28.423 +
  28.424 +      <para id="x_7c">La gestion de source
  28.425 +        <!-- TODO:<footnote><J'ai utilisé systématiquement le terme
  28.426 +            <quote>gestion de source</quote> à travers tout l'ouvrage. Ce
  28.427 +            n'est pas forcement la meilleure traduction, et ceci peut rendre
  28.428 +            la lecture un peu lourde, mais je pense que le document y gagne
  28.429 +            en clarté et en précision. -->
  28.430 +        est un domaine tellement large qu'il n'existe pas qu'un seul nom ou
  28.431 +        acronyme pour le désigner. Voici quelques noms ou acronymes que vous
  28.432 +        rencontrerez le plus souvent.
  28.433 +        <!-- TODO:<footnote> J'ai conservé la liste des noms en anglais pour
  28.434 +          des raisons de commodité (ils sont plus <quote>googelable</quote>).
  28.435 +          En outre, j'ai opté  pour conserver l'ensemble des opérations de
  28.436 +          Mercurial (\textit{commit},\textit{push}, \textit{pull},...) en
  28.437 +          anglais, là aussi pour faciliter la lecture d'autres documents en
  28.438 +          anglais, ainsi que l'utilisation de Mercurial. -->
  28.439 +</para>
  28.440 +
  28.441 +<para>:
  28.442 +</para>
  28.443 +
  28.444 +      <itemizedlist>
  28.445 +	<listitem><para id="x_7d">Revision control (RCS)</para></listitem>
  28.446 +	<listitem><para id="x_7e">Software configuration management (SCM), ou
  28.447 +	    configuration management</para></listitem>
  28.448 +	<listitem><para id="x_7f">Source code management</para></listitem>
  28.449 +	<listitem><para id="x_80">Source code control, ou source control</para></listitem>
  28.450 +	<listitem><para id="x_81">Version control (VCS)</para></listitem></itemizedlist>
  28.451 +
  28.452 + <para id="x_82">Certaines personnes prétendent que ces termes ont en fait
  28.453 +   des sens différents mais en pratique ils se recouvrent tellement qu'il n'y
  28.454 +   a pas réellement de manière pertinente de les distinguer. </para>
  28.455 +
  28.456 +    </sect2>
  28.457 +  </sect1>
  28.458 +
  28.459 +  <sect1>
  28.460 +
  28.461 +<title>A propos des exemples dans ce livre</title>
  28.462 +
  28.463 +    <para id="x_84">Ce livre prend une approche non usuel pour les exemples
  28.464 +      de code. Tous les exemples sont en <quote>live</quote> — Chacun
  28.465 +      est actuellement le résultat d'un script shell qui exécute les
  28.466 +      commandes Mercurial que vous voyez. A chaque fois qu'une image du livre
  28.467 +      est construite à partir des sources, tous les scripts d'exemple sont
  28.468 +      lancés automatiquement, et leurs résultats effectifs sont comparés aux
  28.469 +      résultats attendus.</para>
  28.470 +
  28.471 +    <para id="x_85">L'avantage de dette approche est que les exemples sont
  28.472 +      toujours précis ; ils décrivent <emphasis>exactement</emphasis> la
  28.473 +      conduite de la version de Mercurial qui est mentionnée en entête du
  28.474 +      livre. Si je met à jour la version de Mercurial que je suis en train de
  28.475 +      documenter, et que la sortie de certaines commandes change, la
  28.476 +      construction du livre échoue.</para>
  28.477 +
  28.478 +    <para id="x_86">
  28.479 +      Il existe un petit désavantage à cette approche qui est que les dates et
  28.480 +      heures que vous verrez dans les exemples tendent à être
  28.481 +      <quote>écrasés</quote> ensemble, dans le sens où elles ne sont pas
  28.482 +      celles qu'elles auraient été si un humain avait tapé les commandes. En
  28.483 +      effet, humain ne peut pas taper plus d'une commande toutes les quelques
  28.484 +      secondes, avec le temps qui s'écoule, mes scripts d'exemples exécutent
  28.485 +      plusieurs commandes en une seconde.
  28.486 +    </para>
  28.487 +
  28.488 +    <para id="x_87">Une circonstance de ceci est que plusieurs commits
  28.489 +      consécutifs dans un exemple peuvent apparaître comme ayant eu lieu
  28.490 +      durant la même seconde.
  28.491 +      Vous pouvez observer le phénomène dans l'exemple <literal role="hg-ext" moreinfo="none">bisect</literal> dans <xref linkend="sec:undo:bisect"/>
  28.492 +    </para>
  28.493 +
  28.494 +    <para id="x_88">Donc, lorsque vous lisez ces exemples, ne prêtez pas trop
  28.495 +      d'importance aux dates et heures que vous voyez dans la sortie des
  28.496 +      commandes. Cependant, <emphasis>soyez</emphasis> confiants que le
  28.497 +      comportement que vous voyez est consistent et reproductible 
  28.498 +    </para>
  28.499 +
  28.500 +  </sect1>
  28.501 +
  28.502 +<!-- The next section has disapper from this part of the book. it may be splaced somewhere else... t-->
  28.503 +
  28.504 +  <sect1>
  28.505 +    <title>Tendances de la gestion de source</title>
  28.506 +
  28.507 +    <para id="x_89">Il y a eu une tendance évidente dans le développement et
  28.508 +      l'utilisation d'outils de gestion de source depuis les quatre dernières
  28.509 +      décades, au fur et à mesure que les utilisateurs se sont habitués à
  28.510 +      leur outils et se sont sentis contraints par leurs limitations.
  28.511 +    </para>
  28.512 +
  28.513 +    <para id="x_8a">La première génération commença simplement par gérer un
  28.514 +      fichier unique sur un ordinateur individuel. Cependant, même si ces
  28.515 +      outils présentaient une grande avancée par rapport à la gestion
  28.516 +      manuelle des versions, leur modèle de verrouillage et leur utilisation
  28.517 +      limitée à un seul ordinateur rendaient leur utilisation possible
  28.518 +      uniquement dans une très petite équipe.
  28.519 +    </para>
  28.520 +
  28.521 +    <para id="x_8b">La seconde génération a assoupli ces contraintes en
  28.522 +      adoptant une architecture réseau et centralisée, permettant de gérer
  28.523 +      plusieurs projets entiers en même temps. Alors que les projets
  28.524 +      grandirent en taille, ils rencontrèrent de nouveaux problèmes. Avec les
  28.525 +      clients discutant régulièrement avec le serveurs, la montée en charge
  28.526 +      devint un réel problème sur les gros projets. Une connexion réseau peu
  28.527 +      fiable pouvait complètement empêcher les utilisateurs distants de
  28.528 +      dialoguer avec le serveur. Alors que les projets <emphasis remap="it">Open Source</emphasis> commencèrent à mettre en place des
  28.529 +      accès en lecture seule disponible anonymement, les utilisateurs sans
  28.530 +      les privilèges de <quote>commit</quote> réalisèrent qu'ils ne pouvaient
  28.531 +      pas utiliser les outils pour collaborer naturellement avec le projet,
  28.532 +      comme ils ne pouvaient pas non plus enregistrer leurs modifications.
  28.533 +    </para>
  28.534 +
  28.535 +    <para id="x_8c">La génération actuelle des outils de gestion de source
  28.536 +      est <quote>peer-to-peer</quote> par nature. Tous ces systèmes ont
  28.537 +      abandonné la dépendance à un serveur central, et ont permis à leur
  28.538 +      utilisateur de distribuer les données de leur gestion de source à qui
  28.539 +      en a besoin. La collaboration à travers Internet a transformé la
  28.540 +      contrainte technologique en une simple question de choix et de
  28.541 +      consensus. Les outils modernes peuvent maintenant fonctionner en mode
  28.542 +      déconnecté sans limite et de manière autonome, la connexion au réseau
  28.543 +      n'étant nécessaire que pour synchroniser les modifications avec les
  28.544 +      autres dépôts.
  28.545 +    </para>
  28.546 +  </sect1>
  28.547 +    
  28.548 +  <sect1>
  28.549 +    <title>Quelques avantages des gestionnaires de source distribués</title>
  28.550 +      
  28.551 +    <para id="x_8d">Même si les gestionnaire de source distribués sont depuis
  28.552 +      plusieurs années assez robustes et aussi utilisables que leurs
  28.553 +      prédécesseurs, les utilisateurs d'autres outils n'y ont pas encore été
  28.554 +      sensibilisés. Les gestionnaires de source distribués se distinguent
  28.555 +      particulièrement de leurs équivalents centralisés de nombreuses
  28.556 +      manières.
  28.557 +    </para>
  28.558 +
  28.559 +    <para id="x_8e">Pour un développeur individuel, ils restent beaucoup plus
  28.560 +      rapides que les outils centralisés. Cela pour une raison simple : un
  28.561 +      outil centralisé doit toujours dialoguer à travers le réseau pour la
  28.562 +      plupart des opérations, car presque toutes les métadonnées sont
  28.563 +      stockées sur la seule copie du serveur central. Un outil distribué
  28.564 +      stocke toute ses métadonnées localement. À tâche égale, effectuer un
  28.565 +      échange avec le réseau ajoute un délai aux outils centralisés. Ne
  28.566 +      sous-estimez pas la valeur d'un outil rapide : vous allez passer
  28.567 +      beaucoup de temps à interagir avec un logiciel de gestion de source.
  28.568 +    </para>
  28.569 +
  28.570 +    <para id="x_8f">Les outils distribués sont complètement indépendants des
  28.571 +      aléas de votre serveur, d'autant plus qu'ils répliquent les métadonnées
  28.572 +      à beaucoup d'endroits. Si votre serveur central prend feu, vous avez
  28.573 +      intérêt à ce que les médias de sauvegardes soient fiables, et que votre
  28.574 +      dernier <quote>backup</quote> soit récent et fonctionne sans problème.
  28.575 +      Avec un outil distribué, vous avez autant de <quote>backup</quote> que
  28.576 +      de contributeurs.
  28.577 +    </para>
  28.578 +
  28.579 +    <para id="x_90">En outre, la fiabilité de votre réseau affectera beaucoup
  28.580 +      moins les outils distribués. Vous ne pouvez même pas utiliser un outil
  28.581 +      centralisé sans connexion réseau, à l'exception de quelques commandes,
  28.582 +      très limitées. Avec un outil distribué, si votre connexion réseau tombe
  28.583 +      pendant que vous travaillez, vous pouvez ne même pas vous en rendre
  28.584 +      compte. La seule chose que vous ne serez pas capable de faire sera de
  28.585 +      communiquer avec des dépôts distants, opération somme toute assez rare
  28.586 +      en comparaison aux opérations locales. Si vous avez une équipe de
  28.587 +      collaborateurs très dispersée ceci peut être significatif.
  28.588 +    </para>
  28.589 +
  28.590 +    <sect2>
  28.591 +      <title>Avantages pour les projets Open Source</title>
  28.592 +
  28.593 +      <para id="x_91">Si vous prenez goût à un projet <emphasis remap="it">Open Source</emphasis> et que vous décidez de commencer
  28.594 +        à toucher à son code, et que le projet utilise un gestionnaire de
  28.595 +        source distribué, vous êtes immédiatement un "pair" avec les
  28.596 +        personnes formant le <quote>cœur</quote> du projet. S'ils publient
  28.597 +        leurs dépôts, vous pouvez immédiatement copier leurs historiques de
  28.598 +        projet, faire des modifications, enregistrer votre travail en
  28.599 +        utilisant les mêmes outils qu'eux. Par comparaison avec un outil
  28.600 +        centralisé, vous devez utiliser un logiciel en mode <quote>lecture
  28.601 +          seule</quote> à moins que quelqu'un ne vous donne les privilèges de
  28.602 +        <quote>commit</quote> sur le serveur central. Avant ça, vous ne serez
  28.603 +        pas capable d'enregistrer vos modifications, et vos propres
  28.604 +        modifications risqueront de se corrompre chaque fois que vous
  28.605 +        essayerez de mettre à jour à votre espace de travail avec le serveur
  28.606 +        central.
  28.607 +      </para>
  28.608 +
  28.609 +    <sect3>
  28.610 +      <title>Le non-problème du "fork"</title>
  28.611 +      
  28.612 +      <para id="x_92">Il a été souvent suggéré que les gestionnaires de
  28.613 +        source distribués posent un risque pour les projets <emphasis remap="it">Open Source</emphasis> car ils facilitent grandement la
  28.614 +        création de <quote>fork</quote>.
  28.615 +        <!--footnote{NdT:Création d'une <ulink url="version alternative du
  28.616 +          logiciel">version alternative du
  28.617 +          logiciel</ulink>{http://fr.wikipedia.org/wiki/Fork#Embranchement_d.27un_projet_informatique}
  28.618 +        -->
  28.619 +        Un <quote>fork</quote> apparait quand il y des divergences d'opinion
  28.620 +        ou d'attitude au sein d'un groupe de développeurs qui aboutissent à
  28.621 +        la décision de ne plus travailler ensemble. Chaque parti s'empare
  28.622 +        d'une copie plus ou moins complète du code source du projet et
  28.623 +        continue dans sa propre direction.
  28.624 +      </para>
  28.625 +
  28.626 +
  28.627 +      <para id="x_93">Parfois ces différents partis décident de se
  28.628 +        réconcilier. Avec un serveur central, l'aspect
  28.629 +        <emphasis>technique</emphasis> de cette réconciliation est un
  28.630 +        processus douloureux, et essentiellement manuel. Vous devez décider
  28.631 +        quelle modification est <quote>la gagnante</quote>, et replacer, par
  28.632 +        un moyen ou un autre, les modifications de l'autre équipe dans
  28.633 +        l'arborescence du projet. Ceci implique généralement la perte d'une
  28.634 +        partie de l'historique d'un des partis, ou même des deux.
  28.635 +      </para>
  28.636 +    
  28.637 +      <para id="x_94">Ce que les outils distribués permettent à ce sujet est
  28.638 +        probablement la <emphasis>meilleure</emphasis> façon de développer un
  28.639 +        projet. Chaque modification que vous effectuez est potentiellement un
  28.640 +        <quote>fork</quote>. La grande force de cette approche est que les
  28.641 +        gestionnaires de source distribués doivent être vraiment très
  28.642 +        efficaces pour <emphasis>fusionner (merge)</emphasis>
  28.643 +        <!-- TODO footnote{NdT:j'ai choisi de traduire ici <emphasis
  28.644 +          remap="it">merging</emphasis> par <quote>fusionner</quote> pour des
  28.645 +        raisons de clarté} -->
  28.646 +        des <quote>forks</quote>, car les <quote>forks</quote>, dans ce
  28.647 +        contexte, arrivent tout le temps.
  28.648 +      </para>
  28.649 +      
  28.650 +      <para id="x_95">Si chaque altération que n'importe qui effectue, à tout
  28.651 +        moment, est vue comme un <quote>fork</quote> à fusionner, alors ce
  28.652 +        que le monde de l'<emphasis remap="it">Open Source</emphasis> voit
  28.653 +        comme un <quote>fork</quote> devient <emphasis>uniquement</emphasis>
  28.654 +        une problématique sociale. En fait, les outils de gestions de source
  28.655 +        distribués <emphasis>réduisent</emphasis> les chances de
  28.656 +        <quote>fork</quote> :
  28.657 +      </para>
  28.658 +        
  28.659 +      <itemizedlist>
  28.660 +        <listitem>
  28.661 +        <para>Ils éliminent la distinction sociale qu'imposent les outils
  28.662 +          centralisés entre les membres du projets (ceux qui ont accès au
  28.663 +          <quote>commit</quote>) et ceux de l'extérieur (ce qui ne l'ont
  28.664 +          pas).
  28.665 +        </para>
  28.666 +        <para>Ils rendent plus facile la réconciliation après un
  28.667 +          <quote>fork</quote> social, car tout ce qu'elle implique est une
  28.668 +          simple fusion.
  28.669 +        </para>
  28.670 +        </listitem>
  28.671 +      </itemizedlist>
  28.672 +
  28.673 +      <para id="x_98">Certaines personnes font de la résistance envers les
  28.674 +        gestionnaires de source distribués parce qu'ils veulent garder un
  28.675 +        contrôle ferme sur leur projet, et ils pensent que les outils
  28.676 +        centralisés leur fournissent ce contrôle. Néanmoins, si c'est votre
  28.677 +        cas, sachez que si vous publiez votre dépôt CVS ou Subversion de
  28.678 +        manière publique, il existe une quantité d'outils disponibles pour
  28.679 +        récupérer entièrement votre projet et son historique (quoique
  28.680 +        lentement) et le récréer ailleurs, sans votre contrôle. En fait,
  28.681 +        votre contrôle sur votre projet est illusoire, vous ne faites
  28.682 +        qu'interdire à vos collaborateurs de travailler de manière fluide, en
  28.683 +        disposant d'un miroir ou d'un <quote>fork</quote> de votre
  28.684 +        historique.
  28.685 +      </para>
  28.686 +
  28.687 +    </sect3>
  28.688 +    </sect2>
  28.689 +    <sect2>
  28.690 +      <title>Avantages pour les projets commerciaux</title>
  28.691 +
  28.692 +      <para id="x_99">Beaucoup de projets commerciaux sont réalisés par des
  28.693 +        équipes éparpillées à travers le globe. Les contributeurs qui sont
  28.694 +        loin du serveur central devront subir des commandes lentes et même
  28.695 +        parfois peu fiables. Les solutions propriétaires de gestion de source
  28.696 +        tentent de palier ce problème avec des réplications de sites distants
  28.697 +        qui sont à la fois coûteuses à mettre en place et lourdes à
  28.698 +        administrer. Un système distribué ne souffre pas de ce genre de
  28.699 +        problèmes. En outre, il est très aisé de mettre en place plusieurs
  28.700 +        serveurs de références, disons un par site, de manière à ce qu'il n'y
  28.701 +        ait pas de communication redondante entre les dépôts, sur une
  28.702 +        connexion longue distance souvent onéreuse.
  28.703 +      </para>
  28.704 +
  28.705 +      <para id="x_9a">Les systèmes de gestion de source supportent
  28.706 +        généralement assez mal la monté en charge. Il n'est pas rare pour un
  28.707 +        gestionnaire de source centralisé pourtant onéreux de s'effondrer
  28.708 +        sous la charge combinée d'une douzaine d'utilisateurs concurrents
  28.709 +        seulement. Une fois encore, la réponse à cette problématique est
  28.710 +        généralement encore la mise en place d'un ensemble complexe de
  28.711 +        serveurs synchronisés par un mécanisme de réplication. Dans le cas
  28.712 +        d'un gestionnaire de source distribué, la charge du serveur central
  28.713 +        — si vous avez un— est plusieurs fois inférieure (car
  28.714 +        toutes les données sont déjà répliquées ailleurs), un simple serveur,
  28.715 +        pas très cher, peut gérer les besoins d'une plus grande équipe, et la
  28.716 +        réplication pour balancer la charge devient le travail d'un simple
  28.717 +        script.
  28.718 +      </para>
  28.719 +
  28.720 +      <para id="x_9b">Si vous avez des employés sur le terrain, en train de
  28.721 +        chercher à résoudre un souci sur le site d'un client, ils
  28.722 +        bénéficieront aussi d'un gestionnaire de source distribué. Cet outil
  28.723 +        leur permettra de générer des versions personnalisées, d'essayer
  28.724 +        différentes solutions, en les isolant aisément les unes des autres,
  28.725 +        et de rechercher efficacement à travers l'historique des sources, la
  28.726 +        cause des bugs ou des régressions, tout ceci sans avoir besoin de la
  28.727 +        moindre connexion au réseau de votre compagnie.
  28.728 +      </para>
  28.729 +
  28.730 +    </sect2>
  28.731 +    </sect1>
  28.732 +    <sect1>
  28.733 +      <title>Pourquoi choisir Mercurial?</title>
  28.734 +
  28.735 +      <para id="x_9c">Mercurial a plusieurs caractéristiques qui en font un
  28.736 +        choix particulièrement pertinent pour la gestion de source :
  28.737 +      </para>
  28.738 +    <itemizedlist>
  28.739 +      <listitem><para id="x_9d">Il est simple à apprendre et à utiliser.</para></listitem>
  28.740 +      <listitem><para id="x_9e">Il est léger.</para></listitem>
  28.741 +      <listitem><para id="x_9f">Il s'adapte très bien à la charge.</para></listitem>
  28.742 +      <listitem><para id="x_a0">Il se personnalise facilement.</para></listitem>
  28.743 +    </itemizedlist>
  28.744 +
  28.745 +    <para id="x_a1">Si vous êtes déjà familier d'un outil de gestion de
  28.746 +      source, vous serez capable de l'utiliser en moins de 5 minutes. Sinon,
  28.747 +      ça ne sera pas beaucoup plus long. Les commandes utilisées par
  28.748 +      Mercurial, comme ses fonctionnalités, sont généralement uniformes et
  28.749 +      cohérentes, et vous pouvez ainsi garder en tête simplement quelques
  28.750 +      règles générales, plutôt qu'un lot complexe d'exceptions.
  28.751 +    </para>
  28.752 +
  28.753 +    <para id="x_a2">Sur un petit projet, vous pouvez commencer à travailler
  28.754 +      avec Mercurial en quelques instants. Ajouter des modifications ou des
  28.755 +      branches, transférer ces modifications (localement ou via le réseau),
  28.756 +      et les opérations d'historique ou de statut sont aussi très rapides.
  28.757 +      Mercurial reste hors de votre chemin grâce à sa simplicité
  28.758 +      d'utilisation et sa rapidité d'exécution.
  28.759 +    </para>
  28.760 +
  28.761 +    <para id="x_a3">L'utilité de Mercurial ne se limite pas à de petits
  28.762 +      projets: il est aussi utilisé par des projets ayant des centaines ou
  28.763 +      même des milliers de contributeurs, avec plusieurs dizaines de milliers
  28.764 +      de fichiers, et des centaines de méga octets de code source.
  28.765 +    </para>
  28.766 +
  28.767 +    <para id="x_a4">Si les fonctionnalités au cœur de Mercurial ne sont pas
  28.768 +      suffisantes pour vous, il est très aisé d'en construire d'autres.
  28.769 +      Mercurial est adapté à l'utilisation de scripts, et son implémentation
  28.770 +      interne en Python, propre et claire, rend encore plus facile l'ajout de
  28.771 +      fonctionnalités sous forme d'extensions. Il en existe déjà un certain
  28.772 +      nombre de très populaires et très utiles, dont le périmètre va de la
  28.773 +      recherche de bugs à l'amélioration des performances.
  28.774 +    </para>
  28.775 +
  28.776 +  </sect1>
  28.777 +  <sect1>
  28.778 +    <title>Mercurial comparé aux autres outils</title>
  28.779 +
  28.780 +    <para id="x_a5">Avant que vous n'alliez plus loin, comprenez bien que
  28.781 +      cette section reflète mes propres expériences, et elle est donc (j'ose
  28.782 +      le dire) peu objective. Néanmoins, j'ai utilisé les outils de gestion
  28.783 +      de source listés ci dessous, dans la plupart des cas, pendant plusieurs
  28.784 +      années.
  28.785 +    </para>
  28.786 +
  28.787 +    <sect2>
  28.788 +      <title>Subversion</title>
  28.789 +
  28.790 +      <para id="x_a6">Subversion est un des outils de gestion de source les
  28.791 +        plus populaire, il fût développé pour remplacer CVS. Il a une
  28.792 +        architecture client/server centralisée.
  28.793 +      </para>
  28.794 +
  28.795 +      <para id="x_a7">Subversion et Mercurial ont des noms de commandes très
  28.796 +        similaires pour les mêmes opérations, ainsi si vous êtes familier
  28.797 +        avec l'un, c'est facile d'apprendre l'autre. Ces deux outils sont
  28.798 +        portables sur les systèmes d'exploitation les plus populaires.
  28.799 +      </para>
  28.800 +
  28.801 +      <para id="x_a8">Avant la version 1.5, Subversion n'offrait aucune forme
  28.802 +        de support pour les fusions. Lors de l'écriture de ce livre, ses
  28.803 +        capacités de fusion étaient nouvelles, et réputées pour être <ulink url="http://svnbook.red-bean.com/nightly/en/svn.branchmerge.advanced.html#svn.branchmerge.advanced.finalword">
  28.804 +          complexes et buguées</ulink>.
  28.805 +      </para>
  28.806 +
  28.807 +      <para id="x_a9">Mercurial dispose d'un avantage substantiel en terme de
  28.808 +        performance par rapport à Subversion sur la plupart des opérations
  28.809 +        que j'ai pu tester. J'ai mesuré une différence de performance allant
  28.810 +        de deux à six fois plus rapide avec le système de stockage de fichier
  28.811 +        local de Subversion 1.4.3 (<emphasis>ra_local</emphasis>), qui est la
  28.812 +        méthode d'accès la plus rapide disponible. Dans un déploiement plus
  28.813 +        réaliste, impliquant un stockage réseau, Subversion serait encore
  28.814 +        plus désavantagé. Parce que la plupart des commandes Subversion
  28.815 +        doivent communiquer avec le serveur et que Subversion n'a pas de
  28.816 +        mécanisme de réplication, la capacité du serveur et la bande passante
  28.817 +        sont devenues des goulots d'étranglement pour les projets de taille
  28.818 +        moyenne ou grande.
  28.819 +      </para>
  28.820 +
  28.821 +      <para id="x_aa">En outre, Subversion implique une surcharge
  28.822 +        substantielle dans le stockage local de certaines données, pour
  28.823 +        éviter des transactions avec le serveur, pour certaines opérations
  28.824 +        communes, telles que la recherche des fichiers modifiés
  28.825 +        (<literal moreinfo="none">status</literal>) et l'affichage des modifications par
  28.826 +        rapport à la révision courante (<literal moreinfo="none">diff</literal>). En
  28.827 +        conséquence, un répertoire de travail Subversion a souvent la même
  28.828 +        taille, ou est plus grand, qu'un dépôt Mercurial et son espace de
  28.829 +        travail, et ceci bien que le dépôt Mercurial contienne l'intégralité
  28.830 +        de l'historique.
  28.831 +      </para>
  28.832 +
  28.833 +      <para id="x_ab">Subversion est largement supporté par les outils
  28.834 +        tierces. Mercurial est actuellement encore en retrait de ce point de
  28.835 +        vue. L'écart se réduit néanmoins, en effet, certains des outils
  28.836 +        graphiques sont maintenant supérieurs à leurs équivalents Subversion.
  28.837 +        Comme Mercurial, Subversion dispose d'un excellent manuel
  28.838 +        utilisateur.
  28.839 +      </para>
  28.840 +
  28.841 +      <para id="x_ac">Parce que Subversion ne stocke pas l'historique chez
  28.842 +        ses clients, il est parfaitement adapté à la gestion de projets qui
  28.843 +        doivent suivre un ensemble de larges fichiers binaires et opaques. Si
  28.844 +        vous suivez une cinquantaine de versions d'un fichier incompressible
  28.845 +        de 10MB, l'occupation disque coté client d'un projet sous Subversion
  28.846 +        restera à peu près constante. A l'inverse, l'occupation disque du
  28.847 +        même projet sous n'importe lequel des gestionnaires de source
  28.848 +        distribués grandira rapidement, proportionnellement aux nombres de
  28.849 +        versions, car les différences entre chaque révisions seront très
  28.850 +        grandes.
  28.851 +      </para>
  28.852 +
  28.853 +      <para id="x_ad">En outre, c'est souvent difficile ou, généralement,
  28.854 +        impossible de fusionner des différences dans un fichier binaire. La
  28.855 +        capacité de Subversion de verrouiller des fichiers, pour permettre à
  28.856 +        l'utilisateur d'être le seul à le mettre à jour
  28.857 +        (<quote>commit</quote>) temporairement, est un avantage significatif
  28.858 +        dans un projet doté de beaucoup de fichiers binaires.
  28.859 +      </para>
  28.860 +
  28.861 +      <para id="x_ae">Mercurial peut importer l'historique depuis un dépôt
  28.862 +        Subversion. Il peut aussi exporter l'ensemble des révisions d'un
  28.863 +        projet vers un dépôt Subversion. Ceci rend très facile de
  28.864 +        <quote>prendre la température</quote> et d'utiliser Mercurial et
  28.865 +        Subversion en parallèle, avant de décider de migrer vers Mercurial.
  28.866 +        La conversion de l'historique est incrémentale, donc vous pouvez
  28.867 +        effectuer une conversion initiale, puis de petites additions par la
  28.868 +        suite pour ajouter les nouvelle modifications.
  28.869 +      </para>
  28.870 +
  28.871 +
  28.872 +    </sect2>
  28.873 +    <sect2>
  28.874 +      <title>Git</title>
  28.875 +
  28.876 +      <para id="x_af">Git est un outil de gestion de source distribué qui fût
  28.877 +        développé pour gérer le code source de noyau de Linux. Comme
  28.878 +        Mercurial, sa conception initiale a été inspirée par Monotone.
  28.879 +      </para>
  28.880 +
  28.881 +      <para id="x_b0">Git dispose d'un ensemble conséquent de commandes, avec
  28.882 +        plus de 139 commandes individuelles pour la version 1.5.0. Il a aussi
  28.883 +        la réputation d'être difficile à apprendre. Comparé à Git, le point
  28.884 +        fort de Mercurial est clairement sa simplicité.
  28.885 +      </para>
  28.886 +
  28.887 +      <para id="x_b1">En terme de performance, Git est extrêmement rapide.
  28.888 +        Dans la plupart des cas, il est plus rapide que Mercurial, tout du
  28.889 +        moins sur Linux, alors que Mercurial peut être plus performant sur
  28.890 +        d'autres opérations. Néanmoins, sur Windows, les performances et le
  28.891 +        niveau de support général fourni par Git, au moment de l'écriture de
  28.892 +        cet ouvrage, est bien derrière celui de Mercurial.
  28.893 +      </para>
  28.894 +
  28.895 +      <para id="x_b2">Alors que le dépôt Mercurial ne demande aucune
  28.896 +        maintenance, un dépôt Git exige d'exécuter manuellement et
  28.897 +        régulièrement la commande <quote>repacks</quote> sur ses métadonnées.
  28.898 +        Sans ceci, les performances de git se dégradent et la consommation de
  28.899 +        l'espace disque augmente rapidement. Un serveur qui contient
  28.900 +        plusieurs dépôts Git qui ne sont pas régulièrement et fréquemment
  28.901 +        <quote>repacked</quote> deviendra un vrai problème lors des
  28.902 +        <quote>backups</quote> du disque, et il y eu des cas, où un
  28.903 +        <quote>backup</quote> journalier pouvait durer plus de 24 heures. Un
  28.904 +        dépôt fraichement <quote>repacked</quote> sera légèrement plus petit
  28.905 +        qu'un dépôt Mercurial, mais un dépôt non <quote>repacked</quote> est
  28.906 +        beaucoup plus grand.
  28.907 +      </para>
  28.908 +
  28.909 +      <para id="x_b3">Le cœur de Git est écrit en C. La plupart des commandes
  28.910 +        Git sont implémentées sous forme de scripts Shell ou Perl, et la
  28.911 +        qualité de ces scripts varie grandement. J'ai plusieurs fois constaté
  28.912 +        que certains de ces scripts étaient chargés en mémoire aveuglément et
  28.913 +        que la présence d'erreurs pouvait s'avérer fatal.
  28.914 +      </para>
  28.915 +
  28.916 +      <para id="x_b4">Mercurial peut importer l'historique d'un dépôt Git.</para>
  28.917 +
  28.918 +    </sect2>
  28.919 +    <sect2>
  28.920 +      <title>CVS</title>
  28.921 +
  28.922 +      <para id="x_b5">CVS est probablement l'outil de gestion de source le
  28.923 +        plus utilisé aujourd'hui dans le monde. À cause de son manque de
  28.924 +        clarté interne, il n'est plus maintenu depuis plusieurs années.
  28.925 +      </para>
  28.926 +
  28.927 +      <para id="x_b6">Il a une architecture client/serveur centralisée. Il ne
  28.928 +        regroupe pas les modifications de fichiers dans une opération de
  28.929 +        <quote>commit</quote> atomique, ce qui permet à ses utilisateurs de
  28.930 +        <quote>casser le <emphasis>build</emphasis></quote> assez facilement
  28.931 +        : une personne peut effectuer une opération de <quote>commit</quote>
  28.932 +        sans problème puis être bloquée par besoin de fusion, avec comme
  28.933 +        conséquence néfaste, que les autres utilisateurs ne récupèreront
  28.934 +        qu'une partie de ses modifications. Ce problème affecte aussi la
  28.935 +        manière de travailler avec l'historique du projet. Si vous voulez
  28.936 +        voir toutes les modifications d'une personne du projet, vous devrez
  28.937 +        injecter manuellement les descriptions et les <emphasis remap="it">timestamps</emphasis> des modifications de chacun des
  28.938 +        fichiers impliqués (si vous savez au moins quels sont ces fichiers).
  28.939 +      </para>
  28.940 +
  28.941 +      <para id="x_b7">CVS a une notion étrange des <emphasis remap="it">tags</emphasis> et des branches que je n'essayerai même
  28.942 +        pas de décrire ici. Il ne supporte pas bien les opérations de
  28.943 +        renommage d'un fichier ou d'un répertoire, ce qui facilite la
  28.944 +        corruption de son dépôt. Il n'a presque pas pour ainsi dire de
  28.945 +        contrôle de cohérence interne, il est donc pratiquement impossible de
  28.946 +        dire si un dépôt est corrompu ni à quel point. Je ne recommanderai
  28.947 +        pas CVS pour un projet existant ou nouveau.
  28.948 +      </para>
  28.949 +
  28.950 +      <para id="x_b8">Mercurial peut importer l'historique d'un projet CVS.
  28.951 +        Néanmoins, il y a quelques principes à respecter; ce qui est vrai
  28.952 +        aussi pour les autres outils d'import de projet CVS. À cause de
  28.953 +        l'absence de <quote>commit</quote> atomique et gestion de version de
  28.954 +        l'arborescence, il n'est pas possible de reconstruire de manière
  28.955 +        précise l'ensemble de l'historique. Un travail de
  28.956 +        <quote>devinette</quote> est donc nécessaire, et les fichiers
  28.957 +        renommés ne sont pas détectés. Parce qu'une bonne part de
  28.958 +        l'administration d'un dépôt CVS est effectuée manuellement, et est
  28.959 +        donc, sujette à erreur, il est courant que les imports CVS
  28.960 +        rencontrent de nombreux problèmes avec les dépôt corrompus (des
  28.961 +        <emphasis remap="it">timestamps</emphasis> de révision complètement
  28.962 +        buggés et des fichiers verrouillés depuis des années sont deux des
  28.963 +        problèmes les moins intéressants dont je me souvienne).
  28.964 +      </para>
  28.965 +
  28.966 +      <para id="x_b9">Mercurial peut importer l'historique depuis un dépôt CVS.
  28.967 +      </para>
  28.968 +
  28.969 +
  28.970 +    </sect2>
  28.971 +    <sect2>
  28.972 +      <title>Outils propriétaires</title>
  28.973 +
  28.974 +      <para id="x_ba">Perforce a une architecture client/serveur centralisée,
  28.975 +        sans aucun mécanisme de mise en cache de données coté client.
  28.976 +        Contrairement à la plupart des outils modernes de gestion de source,
  28.977 +        Perforce exige de ses utilisateurs d'exécuter une commande pour
  28.978 +        informer le serveur central de tout fichier qu'ils souhaitent
  28.979 +        modifier.
  28.980 +      </para>
  28.981 +
  28.982 +      <para id="x_bb">Les performances de Perforce sont plutôt bonnes pour
  28.983 +        des petites équipes, mais elles s'effondrent rapidement lorsque le
  28.984 +        nombre d'utilisateurs augmente au delà de la douzaine. Des
  28.985 +        installations de Perforce assez larges nécessitent le déploiement de
  28.986 +        proxies pour supporter la montée en charge associée.
  28.987 +      </para>
  28.988 +
  28.989 +    </sect2>
  28.990 +    <sect2>
  28.991 +      <title>Choisir un outil de gestion de source</title>
  28.992 +
  28.993 +      <para id="x_bc">A l'exception de CVS, tous les outils listés ci-dessus
  28.994 +        ont des forces qui leur sont propres et qui correspondent à certaines
  28.995 +        formes de projet. Il n'y a pas un seul meilleur outil de gestion de
  28.996 +        source qui correspondrait le mieux à toutes les situations.
  28.997 +      </para>
  28.998 +
  28.999 +      <para id="x_bd">En guise exemple, Subversion est un très bon choix
 28.1000 +        lorsqu'on travaille avec beaucoup de fichiers binaires, qui évoluent
 28.1001 +        régulièrement, grâce à sa nature centralisée et sa capacité à
 28.1002 +        verrouiller des fichiers.
 28.1003 +      </para>
 28.1004 +
 28.1005 +      <para id="x_be">Personnellement, je préfère Mercurial pour sa
 28.1006 +        simplicité, ses performances et sa bonne capacité de fusion, et il
 28.1007 +        m'a très bien rendu service de plusieurs années maintenant.
 28.1008 +      </para>
 28.1009 +
 28.1010 +    </sect2>
 28.1011 +  </sect1>
 28.1012 +  <sect1>
 28.1013 +    <title>Migrer depuis un outil à Mercurial</title>
 28.1014 +
 28.1015 +    <para id="x_bf">Mercurial est livré avec une extension nommée <literal role="hg-ext" moreinfo="none">convert</literal>, qui peut, de manière incrémentale
 28.1016 +      importer des révisions depuis différents autres outils de gestion de
 28.1017 +      source. Par <quote>incrémental</quote>, j'entends que vous pouvez
 28.1018 +      convertir l'historique entier du projet en une seule fois, puis
 28.1019 +      relancer l'outil d'import plus tard pour obtenir les modifications
 28.1020 +      effectuées depuis votre import initial.
 28.1021 +    </para>
 28.1022 +
 28.1023 +    <para id="x_c0">Les outils de gestion de source supportés par <literal role="hg-ext" moreinfo="none">convert</literal> sont :
 28.1024 +    </para>
 28.1025 +    <itemizedlist>
 28.1026 +      <listitem><para id="x_c1">Subversion</para></listitem>
 28.1027 +      <listitem><para id="x_c2">CVS</para></listitem>
 28.1028 +      <listitem><para id="x_c3">Git</para></listitem>
 28.1029 +      <listitem><para id="x_c4">Darcs</para></listitem>
 28.1030 +    </itemizedlist>
 28.1031 +
 28.1032 +    <para id="x_c5">En outre, <literal role="hg-ext" moreinfo="none">convert</literal> peut
 28.1033 +      exporter les modifications depuis Mercurial vers Subversion. Ceci rend
 28.1034 +      possible d'essayer Subversion en parallèle avant de choisir une
 28.1035 +      solution définitive, sans aucun risque de perte de données.
 28.1036 +    </para>
 28.1037 +
 28.1038 +    <para id="x_c6">La commande <command role="hg-ext-conver" moreinfo="none">convert</command> est très simple à utiliser.
 28.1039 +      Simplement, indiquez le chemin ou l'URL du dépôt de source, en lui
 28.1040 +      indiquant éventuellement le nom du chemin de destination, et la
 28.1041 +      conversion se met en route. Après cet import initial, il suffit de
 28.1042 +      relancer la commande encore une fois pour importer les modifications
 28.1043 +      effectuées depuis.
 28.1044 +    </para>
 28.1045 +  </sect1>
 28.1046 +
 28.1047 +  <sect1>
 28.1048 +    <title>Une courte histoire de la gestion de source</title>
 28.1049 +
 28.1050 +    <para id="x_c7">Le plus célèbre des anciens outils de gestion de source
 28.1051 +      est <emphasis remap="it">SCCS</emphasis> (Source Code Control System)},
 28.1052 +      que Marc Rochkind conçu dans les laboratoires de recherche de Bell
 28.1053 +      (<emphasis remap="it">Bell Labs</emphasis>), dans le début des années
 28.1054 +      70. <emphasis remap="it">SCCS</emphasis> ne fonctionnait que sur des
 28.1055 +      fichiers individuels, et obligeait chaque personne travaillant sur le
 28.1056 +      projet d'avoir un accès à un répertoire de travail commun, sur le même
 28.1057 +      système. Seulement une seule personne pouvait modifier un fichier au
 28.1058 +      même moment, ce fonctionnement était assuré par l'utilisation de verrou
 28.1059 +      (<quote>lock</quote>). Il était courant que des personnes verrouillent
 28.1060 +      des fichiers, et plus tard, oublient de le déverrouiller ; empêchant
 28.1061 +      n'importe qui d'autre de travailler sur ces fichiers sans l'aide de
 28.1062 +      l'administrateur...
 28.1063 +    </para>
 28.1064 +
 28.1065 +    <para id="x_c8">Walter Tichy a développé une alternative libre à
 28.1066 +      <emphasis remap="it">SCCS</emphasis> au début des années 80, qu'il
 28.1067 +      nomma <emphasis remap="it">RCS (Revision Control System)</emphasis>.
 28.1068 +      Comme <emphasis remap="it">SCCS</emphasis>, <emphasis remap="it">RCS</emphasis> demandait aux développeurs de travailler
 28.1069 +      sur le même répertoire partagé, et de verrouiller les fichiers pour se
 28.1070 +      prémunir de tout conflit issu de modifications concurrentes.
 28.1071 +    </para>
 28.1072 +
 28.1073 +    <para id="x_c9">Un peu plus tard dans les années 1980, Dick Grune utilisa
 28.1074 +      <emphasis remap="it">RCS</emphasis> comme une brique de base pour un
 28.1075 +      ensemble de scripts <emphasis remap="it">shell</emphasis> qu'il
 28.1076 +      intitula cmt, avant de la renommer en <emphasis remap="it">CVS
 28.1077 +        (Concurrent Versions System)</emphasis>.  La grande innovation de CVS
 28.1078 +      était que les développeurs pouvaient travailler simultanément et
 28.1079 +      indépendamment dans leur propre espace de travail. Ces espaces de
 28.1080 +      travail privés assuraient que les développeurs ne se marchent pas
 28.1081 +      mutuellement sur les pieds, comme c'était souvent le cas avec RCS et
 28.1082 +      SCCS. Tous les développeurs disposaient donc de leur copie de tous les
 28.1083 +      fichiers du projet, et ils pouvaient donc librement les modifier. Ils
 28.1084 +      devaient néanmoins effectuer la <quote>fusion</quote> (<emphasis remap="it"><quote>merge</quote></emphasis>) de leurs fichiers, avant
 28.1085 +      d'effectuer le <quote>commit</quote> de leurs modifications sur le dépôt
 28.1086 +      central.
 28.1087 +    </para>
 28.1088 +    
 28.1089 +    <para>Brian Berliner reprit les scripts de Grune's et les réécrit en C,
 28.1090 +      qu'il publia en 1989. Depuis, ce code a été modifié jusqu'à devenir la
 28.1091 +      version moderne de CVS. CVS a acquis ainsi la capacité de fonctionner
 28.1092 +      en réseau, transformant son architecture en client/serveur.
 28.1093 +      L'architecture de CVS est centralisée, seul le serveur a une copie de
 28.1094 +      l'historique du projet. L'espace de travail client ne contient qu'une
 28.1095 +      copie de la dernière version du projet, et quelques métadonnées pour
 28.1096 +      indiquer où le serveur se trouve. CVS a été un grand succès,
 28.1097 +      aujourd'hui il est probablement l'outil de gestion de contrôle le plus
 28.1098 +      utilisé au monde.
 28.1099 +    </para>
 28.1100 +    
 28.1101 +    <para>Au début des années 1990, Sun Microsystems développa un premier
 28.1102 +      outil de gestion de source distribué, nommé TeamWare. Un espace de
 28.1103 +      travail TeamWare contient une copie complète de l'historique du projet.
 28.1104 +      TeamWare n'a pas de notion de dépôt central. (CVS utilisait RCS pour le
 28.1105 +      stockage de l'historique, TeamWare utilisait SCCS).
 28.1106 +    </para>
 28.1107 +    
 28.1108 +    <para>Alors que les années 1990 avançaient, les utilisateurs ont pris
 28.1109 +      conscience d'un certain nombre de problèmes avec CVS. Il enregistrait
 28.1110 +      simultanément des modifications sur différents fichiers
 28.1111 +      individuellement, au lieu de les regrouper dans une seule opération
 28.1112 +      cohérente et atomique. Il ne gère pas bien sa hiérarchie de fichier, il
 28.1113 +      est donc assez aisé de créer le chaos en renommant les fichiers et les
 28.1114 +      répertoires. Pire encore, son code source est difficile à lire et à
 28.1115 +      maintenir, ce qui agrandit largement le <quote>niveau de
 28.1116 +        souffrance</quote> associé à la réparation de ces problèmes
 28.1117 +      d'architecture de manière prohibitive.
 28.1118 +    </para>
 28.1119 +    
 28.1120 +    <para>En 2001, Jim Blandy et Karl Fogel, deux développeurs qui avaient
 28.1121 +      travaillé sur CVS, initièrent un projet pour le remplacer par un outil
 28.1122 +      qui aurait une meilleure architecture et un code plus propre. Le
 28.1123 +      résultat, Subversion, ne quitte pas le modèle centralisé et
 28.1124 +      client/server de CVS, mais ajoute les opérations de
 28.1125 +      <quote>commit</quote> atomique sur de multiples fichiers, une meilleure
 28.1126 +      gestion des espaces de noms, et d'autres fonctionnalités qui en font un
 28.1127 +      meilleur outil que CVS. Depuis sa première publication, il est
 28.1128 +      rapidement devenu très populaire.
 28.1129 +    </para>
 28.1130 +    
 28.1131 +    <para>Plus ou moins simultanément, Graydon Hoare a commencé sur
 28.1132 +      l'ambitieux système de gestion distribué Monotone. Bien que Monotone
 28.1133 +      corrige plusieurs défauts de CVS tout en offrant une architecture
 28.1134 +      <quote>peer-to-peer</quote>, il va aussi plus loin que la plupart des
 28.1135 +      outils de révision de manière assez innovante. Il utilise des
 28.1136 +      <quote>hashs</quote> cryptographiques comme identifiants, et il a une
 28.1137 +      notion complète de <quote>confiance</quote> du code issu des
 28.1138 +      différentes sources.
 28.1139 +    </para>
 28.1140 +    
 28.1141 +    <para>Mercurial est né en 2005. Bien que très influencé par Monotone,
 28.1142 +      Mercurial se concentre sur la facilité d'utilisation, les performances
 28.1143 +      et la capacité à monter en charge pour de très gros projets.
 28.1144 +    </para>
 28.1145 +  
 28.1146 +  </sect1>
 28.1147 +
 28.1148 +</chapter>
 28.1149 +
 28.1150 +<!--
 28.1151 +local variables: 
 28.1152 +sgml-parent-document: ("00book.xml" "book" "chapter")
 28.1153 +end:
 28.1154 +-->
 28.1155 +
 28.1156 +  <!-- BEGIN ch02 -->
 28.1157 +  <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
 28.1158 +
 28.1159 +<chapter id="chap:tour-basic">
 28.1160 +  <?dbhtml filename="a-tour-of-mercurial-the-basics.html"?>
 28.1161 +  <title>Une rapide présentation de Mercurial : les bases</title>
 28.1162 +
 28.1163 +  <sect1>
 28.1164 +    <title>Installer Mercurial sur votre système</title>
 28.1165 +
 28.1166 +    <para id="x_1">Des paquetages binaires de Mercurial sont disponibles pour la
 28.1167 +      plupart des systèmes d'exploitation, ce qui rend facile l'utilisation
 28.1168 +      immédiate de Mercurial sur votre ordinateur.</para>
 28.1169 +
 28.1170 +    <sect2>
 28.1171 +      <title>Windows</title>
 28.1172 +
 28.1173 +      <para id="x_c">La meilleur version de Mercurial pour Windows est
 28.1174 +        TortoiseHg, qui peut être téléchargée ici : <ulink url="http://bitbucket.org/tortoisehg/stable/wiki/Home">http://bitbucket.org/tortoisehg/stable/wiki/Home</ulink>.
 28.1175 +        Ce logiciel n'a aucune dépendance exterieure; il fonctionne <quote>et
 28.1176 +          c'est tout</quote>. Il fournit aussi bien les outils en ligne de
 28.1177 +        commmande qu'une interface graphique.</para>
 28.1178 + 
 28.1179 +    </sect2>
 28.1180 +
 28.1181 +    <sect2>
 28.1182 +      <title>Mac OS X</title>
 28.1183 +  
 28.1184 +      <para id="x_a">Lee Cantey publie un installeur de Mercurial pour Mac OS
 28.1185 +        X sur <ulink url="http://mercurial.berkwood.com">http://mercurial.berkwood.com</ulink>.</para>
 28.1186 +    </sect2>
 28.1187 +      
 28.1188 +    <sect2>
 28.1189 +      <title>Linux</title>
 28.1190 +
 28.1191 +      <para id="x_2">Parce que chaque distribution de Linux a ses propres
 28.1192 +        outils de gestion de paquets, politiques et rythmes de
 28.1193 +        développements, il est difficile de donner un ensemble
 28.1194 +        d'instructions unique pour installer les binaires de Mercurial. La
 28.1195 +        version de Mercurial avec laquelle vous vous retrouverez dépendra
 28.1196 +        grandement de l'activité de la personne en charge du paquetage pour
 28.1197 +        la distribution.</para>
 28.1198 +
 28.1199 +      <para id="x_3">Pour rester simple, je me concentrerai sur
 28.1200 +        l'installation de Mercurial en ligne de commande, sous les
 28.1201 +        distributions les plus courantes. La plupart des distributions
 28.1202 +        fournissent des gestionnaires graphiques de paquetage qui vous
 28.1203 +        permettront d'installer Mercurial en quelques clicks. Le paquetage
 28.1204 +        devrait se nommer <literal moreinfo="none">mercurial</literal>.</para>
 28.1205 +
 28.1206 +      <itemizedlist>
 28.1207 +        <listitem><para id="x_4">Ubuntu et Debian:</para>
 28.1208 +          <programlisting format="linespecific">apt-get install mercurial</programlisting></listitem>
 28.1209 +        <listitem><para id="x_5">Fedora:</para>
 28.1210 +          <programlisting format="linespecific">yum install mercurial</programlisting></listitem>
 28.1211 +        <listitem><para id="x_6">Gentoo:</para>
 28.1212 +           <programlisting format="linespecific">emerge mercurial</programlisting></listitem>
 28.1213 +        <listitem><para id="x_715">OpenSUSE:</para>
 28.1214 +          <programlisting format="linespecific">zypper install
 28.1215 +          mercurial</programlisting></listitem>
 28.1216 +      </itemizedlist>
 28.1217 +
 28.1218 +    </sect2>
 28.1219 +    <sect2>
 28.1220 +      <title>Solaris</title>
 28.1221 +
 28.1222 +      <para id="x_09">SunFreeWare, à <ulink url="http://www.sunfreeware.com">http://www.sunfreeware.com</ulink>,
 28.1223 +      fournit des paquets précompilés pour Mercurial.</para>
 28.1224 +    </sect2>
 28.1225 +  </sect1>
 28.1226 +
 28.1227 +  <sect1>
 28.1228 +    <title>Commencer à utiliser Mercurial</title>
 28.1229 +
 28.1230 +    <para id="x_e">Pour commencer, nous utiliserons la commande <command role="hg-cmd" moreinfo="none">hg version</command> pour vérifier si Mercurial est
 28.1231 +      installé proprement. Les informations affichées sur la version ne sont
 28.1232 +      pas réellement importantes en soit, c'est surtout de savoir si elles
 28.1233 +      s'affichent qui nous intéresse.</para>
 28.1234 +
 28.1235 +    <!-- BEGIN tour.version -->
 28.1236 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg version</userinput>
 28.1237 +Mercurial Distributed SCM (version 1.2.1)
 28.1238 +
 28.1239 +Copyright (C) 2005-2009 Matt Mackall &lt;mpm@selenic.com&gt; and others
 28.1240 +This is free software; see the source for copying conditions. There is NO
 28.1241 +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 28.1242 +</screen>
 28.1243 +<!-- END tour.version -->
 28.1244 +
 28.1245 +
 28.1246 +    <sect2>
 28.1247 +      <title>L'aide intégrée</title>
 28.1248 +
 28.1249 +      <para id="x_f">Mercurial fournit un système d'aide intégré, ce qui est
 28.1250 +        inestimable quand vous vous retrouvez coincé à essayer de vous
 28.1251 +        rappeler comment lancer une commande. Si vous êtes bloqué, exécutez
 28.1252 +        simplement <command role="hg-cmd" moreinfo="none">hg help</command>; elle affichera
 28.1253 +        une brève liste des commandes, avec une description pour chacune. Si
 28.1254 +        vous demandez de l'aide sur une commande spécifique (voir
 28.1255 +        ci-dessous), elle affichera des informations plus détaillées.</para>
 28.1256 +
 28.1257 +      <!-- BEGIN tour.help -->
 28.1258 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg help init</userinput>
 28.1259 +hg init [-e CMD] [--remotecmd CMD] [DEST]
 28.1260 +
 28.1261 +create a new repository in the given directory
 28.1262 +
 28.1263 +    Initialize a new repository in the given directory. If the given
 28.1264 +    directory does not exist, it is created.
 28.1265 +
 28.1266 +    If no directory is given, the current directory is used.
 28.1267 +
 28.1268 +    It is possible to specify an ssh:// URL as the destination.
 28.1269 +    See 'hg help urls' for more information.
 28.1270 +
 28.1271 +options:
 28.1272 +
 28.1273 + -e --ssh        specify ssh command to use
 28.1274 +    --remotecmd  specify hg command to run on the remote side
 28.1275 +
 28.1276 +use "hg -v help init" to show global options
 28.1277 +</screen>
 28.1278 +<!-- END tour.help -->
 28.1279 +
 28.1280 +
 28.1281 +      <para id="x_10">Pour un niveau d'informations encore plus détaillé 
 28.1282 +        (ce dont vous aurez rarement besoin), exécuter <command role="hg-cmd" moreinfo="none">hg 
 28.1283 +        help <option role="hg-opt-global">-v</option></command>.  L'option 
 28.1284 +        <option role="hg-opt-global">-v</option> est l'abréviation de 
 28.1285 +        <option role="hg-opt-global">--verbose</option>, et indique à Mercurial 
 28.1286 +        d'ficher plus d'informations que d'habitude.</para>
 28.1287 +
 28.1288 +     </sect2>
 28.1289 +  </sect1>
 28.1290 +  <sect1>
 28.1291 +    <title>Travailler avec un dépôt</title>
 28.1292 +
 28.1293 +    <para id="x_11">Avec Mercurial, tout se déroule au sein du 
 28.1294 +      <emphasis>dépôt</emphasis>. Le dépôt d'un projet contient tous 
 28.1295 +      les fichiers qui <quote>appartiennent</quote> au projet.</para>
 28.1296 +
 28.1297 +    <para id="x_12">Il n'y a rien de particulièrement magique au sujet de 
 28.1298 +      ce dépôt, c'est simplement une arborescence sur votre système de fichiers 
 28.1299 +      que Mercurial traite de manière spéciale. Vous pouvez renommer ou effacer 
 28.1300 +      ce répertoire à n'impporte quel moment, en utilisant la ligne de commande 
 28.1301 +      ou votre explorateur de fichiers.</para>
 28.1302 +
 28.1303 +    <sect2>
 28.1304 +      <title>Faire une copie locale de votre dépôt</title>
 28.1305 +      
 28.1306 +      <para id="x_13"><emphasis>Copier</emphasis> un dépôt est juste un 
 28.1307 +        peu spécial. Bien que vous puissiez utiliser une commande habituelle de 
 28.1308 +        copie pour copier votre dépôt, il vaut mieux utiliser une commande fournie par
 28.1309 +        Mercurial. Cette commande est appelée <command role="hg-cmd" moreinfo="none">hg clone</command>, 
 28.1310 +        car elle crée une copie identique à un dépôt existant.</para>
 28.1311 +
 28.1312 +      <!-- BEGIN tour.clone -->
 28.1313 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone http://hg.serpentine.com/tutorial/hello</userinput>
 28.1314 +destination directory: hello
 28.1315 +requesting all changes
 28.1316 +adding changesets
 28.1317 +adding manifests
 28.1318 +adding file changes
 28.1319 +added 5 changesets with 5 changes to 2 files
 28.1320 +updating working directory
 28.1321 +2 files updated, 0 files merged, 0 files removed, 0 files unresolved
 28.1322 +</screen>
 28.1323 +<!-- END tour.clone -->
 28.1324 +
 28.1325 +
 28.1326 +      <para id="x_67c">Un avantage de la commande <command role="hg-cmd" moreinfo="none">hg
 28.1327 +          clone</command> est que, comme nous l'avons vu ci dessus, elle nous
 28.1328 +        permet de faire de cloner les dépôts à travers le réseau. Un autre
 28.1329 +        est qu'elle se rappelle d'où a été cloné un dépôt, ce qui est utile
 28.1330 +        quand on veut mettre à jour le clone.</para>
 28.1331 +
 28.1332 +      <para id="x_14">Si votre opération de clonage réussit, vous devriez maintenant
 28.1333 +        avoir un répertoire local appelé <filename class="directory" moreinfo="none">hello</filename>. 
 28.1334 +        Ce répertoire contiendra quelques fichiers.</para>
 28.1335 +
 28.1336 +      <!-- BEGIN tour.ls -->
 28.1337 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls -l</userinput>
 28.1338 +total 4
 28.1339 +drwxr-xr-x 3 rpelisse rpelisse 4096 Aug 16 14:05 hello
 28.1340 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls hello</userinput>
 28.1341 +Makefile  hello.c
 28.1342 +</screen>
 28.1343 +<!-- END tour.ls -->
 28.1344 +
 28.1345 +
 28.1346 +      <para id="x_15">Ces fichiers ont le même contenu et historique dans votre dépôt
 28.1347 +        qu'ils ont dans le dépôt que vous avez cloné.</para>
 28.1348 +
 28.1349 +      <para id="x_16">Chaque dépôt Mercurial est complet, autonome et
 28.1350 +        indépendant. Il contient sa propre copie privée des fichiers du
 28.1351 +        projet et de leur historique. Le clone d'un dépôt se souvient de la
 28.1352 +        localisation du dépôt à partir duquel il a été clôné, mais il ne
 28.1353 +        communique pas avec ce dernier, ou un autre, à moins que vous ne lui
 28.1354 +        demandiez.</para>
 28.1355 +
 28.1356 +      <para id="x_17">Ce que tout ceci signifie pour le moment est que nous
 28.1357 +        sommes libres d'expérimenter avec ce dépôt, confiants dans le fait
 28.1358 +        qu'il s'agit d'un <quote>bac à sable</quote> qui n'affectera personne
 28.1359 +        d'autre.</para>
 28.1360 +
 28.1361 +    </sect2>  
 28.1362 +    <sect2>
 28.1363 +      <title>Quel est le contenu d'un dépôt ?</title>
 28.1364 +
 28.1365 +      <para id="x_18">Prêtons plus attention un instant au contenu d'un dépôt. 
 28.1366 +        Nous voyons qu'il contient un répertoire nommé <filename class="directory" moreinfo="none">.hg
 28.1367 +        </filename>. C'est ici que Mercurial conserve toutes ses
 28.1368 +        métadonnées.</para>
 28.1369 +
 28.1370 +      <!-- BEGIN tour.ls-a -->
 28.1371 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd hello</userinput>
 28.1372 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls -a</userinput>
 28.1373 +.  ..  .hg  Makefile  hello.c
 28.1374 +</screen>
 28.1375 +<!-- END tour.ls-a -->
 28.1376 + 
 28.1377 +
 28.1378 +      <para id="x_19">Le contenu du répertoire <filename class="directory" moreinfo="none">.hg
 28.1379 +        </filename> et ses sous répertoires sont les seuls propres à Mercurial. 
 28.1380 +        Tous les autres fichiers et répertoires dans le dépôt sont à vous, et 
 28.1381 +        vous pouvez en faire ce que vous voulez.</para>
 28.1382 +
 28.1383 +      <para id="x_1a">Pour introduire un peu de terminologie, le répertoire 
 28.1384 +        <filename class="directory" moreinfo="none">.hg</filename> est un <quote>vrai</quote> 
 28.1385 +        dépôt, et tous les fichiers et les répertoires qui coexistent avec lui, 
 28.1386 +        sont désignés sous le nom <emphasis>espace de travail</emphasis>. Une 
 28.1387 +        manière facile de se rappeler cette distinction est de retenir que le 
 28.1388 +        <emphasis>dépôt</emphasis> contient l'<emphasis>historique</emphasis>
 28.1389 +        de votre projet, alors que l'<emphasis>espace de travail</emphasis> 
 28.1390 +        contient un "<emphasis>snapshot</emphasis>"  de votre projet à un certain 
 28.1391 +        point de son historique.</para>
 28.1392 +
 28.1393 +    </sect2>
 28.1394 +  </sect1>
 28.1395 +  <sect1>
 28.1396 +    <title>Une promenade dans l'historique</title>
 28.1397 +
 28.1398 +    <para id="x_1b">Une des premières choses que vous aurez envie 
 28.1399 +      de faire avec un nouveau dépôt, sera de comprendre son historique. 
 28.1400 +      La commande <command role="hg-cmd" moreinfo="none">hg log</command> vous donne une 
 28.1401 +      vue de l'historique.</para>
 28.1402 +
 28.1403 +    <!-- BEGIN tour.log -->
 28.1404 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log</userinput>
 28.1405 +changeset:   4:2278160e78d4
 28.1406 +tag:         tip
 28.1407 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.1408 +date:        Sat Aug 16 22:16:53 2008 +0200
 28.1409 +summary:     Trim comments.
 28.1410 +
 28.1411 +changeset:   3:0272e0d5a517
 28.1412 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.1413 +date:        Sat Aug 16 22:08:02 2008 +0200
 28.1414 +summary:     Get make to generate the final binary from a .o file.
 28.1415 +
 28.1416 +changeset:   2:fef857204a0c
 28.1417 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.1418 +date:        Sat Aug 16 22:05:04 2008 +0200
 28.1419 +summary:     Introduce a typo into hello.c.
 28.1420 +
 28.1421 +changeset:   1:82e55d328c8c
 28.1422 +user:        mpm@selenic.com
 28.1423 +date:        Fri Aug 26 01:21:28 2005 -0700
 28.1424 +summary:     Create a makefile
 28.1425 +
 28.1426 +changeset:   0:0a04b987be5a
 28.1427 +user:        mpm@selenic.com
 28.1428 +date:        Fri Aug 26 01:20:50 2005 -0700
 28.1429 +summary:     Create a standard "hello, world" program
 28.1430 +
 28.1431 +</screen>
 28.1432 +<!-- END tour.log -->
 28.1433 +
 28.1434 +
 28.1435 +    <para id="x_1c">Par défaut, cette commande affiche à l'écran un bref paragraphe pour chaque
 28.1436 +      révision enregistrée pour ce projet. Dans la terminologie de Mercurial, nous
 28.1437 +      appelons chacun de ces évènements enregistrés un <emphasis>changeset</emphasis>, parce
 28.1438 +      qu'il contient un ensemble de modifications sur plusieurs fichiers.</para>
 28.1439 +
 28.1440 +    <para id="x_1d">La commande <command role="hg-cmd" moreinfo="none">hg log</command> affiche 
 28.1441 +    ainsi ces informations :</para>
 28.1442 +
 28.1443 +    <itemizedlist>
 28.1444 +      <listitem><para id="x_1e"><literal moreinfo="none">changeset</literal> : Ce champ contient 
 28.1445 +        un nombre, séparé par deux points (:), d'une chaine hexadécimale. Il 
 28.1446 +        s'agit en fait d'<emphasis>identifiants</emphasis>  d'un changeset. Il y a 
 28.1447 +        deux identifiants car le numéro de la révision est plus court et plus à 
 28.1448 +        facile à saisir qu'une séquence hexadécimale.</para>
 28.1449 +      </listitem>
 28.1450 +      <listitem><para id="x_1f"><literal moreinfo="none">user</literal> : L'identité de la personne 
 28.1451 +        qui a créée ce  %%% laisser le terme anglais car il sera affiché
 28.1452 +        changeset. C'est un champ libre de forme, mais la plupart du
 28.1453 +        temps il contient le nom et l'email de la personne.</para>
 28.1454 +      </listitem>
 28.1455 +      <listitem><para id="x_20"><literal moreinfo="none">date</literal> : La date et l'heure à 
 28.1456 +        laquelle le \textit{changeset} a été créé, ainsi que le fuseau horaire dans 
 28.1457 +        lequelle il a été créé. (La date et l'heure sont locales à ce
 28.1458 +        \textit{fuseau}, elles indiquent donc quelle date et heure il était
 28.1459 +        pour la personne qui a créé ce changeset.</para>
 28.1460 +      </listitem>
 28.1461 +      <listitem><para id="x_21"><literal moreinfo="none">résumé</literal>: La première ligne du 
 28.1462 +        message que le créateur a associé à son changeset pour le décrire.</para>
 28.1463 +      </listitem>
 28.1464 +      <listitem><para id="x_67d">Certains changesets, comme le premier de la
 28.1465 +        liste ci-dessus ont un champ <literal moreinfo="none">tag</literal>. Le tag est une autre
 28.1466 +        façon d'identifier un changeset en lui donnant un nom simple à retenir.
 28.1467 +        (Le tag nommé <literal moreinfo="none">tip</literal> est spécial : il fait toujours
 28.1468 +        référence aux derniers changements dans le dépôt.)</para></listitem>
 28.1469 +    </itemizedlist>
 28.1470 +
 28.1471 +    <para id="x_22">Par défaut, la commande <command role="hg-cmd" moreinfo="none">hg log</command> 
 28.1472 +      n'affiche qu'un résumé, il manque beaucoup de détails.</para>
 28.1473 +
 28.1474 +    <para id="x_23">La figure <xref linkend="fig:tour-basic:history"/> fournit une 
 28.1475 +      représentation graphique de l'historique du dépôt <filename class="directory" moreinfo="none">hello
 28.1476 +      </filename>, pour rendre plus facile de voir dans quelle direction 
 28.1477 +      l'historique se <quote>déroule</quote>. Nous reviendrons régulièrement 
 28.1478 +      sur cette représentation dans ce chapitre et ceux qui suivent.</para>
 28.1479 +
 28.1480 +
 28.1481 +    <figure id="fig:tour-basic:history" float="0">
 28.1482 +      <title>Graphical history of the <filename class="directory" moreinfo="none">hello</filename> repository</title>
 28.1483 +      <mediaobject>
 28.1484 +        <imageobject><imagedata fileref="figs/tour-history.png"/></imageobject>
 28.1485 +        <textobject><phrase>XXX add text</phrase></textobject>
 28.1486 +      </mediaobject>
 28.1487 +    </figure>
 28.1488 +
 28.1489 +
 28.1490 +    <sect2>
 28.1491 +      <title>Changesets, révisions, et collaboration</title>
 28.1492 +      
 28.1493 +      <para id="x_25">Comme l'anglais est réputé pour être un langage maladroit,
 28.1494 +        et que l'informatique est la source de bien des erreurs de terminologie
 28.1495 +        (pourquoi utiliser un seul terme quand quatre feront l'affaire ?), la
 28.1496 +        gestion de version a une variété de mots et de phrases qui veulent dire
 28.1497 +        la même chose. Si vous discutez d'historique de Mercurial avec d'autres
 28.1498 +        personnes, vous constaterez que souvent, le mot <quote>changeset</quote>
 28.1499 +        est contracté simplement en <quote>change</quote> ou (à l'écrit)
 28.1500 +        <quote>cset</quote>, et même parfois un changeset
 28.1501 +        <quote>révision</quote>, abrégé en <quote>rev</quote>.</para>
 28.1502 +
 28.1503 +      <para id="x_26">Bien que le <emphasis>mot</emphasis> que vous utilisez pour 
 28.1504 +        désigner le concept de changeset importe peu, l'<emphasis>identifiant</emphasis> 
 28.1505 +        que vous utilisez pour désigner un <emphasis>changeset</emphasis> spécifique 
 28.1506 +        a une grande importance. Rappelez vous que le champ changeset affiché par la
 28.1507 +        commande <command role="hg-cmd" moreinfo="none">hg log</command> identifie un changeset à
 28.1508 +        la fois avec un numéro de révision et une séquence hexadécimale.</para>
 28.1509 +
 28.1510 +      <itemizedlist>
 28.1511 +        <listitem><para id="x_27">Le numéro de révision est <emphasis>seulement 
 28.1512 +        valable dans ce dépôt</emphasis>,</para></listitem>
 28.1513 +        <listitem><para id="x_28">La séquence hexadécimale est un
 28.1514 +        <emphasis>identifiant permanent, et invariant</emphasis> qui 
 28.1515 +        pourra toujours être associé au changeset exact de <emphasis>chaque</emphasis> 
 28.1516 +        copie de votre dépôt.</para></listitem></itemizedlist>
 28.1517 +
 28.1518 +      <para id="x_29">La distinction est importante. Si vous envoyez un email 
 28.1519 +         à quelqu'un en parlant de la <quote>révision 33</quote>, il est très 
 28.1520 +         probable que sa révision 33 <emphasis>ne sera pas la même</emphasis> 
 28.1521 +         que la votre. La raison de ceci est que le numéro de révision dépend 
 28.1522 +         de l'ordre dans lequel les modifications sont arrivées dans le dépôt, 
 28.1523 +         et il n'y a aucune garantie que les mêmes changements soient arrivés 
 28.1524 +         dans le même ordre dans différents dépôts. Trois modifications
 28.1525 +         <literal moreinfo="none">a,b,c</literal> peuvent aisément apparaitre dans un dépôt 
 28.1526 +         comme <literal moreinfo="none">0,1,2</literal>, et dans un autre comme <literal moreinfo="none">0,2,1
 28.1527 +         </literal>.</para>
 28.1528 +
 28.1529 +      <para id="x_2a">Mercurial utilise les numéros de révision uniquement comme des raccourcis
 28.1530 +        pratiques. Si vous devez discuter d'un \textit{changeset} avec quelqu'un,
 28.1531 +        ou identifer un \textit{changeset} pour une quelconque raison (par exemple,
 28.1532 +        un rapport de \textit{bug}), utilisez la séquence hexadécimale.</para>
 28.1533 +
 28.1534 +    </sect2>
 28.1535 +    <sect2>
 28.1536 +      <title>Afficher une révision spécifique</title>
 28.1537 +
 28.1538 +      <para id="x_2b">Pour réduire la sortie de <command role="hg-cmd" moreinfo="none">hg log
 28.1539 +        </command> à une seule révision, utilisez l'option <option role="hg-opt-log">-r
 28.1540 +        </option> (ou <option role="hg-opt-log">--rev</option>). Vous pouvez utiliser
 28.1541 +        le numéro de révision ou la séquence hexadécimale comme identifiant, et
 28.1542 +        demander autant de révisions que vous le souhaitez.</para>
 28.1543 +
 28.1544 +      <!-- BEGIN tour.log-r -->
 28.1545 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r 3</userinput>
 28.1546 +changeset:   3:0272e0d5a517
 28.1547 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.1548 +date:        Sat Aug 16 22:08:02 2008 +0200
 28.1549 +summary:     Get make to generate the final binary from a .o file.
 28.1550 +
 28.1551 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r 0272e0d5a517</userinput>
 28.1552 +changeset:   3:0272e0d5a517
 28.1553 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.1554 +date:        Sat Aug 16 22:08:02 2008 +0200
 28.1555 +summary:     Get make to generate the final binary from a .o file.
 28.1556 +
 28.1557 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r 1 -r 4</userinput>
 28.1558 +changeset:   1:82e55d328c8c
 28.1559 +user:        mpm@selenic.com
 28.1560 +date:        Fri Aug 26 01:21:28 2005 -0700
 28.1561 +summary:     Create a makefile
 28.1562 +
 28.1563 +changeset:   4:2278160e78d4
 28.1564 +tag:         tip
 28.1565 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.1566 +date:        Sat Aug 16 22:16:53 2008 +0200
 28.1567 +summary:     Trim comments.
 28.1568 +
 28.1569 +</screen>
 28.1570 +<!-- END tour.log-r -->
 28.1571 +
 28.1572 +
 28.1573 +      <para id="x_2c">Si vous voulez voir l'historique de plusieurs révisions
 28.1574 +        sans avoir à les énumérer, vous pouvez utiliser la <emphasis>intervalle
 28.1575 +        de numérotation</emphasis> qui vous permet d'exprimer l'idée <quote>je
 28.1576 +        veux toutes les révisions entre $a$ et $b$, inclus</quote></para>
 28.1577 +
 28.1578 +      <!-- BEGIN tour.log.range -->
 28.1579 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r 2:4</userinput>
 28.1580 +changeset:   2:fef857204a0c
 28.1581 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.1582 +date:        Sat Aug 16 22:05:04 2008 +0200
 28.1583 +summary:     Introduce a typo into hello.c.
 28.1584 +
 28.1585 +changeset:   3:0272e0d5a517
 28.1586 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.1587 +date:        Sat Aug 16 22:08:02 2008 +0200
 28.1588 +summary:     Get make to generate the final binary from a .o file.
 28.1589 +
 28.1590 +changeset:   4:2278160e78d4
 28.1591 +tag:         tip
 28.1592 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.1593 +date:        Sat Aug 16 22:16:53 2008 +0200
 28.1594 +summary:     Trim comments.
 28.1595 +
 28.1596 +</screen>
 28.1597 +<!-- END tour.log.range -->
 28.1598 +
 28.1599 +
 28.1600 +      <para id="x_2d">Mercurial respecte aussi l'ordre dans lequel vous spécifiez
 28.1601 +        les révisions, ainsi <command role="hg-cmd" moreinfo="none">hg log -r 2:4</command>
 28.1602 +        affichera <literal moreinfo="none">2,3,4</literal> alors que <command role="hg-cmd" moreinfo="none">hg
 28.1603 +        log -r 4:2</command> affichera <literal moreinfo="none">4,3,2</literal>.</para>
 28.1604 +
 28.1605 +    </sect2>  
 28.1606 +    <sect2>
 28.1607 +      <title>Informations détaillées</title>
 28.1608 +
 28.1609 +      <para id="x_2e">Le résumé affiché par <command role="hg-cmd" moreinfo="none">hg log</command> 
 28.1610 +        est suffisant si vous savez déjà ce que vous cherchez. En 
 28.1611 +        revanche, vous aurez probablement besoin de voir une description 
 28.1612 +        complète du changement, ou une liste des fichiers modifiés si vous 
 28.1613 +        cherchez à déterminer qu'un changeset est bien celui que vous
 28.1614 +        recherchez. L'option \hgopt{-v} de la commande <command role="hg-cmd" moreinfo="none">hg 
 28.1615 +        log</command> (ou <option role="hp-opt-global">--verbose</option>) vous 
 28.1616 +        donne ces informations supplémentaires.</para>
 28.1617 +
 28.1618 +      <!-- BEGIN tour.log-v -->
 28.1619 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -v -r 3</userinput>
 28.1620 +changeset:   3:0272e0d5a517
 28.1621 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.1622 +date:        Sat Aug 16 22:08:02 2008 +0200
 28.1623 +files:       Makefile
 28.1624 +description:
 28.1625 +Get make to generate the final binary from a .o file.
 28.1626 +
 28.1627 +
 28.1628 +</screen>
 28.1629 +<!-- END tour.log-v -->
 28.1630 +
 28.1631 +
 28.1632 +      <para id="x_2f">Si vous voulez voir à la fois la description 
 28.1633 +        et le contenu d'une modification, ajouter l'option <option role="hg-opt-log">-p</option> (ou <option role="hg-opt-log">
 28.1634 +        --patch</option>). Ceci affiche le contenu d'une modification 
 28.1635 +        comme un <emphasis>diff unifié</emphasis>
 28.1636 +        <!-- \footnote{NdT: \textit{unified diff}} -->
 28.1637 +        (si vous n'avez jamais vu de diff unifié avant, consultez la 
 28.1638 +        section <xref linkend="sec:mq:patch"/> pour un rapide 
 28.1639 +        survol).</para>
 28.1640 +
 28.1641 +      <!-- BEGIN tour.log-vp -->
 28.1642 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -v -p -r 2</userinput>
 28.1643 +changeset:   2:fef857204a0c
 28.1644 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.1645 +date:        Sat Aug 16 22:05:04 2008 +0200
 28.1646 +files:       hello.c
 28.1647 +description:
 28.1648 +Introduce a typo into hello.c.
 28.1649 +
 28.1650 +
 28.1651 +diff -r 82e55d328c8c -r fef857204a0c hello.c
 28.1652 +--- a/hello.c	Fri Aug 26 01:21:28 2005 -0700
 28.1653 ++++ b/hello.c	Sat Aug 16 22:05:04 2008 +0200
 28.1654 +@@ -11,6 +11,6 @@
 28.1655 + 
 28.1656 + int main(int argc, char **argv)
 28.1657 + {
 28.1658 +-	printf("hello, world!\n");
 28.1659 ++	printf("hello, world!\");
 28.1660 + 	return 0;
 28.1661 + }
 28.1662 +
 28.1663 +</screen>
 28.1664 +<!-- END tour.log-vp -->
 28.1665 +
 28.1666 +
 28.1667 +      <para id="x_67e">L'option <option role="hg-opt-log">-p</option> est
 28.1668 +        incroyablement utile, il est donc important dans s'en rappeller.</para>
 28.1669 +
 28.1670 +    </sect2>
 28.1671 +  </sect1>
 28.1672 +  <sect1>
 28.1673 +    <title>Tout sur les options de commandes</title>
 28.1674 +    
 28.1675 +    <para id="x_30">Avant d'aller plus loin sur le fonctionnement 
 28.1676 +      des commandes de Mercurial, étudions un moment comment elles 
 28.1677 +      fonctionnent de manière générale. Vous trouverez ça probablement 
 28.1678 +      utile pour la suite de notre parcours.</para>
 28.1679 +
 28.1680 +    <para id="x_31">Mercurial utilise une approche directe et cohérente 
 28.1681 +      pour interpréter les options que vous passez aux commandes. Il suit une
 28.1682 +      convention commune à la plupart des systèmes Unix et Linux modernes.</para>
 28.1683 +
 28.1684 +    <itemizedlist>
 28.1685 +      <listitem><para id="x_32">Chaque option a un nom complet. Par exemple, 
 28.1686 +        comme nous l'avons déjà vu, la commande <command role="hg-cmd" moreinfo="none">hg 
 28.1687 +        log</command> accepte l'option <option role="hg-opt-log">--rev
 28.1688 +        </option>.</para>
 28.1689 +      </listitem>
 28.1690 +      <listitem><para id="x_33">La plupart des options disposent de 
 28.1691 +        noms abrégés. Aussi, au lieu d'utiliser <option role="hg-opt-log">--rev
 28.1692 +        </option>, vous pouvez utiliser <option role="hg-opt-log">-r</option>. 
 28.1693 +        (Les options qui  n'ont pas de noms abrégés sont généralement 
 28.1694 +        rarement utilisées).</para>
 28.1695 +      </listitem>
 28.1696 +      <listitem><para id="x_34">Les noms complets commencent par deux 
 28.1697 +        tirets (i.e. <option role="hg-opt-log">--rev</option>),
 28.1698 +        alors que les options courtes commencent avec un seul (i.e. 
 28.1699 +        <option role="hg-opt-log">-r</option>).</para>
 28.1700 +      </listitem>
 28.1701 +     <listitem><para id="x_35">Les noms des options sont cohérents 
 28.1702 +       entre les commandes. Par exemple, chaque commande qui accepte 
 28.1703 +       un changeset ID ou un numéro de révision accepte aussi <option role="hg-opt-log">-r</option> et <option role="hg-opt-log">--rev
 28.1704 +       </option> comme arguments.</para>
 28.1705 +     </listitem>
 28.1706 +   </itemizedlist>
 28.1707 +
 28.1708 +   <para id="x_36">Dans les exemples de ce livre, j'utilise les noms abrégés 
 28.1709 +     plutôt que les noms complets. Ceci est une préférence personnelle, pas 
 28.1710 +     une recommandation.</para>
 28.1711 +
 28.1712 +   <para id="x_37">La plupart des commandes qui affichent une quelconque sortie 
 28.1713 +     à l'écran, afficheront davantage avec l'option <option role="hg-opt-global">
 28.1714 +     -v</option> (ou <option role="hg-opt-global">--verbose</option>), et
 28.1715 +     moins avec l'option <option role="hg-opt-global">-q</option> (ou 
 28.1716 +     <option role="hg-opt-global">--quiet</option>).</para>
 28.1717 +
 28.1718 +    <note>
 28.1719 +      <title>Option naming consistency</title>
 28.1720 +      
 28.1721 +      <para id="x_680">Presque toujours, les commandes de Mercurial utilisent
 28.1722 +      des noms d'options cohérentes pour référer à des concepts identiques.
 28.1723 +      Par exemple, si une commande concerne les changesets, vous les
 28.1724 +      identifierez toujours avec l'option <option role="hg-opt-log">-r</option>.
 28.1725 +      Cette utilisation cohérente des noms d'options permet de mémoriser plus
 28.1726 +      facilement quelles options accepte une commande.</para>
 28.1727 +   </note>
 28.1728 +
 28.1729 +
 28.1730 +  </sect1>
 28.1731 +  <sect1>
 28.1732 +    <title>Faire et vérifier des modifications</title>
 28.1733 +
 28.1734 +    <para id="x_38">Maintenant que nous avons une bonne idée des 
 28.1735 +      commandes pour consulter l'historique de Mercurial, regardons 
 28.1736 +      comment faire des modifications et les examiner.</para>
 28.1737 +     
 28.1738 +    <para id="x_39">La première chose que nous allons faire c'est isoler notre
 28.1739 +      expérience dans un dépôt à part. Nous allons utiliser la commande <command role="hg-cmd" moreinfo="none">hg clone</command>, mais nous n'avons pas besoin de faire
 28.1740 +      une copie de dépôt distant. Comme nous avons déjà une copie locale, nous
 28.1741 +      pouvons juste faire un clone de celle-ci à la place. C'est beaucoup plus
 28.1742 +      rapide que de faire une copie à travers le réseau, et un dépôt cloné
 28.1743 +      localement prend également moins d'espace disque<footnote>
 28.1744 +      <para id="x_681">L'économie d'espace disque apparait clairement quand les
 28.1745 +        dépôts source et destination sont sur le même système de fichier, où, dans
 28.1746 +        ce cas, Mercurial utilisera des liens physiques pour effectuer des partages
 28.1747 +        copie-lors-des-écritures de ses métadonnées internes. Si cette explication
 28.1748 +        ne signifie rien pour vous, ne vous inquietez pas : tout ceci se passe de
 28.1749 +        manière transparente et automatiquement. Vous n'avez pas du tout besoin de
 28.1750 +        comprendre ceci.</para></footnote>.</para>
 28.1751 +  
 28.1752 +    <!-- BEGIN tour.reclone -->
 28.1753 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput>
 28.1754 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone hello my-hello</userinput>
 28.1755 +updating working directory
 28.1756 +2 files updated, 0 files merged, 0 files removed, 0 files unresolved
 28.1757 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd my-hello</userinput>
 28.1758 +</screen>
 28.1759 +<!-- END tour.reclone -->
 28.1760 +
 28.1761 +
 28.1762 +    <para id="x_3a">On notera au passage qu'il est souvent considéré comme
 28.1763 +      une bonne pratique de conserver une copie <quote>immaculée</quote>
 28.1764 +      du dépôt distant, à partir de laquelle vous pourrez faire des 
 28.1765 +      copies locales temporaires pour créer des <quote>bacs à sable</quote> 
 28.1766 +      pour chaque tâche sur laquelle vous souhaitez travailler. Ceci 
 28.1767 +      vous permet de travailler sur plusieurs choses en parallèle, 
 28.1768 +      chacune isolée les unes des autres en attendant que ces tâches 
 28.1769 +      soient finies et que vous soyez prêt à les réintégrer. Parce 
 28.1770 +      que les copies locales sont peu coûteuses, il est très rapide 
 28.1771 +      de créer ou détruire des dépôts dès que vous n'en avez plus
 28.1772 +      besoin.</para>
 28.1773 +
 28.1774 +    <para id="x_3b">Dans notre dépôt <filename class="directory" moreinfo="none">my-hello</filename>, nous avons un fichier
 28.1775 +      <filename moreinfo="none">hello.c</filename> qui contient le classique <quote>hello,
 28.1776 +        world</quote>.</para>
 28.1777 +   
 28.1778 +    <!-- BEGIN tour.cat1 -->
 28.1779 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat hello.c</userinput>
 28.1780 +/*
 28.1781 + * Placed in the public domain by Bryan O'Sullivan.  This program is
 28.1782 + * not covered by patents in the United States or other countries.
 28.1783 + */
 28.1784 +
 28.1785 +#include &lt;stdio.h&gt;
 28.1786 +
 28.1787 +int main(int argc, char **argv)
 28.1788 +{
 28.1789 +	printf("hello, world!\");
 28.1790 +	return 0;
 28.1791 +}
 28.1792 +</screen>
 28.1793 +<!-- END tour.cat1 -->
 28.1794 +
 28.1795 +
 28.1796 +    <para id="x_682">Editons ce fichier pour qu'il affiche une autre ligne
 28.1797 +      sur la sortie standard.</para>
 28.1798 +    
 28.1799 +    <!-- BEGIN tour.cat2 -->
 28.1800 +<screen format="linespecific"># ... edit edit edit ...
 28.1801 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat hello.c</userinput>
 28.1802 +/*
 28.1803 + * Placed in the public domain by Bryan O'Sullivan.  This program is
 28.1804 + * not covered by patents in the United States or other countries.
 28.1805 + */
 28.1806 +
 28.1807 +#include &lt;stdio.h&gt;
 28.1808 +
 28.1809 +int main(int argc, char **argv)
 28.1810 +{
 28.1811 +	printf("hello, world!\");
 28.1812 +	printf("hello again!\n");
 28.1813 +	return 0;
 28.1814 +}
 28.1815 +</screen>
 28.1816 +<!-- END tour.cat2 -->
 28.1817 +
 28.1818 +
 28.1819 +    <para id="x_3c">La commande Mercurial <command role="hg-cmd" moreinfo="none">hg
 28.1820 +        status</command> nous dira ce que Mercurial sait des fichiers du
 28.1821 +      dépôts.</para>
 28.1822 +
 28.1823 +    <!-- BEGIN tour.status -->
 28.1824 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls</userinput>
 28.1825 +Makefile  hello.c
 28.1826 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
 28.1827 +M hello.c
 28.1828 +</screen>
 28.1829 +<!-- END tour.status -->
 28.1830 +
 28.1831 +
 28.1832 +    <para id="x_3d">La commande <command role="hg-cmd" moreinfo="none">hg status</command>
 28.1833 +      n'affichera pas le contenu des fichiers, mais une ligne commençant par
 28.1834 +      <quote><literal moreinfo="none">M</literal></quote> pour <filename moreinfo="none">hello.c</filename>.
 28.1835 +      A moins que vous lui demandiez, la commande <command role="hg-cmd" moreinfo="none">hg
 28.1836 +        status</command> n'affichera aucune information sur les fichiers que
 28.1837 +      vous n'avez pas modifiés.</para>
 28.1838 + 
 28.1839 +    <para id="x_3e">Le <quote><literal moreinfo="none">M</literal></quote> indique que
 28.1840 +      Mercurial a remarqué que nous avons modifié le fichier
 28.1841 +      <filename moreinfo="none">hello.c</filename>. Nous n'avons pas besoin
 28.1842 +      <emphasis>d'informer</emphasis> Mercurial que nous allons modifier un
 28.1843 +      fichier avant de commencer à le faire, ou que nous avons modifié un
 28.1844 +      fichier après avoir commencé à le faire, il est capable de découvrir ça
 28.1845 +      tout seul. </para>
 28.1846 +
 28.1847 +    <para id="x_3f">C'est déjà pratique de savoir que nous avons modifié le
 28.1848 +      fichier <filename moreinfo="none">hello.c</filename>, mais nous préférerions savoir
 28.1849 +      exactement <emphasis>ce que</emphasis> nous avons changé. Pour ceci, nous
 28.1850 +      utilisons la commande <command role="hg-cmd" moreinfo="none">hg diff</command>.</para>
 28.1851 +
 28.1852 +    <!-- BEGIN tour.diff -->
 28.1853 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg diff</userinput>
 28.1854 +diff -r 2278160e78d4 hello.c
 28.1855 +--- a/hello.c	Sat Aug 16 22:16:53 2008 +0200
 28.1856 ++++ b/hello.c	Sun Aug 16 14:05:26 2009 +0000
 28.1857 +@@ -8,5 +8,6 @@
 28.1858 + int main(int argc, char **argv)
 28.1859 + {
 28.1860 + 	printf("hello, world!\");
 28.1861 ++	printf("hello again!\n");
 28.1862 + 	return 0;
 28.1863 + }
 28.1864 +</screen>
 28.1865 +<!-- END tour.diff -->
 28.1866 +
 28.1867 +
 28.1868 +    <tip>
 28.1869 +      <title>Comprendre les patches</title>
 28.1870 +   
 28.1871 +      <para id="x_683">Penser à jeter un oeil à <xref linkend="sec:mq:patch"/> si vous n'arrivez pas à lire la sortie
 28.1872 +        ci-dessus.</para>
 28.1873 +    </tip>
 28.1874 +  </sect1>
 28.1875 +  <sect1>
 28.1876 +    <title>Enregister vos modifications dans une nouvelle révision</title>
 28.1877 +   
 28.1878 +    <para id="x_40">Nous pouvons modifier des fichiers, compiler et tester
 28.1879 +      nos modifications, et utiliser les commandes <command role="hg-cmd" moreinfo="none">hg
 28.1880 +        status</command> et <command role="hg-cmd" moreinfo="none">hg diff</command> pour
 28.1881 +      voir les modifications effectuées, jusqu'à ce que nous soyons assez
 28.1882 +      satisfaits pour décider d'enregistrer notre travail dans un
 28.1883 +      \textit{changeset}.</para>
 28.1884 +
 28.1885 +    <para id="x_41">La commande <command role="hg-cmd" moreinfo="none">hg commit</command>
 28.1886 +      vous laisse créer une nouvelle révision, nous désignerons généralement
 28.1887 +      cette opération par <quote>faire un commit</quote> ou
 28.1888 +      <quote>committer</quote>.</para>
 28.1889 +
 28.1890 +    <sect2>
 28.1891 +    <title>Définir le nom d'utilisateur</title>
 28.1892 +
 28.1893 +      <para id="x_42">Quand vous exécutez la commande <command role="hg-cmd" moreinfo="none">hg commit</command> pour la première fois, il n'est
 28.1894 +        pas garanti qu'elle réussisse du premier coup. En effet, Mercurial
 28.1895 +        enregistre votre nom et votre adresse avec chaque modification que
 28.1896 +        vous effectuez, de manière à ce que vous soyez capable (ou d'autres
 28.1897 +        le soient) de savoir qui a fait quelle modification. Mercurial essaye
 28.1898 +        automatiquement de découvrir un nom d'utilisateur qui ait un minimum
 28.1899 +        de sens pour effectuer l'opération de commit avec. Il va essayer
 28.1900 +        chacune des méthodes suivantes, dans l'ordre :</para>
 28.1901 +
 28.1902 +      <orderedlist inheritnum="ignore" continuation="restarts">
 28.1903 +        <listitem><para id="x_43">Si vous spécifiez l'option <option role="hg-opt-commit">-u</option> avec la commande <command role="hg-cmd" moreinfo="none">hg commit</command>, suivi d'un nom
 28.1904 +            d'utilisateur, ceci aura toujours la priorité sur les autres
 28.1905 +            méthodes ci dessous.</para></listitem>
 28.1906 +        <listitem><para id="x_44">Si vous avez défini une variable
 28.1907 +            d'environnement <envar>HGUSER</envar>, c'est cette valeur qui est
 28.1908 +            alors utilisée.</para></listitem>
 28.1909 +        <listitem><para id="x_45">Si vous créez un fichier nommé <filename role="special" moreinfo="none">.hgrc</filename> dans votre répertoire
 28.1910 +            \textit{home}, avec une entrée <envar role="rc-item-ui">username</envar>, c'est la valeur associée
 28.1911 +            qui sera utilisée. Pour voir à quoi ressemble le contenu de ce
 28.1912 +            fichier regardez la section <xref linkend="sec:tour-basic:username"/>
 28.1913 +            ci-dessous.</para></listitem>
 28.1914 +        <listitem><para id="x_46">Si vous avez défini une variable
 28.1915 +            d'environnement <envar>EMAIL</envar> celle ci sera utilisée
 28.1916 +            ensuite.</para></listitem>
 28.1917 +        <listitem><para id="x_47">Enfin, Mercurial interrogera votre système
 28.1918 +            pour trouver votre nom d'utilisateur local ainsi que le nom de la
 28.1919 +            machine hôte, et il fabriquera un nom d'utilisateur à partir de
 28.1920 +            ces données. Comme il arrive souvent que ce genre de noms soit
 28.1921 +            totalement inutile, il vous préviendra en affichant un message
 28.1922 +            d'avertissement.</para></listitem>
 28.1923 +      </orderedlist>
 28.1924 +   
 28.1925 +      <para id="x_48">Si tous ces mécanismes échouent, Mercurial n'exécutera
 28.1926 +        pas la commande, affichant un message d'erreur. Dans ce cas, il ne
 28.1927 +        vous laissera pas effectuer de commit tant que vous n'aurez pas
 28.1928 +        défini un nom d'utilisateur.</para>
 28.1929 +   
 28.1930 +      <para id="x_49">Vous devriez penser à utiliser la variable
 28.1931 +        d'environement <envar>HGUSER</envar> et l'option <option role="hg-opt-commit">-u</option> comme moyen pour
 28.1932 +        <emphasis>changer</emphasis> le nom d'utilisateur par défaut. Pour
 28.1933 +        une utilisation normale, la manière la plus simple et robuste
 28.1934 +        d'opérer est de créer un fichier <filename role="special" moreinfo="none">.hgrc</filename>, voir ci-dessous pour  les détails
 28.1935 +        à ce sujet.</para>
 28.1936 +
 28.1937 +      <sect3 id="sec:tour-basic:username">
 28.1938 +        <title>Créer un fichier de configuration pour Mercurial</title>
 28.1939 +
 28.1940 +        <para id="x_4a">Pour définir un nom d'utilisateur, utilisez votre 
 28.1941 +          éditeur de texte favori pour créer un fichier <filename role="special" moreinfo="none">.hgrc</filename> dans votre répertoire home. 
 28.1942 +          Mercurial va utiliser ce fichier pour retrouver votre 
 28.1943 +          configuration personnelle. Le contenu initial devrait
 28.1944 +          ressembler à ceci :</para>
 28.1945 +   
 28.1946 +        <tip>
 28.1947 +          <title><quote>Home directory</quote> sous Windows</title>
 28.1948 +   
 28.1949 +          <para id="x_716">Quand on parle de répertoire home, sur une version
 28.1950 +            anglaise d'une installation de Windows, il s'agira habituellement
 28.1951 +            d'un répertoire nommée comme votre nom dans <filename moreinfo="none">C:\Documents 
 28.1952 +              and Settings</filename>. Vous pouvez trouver de quelle répertoire
 28.1953 +            il s'agit en lançant une fenêtre d'interpréteur de commande et en
 28.1954 +            exécutant la commande suivante :</para>
 28.1955 +          
 28.1956 +          <screen format="linespecific"><prompt moreinfo="none">C:\</prompt> <userinput moreinfo="none">echo
 28.1957 +              %UserProfile</userinput></screen>
 28.1958 +        </tip>
 28.1959 +   
 28.1960 +        <programlisting format="linespecific"># This is a Mercurial configuration file.
 28.1961 +[ui]
 28.1962 +username = Firstname Lastname &lt;email.address@domain.net&gt;</programlisting>
 28.1963 +
 28.1964 +        <para id="x_4b">La ligne avec <literal moreinfo="none">[ui]</literal> commence une
 28.1965 +          <emphasis>section</emphasis> du fichier de configuration, ainsi la ligne
 28.1966 +          <quote><literal moreinfo="none">username = ...</literal></quote> signifie <quote>
 28.1967 +            définir la valeur de l'élément <literal moreinfo="none">username</literal> dans la
 28.1968 +            section <literal moreinfo="none">ui</literal></quote>. Une section continue jusqu'à ce
 28.1969 +          qu'une nouvelle commence, ou que la fin du fichier soit atteinte.
 28.1970 +          Mercurial ignore les lignes vides et traite tout texte situé à la suite
 28.1971 +          d'un <quote><literal moreinfo="none">#</literal></quote> jusqu'à la fin de la ligne
 28.1972 +          comme un commentaire.</para>
 28.1973 +
 28.1974 +      </sect3>
 28.1975 +      <sect3>
 28.1976 +        <title>Choisir un nom d'utilisateur</title>
 28.1977 + 
 28.1978 +        <para id="x_4c">Vous pouvez utiliser n'importe quelle valeur 
 28.1979 +          pour votre <literal moreinfo="none">username</literal>, car cette information 
 28.1980 +          est destinée à d'autres personnes et non à être interprétée 
 28.1981 +          par Mercurial. La convention que la plupart des personnes
 28.1982 +          suivent est d'utiliser leurs noms suivies de leurs adresses emails,
 28.1983 +          comme montré ci-dessus :</para>
 28.1984 +        <note>
 28.1985 +          <para id="x_4d">Le mécanisme interne du serveur web intégré à Mercurial,
 28.1986 +            masque les adresses emails, pour rendre plus difficile leurs
 28.1987 +            récupérations par les outils utilisés par les spammmers.
 28.1988 +            Ceci réduit la probabilité que de recevoir encore plus de
 28.1989 +            spam si vous vous publiez un dépôt sur internet.</para>
 28.1990 +        </note>
 28.1991 +      </sect3>
 28.1992 +    </sect2>
 28.1993 +    <sect2>
 28.1994 +      <title>Rédiger un message de \textit{commit}</title>
 28.1995 +  
 28.1996 +      <para id="x_4e">Lorsqu'on effectue une opération de commit, Mercurial
 28.1997 +        lance automatiquement un éditeur de texte pour permettre de saisir
 28.1998 +        un message qui décrira les modifications effectuées dans cette
 28.1999 +        révision. Ce message est nommé le <emphasis>message de commit</emphasis>. 
 28.2000 +        Ce sera un enregistrement pour tout lecteur expliquant le pourquoi 
 28.2001 +        et le comment de vos modifications, et il sera affiché par la 
 28.2002 +        commande <command role="hg-cmd" moreinfo="none">hg log</command>.</para>
 28.2003 + 
 28.2004 +      <!-- BEGIN tour.commit -->
 28.2005 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit</userinput>
 28.2006 +</screen>
 28.2007 +<!-- END tour.commit -->
 28.2008 + 
 28.2009 +  
 28.2010 +      <para id="x_4f">L'éditeur que la commande <command role="hg-cmd" moreinfo="none">hg 
 28.2011 +          commit</command> déclenche ne contiendra qu'une ligne vide suivi 
 28.2012 +        d'un certain nombre de lignes commençant par <quote><literal moreinfo="none">HG:
 28.2013 +        </literal></quote>.</para>
 28.2014 +    
 28.2015 +        <programlisting format="linespecific">
 28.2016 +    This is where I type my commit comment.
 28.2017 +    
 28.2018 +    HG: Enter commit message.  Lines beginning with 'HG:' are removed.
 28.2019 +    HG: --
 28.2020 +    HG: user: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.2021 +    HG: branch 'default'
 28.2022 +    HG: changed hello.c</programlisting>
 28.2023 +
 28.2024 +
 28.2025 +      <para id="x_50">Mercurial ignore les lignes qui commencent 
 28.2026 +        avec <quote><literal moreinfo="none">HG:</literal></quote>, il ne les 
 28.2027 +        utilise que pour nous indiquer quels fichiers modifiés il se
 28.2028 +        prépare à \textit{commiter}. Modifier ou effacer ces lignes n'a
 28.2029 +        aucune conséquence sur l'opération de commit.
 28.2030 +      </para>
 28.2031 +
 28.2032 +    </sect2>
 28.2033 +    <sect2>
 28.2034 +      <title>Rédiger un message \textit{approprié}</title>
 28.2035 +  
 28.2036 +      <para id="x_51">Comme <command role="hg-cmd" moreinfo="none">hg log</command> n'affiche
 28.2037 +        que la première ligne du message de commit par défaut, il est souvent
 28.2038 +        considéré comme une bonne pratique de rédiger des messages de commit
 28.2039 +        qui tiennent sur une seule ligne. Voilà un exemple concret de message 
 28.2040 +        de commit qui <emphasis>ne suit pas</emphasis> cette directive, et
 28.2041 +        qui a donc un résumé peu lisible.</para>
 28.2042 +
 28.2043 +      <programlisting format="linespecific">
 28.2044 +changeset:   73:584af0e231be
 28.2045 +user:        Censored Person &lt;censored.person@example.org&gt;
 28.2046 +date:        Tue Sep 26 21:37:07 2006 -0700
 28.2047 +summary:     include buildmeister/commondefs.   Add an exports and install
 28.2048 +      </programlisting>
 28.2049 +  
 28.2050 +      <para id="x_52">A ce sujet, il faut noter qu'il n'existe pas de règle 
 28.2051 +        absolue dans ce domaine. Mercurial lui-même n'interprète pas les 
 28.2052 +        contenus des messages de commit, ainsi votre projet est libre de 
 28.2053 +        concevoir différentes politiques de mise en page des messages.</para>
 28.2054 +      
 28.2055 +      <para id="x_53">Ma préférence personnelle va au message court, mais 
 28.2056 +        informatif, qui offre des précisions supplémentaires par rapport à ce 
 28.2057 +        que pourrait m'apprendre une commande <command role="hg-cmd" moreinfo="none">hg log 
 28.2058 +          --patch</command>.</para>
 28.2059 +      
 28.2060 +      <para id="x_55">Si vous exécutez la commande <command role="hg-cmd" moreinfo="none">hg
 28.2061 +          commit</command> sans aucun argument, elle enregistre tous les 
 28.2062 +        changements qui ont été fait, et qui sont indiqué par les commandes
 28.2063 +        <command role="hg-cmd" moreinfo="none">hg status</command> et  <command role="hg-cmd" moreinfo="none">hg diff</command>.</para>
 28.2064 +      
 28.2065 +      <note>
 28.2066 +        <title>Une surprise pour les utilisateurs habitués à Subversion</title>
 28.2067 +   
 28.2068 +        <para id="x_717">Comme n'importe quel autre commande de Mercurial, si
 28.2069 +          vous soumettez pas de manière explicite les noms des fichiers à
 28.2070 +          committer à la commande <command role="hg-cmd" moreinfo="none">hg commit</command>, elle
 28.2071 +          va travailler sur l'ensemble du répertoire de travail. Soyez conscient
 28.2072 +          de ceci si vous venez du monde Subversion ou CVS, car vous pourriez
 28.2073 +          attendre qu'elle opère uniquement le répertoire courant et ses sous
 28.2074 +          répertoires.</para>
 28.2075 +      </note>
 28.2076 +    </sect2>
 28.2077 +    <sect2>
 28.2078 +      <title>Annuler un \textit{commit}</title>
 28.2079 +
 28.2080 +      <para id="x_54">Si, en rédigeant le message, vous décidez que 
 28.2081 +        finalement vous ne voulez pas effectuer ce commit, il suffit 
 28.2082 +        de quitter simplement l'éditeur sans sauver. Ceci n'aura aucune 
 28.2083 +        conséquence sur le dépôt ou les fichiers du répertoire de 
 28.2084 +        travail.</para>
 28.2085 +    </sect2>
 28.2086 +  
 28.2087 +    <sect2>
 28.2088 +      <title>Admirer votre travail</title>
 28.2089 +  
 28.2090 +      <para id="x_56">Une fois que votre \textit{commit} est terminé, vous
 28.2091 +        pouvez utiliser la commande <command role="hg-cmd" moreinfo="none">hg tip</command>
 28.2092 +        pour afficher le \textit{changeset} que vous venez de créer. Cette
 28.2093 +        commande produit  une sortie à l'écran qui est identique à celle du
 28.2094 +        <command role="hg-cmd" moreinfo="none">hg log</command>, mais qui n'affiche que la
 28.2095 +        dernière révision du dépôt.</para>
 28.2096 + 
 28.2097 +      <!-- BEGIN tour.tip -->
 28.2098 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip -vp</userinput>
 28.2099 +changeset:   5:c94f208d1dfb
 28.2100 +tag:         tip
 28.2101 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.2102 +date:        Sun Aug 16 14:05:26 2009 +0000
 28.2103 +files:       hello.c
 28.2104 +description:
 28.2105 +Added an extra line of output
 28.2106 +
 28.2107 +
 28.2108 +diff -r 2278160e78d4 -r c94f208d1dfb hello.c
 28.2109 +--- a/hello.c	Sat Aug 16 22:16:53 2008 +0200
 28.2110 ++++ b/hello.c	Sun Aug 16 14:05:26 2009 +0000
 28.2111 +@@ -8,5 +8,6 @@
 28.2112 + int main(int argc, char **argv)
 28.2113 + {
 28.2114 + 	printf("hello, world!\");
 28.2115 ++	printf("hello again!\n");
 28.2116 + 	return 0;
 28.2117 + }
 28.2118 +
 28.2119 +</screen>
 28.2120 +<!-- END tour.tip -->
 28.2121 + 
 28.2122 +  
 28.2123 +      <para id="x_57">On fait couramment référence à la dernière révision 
 28.2124 +        du dépôt comme étant la <emphasis>révision tip</emphasis>, ou plus
 28.2125 +        simplement le <emphasis>tip</emphasis>.</para>
 28.2126 +  
 28.2127 +      <para id="x_684">Au passage, la commande <command role="hg-cmd" moreinfo="none">hg
 28.2128 +          tip</command> accepte la plupart des options qu'accepte 
 28.2129 +        <command role="hg-cmd" moreinfo="none">hg log</command>. Ainsi <option role="hg-opt-global">-v</option> ci dessus implique <quote>soit
 28.2130 +          verbeux</quote>, <option role="hg-opt-tip">-p</option>
 28.2131 +        veux dire <quote>affiche le patch</quote>. L'utilisation de l'option
 28.2132 +        <option role="hg-opt-tip">-p</option> pour afficher un patch est un
 28.2133 +        autre exemple de la cohérence des commandes évoquée plus tôt.</para>
 28.2134 +
 28.2135 +    </sect2>
 28.2136 +  </sect1>
 28.2137 +  <sect1>
 28.2138 +    <title>Partager ses modifications</title>
 28.2139 +
 28.2140 +    <para id="x_58">Nous avons mentionné plus haut que les dépôts 
 28.2141 +      de Mercurial sont autosuffisants. Ce qui signifie que la nouvelle
 28.2142 +      révision que vous venez de créer existe seulement dans votre 
 28.2143 +      répertoire <filename class="directory" moreinfo="none">my-hello</filename>. Étudions 
 28.2144 +      comment propager cette modification dans d'autres dépôts.</para>
 28.2145 +
 28.2146 +    <sect2 id="sec:tour:pull">
 28.2147 +      <title>Récupérer les modifications d'autres dépôts</title>
 28.2148 +
 28.2149 +      <para id="x_59">Pour commencer, construisons un clone de notre dépôt 
 28.2150 +        <filename class="directory" moreinfo="none">hello</filename> qui ne contiendra pas 
 28.2151 +        le changement que nous venons d'effectuer. Nous l'appellerons notre 
 28.2152 +        dépôt temporaire <filename class="directory" moreinfo="none">hello-pull</filename>.</para>
 28.2153 + 
 28.2154 +      <!-- BEGIN tour.clone-pull -->
 28.2155 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput>
 28.2156 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone hello hello-pull</userinput>
 28.2157 +updating working directory
 28.2158 +2 files updated, 0 files merged, 0 files removed, 0 files unresolved
 28.2159 +</screen>
 28.2160 +<!-- END tour.clone-pull -->
 28.2161 +
 28.2162 + 
 28.2163 +      <para id="x_5a">Nous allons utiliser la commande <command role="hg-cmd" moreinfo="none">hg pull</command> pour envoyer les modifications
 28.2164 +        depuis <filename class="directory" moreinfo="none">my-hello</filename> dans <filename class="directory" moreinfo="none">hello-pull</filename>. Néanmoins, récupérer
 28.2165 +        aveuglement des modifications depuis un dépôt a quelque chose d'un
 28.2166 +        peu effrayant. Mercurial propose donc une commande <command role="hg-cmd" moreinfo="none">hg incoming</command> qui permet de savoir quelles
 28.2167 +        modifications la commande <command role="hg-cmd" moreinfo="none">hg pull</command>
 28.2168 +        <emphasis>pourrait</emphasis> entraîner dans notre dépôt, et ceci
 28.2169 +        sans effectuer réellement de modification dessus.</para>
 28.2170 +
 28.2171 +      <!-- BEGIN tour.incoming -->
 28.2172 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd hello-pull</userinput>
 28.2173 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg incoming ../my-hello</userinput>
 28.2174 +comparing with ../my-hello
 28.2175 +searching for changes
 28.2176 +changeset:   5:c94f208d1dfb
 28.2177 +tag:         tip
 28.2178 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.2179 +date:        Sun Aug 16 14:05:26 2009 +0000
 28.2180 +summary:     Added an extra line of output
 28.2181 +
 28.2182 +</screen>
 28.2183 +<!-- END tour.incoming -->
 28.2184 + 
 28.2185 +  
 28.2186 +      <para id="x_5c">Apporter les modifications rapatriées dans un dépôt se
 28.2187 +        résume donc à exécuter la commande <command role="hg-cmd" moreinfo="none">hg
 28.2188 +          pull</command>, et préciser depuis quel dépôt effectuer le <command role="hg-cmd" moreinfo="none">hg pull</command>.</para>
 28.2189 +      
 28.2190 +      <!-- BEGIN tour.pull -->
 28.2191 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput>
 28.2192 +changeset:   4:2278160e78d4
 28.2193 +tag:         tip
 28.2194 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.2195 +date:        Sat Aug 16 22:16:53 2008 +0200
 28.2196 +summary:     Trim comments.
 28.2197 +
 28.2198 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull ../my-hello</userinput>
 28.2199 +pulling from ../my-hello
 28.2200 +searching for changes
 28.2201 +adding changesets
 28.2202 +adding manifests
 28.2203 +adding file changes
 28.2204 +added 1 changesets with 1 changes to 1 files
 28.2205 +(run 'hg update' to get a working copy)
 28.2206 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput>
 28.2207 +changeset:   5:c94f208d1dfb
 28.2208 +tag:         tip
 28.2209 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.2210 +date:        Sun Aug 16 14:05:26 2009 +0000
 28.2211 +summary:     Added an extra line of output
 28.2212 +
 28.2213 +</screen>
 28.2214 +<!-- END tour.pull -->
 28.2215 +
 28.2216 +  
 28.2217 +      <para id="x_5d">Comme vous le voyez avec une sortie avant et après de la
 28.2218 +        commande <command role="hg-cmd" moreinfo="none">hg tip</command>, nous avons réussi à
 28.2219 +        récupérer aisément les modifications dans notre dépôt. Il reste néanmoins
 28.2220 +        quelque chose à faire avant de placer ces modifications dans l'espace de
 28.2221 +        travail.</para>
 28.2222 +   
 28.2223 +      <tip>
 28.2224 +        <title>Récupérer des changements précis</title>
 28.2225 +   
 28.2226 +        <para id="x_5b">Il est possible à cause du délai entre l'exécution de la
 28.2227 +          commande <command role="hg-cmd" moreinfo="none">hg incoming</command> et l'exécution de
 28.2228 +          la commande <command role="hg-cmd" moreinfo="none">hg pull</command>, que vous ne
 28.2229 +          puissiez pas voir toutes les modifications que vous rapporterez d'un
 28.2230 +          autre dépôt. Supposons que vous récupériez les modifications d'un dépôt
 28.2231 +          situé quelque part sur le réseau. Alors que vous regardez le résultat de
 28.2232 +          la commande <command role="hg-cmd" moreinfo="none">hg incoming</command>, et avant que
 28.2233 +          vous ne décidiez de récupérer ces modifications, quelqu'un peut ajouter
 28.2234 +          de nouvelles révisions dans le dépôt distant. Ce qui signifie que vous
 28.2235 +          récupérez plus de révision que ce que vous aviez regardées en utilisant
 28.2236 +          la commande <command role="hg-cmd" moreinfo="none">hg incoming</command>.</para>
 28.2237 +
 28.2238 +        <para id="x_718">Si vous voulez seulement récupérer ce que vous aviez
 28.2239 +          vérifier à l'aide de la commande <command role="hg-cmd" moreinfo="none">hg
 28.2240 +            incoming</command>, ou que pour d'autres raisons vous souhaitiez ne
 28.2241 +          récupérer qu'un sous ensemble des révisions supplémentaires
 28.2242 +          disponibles, indiquant simplement les modifications que vous souhaitez
 28.2243 +          récupérer par leurs ID de révision, soit <command moreinfo="none">hg pull
 28.2244 +            -r7e95bb</command>. </para>
 28.2245 +      </tip>
 28.2246 +  
 28.2247 +    </sect2>
 28.2248 +    <sect2>
 28.2249 +      <title>Mise à jour de l'espace de travail</title>
 28.2250 +  
 28.2251 +      <para id="x_5e">Nous avons jusqu'à maintenant grossièrement défini la
 28.2252 +        relation entre un dépôt et un espace de travail. La commande <command role="hg-cmd" moreinfo="none">hg pull</command> que nous avons exécutée dans la section 
 28.2253 +        <xref linkend="sec:tour:pull"/> a apporté des modifications, que nous
 28.2254 +        avons vérifiées, dans notre dépôt, mais il n'y a aucune trace de ces
 28.2255 +        modifications dans notre espace de travail. En effet, <command role="hg-cmd" moreinfo="none">hg pull</command> ne touche pas (par défaut) à l'espace
 28.2256 +        de travail. C'est la commande <command role="hg-cmd" moreinfo="none">hg update</command>
 28.2257 +        qui s'en charge.</para>
 28.2258 + 
 28.2259 +      <!-- BEGIN tour.update -->
 28.2260 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">grep printf hello.c</userinput>
 28.2261 +	printf("hello, world!\");
 28.2262 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg update tip</userinput>
 28.2263 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 28.2264 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">grep printf hello.c</userinput>
 28.2265 +	printf("hello, world!\");
 28.2266 +	printf("hello again!\n");
 28.2267 +</screen>
 28.2268 +<!-- END tour.update -->
 28.2269 +
 28.2270 +  
 28.2271 +      <para id="x_5f">Il peut sembler un peu étrange que la commande <command role="hg-cmd" moreinfo="none">hg pull</command> ne mette pas à jour l'espace de travail
 28.2272 +        automatiquement. Il y a en fait une très bonne raison à cela : vous
 28.2273 +        pouvez utilisez la commande <command role="hg-cmd" moreinfo="none">hg update</command>
 28.2274 +        pour mettre à jour votre espace de travail à l'état dans lequel il était 
 28.2275 +        à <emphasis>n'importe quelle révision</emphasis> de l'historique du dépôt. 
 28.2276 +        Si vous aviez un espace de travail contenant une ancienne
 28.2277 +        révision—pour chercher l'origine d'un bug, par exemple—et
 28.2278 +        que vous effectuiez un <command role="hg-cmd" moreinfo="none">hg pull</command> qui
 28.2279 +        mettrait à jour automatiquement votre espace de travail, vous ne seriez
 28.2280 +        probablement pas très satisfait.</para>
 28.2281 +  
 28.2282 +      <para id="x_60">Néanmoins, comme les opérations de pull sont très souvent
 28.2283 +        suivies d'un update, Mercurial vous permet de combiner les
 28.2284 +        deux aisément en passant l'option <option role="hg-opt-pull">-u</option> 
 28.2285 +        à la commande <command role="hg-cmd" moreinfo="none">hg pull</command>.</para>
 28.2286 +  
 28.2287 +      <para id="x_61">Si vous étudiez de nouveau la sortie de la commande <command role="hg-cmd" moreinfo="none">hg pull</command> dans la section <xref linkend="sec:tour:pull"/> quand nous l'avons exécutée sans l'option
 28.2288 +        <option role="hg-opt-pull">-u</option>, vous pouvez constater qu'elle a
 28.2289 +        affiché un rappel assez utile : vous devez encore effectuer une
 28.2290 +        opération pour mettre à jour votre espace de travail.</para>
 28.2291 +
 28.2292 +      <para id="x_62">Pour découvrir sur quelle révision de l'espace de 
 28.2293 +        travail on se trouve, utilisez la commande <command role="hg-cmd" moreinfo="none">hg
 28.2294 +          parents</command>.</para>
 28.2295 + 
 28.2296 +      <!-- BEGIN tour.parents -->
 28.2297 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg parents</userinput>
 28.2298 +changeset:   5:c94f208d1dfb
 28.2299 +tag:         tip
 28.2300 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.2301 +date:        Sun Aug 16 14:05:26 2009 +0000
 28.2302 +summary:     Added an extra line of output
 28.2303 +
 28.2304 +</screen>
 28.2305 +<!-- END tour.parents -->
 28.2306 +
 28.2307 +   
 28.2308 +      <para id="x_63">Si vous regardez de nouveau le dessin <xref linkend="fig:tour-basic:history"/>, vous verrez les flèches reliant
 28.2309 +        entre elles les révisions. Le nœud d'où la flèche
 28.2310 +        <emphasis>part</emphasis> est dans chaque cas un parent,
 28.2311 +        et le nœud où la flèche <emphasis>arrive</emphasis> est un
 28.2312 +        enfant.</para>
 28.2313 +
 28.2314 +      <para id="x_64">Pour mettre à jour l'espace de travail d'une révision
 28.2315 +        particulière, indiquez un numéro de révision ou un \textit{changeset
 28.2316 +        ID} à la commande <command role="hg-cmd" moreinfo="none">hg update</command>.</para>
 28.2317 +  
 28.2318 +      <!-- BEGIN tour.older -->
 28.2319 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg update 2</userinput>
 28.2320 +2 files updated, 0 files merged, 0 files removed, 0 files unresolved
 28.2321 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg parents</userinput>
 28.2322 +changeset:   2:fef857204a0c
 28.2323 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.2324 +date:        Sat Aug 16 22:05:04 2008 +0200
 28.2325 +summary:     Introduce a typo into hello.c.
 28.2326 +
 28.2327 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg update</userinput>
 28.2328 +2 files updated, 0 files merged, 0 files removed, 0 files unresolved
 28.2329 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg parents</userinput>
 28.2330 +changeset:   5:c94f208d1dfb
 28.2331 +tag:         tip
 28.2332 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.2333 +date:        Sun Aug 16 14:05:26 2009 +0000
 28.2334 +summary:     Added an extra line of output
 28.2335 +
 28.2336 +</screen>
 28.2337 +<!-- END tour.older -->
 28.2338 +
 28.2339 +   
 28.2340 +      <para id="x_65">Si vous ne précisez pas de manière explicite de numéro 
 28.2341 +        de révision la commande <command role="hg-cmd" moreinfo="none">hg update</command>
 28.2342 +        mettra à jour votre espace de travail avec le contenu de la révison
 28.2343 +        \textit{tip}, comme montré dans l'exemple ci dessus lors du second
 28.2344 +        appel à <command role="hg-cmd" moreinfo="none">hg update</command>.</para>
 28.2345 +    
 28.2346 +    </sect2>
 28.2347 +    <sect2>
 28.2348 +      <title>Transférer les modifications vers un autre dépôt</title>
 28.2349 +  
 28.2350 +      <para id="x_66">Mercurial vous laisse transférer les modifications vers
 28.2351 +        un autre dépôt, depuis votre dépôt actuel. Comme dans l'exemple du
 28.2352 +        <command role="hg-cmd" moreinfo="none">hg pull</command> ci-dessus, nous allons créer
 28.2353 +        un dépôt temporaire vers lequel transférer nos modifications.</para>
 28.2354 +        
 28.2355 +      <!-- BEGIN tour.clone-push -->
 28.2356 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput>
 28.2357 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone hello hello-push</userinput>
 28.2358 +updating working directory
 28.2359 +2 files updated, 0 files merged, 0 files removed, 0 files unresolved
 28.2360 +</screen>
 28.2361 +<!-- END tour.clone-push -->
 28.2362 +
 28.2363 +  
 28.2364 +      <para id="x_67">La commande <command role="hg-cmd" moreinfo="none">hg outgoing</command>
 28.2365 +        nous indique quels changements nous allons transférer vers l'autre
 28.2366 +        serveur.</para>
 28.2367 + 
 28.2368 +      <!-- BEGIN tour.outgoing -->
 28.2369 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd my-hello</userinput>
 28.2370 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg outgoing ../hello-push</userinput>
 28.2371 +comparing with ../hello-push
 28.2372 +searching for changes
 28.2373 +changeset:   5:c94f208d1dfb
 28.2374 +tag:         tip
 28.2375 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.2376 +date:        Sun Aug 16 14:05:26 2009 +0000
 28.2377 +summary:     Added an extra line of output
 28.2378 +
 28.2379 +</screen>
 28.2380 +<!-- END tour.outgoing -->
 28.2381 +
 28.2382 +  
 28.2383 +      <para id="x_68">Et la commande <command role="hg-cmd" moreinfo="none">hg push</command> 
 28.2384 +        effectue réellement le transfert.</para>
 28.2385 + 
 28.2386 +      <!-- BEGIN tour.push -->
 28.2387 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg push ../hello-push</userinput>
 28.2388 +pushing to ../hello-push
 28.2389 +searching for changes
 28.2390 +adding changesets
 28.2391 +adding manifests
 28.2392 +adding file changes
 28.2393 +added 1 changesets with 1 changes to 1 files
 28.2394 +</screen>
 28.2395 +<!-- END tour.push -->
 28.2396 +
 28.2397 +  
 28.2398 +      <para id="x_69">Comme avec <command role="hg-cmd" moreinfo="none">hg pull</command>, la
 28.2399 +        commande <command role="hg-cmd" moreinfo="none">hg push</command> ne met pas à jour
 28.2400 +        le répertoire de travail du dépôt dans lequel il transfère les
 28.2401 +        modifications. À l'inverse de <command role="hg-cmd" moreinfo="none">hg
 28.2402 +          pull</command>, <command role="hg-cmd" moreinfo="none">hg push</command> ne fournit
 28.2403 +        pas d'option <literal moreinfo="none">-u</literal> pour forcer la mise à jour de
 28.2404 +        l'espace de travail cible. Cette asymétrie est délibéré : le dépot
 28.2405 +        vers lequel nous transférons peut très bien être un serveur distant
 28.2406 +        et partagé par plusieurs personnes. Si nous devions mettre à jour son
 28.2407 +        répertoire de travail alors que quelqu'un d'autre travaille dessus,
 28.2408 +        nous risquerions de perturber son travail.</para>
 28.2409 +  
 28.2410 +      <para id="x_6a">Qu'est ce qui se passe lorsque vous essayez de récupérer
 28.2411 +        ou de transférer vos modifications et que le dépôt cible a déjà reçu
 28.2412 +        ces modifications ? Rien de bien excitant.</para>
 28.2413 + 
 28.2414 +      <!-- BEGIN tour.push.nothing -->
 28.2415 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg push ../hello-push</userinput>
 28.2416 +pushing to ../hello-push
 28.2417 +searching for changes
 28.2418 +no changes found
 28.2419 +</screen>
 28.2420 +<!-- END tour.push.nothing -->
 28.2421 +
 28.2422 +  
 28.2423 +    </sect2>
 28.2424 +  
 28.2425 +    <sect2>
 28.2426 +      <title>Emplacements par défaut</title>
 28.2427 +
 28.2428 +      <para id="x_719">Quand nous faisons un clone d'un dépôt, Mercurial
 28.2429 +        enregistre l'emplacement du dépôt d'origine dans le fichier
 28.2430 +        <filename moreinfo="none">.hg/hgrc</filename> de notre nouveau dépôt. Si nous ne
 28.2431 +        fournissons pas d'emplacement à la commande <command moreinfo="none">hg
 28.2432 +          pull</command> ou à la commande <command moreinfo="none">hg push</command>, ces
 28.2433 +        commandes utiliseront alors cet emplacement comme valeur par défaut.
 28.2434 +        Les commandes <command moreinfo="none">hg incoming</command> et <command moreinfo="none">hg
 28.2435 +          outgoing</command> feront de même.</para>
 28.2436 +  
 28.2437 +      <para id="x_71a">Si vous regardez le fichier
 28.2438 +        <filename moreinfo="none">.hg/hgrc</filename>, vous constaterez que son contenu
 28.2439 +        ressemble à ce qui suit.</para>
 28.2440 +  
 28.2441 +      <programlisting format="linespecific">[paths]
 28.2442 +default = http://www.selenic.com/repo/hg</programlisting>
 28.2443 +      
 28.2444 +      <para id="x_71b">Il est possible—et souvent
 28.2445 +        pratique—d'avoir un emplacement par défaut pour les commandes
 28.2446 +        <command moreinfo="none">hg push</command> et <command moreinfo="none">hg outgoing</command>
 28.2447 +        différent de celui des commandes <command moreinfo="none">hg pull</command> et
 28.2448 +        <command moreinfo="none">hg incoming</command>. C'est faisable en ajoutant une entrée
 28.2449 +        <literal moreinfo="none">default-push</literal> à la section
 28.2450 +        <literal moreinfo="none">[paths]</literal> du <filename moreinfo="none">.hg/hgrc</filename>, comme
 28.2451 +        suit.</para>
 28.2452 +   
 28.2453 +      <programlisting format="linespecific">[paths]
 28.2454 +default = http://www.selenic.com/repo/hg
 28.2455 +default-push = http://hg.example.com/hg</programlisting>
 28.2456 +
 28.2457 +    </sect2>
 28.2458 +    <sect2>
 28.2459 +      <title>Partager ses modifications à travers le réseau</title>
 28.2460 +  
 28.2461 +      <para id="x_6b">Les commandes que nous avons étudiées dans les sections
 28.2462 +        précédentes ne sont pas limitées aux dépôts locaux. Chacune fonctionne 
 28.2463 +        de la même manière à travers une connexion réseau, il suffit de lui 
 28.2464 +        passer une URL à la place d'un chemin de fichier local.</para>
 28.2465 + 
 28.2466 +      <!-- BEGIN tour.outgoing.net -->
 28.2467 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg outgoing http://hg.serpentine.com/tutorial/hello</userinput>
 28.2468 +comparing with http://hg.serpentine.com/tutorial/hello
 28.2469 +searching for changes
 28.2470 +changeset:   5:c94f208d1dfb
 28.2471 +tag:         tip
 28.2472 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.2473 +date:        Sun Aug 16 14:05:26 2009 +0000
 28.2474 +summary:     Added an extra line of output
 28.2475 +
 28.2476 +</screen>
 28.2477 +<!-- END tour.outgoing.net -->
 28.2478 +
 28.2479 +  
 28.2480 +      <para id="x_6c">Dans cet exemple, nous allons voir quels changements 
 28.2481 +        nous pourrions transférer vers le dépôt distant, mais le dépôt est, 
 28.2482 +        de manière tout à fait compréhensible, pas configuré pour accepter 
 28.2483 +        des modifications d'utilisateurs anonymes.</para>
 28.2484 + 
 28.2485 +      <!-- BEGIN tour.push.net -->
 28.2486 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg push http://hg.serpentine.com/tutorial/hello</userinput>
 28.2487 +pushing to http://hg.serpentine.com/tutorial/hello
 28.2488 +searching for changes
 28.2489 +ssl required
 28.2490 +</screen>
 28.2491 +<!-- END tour.push.net -->
 28.2492 + 
 28.2493 +    
 28.2494 +    </sect2>
 28.2495 +
 28.2496 +  </sect1>
 28.2497 +
 28.2498 +  <sect1>
 28.2499 +    <title>Commencer un nouveau projet</title>
 28.2500 +
 28.2501 +    <para id="x_71c">Il est tout aussi aisé de commencer un nouveau projet
 28.2502 +      que de travailler sur un qui existe déjà. La commande <command moreinfo="none">hg
 28.2503 +        init</command> crée un nouveau dépôt Mercurial vide.</para>
 28.2504 +
 28.2505 +    <!-- BEGIN ch01/new.init -->
 28.2506 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init myproject</userinput>
 28.2507 +</screen>
 28.2508 +<!-- END ch01/new.init -->
 28.2509 +
 28.2510 +
 28.2511 +    <para id="x_71d">Ceci crée simplement un répertoire nommé
 28.2512 +      <filename moreinfo="none">myproject</filename> dans le répertoire courant.</para>
 28.2513 +
 28.2514 +    <!-- BEGIN ch01/new.ls -->
 28.2515 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls -l</userinput>
 28.2516 +total 12
 28.2517 +-rw-r--r-- 1 rpelisse rpelisse   47 Aug 16 14:04 goodbye.c
 28.2518 +-rw-r--r-- 1 rpelisse rpelisse   45 Aug 16 14:04 hello.c
 28.2519 +drwxr-xr-x 3 rpelisse rpelisse 4096 Aug 16 14:04 myproject
 28.2520 +</screen>
 28.2521 +<!-- END ch01/new.ls -->
 28.2522 +
 28.2523 +
 28.2524 +    <para id="x_71e">Nous pouvons dire que <filename moreinfo="none">myproject</filename> est
 28.2525 +      un dépôt Mercurial car il contient un répertoire
 28.2526 +      <filename moreinfo="none">.hg</filename>.</para>
 28.2527 +
 28.2528 +    <!-- BEGIN ch01/new.ls2 -->
 28.2529 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls -al myproject</userinput>
 28.2530 +total 12
 28.2531 +drwxr-xr-x 3 rpelisse rpelisse 4096 Aug 16 14:04 .
 28.2532 +drwx------ 3 rpelisse rpelisse 4096 Aug 16 14:04 ..
 28.2533 +drwxr-xr-x 3 rpelisse rpelisse 4096 Aug 16 14:04 .hg
 28.2534 +</screen>
 28.2535 +<!-- END ch01/new.ls2 -->
 28.2536 +
 28.2537 +
 28.2538 +    <para id="x_71f">Si vous voulons ajouter quelques fichiers préexistants
 28.2539 +      dans ce dépôt, il suffit de les recopier dans le répertoire de travail,
 28.2540 +      et demander à Mercurial de commencer à les suivre en utilisant la
 28.2541 +      commande <command moreinfo="none">hg add</command>.</para>
 28.2542 +
 28.2543 +    <!-- BEGIN ch01/new.add -->
 28.2544 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd myproject</userinput>
 28.2545 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cp ../hello.c .</userinput>
 28.2546 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cp ../goodbye.c .</userinput>
 28.2547 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add</userinput>
 28.2548 +adding goodbye.c
 28.2549 +adding hello.c
 28.2550 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
 28.2551 +A goodbye.c
 28.2552 +A hello.c
 28.2553 +</screen>
 28.2554 +<!-- END ch01/new.add -->
 28.2555 +
 28.2556 +
 28.2557 +    <para id="x_720">Une fois que nous sommes satisfaits de notre projet,
 28.2558 +      nous pouvons commencer à ajouter nos révisions.</para>
 28.2559 +
 28.2560 +    <!-- BEGIN ch01/new.commit -->
 28.2561 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Initial commit'</userinput>
 28.2562 +</screen>
 28.2563 +<!-- END ch01/new.commit -->
 28.2564 +
 28.2565 +
 28.2566 +    <para id="x_721">Il ne prend que quelques instants pour commencer à
 28.2567 +      utiliser Mercurial sur un nouveau projet, ce qui fait aussi de ses
 28.2568 +      points forts. Travailler avec une gestion de révision devient très
 28.2569 +      facile, nous pouvons même l'utiliser pour les plus petits projets où
 28.2570 +      nous aurions probablement jamais penser utiliser un outils aussi
 28.2571 +      complexe.</para>
 28.2572 +  </sect1>
 28.2573 +</chapter>
 28.2574 +
 28.2575 +<!--
 28.2576 +local variables: 
 28.2577 +sgml-parent-document: ("00book.xml" "book" "chapter")
 28.2578 +end:
 28.2579 +-->
 28.2580 +
 28.2581 +  <!-- BEGIN ch03 -->
 28.2582 +  <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
 28.2583 +
 28.2584 +<chapter id="chap:tour-merge">
 28.2585 +  <?dbhtml filename="a-tour-of-mercurial-merging-work.html"?>
 28.2586 +  <title>Un rapide tour de Mercurial: fusionner les travaux</title>
 28.2587 +  
 28.2588 +  <para id="x_338">Nous avons maintenant étudié comment cloner un dépôt, effectuer
 28.2589 +    des changements dedans, et récupérer ou transférer depuis un
 28.2590 +    autre dépôt. La prochaine étape est donc de <emphasis>fusionner</emphasis> les
 28.2591 +    modifications de différents dépôts.</para>
 28.2592 +
 28.2593 +  <sect1>
 28.2594 +    <title>Fusionner différents travaux</title>
 28.2595 +      <para id="x_339">La fusion  est un aspect fondamental lorsqu'on
 28.2596 +      travaille iavec un gestionnaire de source distribué.</para>
 28.2597 +
 28.2598 +      <itemizedlist>
 28.2599 +        <listitem>
 28.2600 +          <para id="x_33a">Alice et Bob ont chacun une copie personnelle du dépôt d'un
 28.2601 +            projet sur lequel ils collaborent. Alice corrige un bug
 28.2602 +            dans son dépôt, et Bob ajoute une nouvelle fonctionnalité dans le
 28.2603 +            sien. Ils veulent un dépôt partagé avec à la fois le correctif du
 28.2604 +            bug et la nouvelle fonctionnalité.</para>
 28.2605 +       </listitem>
 28.2606 +       <listitem>
 28.2607 +         <para id="x_33b">Je travaille régulièrement sur plusieurs tâches différentes sur
 28.2608 +           un seul projet en même temps, chacun isolé dans son propre dépôt.
 28.2609 +           Travailler ainsi signifie que je dois régulièrement fusionner une
 28.2610 +           partie de mon code avec celui des autres.</para>
 28.2611 +       </listitem>
 28.2612 +     </itemizedlist>
 28.2613 +
 28.2614 +     <para id="x_33c">Parce que la fusion est une opération si commune à réaliser,
 28.2615 +       Mercurial la rend facile. Étudions ensemble le déroulement des
 28.2616 +       opérations. Nous commencerons encore par faire un clone d'un autre
 28.2617 +       dépôt (vous voyez que l'on fait ça tout le temps ?) puis nous ferons 
 28.2618 +       quelques modifications dessus.</para>
 28.2619 +       
 28.2620 +       <!-- BEGIN tour.merge.clone -->
 28.2621 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput>
 28.2622 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone hello my-new-hello</userinput>
 28.2623 +updating working directory
 28.2624 +2 files updated, 0 files merged, 0 files removed, 0 files unresolved
 28.2625 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd my-new-hello</userinput>
 28.2626 +# Make some simple edits to hello.c.
 28.2627 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">my-text-editor hello.c</userinput>
 28.2628 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'A new hello for a new day.'</userinput>
 28.2629 +</screen>
 28.2630 +<!-- END tour.merge.clone -->
 28.2631 +
 28.2632 +       
 28.2633 +     <para id="x_33d">Nous devrions avoir maintenant deux copies de
 28.2634 +       <filename moreinfo="none">hello.c</filename> avec des contenus différents. Les
 28.2635 +       historiques de ces deux dépôts ont aussi divergés, comme illustré dans
 28.2636 +       la figure <xref linkend="fig:tour-merge:sep-repos"/>.</para>
 28.2637 +
 28.2638 +      <!-- BEGIN tour.merge.cat1 -->
 28.2639 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat hello.c</userinput>
 28.2640 +/*
 28.2641 + * Placed in the public domain by Bryan O'Sullivan.  This program is
 28.2642 + * not covered by patents in the United States or other countries.
 28.2643 + */
 28.2644 +
 28.2645 +#include &lt;stdio.h&gt;
 28.2646 +
 28.2647 +int main(int argc, char **argv)
 28.2648 +{
 28.2649 +	printf("once more, hello.\n");
 28.2650 +	printf("hello, world!\");
 28.2651 +	printf("hello again!\n");
 28.2652 +	return 0;
 28.2653 +}
 28.2654 +</screen>
 28.2655 +<!-- END tour.merge.cat1 -->
 28.2656 +
 28.2657 +     
 28.2658 +     <para id="x_722">Et ici est notre légèrement différente version du
 28.2659 +       dépôt.</para>
 28.2660 +     
 28.2661 +      <!-- BEGIN tour.merge.cat2 -->
 28.2662 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat ../my-hello/hello.c</userinput>
 28.2663 +/*
 28.2664 + * Placed in the public domain by Bryan O'Sullivan.  This program is
 28.2665 + * not covered by patents in the United States or other countries.
 28.2666 + */
 28.2667 +
 28.2668 +#include &lt;stdio.h&gt;
 28.2669 +
 28.2670 +int main(int argc, char **argv)
 28.2671 +{
 28.2672 +	printf("hello, world!\");
 28.2673 +	printf("hello again!\n");
 28.2674 +	return 0;
 28.2675 +}
 28.2676 +</screen>
 28.2677 +<!-- END tour.merge.cat2 -->
 28.2678 +
 28.2679 +     
 28.2680 +     <figure id="fig:tour-merge:sep-repos" float="0">
 28.2681 +       <title>Historique divergent des dépôts <filename class="directory" moreinfo="none">my-hello</filename> et <filename class="directory" moreinfo="none">my-new-hello</filename>.</title>
 28.2682 +       <mediaobject>
 28.2683 +         <imageobject><imagedata fileref="figs/tour-merge-sep-repos.png"/></imageobject>
 28.2684 +         <textobject><phrase>XXX ajoute un test</phrase></textobject>
 28.2685 +       </mediaobject>
 28.2686 +     </figure>
 28.2687 +
 28.2688 +     <para id="x_33f">Nous savons déjà que récupérer les modifications depuis
 28.2689 +       notre dépôt <filename class="directory" moreinfo="none">my-hello</filename> n'aura
 28.2690 +       aucun effet sur l'espace de travail.</para>
 28.2691 +
 28.2692 +      <!-- BEGIN tour.merge.pull -->
 28.2693 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull ../my-hello</userinput>
 28.2694 +pulling from ../my-hello
 28.2695 +searching for changes
 28.2696 +adding changesets
 28.2697 +adding manifests
 28.2698 +adding file changes
 28.2699 +added 1 changesets with 1 changes to 1 files (+1 heads)
 28.2700 +(run 'hg heads' to see heads, 'hg merge' to merge)
 28.2701 +</screen>
 28.2702 +<!-- END tour.merge.pull -->
 28.2703 +
 28.2704 +
 28.2705 +     <para id="x_340">Néanmoins, la commande <command role="hg-cmd" moreinfo="none">hg
 28.2706 +       pull</command> nous indique quelque chose au sujet des 
 28.2707 +       <quote>heads</quote>.</para>
 28.2708 +
 28.2709 +     <sect2>
 28.2710 +       <title>Les révisions 'heads'</title>
 28.2711 +
 28.2712 +       <para id="x_341">Rappellez vous que Mercurial enregistre quelle révision
 28.2713 +         est le parent de chaque révision. Si une révision a un parent, nous
 28.2714 +         l'appelons un enfant(child) ou un descendant de ce parent. Une
 28.2715 +         "head" est une révision qui n'a donc pas d'enfant. La révision tip
 28.2716 +         est donc une "head", car c'est la révision la plus récente du dépôt
 28.2717 +         qui n'a pas d'enfant. Il y a des moments où un dépôt peut contenir
 28.2718 +         plusieurs "head".</para>
 28.2719 +
 28.2720 +       <figure id="fig:tour-merge:pull" float="0">
 28.2721 +         <title>Contenu du dépôt après une récupération ("pull") depuis le
 28.2722 +           dépôt <filename class="directory" moreinfo="none">my-hello</filename> vers le dépôt <filename class="directory" moreinfo="none">my-new-hello</filename></title>
 28.2723 +         <mediaobject>
 28.2724 +           <imageobject>
 28.2725 +             <imagedata fileref="tour-merge-pull"/>
 28.2726 +           </imageobject>
 28.2727 +           <textobject><phrase>XXX ajoute un texte</phrase></textobject>
 28.2728 +         </mediaobject>
 28.2729 +       </figure>
 28.2730 +
 28.2731 +       <para id="x_343">Dans la figure <xref linkend="fig:tour-merge:pull"/>,
 28.2732 +         vous pouvez constater l'effet d'un \textit{pull} depuis le dépôt
 28.2733 +         <filename class="directory" moreinfo="none">my-hello</filename> dans le dépôt
 28.2734 +         <filename class="directory" moreinfo="none">my-new-hello</filename>. L'historique qui
 28.2735 +         était déjà présent dans le dépôt <filename class="directory" moreinfo="none">my-new-hello</filename> reste intact, mais une
 28.2736 +         nouvelle révision a été ajoutée. En vous reportant à la figure <xref linkend="fig:tour-merge:sep-repos"/>, vous pouvez voir que le
 28.2737 +         <emphasis>ID de révision (changeset ID)</emphasis> reste le même dans
 28.2738 +         le nouveau dépôt, mais que le <emphasis>numéro de
 28.2739 +         révision</emphasis> reste le même. (Ceci est un parfait exemple de
 28.2740 +         pourquoi il n'est fiable d'utiliser les numéros de révision lorsque
 28.2741 +         l'on discute d'un \textit{changeset}.) Vous pouvez voir les "heads"
 28.2742 +         présentes dans le dépôt en utilisant la commande <command role="hg-cmd" moreinfo="none">hg heads</command>.</para>
 28.2743 +
 28.2744 +        <!-- BEGIN tour.merge.heads -->
 28.2745 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg heads</userinput>
 28.2746 +changeset:   6:c94f208d1dfb
 28.2747 +tag:         tip
 28.2748 +parent:      4:2278160e78d4
 28.2749 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.2750 +date:        Sun Aug 16 14:05:26 2009 +0000
 28.2751 +summary:     Added an extra line of output
 28.2752 +
 28.2753 +changeset:   5:5f06f94fbeca
 28.2754 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.2755 +date:        Sun Aug 16 14:05:31 2009 +0000
 28.2756 +summary:     A new hello for a new day.
 28.2757 +
 28.2758 +</screen>
 28.2759 +<!-- END tour.merge.heads -->
 28.2760 +
 28.2761 +      </sect2>
 28.2762 +
 28.2763 +      <sect2>
 28.2764 +        <title>Effectuer la fusion</title>
 28.2765 +
 28.2766 +        <para id="x_344">Que se passe-t-il quand vous essayez d'utiliser la
 28.2767 +          commande <command role="hg-cmd" moreinfo="none">hg update</command> pour mettre à
 28.2768 +          jour votre espace de travail au nouveau "tip"</para>
 28.2769 +         
 28.2770 +         <!-- BEGIN tour.merge.update -->
 28.2771 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg update</userinput>
 28.2772 +abort: crosses branches (use 'hg merge' or 'hg update -C')
 28.2773 +</screen>
 28.2774 +<!-- END tour.merge.update -->
 28.2775 +
 28.2776 +
 28.2777 +         
 28.2778 +        <para id="x_345">Mercurial nous prévient que la commande <command role="hg-cmd" moreinfo="none">hg update</command> n'effectuera pas
 28.2779 +          la fusion, il ne veut pas mettre à jour l'espace de travail quand il
 28.2780 +          estime que nous pourrions avoir besoin d'une fusion, à moins de lui
 28.2781 +          forcer la main. À la place, il faut utiliser la commande <command role="hg-cmd" moreinfo="none">hg merge</command> pour fusionner les deux
 28.2782 +          "heads".</para>
 28.2783 +
 28.2784 +       <para id="x_723">Pour commencer une fusion (merge) entre deux "heads",
 28.2785 +       nous utilisons la commande <command role="hg-cmd" moreinfo="none">hg merge</command>.</para>
 28.2786 +
 28.2787 +        <!-- BEGIN tour.merge.merge -->
 28.2788 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg merge</userinput>
 28.2789 +merging hello.c
 28.2790 +0 files updated, 1 files merged, 0 files removed, 0 files unresolved
 28.2791 +(branch merge, don't forget to commit)
 28.2792 +</screen>
 28.2793 +<!-- END tour.merge.merge -->
 28.2794 + 
 28.2795 +      
 28.2796 +       <para id="x_347">Nous résolvons les conflits dans le fichier
 28.2797 +         <filename moreinfo="none">hello.c</filename>. Ceci met à jour le répertoire de travail
 28.2798 +         de sorte qu'il ne contienne les modifications ne provenance des
 28.2799 +         <emphasis>deux</emphasis> "heads", ce qui est indiqué par la
 28.2800 +         la sortie de la commande <command role="hg-cmd" moreinfo="none">hg
 28.2801 +         parents</command> et le contenu du fichier
 28.2802 +         <filename moreinfo="none">hello.c</filename>.</para>
 28.2803 +
 28.2804 +        <!-- BEGIN tour.merge.parents -->
 28.2805 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg parents</userinput>
 28.2806 +changeset:   5:5f06f94fbeca
 28.2807 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.2808 +date:        Sun Aug 16 14:05:31 2009 +0000
 28.2809 +summary:     A new hello for a new day.
 28.2810 +
 28.2811 +changeset:   6:c94f208d1dfb
 28.2812 +tag:         tip
 28.2813 +parent:      4:2278160e78d4
 28.2814 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.2815 +date:        Sun Aug 16 14:05:26 2009 +0000
 28.2816 +summary:     Added an extra line of output
 28.2817 +
 28.2818 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat hello.c</userinput>
 28.2819 +/*
 28.2820 + * Placed in the public domain by Bryan O'Sullivan.  This program is
 28.2821 + * not covered by patents in the United States or other countries.
 28.2822 + */
 28.2823 +
 28.2824 +#include &lt;stdio.h&gt;
 28.2825 +
 28.2826 +int main(int argc, char **argv)
 28.2827 +{
 28.2828 +	printf("once more, hello.\n");
 28.2829 +	printf("hello, world!\");
 28.2830 +	printf("hello again!\n");
 28.2831 +	return 0;
 28.2832 +}
 28.2833 +</screen>
 28.2834 +<!-- END tour.merge.parents -->
 28.2835 +
 28.2836 +     </sect2>
 28.2837 +
 28.2838 +     <sect2>
 28.2839 +       <title>Effectuer l'ajout (commit) du résultat de la fusion</title>
 28.2840 +
 28.2841 +       <para id="x_348">Dès l'instant où vous avez effectué une fusion
 28.2842 +         (merge), <command role="hg-cmd" moreinfo="none">hg parents</command> vous
 28.2843 +         affichera deux parents, avant que vous n'exécutiez la commande
 28.2844 +         <command role="hg-cmd" moreinfo="none">hg commit</command> sur le résultat de la
 28.2845 +         fusion.</para>
 28.2846 +
 28.2847 +        <!-- BEGIN tour.merge.commit -->
 28.2848 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Merged changes'</userinput>
 28.2849 +</screen>
 28.2850 +<!-- END tour.merge.commit -->
 28.2851 +
 28.2852 +
 28.2853 +      <para id="x_349">Nous avons maintenant un nouveau tip, remarquer qu'il
 28.2854 +        contient <emphasis>à la fois</emphasis> nos anciennes "heads" et leurs
 28.2855 +        parents. Ce sont les mêmes révisions que nous avions affichées avec
 28.2856 +        la commande <command role="hg-cmd" moreinfo="none">hg parents</command>.</para>
 28.2857 +
 28.2858 +       <!-- BEGIN tour.merge.tip -->
 28.2859 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput>
 28.2860 +changeset:   7:b8e1e756ef55
 28.2861 +tag:         tip
 28.2862 +parent:      5:5f06f94fbeca
 28.2863 +parent:      6:c94f208d1dfb
 28.2864 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.2865 +date:        Sun Aug 16 14:05:33 2009 +0000
 28.2866 +summary:     Merged changes
 28.2867 +
 28.2868 +</screen>
 28.2869 +<!-- END tour.merge.tip -->
 28.2870 +
 28.2871 +
 28.2872 +      <para id="x_34a">Dans la figure <xref linkend="fig:tour-merge:merge"/>,
 28.2873 +        vous pouvez voir une représentation de ce qui se passe dans l'espace
 28.2874 +        de travail pendant la fusion, et comment ceci affecte le dépôt lors
 28.2875 +        du "commit". Pendant la fusion, l'espace de travail, qui a deux
 28.2876 +        révisions (changesets) comme parents, voit ces derniers devenir le parent
 28.2877 +        d'une nouvelle révision (changeset).</para>
 28.2878 +
 28.2879 +      <figure id="fig:tour-merge:merge" float="0">
 28.2880 +        <title>Working directory and repository during merge, and
 28.2881 +          following commit</title>
 28.2882 +        <mediaobject>
 28.2883 +          <imageobject>
 28.2884 +            <imagedata fileref="figs/tour-merge-merge.png"/>
 28.2885 +          </imageobject>
 28.2886 +          <textobject><phrase>XXX ajoute texte</phrase></textobject>
 28.2887 +        </mediaobject>
 28.2888 +      </figure>
 28.2889 +
 28.2890 +    </sect2>
 28.2891 +  </sect1>
 28.2892 +
 28.2893 +  <sect1>
 28.2894 +    <title>Fusionner les modifications en conflit</title>
 28.2895 +
 28.2896 +    <para id="x_34b">La plupart des fusions sont assez simple à réaliser, mais 
 28.2897 +      parfois vous vous retrouverez à fusionner des fichiers où la modification 
 28.2898 +      touche la même portion de code, au sein d'un même fichier. À moins 
 28.2899 +      que ces modification ne soient identiques, ceci aboutira à un 
 28.2900 +      <emphasis>conflit</emphasis>, et vous devrez décider comment réconcilier 
 28.2901 +      les différentes modifications dans un tout cohérent.</para>
 28.2902 +
 28.2903 +    <figure id="fig:tour-merge:conflict" float="0">
 28.2904 +      <title>Modifications en conflits dans un document</title>
 28.2905 +      <mediaobject>
 28.2906 +        <imageobject><imagedata fileref="tour-merge-conflict"/></imageobject>
 28.2907 +        <textobject><phrase>XXX ajoute texte</phrase></textobject>
 28.2908 +      </mediaobject>
 28.2909 +    </figure>
 28.2910 +
 28.2911 +    <para id="x_34d">La figure <xref linkend="fig:tour-merge:conflict"/>
 28.2912 +      illustre un cas de modifications conflictuelles dans un document. Nous
 28.2913 +      avons commencé avec une version simple de ce fichier, puis nous avons
 28.2914 +      ajouté des modifications, pendant que quelqu'un d'autre modifiait le même
 28.2915 +      texte. Notre tâche dans la résolution du conflit est de décider à quoi le
 28.2916 +      fichier devrait ressembler.</para>
 28.2917 +
 28.2918 +    <para id="x_34e">Mercurial n'a pas de mécanisme interne pour gérer 
 28.2919 +      les conflits. À la place, il exécute un programme externe appelé 
 28.2920 +      <command moreinfo="none">hgmerge</command>. Il s'agit d'un script shell qui est 
 28.2921 +      embarqué par Mercurial, vous pouvez le modifier si vous le voulez. 
 28.2922 +      Ce qu'il fait par défaut est d'essayer de trouver un des différents 
 28.2923 +      outils de fusion qui seront probablement installés sur le système. 
 28.2924 +      Il commence par les outils totalement automatiques, et si ils 
 28.2925 +      échouent (parce que la résolution du conflit nécessite une
 28.2926 +      intervention humaine) ou si ils sont absents, le script tente
 28.2927 +      d'exécuter certains outils graphiques de fusion.</para>
 28.2928 +
 28.2929 +    <para id="x_34f">Il est aussi possible de demander à Mercurial d'exécuter
 28.2930 +      un autre programme ou un autre script en définissant la variable
 28.2931 +      d'environnement <envar>HGMERGE</envar> avec le nom
 28.2932 +      du programme de votre choix.</para>
 28.2933 +
 28.2934 +    <sect2>
 28.2935 +      <title>Utiliser un outil graphique de fusion</title>
 28.2936 +
 28.2937 +      <para id="x_350">Mon outil de fusion préféré est
 28.2938 +      <command moreinfo="none">kdiff3</command>, que j'utilise ici pour illustrer les
 28.2939 +        fonctionnalités classiques des outils graphiques de fusion. Vous pouvez
 28.2940 +        voir une capture d'écran de l'utilisation de <command moreinfo="none">kdiff3</command>
 28.2941 +        dans la figure <xref linkend="fig:tour-merge:kdiff3"/>. Cet outil
 28.2942 +        effectue une <emphasis>fusion \textit{three-way</emphasis>}, car il y a
 28.2943 +        trois différentes versions du fichier qui nous intéresse. Le fichier
 28.2944 +        découpe la partie supérieure de la fenêtre en trois panneaux:</para>
 28.2945 +      <itemizedlist>
 28.2946 +        <listitem><para id="x_351">A gauche on la version de
 28.2947 +          <emphasis>base</emphasis> du fichier, soit la plus récente version
 28.2948 +          des deux versions qu'on souhaite fusionner.</para></listitem>
 28.2949 +        <listitem><para id="x_352">Au centre, il y a <quote>notre</quote>
 28.2950 +          version du fichier, avec le contenu que nous avons modifié.</para></listitem>
 28.2951 +        <listitem><para id="x_353">Sur la droite, on trouve
 28.2952 +        <quote>leur</quote> version du fichier, celui qui contient la
 28.2953 +        révision que nous souhaitons intégré.</para>
 28.2954 +        </listitem></itemizedlist>
 28.2955 +      <para id="x_354">Dans le panneau en dessous, on trouve le
 28.2956 +        <emphasis>résultat</emphasis> actuel de notre fusion. Notre tâche
 28.2957 +        consiste donc à remplacement tous les textes en rouges,
 28.2958 +        qui indiquent des conflits non résolus, avec une fusion manuelle et 
 28.2959 +        pertinente de <quote>notre</quote> version et de la <quote>leur</quote>.
 28.2960 +      </para>
 28.2961 +
 28.2962 +      <para id="x_355">Tous les quatre panneaux sont <emphasis>accrochés ensemble</emphasis>, 
 28.2963 +        si nous déroulons les ascenseurs verticalement ou horizontalement dans chacun 
 28.2964 +        d'entre eux, les autres sont mis à jour avec la section correspondante dans leurs 
 28.2965 +        fichiers respectifs.</para>
 28.2966 +
 28.2967 +      <figure id="fig:tour-merge:kdiff3" float="0">
 28.2968 +        <title>Utiliser <command moreinfo="none">kdiff3</command> pour fusionner les
 28.2969 +          différentes version d'un fichier.</title>
 28.2970 +        <mediaobject>
 28.2971 +          <imageobject>
 28.2972 +            <imagedata width="100%" fileref="figs/kdiff3.png"/></imageobject>
 28.2973 +            <textobject>
 28.2974 +              <phrase>XXX ajoute texte</phrase>
 28.2975 +            </textobject>
 28.2976 +          </mediaobject>
 28.2977 +       </figure>
 28.2978 +
 28.2979 +       <para id="x_357">Pour chaque portion de fichier posant problème, nous
 28.2980 +         pouvons choisir de résoudre le conflit en utilisant une combinaison de
 28.2981 +         texte depuis la version de base, la notre, ou la leur. Nous pouvons
 28.2982 +         aussi éditer manuellement les fichiers à tout moment, si c'est nécessaire.</para>
 28.2983 +
 28.2984 +       <para id="x_358">Il y a <emphasis>beaucoup</emphasis> d'outils de
 28.2985 +         fusion disponibles, bien trop pour en parler de tous ici. Leurs
 28.2986 +         disponibilités varient selon les plate formes  ainsi que leurs
 28.2987 +         avantages et inconvénients. La plupart sont optimisé pour
 28.2988 +         la fusion de fichier contenant un texte plat, certains sont spécialisé
 28.2989 +         dans un format de fichier précis (généralement XML).</para>
 28.2990 +    </sect2>
 28.2991 +
 28.2992 +    <sect2>
 28.2993 +      <title>Un exemple concret</title>
 28.2994 +
 28.2995 +      <para id="x_359">Dans cet exemple, nous allons reproduire la
 28.2996 +        modification de l'historique du fichier de la figure <xref linkend="fig:tour-merge:conflict"/> ci dessus. Commençons par créer
 28.2997 +        un dépôt avec une version de base de notre document.</para>
 28.2998 +
 28.2999 +      <!-- BEGIN tour-merge-conflict.wife -->
 28.3000 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat &gt; letter.txt &lt;&lt;EOF</userinput>
 28.3001 +<prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">Greetings!</userinput>
 28.3002 +<prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">I am Mariam Abacha, the wife of former</userinput>
 28.3003 +<prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">Nigerian dictator Sani Abacha.</userinput>
 28.3004 +<prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">EOF</userinput>
 28.3005 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add letter.txt</userinput>
 28.3006 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m '419 scam, first draft'</userinput>
 28.3007 +</screen>
 28.3008 +<!-- END tour-merge-conflict.wife -->
 28.3009 + 
 28.3010 +
 28.3011 +      <para id="x_35a">Créons un clone de ce dépôt et faisons une
 28.3012 +        modification dans le fichier.</para>
 28.3013 +
 28.3014 +      <!-- BEGIN tour-merge-conflict.cousin -->
 28.3015 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput>
 28.3016 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone scam scam-cousin</userinput>
 28.3017 +updating working directory
 28.3018 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 28.3019 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd scam-cousin</userinput>
 28.3020 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat &gt; letter.txt &lt;&lt;EOF</userinput>
 28.3021 +<prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">Greetings!</userinput>
 28.3022 +<prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">I am Shehu Musa Abacha, cousin to the former</userinput>
 28.3023 +<prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">Nigerian dictator Sani Abacha.</userinput>
 28.3024 +<prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">EOF</userinput>
 28.3025 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m '419 scam, with cousin'</userinput>
 28.3026 +</screen>
 28.3027 +<!-- END tour-merge-conflict.cousin -->
 28.3028 +
 28.3029 +      
 28.3030 +      <para id="x_35b">Et un autre clone, pour simuler que quelqu'un d'autre effectue une
 28.3031 +        modification sur le fichier. (Ceci pour suggérer qu'il n'est pas rare
 28.3032 +        de devoir effectuer des fusions (merges) avec vos propres travaux quand
 28.3033 +        vous isolez les tâches dans des dépôts distincts. En effet, vous
 28.3034 +        aurez alors à trouver et résoudre certains conflits).</para>
 28.3035 +
 28.3036 +      <!-- BEGIN tour-merge-conflict.son -->
 28.3037 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput>
 28.3038 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone scam scam-son</userinput>
 28.3039 +updating working directory
 28.3040 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 28.3041 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd scam-son</userinput>
 28.3042 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat &gt; letter.txt &lt;&lt;EOF</userinput>
 28.3043 +<prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">Greetings!</userinput>
 28.3044 +<prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">I am Alhaji Abba Abacha, son of the former</userinput>
 28.3045 +<prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">Nigerian dictator Sani Abacha.</userinput>
 28.3046 +<prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">EOF</userinput>
 28.3047 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m '419 scam, with son'</userinput>
 28.3048 +</screen>
 28.3049 +<!-- END tour-merge-conflict.son -->
 28.3050 +
 28.3051 +
 28.3052 +      <para id="x_35c">Maintenant que ces deux versions différentes du même fichier sont
 28.3053 +        créées, nous allons configurer l'environnement de manière appropriée pour
 28.3054 +        exécuter notre fusion (merge).</para>
 28.3055 +
 28.3056 +      <!-- BEGIN tour-merge-conflict.pull -->
 28.3057 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput>
 28.3058 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone scam-cousin scam-merge</userinput>
 28.3059 +updating working directory
 28.3060 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 28.3061 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd scam-merge</userinput>
 28.3062 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull -u ../scam-son</userinput>
 28.3063 +pulling from ../scam-son
 28.3064 +searching for changes
 28.3065 +adding changesets
 28.3066 +adding manifests
 28.3067 +adding file changes
 28.3068 +added 1 changesets with 1 changes to 1 files (+1 heads)
 28.3069 +not updating, since new heads added
 28.3070 +(run 'hg heads' to see heads, 'hg merge' to merge)
 28.3071 +</screen>
 28.3072 +<!-- END tour-merge-conflict.pull -->
 28.3073 +
 28.3074 +
 28.3075 +      <para id="x_35d">Dans cette exemple, je n'utiliserais pas la commande Mercurial
 28.3076 +        habituelle <command moreinfo="none">hgmerge</command> pour effectuer le
 28.3077 +        fusion (merge), car il me faudrait abandonner ce joli petit exemple automatisé
 28.3078 +        pour utiliser un outil graphique. À la place, je vais définir la
 28.3079 +        variable d'environnement <envar>HGMERGE</envar> pour indiquer à
 28.3080 +        Mercurial d'utiliser la commande non-interactive <command moreinfo="none">merge</command>.
 28.3081 +        Cette dernière est embarquée par de nombreux systèmes <quote>à la Unix</quote>.
 28.3082 +        Si vous exécutez cet exemple depuis votre ordinateur, ne vous
 28.3083 +        occupez pas de définir <envar>HGMERGE</envar>.</para>
 28.3084 +
 28.3085 +     <!-- BEGIN tour-merge-conflict.merge -->
 28.3086 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">export HGMERGE=merge</userinput>
 28.3087 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg merge</userinput>
 28.3088 +merging letter.txt
 28.3089 +merge: warning: conflicts during merge
 28.3090 +merging letter.txt failed!
 28.3091 +0 files updated, 0 files merged, 0 files removed, 1 files unresolved
 28.3092 +use 'hg resolve' to retry unresolved file merges or 'hg up --clean' to abandon
 28.3093 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat letter.txt</userinput>
 28.3094 +Greetings!
 28.3095 +&lt;&lt;&lt;&lt;&lt;&lt;&lt; /tmp/tour-merge-conflictk3twLJ/scam-merge/letter.txt
 28.3096 +I am Shehu Musa Abacha, cousin to the former
 28.3097 +=======
 28.3098 +I am Alhaji Abba Abacha, son of the former
 28.3099 +&gt;&gt;&gt;&gt;&gt;&gt;&gt; /tmp/letter.txt~other.4O623C
 28.3100 +Nigerian dictator Sani Abacha.
 28.3101 +</screen>
 28.3102 +<!-- END tour-merge-conflict.merge -->
 28.3103 + 
 28.3104 +
 28.3105 +
 28.3106 +     <para id="x_35f">Parce que <command moreinfo="none">merge</command> ne peut pas résoudre
 28.3107 +       les modifications conflictuelles, il laisse des <emphasis>marqueurs de
 28.3108 +       différences</emphasis> à l'intérieur du fichier qui a des conflits,
 28.3109 +       indiquant clairement quelles lignes sont en conflits, et si elles
 28.3110 +       viennent de notre fichier ou du fichier externe.
 28.3111 +     </para>
 28.3112 +
 28.3113 +     <para id="x_360">Mercurial peut distinguer, à la manière dont la
 28.3114 +       commande <command moreinfo="none">merge</command> se termine, qu'elle n'a pas été
 28.3115 +       capable d'effectuer la fusion (merge), alors il nous indique que nous
 28.3116 +       devons effectuer de nouveau cette opération. Ceci peut être très utile
 28.3117 +       si, par exemple, nous exécutons un outil graphique de fusion et que
 28.3118 +       nous le quittons sans nous rendre compte qu'il reste des conflits ou 
 28.3119 +       simplement par erreur.</para>
 28.3120 +
 28.3121 +     <para id="x_361">Si la fusion (merge) automatique ou manuelle échoue, 
 28.3122 +       il n'y a rien pour nous empêcher de <quote>corriger le tir</quote> en
 28.3123 +       modifiant nous même les fichiers, et enfin effectuer le "commit" du 
 28.3124 +       fichier:</para>
 28.3125 +
 28.3126 +     <!-- BEGIN tour-merge-conflict.commit -->
 28.3127 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat &gt; letter.txt &lt;&lt;EOF</userinput>
 28.3128 +<prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">Greetings!</userinput>
 28.3129 +<prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">I am Bryan O'Sullivan, no relation of the former</userinput>
 28.3130 +<prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">Nigerian dictator Sani Abacha.</userinput>
 28.3131 +<prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">EOF</userinput>
 28.3132 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg resolve -m letter.txt</userinput>
 28.3133 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Send me your money'</userinput>
 28.3134 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput>
 28.3135 +changeset:   3:0954bda76c6b
 28.3136 +tag:         tip
 28.3137 +parent:      1:1ac156b6e708
 28.3138 +parent:      2:7ee20631b33b
 28.3139 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.3140 +date:        Sun Aug 16 14:05:34 2009 +0000
 28.3141 +summary:     Send me your money
 28.3142 +
 28.3143 +</screen>
 28.3144 +<!-- END tour-merge-conflict.commit -->
 28.3145 +
 28.3146 +
 28.3147 +     <note>
 28.3148 +       <title>Où est la <command moreinfo="none">hg resolve</command> ?</title>
 28.3149 +       
 28.3150 +       <para id="x_724">La commande <command moreinfo="none">hg resolve</command> a été
 28.3151 +         introduit dans la version 1.1 de Mercurial, qui a été publié en
 28.3152 +         décembre 2008. Si vous utilisez une version plus anciennne de
 28.3153 +         Mercurial (exécutez la command <command moreinfo="none">hg version</command> pour en
 28.3154 +         avoir le coeur net), cette commande ne sera pas disponible. Si votre
 28.3155 +         version de Mercurial est plus ancienne que la 1.1, vous devriez très
 28.3156 +         fortement considérer une mise à jour à une version plus récente avant
 28.3157 +         d'essayer de régler des fusions complexes.</para>
 28.3158 +       </note>
 28.3159 +     </sect2>
 28.3160 +   </sect1>
 28.3161 +
 28.3162 +   <sect1 id="sec:tour-merge:fetch">
 28.3163 +     <title>Simplification de la séquence pull-merge-commit</title>
 28.3164 +
 28.3165 +     <para id="x_362">La procédure pour effectuer la fusion indiquée
 28.3166 +       ci-dessus est simple, mais requiert le lancement de trois commandes à la
 28.3167 +       suite.</para>
 28.3168 +
 28.3169 +     <programlisting format="linespecific">hg pull -u
 28.3170 +hg merge
 28.3171 +hg commit -m 'Merged remote changes'</programlisting>
 28.3172 +
 28.3173 +     <para id="x_363">Lors du "commit" final, vous devez également saisir un
 28.3174 +       message, qui aura vraisemblablement assez peu d'intérêt.</para>
 28.3175 +
 28.3176 +     <para id="x_364">Il serait assez sympathique de pouvoir réduire le
 28.3177 +       nombre d'opérations nécessaire, si possible. De fait Mercurial est
 28.3178 +       fourni avec une extension appelé <literal role="hg-ext" moreinfo="none">fetch</literal>
 28.3179 +       qui fait justement cela.</para>
 28.3180 +
 28.3181 +     <para id="x_365">Mercurial fourni un mécanisme d'extension flexible qui permet à chacun
 28.3182 +       d'étendre ces fonctionnalités, tout en conservant le cœur de Mercurial
 28.3183 +       léger et facile à utiliser. Certains extensions ajoutent de nouvelles
 28.3184 +       commandes que vous pouvez utiliser en ligne de commande, alors que
 28.3185 +       d'autres travaillent <quote>en coulisse,</quote> par exemple en ajoutant des
 28.3186 +       possibilités au serveur.</para>
 28.3187 +
 28.3188 +     <para id="x_366">L'extension <literal role="hg-ext" moreinfo="none">fetch</literal>
 28.3189 +       ajoute une nouvelle commande nommée, sans surprise, <command role="hg-cmd" moreinfo="none">hg fetch</command>. Cette extension résulte en une
 28.3190 +       combinaison de <command role="hg-cmd" moreinfo="none">hg pull</command>, <command role="hg-cmd" moreinfo="none">hg update</command> and <command role="hg-cmd" moreinfo="none">hg
 28.3191 +       merge</command>. Elle commence par récupérer les modifications d'un
 28.3192 +       autre dépôt dans le dépôt courant. Si elle trouve que les
 28.3193 +       modifications ajoutent une nouvelle "head", elle effectue un "merge",
 28.3194 +       et ensuite "commit" le résultat du "merge" avec un message généré
 28.3195 +       automatiquement. Si aucune "head" n'ont été ajouté, elle met à jour le
 28.3196 +       répertoire de travail au niveau de la nouvelle révision tip.</para>
 28.3197 +     
 28.3198 +     <para id="x_367">Activer l'extension <literal role="hg-ext" moreinfo="none">fetch</literal> est facile. Modifiez votre <filename role="special" moreinfo="none">.hgrc</filename>, et soit allez à la section <literal role="rc-extensions" moreinfo="none">extensions</literal> soit créer une section
 28.3199 +       <literal role="rc-extensions" moreinfo="none">extensions</literal>. Ensuite ajoutez
 28.3200 +       une ligne qui consiste simplement en <quote>\Verb+fetch =</quote>.</para>
 28.3201 +
 28.3202 +     <programlisting format="linespecific">[extensions]
 28.3203 +fetch =</programlisting>
 28.3204 +
 28.3205 +    <para id="x_368">(Normalement, sur la partie droite de
 28.3206 +      <quote><literal moreinfo="none">=</literal></quote> devrait apparaître le chemin de
 28.3207 +      l'extension, mais étant donné que l'extension <literal role="hg-ext" moreinfo="none">fetch</literal> fait partie de la distribution standard,
 28.3208 +      Mercurial sait où la trouver.) </para>
 28.3209 +
 28.3210 +  </sect1>
 28.3211 +  
 28.3212 +  <sect1>
 28.3213 +    <title>Renommer, copier, et fusionner (merge)</title>
 28.3214 +
 28.3215 +    <para id="x_729">En cours de la vie d'un projet, nous allons souvent 
 28.3216 +      vouloir changer la disposition de ses fichiers et de ses répertoires. 
 28.3217 +      Ceci peut être aussi simple que de changer le nom d'un seul fichier, 
 28.3218 +      et aussi compliqué que de restructurer une hiérarchie entiere de fichier
 28.3219 +      au sein du projet.</para>
 28.3220 +
 28.3221 +    <para id="x_72a">Mercurial permet de faire ce genre de modification de
 28.3222 +      manière fluide, à condition de l'informer de ce que nous faisons. Si 
 28.3223 +      vous voulez renommenr un ficher, vous devriez utiliser les commande
 28.3224 +      <command moreinfo="none">hg rename</command><footnote>
 28.3225 +        <para id="x_72b">Si vous un utilisateur de Unix, vous serez content
 28.3226 +          de savoir que la commande  <command moreinfo="none">hg rename</command> command 
 28.3227 +          peut être abrégée en <command moreinfo="none">hg mv</command>.</para>
 28.3228 +      </footnote> pour changer son nom, ainsi Mercurial peut ensuite prendre
 28.3229 +      la bonne décision, plus tard, en cas de fusionv (merge).</para>
 28.3230 +
 28.3231 +    <para id="x_72c">Nous étudierojns en détail l'utilisation de ces commandes, 
 28.3232 +      en détail, dans le chapitre <xref linkend="chap:daily.copy"/>.</para>
 28.3233 +  </sect1>
 28.3234 +</chapter>
 28.3235 +
 28.3236 +<!--
 28.3237 +local variables: 
 28.3238 +sgml-parent-document: ("00book.xml" "book" "chapter")
 28.3239 +end:
 28.3240 +-->
 28.3241 +
 28.3242 +  <!-- BEGIN ch04 -->
 28.3243 +  <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
 28.3244 +
 28.3245 +<chapter id="chap:concepts">
 28.3246 +  <?dbhtml filename="behind-the-scenes.html"?>
 28.3247 +  <title>Derrière le décor</title>
 28.3248 +  
 28.3249 +  <para id="x_2e8">À la différence de beaucoup d'outils de gestion de versions,
 28.3250 +    les concepts sur lesquels se base Mercurial sont assez simples pour
 28.3251 +    qu'il soit facile de comprendre comment le logiciel fonctionne.
 28.3252 +    Bien que leur connaissance ne soit pas nécéssaire, je trouve utile
 28.3253 +    d'avoir un <quote>modèle mental</quote> de ce qui se passe.</para>
 28.3254 +
 28.3255 +  <para id="x_2e9">En effet, cette compréhension m'apporte la confiance que
 28.3256 +    Mercurial a été développé avec soin pour être à la fois
 28.3257 +    <emphasis>sûr</emphasis> et <emphasis>efficace</emphasis>. De surcroît,
 28.3258 +    si il m'est facile de garder en tête ce que le logiciel fait lorsque
 28.3259 +    j'accompli des tâches de révision, j'aurai moins de risques d'être
 28.3260 +    surpris par son comportement.</para>
 28.3261 +
 28.3262 +  <para id="x_2ea">Dans ce chapitre, nous décrirons tout d'abord les concepts
 28.3263 +    essentiels de l'architecture de Mercurial, pour ensuite discuter quelques
 28.3264 +    uns des détails intéressants de son implémentation.</para>
 28.3265 +
 28.3266 +  <sect1>
 28.3267 +    <title>Conservation de l'historique sous Mercurial</title>
 28.3268 +    <sect2>
 28.3269 +      <title>Suivi de l'historique pour un seul fichier</title>
 28.3270 +      
 28.3271 +      <para id="x_2eb">Lorsque Mercurial effectue un suivi des modifications
 28.3272 +        faites à un fichier, il conserve l'historique pour ce fichier dans un
 28.3273 +        <emphasis>filelog</emphasis> sous forme de métadonnées. Chaque entrée
 28.3274 +        dans le filelog contient assez d'informations pour reconstituer une
 28.3275 +        révision du fichier correspondant. Les filelogs sont des fichiers
 28.3276 +        stockés dans le répertoire  <filename role="special" class="directory" moreinfo="none">.hg/store/data</filename>. Un filelog contient
 28.3277 +        des informations de deux types: les données de révision, et un index
 28.3278 +        pour permettre à Mercurial une recherche efficace d'une révision
 28.3279 +        donnée.</para>
 28.3280 +
 28.3281 +      <para id="x_2ec">Lorsqu'un fichier devient trop gros ou a un long
 28.3282 +        historique, son filelog se voit stocker dans un fichier de données
 28.3283 +        (avec un suffixe <quote><literal moreinfo="none">.d</literal></quote>) et un fichier
 28.3284 +        index (avec un suffixe<quote><literal moreinfo="none">.i</literal></quote>)
 28.3285 +        distincts. La relation entre un fichier dans le répertoire de travail
 28.3286 +        et le  filelog couvrant le suivi de son historique dans le dépôt est
 28.3287 +        illustré à la figure <xref linkend="fig:concepts:filelog"/>.</para>
 28.3288 +
 28.3289 +      <figure id="fig:concepts:filelog" float="0">
 28.3290 +        <title>Relations entre les fichiers dans le répertoire de travail et
 28.3291 +        leurs filelogs dans le dépôt</title> 
 28.3292 +        <mediaobject> <imageobject><imagedata fileref="figs/filelog.png"/></imageobject>
 28.3293 +          <textobject><phrase>XXX add text</phrase></textobject>
 28.3294 +        </mediaobject> </figure>
 28.3295 +
 28.3296 +    </sect2>
 28.3297 +    <sect2>
 28.3298 +      <title>Gestion des fichiers suivis</title>
 28.3299 +      
 28.3300 +      <para id="x_2ee">Mercurial a recours à une structure nommée
 28.3301 +        <emphasis>manifest</emphasis> pour rassembler les informations sur
 28.3302 +        les fichiers dont il gère le suivi. Chaque entrée dans ce manifest
 28.3303 +        contient des informations sur les fichiers présents dans une révision
 28.3304 +        donnée. Une entrée store la liste des fichiers faisant partie de la
 28.3305 +        révision, la version de chaque fichier, et quelques autres
 28.3306 +        métadonnées sur ces fichiers.</para>
 28.3307 +
 28.3308 +    </sect2>
 28.3309 +    <sect2>
 28.3310 +      <title>Recording changeset information</title>
 28.3311 +
 28.3312 +      <para id="x_2ef">The <emphasis>changelog</emphasis> contains
 28.3313 +        information about each changeset.  Each revision records who
 28.3314 +        committed a change, the changeset comment, other pieces of
 28.3315 +        changeset-related information, and the revision of the manifest to
 28.3316 +        use.</para>
 28.3317 +
 28.3318 +    </sect2>
 28.3319 +    <sect2>
 28.3320 +      <title>Relationships between revisions</title>
 28.3321 +
 28.3322 +      <para id="x_2f0">Within a changelog, a manifest, or a filelog, each
 28.3323 +	revision stores a pointer to its immediate parent (or to its
 28.3324 +	two parents, if it's a merge revision).  As I mentioned above,
 28.3325 +	there are also relationships between revisions
 28.3326 +	<emphasis>across</emphasis> these structures, and they are
 28.3327 +	hierarchical in nature.</para>
 28.3328 +
 28.3329 +      <para id="x_2f1">For every changeset in a repository, there is exactly one
 28.3330 +	revision stored in the changelog.  Each revision of the
 28.3331 +	changelog contains a pointer to a single revision of the
 28.3332 +	manifest.  A revision of the manifest stores a pointer to a
 28.3333 +	single revision of each filelog tracked when that changeset
 28.3334 +	was created.  These relationships are illustrated in
 28.3335 +	<xref linkend="fig:concepts:metadata"/>.</para>
 28.3336 +
 28.3337 +      <figure id="fig:concepts:metadata" float="0">
 28.3338 +	<title>Metadata relationships</title>
 28.3339 +	<mediaobject>
 28.3340 +	  <imageobject><imagedata fileref="figs/metadata.png"/></imageobject>
 28.3341 +	  <textobject><phrase>XXX add text</phrase></textobject>
 28.3342 +	</mediaobject>
 28.3343 +      </figure>
 28.3344 +
 28.3345 +      <para id="x_2f3">As the illustration shows, there is
 28.3346 +	<emphasis>not</emphasis> a <quote>one to one</quote>
 28.3347 +	relationship between revisions in the changelog, manifest, or
 28.3348 +	filelog. If a file that
 28.3349 +	Mercurial tracks hasn't changed between two changesets, the
 28.3350 +	entry for that file in the two revisions of the manifest will
 28.3351 +	point to the same revision of its filelog<footnote>
 28.3352 +	  <para id="x_725">It is possible (though unusual) for the manifest to
 28.3353 +	    remain the same between two changesets, in which case the
 28.3354 +	    changelog entries for those changesets will point to the
 28.3355 +	    same revision of the manifest.</para>
 28.3356 +	</footnote>.</para>
 28.3357 +
 28.3358 +    </sect2>
 28.3359 +  </sect1>
 28.3360 +  <sect1>
 28.3361 +    <title>Safe, efficient storage</title>
 28.3362 +
 28.3363 +    <para id="x_2f4">The underpinnings of changelogs, manifests, and filelogs are
 28.3364 +      provided by a single structure called the
 28.3365 +      <emphasis>revlog</emphasis>.</para>
 28.3366 +
 28.3367 +    <sect2>
 28.3368 +      <title>Efficient storage</title>
 28.3369 +
 28.3370 +      <para id="x_2f5">The revlog provides efficient storage of revisions using a
 28.3371 +	<emphasis>delta</emphasis> mechanism.  Instead of storing a
 28.3372 +	complete copy of a file for each revision, it stores the
 28.3373 +	changes needed to transform an older revision into the new
 28.3374 +	revision.  For many kinds of file data, these deltas are
 28.3375 +	typically a fraction of a percent of the size of a full copy
 28.3376 +	of a file.</para>
 28.3377 +
 28.3378 +      <para id="x_2f6">Some obsolete revision control systems can only work with
 28.3379 +	deltas of text files.  They must either store binary files as
 28.3380 +	complete snapshots or encoded into a text representation, both
 28.3381 +	of which are wasteful approaches.  Mercurial can efficiently
 28.3382 +	handle deltas of files with arbitrary binary contents; it
 28.3383 +	doesn't need to treat text as special.</para>
 28.3384 +
 28.3385 +    </sect2>
 28.3386 +    <sect2 id="sec:concepts:txn">
 28.3387 +      <title>Safe operation</title>
 28.3388 +
 28.3389 +      <para id="x_2f7">Mercurial only ever <emphasis>appends</emphasis> data to
 28.3390 +	the end of a revlog file. It never modifies a section of a
 28.3391 +	file after it has written it.  This is both more robust and
 28.3392 +	efficient than schemes that need to modify or rewrite
 28.3393 +	data.</para>
 28.3394 +
 28.3395 +      <para id="x_2f8">In addition, Mercurial treats every write as part of a
 28.3396 +	<emphasis>transaction</emphasis> that can span a number of
 28.3397 +	files.  A transaction is <emphasis>atomic</emphasis>: either
 28.3398 +	the entire transaction succeeds and its effects are all
 28.3399 +	visible to readers in one go, or the whole thing is undone.
 28.3400 +	This guarantee of atomicity means that if you're running two
 28.3401 +	copies of Mercurial, where one is reading data and one is
 28.3402 +	writing it, the reader will never see a partially written
 28.3403 +	result that might confuse it.</para>
 28.3404 +
 28.3405 +      <para id="x_2f9">The fact that Mercurial only appends to files makes it
 28.3406 +	easier to provide this transactional guarantee.  The easier it
 28.3407 +	is to do stuff like this, the more confident you should be
 28.3408 +	that it's done correctly.</para>
 28.3409 +
 28.3410 +    </sect2>
 28.3411 +    <sect2>
 28.3412 +      <title>Fast retrieval</title>
 28.3413 +
 28.3414 +      <para id="x_2fa">Mercurial cleverly avoids a pitfall common to
 28.3415 +	all earlier revision control systems: the problem of
 28.3416 +	<emphasis>inefficient retrieval</emphasis>. Most revision
 28.3417 +	control systems store the contents of a revision as an
 28.3418 +	incremental series of modifications against a
 28.3419 +	<quote>snapshot</quote>.  (Some base the snapshot on the
 28.3420 +	oldest revision, others on the newest.)  To reconstruct a
 28.3421 +	specific revision, you must first read the snapshot, and then
 28.3422 +	every one of the revisions between the snapshot and your
 28.3423 +	target revision.  The more history that a file accumulates,
 28.3424 +	the more revisions you must read, hence the longer it takes to
 28.3425 +	reconstruct a particular revision.</para>
 28.3426 +
 28.3427 +      <figure id="fig:concepts:snapshot" float="0">
 28.3428 +	<title>Snapshot of a revlog, with incremental deltas</title>
 28.3429 +	<mediaobject>
 28.3430 +	  <imageobject><imagedata fileref="figs/snapshot.png"/></imageobject>
 28.3431 +	  <textobject><phrase>XXX add text</phrase></textobject>
 28.3432 +	</mediaobject>
 28.3433 +      </figure>
 28.3434 +
 28.3435 +      <para id="x_2fc">The innovation that Mercurial applies to this problem is
 28.3436 +	simple but effective.  Once the cumulative amount of delta
 28.3437 +	information stored since the last snapshot exceeds a fixed
 28.3438 +	threshold, it stores a new snapshot (compressed, of course),
 28.3439 +	instead of another delta.  This makes it possible to
 28.3440 +	reconstruct <emphasis>any</emphasis> revision of a file
 28.3441 +	quickly.  This approach works so well that it has since been
 28.3442 +	copied by several other revision control systems.</para>
 28.3443 +
 28.3444 +      <para id="x_2fd"><xref linkend="fig:concepts:snapshot"/> illustrates
 28.3445 +	the idea.  In an entry in a revlog's index file, Mercurial
 28.3446 +	stores the range of entries from the data file that it must
 28.3447 +	read to reconstruct a particular revision.</para>
 28.3448 +
 28.3449 +      <sect3>
 28.3450 +	<title>Aside: the influence of video compression</title>
 28.3451 +
 28.3452 +	<para id="x_2fe">If you're familiar with video compression or
 28.3453 +	  have ever watched a TV feed through a digital cable or
 28.3454 +	  satellite service, you may know that most video compression
 28.3455 +	  schemes store each frame of video as a delta against its
 28.3456 +	  predecessor frame.</para>
 28.3457 +
 28.3458 +	<para id="x_2ff">Mercurial borrows this idea to make it
 28.3459 +	  possible to reconstruct a revision from a snapshot and a
 28.3460 +	  small number of deltas.</para>
 28.3461 +
 28.3462 +      </sect3>
 28.3463 +    </sect2>
 28.3464 +    <sect2>
 28.3465 +      <title>Identification and strong integrity</title>
 28.3466 +
 28.3467 +      <para id="x_300">Along with delta or snapshot information, a revlog entry
 28.3468 +	contains a cryptographic hash of the data that it represents.
 28.3469 +	This makes it difficult to forge the contents of a revision,
 28.3470 +	and easy to detect accidental corruption.</para>
 28.3471 +
 28.3472 +      <para id="x_301">Hashes provide more than a mere check against corruption;
 28.3473 +	they are used as the identifiers for revisions.  The changeset
 28.3474 +	identification hashes that you see as an end user are from
 28.3475 +	revisions of the changelog.  Although filelogs and the
 28.3476 +	manifest also use hashes, Mercurial only uses these behind the
 28.3477 +	scenes.</para>
 28.3478 +
 28.3479 +      <para id="x_302">Mercurial verifies that hashes are correct when it
 28.3480 +	retrieves file revisions and when it pulls changes from
 28.3481 +	another repository.  If it encounters an integrity problem, it
 28.3482 +	will complain and stop whatever it's doing.</para>
 28.3483 +
 28.3484 +      <para id="x_303">In addition to the effect it has on retrieval efficiency,
 28.3485 +	Mercurial's use of periodic snapshots makes it more robust
 28.3486 +	against partial data corruption.  If a revlog becomes partly
 28.3487 +	corrupted due to a hardware error or system bug, it's often
 28.3488 +	possible to reconstruct some or most revisions from the
 28.3489 +	uncorrupted sections of the revlog, both before and after the
 28.3490 +	corrupted section.  This would not be possible with a
 28.3491 +	delta-only storage model.</para>
 28.3492 +    </sect2>
 28.3493 +  </sect1>
 28.3494 +
 28.3495 +  <sect1>
 28.3496 +    <title>Revision history, branching, and merging</title>
 28.3497 +
 28.3498 +    <para id="x_304">Every entry in a Mercurial revlog knows the identity of its
 28.3499 +      immediate ancestor revision, usually referred to as its
 28.3500 +      <emphasis>parent</emphasis>.  In fact, a revision contains room
 28.3501 +      for not one parent, but two.  Mercurial uses a special hash,
 28.3502 +      called the <quote>null ID</quote>, to represent the idea
 28.3503 +      <quote>there is no parent here</quote>.  This hash is simply a
 28.3504 +      string of zeroes.</para>
 28.3505 +
 28.3506 +    <para id="x_305">In <xref linkend="fig:concepts:revlog"/>, you can see
 28.3507 +      an example of the conceptual structure of a revlog.  Filelogs,
 28.3508 +      manifests, and changelogs all have this same structure; they
 28.3509 +      differ only in the kind of data stored in each delta or
 28.3510 +      snapshot.</para>
 28.3511 +
 28.3512 +    <para id="x_306">The first revision in a revlog (at the bottom of the image)
 28.3513 +      has the null ID in both of its parent slots.  For a
 28.3514 +      <quote>normal</quote> revision, its first parent slot contains
 28.3515 +      the ID of its parent revision, and its second contains the null
 28.3516 +      ID, indicating that the revision has only one real parent.  Any
 28.3517 +      two revisions that have the same parent ID are branches.  A
 28.3518 +      revision that represents a merge between branches has two normal
 28.3519 +      revision IDs in its parent slots.</para>
 28.3520 +
 28.3521 +    <figure id="fig:concepts:revlog" float="0">
 28.3522 +      <title>The conceptual structure of a revlog</title>
 28.3523 +      <mediaobject>
 28.3524 +	<imageobject><imagedata fileref="figs/revlog.png"/></imageobject>
 28.3525 +	<textobject><phrase>XXX add text</phrase></textobject>
 28.3526 +      </mediaobject>
 28.3527 +    </figure>
 28.3528 +
 28.3529 +  </sect1>
 28.3530 +  <sect1>
 28.3531 +    <title>The working directory</title>
 28.3532 +
 28.3533 +    <para id="x_307">In the working directory, Mercurial stores a snapshot of the
 28.3534 +      files from the repository as of a particular changeset.</para>
 28.3535 +
 28.3536 +    <para id="x_308">The working directory <quote>knows</quote> which changeset
 28.3537 +      it contains.  When you update the working directory to contain a
 28.3538 +      particular changeset, Mercurial looks up the appropriate
 28.3539 +      revision of the manifest to find out which files it was tracking
 28.3540 +      at the time that changeset was committed, and which revision of
 28.3541 +      each file was then current.  It then recreates a copy of each of
 28.3542 +      those files, with the same contents it had when the changeset
 28.3543 +      was committed.</para>
 28.3544 +
 28.3545 +    <para id="x_309">The <emphasis>dirstate</emphasis> is a special
 28.3546 +      structure that contains Mercurial's knowledge of the working
 28.3547 +      directory.  It is maintained as a file named
 28.3548 +      <filename moreinfo="none">.hg/dirstate</filename> inside a repository.  The
 28.3549 +      dirstate details which changeset the working directory is
 28.3550 +      updated to, and all of the files that Mercurial is tracking in
 28.3551 +      the working directory. It also lets Mercurial quickly notice
 28.3552 +      changed files, by recording their checkout times and
 28.3553 +      sizes.</para>
 28.3554 +
 28.3555 +    <para id="x_30a">Just as a revision of a revlog has room for two parents, so
 28.3556 +      that it can represent either a normal revision (with one parent)
 28.3557 +      or a merge of two earlier revisions, the dirstate has slots for
 28.3558 +      two parents.  When you use the <command role="hg-cmd" moreinfo="none">hg
 28.3559 +	update</command> command, the changeset that you update to is
 28.3560 +      stored in the <quote>first parent</quote> slot, and the null ID
 28.3561 +      in the second. When you <command role="hg-cmd" moreinfo="none">hg
 28.3562 +	merge</command> with another changeset, the first parent
 28.3563 +      remains unchanged, and the second parent is filled in with the
 28.3564 +      changeset you're merging with.  The <command role="hg-cmd" moreinfo="none">hg
 28.3565 +	parents</command> command tells you what the parents of the
 28.3566 +      dirstate are.</para>
 28.3567 +
 28.3568 +    <sect2>
 28.3569 +      <title>What happens when you commit</title>
 28.3570 +
 28.3571 +      <para id="x_30b">The dirstate stores parent information for more than just
 28.3572 +	book-keeping purposes.  Mercurial uses the parents of the
 28.3573 +	dirstate as <emphasis>the parents of a new
 28.3574 +	  changeset</emphasis> when you perform a commit.</para>
 28.3575 +
 28.3576 +      <figure id="fig:concepts:wdir" float="0">
 28.3577 +	<title>The working directory can have two parents</title>
 28.3578 +	<mediaobject>
 28.3579 +	  <imageobject><imagedata fileref="figs/wdir.png"/></imageobject>
 28.3580 +	  <textobject><phrase>XXX add text</phrase></textobject>
 28.3581 +	</mediaobject>
 28.3582 +      </figure>
 28.3583 +
 28.3584 +      <para id="x_30d"><xref linkend="fig:concepts:wdir"/> shows the
 28.3585 +	normal state of the working directory, where it has a single
 28.3586 +	changeset as parent.  That changeset is the
 28.3587 +	<emphasis>tip</emphasis>, the newest changeset in the
 28.3588 +	repository that has no children.</para>
 28.3589 +
 28.3590 +      <figure id="fig:concepts:wdir-after-commit" float="0">
 28.3591 +	<title>The working directory gains new parents after a
 28.3592 +	  commit</title>
 28.3593 +	<mediaobject>
 28.3594 +	  <imageobject><imagedata fileref="figs/wdir-after-commit.png"/></imageobject>
 28.3595 +	  <textobject><phrase>XXX add text</phrase></textobject>
 28.3596 +	</mediaobject>
 28.3597 +      </figure>
 28.3598 +
 28.3599 +      <para id="x_30f">It's useful to think of the working directory as
 28.3600 +	<quote>the changeset I'm about to commit</quote>.  Any files
 28.3601 +	that you tell Mercurial that you've added, removed, renamed,
 28.3602 +	or copied will be reflected in that changeset, as will
 28.3603 +	modifications to any files that Mercurial is already tracking;
 28.3604 +	the new changeset will have the parents of the working
 28.3605 +	directory as its parents.</para>
 28.3606 +
 28.3607 +      <para id="x_310">After a commit, Mercurial will update the
 28.3608 +	parents of the working directory, so that the first parent is
 28.3609 +	the ID of the new changeset, and the second is the null ID.
 28.3610 +	This is shown in <xref linkend="fig:concepts:wdir-after-commit"/>. Mercurial
 28.3611 +	doesn't touch any of the files in the working directory when
 28.3612 +	you commit; it just modifies the dirstate to note its new
 28.3613 +	parents.</para>
 28.3614 +
 28.3615 +    </sect2>
 28.3616 +    <sect2>
 28.3617 +      <title>Creating a new head</title>
 28.3618 +
 28.3619 +      <para id="x_311">It's perfectly normal to update the working directory to a
 28.3620 +	changeset other than the current tip.  For example, you might
 28.3621 +	want to know what your project looked like last Tuesday, or
 28.3622 +	you could be looking through changesets to see which one
 28.3623 +	introduced a bug.  In cases like this, the natural thing to do
 28.3624 +	is update the working directory to the changeset you're
 28.3625 +	interested in, and then examine the files in the working
 28.3626 +	directory directly to see their contents as they were when you
 28.3627 +	committed that changeset.  The effect of this is shown in
 28.3628 +	<xref linkend="fig:concepts:wdir-pre-branch"/>.</para>
 28.3629 +
 28.3630 +      <figure id="fig:concepts:wdir-pre-branch" float="0">
 28.3631 +	<title>The working directory, updated to an older
 28.3632 +	  changeset</title>
 28.3633 +	<mediaobject>
 28.3634 +	  <imageobject><imagedata fileref="figs/wdir-pre-branch.png"/></imageobject>
 28.3635 +	  <textobject><phrase>XXX add text</phrase></textobject>
 28.3636 +	</mediaobject>
 28.3637 +      </figure>
 28.3638 +
 28.3639 +      <para id="x_313">Having updated the working directory to an
 28.3640 +	older changeset, what happens if you make some changes, and
 28.3641 +	then commit?  Mercurial behaves in the same way as I outlined
 28.3642 +	above.  The parents of the working directory become the
 28.3643 +	parents of the new changeset.  This new changeset has no
 28.3644 +	children, so it becomes the new tip.  And the repository now
 28.3645 +	contains two changesets that have no children; we call these
 28.3646 +	<emphasis>heads</emphasis>.  You can see the structure that
 28.3647 +	this creates in <xref linkend="fig:concepts:wdir-branch"/>.</para>
 28.3648 +
 28.3649 +      <figure id="fig:concepts:wdir-branch" float="0">
 28.3650 +	<title>After a commit made while synced to an older
 28.3651 +	  changeset</title>
 28.3652 +	<mediaobject>
 28.3653 +	  <imageobject><imagedata fileref="figs/wdir-branch.png"/></imageobject>
 28.3654 +	  <textobject><phrase>XXX add text</phrase></textobject>
 28.3655 +	</mediaobject>
 28.3656 +      </figure>
 28.3657 +
 28.3658 +      <note>
 28.3659 +	<para id="x_315">If you're new to Mercurial, you should keep
 28.3660 +	  in mind a common <quote>error</quote>, which is to use the
 28.3661 +	  <command role="hg-cmd" moreinfo="none">hg pull</command> command without any
 28.3662 +	  options.  By default, the <command role="hg-cmd" moreinfo="none">hg
 28.3663 +	    pull</command> command <emphasis>does not</emphasis>
 28.3664 +	  update the working directory, so you'll bring new changesets
 28.3665 +	  into your repository, but the working directory will stay
 28.3666 +	  synced at the same changeset as before the pull.  If you
 28.3667 +	  make some changes and commit afterwards, you'll thus create
 28.3668 +	  a new head, because your working directory isn't synced to
 28.3669 +	  whatever the current tip is.  To combine the operation of a
 28.3670 +	  pull, followed by an update, run <command moreinfo="none">hg pull
 28.3671 +	    -u</command>.</para>
 28.3672 +
 28.3673 +	<para id="x_316">I put the word <quote>error</quote> in quotes
 28.3674 +	  because all that you need to do to rectify the situation
 28.3675 +	  where you created a new head by accident is
 28.3676 +	  <command role="hg-cmd" moreinfo="none">hg merge</command>, then <command role="hg-cmd" moreinfo="none">hg commit</command>.  In other words, this
 28.3677 +	  almost never has negative consequences; it's just something
 28.3678 +	  of a surprise for newcomers.  I'll discuss other ways to
 28.3679 +	  avoid this behavior, and why Mercurial behaves in this
 28.3680 +	  initially surprising way, later on.</para>
 28.3681 +      </note>
 28.3682 +
 28.3683 +    </sect2>
 28.3684 +    <sect2>
 28.3685 +      <title>Merging changes</title>
 28.3686 +
 28.3687 +      <para id="x_317">When you run the <command role="hg-cmd" moreinfo="none">hg
 28.3688 +	  merge</command> command, Mercurial leaves the first parent
 28.3689 +	of the working directory unchanged, and sets the second parent
 28.3690 +	to the changeset you're merging with, as shown in <xref linkend="fig:concepts:wdir-merge"/>.</para>
 28.3691 +
 28.3692 +      <figure id="fig:concepts:wdir-merge" float="0">
 28.3693 +	<title>Merging two heads</title>
 28.3694 +	<mediaobject>
 28.3695 +	  <imageobject>
 28.3696 +	    <imagedata fileref="figs/wdir-merge.png"/>
 28.3697 +	  </imageobject>
 28.3698 +	  <textobject><phrase>XXX add text</phrase></textobject>
 28.3699 +	</mediaobject>
 28.3700 +      </figure>
 28.3701 +
 28.3702 +      <para id="x_319">Mercurial also has to modify the working directory, to
 28.3703 +	merge the files managed in the two changesets.  Simplified a
 28.3704 +	little, the merging process goes like this, for every file in
 28.3705 +	the manifests of both changesets.</para>
 28.3706 +      <itemizedlist>
 28.3707 +	<listitem><para id="x_31a">If neither changeset has modified a file, do
 28.3708 +	    nothing with that file.</para>
 28.3709 +	</listitem>
 28.3710 +	<listitem><para id="x_31b">If one changeset has modified a file, and the
 28.3711 +	    other hasn't, create the modified copy of the file in the
 28.3712 +	    working directory.</para>
 28.3713 +	</listitem>
 28.3714 +	<listitem><para id="x_31c">If one changeset has removed a file, and the
 28.3715 +	    other hasn't (or has also deleted it), delete the file
 28.3716 +	    from the working directory.</para>
 28.3717 +	</listitem>
 28.3718 +	<listitem><para id="x_31d">If one changeset has removed a file, but the
 28.3719 +	    other has modified the file, ask the user what to do: keep
 28.3720 +	    the modified file, or remove it?</para>
 28.3721 +	</listitem>
 28.3722 +	<listitem><para id="x_31e">If both changesets have modified a file,
 28.3723 +	    invoke an external merge program to choose the new
 28.3724 +	    contents for the merged file.  This may require input from
 28.3725 +	    the user.</para>
 28.3726 +	</listitem>
 28.3727 +	<listitem><para id="x_31f">If one changeset has modified a file, and the
 28.3728 +	    other has renamed or copied the file, make sure that the
 28.3729 +	    changes follow the new name of the file.</para>
 28.3730 +	</listitem></itemizedlist>
 28.3731 +      <para id="x_320">There are more details—merging has plenty of corner
 28.3732 +	cases—but these are the most common choices that are
 28.3733 +	involved in a merge.  As you can see, most cases are
 28.3734 +	completely automatic, and indeed most merges finish
 28.3735 +	automatically, without requiring your input to resolve any
 28.3736 +	conflicts.</para>
 28.3737 +
 28.3738 +      <para id="x_321">When you're thinking about what happens when you commit
 28.3739 +	after a merge, once again the working directory is <quote>the
 28.3740 +	  changeset I'm about to commit</quote>.  After the <command role="hg-cmd" moreinfo="none">hg merge</command> command completes, the
 28.3741 +	working directory has two parents; these will become the
 28.3742 +	parents of the new changeset.</para>
 28.3743 +
 28.3744 +      <para id="x_322">Mercurial lets you perform multiple merges, but
 28.3745 +	you must commit the results of each individual merge as you
 28.3746 +	go.  This is necessary because Mercurial only tracks two
 28.3747 +	parents for both revisions and the working directory.  While
 28.3748 +	it would be technically feasible to merge multiple changesets
 28.3749 +	at once, Mercurial avoids this for simplicity.  With multi-way
 28.3750 +	merges, the risks of user confusion, nasty conflict
 28.3751 +	resolution, and making a terrible mess of a merge would grow
 28.3752 +	intolerable.</para>
 28.3753 +
 28.3754 +    </sect2>
 28.3755 +
 28.3756 +    <sect2>
 28.3757 +      <title>Merging and renames</title>
 28.3758 +
 28.3759 +      <para id="x_69a">A surprising number of revision control systems pay little
 28.3760 +	or no attention to a file's <emphasis>name</emphasis> over
 28.3761 +	time.  For instance, it used to be common that if a file got
 28.3762 +	renamed on one side of a merge, the changes from the other
 28.3763 +	side would be silently dropped.</para>
 28.3764 +
 28.3765 +      <para id="x_69b">Mercurial records metadata when you tell it to perform a
 28.3766 +	rename or copy. It uses this metadata during a merge to do the
 28.3767 +	right thing in the case of a merge.  For instance, if I rename
 28.3768 +	a file, and you edit it without renaming it, when we merge our
 28.3769 +	work the file will be renamed and have your edits
 28.3770 +	applied.</para>
 28.3771 +    </sect2>
 28.3772 +  </sect1>
 28.3773 +
 28.3774 +  <sect1>
 28.3775 +    <title>Other interesting design features</title>
 28.3776 +
 28.3777 +    <para id="x_323">In the sections above, I've tried to highlight some of the
 28.3778 +      most important aspects of Mercurial's design, to illustrate that
 28.3779 +      it pays careful attention to reliability and performance.
 28.3780 +      However, the attention to detail doesn't stop there.  There are
 28.3781 +      a number of other aspects of Mercurial's construction that I
 28.3782 +      personally find interesting.  I'll detail a few of them here,
 28.3783 +      separate from the <quote>big ticket</quote> items above, so that
 28.3784 +      if you're interested, you can gain a better idea of the amount
 28.3785 +      of thinking that goes into a well-designed system.</para>
 28.3786 +
 28.3787 +    <sect2>
 28.3788 +      <title>Clever compression</title>
 28.3789 +
 28.3790 +      <para id="x_324">When appropriate, Mercurial will store both snapshots and
 28.3791 +	deltas in compressed form.  It does this by always
 28.3792 +	<emphasis>trying to</emphasis> compress a snapshot or delta,
 28.3793 +	but only storing the compressed version if it's smaller than
 28.3794 +	the uncompressed version.</para>
 28.3795 +
 28.3796 +      <para id="x_325">This means that Mercurial does <quote>the right
 28.3797 +	  thing</quote> when storing a file whose native form is
 28.3798 +	compressed, such as a <literal moreinfo="none">zip</literal> archive or a JPEG
 28.3799 +	image.  When these types of files are compressed a second
 28.3800 +	time, the resulting file is usually bigger than the
 28.3801 +	once-compressed form, and so Mercurial will store the plain
 28.3802 +	<literal moreinfo="none">zip</literal> or JPEG.</para>
 28.3803 +
 28.3804 +      <para id="x_326">Deltas between revisions of a compressed file are usually
 28.3805 +	larger than snapshots of the file, and Mercurial again does
 28.3806 +	<quote>the right thing</quote> in these cases.  It finds that
 28.3807 +	such a delta exceeds the threshold at which it should store a
 28.3808 +	complete snapshot of the file, so it stores the snapshot,
 28.3809 +	again saving space compared to a naive delta-only
 28.3810 +	approach.</para>
 28.3811 +
 28.3812 +      <sect3>
 28.3813 +	<title>Network recompression</title>
 28.3814 +
 28.3815 +	<para id="x_327">When storing revisions on disk, Mercurial uses the
 28.3816 +	  <quote>deflate</quote> compression algorithm (the same one
 28.3817 +	  used by the popular <literal moreinfo="none">zip</literal> archive format),
 28.3818 +	  which balances good speed with a respectable compression
 28.3819 +	  ratio.  However, when transmitting revision data over a
 28.3820 +	  network connection, Mercurial uncompresses the compressed
 28.3821 +	  revision data.</para>
 28.3822 +
 28.3823 +	<para id="x_328">If the connection is over HTTP, Mercurial recompresses
 28.3824 +	  the entire stream of data using a compression algorithm that
 28.3825 +	  gives a better compression ratio (the Burrows-Wheeler
 28.3826 +	  algorithm from the widely used <literal moreinfo="none">bzip2</literal>
 28.3827 +	  compression package).  This combination of algorithm and
 28.3828 +	  compression of the entire stream (instead of a revision at a
 28.3829 +	  time) substantially reduces the number of bytes to be
 28.3830 +	  transferred, yielding better network performance over most
 28.3831 +	  kinds of network.</para>
 28.3832 +
 28.3833 +	<para id="x_329">If the connection is over
 28.3834 +	  <command moreinfo="none">ssh</command>, Mercurial
 28.3835 +	  <emphasis>doesn't</emphasis> recompress the stream, because
 28.3836 +	  <command moreinfo="none">ssh</command> can already do this itself.  You can
 28.3837 +	  tell Mercurial to always use <command moreinfo="none">ssh</command>'s
 28.3838 +	  compression feature by editing the
 28.3839 +	  <filename moreinfo="none">.hgrc</filename> file in your home directory as
 28.3840 +	  follows.</para>
 28.3841 +
 28.3842 +	<programlisting format="linespecific">[ui]
 28.3843 +ssh = ssh -C</programlisting>
 28.3844 +
 28.3845 +      </sect3>
 28.3846 +    </sect2>
 28.3847 +    <sect2>
 28.3848 +      <title>Read/write ordering and atomicity</title>
 28.3849 +
 28.3850 +      <para id="x_32a">Appending to files isn't the whole story when
 28.3851 +	it comes to guaranteeing that a reader won't see a partial
 28.3852 +	write.  If you recall <xref linkend="fig:concepts:metadata"/>,
 28.3853 +	revisions in the changelog point to revisions in the manifest,
 28.3854 +	and revisions in the manifest point to revisions in filelogs.
 28.3855 +	This hierarchy is deliberate.</para>
 28.3856 +
 28.3857 +      <para id="x_32b">A writer starts a transaction by writing filelog and
 28.3858 +	manifest data, and doesn't write any changelog data until
 28.3859 +	those are finished.  A reader starts by reading changelog
 28.3860 +	data, then manifest data, followed by filelog data.</para>
 28.3861 +
 28.3862 +      <para id="x_32c">Since the writer has always finished writing filelog and
 28.3863 +	manifest data before it writes to the changelog, a reader will
 28.3864 +	never read a pointer to a partially written manifest revision
 28.3865 +	from the changelog, and it will never read a pointer to a
 28.3866 +	partially written filelog revision from the manifest.</para>
 28.3867 +
 28.3868 +    </sect2>
 28.3869 +    <sect2>
 28.3870 +      <title>Concurrent access</title>
 28.3871 +
 28.3872 +      <para id="x_32d">The read/write ordering and atomicity guarantees mean that
 28.3873 +	Mercurial never needs to <emphasis>lock</emphasis> a
 28.3874 +	repository when it's reading data, even if the repository is
 28.3875 +	being written to while the read is occurring. This has a big
 28.3876 +	effect on scalability; you can have an arbitrary number of
 28.3877 +	Mercurial processes safely reading data from a repository
 28.3878 +	all at once, no matter whether it's being written to or
 28.3879 +	not.</para>
 28.3880 +
 28.3881 +      <para id="x_32e">The lockless nature of reading means that if you're
 28.3882 +	sharing a repository on a multi-user system, you don't need to
 28.3883 +	grant other local users permission to
 28.3884 +	<emphasis>write</emphasis> to your repository in order for
 28.3885 +	them to be able to clone it or pull changes from it; they only
 28.3886 +	need <emphasis>read</emphasis> permission.  (This is
 28.3887 +	<emphasis>not</emphasis> a common feature among revision
 28.3888 +	control systems, so don't take it for granted!  Most require
 28.3889 +	readers to be able to lock a repository to access it safely,
 28.3890 +	and this requires write permission on at least one directory,
 28.3891 +	which of course makes for all kinds of nasty and annoying
 28.3892 +	security and administrative problems.)</para>
 28.3893 +
 28.3894 +      <para id="x_32f">Mercurial uses locks to ensure that only one process can
 28.3895 +	write to a repository at a time (the locking mechanism is safe
 28.3896 +	even over filesystems that are notoriously hostile to locking,
 28.3897 +	such as NFS).  If a repository is locked, a writer will wait
 28.3898 +	for a while to retry if the repository becomes unlocked, but
 28.3899 +	if the repository remains locked for too long, the process
 28.3900 +	attempting to write will time out after a while. This means
 28.3901 +	that your daily automated scripts won't get stuck forever and
 28.3902 +	pile up if a system crashes unnoticed, for example.  (Yes, the
 28.3903 +	timeout is configurable, from zero to infinity.)</para>
 28.3904 +
 28.3905 +      <sect3>
 28.3906 +	<title>Safe dirstate access</title>
 28.3907 +
 28.3908 +	<para id="x_330">As with revision data, Mercurial doesn't take a lock to
 28.3909 +	  read the dirstate file; it does acquire a lock to write it.
 28.3910 +	  To avoid the possibility of reading a partially written copy
 28.3911 +	  of the dirstate file, Mercurial writes to a file with a
 28.3912 +	  unique name in the same directory as the dirstate file, then
 28.3913 +	  renames the temporary file atomically to
 28.3914 +	  <filename moreinfo="none">dirstate</filename>.  The file named
 28.3915 +	  <filename moreinfo="none">dirstate</filename> is thus guaranteed to be
 28.3916 +	  complete, not partially written.</para>
 28.3917 +
 28.3918 +      </sect3>
 28.3919 +    </sect2>
 28.3920 +    <sect2>
 28.3921 +      <title>Avoiding seeks</title>
 28.3922 +
 28.3923 +      <para id="x_331">Critical to Mercurial's performance is the avoidance of
 28.3924 +	seeks of the disk head, since any seek is far more expensive
 28.3925 +	than even a comparatively large read operation.</para>
 28.3926 +
 28.3927 +      <para id="x_332">This is why, for example, the dirstate is stored in a
 28.3928 +	single file.  If there were a dirstate file per directory that
 28.3929 +	Mercurial tracked, the disk would seek once per directory.
 28.3930 +	Instead, Mercurial reads the entire single dirstate file in
 28.3931 +	one step.</para>
 28.3932 +
 28.3933 +      <para id="x_333">Mercurial also uses a <quote>copy on write</quote> scheme
 28.3934 +	when cloning a repository on local storage.  Instead of
 28.3935 +	copying every revlog file from the old repository into the new
 28.3936 +	repository, it makes a <quote>hard link</quote>, which is a
 28.3937 +	shorthand way to say <quote>these two names point to the same
 28.3938 +	  file</quote>.  When Mercurial is about to write to one of a
 28.3939 +	revlog's files, it checks to see if the number of names
 28.3940 +	pointing at the file is greater than one.  If it is, more than
 28.3941 +	one repository is using the file, so Mercurial makes a new
 28.3942 +	copy of the file that is private to this repository.</para>
 28.3943 +
 28.3944 +      <para id="x_334">A few revision control developers have pointed out that
 28.3945 +	this idea of making a complete private copy of a file is not
 28.3946 +	very efficient in its use of storage.  While this is true,
 28.3947 +	storage is cheap, and this method gives the highest
 28.3948 +	performance while deferring most book-keeping to the operating
 28.3949 +	system.  An alternative scheme would most likely reduce
 28.3950 +	performance and increase the complexity of the software, but
 28.3951 +	speed and simplicity are key to the <quote>feel</quote> of
 28.3952 +	day-to-day use.</para>
 28.3953 +
 28.3954 +    </sect2>
 28.3955 +    <sect2>
 28.3956 +      <title>Other contents of the dirstate</title>
 28.3957 +
 28.3958 +      <para id="x_335">Because Mercurial doesn't force you to tell it when you're
 28.3959 +	modifying a file, it uses the dirstate to store some extra
 28.3960 +	information so it can determine efficiently whether you have
 28.3961 +	modified a file.  For each file in the working directory, it
 28.3962 +	stores the time that it last modified the file itself, and the
 28.3963 +	size of the file at that time.</para>
 28.3964 +
 28.3965 +      <para id="x_336">When you explicitly <command role="hg-cmd" moreinfo="none">hg
 28.3966 +	  add</command>, <command role="hg-cmd" moreinfo="none">hg remove</command>,
 28.3967 +	<command role="hg-cmd" moreinfo="none">hg rename</command> or <command role="hg-cmd" moreinfo="none">hg copy</command> files, Mercurial updates the
 28.3968 +	dirstate so that it knows what to do with those files when you
 28.3969 +	commit.</para>
 28.3970 +
 28.3971 +      <para id="x_337">The dirstate helps Mercurial to efficiently
 28.3972 +	  check the status of files in a repository.</para>
 28.3973 +
 28.3974 +      <itemizedlist>
 28.3975 +	<listitem>
 28.3976 +	  <para id="x_726">When Mercurial checks the state of a file in the
 28.3977 +	    working directory, it first checks a file's modification
 28.3978 +	    time against the time in the dirstate that records when
 28.3979 +	    Mercurial last wrote the file. If the last modified time
 28.3980 +	    is the same as the time when Mercurial wrote the file, the
 28.3981 +	    file must not have been modified, so Mercurial does not
 28.3982 +	    need to check any further.</para>
 28.3983 +	</listitem>
 28.3984 +	<listitem>
 28.3985 +	  <para id="x_727">If the file's size has changed, the file must have
 28.3986 +	    been modified.  If the modification time has changed, but
 28.3987 +	    the size has not, only then does Mercurial need to
 28.3988 +	    actually read the contents of the file to see if it has
 28.3989 +	    changed.</para>
 28.3990 +	</listitem>
 28.3991 +      </itemizedlist>
 28.3992 +
 28.3993 +      <para id="x_728">Storing the modification time and size dramatically
 28.3994 +	reduces the number of read operations that Mercurial needs to
 28.3995 +	perform when we run commands like <command moreinfo="none">hg status</command>.
 28.3996 +	This results in large performance improvements.</para>
 28.3997 +    </sect2>
 28.3998 +  </sect1>
 28.3999 +</chapter>
 28.4000 +
 28.4001 +<!--
 28.4002 +local variables: 
 28.4003 +sgml-parent-document: ("00book.xml" "book" "chapter")
 28.4004 +end:
 28.4005 +-->
 28.4006 +
 28.4007 +  <!-- BEGIN ch05 -->
 28.4008 +  <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
 28.4009 +
 28.4010 +<chapter id="chap:daily">
 28.4011 +  <?dbhtml filename="mercurial-in-daily-use.html"?>
 28.4012 +  <title>Mercurial pour une utilisation de tous les jours</title>
 28.4013 +
 28.4014 +  <sect1>
 28.4015 +    <title>Informer Mercurial des fichier à suivre</title>
 28.4016 +
 28.4017 +    <para id="x_1a3">Mercurial ne suit pas les fichiers de votre dépôt tant
 28.4018 +      que vous ne lui avez pas dit de les gérer. La commande <command role="hg-cmd" moreinfo="none">hg status</command> vous dira quels fichiers sont
 28.4019 +      inconnus de Mercurial. Il utilise un
 28.4020 +      <quote><literal moreinfo="none">?</literal></quote> pour montrer ces fichiers.</para>
 28.4021 +
 28.4022 +    <para id="x_1a4">Pour informer Mercurial de suivre un fichier, utilisez
 28.4023 +      la commande <command role="hg-cmd" moreinfo="none">hg add</command>. Une fois que vous
 28.4024 +      avez ajouté un fichier, la ligne correspondante à ce fichier dans la
 28.4025 +      sortie de <command role="hg-cmd" moreinfo="none">hg status</command> change de
 28.4026 +      <quote><literal moreinfo="none">?</literal></quote> à
 28.4027 +      <quote><literal moreinfo="none">A</literal></quote>.</para>
 28.4028 +
 28.4029 +    <!-- BEGIN daily.files.add -->
 28.4030 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init add-example</userinput>
 28.4031 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd add-example</userinput>
 28.4032 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a &gt; myfile.txt</userinput>
 28.4033 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
 28.4034 +? myfile.txt
 28.4035 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add myfile.txt</userinput>
 28.4036 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
 28.4037 +A myfile.txt
 28.4038 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Added one file'</userinput>
 28.4039 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
 28.4040 +</screen>
 28.4041 +<!-- END daily.files.add -->
 28.4042 +
 28.4043 +
 28.4044 +    <para id="x_1a5">Après avoir exécuté un <command role="hg-cmd" moreinfo="none">hg
 28.4045 +        commit</command>, les fichiers que vous avez ajoutés avant le commit
 28.4046 +      ne seront plus listés dans la sortie de <command role="hg-cmd" moreinfo="none">hg
 28.4047 +        status</command>. La raison de ceci est que, par défaut, <command role="hg-cmd" moreinfo="none">hg status</command> ne vous montre que les fichiers
 28.4048 +      <quote>intéressants</quote> —ceux que vous avez (par exemple)
 28.4049 +      modifiés, supprimés ou renommés. Si vous aviez un dépôt qui contient un
 28.4050 +      millier de fichiers, vous ne voudriez certainement que rarement entendre
 28.4051 +      parler des fichiers que Mercurial suit, mais qui n'ont pas changés.
 28.4052 +      (Vous pouvez quand même avoir cette information, nous y reviendrons
 28.4053 +      plus tard.)</para>
 28.4054 +
 28.4055 +    <para id="x_1a6">Une fois que vous ajoutez un fichier, Mercurial ne fait
 28.4056 +      rien du tout avec celui-ci immédiatement. Au lieu de ça, il va prendre
 28.4057 +      un "snapshot" de l'état du fichier la prochaine fois que vous
 28.4058 +      exécuterez un commit. Il continuera ensuite à suivre les changements
 28.4059 +      que vous avez fait au fichier chaque fois que vous committerez, et ce,
 28.4060 +      jusqu'à ce que vous supprimiez le fichier.</para>
 28.4061 +
 28.4062 +    <sect2>
 28.4063 +      <title>Nommage des fichiers explicite versus implicite</title>
 28.4064 +
 28.4065 +      <para id="x_1a7">Un comportement utile que Mercurial possède est que si
 28.4066 +        vous passez le nom d'un répertoire à une commande, toute commande
 28.4067 +        Mercurial la traitera comme : <quote>Je veux opérer sur chaque fichier
 28.4068 +          dans ce répertoire et ses sous-répertoires</quote>.</para>
 28.4069 +
 28.4070 +      <!-- BEGIN daily.files.add-dir -->
 28.4071 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mkdir b</userinput>
 28.4072 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo b &gt; b/somefile.txt</userinput>
 28.4073 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo c &gt; b/source.cpp</userinput>
 28.4074 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mkdir b/d</userinput>
 28.4075 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo d &gt; b/d/test.h</userinput>
 28.4076 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add b</userinput>
 28.4077 +adding b/d/test.h
 28.4078 +adding b/somefile.txt
 28.4079 +adding b/source.cpp
 28.4080 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Added all files in subdirectory'</userinput>
 28.4081 +</screen>
 28.4082 +<!-- END daily.files.add-dir -->
 28.4083 +
 28.4084 +
 28.4085 +      <para id="x_1a8">Remarquez que dans cet exemple, Mercurial affiche le
 28.4086 +        nom des fichiers qu'il a ajouté, alors qu'il ne l'a pas fait lorsque
 28.4087 +        nous avons ajouté le fichier nommé <filename moreinfo="none">myfile.txt</filename>
 28.4088 +        dans l'exemple précédent.</para>
 28.4089 +
 28.4090 +      <para id="x_1a9">Ce qu'il se passe est que dans le premier cas, nous
 28.4091 +        avons nommé explicitement le fichier à ajouter sur la ligne de
 28.4092 +        commande. Ce que Mercurial suppose dans ce cas est que nous savons ce
 28.4093 +        que nous faisons, il n'affiche donc rien en sortie.</para>
 28.4094 +
 28.4095 +      <para id="x_1aa">Cependant, lorsque nous avons
 28.4096 +        <emphasis>implicitement</emphasis> donné les fichiers à l'aide du nom
 28.4097 +        d'un répertoire, Mercurial prend l'initiative d'afficher le nom de
 28.4098 +        chaque fichier avec lequel il fait quelque chose. Ceci clarifie ce
 28.4099 +        qu'il se passe et réduit la probabilité d'une mauvaise surprise
 28.4100 +        restée silencieuse. Ce comportement est commun à la plupart des
 28.4101 +        commandes Mercurial.</para>
 28.4102 +    </sect2>
 28.4103 +    <sect2>
 28.4104 +      <title>Mercurial suit les fichiers, pas les répertoires</title>
 28.4105 +
 28.4106 +      <para id="x_1ab">Mercurial ne suit pas les informations sur les
 28.4107 +        répertoires. En contrepartie, il suit le chemin vers un fichier. Avant
 28.4108 +        de créer un fichier, il crée au préalable les répertoires manquants
 28.4109 +        dans le chemin. Après avoir supprimé un fichier, il supprime chaque
 28.4110 +        répertoire vide qui apparaît dans le chemin du fichier. Ceci apparaît
 28.4111 +        comme une distinction triviale, cependant, cela a une conséquence
 28.4112 +        pratique mineure : il n'est pas possible de représenter un répertoire
 28.4113 +        totalement vide dans Mercurial.</para>
 28.4114 +
 28.4115 +      <para id="x_1ac">Les répertoires vides sont rarement utiles. Il existe
 28.4116 +        cependant des solutions alternatives et non intrusives que vous
 28.4117 +        pouvez utiliser pour obtenir l'effet approprié. Les développeurs de
 28.4118 +        Mercurial ont ainsi pensé que la complexité requise pour gérer les
 28.4119 +        répertoires n'était pas aussi importante que le bénéfice que cette
 28.4120 +        fonctionnalité apporterait.</para>
 28.4121 +
 28.4122 +      <para id="x_1ad">Si vous avez besoin d'un répertoire vide dans votre
 28.4123 +        dépôt, il existe quelques façons d'y arriver. L'une d'elles est de
 28.4124 +        créer un répertoire et ensuite, de faire un <command role="hg-cmd" moreinfo="none">hg
 28.4125 +          add</command> sur un fichier <quote>caché</quote> dans ce
 28.4126 +        répertoire. Sur les systèmes de type Unix, tout fichier dont le nom
 28.4127 +        commence avec un point (<quote><literal moreinfo="none">.</literal></quote>) est
 28.4128 +        considéré comme caché par la plupart des commandes et outils
 28.4129 +        graphiques. Cette approche est illustrée ci-après.</para>
 28.4130 +      
 28.4131 +      <!-- BEGIN daily.files.hidden -->
 28.4132 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init hidden-example</userinput>
 28.4133 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd hidden-example</userinput>
 28.4134 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mkdir empty</userinput>
 28.4135 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">touch empty/.hidden</userinput>
 28.4136 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add empty/.hidden</userinput>
 28.4137 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Manage an empty-looking directory'</userinput>
 28.4138 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls empty</userinput>
 28.4139 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput>
 28.4140 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone hidden-example tmp</userinput>
 28.4141 +updating working directory
 28.4142 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 28.4143 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls tmp</userinput>
 28.4144 +empty
 28.4145 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls tmp/empty</userinput>
 28.4146 +</screen>
 28.4147 +<!-- END daily.files.hidden -->
 28.4148 +
 28.4149 +
 28.4150 +      <para id="x_1ae">Une autre façon de s'attaquer au besoin d'un
 28.4151 +        répertoire vide est de simplement d'en créer un dans vos scripts
 28.4152 +        de construction avant qu'ils n'en aient le besoin.</para>
 28.4153 +    </sect2>
 28.4154 +  </sect1>
 28.4155 +
 28.4156 +  <sect1>
 28.4157 +    <title>Comment arrêter de suivre un fichier</title>
 28.4158 +
 28.4159 +    <para id="x_1af">Une fois que vous décidez qu'un fichier n'appartient
 28.4160 +      plus à votre dépôt, utilisez la commande <command role="hg-cmd" moreinfo="none">hg
 28.4161 +        remove</command>. Ceci supprime le fichier et informe Mercurial
 28.4162 +      d'arrêter de le suivre (ce qui prendra effet lors du prochain commit).
 28.4163 +      Un fichier supprimé est représenté dans la sortie de la commande
 28.4164 +      <command role="hg-cmd" moreinfo="none">hg status</command> par un
 28.4165 +      <quote><literal moreinfo="none">R</literal></quote>.</para>
 28.4166 +
 28.4167 +    <!-- BEGIN daily.files.remove -->
 28.4168 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init remove-example</userinput>
 28.4169 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd remove-example</userinput>
 28.4170 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a &gt; a</userinput>
 28.4171 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mkdir b</userinput>
 28.4172 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo b &gt; b/b</userinput>
 28.4173 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add a b</userinput>
 28.4174 +adding b/b
 28.4175 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Small example for file removal'</userinput>
 28.4176 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg remove a</userinput>
 28.4177 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
 28.4178 +R a
 28.4179 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg remove b</userinput>
 28.4180 +removing b/b
 28.4181 +</screen>
 28.4182 +<!-- END daily.files.remove -->
 28.4183 +
 28.4184 +
 28.4185 +    <para id="x_1b0">Après avoir fait un <command role="hg-cmd" moreinfo="none">hg
 28.4186 +        remove</command> sur un fichier, Mercurial ne suivra plus aucun
 28.4187 +      changement sur ce fichier, même si vous recréez un fichier avec le même
 28.4188 +      nom dans votre répertoire de travail. Si vous recréez un fichier avec le
 28.4189 +      même nom et que vous désirez que Mercurial suive ce dernier, faite
 28.4190 +      simplement un <command role="hg-cmd" moreinfo="none">hg add</command> sur celui-ci.
 28.4191 +      Mercurial saura alors que le nouveau fichier ne fait pas référence à
 28.4192 +      l'ancien fichier qui portait le même nom.</para>
 28.4193 +
 28.4194 +    <sect2>
 28.4195 +      <title>Supprimer un fichier n'affecte pas son historique</title>
 28.4196 +
 28.4197 +      <para id="x_1b1">Il est important de comprendre que supprimer un fichier
 28.4198 +        n'a que deux effets.</para>
 28.4199 +
 28.4200 +      <itemizedlist>
 28.4201 +        <listitem><para id="x_1b2">Il supprime la version actuelle de ce
 28.4202 +            fichier du répertoire de travail.</para>
 28.4203 +        </listitem>
 28.4204 +        <listitem><para id="x_1b3">Il arrête, à partir du prochain commit, le
 28.4205 +            suivi de Mercurial sur les changements qui ont lieu sur ce
 28.4206 +            fichier.</para>
 28.4207 +        </listitem></itemizedlist>
 28.4208 +        
 28.4209 +      <para id="x_1b4">Supprimer un fichier <emphasis>n'</emphasis>affecte en
 28.4210 +        <emphasis>aucun</emphasis> cas l'<emphasis>historique</emphasis> du
 28.4211 +        fichier.</para>
 28.4212 +
 28.4213 +      <para id="x_1b5">Si vous mettez à jour le répertoire de travail à un
 28.4214 +        changeset qui a été committé alors que le fichier que vous venez de
 28.4215 +        supprimer était encore suivi, ce fichier réapparaîtra dans le
 28.4216 +        répertoire de travail, avec le contenu qu'il avait lorsque vous aviez
 28.4217 +        committé ce changeset. Si vous mettez à jour (update) le répertoire de
 28.4218 +        travail à un changeset ultérieur dans lequel le fichier a été
 28.4219 +        supprimé, Mercurial supprimera une nouvelle fois le fichier du
 28.4220 +        répertoire de travail.</para>
 28.4221 +    </sect2>
 28.4222 +
 28.4223 +    <sect2>
 28.4224 +      <title>Fichiers manquants</title>
 28.4225 +
 28.4226 +      <para id="x_1b6">Mercurial considère qu'un fichier que vous avez
 28.4227 +        supprimé sans utiliser<command role="hg-cmd" moreinfo="none">hg remove</command>
 28.4228 +        comme étant <emphasis>manquant</emphasis>.  Un fichier manquant est
 28.4229 +        représenté avec un <quote><literal moreinfo="none">!</literal></quote> en sortie de
 28.4230 +        <command role="hg-cmd" moreinfo="none">hg status</command>.
 28.4231 +        Les commandes Mercurial ne feront rien avec les fichiers
 28.4232 +        manquants.</para>
 28.4233 +
 28.4234 +      <!-- BEGIN daily.files.missing -->
 28.4235 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init missing-example</userinput>
 28.4236 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd missing-example</userinput>
 28.4237 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a &gt; a</userinput>
 28.4238 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add a</userinput>
 28.4239 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'File about to be missing'</userinput>
 28.4240 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">rm a</userinput>
 28.4241 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
 28.4242 +! a
 28.4243 +</screen>
 28.4244 +<!-- END daily.files.missing -->
 28.4245 +
 28.4246 +
 28.4247 +      <para id="x_1b7">Si votre dépôt contient un fichier que <command role="hg-cmd" moreinfo="none">hg status</command> reporte comme manquant, et que
 28.4248 +        vous voulez que ce fichier reste supprimé, vous pouvez exécuter
 28.4249 +        <command role="hg-cmd" moreinfo="none">hg remove <option role="hg-opt-remove">--after</option></command> à tout moment
 28.4250 +        pour dire à Mercurial que vous aviez bien voulu supprimer ce
 28.4251 +        fichier.</para>
 28.4252 +
 28.4253 +      <!-- BEGIN daily.files.remove-after -->
 28.4254 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg remove --after a</userinput>
 28.4255 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
 28.4256 +R a
 28.4257 +</screen>
 28.4258 +<!-- END daily.files.remove-after -->
 28.4259 +
 28.4260 +
 28.4261 +      <para id="x_1b8">D'un autre coté, si vous avez supprimé le fichier
 28.4262 +        manquant par accident, donnez à la commande <command role="hg-cmd" moreinfo="none">hg
 28.4263 +          revert</command> le nom du fichier à retrouver. Il réapparaitra dans
 28.4264 +        sa forme non modifiée.</para>
 28.4265 +
 28.4266 +      <!-- BEGIN daily.files.recover-missing -->
 28.4267 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg revert a</userinput>
 28.4268 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat a</userinput>
 28.4269 +a
 28.4270 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
 28.4271 +</screen>
 28.4272 +<!-- END daily.files.recover-missing -->
 28.4273 +
 28.4274 +    
 28.4275 +    </sect2>
 28.4276 +
 28.4277 +    <sect2>
 28.4278 +      <title>Entre nous : Pourquoi dire explicitement à Mercurial de supprimer un
 28.4279 +      fichier ?</title>
 28.4280 +
 28.4281 +      <para id="x_1b9">Vous pourriez vous demander pourquoi il est nécessaire
 28.4282 +        de dire explicitement à Mercurial que vous souhaitez supprimer un
 28.4283 +        fichier. Au début du développement de Mercurial, celui ci vous
 28.4284 +        laissait pourtant supprimer un fichier sans soucis ; Mercurial vous
 28.4285 +        aurait automatiquement informé de l'absence du fichier lorsque vous
 28.4286 +        auriez lancé un <command role="hg-cmd" moreinfo="none">hg commit</command> et arrêté
 28.4287 +        de le suivre. En pratique, ceci a montré qu'il était trop facile de
 28.4288 +        supprimer accidentellement un fichier sans le remarquer.</para>
 28.4289 +    </sect2>
 28.4290 +
 28.4291 +    <sect2>
 28.4292 +      <title>Raccourci utile—ajouter et supprimer des fichiers en une
 28.4293 +      seule étape.</title>
 28.4294 +
 28.4295 +      <para id="x_1ba">Mercurial offre une commande combinée, <command role="hg-cmd" moreinfo="none">hg addremove</command>, qui ajoute les fichiers non
 28.4296 +        suivis et marque les fichiers manquants comme supprimés.</para>
 28.4297 +
 28.4298 +      <!-- BEGIN daily.files.addremove -->
 28.4299 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init addremove-example</userinput>
 28.4300 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd addremove-example</userinput>
 28.4301 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a &gt; a</userinput>
 28.4302 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo b &gt; b</userinput>
 28.4303 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg addremove</userinput>
 28.4304 +adding a
 28.4305 +adding b
 28.4306 +</screen>
 28.4307 +<!-- END daily.files.addremove -->
 28.4308 +
 28.4309 +
 28.4310 +      <para id="x_1bb">La commande <command role="hg-cmd" moreinfo="none">hg commit</command>
 28.4311 +        fournit aussi une option <option role="hg-opt-commit">-A</option> qui
 28.4312 +        exécute le même ajouter-et-supprimer, immédiatement suivi d'un
 28.4313 +        commit.</para>
 28.4314 +
 28.4315 +      <!-- BEGIN daily.files.commit-addremove -->
 28.4316 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo c &gt; c</userinput>
 28.4317 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'Commit with addremove'</userinput>
 28.4318 +adding c
 28.4319 +</screen>
 28.4320 +<!-- END daily.files.commit-addremove -->
 28.4321 +
 28.4322 +    
 28.4323 +    </sect2>
 28.4324 +  </sect1>
 28.4325 +
 28.4326 +  <sect1 id="chap:daily.copy">
 28.4327 +    <title>Copier des fichiers</title>
 28.4328 +
 28.4329 +    <para id="x_1bc">Mercurial fournit une commande <command role="hg-cmd" moreinfo="none">hg
 28.4330 +        copy</command> qui vous permet de faire une nouvelle copie d'un
 28.4331 +      fichier. Lorsque vous copiez un fichier en utilisant cette commande,
 28.4332 +      Mercurial crée un enregistrement du fait que ce nouveau fichier est une
 28.4333 +      copie du fichier originel. Il traite ces fichiers copiés spécialement
 28.4334 +      lorsque vous fusionnez (merge) votre travail avec quelqu'un
 28.4335 +      d'autre.</para>
 28.4336 +
 28.4337 +    <sect2>
 28.4338 +      <title>Les résultats d'une copie durant une fusion (merge)</title>
 28.4339 +
 28.4340 +      <para id="x_1bd">Ce qu'il se passe durant une fusion (merge) est que
 28.4341 +        les changements <quote>suivent</quote> une copie. Pour illustrer ce
 28.4342 +        que cela veut dire de la meilleure façon, créons un exemple. Nous
 28.4343 +        allons commencer avec le mini dépôt usuel qui contient un simple
 28.4344 +        fichier.</para>
 28.4345 +
 28.4346 +      <!-- BEGIN daily.copy.init -->
 28.4347 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init my-copy</userinput>
 28.4348 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd my-copy</userinput>
 28.4349 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo line &gt; file</userinput>
 28.4350 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add file</userinput>
 28.4351 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Added a file'</userinput>
 28.4352 +</screen>
 28.4353 +<!-- END daily.copy.init -->
 28.4354 +
 28.4355 +
 28.4356 +      <para id="x_1be">Nous devons faire du travail en parallèle, ainsi,
 28.4357 +        nous aurons quelque chose à fusionner (merge). Donc clonons notre
 28.4358 +        dépôt.</para>
 28.4359 +
 28.4360 +      <!-- BEGIN daily.copy.clone -->
 28.4361 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput>
 28.4362 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone my-copy your-copy</userinput>
 28.4363 +updating working directory
 28.4364 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 28.4365 +</screen>
 28.4366 +<!-- END daily.copy.clone -->
 28.4367 +
 28.4368 +
 28.4369 +      <para id="x_1bf">De retour dans notre dépôt initial, utilisons la
 28.4370 +        commande <command role="hg-cmd" moreinfo="none">hg copy</command> pour faire une
 28.4371 +        copie du premier fichier que nous avons créé.</para>
 28.4372 +
 28.4373 +      <!-- BEGIN daily.copy.copy -->
 28.4374 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd my-copy</userinput>
 28.4375 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg copy file new-file</userinput>
 28.4376 +</screen>
 28.4377 +<!-- END daily.copy.copy -->
 28.4378 +
 28.4379 +
 28.4380 +      <para id="x_1c0">Si nous regardons ensuite à la sortie de la commande
 28.4381 +        <command role="hg-cmd" moreinfo="none">hg status</command>, les fichiers copiés
 28.4382 +        ont l'air de fichiers normalement ajoutés.</para>
 28.4383 +
 28.4384 +      <!-- BEGIN daily.copy.status -->
 28.4385 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
 28.4386 +A new-file
 28.4387 +</screen>
 28.4388 +<!-- END daily.copy.status -->
 28.4389 +
 28.4390 +
 28.4391 +      <para id="x_1c1">Mais si nous passons l'option <option role="hg-opt-status">-C</option> à <command role="hg-cmd" moreinfo="none">hg
 28.4392 +          status</command>, il affiche une autre ligne de sortie : il s'agit
 28.4393 +        du fichier <emphasis>source</emphasis> pour notre copie.</para>
 28.4394 +
 28.4395 +      <!-- BEGIN daily.copy.status-copy -->
 28.4396 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status -C</userinput>
 28.4397 +A new-file
 28.4398 +  file
 28.4399 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Copied file'</userinput>
 28.4400 +</screen>
 28.4401 +<!-- END daily.copy.status-copy -->
 28.4402 +
 28.4403 +
 28.4404 +      <para id="x_1c2">Maintenant, de retour dans le dépôt que nous avons
 28.4405 +        cloné, créons un changement en parallèle. Nous allons ajouter une
 28.4406 +        ligne de contenu au fichier original qui a été créé.</para>
 28.4407 +
 28.4408 +      <!-- BEGIN daily.copy.other -->
 28.4409 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ../your-copy</userinput>
 28.4410 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'new contents' &gt;&gt; file</userinput>
 28.4411 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Changed file'</userinput>
 28.4412 +</screen>
 28.4413 +<!-- END daily.copy.other -->
 28.4414 +
 28.4415 +
 28.4416 +      <para id="x_1c3">Nous avons alors un fichier <filename moreinfo="none">file</filename>
 28.4417 +        modifié dans ce dépôt. Lorsque nous récupérons (pull) les changements
 28.4418 +        depuis le premier répertoire et fusionnons (merge) les deux "heads",
 28.4419 +        Mercurial propagera les changements que nous avons faits localement
 28.4420 +        au fichier <filename moreinfo="none">file</filename> dans sa copie
 28.4421 +        <filename moreinfo="none">new-file</filename>.</para>
 28.4422 +
 28.4423 +      <!-- BEGIN daily.copy.merge -->
 28.4424 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull ../my-copy</userinput>
 28.4425 +pulling from ../my-copy
 28.4426 +searching for changes
 28.4427 +adding changesets
 28.4428 +adding manifests
 28.4429 +adding file changes
 28.4430 +added 1 changesets with 1 changes to 1 files (+1 heads)
 28.4431 +(run 'hg heads' to see heads, 'hg merge' to merge)
 28.4432 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg merge</userinput>
 28.4433 +merging file and new-file to new-file
 28.4434 +0 files updated, 1 files merged, 0 files removed, 0 files unresolved
 28.4435 +(branch merge, don't forget to commit)
 28.4436 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat new-file</userinput>
 28.4437 +line
 28.4438 +new contents
 28.4439 +</screen>
 28.4440 +<!-- END daily.copy.merge -->
 28.4441 +
 28.4442 +    
 28.4443 +    </sect2>
 28.4444 +    <sect2 id="sec:daily:why-copy">
 28.4445 +      <title>Pourquoi est-ce que les changements devraient suivre les copies
 28.4446 +        ?</title>
 28.4447 +
 28.4448 +      <para id="x_1c4">Ce comportement—des changements d'un fichiers
 28.4449 +        qui se propagent aux copies de ce fichier—peut sembler
 28.4450 +        ésotérique, mais, dans la plupart des cas, c'est hautement
 28.4451 +        désirable.</para>
 28.4452 +
 28.4453 +      <para id="x_1c5">Pour commencer, souvenez vous que cette propagation
 28.4454 +        a lieue <emphasis>seulement</emphasis> lors des fusions (merge).
 28.4455 +        Donc, si vous faites un	<command role="hg-cmd" moreinfo="none">hg copy</command> sur
 28.4456 +        un fichier, et par la suite modifiez le fichier original durant le
 28.4457 +        cours normal de votre travail, rien n'a lieu.</para>
 28.4458 +
 28.4459 +      <para id="x_1c6">La deuxième chose à savoir c'est que les modifications
 28.4460 +        ne se propageront à travers une copie que si le changeset à partir
 28.4461 +        duquel vous faites une fusion (merge) <emphasis>n'a pas encore
 28.4462 +          vu</emphasis> la copie.</para>
 28.4463 +          
 28.4464 +      <para id="x_1c7">La raison pour laquelle Mercurial fait ainsi est une
 28.4465 +        règle. Imaginons que je corrige un important bug dans un fichier source
 28.4466 +        et que je commit mes changements. Pendant ce temps, vous avez décidé de
 28.4467 +        faire un <command role="hg-cmd" moreinfo="none">hg copy</command> du fichier dans
 28.4468 +        votre dépôt, sans rien savoir au sujet du bug ou à propos de la
 28.4469 +        correction. Vous avez alors commencé à "hacker" sur votre copie du
 28.4470 +        fichier.</para>
 28.4471 +
 28.4472 +      <para id="x_1c8">Si vous aviez récupéré (pull) et fusionné (merge) mes
 28.4473 +        changements, et que Mercurial <emphasis>n'avait pas</emphasis>
 28.4474 +        propagé les changements à travers les copies, votre nouveau fichier
 28.4475 +        source contiendrait maintenant le bug, et à moins que vous ne sachiez
 28.4476 +        qu'il faille propager la correction du bug à la main, le bug aurait
 28.4477 +        <emphasis>subsisté</emphasis> dans votre copie du fichier.</para>
 28.4478 +
 28.4479 +      <para id="x_1c9">En propageant automatiquement les changements qui
 28.4480 +        fixent les bugs à partir du fichier original vers les copies,
 28.4481 +        Mercurial prévient ce type de problèmes. A ma connaissance, Mercurial
 28.4482 +        est le <emphasis>seul</emphasis> système de gestion de révisions qui
 28.4483 +        propage les changements à travers les copies comme ceci.</para>
 28.4484 +
 28.4485 +      <para id="x_1ca">Une fois que votre historique des changements a un
 28.4486 +        enregistrement concernant une copie et qu'une fusion postérieure a
 28.4487 +        eu lieue, il n'y a d'habitude pas d'autre besoin de propager les
 28.4488 +        changements du fichier originel vers le fichier copié. C'est pourquoi
 28.4489 +        Mercurial ne propage les changements à travers les copies qu'à la
 28.4490 +        première fusion, et pas d'avantage.</para>
 28.4491 +    </sect2>
 28.4492 +
 28.4493 +    <sect2>
 28.4494 +      <title>Comment faire des changements qui <emphasis>ne</emphasis>
 28.4495 +      suivent <emphasis>pas</emphasis> une copie</title>
 28.4496 +
 28.4497 +      <para id="x_1cb">Si pour une raison ou une autre, vous décidez que
 28.4498 +        cette fonctionnalité de propager automatiquement les changements à
 28.4499 +        travers les copies n'est pas pour vous, utilisez simplement la
 28.4500 +        commande normale de copie de votre système (sur les systèmes de type
 28.4501 +        Unix, il s'agit de <command moreinfo="none">cp</command>) pour faire une copie d'un
 28.4502 +        fichier. Utilisez ensuite <command role="hg-cmd" moreinfo="none">hg add</command>
 28.4503 +        pour ajouter les nouveaux fichiers à la main. Cependant, avant d'en
 28.4504 +        faire ainsi, relisez <xref linkend="sec:daily:why-copy"/>, et faites
 28.4505 +        un choix en connaissance de cause comme quoi cette fonctionnalité
 28.4506 +        n'est pas appropriée à votre cas spécifique.</para>
 28.4507 +
 28.4508 +    </sect2>
 28.4509 +    <sect2>
 28.4510 +      <title>Comportement de la commande <command role="hg-cmd" moreinfo="none">hg copy</command></title>
 28.4511 +
 28.4512 +      <para id="x_1cc">Lorsque vous utilisez la commande <command role="hg-cmd" moreinfo="none">hg copy</command>, Mercurial crée une copie de chaque
 28.4513 +        fichier source tel qu'il est actuellement dans le répertoire de
 28.4514 +        travail. Cela signifie que si vous effectuez des modifications sur un
 28.4515 +        fichier, puis faites un <command role="hg-cmd" moreinfo="none">hg copy</command> sur
 28.4516 +        celui-ci sans avoir au préalable committé ces changements, la nouvelle
 28.4517 +        copie contiendra aussi les modifications que vous avez fait jusqu'à
 28.4518 +        ce point.	(Je trouve ce comportement quelque peu contre intuitif,
 28.4519 +        c'est pourquoi j'en fais mention ici.)</para>
 28.4520 +      <!-- Vérifier que je n'ai pas fait de contre sens en relisant la
 28.4521 +      version anglaise, ce que je comprend ici me paraît un peu bizarre -->
 28.4522 +
 28.4523 +      <para id="x_1cd">La commande <command role="hg-cmd" moreinfo="none">hg copy</command>
 28.4524 +        agit comme la commande Unix <command moreinfo="none">cp</command> (vous pouvez
 28.4525 +        utilisez l'alias <command role="hg-cmd" moreinfo="none">hg cp</command> si vous
 28.4526 +        préférez).  Nous devons lui donner deux ou plus arguments où le
 28.4527 +        dernier est considéré comme la <emphasis>destination</emphasis>, et
 28.4528 +        les autres comme les <emphasis>sources</emphasis>.</para>
 28.4529 +
 28.4530 +      <para id="x_685">Si vous passez à <command role="hg-cmd" moreinfo="none">hg
 28.4531 +          copy</command> un seul fichier source, et que la destination
 28.4532 +        n'existe pas, ceci créera un nouveau fichier avec ce nom.</para>
 28.4533 +
 28.4534 +      <!-- BEGIN daily.copy.simple -->
 28.4535 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mkdir k</userinput>
 28.4536 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg copy a k</userinput>
 28.4537 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls k</userinput>
 28.4538 +a
 28.4539 +</screen>
 28.4540 +<!-- END daily.copy.simple -->
 28.4541 +
 28.4542 +
 28.4543 +      <para id="x_1ce">Si la destination est un répertoire, Mercurial copie
 28.4544 +        les sources dans ce répertoire.</para>
 28.4545 +
 28.4546 +      <!-- BEGIN daily.copy.dir-dest -->
 28.4547 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mkdir d</userinput>
 28.4548 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg copy a b d</userinput>
 28.4549 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls d</userinput>
 28.4550 +a  b
 28.4551 +</screen>
 28.4552 +<!-- END daily.copy.dir-dest -->
 28.4553 +
 28.4554 +
 28.4555 +      <para id="x_1cf">La copie de répertoire est récursive et préserve la
 28.4556 +        structure du répertoire source.</para>
 28.4557 +
 28.4558 +      <!-- BEGIN daily.copy.dir-src -->
 28.4559 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg copy z e</userinput>
 28.4560 +copying z/a/c to e/a/c
 28.4561 +</screen>
 28.4562 +<!-- END daily.copy.dir-src -->
 28.4563 +
 28.4564 +
 28.4565 +      <para id="x_1d0">Si la source et la destination sont tous deux des
 28.4566 +        répertoires, l'arborescence de la source est recréée dans le
 28.4567 +        répertoire destination.</para>
 28.4568 +    
 28.4569 +      <!-- BEGIN daily.copy.dir-src-dest -->
 28.4570 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg copy z d</userinput>
 28.4571 +copying z/a/c to d/z/a/c
 28.4572 +</screen>
 28.4573 +<!-- END daily.copy.dir-src-dest -->
 28.4574 +
 28.4575 +
 28.4576 +      <para id="x_1d1">Comme avec la commande <command role="hg-cmd" moreinfo="none">hg
 28.4577 +          remove</command>, si vous copiez un fichier manuellement et voulez
 28.4578 +        que Mercurial sache qu'il s'agit d'une copie, utilisez simplement
 28.4579 +        l'option <option role="hg-opt-copy">--after</option> avec <command role="hg-cmd" moreinfo="none">hg copy</command>.</para>
 28.4580 +
 28.4581 +      <!-- BEGIN daily.copy.after -->
 28.4582 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cp a n</userinput>
 28.4583 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg copy --after a n</userinput>
 28.4584 +</screen>
 28.4585 +<!-- END daily.copy.after -->
 28.4586 +
 28.4587 +    </sect2>
 28.4588 +  </sect1>
 28.4589 +
 28.4590 +  <sect1>
 28.4591 +    <title>Renommer les fichiers</title>
 28.4592 +
 28.4593 +    <para id="x_1d2">Il est plus commun d'avoir besoin de renommer un
 28.4594 +      fichier que d'en faire une copie. La raison pour laquelle j'ai discuté
 28.4595 +      de la commande <command role="hg-cmd" moreinfo="none">hg copy</command> avant de parler
 28.4596 +      de renommage des fichiers est que Mercurial traite les renommages
 28.4597 +      essentiellement comme une copie. Ainsi, savoir comment Mercurial traite
 28.4598 +      les copies de fichiers vous informe sur ce que vous êtes en droit
 28.4599 +      d'attendre lorsque vous renommez un fichier.</para>
 28.4600 +
 28.4601 +    <para id="x_1d3">Lorsque vous utilisez la commande <command role="hg-cmd" moreinfo="none">hg rename</command>, Mercurial crée une copie de tous
 28.4602 +      les fichiers sources, les supprime et marque ces fichiers comme étant
 28.4603 +      supprimés.</para>
 28.4604 +
 28.4605 +    <!-- BEGIN daily.rename.rename -->
 28.4606 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg rename a b</userinput>
 28.4607 +</screen>
 28.4608 +<!-- END daily.rename.rename -->
 28.4609 +
 28.4610 +
 28.4611 +    <para id="x_1d4">La commande <command role="hg-cmd" moreinfo="none">hg status</command>
 28.4612 +      montre les nouveaux fichiers comme ajoutés et les fichiers originaux
 28.4613 +      comme supprimés.</para>
 28.4614 +
 28.4615 +    <!-- BEGIN daily.rename.status -->
 28.4616 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
 28.4617 +A b
 28.4618 +R a
 28.4619 +</screen>
 28.4620 +<!-- END daily.rename.status -->
 28.4621 +
 28.4622 +
 28.4623 +    <para id="x_1d5">A cause du <command role="hg-cmd" moreinfo="none">hg	copy</command>,
 28.4624 +      nous devons utiliser l'option <option role="hg-opt-status">-C</option>
 28.4625 +      pour la commande <command role="hg-cmd" moreinfo="none">hg status</command> afin
 28.4626 +      d'observer que le fichier ajouté est bien suivi par Mercurial comme
 28.4627 +      étant une copie de l'original maintenant supprimé.</para>
 28.4628 +
 28.4629 +    <!-- BEGIN daily.rename.status-copy -->
 28.4630 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status -C</userinput>
 28.4631 +A b
 28.4632 +  a
 28.4633 +R a
 28.4634 +</screen>
 28.4635 +<!-- END daily.rename.status-copy -->
 28.4636 +
 28.4637 +
 28.4638 +    <para id="x_1d6">Comme avec <command role="hg-cmd" moreinfo="none">hg remove</command> et
 28.4639 +      <command role="hg-cmd" moreinfo="none">hg copy</command>, vous pouvez informer
 28.4640 +      Mercurial au sujet d'un renommage après coup en utilisant l'option
 28.4641 +      <option role="hg-opt-rename">--after</option>. Dans le plus grand
 28.4642 +      respect, le comportement de la commande <command role="hg-cmd" moreinfo="none">hg
 28.4643 +        rename</command>, et les options qu'il accepte sont similaires à la
 28.4644 +      commande <command role="hg-cmd" moreinfo="none">hg copy</command>.</para>
 28.4645 +
 28.4646 +    <para id="x_686">Si vous êtes familier avec la ligne de commande Unix,
 28.4647 +      vous serez heureux d'apprendre que la commande <command role="hg-cmd" moreinfo="none">hg rename</command> peut être invoquée par <command role="hg-cmd" moreinfo="none">hg mv</command>.</para>
 28.4648 +
 28.4649 +    <sect2>
 28.4650 +      <title>Renommer les fichiers et fusionner (merge) les changements</title>
 28.4651 +
 28.4652 +      <para id="x_1d7">Puise que le "rename" de Mercurial est implanté comme un
 28.4653 +        "copy-and-remove", la même propagation des changements a lieue après
 28.4654 +        un "rename" qu'après un "copy" lorsque vous fusionnez (merge).</para>
 28.4655 +
 28.4656 +      <para id="x_1d8">Si je modifie un fichier et que vous le renommez, si
 28.4657 +        ensuite nous fusionnons nos changements respectifs, mes modifications
 28.4658 +        sur le fichier sous son nom originel seront propagés vers le même
 28.4659 +        fichier sous son nouveau nom. (C'est quelque chose que vous pourriez
 28.4660 +        espérer voir <quote>fonctionner simplement</quote>, mais tous les
 28.4661 +        systèmes de gestion de version ne le font pas.)</para>
 28.4662 +
 28.4663 +      <para id="x_1d9">Tandis qu'avoir des changements qui suivent une copie
 28.4664 +        est une fonctionnalité où vous hocheriez sûrement la tête en disant
 28.4665 +        <quote>oui, cela pourrait être utile</quote>, il est clair que les
 28.4666 +        voir suivre un renommage est définitivement important. Sans cette
 28.4667 +        aptitude, il serait vraiment trop facile d'avoir des changements
 28.4668 +        qui deviennent orphelins lorsque des fichiers sont renommés.</para>
 28.4669 +    </sect2>
 28.4670 +
 28.4671 +    <sect2>
 28.4672 +      <title>Renommages divergeants et fusion (merge)</title>
 28.4673 +
 28.4674 +      <para id="x_1da">Le cas de noms divergeants a lieu lorsque deux
 28.4675 +        développeurs commencent avec un fichier—appelons le
 28.4676 +        <filename moreinfo="none">foo</filename>—dans leurs dépôts respectifs.</para>
 28.4677 +
 28.4678 +      <!-- BEGIN rename.divergent.clone -->
 28.4679 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone orig anne</userinput>
 28.4680 +updating working directory
 28.4681 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 28.4682 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone orig bob</userinput>
 28.4683 +updating working directory
 28.4684 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 28.4685 +</screen>
 28.4686 +<!-- END rename.divergent.clone -->
 28.4687 +
 28.4688 +
 28.4689 +      <para id="x_1db">Anne renomme le fichier en
 28.4690 +        <filename moreinfo="none">bar</filename>.</para>
 28.4691 +
 28.4692 +      <!-- BEGIN rename.divergent.rename.anne -->
 28.4693 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd anne</userinput>
 28.4694 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg rename foo bar</userinput>
 28.4695 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg ci -m 'Rename foo to bar'</userinput>
 28.4696 +</screen>
 28.4697 +<!-- END rename.divergent.rename.anne -->
 28.4698 +
 28.4699 +
 28.4700 +      <para id="x_1dc">Pendant ce temps, Bob le renomme en
 28.4701 +        <filename moreinfo="none">quux</filename>. (Souvenez vous que <command role="hg-cmd" moreinfo="none">hg mv</command> est un alias pour <command role="hg-cmd" moreinfo="none">hg rename</command>.)</para>
 28.4702 +    
 28.4703 +      <!-- BEGIN rename.divergent.rename.bob -->
 28.4704 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ../bob</userinput>
 28.4705 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg mv foo quux</userinput>
 28.4706 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg ci -m 'Rename foo to quux'</userinput>
 28.4707 +</screen>
 28.4708 +<!-- END rename.divergent.rename.bob -->
 28.4709 +
 28.4710 +
 28.4711 +      <para id="x_1dd">J'aime à penser qu'il s'agit d'un conflit puisque
 28.4712 +        chaque développeur a exprimé différentes intentions au sujet de ce
 28.4713 +        que le nom de ce fichier aurait du être.</para>
 28.4714 +
 28.4715 +      <para id="x_1de">Que pensez vous qu'il devrait se produire lorsqu'ils
 28.4716 +        fusionnent (merge) leurs travaux ? Le comportement actuel de
 28.4717 +        Mercurial est qu'il préserve toujours les <emphasis>deux</emphasis>
 28.4718 +        noms lorsqu'il fusionne (merge) des changesets qui contiennent des
 28.4719 +        renommages divergeants.</para>
 28.4720 +
 28.4721 +      <!-- BEGIN rename.divergent.merge -->
 28.4722 +<screen format="linespecific"># See http://www.selenic.com/mercurial/bts/issue455
 28.4723 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ../orig</userinput>
 28.4724 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull -u ../anne</userinput>
 28.4725 +pulling from ../anne
 28.4726 +searching for changes
 28.4727 +adding changesets
 28.4728 +adding manifests
 28.4729 +adding file changes
 28.4730 +added 1 changesets with 1 changes to 1 files
 28.4731 +1 files updated, 0 files merged, 1 files removed, 0 files unresolved
 28.4732 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull ../bob</userinput>
 28.4733 +pulling from ../bob
 28.4734 +searching for changes
 28.4735 +adding changesets
 28.4736 +adding manifests
 28.4737 +adding file changes
 28.4738 +added 1 changesets with 1 changes to 1 files (+1 heads)
 28.4739 +(run 'hg heads' to see heads, 'hg merge' to merge)
 28.4740 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg merge</userinput>
 28.4741 +warning: detected divergent renames of foo to:
 28.4742 + bar
 28.4743 + quux
 28.4744 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 28.4745 +(branch merge, don't forget to commit)
 28.4746 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls</userinput>
 28.4747 +bar  quux
 28.4748 +</screen>
 28.4749 +<!-- END rename.divergent.merge -->
 28.4750 +
 28.4751 +
 28.4752 +      <para id="x_1df">Remarquez que bien que Mercurial vous avertisse au
 28.4753 +        sujet de la divergeance des renommages, il vous laisse faire quelque
 28.4754 +        chose au sujet de la divergeance après la fusion (merge).</para>
 28.4755 +    </sect2>
 28.4756 +
 28.4757 +    <sect2>
 28.4758 +      <title>Renommages et fusion convergeants</title>
 28.4759 +
 28.4760 +      <para id="x_1e0">Un autre type de conflit de renommage intervient
 28.4761 +        lorsque deux personne choisissent de renommer différents fichiers
 28.4762 +        <emphasis>source</emphasis> vers la même
 28.4763 +        <emphasis>destination</emphasis>. Dans ce cas, Mercurial exécute la
 28.4764 +        machinerie normale de fusion (merge) et vous guide vers une
 28.4765 +        solution convenable.</para>
 28.4766 +    </sect2>
 28.4767 +
 28.4768 +    <sect2>
 28.4769 +      <title>Autres cas anguleux relatifs aux noms</title>
 28.4770 +
 28.4771 +      <para id="x_1e1">Mercurial possède un bug de longue date dans lequel il
 28.4772 +        échoue à traiter une fusion (merge) où un coté a un fichier avec un
 28.4773 +        nom donné, alors que l'autre coté possède un répertoire avec le même nom.
 28.4774 +        Ceci est documenté dans l'<ulink role="hg-bug" url="http://www.selenic.com/mercurial/bts/issue29">issue
 28.4775 +          29</ulink>.</para>
 28.4776 +
 28.4777 +      <!-- BEGIN issue29.go -->
 28.4778 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init issue29</userinput>
 28.4779 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd issue29</userinput>
 28.4780 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a &gt; a</userinput>
 28.4781 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg ci -Ama</userinput>
 28.4782 +adding a
 28.4783 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo b &gt; b</userinput>
 28.4784 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg ci -Amb</userinput>
 28.4785 +adding b
 28.4786 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg up 0</userinput>
 28.4787 +0 files updated, 0 files merged, 1 files removed, 0 files unresolved
 28.4788 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mkdir b</userinput>
 28.4789 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo b &gt; b/b</userinput>
 28.4790 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg ci -Amc</userinput>
 28.4791 +adding b/b
 28.4792 +created new head
 28.4793 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg merge</userinput>
 28.4794 +abort: Is a directory: /tmp/issue29vhrzWD/issue29/b
 28.4795 +</screen>
 28.4796 +<!-- END issue29.go -->
 28.4797 +
 28.4798 +
 28.4799 +    </sect2>
 28.4800 +  </sect1>
 28.4801 +
 28.4802 +  <sect1>
 28.4803 +    <title>Récupération d'erreurs</title>
 28.4804 +
 28.4805 +    <para id="x_1e2">Mercurial possède certaines commandes utiles qui vont
 28.4806 +      vous aider à récupérer de certaines erreurs communes.</para>
 28.4807 +
 28.4808 +    <para id="x_1e3">La commande <command role="hg-cmd" moreinfo="none">hg revert</command>
 28.4809 +      vous permet d'annuler les changements que vous avez faits dans votre
 28.4810 +      répertoire de travail. Par exemple, si vous faites un <command role="hg-cmd" moreinfo="none">hg add</command> sur un fichier par accident, exécutez
 28.4811 +      juste <command role="hg-cmd" moreinfo="none">hg	revert</command> avec le nom du fichier
 28.4812 +      que vous avez ajouté et tandis que le fichier ne sera touché d'une
 28.4813 +      quelconque manière, il ne sera plus suivi comme ajouté par Mercurial.
 28.4814 +      Vous pouvez aussi utiliser la commande <command role="hg-cmd" moreinfo="none">hg
 28.4815 +        revert</command> pour vous débarrasser de modifications erronés
 28.4816 +      apportées à un fichier.</para>
 28.4817 +
 28.4818 +    <para id="x_1e4">Il est utile de se souvenir que la commande <command role="hg-cmd" moreinfo="none">hg revert</command> est utile pour les modifications
 28.4819 +      qui n'ont pas encore été committées. Une fois que vous avez committé un
 28.4820 +      changement, si vous décidez qu'il s'agissait d'une erreur, vous pouvez
 28.4821 +      toujours faire quelque chose à ce sujet, bien que vos options soient
 28.4822 +      un peu plus limitées.</para>
 28.4823 +
 28.4824 +    <para id="x_1e5">Pour plus d'informations au sujet de la commande
 28.4825 +      <command role="hg-cmd" moreinfo="none">hg revert</command>, et des détails sur comment
 28.4826 +      traiter les modifications que vous avez déjà committées, référez vous à
 28.4827 +      <xref linkend="chap:undo"/>.</para>
 28.4828 +  </sect1>
 28.4829 +
 28.4830 +  <sect1>
 28.4831 +    <title>Traiter avec les fusions (merge) malicieuses</title>
 28.4832 +
 28.4833 +    <para id="x_687">Dans des projets compliqués ou conséquents, il n'est pas
 28.4834 +      rare qu'une fusion (merge) de deux changesets finisse par une migraine.
 28.4835 +      Supposez qu'il y ait un gros fichier source qui ait été largement édité de
 28.4836 +      chaque coté de la fusion (merge) : ceci va inévitablement résulter en
 28.4837 +      conflits, dont certains peuvent prendre plusieurs essais pour s'en
 28.4838 +      sortir.</para>
 28.4839 +
 28.4840 +    <para id="x_688">Développons en un cas simple pour voir comment le gérer.
 28.4841 +      Nous allons commencer avec un dépôt contenant un fichier, et le
 28.4842 +      cloner deux fois.</para>
 28.4843 +
 28.4844 +    <!-- BEGIN ch04/resolve.init -->
 28.4845 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init conflict</userinput>
 28.4846 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd conflict</userinput>
 28.4847 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo first &gt; myfile.txt</userinput>
 28.4848 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg ci -A -m first</userinput>
 28.4849 +adding myfile.txt
 28.4850 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput>
 28.4851 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone conflict left</userinput>
 28.4852 +updating working directory
 28.4853 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 28.4854 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone conflict right</userinput>
 28.4855 +updating working directory
 28.4856 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 28.4857 +</screen>
 28.4858 +<!-- END ch04/resolve.init -->
 28.4859 +
 28.4860 +
 28.4861 +    <para id="x_689">Dans un des clones, nous allons modifier le fichier
 28.4862 +      d'une façon.</para>
 28.4863 +
 28.4864 +    <!-- BEGIN ch04/resolve.left -->
 28.4865 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd left</userinput>
 28.4866 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo left &gt;&gt; myfile.txt</userinput>
 28.4867 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg ci -m left</userinput>
 28.4868 +</screen>
 28.4869 +<!-- END ch04/resolve.left -->
 28.4870 +
 28.4871 +
 28.4872 +    <para id="x_68a">Dans un autre, nous allons modifier le fichier
 28.4873 +      différemment.</para>
 28.4874 +
 28.4875 +    <!-- BEGIN ch04/resolve.right -->
 28.4876 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ../right</userinput>
 28.4877 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo right &gt;&gt; myfile.txt</userinput>
 28.4878 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg ci -m right</userinput>
 28.4879 +</screen>
 28.4880 +<!-- END ch04/resolve.right -->
 28.4881 +
 28.4882 +
 28.4883 +    <para id="x_68b">Ensuite, nous allons récupérer (pull) chaque ensemble de
 28.4884 +      changement dans notre dépôt original.</para>
 28.4885 +
 28.4886 +    <!-- BEGIN ch04/resolve.pull -->
 28.4887 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ../conflict</userinput>
 28.4888 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull -u ../left</userinput>
 28.4889 +pulling from ../left
 28.4890 +searching for changes
 28.4891 +adding changesets
 28.4892 +adding manifests
 28.4893 +adding file changes
 28.4894 +added 1 changesets with 1 changes to 1 files
 28.4895 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 28.4896 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull -u ../right</userinput>
 28.4897 +pulling from ../right
 28.4898 +searching for changes
 28.4899 +adding changesets
 28.4900 +adding manifests
 28.4901 +adding file changes
 28.4902 +added 1 changesets with 1 changes to 1 files (+1 heads)
 28.4903 +not updating, since new heads added
 28.4904 +(run 'hg heads' to see heads, 'hg merge' to merge)
 28.4905 +</screen>
 28.4906 +<!-- END ch04/resolve.pull -->
 28.4907 +
 28.4908 +
 28.4909 +    <para id="x_68c">Nous nous attendons à ce que notre dépôt contienne deux
 28.4910 +      "heads".</para>
 28.4911 +
 28.4912 +    <!-- BEGIN ch04/resolve.heads -->
 28.4913 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg heads</userinput>
 28.4914 +changeset:   2:85f1afc84c33
 28.4915 +tag:         tip
 28.4916 +parent:      0:14a820f81f48
 28.4917 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.4918 +date:        Sun Aug 16 14:04:51 2009 +0000
 28.4919 +summary:     right
 28.4920 +
 28.4921 +changeset:   1:085ebbf44348
 28.4922 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.4923 +date:        Sun Aug 16 14:04:51 2009 +0000
 28.4924 +summary:     left
 28.4925 +
 28.4926 +</screen>
 28.4927 +<!-- END ch04/resolve.heads -->
 28.4928 +
 28.4929 +
 28.4930 +    <para id="x_68d">Normalement, si nous lançons <command role="hg-cmd" moreinfo="none">hg
 28.4931 +        merge</command> à ce point, il nous renverra vers une interface
 28.4932 +      utilisateur qui nous permettra de résoudre manuellement les éditions
 28.4933 +      conflictuelles sur le fichier <filename moreinfo="none">myfile.txt</filename>.
 28.4934 +      Cependant, pour simplifier ici les choses dans la présentation, nous
 28.4935 +      aimerions plutôt que la fusion (merge) échoue immédiatement. Voici une
 28.4936 +      façon de le faire.</para>
 28.4937 +
 28.4938 +    <!-- BEGIN ch04/resolve.export -->
 28.4939 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">export HGMERGE=false</userinput>
 28.4940 +</screen>
 28.4941 +<!-- END ch04/resolve.export -->
 28.4942 +
 28.4943 +
 28.4944 +    <para id="x_68e">Nous avons dit au processus de fusion de Mercurial
 28.4945 +      d'exécuter la commande <command moreinfo="none">false</command> (qui échoue
 28.4946 +      immédiatement, à la demande) s'il détecte une fusion (merge) qu'il ne
 28.4947 +      peut pas arranger automatiquement.</para>
 28.4948 +
 28.4949 +    <para id="x_68f">Si nous appelons maintenant <command role="hg-cmd" moreinfo="none">hg
 28.4950 +        merge</command>, il devrait échouer et reporter une erreur.</para>
 28.4951 +
 28.4952 +    <!-- BEGIN ch04/resolve.merge -->
 28.4953 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg merge</userinput>
 28.4954 +merging myfile.txt
 28.4955 +merging myfile.txt failed!
 28.4956 +0 files updated, 0 files merged, 0 files removed, 1 files unresolved
 28.4957 +use 'hg resolve' to retry unresolved file merges or 'hg up --clean' to abandon
 28.4958 +</screen>
 28.4959 +<!-- END ch04/resolve.merge -->
 28.4960 +
 28.4961 +
 28.4962 +    <para id="x_690">Même si nous ne remarquons pas qu'une fusion (merge) a
 28.4963 +      échoué, Mercurial nous empêchera de committer le résultat d'une fusion
 28.4964 +      ratée.</para>
 28.4965 +
 28.4966 +    <!-- BEGIN ch04/resolve.cifail -->
 28.4967 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Attempt to commit a failed merge'</userinput>
 28.4968 +abort: unresolved merge conflicts (see hg resolve)
 28.4969 +</screen>
 28.4970 +<!-- END ch04/resolve.cifail -->
 28.4971 +
 28.4972 +
 28.4973 +    <para id="x_691">Lorsque <command role="hg-cmd" moreinfo="none">hg commit</command>
 28.4974 +      échoue dans ce cas, il suggère que nous utilisons la commande peu
 28.4975 +      connue <command role="hg-cmd" moreinfo="none">hg resolve</command>.  Comme d'habitude,
 28.4976 +      <command role="hg-cmd" moreinfo="none">hg help resolve</command> affichera une aide
 28.4977 +      sommaire.</para>
 28.4978 +
 28.4979 +    <sect2>
 28.4980 +      <title>États de résolution des fichiers</title>
 28.4981 +      <!-- TODO Vérifier traduction : File resolution states -->
 28.4982 +
 28.4983 +      <para id="x_692">Lorsqu'une fusion intervient, la plupart des fichiers
 28.4984 +        vont, la plupart du temps, rester sans modification. Pour chaque
 28.4985 +        fichier sur lequel Mercurial doit faire quelque chose, il suit l'état
 28.4986 +        de celui-ci.</para>
 28.4987 +
 28.4988 +      <itemizedlist>
 28.4989 +        <listitem><para id="x_693">Un fichier
 28.4990 +            <quote><emphasis>resolved</emphasis></quote> a été fusionné
 28.4991 +            (merge) avec succès, que ce soit automatiquement par Mercurial ou
 28.4992 +            manuellement par une intervention humaine.</para></listitem>
 28.4993 +        <listitem><para id="x_694">Un fichier
 28.4994 +            <quote><emphasis>unresolved</emphasis></quote> n'a pas été
 28.4995 +            fusionné (merge) correctement et a besoin de plus
 28.4996 +            d'attention.</para>
 28.4997 +        </listitem>
 28.4998 +      </itemizedlist>
 28.4999 +
 28.5000 +      <para id="x_695">Si Mercurial voit un fichier
 28.5001 +        <emphasis>quelconque</emphasis> dans un état
 28.5002 +        <quote>unresolved</quote> après une fusion (merge), il considère que
 28.5003 +        la fusion (merge) a échoué. Heureusement, nous n'avons pas à
 28.5004 +        recommencer la procédure à partir du début.</para>
 28.5005 +
 28.5006 +      <para id="x_696">L'option <option role="hg-opt-resolve">--list</option>
 28.5007 +        ou <option role="hg-opt-resolve">-l</option> passée à <command role="hg-cmd" moreinfo="none">hg resolve</command> liste l'état de chaque fichier
 28.5008 +        fusionné (merge).</para>
 28.5009 +
 28.5010 +      <!-- BEGIN ch04/resolve.list -->
 28.5011 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg resolve -l</userinput>
 28.5012 +U myfile.txt
 28.5013 +</screen>
 28.5014 +<!-- END ch04/resolve.list -->
 28.5015 +
 28.5016 +
 28.5017 +      <para id="x_697">En sortie de <command role="hg-cmd" moreinfo="none">hg
 28.5018 +          resolve</command>, un fichier "resolved" est marqué avec un
 28.5019 +        <literal moreinfo="none">R</literal>, alors qu'un fichier "unresolved" est marqué
 28.5020 +        d'un <literal moreinfo="none">U</literal>.  S'il existe un fichier listé avec un
 28.5021 +        <literal moreinfo="none">U</literal>, nous savons qu'essayer de committer le résultat
 28.5022 +        de la fusion (merge) échouera.</para>
 28.5023 +    </sect2>
 28.5024 +
 28.5025 +    <sect2>
 28.5026 +      <title>Résoudre une fusion de fichier</title>
 28.5027 +
 28.5028 +      <para id="x_698">Nous avons plusieurs options pour changer l'état d'un
 28.5029 +        fichier de "unresolved" à "resolved". Le plus commun est de relancer
 28.5030 +        <command role="hg-cmd" moreinfo="none">hg resolve</command>. Si nous passons les noms
 28.5031 +        des fichiers individuels ou des répertoires, ceci retentera la fusion
 28.5032 +        de tous les fichiers présents à cet endroit. Nous pouvons aussi
 28.5033 +        passer l'option <option role="hg-opt-resolve">--all</option> ou
 28.5034 +        <option role="hg-opt-resolve">-a</option> qui tentera de fusionner
 28.5035 +        <emphasis>tous</emphasis> les fichiers "unresolved".</para>
 28.5036 +
 28.5037 +      <para id="x_699">Mercurial nous laisse aussi modifier la résolution
 28.5038 +        d'un fichier directement. Nous pouvons marquer un fichier "resolved"
 28.5039 +        en utilisant l'option <option role="hg-opt-resolve">--mark</option>,
 28.5040 +        ou "unresolved" en utilisant l'option <option role="hg-opt-resolve">--unmark</option>. Ceci nous autorise à
 28.5041 +        nettoyer une fusion particulièrement compliquée à la main, et de
 28.5042 +        garder un suivi de nos progrès avec chaque fichier pendant que nous
 28.5043 +        procédons.</para>
 28.5044 +    </sect2>
 28.5045 +  </sect1>
 28.5046 +
 28.5047 +  <sect1>
 28.5048 +    <title>Des "diffs" plus utiles</title>
 28.5049 +
 28.5050 +    <para id="x_6c7">La sortie par défaut de la commande <command role="hg-cmd" moreinfo="none">hg diff</command> est compatible rétrospectivement avec
 28.5051 +      la commande régulière <command moreinfo="none">diff</command>, mais ceci a quelques
 28.5052 +      inconvénients.</para>
 28.5053 +
 28.5054 +    <para id="x_6c8">Considérez le cas où nous utilisons <command role="hg-cmd" moreinfo="none">hg
 28.5055 +        rename</command> pour renommer un fichier.</para>
 28.5056 +
 28.5057 +    <!-- BEGIN ch04/diff.rename.basic -->
 28.5058 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg rename a b</userinput>
 28.5059 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg diff</userinput>
 28.5060 +diff -r f5deb7868663 a
 28.5061 +--- a/a	Sun Aug 16 14:04:49 2009 +0000
 28.5062 ++++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
 28.5063 +@@ -1,1 +0,0 @@
 28.5064 +-a
 28.5065 +diff -r f5deb7868663 b
 28.5066 +--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
 28.5067 ++++ b/b	Sun Aug 16 14:04:49 2009 +0000
 28.5068 +@@ -0,0 +1,1 @@
 28.5069 ++a
 28.5070 +</screen>
 28.5071 +<!-- END ch04/diff.rename.basic -->
 28.5072 +
 28.5073 +
 28.5074 +    <para id="x_6c9">La sortie de <command role="hg-cmd" moreinfo="none">hg diff</command>
 28.5075 +      ci-dessus cache le fait que nous avons simplement renommé un fichier.
 28.5076 +      La commande <command role="hg-cmd" moreinfo="none">hg diff</command> accepte l'option
 28.5077 +      <option>--git</option> ou <option>-g</option> pour utiliser un nouveau
 28.5078 +      format de diff qui montre ces informations sous une forme plus
 28.5079 +      expressive.</para>
 28.5080 +
 28.5081 +    <!-- BEGIN ch04/diff.rename.git -->
 28.5082 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg diff -g</userinput>
 28.5083 +diff --git a/a b/b
 28.5084 +rename from a
 28.5085 +rename to b
 28.5086 +</screen>
 28.5087 +<!-- END ch04/diff.rename.git -->
 28.5088 +
 28.5089 +
 28.5090 +    <para id="x_6ca">Cette option peut aussi aider avec le cas autrement
 28.5091 +      confus : un fichier qui apparaît comme étant modifié en accord avec
 28.5092 +      <command role="hg-cmd" moreinfo="none">hg status</command>, mais où <command role="hg-cmd" moreinfo="none">hg diff</command> n'affiche rien. Cette situation peut
 28.5093 +      survenir si nous changeons les permissions d'exécution du
 28.5094 +      fichier.</para>
 28.5095 +
 28.5096 +    <!-- BEGIN ch04/diff.chmod -->
 28.5097 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">chmod +x a</userinput>
 28.5098 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg st</userinput>
 28.5099 +M a
 28.5100 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg diff</userinput>
 28.5101 +</screen>
 28.5102 +<!-- END ch04/diff.chmod -->
 28.5103 +
 28.5104 +
 28.5105 +    <para id="x_6cb">La commande normale <command moreinfo="none">diff</command> ne fait pas
 28.5106 +      attention aux permissions des fichiers, ce qui explique pourquoi
 28.5107 +      <command role="hg-cmd" moreinfo="none">hg diff</command> n'affiche rien du tout par
 28.5108 +      défaut. Si nous lui passons l'option <option>-g</option>, ceci nous
 28.5109 +      informe de ce qu'il s'est vraiment passé.</para>
 28.5110 +
 28.5111 +    <!-- BEGIN ch04/diff.chmod.git -->
 28.5112 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg diff -g</userinput>
 28.5113 +diff --git a/a b/a
 28.5114 +old mode 100644
 28.5115 +new mode 100755
 28.5116 +</screen>
 28.5117 +<!-- END ch04/diff.chmod.git -->
 28.5118 +
 28.5119 +  </sect1>
 28.5120 +
 28.5121 +  <sect1>
 28.5122 +    <title>Quels fichiers suivre et lesquels éviter</title>
 28.5123 +
 28.5124 +    <para id="x_6cc">Les systèmes de gestion de révisions sont en général
 28.5125 +      meilleurs pour gérer les fichiers textes qui sont écrits par les
 28.5126 +      humains, comme le code source, où les fichiers ne changent pas
 28.5127 +      énormément d'une révision à l'autre. Certains systèmes de gestion de
 28.5128 +      révisions centralisés peuvent aussi traiter très convenablement les
 28.5129 +      fichiers binaires, tels que les images bitmap.</para>
 28.5130 +
 28.5131 +    <para id="x_6cd">Par exemple, une équipe de développement de jeux va
 28.5132 +      probablement gérer les deux types : ses codes source et tous ses binaires
 28.5133 +      (ex. données géométriques, textures, schémas de cartes) dans un système
 28.5134 +      de contrôle de révisions.</para>
 28.5135 +    <!-- Vérifier la traduction de map layouts que j'ai traduit par schémas
 28.5136 +    de cartes -->
 28.5137 +
 28.5138 +    <para id="x_6ce">Puisqu'il est d'habitude impossible de fusionner (merge)
 28.5139 +      deux modifications conflictuelles sur un fichier binaire, les systèmes
 28.5140 +      de version centralisés offrent souvent un mécanisme de verrou (lock) qui
 28.5141 +      permet à un utilisateur de dire <quote>Je suis la seule personne qui
 28.5142 +        peut éditer ce fichier</quote>.</para>
 28.5143 +
 28.5144 +    <para id="x_6cf">En comparaison avec un système centralisé, un système
 28.5145 +      décentralisé de gestion de révision change certains facteurs qui
 28.5146 +      guident les décisions sur quels fichiers gérer et comment.</para>
 28.5147 +
 28.5148 +    <para id="x_6d0">Par exemple, un système distribué de gestion de révisions
 28.5149 +      ne peut pas, par sa nature, offrir un système de véroux (lock) sur les
 28.5150 +      fichiers. Il n'y a donc pas de mécanisme inclus pour empêcher deux
 28.5151 +      personnes de faire des modifications conflictuelles sur un fichier
 28.5152 +      binaire. Si vous avez une équipe où plusieurs personnes peuvent souvent
 28.5153 +      éditer un fichier binaire, cela ne serait pas une très bonne idée
 28.5154 +      d'utiliser Mercurial —ou tout autre système distribué de gestion
 28.5155 +      de révisions—pour gérer ces fichiers.</para>
 28.5156 +
 28.5157 +    <para id="x_6d1">Lorsque vous sauvegardez les modifications sur un
 28.5158 +      fichier, Mercurial ne sauvegarde d'habitude que les différences entre
 28.5159 +      la version précédente et la version actuelle d'un fichier. Pour la
 28.5160 +      plupart des fichiers texte, ceci est très efficace. Cependant, certains
 28.5161 +      fichiers (en particulier les fichiers binaires) sont construits d'une
 28.5162 +      façon que même un petit changement sur un contenu logique résulte sur
 28.5163 +      un changement de la plupart des octets du fichier. Par exemple, les
 28.5164 +      fichiers compressés sont particulièrement sujets à ce comportement. Si
 28.5165 +      les différences entre deux versions successives d'un fichier sont
 28.5166 +      toujours très grandes, Mercurial ne sera pas capable de sauvegarder
 28.5167 +      l'historique des révisions sur le fichier très efficacement. Ceci peut
 28.5168 +      affecter aussi bien les besoins pour la sauvegarde locale que le temps
 28.5169 +      nécessaire à cloner le dépôt.</para>
 28.5170 +
 28.5171 +    <para id="x_6d2">Pour avoir une idée de comment ceci pourrait vous
 28.5172 +      affecter en pratique, supposez que nous voulions que Mercurial gère des
 28.5173 +      documents OpenOffice. OpenOffice sauvegarde les documents sur le disque
 28.5174 +      comme des fichiers compressés zip. Même le fait d'éditer ces fichiers
 28.5175 +      d'une seule lettre, changera les bits de la quasi totalité du fichier
 28.5176 +      lorsque vous le sauvegarderez. Maintenant, supposez que ce fichier
 28.5177 +      fasse une taille de 2Mo. Puisque la plupart du fichier change à chaque
 28.5178 +      fois que vous sauvegardez, Mercurial aura à sauvegarder tous les 2Mo du
 28.5179 +      fichier à chaque commit, alors que de votre point de vue, il n'y a
 28.5180 +      que peu de mots qui changent à chaque fois. Un seul fichier
 28.5181 +      souvent édité qui n'est pas bien traité par les hypothèses que Mercurial
 28.5182 +      fait sur les sauvegardes peut facilement avoir un effet colossal sur la
 28.5183 +      taille du dépôt.</para>
 28.5184 +
 28.5185 +    <para id="x_6d3">Même pire, si vous et quelqu'un d'autre éditez le même
 28.5186 +      document OpenOffice sur lequel vous travaillez, il n'y a pas de façon
 28.5187 +      utile pour fusionner votre travail. En fait, il n'y a pas de moyen
 28.5188 +      utile de montrer que les différences sont faites à partir de votre
 28.5189 +      vision des modifications.</para>
 28.5190 +
 28.5191 +    <para id="x_6d4">Il y a ainsi quelques recommandations claires sur les
 28.5192 +      types de fichiers spécifiques avec lesquels faire très
 28.5193 +      attention.</para>
 28.5194 +
 28.5195 +    <itemizedlist>
 28.5196 +      <listitem><para id="x_6d5">Les fichier qui sont très gros et
 28.5197 +          incompressibles, comme les images ISO de CD-ROM, sont, par
 28.5198 +          construction très gros et les cloner à travers un réseau sera très
 28.5199 +          long.</para></listitem>
 28.5200 +     <!-- TODO : Trouver une meilleure traduction pour : ISO CD-ROM images, will by
 28.5201 +     virtue of sheer size make clones over a network very slow. -->
 28.5202 +      <listitem><para id="x_6d6">Les fichiers qui changent beaucoup d'une
 28.5203 +          révision à l'autre peuvent être très chers à sauvegarder si vous
 28.5204 +          les éditez fréquemment, de même que les conflits entre deux éditions
 28.5205 +          concurrentes peuvent être difficiles à résoudre.</para>
 28.5206 +      </listitem>
 28.5207 +    </itemizedlist>
 28.5208 +  </sect1>
 28.5209 +
 28.5210 +  <sect1>
 28.5211 +    <title>Sauvegardes et miroirs</title>
 28.5212 +
 28.5213 +    <para id="x_6d7">Puisque Mercurial maintient une copie complète de
 28.5214 +      l'historique de chaque clone, toute personne qui utilise Mercurial pour
 28.5215 +      collaborer à un projet peut potentiellement agir comme une source de
 28.5216 +      sauvegarde si une catastrophe survenait. Si un dépôt central devient
 28.5217 +      indisponible, vous pouvez construire un remplaçant en clonant une copie
 28.5218 +      du dépôt à partir d'un des contributeurs en récupérant (pull) tous les
 28.5219 +      changements qui n'auraient pas été vus par les autres.</para>
 28.5220 +
 28.5221 +    <para id="x_6d8">Il est simple d'utiliser Mercurial pour construire des
 28.5222 +      serveurs hors site de sauvegarde et des miroirs distants. Initiez une
 28.5223 +      tâche périodique (ex. via la commande <command moreinfo="none">cron</command>) sur un
 28.5224 +      serveur distant pour récupérer (pull) les changements de votre dépôt
 28.5225 +      distant chaque heure. Ceci sera difficile seulement dans le cas
 28.5226 +      improbable où le nombre des dépôts maîtres que vous maintenez change
 28.5227 +      souvent, auquel cas vous aurez besoin de faire un peu de scripting pour
 28.5228 +      rafraichir la liste des dépôt à sauvegarder.</para>
 28.5229 +
 28.5230 +    <para id="x_6d9">Si vous exécutez des sauvegardes traditionnelles de
 28.5231 +      votre dépôt maître sur bande ou disque, et que vous voulez sauvegarder
 28.5232 +      un dépôt nommé <filename moreinfo="none">myrepo</filename>, utilisez la commande
 28.5233 +      <command moreinfo="none">hg clone -U myrepo myrepo.bak</command> pour créer un clone de
 28.5234 +      <filename moreinfo="none">myrepo</filename> avant de commencer vos backups.
 28.5235 +      L'option <option>-U</option> ne crée pas de répertoire de travail après
 28.5236 +      que le clone soit accompli, puisque ceci serait superflu et ferait que
 28.5237 +      la sauvegarde prenne plus de temps.</para>
 28.5238 +
 28.5239 +    <para id="x_6da">Si vous voulez ensuite sauvegarder
 28.5240 +      <filename moreinfo="none">myrepo.bak</filename> au lieu de <filename moreinfo="none">myrepo</filename>,
 28.5241 +      vous aurez la garantie d'avoir une image (snapshot) consistante de
 28.5242 +      votre dépôt sur lequel un développeur insomniaque n'enverra (push) pas de
 28.5243 +      changements en milieu de sauvegarde.</para>
 28.5244 +  </sect1>
 28.5245 +</chapter>
 28.5246 +
 28.5247 +<!--
 28.5248 +local variables: 
 28.5249 +sgml-parent-document: ("00book.xml" "book" "chapter")
 28.5250 +end:
 28.5251 +-->
 28.5252 +
 28.5253 +  <!-- BEGIN ch06 -->
 28.5254 +  <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
 28.5255 +
 28.5256 +<chapter id="cha:collab">
 28.5257 +  <?dbhtml filename="collaborating-with-other-people.html"?>
 28.5258 +  <title>Collaborating with other people</title>
 28.5259 +
 28.5260 +  <para id="x_44a">As a completely decentralised tool, Mercurial doesn't impose
 28.5261 +    any policy on how people ought to work with each other.  However,
 28.5262 +    if you're new to distributed revision control, it helps to have
 28.5263 +    some tools and examples in mind when you're thinking about
 28.5264 +    possible workflow models.</para>
 28.5265 +
 28.5266 +  <sect1>
 28.5267 +    <title>Mercurial's web interface</title>
 28.5268 +
 28.5269 +    <para id="x_44b">Mercurial has a powerful web interface that provides several
 28.5270 +      useful capabilities.</para>
 28.5271 +
 28.5272 +    <para id="x_44c">For interactive use, the web interface lets you browse a
 28.5273 +      single repository or a collection of repositories.  You can view
 28.5274 +      the history of a repository, examine each change (comments and
 28.5275 +      diffs), and view the contents of each directory and file.  You
 28.5276 +      can even get a view of history that gives a graphical view of
 28.5277 +      the relationships between individual changes and merges.</para>
 28.5278 +
 28.5279 +    <para id="x_44d">Also for human consumption, the web interface provides
 28.5280 +      Atom and RSS feeds of the changes in a repository.  This lets you
 28.5281 +      <quote>subscribe</quote> to a repository using your favorite
 28.5282 +      feed reader, and be automatically notified of activity in that
 28.5283 +      repository as soon as it happens.  I find this capability much
 28.5284 +      more convenient than the model of subscribing to a mailing list
 28.5285 +      to which notifications are sent, as it requires no additional
 28.5286 +      configuration on the part of whoever is serving the
 28.5287 +      repository.</para>
 28.5288 +
 28.5289 +    <para id="x_44e">The web interface also lets remote users clone a repository,
 28.5290 +      pull changes from it, and (when the server is configured to
 28.5291 +      permit it) push changes back to it.  Mercurial's HTTP tunneling
 28.5292 +      protocol aggressively compresses data, so that it works
 28.5293 +      efficiently even over low-bandwidth network connections.</para>
 28.5294 +
 28.5295 +    <para id="x_44f">The easiest way to get started with the web interface is to
 28.5296 +      use your web browser to visit an existing repository, such as
 28.5297 +      the master Mercurial repository at <ulink url="http://www.selenic.com/repo/hg">http://www.selenic.com/repo/hg</ulink>.</para>
 28.5298 +
 28.5299 +    <para id="x_450">If you're interested in providing a web interface
 28.5300 +      to your own repositories, there are several good ways to do
 28.5301 +      this.</para>
 28.5302 +
 28.5303 +    <para id="x_69d">The easiest and fastest way to get started in an informal
 28.5304 +      environment is to use the <command role="hg-cmd" moreinfo="none">hg
 28.5305 +	serve</command> command, which is best suited to short-term
 28.5306 +      <quote>lightweight</quote> serving.  See <xref linkend="sec:collab:serve"/> below for details of how to use
 28.5307 +      this command.</para>
 28.5308 +
 28.5309 +    <para id="x_69e">For longer-lived repositories that you'd like to
 28.5310 +      have permanently available, there are several public hosting
 28.5311 +      services available.  Some are free to open source projects,
 28.5312 +      while others offer paid commercial hosting.  An up-to-date list
 28.5313 +      is available at <ulink url="http://www.selenic.com/mercurial/wiki/index.cgi/MercurialHosting">http://www.selenic.com/mercurial/wiki/index.cgi/MercurialHosting</ulink>.</para>
 28.5314 +
 28.5315 +    <para id="x_6a0">If you would prefer to host your own repositories, Mercurial
 28.5316 +      has built-in support for several popular hosting technologies,
 28.5317 +      most notably CGI (Common Gateway Interface), and WSGI (Web
 28.5318 +      Services Gateway Interface).  See <xref linkend="sec:collab:cgi"/> for details of CGI and WSGI
 28.5319 +      configuration.</para>
 28.5320 +  </sect1>
 28.5321 +
 28.5322 +  <sect1>
 28.5323 +    <title>Collaboration models</title>
 28.5324 +
 28.5325 +    <para id="x_451">With a suitably flexible tool, making decisions about
 28.5326 +      workflow is much more of a social engineering challenge than a
 28.5327 +      technical one. Mercurial imposes few limitations on how you can
 28.5328 +      structure the flow of work in a project, so it's up to you and
 28.5329 +      your group to set up and live with a model that matches your own
 28.5330 +      particular needs.</para>
 28.5331 +
 28.5332 +    <sect2>
 28.5333 +      <title>Factors to keep in mind</title>
 28.5334 +
 28.5335 +      <para id="x_452">The most important aspect of any model that you must keep
 28.5336 +	in mind is how well it matches the needs and capabilities of
 28.5337 +	the people who will be using it.  This might seem
 28.5338 +	self-evident; even so, you still can't afford to forget it for
 28.5339 +	a moment.</para>
 28.5340 +
 28.5341 +      <para id="x_453">I once put together a workflow model that seemed to make
 28.5342 +	perfect sense to me, but that caused a considerable amount of
 28.5343 +	consternation and strife within my development team.  In spite
 28.5344 +	of my attempts to explain why we needed a complex set of
 28.5345 +	branches, and how changes ought to flow between them, a few
 28.5346 +	team members revolted.  Even though they were smart people,
 28.5347 +	they didn't want to pay attention to the constraints we were
 28.5348 +	operating under, or face the consequences of those constraints
 28.5349 +	in the details of the model that I was advocating.</para>
 28.5350 +
 28.5351 +      <para id="x_454">Don't sweep foreseeable social or technical problems under
 28.5352 +	the rug. Whatever scheme you put into effect, you should plan
 28.5353 +	for mistakes and problem scenarios.  Consider adding automated
 28.5354 +	machinery to prevent, or quickly recover from, trouble that
 28.5355 +	you can anticipate.  As an example, if you intend to have a
 28.5356 +	branch with not-for-release changes in it, you'd do well to
 28.5357 +	think early about the possibility that someone might
 28.5358 +	accidentally merge those changes into a release branch.  You
 28.5359 +	could avoid this particular problem by writing a hook that
 28.5360 +	prevents changes from being merged from an inappropriate
 28.5361 +	branch.</para>
 28.5362 +    </sect2>
 28.5363 +
 28.5364 +    <sect2>
 28.5365 +      <title>Informal anarchy</title>
 28.5366 +
 28.5367 +      <para id="x_455">I wouldn't suggest an <quote>anything goes</quote>
 28.5368 +	approach as something sustainable, but it's a model that's
 28.5369 +	easy to grasp, and it works perfectly well in a few unusual
 28.5370 +	situations.</para>
 28.5371 +
 28.5372 +      <para id="x_456">As one example, many projects have a loose-knit group of
 28.5373 +	collaborators who rarely physically meet each other.  Some
 28.5374 +	groups like to overcome the isolation of working at a distance
 28.5375 +	by organizing occasional <quote>sprints</quote>.  In a sprint,
 28.5376 +	a number of people get together in a single location (a
 28.5377 +	company's conference room, a hotel meeting room, that kind of
 28.5378 +	place) and spend several days more or less locked in there,
 28.5379 +	hacking intensely on a handful of projects.</para>
 28.5380 +
 28.5381 +      <para id="x_457">A sprint or a hacking session in a coffee shop are the perfect places to use the
 28.5382 +	<command role="hg-cmd" moreinfo="none">hg serve</command> command, since
 28.5383 +	<command role="hg-cmd" moreinfo="none">hg serve</command> does not require any
 28.5384 +	fancy server infrastructure.  You can get started with
 28.5385 +	<command role="hg-cmd" moreinfo="none">hg serve</command> in moments, by
 28.5386 +	reading <xref linkend="sec:collab:serve"/> below.  Then simply
 28.5387 +	tell the person next to you that you're running a server, send
 28.5388 +	the URL to them in an instant message, and you immediately
 28.5389 +	have a quick-turnaround way to work together.  They can type
 28.5390 +	your URL into their web browser and quickly review your
 28.5391 +	changes; or they can pull a bugfix from you and verify it; or
 28.5392 +	they can clone a branch containing a new feature and try it
 28.5393 +	out.</para>
 28.5394 +
 28.5395 +      <para id="x_458">The charm, and the problem, with doing things
 28.5396 +	in an ad hoc fashion like this is that only people who know
 28.5397 +	about your changes, and where they are, can see them.  Such an
 28.5398 +	informal approach simply doesn't scale beyond a handful
 28.5399 +	people, because each individual needs to know about
 28.5400 +	<emphasis>n</emphasis> different repositories to pull
 28.5401 +	from.</para>
 28.5402 +    </sect2>
 28.5403 +
 28.5404 +    <sect2>
 28.5405 +      <title>A single central repository</title>
 28.5406 +
 28.5407 +      <para id="x_459">For smaller projects migrating from a centralised revision
 28.5408 +	control tool, perhaps the easiest way to get started is to
 28.5409 +	have changes flow through a single shared central repository.
 28.5410 +	This is also the most common <quote>building block</quote> for
 28.5411 +	more ambitious workflow schemes.</para>
 28.5412 +
 28.5413 +      <para id="x_45a">Contributors start by cloning a copy of this repository.
 28.5414 +	They can pull changes from it whenever they need to, and some
 28.5415 +	(perhaps all) developers have permission to push a change back
 28.5416 +	when they're ready for other people to see it.</para>
 28.5417 +
 28.5418 +      <para id="x_45b">Under this model, it can still often make sense for people
 28.5419 +	to pull changes directly from each other, without going
 28.5420 +	through the central repository.  Consider a case in which I
 28.5421 +	have a tentative bug fix, but I am worried that if I were to
 28.5422 +	publish it to the central repository, it might subsequently
 28.5423 +	break everyone else's trees as they pull it.  To reduce the
 28.5424 +	potential for damage, I can ask you to clone my repository
 28.5425 +	into a temporary repository of your own and test it.  This
 28.5426 +	lets us put off publishing the potentially unsafe change until
 28.5427 +	it has had a little testing.</para>
 28.5428 +
 28.5429 +      <para id="x_45c">If a team is hosting its own repository in this
 28.5430 +	kind of scenario, people will usually use the
 28.5431 +	<command moreinfo="none">ssh</command> protocol to securely push changes to
 28.5432 +	the central repository, as documented in <xref linkend="sec:collab:ssh"/>.  It's also usual to publish a
 28.5433 +	read-only copy of the repository over HTTP, as in
 28.5434 +	<xref linkend="sec:collab:cgi"/>. Publishing over HTTP
 28.5435 +	satisfies the needs of people who don't have push access, and
 28.5436 +	those who want to use web browsers to browse the repository's
 28.5437 +	history.</para>
 28.5438 +    </sect2>
 28.5439 +
 28.5440 +    <sect2>
 28.5441 +      <title>A hosted central repository</title>
 28.5442 +
 28.5443 +      <para id="x_6a1">A wonderful thing about public hosting services like
 28.5444 +	<ulink url="http://bitbucket.org/">Bitbucket</ulink> is that
 28.5445 +	not only do they handle the fiddly server configuration
 28.5446 +	details, such as user accounts, authentication, and secure
 28.5447 +	wire protocols, they provide additional infrastructure to make
 28.5448 +	this model work well.</para>
 28.5449 +
 28.5450 +      <para id="x_6a2">For instance, a well-engineered hosting service will let
 28.5451 +	people clone their own copies of a repository with a single
 28.5452 +	click.  This lets people work in separate spaces and share
 28.5453 +	their changes when they're ready.</para>
 28.5454 +
 28.5455 +      <para id="x_6a3">In addition, a good hosting service will let people
 28.5456 +	communicate with each other, for instance to say <quote>there
 28.5457 +	  are changes ready for you to review in this
 28.5458 +	  tree</quote>.</para>
 28.5459 +    </sect2>
 28.5460 +
 28.5461 +    <sect2>
 28.5462 +      <title>Working with multiple branches</title>
 28.5463 +
 28.5464 +      <para id="x_45d">Projects of any significant size naturally tend to make
 28.5465 +	progress on several fronts simultaneously.  In the case of
 28.5466 +	software, it's common for a project to go through periodic
 28.5467 +	official releases.  A release might then go into
 28.5468 +	<quote>maintenance mode</quote> for a while after its first
 28.5469 +	publication; maintenance releases tend to contain only bug
 28.5470 +	fixes, not new features.  In parallel with these maintenance
 28.5471 +	releases, one or more future releases may be under
 28.5472 +	development.  People normally use the word
 28.5473 +	<quote>branch</quote> to refer to one of these many slightly
 28.5474 +	different directions in which development is
 28.5475 +	proceeding.</para>
 28.5476 +
 28.5477 +      <para id="x_45e">Mercurial is particularly well suited to managing a number
 28.5478 +	of simultaneous, but not identical, branches.  Each
 28.5479 +	<quote>development direction</quote> can live in its own
 28.5480 +	central repository, and you can merge changes from one to
 28.5481 +	another as the need arises.  Because repositories are
 28.5482 +	independent of each other, unstable changes in a development
 28.5483 +	branch will never affect a stable branch unless someone
 28.5484 +	explicitly merges those changes into the stable branch.</para>
 28.5485 +
 28.5486 +      <para id="x_45f">Here's an example of how this can work in practice.  Let's
 28.5487 +	say you have one <quote>main branch</quote> on a central
 28.5488 +	server.</para>
 28.5489 +
 28.5490 +      <!-- BEGIN branching.init -->
 28.5491 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init main</userinput>
 28.5492 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd main</userinput>
 28.5493 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'This is a boring feature.' &gt; myfile</userinput>
 28.5494 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'We have reached an important milestone!'</userinput>
 28.5495 +adding myfile
 28.5496 +</screen>
 28.5497 +<!-- END branching.init -->
 28.5498 +
 28.5499 +
 28.5500 +      <para id="x_460">People clone it, make changes locally, test them, and push
 28.5501 +	them back.</para>
 28.5502 +
 28.5503 +      <para id="x_461">Once the main branch reaches a release milestone, you can
 28.5504 +	use the <command role="hg-cmd" moreinfo="none">hg tag</command> command to
 28.5505 +	give a permanent name to the milestone revision.</para>
 28.5506 +
 28.5507 +	<!-- BEGIN branching.tag -->
 28.5508 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tag v1.0</userinput>
 28.5509 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput>
 28.5510 +changeset:   1:5e447fdaf941
 28.5511 +tag:         tip
 28.5512 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.5513 +date:        Sun Aug 16 14:04:47 2009 +0000
 28.5514 +summary:     Added tag v1.0 for changeset 6412b791fd06
 28.5515 +
 28.5516 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tags</userinput>
 28.5517 +tip                                1:5e447fdaf941
 28.5518 +v1.0                               0:6412b791fd06
 28.5519 +</screen>
 28.5520 +<!-- END branching.tag -->
 28.5521 +
 28.5522 +
 28.5523 +      <para id="x_462">Let's say some ongoing
 28.5524 +	development occurs on the main branch.</para>
 28.5525 +
 28.5526 +      <!-- BEGIN branching.main -->
 28.5527 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ../main</userinput>
 28.5528 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'This is exciting and new!' &gt;&gt; myfile</userinput>
 28.5529 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Add a new feature'</userinput>
 28.5530 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat myfile</userinput>
 28.5531 +This is a boring feature.
 28.5532 +This is exciting and new!
 28.5533 +</screen>
 28.5534 +<!-- END branching.main -->
 28.5535 +
 28.5536 +
 28.5537 +      <para id="x_463">Using the tag that was recorded at the milestone, people
 28.5538 +	who clone that repository at any time in the future can use
 28.5539 +	<command role="hg-cmd" moreinfo="none">hg update</command> to get a copy of
 28.5540 +	the working directory exactly as it was when that tagged
 28.5541 +	revision was committed.</para>
 28.5542 +
 28.5543 +      <!-- BEGIN branching.update -->
 28.5544 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput>
 28.5545 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone -U main main-old</userinput>
 28.5546 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd main-old</userinput>
 28.5547 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg update v1.0</userinput>
 28.5548 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 28.5549 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat myfile</userinput>
 28.5550 +This is a boring feature.
 28.5551 +</screen>
 28.5552 +<!-- END branching.update -->
 28.5553 +
 28.5554 +
 28.5555 +      <para id="x_464">In addition, immediately after the main branch is tagged,
 28.5556 +	we can then clone the main branch on the server to a new
 28.5557 +	<quote>stable</quote> branch, also on the server.</para>
 28.5558 +
 28.5559 +      <!-- BEGIN branching.clone -->
 28.5560 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput>
 28.5561 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone -rv1.0 main stable</userinput>
 28.5562 +requesting all changes
 28.5563 +adding changesets
 28.5564 +adding manifests
 28.5565 +adding file changes
 28.5566 +added 1 changesets with 1 changes to 1 files
 28.5567 +updating working directory
 28.5568 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 28.5569 +</screen>
 28.5570 +<!-- END branching.clone -->
 28.5571 +
 28.5572 +
 28.5573 +      <para id="x_465">If we need to make a change to the stable
 28.5574 +	branch, we can then clone <emphasis>that</emphasis>
 28.5575 +	repository, make our changes, commit, and push our changes
 28.5576 +	back there.</para>
 28.5577 +
 28.5578 +      <!-- BEGIN branching.stable -->
 28.5579 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone stable stable-fix</userinput>
 28.5580 +updating working directory
 28.5581 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 28.5582 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd stable-fix</userinput>
 28.5583 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'This is a fix to a boring feature.' &gt; myfile</userinput>
 28.5584 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Fix a bug'</userinput>
 28.5585 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg push</userinput>
 28.5586 +pushing to /tmp/branchingPsTziR/stable
 28.5587 +searching for changes
 28.5588 +adding changesets
 28.5589 +adding manifests
 28.5590 +adding file changes
 28.5591 +added 1 changesets with 1 changes to 1 files
 28.5592 +</screen>
 28.5593 +<!-- END branching.stable -->
 28.5594 +
 28.5595 +
 28.5596 +      <para id="x_466">Because Mercurial repositories are independent, and
 28.5597 +	Mercurial doesn't move changes around automatically, the
 28.5598 +	stable and main branches are <emphasis>isolated</emphasis>
 28.5599 +	from each other.  The changes that we made on the main branch
 28.5600 +	don't <quote>leak</quote> to the stable branch, and vice
 28.5601 +	versa.</para>
 28.5602 +
 28.5603 +      <para id="x_467">We'll often want all of our bugfixes on the stable
 28.5604 +	branch to show up on the main branch, too.  Rather than
 28.5605 +	rewrite a bugfix on the main branch, we can simply pull and
 28.5606 +	merge changes from the stable to the main branch, and
 28.5607 +	Mercurial will bring those bugfixes in for us.</para>
 28.5608 +
 28.5609 +      <!-- BEGIN branching.merge -->
 28.5610 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ../main</userinput>
 28.5611 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull ../stable</userinput>
 28.5612 +pulling from ../stable
 28.5613 +searching for changes
 28.5614 +adding changesets
 28.5615 +adding manifests
 28.5616 +adding file changes
 28.5617 +added 1 changesets with 1 changes to 1 files (+1 heads)
 28.5618 +(run 'hg heads' to see heads, 'hg merge' to merge)
 28.5619 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg merge</userinput>
 28.5620 +merging myfile
 28.5621 +0 files updated, 1 files merged, 0 files removed, 0 files unresolved
 28.5622 +(branch merge, don't forget to commit)
 28.5623 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Bring in bugfix from stable branch'</userinput>
 28.5624 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat myfile</userinput>
 28.5625 +This is a fix to a boring feature.
 28.5626 +This is exciting and new!
 28.5627 +</screen>
 28.5628 +<!-- END branching.merge -->
 28.5629 +
 28.5630 +
 28.5631 +      <para id="x_468">The main branch will still contain changes that
 28.5632 +	are not on the stable branch, but it will also contain all of
 28.5633 +	the bugfixes from the stable branch.  The stable branch
 28.5634 +	remains unaffected by these changes, since changes are only
 28.5635 +	flowing from the stable to the main branch, and not the other
 28.5636 +	way.</para>
 28.5637 +    </sect2>
 28.5638 +
 28.5639 +    <sect2>
 28.5640 +      <title>Feature branches</title>
 28.5641 +
 28.5642 +      <para id="x_469">For larger projects, an effective way to manage change is
 28.5643 +	to break up a team into smaller groups.  Each group has a
 28.5644 +	shared branch of its own, cloned from a single
 28.5645 +	<quote>master</quote> branch used by the entire project.
 28.5646 +	People working on an individual branch are typically quite
 28.5647 +	isolated from developments on other branches.</para>
 28.5648 +
 28.5649 +      <figure id="fig:collab:feature-branches" float="0">
 28.5650 +	<title>Feature branches</title>
 28.5651 +	<mediaobject>
 28.5652 +	  <imageobject><imagedata width="100%" fileref="figs/feature-branches.png"/></imageobject>
 28.5653 +	  <textobject><phrase>XXX add text</phrase></textobject>
 28.5654 +	</mediaobject>
 28.5655 +      </figure>
 28.5656 +
 28.5657 +      <para id="x_46b">When a particular feature is deemed to be in suitable
 28.5658 +	shape, someone on that feature team pulls and merges from the
 28.5659 +	master branch into the feature branch, then pushes back up to
 28.5660 +	the master branch.</para>
 28.5661 +    </sect2>
 28.5662 +
 28.5663 +    <sect2>
 28.5664 +      <title>The release train</title>
 28.5665 +
 28.5666 +      <para id="x_46c">Some projects are organized on a <quote>train</quote>
 28.5667 +	basis: a release is scheduled to happen every few months, and
 28.5668 +	whatever features are ready when the <quote>train</quote> is
 28.5669 +	ready to leave are allowed in.</para>
 28.5670 +
 28.5671 +      <para id="x_46d">This model resembles working with feature branches.  The
 28.5672 +	difference is that when a feature branch misses a train,
 28.5673 +	someone on the feature team pulls and merges the changes that
 28.5674 +	went out on that train release into the feature branch, and
 28.5675 +	the team continues its work on top of that release so that
 28.5676 +	their feature can make the next release.</para>
 28.5677 +    </sect2>
 28.5678 +
 28.5679 +    <sect2>
 28.5680 +      <title>The Linux kernel model</title>
 28.5681 +
 28.5682 +      <para id="x_46e">The development of the Linux kernel has a shallow
 28.5683 +	hierarchical structure, surrounded by a cloud of apparent
 28.5684 +	chaos.  Because most Linux developers use
 28.5685 +	<command moreinfo="none">git</command>, a distributed revision control tool
 28.5686 +	with capabilities similar to Mercurial, it's useful to
 28.5687 +	describe the way work flows in that environment; if you like
 28.5688 +	the ideas, the approach translates well across tools.</para>
 28.5689 +
 28.5690 +      <para id="x_46f">At the center of the community sits Linus Torvalds, the
 28.5691 +	creator of Linux.  He publishes a single source repository
 28.5692 +	that is considered the <quote>authoritative</quote> current
 28.5693 +	tree by the entire developer community. Anyone can clone
 28.5694 +	Linus's tree, but he is very choosy about whose trees he pulls
 28.5695 +	from.</para>
 28.5696 +
 28.5697 +      <para id="x_470">Linus has a number of <quote>trusted lieutenants</quote>.
 28.5698 +	As a general rule, he pulls whatever changes they publish, in
 28.5699 +	most cases without even reviewing those changes.  Some of
 28.5700 +	those lieutenants are generally agreed to be
 28.5701 +	<quote>maintainers</quote>, responsible for specific
 28.5702 +	subsystems within the kernel.  If a random kernel hacker wants
 28.5703 +	to make a change to a subsystem that they want to end up in
 28.5704 +	Linus's tree, they must find out who the subsystem's
 28.5705 +	maintainer is, and ask that maintainer to take their change.
 28.5706 +	If the maintainer reviews their changes and agrees to take
 28.5707 +	them, they'll pass them along to Linus in due course.</para>
 28.5708 +
 28.5709 +      <para id="x_471">Individual lieutenants have their own approaches to
 28.5710 +	reviewing, accepting, and publishing changes; and for deciding
 28.5711 +	when to feed them to Linus.  In addition, there are several
 28.5712 +	well known branches that people use for different purposes.
 28.5713 +	For example, a few people maintain <quote>stable</quote>
 28.5714 +	repositories of older versions of the kernel, to which they
 28.5715 +	apply critical fixes as needed.  Some maintainers publish
 28.5716 +	multiple trees: one for experimental changes; one for changes
 28.5717 +	that they are about to feed upstream; and so on.  Others just
 28.5718 +	publish a single tree.</para>
 28.5719 +
 28.5720 +      <para id="x_472">This model has two notable features.  The first is that
 28.5721 +	it's <quote>pull only</quote>.  You have to ask, convince, or
 28.5722 +	beg another developer to take a change from you, because there
 28.5723 +	are almost no trees to which more than one person can push,
 28.5724 +	and there's no way to push changes into a tree that someone
 28.5725 +	else controls.</para>
 28.5726 +
 28.5727 +      <para id="x_473">The second is that it's based on reputation and acclaim.
 28.5728 +	If you're an unknown, Linus will probably ignore changes from
 28.5729 +	you without even responding.  But a subsystem maintainer will
 28.5730 +	probably review them, and will likely take them if they pass
 28.5731 +	their criteria for suitability. The more <quote>good</quote>
 28.5732 +	changes you contribute to a maintainer, the more likely they
 28.5733 +	are to trust your judgment and accept your changes.  If you're
 28.5734 +	well-known and maintain a long-lived branch for something
 28.5735 +	Linus hasn't yet accepted, people with similar interests may
 28.5736 +	pull your changes regularly to keep up with your work.</para>
 28.5737 +
 28.5738 +      <para id="x_474">Reputation and acclaim don't necessarily cross subsystem
 28.5739 +	or <quote>people</quote> boundaries.  If you're a respected
 28.5740 +	but specialised storage hacker, and you try to fix a
 28.5741 +	networking bug, that change will receive a level of scrutiny
 28.5742 +	from a network maintainer comparable to a change from a
 28.5743 +	complete stranger.</para>
 28.5744 +
 28.5745 +      <para id="x_475">To people who come from more orderly project backgrounds,
 28.5746 +	the comparatively chaotic Linux kernel development process
 28.5747 +	often seems completely insane.  It's subject to the whims of
 28.5748 +	individuals; people make sweeping changes whenever they deem
 28.5749 +	it appropriate; and the pace of development is astounding.
 28.5750 +	And yet Linux is a highly successful, well-regarded piece of
 28.5751 +	software.</para>
 28.5752 +    </sect2>
 28.5753 +
 28.5754 +    <sect2>
 28.5755 +      <title>Pull-only versus shared-push collaboration</title>
 28.5756 +
 28.5757 +      <para id="x_476">A perpetual source of heat in the open source community is
 28.5758 +	whether a development model in which people only ever pull
 28.5759 +	changes from others is <quote>better than</quote> one in which
 28.5760 +	multiple people can push changes to a shared
 28.5761 +	repository.</para>
 28.5762 +
 28.5763 +      <para id="x_477">Typically, the backers of the shared-push model use tools
 28.5764 +	that actively enforce this approach.  If you're using a
 28.5765 +	centralised revision control tool such as Subversion, there's
 28.5766 +	no way to make a choice over which model you'll use: the tool
 28.5767 +	gives you shared-push, and if you want to do anything else,
 28.5768 +	you'll have to roll your own approach on top (such as applying
 28.5769 +	a patch by hand).</para>
 28.5770 +
 28.5771 +      <para id="x_478">A good distributed revision control tool will
 28.5772 +	support both models.  You and your collaborators can then
 28.5773 +	structure how you work together based on your own needs and
 28.5774 +	preferences, not on what contortions your tools force you
 28.5775 +	into.</para>
 28.5776 +    </sect2>
 28.5777 +    <sect2>
 28.5778 +      <title>Where collaboration meets branch management</title>
 28.5779 +
 28.5780 +      <para id="x_479">Once you and your team set up some shared
 28.5781 +	repositories and start propagating changes back and forth
 28.5782 +	between local and shared repos, you begin to face a related,
 28.5783 +	but slightly different challenge: that of managing the
 28.5784 +	multiple directions in which your team may be moving at once.
 28.5785 +	Even though this subject is intimately related to how your
 28.5786 +	team collaborates, it's dense enough to merit treatment of its
 28.5787 +	own, in <xref linkend="chap:branch"/>.</para>
 28.5788 +    </sect2>
 28.5789 +  </sect1>
 28.5790 +
 28.5791 +  <sect1>
 28.5792 +    <title>The technical side of sharing</title>
 28.5793 +
 28.5794 +    <para id="x_47a">The remainder of this chapter is devoted to the question of
 28.5795 +      sharing changes with your collaborators.</para>
 28.5796 +  </sect1>
 28.5797 +
 28.5798 +  <sect1 id="sec:collab:serve">
 28.5799 +    <title>Informal sharing with <command role="hg-cmd" moreinfo="none">hg
 28.5800 +	serve</command></title>
 28.5801 +
 28.5802 +    <para id="x_47b">Mercurial's <command role="hg-cmd" moreinfo="none">hg serve</command>
 28.5803 +      command is wonderfully suited to small, tight-knit, and
 28.5804 +      fast-paced group environments.  It also provides a great way to
 28.5805 +      get a feel for using Mercurial commands over a network.</para>
 28.5806 +
 28.5807 +    <para id="x_47c">Run <command role="hg-cmd" moreinfo="none">hg serve</command> inside a
 28.5808 +      repository, and in under a second it will bring up a specialised
 28.5809 +      HTTP server; this will accept connections from any client, and
 28.5810 +      serve up data for that repository until you terminate it.
 28.5811 +      Anyone who knows the URL of the server you just started, and can
 28.5812 +      talk to your computer over the network, can then use a web
 28.5813 +      browser or Mercurial to read data from that repository.  A URL
 28.5814 +      for a <command role="hg-cmd" moreinfo="none">hg serve</command> instance running
 28.5815 +      on a laptop is likely to look something like
 28.5816 +      <literal moreinfo="none">http://my-laptop.local:8000/</literal>.</para>
 28.5817 +
 28.5818 +    <para id="x_47d">The <command role="hg-cmd" moreinfo="none">hg serve</command> command is
 28.5819 +      <emphasis>not</emphasis> a general-purpose web server. It can do
 28.5820 +      only two things:</para>
 28.5821 +    <itemizedlist>
 28.5822 +      <listitem><para id="x_47e">Allow people to browse the history of the
 28.5823 +	  repository it's serving, from their normal web
 28.5824 +	  browsers.</para>
 28.5825 +      </listitem>
 28.5826 +      <listitem><para id="x_47f">Speak Mercurial's wire protocol, so that people
 28.5827 +	  can <command role="hg-cmd" moreinfo="none">hg clone</command> or <command role="hg-cmd" moreinfo="none">hg pull</command> changes from that
 28.5828 +	  repository.</para>
 28.5829 +      </listitem></itemizedlist>
 28.5830 +    <para id="x_480">In particular, <command role="hg-cmd" moreinfo="none">hg serve</command>
 28.5831 +      won't allow remote users to <emphasis>modify</emphasis> your
 28.5832 +      repository.  It's intended for read-only use.</para>
 28.5833 +
 28.5834 +    <para id="x_481">If you're getting started with Mercurial, there's nothing to
 28.5835 +      prevent you from using <command role="hg-cmd" moreinfo="none">hg serve</command>
 28.5836 +      to serve up a repository on your own computer, then use commands
 28.5837 +      like <command role="hg-cmd" moreinfo="none">hg clone</command>, <command role="hg-cmd" moreinfo="none">hg incoming</command>, and so on to talk to that
 28.5838 +      server as if the repository was hosted remotely. This can help
 28.5839 +      you to quickly get acquainted with using commands on
 28.5840 +      network-hosted repositories.</para>
 28.5841 +
 28.5842 +    <sect2>
 28.5843 +      <title>A few things to keep in mind</title>
 28.5844 +
 28.5845 +      <para id="x_482">Because it provides unauthenticated read access to all
 28.5846 +	clients, you should only use <command role="hg-cmd" moreinfo="none">hg
 28.5847 +	  serve</command> in an environment where you either don't
 28.5848 +	care, or have complete control over, who can access your
 28.5849 +	network and pull data from your repository.</para>
 28.5850 +
 28.5851 +      <para id="x_483">The <command role="hg-cmd" moreinfo="none">hg serve</command> command
 28.5852 +	knows nothing about any firewall software you might have
 28.5853 +	installed on your system or network.  It cannot detect or
 28.5854 +	control your firewall software.  If other people are unable to
 28.5855 +	talk to a running <command role="hg-cmd" moreinfo="none">hg serve</command>
 28.5856 +	instance, the second thing you should do
 28.5857 +	(<emphasis>after</emphasis> you make sure that they're using
 28.5858 +	the correct URL) is check your firewall configuration.</para>
 28.5859 +
 28.5860 +      <para id="x_484">By default, <command role="hg-cmd" moreinfo="none">hg serve</command>
 28.5861 +	listens for incoming connections on port 8000.  If another
 28.5862 +	process is already listening on the port you want to use, you
 28.5863 +	can specify a different port to listen on using the <option role="hg-opt-serve">-p</option> option.</para>
 28.5864 +
 28.5865 +      <para id="x_485">Normally, when <command role="hg-cmd" moreinfo="none">hg serve</command>
 28.5866 +	starts, it prints no output, which can be a bit unnerving.  If
 28.5867 +	you'd like to confirm that it is indeed running correctly, and
 28.5868 +	find out what URL you should send to your collaborators, start
 28.5869 +	it with the <option role="hg-opt-global">-v</option>
 28.5870 +	option.</para>
 28.5871 +    </sect2>
 28.5872 +  </sect1>
 28.5873 +
 28.5874 +  <sect1 id="sec:collab:ssh">
 28.5875 +    <title>Using the Secure Shell (ssh) protocol</title>
 28.5876 +
 28.5877 +    <para id="x_486">You can pull and push changes securely over a network
 28.5878 +      connection using the Secure Shell (<literal moreinfo="none">ssh</literal>)
 28.5879 +      protocol.  To use this successfully, you may have to do a little
 28.5880 +      bit of configuration on the client or server sides.</para>
 28.5881 +
 28.5882 +    <para id="x_487">If you're not familiar with ssh, it's the name of
 28.5883 +      both a command and a network protocol that let you securely
 28.5884 +      communicate with another computer.  To use it with Mercurial,
 28.5885 +      you'll be setting up one or more user accounts on a server so
 28.5886 +      that remote users can log in and execute commands.</para>
 28.5887 +
 28.5888 +    <para id="x_488">(If you <emphasis>are</emphasis> familiar with ssh, you'll
 28.5889 +      probably find some of the material that follows to be elementary
 28.5890 +      in nature.)</para>
 28.5891 +
 28.5892 +    <sect2>
 28.5893 +      <title>How to read and write ssh URLs</title>
 28.5894 +
 28.5895 +      <para id="x_489">An ssh URL tends to look like this:</para>
 28.5896 +      <programlisting format="linespecific">ssh://bos@hg.serpentine.com:22/hg/hgbook</programlisting>
 28.5897 +      <orderedlist inheritnum="ignore" continuation="restarts">
 28.5898 +	<listitem><para id="x_48a">The <quote><literal moreinfo="none">ssh://</literal></quote>
 28.5899 +	    part tells Mercurial to use the ssh protocol.</para>
 28.5900 +	</listitem>
 28.5901 +	<listitem><para id="x_48b">The <quote><literal moreinfo="none">bos@</literal></quote>
 28.5902 +	    component indicates what username to log into the server
 28.5903 +	    as.  You can leave this out if the remote username is the
 28.5904 +	    same as your local username.</para>
 28.5905 +	</listitem>
 28.5906 +	<listitem><para id="x_48c">The
 28.5907 +	    <quote><literal moreinfo="none">hg.serpentine.com</literal></quote> gives
 28.5908 +	    the hostname of the server to log into.</para>
 28.5909 +	</listitem>
 28.5910 +	<listitem><para id="x_48d">The <quote>:22</quote> identifies the port
 28.5911 +	    number to connect to the server on.  The default port is
 28.5912 +	    22, so you only need to specify a colon and port number if
 28.5913 +	    you're <emphasis>not</emphasis> using port 22.</para>
 28.5914 +	</listitem>
 28.5915 +	<listitem><para id="x_48e">The remainder of the URL is the local path to
 28.5916 +	    the repository on the server.</para>
 28.5917 +	</listitem></orderedlist>
 28.5918 +
 28.5919 +      <para id="x_48f">There's plenty of scope for confusion with the path
 28.5920 +	component of ssh URLs, as there is no standard way for tools
 28.5921 +	to interpret it.  Some programs behave differently than others
 28.5922 +	when dealing with these paths. This isn't an ideal situation,
 28.5923 +	but it's unlikely to change.  Please read the following
 28.5924 +	paragraphs carefully.</para>
 28.5925 +
 28.5926 +      <para id="x_490">Mercurial treats the path to a repository on the server as
 28.5927 +	relative to the remote user's home directory.  For example, if
 28.5928 +	user <literal moreinfo="none">foo</literal> on the server has a home directory
 28.5929 +	of <filename class="directory" moreinfo="none">/home/foo</filename>, then an
 28.5930 +	ssh URL that contains a path component of <filename class="directory" moreinfo="none">bar</filename> <emphasis>really</emphasis>
 28.5931 +	refers to the directory <filename class="directory" moreinfo="none">/home/foo/bar</filename>.</para>
 28.5932 +
 28.5933 +      <para id="x_491">If you want to specify a path relative to another user's
 28.5934 +	home directory, you can use a path that starts with a tilde
 28.5935 +	character followed by the user's name (let's call them
 28.5936 +	<literal moreinfo="none">otheruser</literal>), like this.</para>
 28.5937 +      <programlisting format="linespecific">ssh://server/~otheruser/hg/repo</programlisting>
 28.5938 +
 28.5939 +      <para id="x_492">And if you really want to specify an
 28.5940 +	<emphasis>absolute</emphasis> path on the server, begin the
 28.5941 +	path component with two slashes, as in this example.</para>
 28.5942 +      <programlisting format="linespecific">ssh://server//absolute/path</programlisting>
 28.5943 +    </sect2>
 28.5944 +
 28.5945 +    <sect2>
 28.5946 +      <title>Finding an ssh client for your system</title>
 28.5947 +
 28.5948 +      <para id="x_493">Almost every Unix-like system comes with OpenSSH
 28.5949 +	preinstalled.  If you're using such a system, run
 28.5950 +	<literal moreinfo="none">which ssh</literal> to find out if the
 28.5951 +	<command moreinfo="none">ssh</command> command is installed (it's usually in
 28.5952 +	<filename class="directory" moreinfo="none">/usr/bin</filename>).  In the
 28.5953 +	unlikely event that it isn't present, take a look at your
 28.5954 +	system documentation to figure out how to install it.</para>
 28.5955 +
 28.5956 +      <para id="x_494">On Windows, the TortoiseHg package is bundled
 28.5957 +	with a version of Simon Tatham's excellent
 28.5958 +	<command moreinfo="none">plink</command> command, and you should not need to
 28.5959 +	do any further configuration.</para>
 28.5960 +    </sect2>
 28.5961 +
 28.5962 +    <sect2>
 28.5963 +      <title>Generating a key pair</title>
 28.5964 +
 28.5965 +      <para id="x_499">To avoid the need to repetitively type a
 28.5966 +	password every time you need to use your ssh client, I
 28.5967 +	recommend generating a key pair.</para>
 28.5968 +
 28.5969 +      <tip>
 28.5970 +	<title>Key pairs are not mandatory</title>
 28.5971 +
 28.5972 +	<para id="x_6a4">Mercurial knows nothing about ssh authentication or key
 28.5973 +	  pairs.  You can, if you like, safely ignore this section and
 28.5974 +	  the one that follows until you grow tired of repeatedly
 28.5975 +	  typing ssh passwords.</para>
 28.5976 +      </tip>
 28.5977 +
 28.5978 +      <itemizedlist>
 28.5979 +	<listitem>
 28.5980 +	  <para id="x_6a5">On a Unix-like system, the
 28.5981 +	    <command moreinfo="none">ssh-keygen</command> command will do the
 28.5982 +	    trick.</para>
 28.5983 +	  <para id="x_6a6">On Windows, if you're using TortoiseHg, you may need
 28.5984 +	    to download a command named <command moreinfo="none">puttygen</command>
 28.5985 +	    from <ulink url="http://www.chiark.greenend.org.uk/~sgtatham/putty">the 
 28.5986 +	      PuTTY web site</ulink> to generate a key pair.  See
 28.5987 +	    <ulink url="http://the.earth.li/~sgtatham/putty/0.60/htmldoc/Chapter8.html#pubkey-puttygen">the 
 28.5988 +	      <command moreinfo="none">puttygen</command> documentation</ulink> for
 28.5989 +	    details of how use the command.</para>
 28.5990 +	</listitem>
 28.5991 +      </itemizedlist>
 28.5992 +
 28.5993 +      <para id="x_49a">When you generate a key pair, it's usually
 28.5994 +	<emphasis>highly</emphasis> advisable to protect it with a
 28.5995 +	passphrase.  (The only time that you might not want to do this
 28.5996 +	is when you're using the ssh protocol for automated tasks on a
 28.5997 +	secure network.)</para>
 28.5998 +
 28.5999 +      <para id="x_49b">Simply generating a key pair isn't enough, however.
 28.6000 +	You'll need to add the public key to the set of authorised
 28.6001 +	keys for whatever user you're logging in remotely as.  For
 28.6002 +	servers using OpenSSH (the vast majority), this will mean
 28.6003 +	adding the public key to a list in a file called <filename role="special" moreinfo="none">authorized_keys</filename> in their <filename role="special" class="directory" moreinfo="none">.ssh</filename>
 28.6004 +	directory.</para>
 28.6005 +
 28.6006 +      <para id="x_49c">On a Unix-like system, your public key will have a
 28.6007 +	<filename moreinfo="none">.pub</filename> extension.  If you're using
 28.6008 +	<command moreinfo="none">puttygen</command> on Windows, you can save the
 28.6009 +	public key to a file of your choosing, or paste it from the
 28.6010 +	window it's displayed in straight into the <filename role="special" moreinfo="none">authorized_keys</filename> file.</para>
 28.6011 +    </sect2>
 28.6012 +    <sect2>
 28.6013 +      <title>Using an authentication agent</title>
 28.6014 +
 28.6015 +      <para id="x_49d">An authentication agent is a daemon that stores
 28.6016 +	passphrases in memory (so it will forget passphrases if you
 28.6017 +	log out and log back in again). An ssh client will notice if
 28.6018 +	it's running, and query it for a passphrase.  If there's no
 28.6019 +	authentication agent running, or the agent doesn't store the
 28.6020 +	necessary passphrase, you'll have to type your passphrase
 28.6021 +	every time Mercurial tries to communicate with a server on
 28.6022 +	your behalf (e.g. whenever you pull or push changes).</para>
 28.6023 +
 28.6024 +      <para id="x_49e">The downside of storing passphrases in an agent is that
 28.6025 +	it's possible for a well-prepared attacker to recover the
 28.6026 +	plain text of your passphrases, in some cases even if your
 28.6027 +	system has been power-cycled. You should make your own
 28.6028 +	judgment as to whether this is an acceptable risk.  It
 28.6029 +	certainly saves a lot of repeated typing.</para>
 28.6030 +
 28.6031 +      <itemizedlist>
 28.6032 +	<listitem>
 28.6033 +	  <para id="x_49f">On Unix-like systems, the agent is called
 28.6034 +	    <command moreinfo="none">ssh-agent</command>, and it's often run
 28.6035 +	    automatically for you when you log in.  You'll need to use
 28.6036 +	    the <command moreinfo="none">ssh-add</command> command to add passphrases
 28.6037 +	    to the agent's store.</para>
 28.6038 +	</listitem>
 28.6039 +	<listitem>
 28.6040 +	  <para id="x_6a7">On Windows, if you're using TortoiseHg, the
 28.6041 +	    <command moreinfo="none">pageant</command> command acts as the agent.  As
 28.6042 +	    with <command moreinfo="none">puttygen</command>, you'll need to <ulink url="http://www.chiark.greenend.org.uk/%7Esgtatham/putty/download.html">download 
 28.6043 +	      <command moreinfo="none">pageant</command></ulink> from the PuTTY web
 28.6044 +	    site and read <ulink url="http://the.earth.li/~sgtatham/putty/0.60/htmldoc/Chapter9.html#pageant">its 
 28.6045 +	      documentation</ulink>.  The <command moreinfo="none">pageant</command>
 28.6046 +	    command adds an icon to your system tray that will let you
 28.6047 +	    manage stored passphrases.</para>
 28.6048 +	</listitem>
 28.6049 +      </itemizedlist>
 28.6050 +    </sect2>
 28.6051 +
 28.6052 +    <sect2>
 28.6053 +      <title>Configuring the server side properly</title>
 28.6054 +
 28.6055 +      <para id="x_4a0">Because ssh can be fiddly to set up if you're new to it,
 28.6056 +	a variety of things can go wrong.  Add Mercurial
 28.6057 +	on top, and there's plenty more scope for head-scratching.
 28.6058 +	Most of these potential problems occur on the server side, not
 28.6059 +	the client side.  The good news is that once you've gotten a
 28.6060 +	configuration working, it will usually continue to work
 28.6061 +	indefinitely.</para>
 28.6062 +
 28.6063 +      <para id="x_4a1">Before you try using Mercurial to talk to an ssh server,
 28.6064 +	it's best to make sure that you can use the normal
 28.6065 +	<command moreinfo="none">ssh</command> or <command moreinfo="none">putty</command> command to
 28.6066 +	talk to the server first.  If you run into problems with using
 28.6067 +	these commands directly, Mercurial surely won't work.  Worse,
 28.6068 +	it will obscure the underlying problem.  Any time you want to
 28.6069 +	debug ssh-related Mercurial problems, you should drop back to
 28.6070 +	making sure that plain ssh client commands work first,
 28.6071 +	<emphasis>before</emphasis> you worry about whether there's a
 28.6072 +	problem with Mercurial.</para>
 28.6073 +
 28.6074 +      <para id="x_4a2">The first thing to be sure of on the server side is that
 28.6075 +	you can actually log in from another machine at all.  If you
 28.6076 +	can't use <command moreinfo="none">ssh</command> or <command moreinfo="none">putty</command>
 28.6077 +	to log in, the error message you get may give you a few hints
 28.6078 +	as to what's wrong.  The most common problems are as
 28.6079 +	follows.</para>
 28.6080 +      <itemizedlist>
 28.6081 +	<listitem><para id="x_4a3">If you get a <quote>connection refused</quote>
 28.6082 +	    error, either there isn't an SSH daemon running on the
 28.6083 +	    server at all, or it's inaccessible due to firewall
 28.6084 +	    configuration.</para>
 28.6085 +	</listitem>
 28.6086 +	<listitem><para id="x_4a4">If you get a <quote>no route to host</quote>
 28.6087 +	    error, you either have an incorrect address for the server
 28.6088 +	    or a seriously locked down firewall that won't admit its
 28.6089 +	    existence at all.</para>
 28.6090 +	</listitem>
 28.6091 +	<listitem><para id="x_4a5">If you get a <quote>permission denied</quote>
 28.6092 +	    error, you may have mistyped the username on the server,
 28.6093 +	    or you could have mistyped your key's passphrase or the
 28.6094 +	    remote user's password.</para>
 28.6095 +	</listitem></itemizedlist>
 28.6096 +      <para id="x_4a6">In summary, if you're having trouble talking to the
 28.6097 +	server's ssh daemon, first make sure that one is running at
 28.6098 +	all.  On many systems it will be installed, but disabled, by
 28.6099 +	default.  Once you're done with this step, you should then
 28.6100 +	check that the server's firewall is configured to allow
 28.6101 +	incoming connections on the port the ssh daemon is listening
 28.6102 +	on (usually 22).  Don't worry about more exotic possibilities
 28.6103 +	for misconfiguration until you've checked these two
 28.6104 +	first.</para>
 28.6105 +
 28.6106 +      <para id="x_4a7">If you're using an authentication agent on the client side
 28.6107 +	to store passphrases for your keys, you ought to be able to
 28.6108 +	log into the server without being prompted for a passphrase or
 28.6109 +	a password.  If you're prompted for a passphrase, there are a
 28.6110 +	few possible culprits.</para>
 28.6111 +      <itemizedlist>
 28.6112 +	<listitem><para id="x_4a8">You might have forgotten to use
 28.6113 +	    <command moreinfo="none">ssh-add</command> or <command moreinfo="none">pageant</command>
 28.6114 +	    to store the passphrase.</para>
 28.6115 +	</listitem>
 28.6116 +	<listitem><para id="x_4a9">You might have stored the passphrase for the
 28.6117 +	    wrong key.</para>
 28.6118 +	</listitem></itemizedlist>
 28.6119 +      <para id="x_4aa">If you're being prompted for the remote user's password,
 28.6120 +	there are another few possible problems to check.</para>
 28.6121 +      <itemizedlist>
 28.6122 +	<listitem><para id="x_4ab">Either the user's home directory or their
 28.6123 +	    <filename role="special" class="directory" moreinfo="none">.ssh</filename>
 28.6124 +	    directory might have excessively liberal permissions.  As
 28.6125 +	    a result, the ssh daemon will not trust or read their
 28.6126 +	    <filename role="special" moreinfo="none">authorized_keys</filename> file.
 28.6127 +	    For example, a group-writable home or <filename role="special" class="directory" moreinfo="none">.ssh</filename>
 28.6128 +	    directory will often cause this symptom.</para>
 28.6129 +	</listitem>
 28.6130 +	<listitem><para id="x_4ac">The user's <filename role="special" moreinfo="none">authorized_keys</filename> file may have
 28.6131 +	    a problem. If anyone other than the user owns or can write
 28.6132 +	    to that file, the ssh daemon will not trust or read
 28.6133 +	    it.</para>
 28.6134 +	</listitem></itemizedlist>
 28.6135 +
 28.6136 +      <para id="x_4ad">In the ideal world, you should be able to run the
 28.6137 +	following command successfully, and it should print exactly
 28.6138 +	one line of output, the current date and time.</para>
 28.6139 +      <programlisting format="linespecific">ssh myserver date</programlisting>
 28.6140 +
 28.6141 +      <para id="x_4ae">If, on your server, you have login scripts that print
 28.6142 +	banners or other junk even when running non-interactive
 28.6143 +	commands like this, you should fix them before you continue,
 28.6144 +	so that they only print output if they're run interactively.
 28.6145 +	Otherwise these banners will at least clutter up Mercurial's
 28.6146 +	output.  Worse, they could potentially cause problems with
 28.6147 +	running Mercurial commands remotely.  Mercurial tries to
 28.6148 +	detect and ignore banners in non-interactive
 28.6149 +	<command moreinfo="none">ssh</command> sessions, but it is not foolproof.  (If
 28.6150 +	you're editing your login scripts on your server, the usual
 28.6151 +	way to see if a login script is running in an interactive
 28.6152 +	shell is to check the return code from the command
 28.6153 +	<literal moreinfo="none">tty -s</literal>.)</para>
 28.6154 +
 28.6155 +      <para id="x_4af">Once you've verified that plain old ssh is working with
 28.6156 +	your server, the next step is to ensure that Mercurial runs on
 28.6157 +	the server.  The following command should run
 28.6158 +	successfully:</para>
 28.6159 +
 28.6160 +      <programlisting format="linespecific">ssh myserver hg version</programlisting>
 28.6161 +
 28.6162 +      <para id="x_4b0">If you see an error message instead of normal <command role="hg-cmd" moreinfo="none">hg version</command> output, this is usually
 28.6163 +	because you haven't installed Mercurial to <filename class="directory" moreinfo="none">/usr/bin</filename>.  Don't worry if this
 28.6164 +	is the case; you don't need to do that.  But you should check
 28.6165 +	for a few possible problems.</para>
 28.6166 +      <itemizedlist>
 28.6167 +	<listitem><para id="x_4b1">Is Mercurial really installed on the server at
 28.6168 +	    all?  I know this sounds trivial, but it's worth
 28.6169 +	    checking!</para>
 28.6170 +	</listitem>
 28.6171 +	<listitem><para id="x_4b2">Maybe your shell's search path (usually set
 28.6172 +	    via the <envar>PATH</envar> environment variable) is
 28.6173 +	    simply misconfigured.</para>
 28.6174 +	</listitem>
 28.6175 +	<listitem><para id="x_4b3">Perhaps your <envar>PATH</envar> environment
 28.6176 +	    variable is only being set to point to the location of the
 28.6177 +	    <command moreinfo="none">hg</command> executable if the login session is
 28.6178 +	    interactive.  This can happen if you're setting the path
 28.6179 +	    in the wrong shell login script.  See your shell's
 28.6180 +	    documentation for details.</para>
 28.6181 +	</listitem>
 28.6182 +	<listitem><para id="x_4b4">The <envar>PYTHONPATH</envar> environment
 28.6183 +	    variable may need to contain the path to the Mercurial
 28.6184 +	    Python modules.  It might not be set at all; it could be
 28.6185 +	    incorrect; or it may be set only if the login is
 28.6186 +	    interactive.</para>
 28.6187 +	</listitem></itemizedlist>
 28.6188 +
 28.6189 +      <para id="x_4b5">If you can run <command role="hg-cmd" moreinfo="none">hg version</command>
 28.6190 +	over an ssh connection, well done! You've got the server and
 28.6191 +	client sorted out.  You should now be able to use Mercurial to
 28.6192 +	access repositories hosted by that username on that server.
 28.6193 +	If you run into problems with Mercurial and ssh at this point,
 28.6194 +	try using the <option role="hg-opt-global">--debug</option>
 28.6195 +	option to get a clearer picture of what's going on.</para>
 28.6196 +    </sect2>
 28.6197 +    <sect2>
 28.6198 +      <title>Using compression with ssh</title>
 28.6199 +
 28.6200 +      <para id="x_4b6">Mercurial does not compress data when it uses the ssh
 28.6201 +	protocol, because the ssh protocol can transparently compress
 28.6202 +	data.  However, the default behavior of ssh clients is
 28.6203 +	<emphasis>not</emphasis> to request compression.</para>
 28.6204 +
 28.6205 +      <para id="x_4b7">Over any network other than a fast LAN (even a wireless
 28.6206 +	network), using compression is likely to significantly speed
 28.6207 +	up Mercurial's network operations.  For example, over a WAN,
 28.6208 +	someone measured compression as reducing the amount of time
 28.6209 +	required to clone a particularly large repository from 51
 28.6210 +	minutes to 17 minutes.</para>
 28.6211 +
 28.6212 +      <para id="x_4b8">Both <command moreinfo="none">ssh</command> and <command moreinfo="none">plink</command>
 28.6213 +	accept a <option role="cmd-opt-ssh">-C</option> option which
 28.6214 +	turns on compression.  You can easily edit your <filename role="special" moreinfo="none">~/.hgrc</filename> to enable compression for
 28.6215 +	all of Mercurial's uses of the ssh protocol.  Here is how to
 28.6216 +	do so for regular <command moreinfo="none">ssh</command> on Unix-like systems,
 28.6217 +	for example.</para>
 28.6218 +      <programlisting format="linespecific">[ui]
 28.6219 +ssh = ssh -C</programlisting>
 28.6220 +
 28.6221 +      <para id="x_4b9">If you use <command moreinfo="none">ssh</command> on a
 28.6222 +	Unix-like system, you can configure it to always use
 28.6223 +	compression when talking to your server.  To do this, edit
 28.6224 +	your <filename role="special" moreinfo="none">.ssh/config</filename> file
 28.6225 +	(which may not yet exist), as follows.</para>
 28.6226 +
 28.6227 +      <programlisting format="linespecific">Host hg
 28.6228 +  Compression yes
 28.6229 +  HostName hg.example.com</programlisting>
 28.6230 +
 28.6231 +      <para id="x_4ba">This defines a hostname alias,
 28.6232 +	<literal moreinfo="none">hg</literal>.  When you use that hostname on the
 28.6233 +	<command moreinfo="none">ssh</command> command line or in a Mercurial
 28.6234 +	<literal moreinfo="none">ssh</literal>-protocol URL, it will cause
 28.6235 +	<command moreinfo="none">ssh</command> to connect to
 28.6236 +	<literal moreinfo="none">hg.example.com</literal> and use compression.  This
 28.6237 +	gives you both a shorter name to type and compression, each of
 28.6238 +	which is a good thing in its own right.</para>
 28.6239 +    </sect2>
 28.6240 +  </sect1>
 28.6241 +
 28.6242 +  <sect1 id="sec:collab:cgi">
 28.6243 +    <title>Serving over HTTP using CGI</title>
 28.6244 +
 28.6245 +    <para id="x_6a8">The simplest way to host one or more repositories in a
 28.6246 +      permanent way is to use a web server and Mercurial's CGI
 28.6247 +      support.</para>
 28.6248 +
 28.6249 +    <para id="x_4bb">Depending on how ambitious you are, configuring Mercurial's
 28.6250 +      CGI interface can take anything from a few moments to several
 28.6251 +      hours.</para>
 28.6252 +
 28.6253 +    <para id="x_4bc">We'll begin with the simplest of examples, and work our way
 28.6254 +      towards a more complex configuration.  Even for the most basic
 28.6255 +      case, you're almost certainly going to need to read and modify
 28.6256 +      your web server's configuration.</para>
 28.6257 +
 28.6258 +    <note>
 28.6259 +      <title>High pain tolerance required</title>
 28.6260 +
 28.6261 +      <para id="x_4bd">Configuring a web server is a complex, fiddly,
 28.6262 +	and highly system-dependent activity.  I can't possibly give
 28.6263 +	you instructions that will cover anything like all of the
 28.6264 +	cases you will encounter. Please use your discretion and
 28.6265 +	judgment in following the sections below.  Be prepared to make
 28.6266 +	plenty of mistakes, and to spend a lot of time reading your
 28.6267 +	server's error logs.</para>
 28.6268 +
 28.6269 +      <para id="x_6a9">If you don't have a strong stomach for tweaking
 28.6270 +	configurations over and over, or a compelling need to host
 28.6271 +	your own services, you might want to try one of the public
 28.6272 +	hosting services that I mentioned earlier.</para>
 28.6273 +    </note>
 28.6274 +
 28.6275 +    <sect2>
 28.6276 +      <title>Web server configuration checklist</title>
 28.6277 +
 28.6278 +      <para id="x_4be">Before you continue, do take a few moments to check a few
 28.6279 +	aspects of your system's setup.</para>
 28.6280 +
 28.6281 +      <orderedlist inheritnum="ignore" continuation="restarts">
 28.6282 +	<listitem><para id="x_4bf">Do you have a web server installed
 28.6283 +	    at all? Mac OS X and some Linux distributions ship with
 28.6284 +	    Apache, but many other systems may not have a web server
 28.6285 +	    installed.</para>
 28.6286 +	</listitem>
 28.6287 +	<listitem><para id="x_4c0">If you have a web server installed, is it
 28.6288 +	    actually running?  On most systems, even if one is
 28.6289 +	    present, it will be disabled by default.</para>
 28.6290 +	</listitem>
 28.6291 +	<listitem><para id="x_4c1">Is your server configured to allow you to run
 28.6292 +	    CGI programs in the directory where you plan to do so?
 28.6293 +	    Most servers default to explicitly disabling the ability
 28.6294 +	    to run CGI programs.</para>
 28.6295 +	</listitem></orderedlist>
 28.6296 +
 28.6297 +      <para id="x_4c2">If you don't have a web server installed, and don't have
 28.6298 +	substantial experience configuring Apache, you should consider
 28.6299 +	using the <literal moreinfo="none">lighttpd</literal> web server instead of
 28.6300 +	Apache.  Apache has a well-deserved reputation for baroque and
 28.6301 +	confusing configuration. While <literal moreinfo="none">lighttpd</literal> is
 28.6302 +	less capable in some ways than Apache, most of these
 28.6303 +	capabilities are not relevant to serving Mercurial
 28.6304 +	repositories.  And <literal moreinfo="none">lighttpd</literal> is undeniably
 28.6305 +	<emphasis>much</emphasis> easier to get started with than
 28.6306 +	Apache.</para>
 28.6307 +    </sect2>
 28.6308 +
 28.6309 +    <sect2>
 28.6310 +      <title>Basic CGI configuration</title>
 28.6311 +
 28.6312 +      <para id="x_4c3">On Unix-like systems, it's common for users to have a
 28.6313 +	subdirectory named something like <filename class="directory" moreinfo="none">public_html</filename> in their home
 28.6314 +	directory, from which they can serve up web pages.  A file
 28.6315 +	named <filename moreinfo="none">foo</filename> in this directory will be
 28.6316 +	accessible at a URL of the form
 28.6317 +	<literal moreinfo="none">http://www.example.com/username/foo</literal>.</para>
 28.6318 +
 28.6319 +      <para id="x_4c4">To get started, find the <filename role="special" moreinfo="none">hgweb.cgi</filename> script that should be
 28.6320 +	present in your Mercurial installation.  If you can't quickly
 28.6321 +	find a local copy on your system, simply download one from the
 28.6322 +	master Mercurial repository at <ulink url="http://www.selenic.com/repo/hg/raw-file/tip/hgweb.cgi">http://www.selenic.com/repo/hg/raw-file/tip/hgweb.cgi</ulink>.</para>
 28.6323 +
 28.6324 +      <para id="x_4c5">You'll need to copy this script into your <filename class="directory" moreinfo="none">public_html</filename> directory, and
 28.6325 +	ensure that it's executable.</para>
 28.6326 +      <programlisting format="linespecific">cp .../hgweb.cgi ~/public_html
 28.6327 +chmod 755 ~/public_html/hgweb.cgi</programlisting>
 28.6328 +      <para id="x_4c6">The <literal moreinfo="none">755</literal> argument to
 28.6329 +	<command moreinfo="none">chmod</command> is a little more general than just
 28.6330 +	making the script executable: it ensures that the script is
 28.6331 +	executable by anyone, and that <quote>group</quote> and
 28.6332 +	<quote>other</quote> write permissions are
 28.6333 +	<emphasis>not</emphasis> set.  If you were to leave those
 28.6334 +	write permissions enabled, Apache's <literal moreinfo="none">suexec</literal>
 28.6335 +	subsystem would likely refuse to execute the script.  In fact,
 28.6336 +	<literal moreinfo="none">suexec</literal> also insists that the
 28.6337 +	<emphasis>directory</emphasis> in which the script resides
 28.6338 +	must not be writable by others.</para>
 28.6339 +      <programlisting format="linespecific">chmod 755 ~/public_html</programlisting>
 28.6340 +
 28.6341 +      <sect3 id="sec:collab:wtf">
 28.6342 +	<title>What could <emphasis>possibly</emphasis> go
 28.6343 +	  wrong?</title>
 28.6344 +
 28.6345 +	<para id="x_4c7">Once you've copied the CGI script into place,
 28.6346 +	  go into a web browser, and try to open the URL
 28.6347 +	  <literal moreinfo="none">http://myhostname/~myuser/hgweb.cgi</literal>,
 28.6348 +	  <emphasis>but</emphasis> brace yourself for instant failure.
 28.6349 +	  There's a high probability that trying to visit this URL
 28.6350 +	  will fail, and there are many possible reasons for this.  In
 28.6351 +	  fact, you're likely to stumble over almost every one of the
 28.6352 +	  possible errors below, so please read carefully.  The
 28.6353 +	  following are all of the problems I ran into on a system
 28.6354 +	  running Fedora 7, with a fresh installation of Apache, and a
 28.6355 +	  user account that I created specially to perform this
 28.6356 +	  exercise.</para>
 28.6357 +
 28.6358 +	<para id="x_4c8">Your web server may have per-user directories disabled.
 28.6359 +	  If you're using Apache, search your config file for a
 28.6360 +	  <literal moreinfo="none">UserDir</literal> directive.  If there's none
 28.6361 +	  present, per-user directories will be disabled.  If one
 28.6362 +	  exists, but its value is <literal moreinfo="none">disabled</literal>, then
 28.6363 +	  per-user directories will be disabled.  Otherwise, the
 28.6364 +	  string after <literal moreinfo="none">UserDir</literal> gives the name of
 28.6365 +	  the subdirectory that Apache will look in under your home
 28.6366 +	  directory, for example <filename class="directory" moreinfo="none">public_html</filename>.</para>
 28.6367 +
 28.6368 +	<para id="x_4c9">Your file access permissions may be too restrictive.
 28.6369 +	  The web server must be able to traverse your home directory
 28.6370 +	  and directories under your <filename class="directory" moreinfo="none">public_html</filename> directory, and
 28.6371 +	  read files under the latter too.  Here's a quick recipe to
 28.6372 +	  help you to make your permissions more appropriate.</para>
 28.6373 +	<programlisting format="linespecific">chmod 755 ~
 28.6374 +find ~/public_html -type d -print0 | xargs -0r chmod 755
 28.6375 +find ~/public_html -type f -print0 | xargs -0r chmod 644</programlisting>
 28.6376 +
 28.6377 +	<para id="x_4ca">The other possibility with permissions is that you might
 28.6378 +	  get a completely empty window when you try to load the
 28.6379 +	  script.  In this case, it's likely that your access
 28.6380 +	  permissions are <emphasis>too permissive</emphasis>.  Apache's
 28.6381 +	  <literal moreinfo="none">suexec</literal> subsystem won't execute a script
 28.6382 +	  that's group- or world-writable, for example.</para>
 28.6383 +
 28.6384 +	<para id="x_4cb">Your web server may be configured to disallow execution
 28.6385 +	  of CGI programs in your per-user web directory.  Here's
 28.6386 +	  Apache's default per-user configuration from my Fedora
 28.6387 +	  system.</para>
 28.6388 +
 28.6389 +	<!-- BEGIN ch06/apache-config.lst -->
 28.6390 +<programlisting format="linespecific">&lt;Directory /home/*/public_html&gt;
 28.6391 +  AllowOverride FileInfo AuthConfig Limit
 28.6392 +  Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
 28.6393 +  &lt;Limit GET POST OPTIONS&gt;
 28.6394 +    Order allow,deny
 28.6395 +    Allow from all
 28.6396 +  &lt;/Limit&gt;
 28.6397 +  &lt;LimitExcept GET POST OPTIONS&gt;
 28.6398 +    Order deny,allow Deny from all
 28.6399 +  &lt;/LimitExcept&gt;
 28.6400 +&lt;/Directory&gt;</programlisting>
 28.6401 +<!-- END ch06/apache-config.lst -->
 28.6402 +
 28.6403 +
 28.6404 +	<para id="x_4cc">If you find a similar-looking
 28.6405 +	  <literal moreinfo="none">Directory</literal> group in your Apache
 28.6406 +	  configuration, the directive to look at inside it is
 28.6407 +	  <literal moreinfo="none">Options</literal>. Add <literal moreinfo="none">ExecCGI</literal>
 28.6408 +	  to the end of this list if it's missing, and restart the web
 28.6409 +	  server.</para>
 28.6410 +
 28.6411 +	<para id="x_4cd">If you find that Apache serves you the text of the CGI
 28.6412 +	  script instead of executing it, you may need to either
 28.6413 +	  uncomment (if already present) or add a directive like
 28.6414 +	  this.</para>
 28.6415 +	<programlisting format="linespecific">AddHandler cgi-script .cgi</programlisting>
 28.6416 +
 28.6417 +	<para id="x_4ce">The next possibility is that you might be served with a
 28.6418 +	  colourful Python backtrace claiming that it can't import a
 28.6419 +	  <literal moreinfo="none">mercurial</literal>-related module.  This is
 28.6420 +	  actually progress!  The server is now capable of executing
 28.6421 +	  your CGI script.  This error is only likely to occur if
 28.6422 +	  you're running a private installation of Mercurial, instead
 28.6423 +	  of a system-wide version.  Remember that the web server runs
 28.6424 +	  the CGI program without any of the environment variables
 28.6425 +	  that you take for granted in an interactive session.  If
 28.6426 +	  this error happens to you, edit your copy of <filename role="special" moreinfo="none">hgweb.cgi</filename> and follow the
 28.6427 +	  directions inside it to correctly set your
 28.6428 +	  <envar>PYTHONPATH</envar> environment variable.</para>
 28.6429 +
 28.6430 +	<para id="x_4cf">Finally, you are <emphasis>certain</emphasis> to be
 28.6431 +	  served with another colourful Python backtrace: this one
 28.6432 +	  will complain that it can't find <filename class="directory" moreinfo="none">/path/to/repository</filename>.  Edit
 28.6433 +	  your <filename role="special" moreinfo="none">hgweb.cgi</filename> script
 28.6434 +	  and replace the <filename class="directory" moreinfo="none">/path/to/repository</filename> string
 28.6435 +	  with the complete path to the repository you want to serve
 28.6436 +	  up.</para>
 28.6437 +
 28.6438 +	<para id="x_4d0">At this point, when you try to reload the page, you
 28.6439 +	  should be presented with a nice HTML view of your
 28.6440 +	  repository's history.  Whew!</para>
 28.6441 +      </sect3>
 28.6442 +
 28.6443 +      <sect3>
 28.6444 +	<title>Configuring lighttpd</title>
 28.6445 +
 28.6446 +	<para id="x_4d1">To be exhaustive in my experiments, I tried configuring
 28.6447 +	  the increasingly popular <literal moreinfo="none">lighttpd</literal> web
 28.6448 +	  server to serve the same repository as I described with
 28.6449 +	  Apache above.  I had already overcome all of the problems I
 28.6450 +	  outlined with Apache, many of which are not server-specific.
 28.6451 +	  As a result, I was fairly sure that my file and directory
 28.6452 +	  permissions were good, and that my <filename role="special" moreinfo="none">hgweb.cgi</filename> script was properly
 28.6453 +	  edited.</para>
 28.6454 +
 28.6455 +	<para id="x_4d2">Once I had Apache running, getting
 28.6456 +	  <literal moreinfo="none">lighttpd</literal> to serve the repository was a
 28.6457 +	  snap (in other words, even if you're trying to use
 28.6458 +	  <literal moreinfo="none">lighttpd</literal>, you should read the Apache
 28.6459 +	  section).  I first had to edit the
 28.6460 +	  <literal moreinfo="none">mod_access</literal> section of its config file to
 28.6461 +	  enable <literal moreinfo="none">mod_cgi</literal> and
 28.6462 +	  <literal moreinfo="none">mod_userdir</literal>, both of which were disabled
 28.6463 +	  by default on my system.  I then added a few lines to the
 28.6464 +	  end of the config file, to configure these modules.</para>
 28.6465 +	<programlisting format="linespecific">userdir.path = "public_html"
 28.6466 +cgi.assign = (".cgi" =&gt; "" )</programlisting>
 28.6467 +	<para id="x_4d3">With this done, <literal moreinfo="none">lighttpd</literal> ran
 28.6468 +	  immediately for me.  If I had configured
 28.6469 +	  <literal moreinfo="none">lighttpd</literal> before Apache, I'd almost
 28.6470 +	  certainly have run into many of the same system-level
 28.6471 +	  configuration problems as I did with Apache.  However, I
 28.6472 +	  found <literal moreinfo="none">lighttpd</literal> to be noticeably easier to
 28.6473 +	  configure than Apache, even though I've used Apache for over
 28.6474 +	  a decade, and this was my first exposure to
 28.6475 +	  <literal moreinfo="none">lighttpd</literal>.</para>
 28.6476 +      </sect3>
 28.6477 +    </sect2>
 28.6478 +
 28.6479 +    <sect2>
 28.6480 +      <title>Sharing multiple repositories with one CGI script</title>
 28.6481 +
 28.6482 +      <para id="x_4d4">The <filename role="special" moreinfo="none">hgweb.cgi</filename> script
 28.6483 +	only lets you publish a single repository, which is an
 28.6484 +	annoying restriction.  If you want to publish more than one
 28.6485 +	without wracking yourself with multiple copies of the same
 28.6486 +	script, each with different names, a better choice is to use
 28.6487 +	the <filename role="special" moreinfo="none">hgwebdir.cgi</filename>
 28.6488 +	script.</para>
 28.6489 +
 28.6490 +      <para id="x_4d5">The procedure to configure <filename role="special" moreinfo="none">hgwebdir.cgi</filename> is only a little more
 28.6491 +	involved than for <filename role="special" moreinfo="none">hgweb.cgi</filename>.  First, you must obtain
 28.6492 +	a copy of the script.  If you don't have one handy, you can
 28.6493 +	download a copy from the master Mercurial repository at <ulink url="http://www.selenic.com/repo/hg/raw-file/tip/hgwebdir.cgi">http://www.selenic.com/repo/hg/raw-file/tip/hgwebdir.cgi</ulink>.</para>
 28.6494 +
 28.6495 +      <para id="x_4d6">You'll need to copy this script into your <filename class="directory" moreinfo="none">public_html</filename> directory, and
 28.6496 +	ensure that it's executable.</para>
 28.6497 +
 28.6498 +      <programlisting format="linespecific">cp .../hgwebdir.cgi ~/public_html
 28.6499 +chmod 755 ~/public_html ~/public_html/hgwebdir.cgi</programlisting>
 28.6500 +
 28.6501 +      <para id="x_4d7">With basic configuration out of the way, try to
 28.6502 +	visit <literal moreinfo="none">http://myhostname/~myuser/hgwebdir.cgi</literal>
 28.6503 +	in your	browser.  It should
 28.6504 +	display an empty list of repositories.  If you get a blank
 28.6505 +	window or error message, try walking through the list of
 28.6506 +	potential problems in <xref linkend="sec:collab:wtf"/>.</para>
 28.6507 +
 28.6508 +      <para id="x_4d8">The <filename role="special" moreinfo="none">hgwebdir.cgi</filename>
 28.6509 +	script relies on an external configuration file.  By default,
 28.6510 +	it searches for a file named <filename role="special" moreinfo="none">hgweb.config</filename> in the same directory
 28.6511 +	as itself.  You'll need to create this file, and make it
 28.6512 +	world-readable.  The format of the file is similar to a
 28.6513 +	Windows <quote>ini</quote> file, as understood by Python's
 28.6514 +	<literal moreinfo="none">ConfigParser</literal>
 28.6515 +	<citation>web:configparser</citation> module.</para>
 28.6516 +
 28.6517 +      <para id="x_4d9">The easiest way to configure <filename role="special" moreinfo="none">hgwebdir.cgi</filename> is with a section
 28.6518 +	named <literal moreinfo="none">collections</literal>.  This will automatically
 28.6519 +	publish <emphasis>every</emphasis> repository under the
 28.6520 +	directories you name.  The section should look like
 28.6521 +	this:</para>
 28.6522 +      <programlisting format="linespecific">[collections]
 28.6523 +/my/root = /my/root</programlisting>
 28.6524 +      <para id="x_4da">Mercurial interprets this by looking at the directory name
 28.6525 +	on the <emphasis>right</emphasis> hand side of the
 28.6526 +	<quote><literal moreinfo="none">=</literal></quote> sign; finding repositories
 28.6527 +	in that directory hierarchy; and using the text on the
 28.6528 +	<emphasis>left</emphasis> to strip off matching text from the
 28.6529 +	names it will actually list in the web interface.  The
 28.6530 +	remaining component of a path after this stripping has
 28.6531 +	occurred is called a <quote>virtual path</quote>.</para>
 28.6532 +
 28.6533 +      <para id="x_4db">Given the example above, if we have a
 28.6534 +	repository whose local path is <filename class="directory" moreinfo="none">/my/root/this/repo</filename>, the CGI
 28.6535 +	script will strip the leading <filename class="directory" moreinfo="none">/my/root</filename> from the name, and
 28.6536 +	publish the repository with a virtual path of <filename class="directory" moreinfo="none">this/repo</filename>.  If the base URL for
 28.6537 +	our CGI script is
 28.6538 +	<literal moreinfo="none">http://myhostname/~myuser/hgwebdir.cgi</literal>, the
 28.6539 +	complete URL for that repository will be
 28.6540 +	<literal moreinfo="none">http://myhostname/~myuser/hgwebdir.cgi/this/repo</literal>.</para>
 28.6541 +
 28.6542 +      <para id="x_4dc">If we replace <filename class="directory" moreinfo="none">/my/root</filename> on the left hand side
 28.6543 +	of this example with <filename class="directory" moreinfo="none">/my</filename>, then <filename role="special" moreinfo="none">hgwebdir.cgi</filename> will only strip off
 28.6544 +	<filename class="directory" moreinfo="none">/my</filename> from the repository
 28.6545 +	name, and will give us a virtual path of <filename class="directory" moreinfo="none">root/this/repo</filename> instead of
 28.6546 +	<filename class="directory" moreinfo="none">this/repo</filename>.</para>
 28.6547 +
 28.6548 +      <para id="x_4dd">The <filename role="special" moreinfo="none">hgwebdir.cgi</filename>
 28.6549 +	script will recursively search each directory listed in the
 28.6550 +	<literal moreinfo="none">collections</literal> section of its configuration
 28.6551 +	file, but it will <literal moreinfo="none">not</literal> recurse into the
 28.6552 +	repositories it finds.</para>
 28.6553 +
 28.6554 +      <para id="x_4de">The <literal moreinfo="none">collections</literal> mechanism makes it easy
 28.6555 +	to publish many repositories in a <quote>fire and
 28.6556 +	  forget</quote> manner.  You only need to set up the CGI
 28.6557 +	script and configuration file one time.  Afterwards, you can
 28.6558 +	publish or unpublish a repository at any time by simply moving
 28.6559 +	it into, or out of, the directory hierarchy in which you've
 28.6560 +	configured <filename role="special" moreinfo="none">hgwebdir.cgi</filename> to
 28.6561 +	look.</para>
 28.6562 +
 28.6563 +      <sect3>
 28.6564 +	<title>Explicitly specifying which repositories to
 28.6565 +	  publish</title>
 28.6566 +
 28.6567 +	<para id="x_4df">In addition to the <literal moreinfo="none">collections</literal>
 28.6568 +	  mechanism, the <filename role="special" moreinfo="none">hgwebdir.cgi</filename> script allows you
 28.6569 +	  to publish a specific list of repositories.  To do so,
 28.6570 +	  create a <literal moreinfo="none">paths</literal> section, with contents of
 28.6571 +	  the following form.</para>
 28.6572 +	<programlisting format="linespecific">[paths]
 28.6573 +repo1 = /my/path/to/some/repo
 28.6574 +repo2 = /some/path/to/another</programlisting>
 28.6575 +	<para id="x_4e0">In this case, the virtual path (the component that will
 28.6576 +	  appear in a URL) is on the left hand side of each
 28.6577 +	  definition, while the path to the repository is on the
 28.6578 +	  right.  Notice that there does not need to be any
 28.6579 +	  relationship between the virtual path you choose and the
 28.6580 +	  location of a repository in your filesystem.</para>
 28.6581 +
 28.6582 +	<para id="x_4e1">If you wish, you can use both the
 28.6583 +	  <literal moreinfo="none">collections</literal> and <literal moreinfo="none">paths</literal>
 28.6584 +	  mechanisms simultaneously in a single configuration
 28.6585 +	  file.</para>
 28.6586 +
 28.6587 +	<note>
 28.6588 +	  <title>Beware duplicate virtual paths</title>
 28.6589 +
 28.6590 +	  <para id="x_4e2">  If several repositories have the same
 28.6591 +	    virtual path, <filename role="special" moreinfo="none">hgwebdir.cgi</filename> will not report
 28.6592 +	    an error.  Instead, it will behave unpredictably.</para>
 28.6593 +	</note>
 28.6594 +      </sect3>
 28.6595 +    </sect2>
 28.6596 +
 28.6597 +    <sect2>
 28.6598 +      <title>Downloading source archives</title>
 28.6599 +
 28.6600 +      <para id="x_4e3">Mercurial's web interface lets users download an archive
 28.6601 +	of any revision.  This archive will contain a snapshot of the
 28.6602 +	working directory as of that revision, but it will not contain
 28.6603 +	a copy of the repository data.</para>
 28.6604 +
 28.6605 +      <para id="x_4e4">By default, this feature is not enabled.  To enable it,
 28.6606 +	you'll need to add an <envar role="rc-item-web">allow_archive</envar> item to the
 28.6607 +	<literal role="rc-web" moreinfo="none">web</literal> section of your <filename role="special" moreinfo="none">~/.hgrc</filename>; see below for details.</para>
 28.6608 +    </sect2>
 28.6609 +    <sect2>
 28.6610 +      <title>Web configuration options</title>
 28.6611 +
 28.6612 +      <para id="x_4e5">Mercurial's web interfaces (the <command role="hg-cmd" moreinfo="none">hg
 28.6613 +	  serve</command> command, and the <filename role="special" moreinfo="none">hgweb.cgi</filename> and <filename role="special" moreinfo="none">hgwebdir.cgi</filename> scripts) have a
 28.6614 +	number of configuration options that you can set.  These
 28.6615 +	belong in a section named <literal role="rc-web" moreinfo="none">web</literal>.</para>
 28.6616 +      <itemizedlist>
 28.6617 +	<listitem><para id="x_4e6"><envar role="rc-item-web">allow_archive</envar>: Determines
 28.6618 +	    which (if any) archive download mechanisms Mercurial
 28.6619 +	    supports.  If you enable this feature, users of the web
 28.6620 +	    interface will be able to download an archive of whatever
 28.6621 +	    revision of a repository they are viewing. To enable the
 28.6622 +	    archive feature, this item must take the form of a
 28.6623 +	    sequence of words drawn from the list below.</para>
 28.6624 +	  <itemizedlist>
 28.6625 +	    <listitem><para id="x_4e7"><literal moreinfo="none">bz2</literal>: A
 28.6626 +		<command moreinfo="none">tar</command> archive, compressed using
 28.6627 +		<literal moreinfo="none">bzip2</literal> compression.  This has the
 28.6628 +		best compression ratio, but uses the most CPU time on
 28.6629 +		the server.</para>
 28.6630 +	    </listitem>
 28.6631 +	    <listitem><para id="x_4e8"><literal moreinfo="none">gz</literal>: A
 28.6632 +		<command moreinfo="none">tar</command> archive, compressed using
 28.6633 +		<literal moreinfo="none">gzip</literal> compression.</para>
 28.6634 +	    </listitem>
 28.6635 +	    <listitem><para id="x_4e9"><literal moreinfo="none">zip</literal>: A
 28.6636 +		<command moreinfo="none">zip</command> archive, compressed using LZW
 28.6637 +		compression.  This format has the worst compression
 28.6638 +		ratio, but is widely used in the Windows world.</para>
 28.6639 +	    </listitem>
 28.6640 +	  </itemizedlist>
 28.6641 +	  <para id="x_4ea">  If you provide an empty list, or don't have an
 28.6642 +	    <envar role="rc-item-web">allow_archive</envar> entry at
 28.6643 +	    all, this feature will be disabled.  Here is an example of
 28.6644 +	    how to enable all three supported formats.</para>
 28.6645 +	  <programlisting format="linespecific">[web]
 28.6646 +allow_archive = bz2 gz zip</programlisting>
 28.6647 +	</listitem>
 28.6648 +	<listitem><para id="x_4eb"><envar role="rc-item-web">allowpull</envar>:
 28.6649 +	    Boolean.  Determines whether the web interface allows
 28.6650 +	    remote users to <command role="hg-cmd" moreinfo="none">hg pull</command>
 28.6651 +	    and <command role="hg-cmd" moreinfo="none">hg clone</command> this
 28.6652 +	    repository over HTTP.  If set to <literal moreinfo="none">no</literal> or
 28.6653 +	    <literal moreinfo="none">false</literal>, only the
 28.6654 +	    <quote>human-oriented</quote> portion of the web interface
 28.6655 +	    is available.</para>
 28.6656 +	</listitem>
 28.6657 +	<listitem><para id="x_4ec"><envar role="rc-item-web">contact</envar>:
 28.6658 +	    String.  A free-form (but preferably brief) string
 28.6659 +	    identifying the person or group in charge of the
 28.6660 +	    repository.  This often contains the name and email
 28.6661 +	    address of a person or mailing list.  It often makes sense
 28.6662 +	    to place this entry in a repository's own <filename role="special" moreinfo="none">.hg/hgrc</filename> file, but it can make
 28.6663 +	    sense to use in a global <filename role="special" moreinfo="none">~/.hgrc</filename> if every repository
 28.6664 +	    has a single maintainer.</para>
 28.6665 +	</listitem>
 28.6666 +	<listitem><para id="x_4ed"><envar role="rc-item-web">maxchanges</envar>:
 28.6667 +	    Integer.  The default maximum number of changesets to
 28.6668 +	    display in a single page of output.</para>
 28.6669 +	</listitem>
 28.6670 +	<listitem><para id="x_4ee"><envar role="rc-item-web">maxfiles</envar>:
 28.6671 +	    Integer.  The default maximum number of modified files to
 28.6672 +	    display in a single page of output.</para>
 28.6673 +	</listitem>
 28.6674 +	<listitem><para id="x_4ef"><envar role="rc-item-web">stripes</envar>:
 28.6675 +	    Integer.  If the web interface displays alternating
 28.6676 +	    <quote>stripes</quote> to make it easier to visually align
 28.6677 +	    rows when you are looking at a table, this number controls
 28.6678 +	    the number of rows in each stripe.</para>
 28.6679 +	</listitem>
 28.6680 +	<listitem><para id="x_4f0"><envar role="rc-item-web">style</envar>: Controls the template
 28.6681 +	    Mercurial uses to display the web interface.  Mercurial
 28.6682 +	    ships with several web templates.</para>
 28.6683 +	  <itemizedlist>
 28.6684 +	    <listitem>
 28.6685 +	      <para id="x_6aa"><literal moreinfo="none">coal</literal> is monochromatic.</para>
 28.6686 +	    </listitem>
 28.6687 +	    <listitem>
 28.6688 +	      <para id="x_6ab"><literal moreinfo="none">gitweb</literal> emulates the visual
 28.6689 +		style of git's web interface.</para>
 28.6690 +	    </listitem>
 28.6691 +	    <listitem>
 28.6692 +	      <para id="x_6ac"><literal moreinfo="none">monoblue</literal> uses solid blues and
 28.6693 +		greys.</para>
 28.6694 +	    </listitem>
 28.6695 +	    <listitem>
 28.6696 +	      <para id="x_6ad"><literal moreinfo="none">paper</literal> is the default.</para>
 28.6697 +	    </listitem>
 28.6698 +	    <listitem>
 28.6699 +	      <para id="x_6ae"><literal moreinfo="none">spartan</literal> was the default for a
 28.6700 +		long time.</para>
 28.6701 +	    </listitem>
 28.6702 +	  </itemizedlist>
 28.6703 +	  <para id="x_6af">You can
 28.6704 +	    also specify a custom template of your own; see 
 28.6705 +	    <xref linkend="chap:template"/> for details. Here, you can
 28.6706 +	    see how to enable the <literal moreinfo="none">gitweb</literal>
 28.6707 +	    style.</para>
 28.6708 +	  <programlisting format="linespecific">[web]
 28.6709 +style = gitweb</programlisting>
 28.6710 +	</listitem>
 28.6711 +	<listitem><para id="x_4f1"><envar role="rc-item-web">templates</envar>:
 28.6712 +	    Path.  The directory in which to search for template
 28.6713 +	    files.  By default, Mercurial searches in the directory in
 28.6714 +	    which it was installed.</para>
 28.6715 +	</listitem></itemizedlist>
 28.6716 +      <para id="x_4f2">If you are using <filename role="special" moreinfo="none">hgwebdir.cgi</filename>, you can place a few
 28.6717 +	configuration items in a <literal role="rc-web" moreinfo="none">web</literal>
 28.6718 +	section of the <filename role="special" moreinfo="none">hgweb.config</filename> file instead of a
 28.6719 +	<filename role="special" moreinfo="none">~/.hgrc</filename> file, for
 28.6720 +	convenience.  These items are <envar role="rc-item-web">motd</envar> and <envar role="rc-item-web">style</envar>.</para>
 28.6721 +
 28.6722 +      <sect3>
 28.6723 +	<title>Options specific to an individual repository</title>
 28.6724 +
 28.6725 +	<para id="x_4f3">A few <literal role="rc-web" moreinfo="none">web</literal> configuration
 28.6726 +	  items ought to be placed in a repository's local <filename role="special" moreinfo="none">.hg/hgrc</filename>, rather than a user's
 28.6727 +	  or global <filename role="special" moreinfo="none">~/.hgrc</filename>.</para>
 28.6728 +	<itemizedlist>
 28.6729 +	  <listitem><para id="x_4f4"><envar role="rc-item-web">description</envar>: String.  A
 28.6730 +	      free-form (but preferably brief) string that describes
 28.6731 +	      the contents or purpose of the repository.</para>
 28.6732 +	  </listitem>
 28.6733 +	  <listitem><para id="x_4f5"><envar role="rc-item-web">name</envar>:
 28.6734 +	      String.  The name to use for the repository in the web
 28.6735 +	      interface.  This overrides the default name, which is
 28.6736 +	      the last component of the repository's path.</para>
 28.6737 +	  </listitem></itemizedlist>
 28.6738 +      </sect3>
 28.6739 +
 28.6740 +      <sect3>
 28.6741 +	<title>Options specific to the <command role="hg-cmd" moreinfo="none">hg
 28.6742 +	    serve</command> command</title>
 28.6743 +
 28.6744 +	<para id="x_4f6">Some of the items in the <literal role="rc-web" moreinfo="none">web</literal> section of a <filename role="special" moreinfo="none">~/.hgrc</filename> file are only for use
 28.6745 +	  with the <command role="hg-cmd" moreinfo="none">hg serve</command>
 28.6746 +	  command.</para>
 28.6747 +	<itemizedlist>
 28.6748 +	  <listitem><para id="x_4f7"><envar role="rc-item-web">accesslog</envar>:
 28.6749 +	      Path.  The name of a file into which to write an access
 28.6750 +	      log.  By default, the <command role="hg-cmd" moreinfo="none">hg
 28.6751 +		serve</command> command writes this information to
 28.6752 +	      standard output, not to a file.  Log entries are written
 28.6753 +	      in the standard <quote>combined</quote> file format used
 28.6754 +	      by almost all web servers.</para>
 28.6755 +	  </listitem>
 28.6756 +	  <listitem><para id="x_4f8"><envar role="rc-item-web">address</envar>:
 28.6757 +	      String.  The local address on which the server should
 28.6758 +	      listen for incoming connections.  By default, the server
 28.6759 +	      listens on all addresses.</para>
 28.6760 +	  </listitem>
 28.6761 +	  <listitem><para id="x_4f9"><envar role="rc-item-web">errorlog</envar>:
 28.6762 +	      Path.  The name of a file into which to write an error
 28.6763 +	      log.  By default, the <command role="hg-cmd" moreinfo="none">hg
 28.6764 +		serve</command> command writes this information to
 28.6765 +	      standard error, not to a file.</para>
 28.6766 +	  </listitem>
 28.6767 +	  <listitem><para id="x_4fa"><envar role="rc-item-web">ipv6</envar>:
 28.6768 +	      Boolean.  Whether to use the IPv6 protocol. By default,
 28.6769 +	      IPv6 is not used.</para>
 28.6770 +	  </listitem>
 28.6771 +	  <listitem><para id="x_4fb"><envar role="rc-item-web">port</envar>:
 28.6772 +	      Integer.  The TCP port number on which the server should
 28.6773 +	      listen.  The default port number used is 8000.</para>
 28.6774 +	  </listitem></itemizedlist>
 28.6775 +      </sect3>
 28.6776 +
 28.6777 +      <sect3>
 28.6778 +	<title>Choosing the right <filename role="special" moreinfo="none">~/.hgrc</filename> file to add <literal role="rc-web" moreinfo="none">web</literal> items to</title>
 28.6779 +
 28.6780 +	<para id="x_4fc">It is important to remember that a web server like
 28.6781 +	  Apache or <literal moreinfo="none">lighttpd</literal> will run under a user
 28.6782 +	  ID that is different to yours. CGI scripts run by your
 28.6783 +	  server, such as <filename role="special" moreinfo="none">hgweb.cgi</filename>, will usually also run
 28.6784 +	  under that user ID.</para>
 28.6785 +
 28.6786 +	<para id="x_4fd">If you add <literal role="rc-web" moreinfo="none">web</literal> items to
 28.6787 +	  your own personal <filename role="special" moreinfo="none">~/.hgrc</filename> file, CGI scripts won't read that
 28.6788 +	  <filename role="special" moreinfo="none">~/.hgrc</filename> file.  Those
 28.6789 +	  settings will thus only affect the behavior of the <command role="hg-cmd" moreinfo="none">hg serve</command> command when you run it.
 28.6790 +	  To cause CGI scripts to see your settings, either create a
 28.6791 +	  <filename role="special" moreinfo="none">~/.hgrc</filename> file in the
 28.6792 +	  home directory of the user ID that runs your web server, or
 28.6793 +	  add those settings to a system-wide <filename role="special" moreinfo="none">hgrc</filename> file.</para>
 28.6794 +      </sect3>
 28.6795 +    </sect2>
 28.6796 +  </sect1>
 28.6797 +
 28.6798 +  <sect1>
 28.6799 +    <title>System-wide configuration</title>
 28.6800 +
 28.6801 +    <para id="x_6b0">On Unix-like systems shared by multiple users (such as a
 28.6802 +      server to which people publish changes), it often makes sense to
 28.6803 +      set up some global default behaviors, such as what theme to use
 28.6804 +      in web interfaces.</para>
 28.6805 +
 28.6806 +    <para id="x_6b1">If a file named <filename moreinfo="none">/etc/mercurial/hgrc</filename>
 28.6807 +      exists, Mercurial will read it at startup time and apply any
 28.6808 +      configuration settings it finds in that file.  It will also look
 28.6809 +      for files ending in a <literal moreinfo="none">.rc</literal> extension in a
 28.6810 +      directory named <filename moreinfo="none">/etc/mercurial/hgrc.d</filename>, and
 28.6811 +      apply any configuration settings it finds in each of those
 28.6812 +      files.</para>
 28.6813 +
 28.6814 +    <sect2>
 28.6815 +      <title>Making Mercurial more trusting</title>
 28.6816 +
 28.6817 +      <para id="x_6b2">One situation in which a global <filename moreinfo="none">hgrc</filename>
 28.6818 +	can be useful is if users are pulling changes owned by other
 28.6819 +	users.  By default, Mercurial will not trust most of the
 28.6820 +	configuration items in a <filename moreinfo="none">.hg/hgrc</filename> file
 28.6821 +	inside a repository that is owned by a different user. If we
 28.6822 +	clone or pull changes from such a repository, Mercurial will
 28.6823 +	print a warning stating that it does not trust their
 28.6824 +	<filename moreinfo="none">.hg/hgrc</filename>.</para>
 28.6825 +
 28.6826 +      <para id="x_6b3">If everyone in a particular Unix group is on the same team
 28.6827 +	and <emphasis>should</emphasis> trust each other's
 28.6828 +	configuration settings, or we want to trust particular users,
 28.6829 +	we can override Mercurial's skeptical defaults by creating a
 28.6830 +	system-wide <filename moreinfo="none">hgrc</filename> file such as the
 28.6831 +	following:</para>
 28.6832 +
 28.6833 +    <programlisting format="linespecific"># Save this as e.g. /etc/mercurial/hgrc.d/trust.rc
 28.6834 +[trusted]
 28.6835 +# Trust all entries in any hgrc file owned by the "editors" or
 28.6836 +# "www-data" groups.
 28.6837 +groups = editors, www-data
 28.6838 +
 28.6839 +# Trust entries in hgrc files owned by the following users.
 28.6840 +users = apache, bobo
 28.6841 +</programlisting>
 28.6842 +    </sect2>
 28.6843 +  </sect1>
 28.6844 +</chapter>
 28.6845 +
 28.6846 +<!--
 28.6847 +local variables: 
 28.6848 +sgml-parent-document: ("00book.xml" "book" "chapter")
 28.6849 +end:
 28.6850 +-->
 28.6851 +
 28.6852 +  <!-- BEGIN ch07 -->
 28.6853 +  <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
 28.6854 +
 28.6855 +<chapter id="chap:names">
 28.6856 +  <?dbhtml filename="file-names-and-pattern-matching.html"?>
 28.6857 +  <title>File names and pattern matching</title>
 28.6858 +
 28.6859 +  <para id="x_543">Mercurial provides mechanisms that let you work with file
 28.6860 +    names in a consistent and expressive way.</para>
 28.6861 +
 28.6862 +  <sect1>
 28.6863 +    <title>Simple file naming</title>
 28.6864 +
 28.6865 +    <para id="x_544">Mercurial uses a unified piece of machinery <quote>under the
 28.6866 +	hood</quote> to handle file names.  Every command behaves
 28.6867 +      uniformly with respect to file names.  The way in which commands
 28.6868 +      work with file names is as follows.</para>
 28.6869 +
 28.6870 +    <para id="x_545">If you explicitly name real files on the command line,
 28.6871 +      Mercurial works with exactly those files, as you would expect.
 28.6872 +      <!-- BEGIN filenames.files -->
 28.6873 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add COPYING README examples/simple.py</userinput>
 28.6874 +</screen>
 28.6875 +<!-- END filenames.files -->
 28.6876 +</para>
 28.6877 +
 28.6878 +    <para id="x_546">When you provide a directory name, Mercurial will interpret
 28.6879 +      this as <quote>operate on every file in this directory and its
 28.6880 +	subdirectories</quote>. Mercurial traverses the files and
 28.6881 +      subdirectories in a directory in alphabetical order.  When it
 28.6882 +      encounters a subdirectory, it will traverse that subdirectory
 28.6883 +      before continuing with the current directory.</para>
 28.6884 +
 28.6885 +      <!-- BEGIN filenames.dirs -->
 28.6886 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status src</userinput>
 28.6887 +? src/main.py
 28.6888 +? src/watcher/_watcher.c
 28.6889 +? src/watcher/watcher.py
 28.6890 +? src/xyzzy.txt
 28.6891 +</screen>
 28.6892 +<!-- END filenames.dirs -->
 28.6893 +
 28.6894 +  </sect1>
 28.6895 +
 28.6896 +  <sect1>
 28.6897 +    <title>Running commands without any file names</title>
 28.6898 +
 28.6899 +    <para id="x_547">Mercurial's commands that work with file names have useful
 28.6900 +      default behaviors when you invoke them without providing any
 28.6901 +      file names or patterns.  What kind of behavior you should
 28.6902 +      expect depends on what the command does.  Here are a few rules
 28.6903 +      of thumb you can use to predict what a command is likely to do
 28.6904 +      if you don't give it any names to work with.</para>
 28.6905 +    <itemizedlist>
 28.6906 +      <listitem><para id="x_548">Most commands will operate on the entire working
 28.6907 +	  directory. This is what the <command role="hg-cmd" moreinfo="none">hg
 28.6908 +	    add</command> command does, for example.</para>
 28.6909 +      </listitem>
 28.6910 +      <listitem><para id="x_549">If the command has effects that are difficult or
 28.6911 +	  impossible to reverse, it will force you to explicitly
 28.6912 +	  provide at least one name or pattern (see below).  This
 28.6913 +	  protects you from accidentally deleting files by running
 28.6914 +	  <command role="hg-cmd" moreinfo="none">hg remove</command> with no
 28.6915 +	  arguments, for example.</para>
 28.6916 +      </listitem></itemizedlist>
 28.6917 +
 28.6918 +    <para id="x_54a">It's easy to work around these default behaviors if they
 28.6919 +      don't suit you.  If a command normally operates on the whole
 28.6920 +      working directory, you can invoke it on just the current
 28.6921 +      directory and its subdirectories by giving it the name
 28.6922 +      <quote><filename class="directory" moreinfo="none">.</filename></quote>.</para>
 28.6923 +
 28.6924 +    <!-- BEGIN filenames.wdir-subdir -->
 28.6925 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd src</userinput>
 28.6926 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add -n</userinput>
 28.6927 +adding ../MANIFEST.in
 28.6928 +adding ../examples/performant.py
 28.6929 +adding ../setup.py
 28.6930 +adding main.py
 28.6931 +adding watcher/_watcher.c
 28.6932 +adding watcher/watcher.py
 28.6933 +adding xyzzy.txt
 28.6934 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add -n .</userinput>
 28.6935 +adding main.py
 28.6936 +adding watcher/_watcher.c
 28.6937 +adding watcher/watcher.py
 28.6938 +adding xyzzy.txt
 28.6939 +</screen>
 28.6940 +<!-- END filenames.wdir-subdir -->
 28.6941 +
 28.6942 +
 28.6943 +    <para id="x_54b">Along the same lines, some commands normally print file
 28.6944 +      names relative to the root of the repository, even if you're
 28.6945 +      invoking them from a subdirectory.  Such a command will print
 28.6946 +      file names relative to your subdirectory if you give it explicit
 28.6947 +      names.  Here, we're going to run <command role="hg-cmd" moreinfo="none">hg
 28.6948 +	status</command> from a subdirectory, and get it to operate on
 28.6949 +      the entire working directory while printing file names relative
 28.6950 +      to our subdirectory, by passing it the output of the <command role="hg-cmd" moreinfo="none">hg root</command> command.</para>
 28.6951 +
 28.6952 +      <!-- BEGIN filenames.wdir-relname -->
 28.6953 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
 28.6954 +A COPYING
 28.6955 +A README
 28.6956 +A examples/simple.py
 28.6957 +? MANIFEST.in
 28.6958 +? examples/performant.py
 28.6959 +? setup.py
 28.6960 +? src/main.py
 28.6961 +? src/watcher/_watcher.c
 28.6962 +? src/watcher/watcher.py
 28.6963 +? src/xyzzy.txt
 28.6964 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status `hg root`</userinput>
 28.6965 +A ../COPYING
 28.6966 +A ../README
 28.6967 +A ../examples/simple.py
 28.6968 +? ../MANIFEST.in
 28.6969 +? ../examples/performant.py
 28.6970 +? ../setup.py
 28.6971 +? main.py
 28.6972 +? watcher/_watcher.c
 28.6973 +? watcher/watcher.py
 28.6974 +? xyzzy.txt
 28.6975 +</screen>
 28.6976 +<!-- END filenames.wdir-relname -->
 28.6977 +
 28.6978 +  </sect1>
 28.6979 +
 28.6980 +  <sect1>
 28.6981 +    <title>Telling you what's going on</title>
 28.6982 +
 28.6983 +    <para id="x_54c">The <command role="hg-cmd" moreinfo="none">hg add</command> example in the
 28.6984 +      preceding section illustrates something else that's helpful
 28.6985 +      about Mercurial commands.  If a command operates on a file that
 28.6986 +      you didn't name explicitly on the command line, it will usually
 28.6987 +      print the name of the file, so that you will not be surprised
 28.6988 +      what's going on.</para>
 28.6989 +
 28.6990 +    <para id="x_54d">The principle here is of <emphasis>least
 28.6991 +	surprise</emphasis>.  If you've exactly named a file on the
 28.6992 +      command line, there's no point in repeating it back at you.  If
 28.6993 +      Mercurial is acting on a file <emphasis>implicitly</emphasis>, e.g.
 28.6994 +      because you provided no names, or a directory, or a pattern (see
 28.6995 +      below), it is safest to tell you what files it's operating on.</para>
 28.6996 +
 28.6997 +    <para id="x_54e">For commands that behave this way, you can silence them
 28.6998 +      using the <option role="hg-opt-global">-q</option> option.  You
 28.6999 +      can also get them to print the name of every file, even those
 28.7000 +      you've named explicitly, using the <option role="hg-opt-global">-v</option> option.</para>
 28.7001 +  </sect1>
 28.7002 +
 28.7003 +  <sect1>
 28.7004 +    <title>Using patterns to identify files</title>
 28.7005 +
 28.7006 +    <para id="x_54f">In addition to working with file and directory names,
 28.7007 +      Mercurial lets you use <emphasis>patterns</emphasis> to identify
 28.7008 +      files.  Mercurial's pattern handling is expressive.</para>
 28.7009 +
 28.7010 +    <para id="x_550">On Unix-like systems (Linux, MacOS, etc.), the job of
 28.7011 +      matching file names to patterns normally falls to the shell.  On
 28.7012 +      these systems, you must explicitly tell Mercurial that a name is
 28.7013 +      a pattern.  On Windows, the shell does not expand patterns, so
 28.7014 +      Mercurial will automatically identify names that are patterns,
 28.7015 +      and expand them for you.</para>
 28.7016 +
 28.7017 +    <para id="x_551">To provide a pattern in place of a regular name on the
 28.7018 +      command line, the mechanism is simple:</para>
 28.7019 +    <programlisting format="linespecific">syntax:patternbody</programlisting>
 28.7020 +    <para id="x_552">That is, a pattern is identified by a short text string that
 28.7021 +      says what kind of pattern this is, followed by a colon, followed
 28.7022 +      by the actual pattern.</para>
 28.7023 +
 28.7024 +    <para id="x_553">Mercurial supports two kinds of pattern syntax.  The most
 28.7025 +      frequently used is called <literal moreinfo="none">glob</literal>; this is the
 28.7026 +      same kind of pattern matching used by the Unix shell, and should
 28.7027 +      be familiar to Windows command prompt users, too.</para>
 28.7028 +
 28.7029 +    <para id="x_554">When Mercurial does automatic pattern matching on Windows,
 28.7030 +      it uses <literal moreinfo="none">glob</literal> syntax.  You can thus omit the
 28.7031 +      <quote><literal moreinfo="none">glob:</literal></quote> prefix on Windows, but
 28.7032 +      it's safe to use it, too.</para>
 28.7033 +
 28.7034 +    <para id="x_555">The <literal moreinfo="none">re</literal> syntax is more powerful; it lets
 28.7035 +      you specify patterns using regular expressions, also known as
 28.7036 +      regexps.</para>
 28.7037 +
 28.7038 +    <para id="x_556">By the way, in the examples that follow, notice that I'm
 28.7039 +      careful to wrap all of my patterns in quote characters, so that
 28.7040 +      they won't get expanded by the shell before Mercurial sees
 28.7041 +      them.</para>
 28.7042 +
 28.7043 +    <sect2>
 28.7044 +      <title>Shell-style <literal moreinfo="none">glob</literal> patterns</title>
 28.7045 +
 28.7046 +      <para id="x_557">This is an overview of the kinds of patterns you can use
 28.7047 +	when you're matching on glob patterns.</para>
 28.7048 +
 28.7049 +      <para id="x_558">The <quote><literal moreinfo="none">*</literal></quote> character matches
 28.7050 +	any string, within a single directory.</para>
 28.7051 +
 28.7052 +      <!-- BEGIN filenames.glob.star -->
 28.7053 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add 'glob:*.py'</userinput>
 28.7054 +adding main.py
 28.7055 +</screen>
 28.7056 +<!-- END filenames.glob.star -->
 28.7057 +
 28.7058 +
 28.7059 +      <para id="x_559">The <quote><literal moreinfo="none">**</literal></quote> pattern matches
 28.7060 +	any string, and crosses directory boundaries.  It's not a
 28.7061 +	standard Unix glob token, but it's accepted by several popular
 28.7062 +	Unix shells, and is very useful.</para>
 28.7063 +
 28.7064 +      <!-- BEGIN filenames.glob.starstar -->
 28.7065 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput>
 28.7066 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status 'glob:**.py'</userinput>
 28.7067 +A examples/simple.py
 28.7068 +A src/main.py
 28.7069 +? examples/performant.py
 28.7070 +? setup.py
 28.7071 +? src/watcher/watcher.py
 28.7072 +</screen>
 28.7073 +<!-- END filenames.glob.starstar -->
 28.7074 +
 28.7075 +
 28.7076 +      <para id="x_55a">The <quote><literal moreinfo="none">?</literal></quote> pattern matches
 28.7077 +	any single character.</para>
 28.7078 +
 28.7079 +      <!-- BEGIN filenames.glob.question -->
 28.7080 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status 'glob:**.?'</userinput>
 28.7081 +? src/watcher/_watcher.c
 28.7082 +</screen>
 28.7083 +<!-- END filenames.glob.question -->
 28.7084 +
 28.7085 +
 28.7086 +      <para id="x_55b">The <quote><literal moreinfo="none">[</literal></quote> character begins a
 28.7087 +	<emphasis>character class</emphasis>.  This matches any single
 28.7088 +	character within the class.  The class ends with a
 28.7089 +	<quote><literal moreinfo="none">]</literal></quote> character.  A class may
 28.7090 +	contain multiple <emphasis>range</emphasis>s of the form
 28.7091 +	<quote><literal moreinfo="none">a-f</literal></quote>, which is shorthand for
 28.7092 +	<quote><literal moreinfo="none">abcdef</literal></quote>.</para>
 28.7093 +
 28.7094 +	<!-- BEGIN filenames.glob.range -->
 28.7095 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status 'glob:**[nr-t]'</userinput>
 28.7096 +? MANIFEST.in
 28.7097 +? src/xyzzy.txt
 28.7098 +</screen>
 28.7099 +<!-- END filenames.glob.range -->
 28.7100 +
 28.7101 +
 28.7102 +      <para id="x_55c">If the first character after the
 28.7103 +	<quote><literal moreinfo="none">[</literal></quote> in a character class is a
 28.7104 +	<quote><literal moreinfo="none">!</literal></quote>, it
 28.7105 +	<emphasis>negates</emphasis> the class, making it match any
 28.7106 +	single character not in the class.</para>
 28.7107 +
 28.7108 +      <para id="x_55d">A <quote><literal moreinfo="none">{</literal></quote> begins a group of
 28.7109 +	subpatterns, where the whole group matches if any subpattern
 28.7110 +	in the group matches.  The <quote><literal moreinfo="none">,</literal></quote>
 28.7111 +	character separates subpatterns, and
 28.7112 +	<quote><literal moreinfo="none">}</literal></quote> ends the group.</para>
 28.7113 +
 28.7114 +      <!-- BEGIN filenames.glob.group -->
 28.7115 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status 'glob:*.{in,py}'</userinput>
 28.7116 +? MANIFEST.in
 28.7117 +? setup.py
 28.7118 +</screen>
 28.7119 +<!-- END filenames.glob.group -->
 28.7120 +
 28.7121 +
 28.7122 +      <sect3>
 28.7123 +	<title>Watch out!</title>
 28.7124 +
 28.7125 +	<para id="x_55e">Don't forget that if you want to match a pattern in any
 28.7126 +	  directory, you should not be using the
 28.7127 +	  <quote><literal moreinfo="none">*</literal></quote> match-any token, as this
 28.7128 +	  will only match within one directory.  Instead, use the
 28.7129 +	  <quote><literal moreinfo="none">**</literal></quote> token.  This small
 28.7130 +	  example illustrates the difference between the two.</para>
 28.7131 +
 28.7132 +	  <!-- BEGIN filenames.glob.star-starstar -->
 28.7133 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status 'glob:*.py'</userinput>
 28.7134 +? setup.py
 28.7135 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status 'glob:**.py'</userinput>
 28.7136 +A examples/simple.py
 28.7137 +A src/main.py
 28.7138 +? examples/performant.py
 28.7139 +? setup.py
 28.7140 +? src/watcher/watcher.py
 28.7141 +</screen>
 28.7142 +<!-- END filenames.glob.star-starstar -->
 28.7143 +
 28.7144 +      </sect3>
 28.7145 +    </sect2>
 28.7146 +
 28.7147 +    <sect2>
 28.7148 +      <title>Regular expression matching with <literal moreinfo="none">re</literal>
 28.7149 +	patterns</title>
 28.7150 +
 28.7151 +      <para id="x_55f">Mercurial accepts the same regular expression syntax as
 28.7152 +	the Python programming language (it uses Python's regexp
 28.7153 +	engine internally). This is based on the Perl language's
 28.7154 +	regexp syntax, which is the most popular dialect in use (it's
 28.7155 +	also used in Java, for example).</para>
 28.7156 +
 28.7157 +      <para id="x_560">I won't discuss Mercurial's regexp dialect in any detail
 28.7158 +	here, as regexps are not often used.  Perl-style regexps are
 28.7159 +	in any case already exhaustively documented on a multitude of
 28.7160 +	web sites, and in many books.  Instead, I will focus here on a
 28.7161 +	few things you should know if you find yourself needing to use
 28.7162 +	regexps with Mercurial.</para>
 28.7163 +
 28.7164 +      <para id="x_561">A regexp is matched against an entire file name, relative
 28.7165 +	to the root of the repository.  In other words, even if you're
 28.7166 +	already in subbdirectory <filename class="directory" moreinfo="none">foo</filename>, if you want to match files
 28.7167 +	under this directory, your pattern must start with
 28.7168 +	<quote><literal moreinfo="none">foo/</literal></quote>.</para>
 28.7169 +
 28.7170 +      <para id="x_562">One thing to note, if you're familiar with Perl-style
 28.7171 +	regexps, is that Mercurial's are <emphasis>rooted</emphasis>.
 28.7172 +	That is, a regexp starts matching against the beginning of a
 28.7173 +	string; it doesn't look for a match anywhere within the
 28.7174 +	string.  To match anywhere in a string, start your pattern
 28.7175 +	with <quote><literal moreinfo="none">.*</literal></quote>.</para>
 28.7176 +    </sect2>
 28.7177 +  </sect1>
 28.7178 +
 28.7179 +  <sect1>
 28.7180 +    <title>Filtering files</title>
 28.7181 +
 28.7182 +    <para id="x_563">Not only does Mercurial give you a variety of ways to
 28.7183 +      specify files; it lets you further winnow those files using
 28.7184 +      <emphasis>filters</emphasis>.  Commands that work with file
 28.7185 +      names accept two filtering options.</para>
 28.7186 +    <itemizedlist>
 28.7187 +      <listitem><para id="x_564"><option role="hg-opt-global">-I</option>, or
 28.7188 +	  <option role="hg-opt-global">--include</option>, lets you
 28.7189 +	  specify a pattern that file names must match in order to be
 28.7190 +	  processed.</para>
 28.7191 +      </listitem>
 28.7192 +      <listitem><para id="x_565"><option role="hg-opt-global">-X</option>, or
 28.7193 +	  <option role="hg-opt-global">--exclude</option>, gives you a
 28.7194 +	  way to <emphasis>avoid</emphasis> processing files, if they
 28.7195 +	  match this pattern.</para>
 28.7196 +      </listitem></itemizedlist>
 28.7197 +    <para id="x_566">You can provide multiple <option role="hg-opt-global">-I</option> and <option role="hg-opt-global">-X</option> options on the command line,
 28.7198 +      and intermix them as you please.  Mercurial interprets the
 28.7199 +      patterns you provide using glob syntax by default (but you can
 28.7200 +      use regexps if you need to).</para>
 28.7201 +
 28.7202 +    <para id="x_567">You can read a <option role="hg-opt-global">-I</option>
 28.7203 +      filter as <quote>process only the files that match this
 28.7204 +	filter</quote>.</para>
 28.7205 +
 28.7206 +    <!-- BEGIN filenames.filter.include -->
 28.7207 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status -I '*.in'</userinput>
 28.7208 +? MANIFEST.in
 28.7209 +</screen>
 28.7210 +<!-- END filenames.filter.include -->
 28.7211 +
 28.7212 +
 28.7213 +    <para id="x_568">The <option role="hg-opt-global">-X</option> filter is best
 28.7214 +      read as <quote>process only the files that don't match this
 28.7215 +	pattern</quote>.</para>
 28.7216 +
 28.7217 +    <!-- BEGIN filenames.filter.exclude -->
 28.7218 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status -X '**.py' src</userinput>
 28.7219 +? src/watcher/_watcher.c
 28.7220 +? src/xyzzy.txt
 28.7221 +</screen>
 28.7222 +<!-- END filenames.filter.exclude -->
 28.7223 +
 28.7224 +  </sect1>
 28.7225 +
 28.7226 +  <sect1>
 28.7227 +    <title>Permanently ignoring unwanted files and directories</title>
 28.7228 +
 28.7229 +    <para id="x_569">When you create a new repository, the chances are
 28.7230 +      that over time it will grow to contain files that ought to
 28.7231 +      <emphasis>not</emphasis> be managed by Mercurial, but which you
 28.7232 +      don't want to see listed every time you run <command moreinfo="none">hg
 28.7233 +	status</command>.  For instance, <quote>build products</quote>
 28.7234 +      are files that are created as part of a build but which should
 28.7235 +      not be managed by a revision control system.  The most common
 28.7236 +      build products are output files produced by software tools such
 28.7237 +      as compilers.  As another example, many text editors litter a
 28.7238 +      directory with lock files, temporary working files, and backup
 28.7239 +      files, which it also makes no sense to manage.</para>
 28.7240 +
 28.7241 +    <para id="x_6b4">To have Mercurial permanently ignore such files, create a
 28.7242 +      file named <filename moreinfo="none">.hgignore</filename> in the root of your
 28.7243 +      repository.  You <emphasis>should</emphasis> <command moreinfo="none">hg
 28.7244 +      add</command> this file so that it gets tracked with the rest of
 28.7245 +      your repository contents, since your collaborators will probably
 28.7246 +      find it useful too.</para>
 28.7247 +
 28.7248 +    <para id="x_6b5">By default, the <filename moreinfo="none">.hgignore</filename> file should
 28.7249 +      contain a list of regular expressions, one per line.  Empty
 28.7250 +      lines are skipped. Most people prefer to describe the files they
 28.7251 +      want to ignore using the <quote>glob</quote> syntax that we
 28.7252 +      described above, so a typical <filename moreinfo="none">.hgignore</filename>
 28.7253 +      file will start with this directive:</para>
 28.7254 +
 28.7255 +    <programlisting format="linespecific">syntax: glob</programlisting>
 28.7256 +
 28.7257 +    <para id="x_6b6">This tells Mercurial to interpret the lines that follow as
 28.7258 +      glob patterns, not regular expressions.</para>
 28.7259 +
 28.7260 +    <para id="x_6b7">Here is a typical-looking <filename moreinfo="none">.hgignore</filename>
 28.7261 +      file.</para>
 28.7262 +
 28.7263 +    <programlisting format="linespecific">syntax: glob
 28.7264 +# This line is a comment, and will be skipped.
 28.7265 +# Empty lines are skipped too.
 28.7266 +
 28.7267 +# Backup files left behind by the Emacs editor.
 28.7268 +*~
 28.7269 +
 28.7270 +# Lock files used by the Emacs editor.
 28.7271 +# Notice that the "#" character is quoted with a backslash.
 28.7272 +# This prevents it from being interpreted as starting a comment.
 28.7273 +.\#*
 28.7274 +
 28.7275 +# Temporary files used by the vim editor.
 28.7276 +.*.swp
 28.7277 +
 28.7278 +# A hidden file created by the Mac OS X Finder.
 28.7279 +.DS_Store
 28.7280 +</programlisting>
 28.7281 +  </sect1>
 28.7282 +
 28.7283 +  <sect1 id="sec:names:case">
 28.7284 +    <title>Case sensitivity</title>
 28.7285 +
 28.7286 +    <para id="x_56a">If you're working in a mixed development environment that
 28.7287 +      contains both Linux (or other Unix) systems and Macs or Windows
 28.7288 +      systems, you should keep in the back of your mind the knowledge
 28.7289 +      that they treat the case (<quote>N</quote> versus
 28.7290 +      <quote>n</quote>) of file names in incompatible ways.  This is
 28.7291 +      not very likely to affect you, and it's easy to deal with if it
 28.7292 +      does, but it could surprise you if you don't know about
 28.7293 +      it.</para>
 28.7294 +
 28.7295 +    <para id="x_56b">Operating systems and filesystems differ in the way they
 28.7296 +      handle the <emphasis>case</emphasis> of characters in file and
 28.7297 +      directory names.  There are three common ways to handle case in
 28.7298 +      names.</para>
 28.7299 +    <itemizedlist>
 28.7300 +      <listitem><para id="x_56c">Completely case insensitive.  Uppercase and
 28.7301 +	  lowercase versions of a letter are treated as identical,
 28.7302 +	  both when creating a file and during subsequent accesses.
 28.7303 +	  This is common on older DOS-based systems.</para>
 28.7304 +      </listitem>
 28.7305 +      <listitem><para id="x_56d">Case preserving, but insensitive.  When a file
 28.7306 +	  or directory is created, the case of its name is stored, and
 28.7307 +	  can be retrieved and displayed by the operating system.
 28.7308 +	  When an existing file is being looked up, its case is
 28.7309 +	  ignored.  This is the standard arrangement on Windows and
 28.7310 +	  MacOS.  The names <filename moreinfo="none">foo</filename> and
 28.7311 +	  <filename moreinfo="none">FoO</filename> identify the same file.  This
 28.7312 +	  treatment of uppercase and lowercase letters as
 28.7313 +	  interchangeable is also referred to as <emphasis>case
 28.7314 +	    folding</emphasis>.</para>
 28.7315 +      </listitem>
 28.7316 +      <listitem><para id="x_56e">Case sensitive.  The case of a name
 28.7317 +	  is significant at all times. The names
 28.7318 +	  <filename moreinfo="none">foo</filename> and <filename moreinfo="none">FoO</filename>
 28.7319 +	  identify different files.  This is the way Linux and Unix
 28.7320 +	  systems normally work.</para>
 28.7321 +      </listitem></itemizedlist>
 28.7322 +
 28.7323 +    <para id="x_56f">On Unix-like systems, it is possible to have any or all of
 28.7324 +      the above ways of handling case in action at once.  For example,
 28.7325 +      if you use a USB thumb drive formatted with a FAT32 filesystem
 28.7326 +      on a Linux system, Linux will handle names on that filesystem in
 28.7327 +      a case preserving, but insensitive, way.</para>
 28.7328 +
 28.7329 +    <sect2>
 28.7330 +      <title>Safe, portable repository storage</title>
 28.7331 +
 28.7332 +      <para id="x_570">Mercurial's repository storage mechanism is <emphasis>case
 28.7333 +	  safe</emphasis>.  It translates file names so that they can
 28.7334 +	be safely stored on both case sensitive and case insensitive
 28.7335 +	filesystems.  This means that you can use normal file copying
 28.7336 +	tools to transfer a Mercurial repository onto, for example, a
 28.7337 +	USB thumb drive, and safely move that drive and repository
 28.7338 +	back and forth between a Mac, a PC running Windows, and a
 28.7339 +	Linux box.</para>
 28.7340 +
 28.7341 +    </sect2>
 28.7342 +    <sect2>
 28.7343 +      <title>Detecting case conflicts</title>
 28.7344 +
 28.7345 +      <para id="x_571">When operating in the working directory, Mercurial honours
 28.7346 +	the naming policy of the filesystem where the working
 28.7347 +	directory is located.  If the filesystem is case preserving,
 28.7348 +	but insensitive, Mercurial will treat names that differ only
 28.7349 +	in case as the same.</para>
 28.7350 +
 28.7351 +      <para id="x_572">An important aspect of this approach is that it is
 28.7352 +	possible to commit a changeset on a case sensitive (typically
 28.7353 +	Linux or Unix) filesystem that will cause trouble for users on
 28.7354 +	case insensitive (usually Windows and MacOS) users.  If a
 28.7355 +	Linux user commits changes to two files, one named
 28.7356 +	<filename moreinfo="none">myfile.c</filename> and the other named
 28.7357 +	<filename moreinfo="none">MyFile.C</filename>, they will be stored correctly
 28.7358 +	in the repository.  And in the working directories of other
 28.7359 +	Linux users, they will be correctly represented as separate
 28.7360 +	files.</para>
 28.7361 +
 28.7362 +      <para id="x_573">If a Windows or Mac user pulls this change, they will not
 28.7363 +	initially have a problem, because Mercurial's repository
 28.7364 +	storage mechanism is case safe.  However, once they try to
 28.7365 +	<command role="hg-cmd" moreinfo="none">hg update</command> the working
 28.7366 +	directory to that changeset, or <command role="hg-cmd" moreinfo="none">hg
 28.7367 +	  merge</command> with that changeset, Mercurial will spot the
 28.7368 +	conflict between the two file names that the filesystem would
 28.7369 +	treat as the same, and forbid the update or merge from
 28.7370 +	occurring.</para>
 28.7371 +    </sect2>
 28.7372 +
 28.7373 +    <sect2>
 28.7374 +      <title>Fixing a case conflict</title>
 28.7375 +
 28.7376 +      <para id="x_574">If you are using Windows or a Mac in a mixed environment
 28.7377 +	where some of your collaborators are using Linux or Unix, and
 28.7378 +	Mercurial reports a case folding conflict when you try to
 28.7379 +	<command role="hg-cmd" moreinfo="none">hg update</command> or <command role="hg-cmd" moreinfo="none">hg merge</command>, the procedure to fix the
 28.7380 +	problem is simple.</para>
 28.7381 +
 28.7382 +      <para id="x_575">Just find a nearby Linux or Unix box, clone the problem
 28.7383 +	repository onto it, and use Mercurial's <command role="hg-cmd" moreinfo="none">hg rename</command> command to change the
 28.7384 +	names of any offending files or directories so that they will
 28.7385 +	no longer cause case folding conflicts.  Commit this change,
 28.7386 +	<command role="hg-cmd" moreinfo="none">hg pull</command> or <command role="hg-cmd" moreinfo="none">hg push</command> it across to your Windows or
 28.7387 +	MacOS system, and <command role="hg-cmd" moreinfo="none">hg update</command>
 28.7388 +	to the revision with the non-conflicting names.</para>
 28.7389 +
 28.7390 +      <para id="x_576">The changeset with case-conflicting names will remain in
 28.7391 +	your project's history, and you still won't be able to
 28.7392 +	<command role="hg-cmd" moreinfo="none">hg update</command> your working
 28.7393 +	directory to that changeset on a Windows or MacOS system, but
 28.7394 +	you can continue development unimpeded.</para>
 28.7395 +    </sect2>
 28.7396 +  </sect1>
 28.7397 +</chapter>
 28.7398 +
 28.7399 +<!--
 28.7400 +local variables: 
 28.7401 +sgml-parent-document: ("00book.xml" "book" "chapter")
 28.7402 +end:
 28.7403 +-->
 28.7404 +
 28.7405 +  <!-- BEGIN ch08 -->
 28.7406 +  <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
 28.7407 +
 28.7408 +<chapter id="chap:branch">
 28.7409 +  <?dbhtml filename="managing-releases-and-branchy-development.html"?>
 28.7410 +  <title>Managing releases and branchy development</title>
 28.7411 +
 28.7412 +  <para id="x_369">Mercurial provides several mechanisms for you to manage a
 28.7413 +    project that is making progress on multiple fronts at once.  To
 28.7414 +    understand these mechanisms, let's first take a brief look at a
 28.7415 +    fairly normal software project structure.</para>
 28.7416 +
 28.7417 +  <para id="x_36a">Many software projects issue periodic <quote>major</quote>
 28.7418 +    releases that contain substantial new features.  In parallel, they
 28.7419 +    may issue <quote>minor</quote> releases.  These are usually
 28.7420 +    identical to the major releases off which they're based, but with
 28.7421 +    a few bugs fixed.</para>
 28.7422 +
 28.7423 +  <para id="x_36b">In this chapter, we'll start by talking about how to keep
 28.7424 +    records of project milestones such as releases.  We'll then
 28.7425 +    continue on to talk about the flow of work between different
 28.7426 +    phases of a project, and how Mercurial can help you to isolate and
 28.7427 +    manage this work.</para>
 28.7428 +
 28.7429 +  <sect1>
 28.7430 +    <title>Giving a persistent name to a revision</title>
 28.7431 +
 28.7432 +    <para id="x_36c">Once you decide that you'd like to call a particular
 28.7433 +      revision a <quote>release</quote>, it's a good idea to record
 28.7434 +      the identity of that revision. This will let you reproduce that
 28.7435 +      release at a later date, for whatever purpose you might need at
 28.7436 +      the time (reproducing a bug, porting to a new platform, etc).
 28.7437 +      <!-- BEGIN tag.init -->
 28.7438 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init mytag</userinput>
 28.7439 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd mytag</userinput>
 28.7440 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo hello &gt; myfile</userinput>
 28.7441 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'Initial commit'</userinput>
 28.7442 +adding myfile
 28.7443 +</screen>
 28.7444 +<!-- END tag.init -->
 28.7445 +</para>
 28.7446 +
 28.7447 +    <para id="x_36d">Mercurial lets you give a permanent name to any revision
 28.7448 +      using the <command role="hg-cmd" moreinfo="none">hg tag</command> command.  Not
 28.7449 +      surprisingly, these names are called <quote>tags</quote>.</para>
 28.7450 +
 28.7451 +    <!-- BEGIN tag.tag -->
 28.7452 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tag v1.0</userinput>
 28.7453 +</screen>
 28.7454 +<!-- END tag.tag -->
 28.7455 +
 28.7456 +
 28.7457 +    <para id="x_36e">A tag is nothing more than a <quote>symbolic name</quote>
 28.7458 +      for a revision.  Tags exist purely for your convenience, so that
 28.7459 +      you have a handy permanent way to refer to a revision; Mercurial
 28.7460 +      doesn't interpret the tag names you use in any way.  Neither
 28.7461 +      does Mercurial place any restrictions on the name of a tag,
 28.7462 +      beyond a few that are necessary to ensure that a tag can be
 28.7463 +      parsed unambiguously.  A tag name cannot contain any of the
 28.7464 +      following characters:</para>
 28.7465 +    <itemizedlist>
 28.7466 +      <listitem><para id="x_36f">Colon (ASCII 58,
 28.7467 +	  <quote><literal moreinfo="none">:</literal></quote>)</para>
 28.7468 +      </listitem>
 28.7469 +      <listitem><para id="x_370">Carriage return (ASCII 13,
 28.7470 +	  <quote><literal moreinfo="none">\r</literal></quote>)</para>
 28.7471 +      </listitem>
 28.7472 +      <listitem><para id="x_371">Newline (ASCII 10,
 28.7473 +	  <quote><literal moreinfo="none">\n</literal></quote>)</para>
 28.7474 +      </listitem></itemizedlist>
 28.7475 +
 28.7476 +    <para id="x_372">You can use the <command role="hg-cmd" moreinfo="none">hg tags</command>
 28.7477 +      command to display the tags present in your repository.  In the
 28.7478 +      output, each tagged revision is identified first by its name,
 28.7479 +      then by revision number, and finally by the unique hash of the
 28.7480 +      revision.</para>
 28.7481 +
 28.7482 +    <!-- BEGIN tag.tags -->
 28.7483 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tags</userinput>
 28.7484 +tip                                1:f283c2669b38
 28.7485 +v1.0                               0:0c957785065f
 28.7486 +</screen>
 28.7487 +<!-- END tag.tags -->
 28.7488 +
 28.7489 +
 28.7490 +    <para id="x_373">Notice that <literal moreinfo="none">tip</literal> is listed in the output
 28.7491 +      of <command role="hg-cmd" moreinfo="none">hg tags</command>.  The
 28.7492 +      <literal moreinfo="none">tip</literal> tag is a special <quote>floating</quote>
 28.7493 +      tag, which always identifies the newest revision in the
 28.7494 +      repository.</para>
 28.7495 +
 28.7496 +    <para id="x_374">In the output of the <command role="hg-cmd" moreinfo="none">hg
 28.7497 +	tags</command> command, tags are listed in reverse order, by
 28.7498 +      revision number.  This usually means that recent tags are listed
 28.7499 +      before older tags.  It also means that <literal moreinfo="none">tip</literal> is
 28.7500 +      always going to be the first tag listed in the output of
 28.7501 +      <command role="hg-cmd" moreinfo="none">hg tags</command>.</para>
 28.7502 +
 28.7503 +    <para id="x_375">When you run <command role="hg-cmd" moreinfo="none">hg log</command>, if it
 28.7504 +      displays a revision that has tags associated with it, it will
 28.7505 +      print those tags.</para>
 28.7506 +
 28.7507 +    <!-- BEGIN tag.log -->
 28.7508 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log</userinput>
 28.7509 +changeset:   1:f283c2669b38
 28.7510 +tag:         tip
 28.7511 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.7512 +date:        Sun Aug 16 14:05:16 2009 +0000
 28.7513 +summary:     Added tag v1.0 for changeset 0c957785065f
 28.7514 +
 28.7515 +changeset:   0:0c957785065f
 28.7516 +tag:         v1.0
 28.7517 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.7518 +date:        Sun Aug 16 14:05:15 2009 +0000
 28.7519 +summary:     Initial commit
 28.7520 +
 28.7521 +</screen>
 28.7522 +<!-- END tag.log -->
 28.7523 +
 28.7524 +
 28.7525 +    <para id="x_376">Any time you need to provide a revision ID to a Mercurial
 28.7526 +      command, the command will accept a tag name in its place.
 28.7527 +      Internally, Mercurial will translate your tag name into the
 28.7528 +      corresponding revision ID, then use that.</para>
 28.7529 +
 28.7530 +    <!-- BEGIN tag.log.v1.0 -->
 28.7531 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo goodbye &gt; myfile2</userinput>
 28.7532 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'Second commit'</userinput>
 28.7533 +adding myfile2
 28.7534 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r v1.0</userinput>
 28.7535 +changeset:   0:0c957785065f
 28.7536 +tag:         v1.0
 28.7537 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.7538 +date:        Sun Aug 16 14:05:15 2009 +0000
 28.7539 +summary:     Initial commit
 28.7540 +
 28.7541 +</screen>
 28.7542 +<!-- END tag.log.v1.0 -->
 28.7543 +
 28.7544 +
 28.7545 +    <para id="x_377">There's no limit on the number of tags you can have in a
 28.7546 +      repository, or on the number of tags that a single revision can
 28.7547 +      have.  As a practical matter, it's not a great idea to have
 28.7548 +      <quote>too many</quote> (a number which will vary from project
 28.7549 +      to project), simply because tags are supposed to help you to
 28.7550 +      find revisions.  If you have lots of tags, the ease of using
 28.7551 +      them to identify revisions diminishes rapidly.</para>
 28.7552 +
 28.7553 +    <para id="x_378">For example, if your project has milestones as frequent as
 28.7554 +      every few days, it's perfectly reasonable to tag each one of
 28.7555 +      those.  But if you have a continuous build system that makes
 28.7556 +      sure every revision can be built cleanly, you'd be introducing a
 28.7557 +      lot of noise if you were to tag every clean build.  Instead, you
 28.7558 +      could tag failed builds (on the assumption that they're rare!),
 28.7559 +      or simply not use tags to track buildability.</para>
 28.7560 +
 28.7561 +    <para id="x_379">If you want to remove a tag that you no longer want, use
 28.7562 +      <command role="hg-cmd" moreinfo="none">hg tag --remove</command>.</para>
 28.7563 +
 28.7564 +    <!-- BEGIN tag.remove -->
 28.7565 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tag --remove v1.0</userinput>
 28.7566 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tags</userinput>
 28.7567 +tip                                3:0f446f1d1f7f
 28.7568 +</screen>
 28.7569 +<!-- END tag.remove -->
 28.7570 +
 28.7571 +
 28.7572 +    <para id="x_37a">You can also modify a tag at any time, so that it identifies
 28.7573 +      a different revision, by simply issuing a new <command role="hg-cmd" moreinfo="none">hg tag</command> command. You'll have to use the
 28.7574 +      <option role="hg-opt-tag">-f</option> option to tell Mercurial
 28.7575 +      that you <emphasis>really</emphasis> want to update the
 28.7576 +      tag.</para>
 28.7577 +
 28.7578 +    <!-- BEGIN tag.replace -->
 28.7579 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tag -r 1 v1.1</userinput>
 28.7580 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tags</userinput>
 28.7581 +tip                                4:12fc7bf92915
 28.7582 +v1.1                               1:f283c2669b38
 28.7583 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tag -r 2 v1.1</userinput>
 28.7584 +abort: tag 'v1.1' already exists (use -f to force)
 28.7585 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tag -f -r 2 v1.1</userinput>
 28.7586 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tags</userinput>
 28.7587 +tip                                5:17e25cf010af
 28.7588 +v1.1                               2:737882b3cc76
 28.7589 +</screen>
 28.7590 +<!-- END tag.replace -->
 28.7591 +
 28.7592 +
 28.7593 +    <para id="x_37b">There will still be a permanent record of the previous
 28.7594 +      identity of the tag, but Mercurial will no longer use it.
 28.7595 +      There's thus no penalty to tagging the wrong revision; all you
 28.7596 +      have to do is turn around and tag the correct revision once you
 28.7597 +      discover your error.</para>
 28.7598 +
 28.7599 +    <para id="x_37c">Mercurial stores tags in a normal revision-controlled file
 28.7600 +      in your repository.  If you've created any tags, you'll find
 28.7601 +      them in a file in the root of your repository named <filename role="special" moreinfo="none">.hgtags</filename>.  When you run the <command role="hg-cmd" moreinfo="none">hg tag</command> command, Mercurial modifies
 28.7602 +      this file, then automatically commits the change to it.  This
 28.7603 +      means that every time you run <command role="hg-cmd" moreinfo="none">hg
 28.7604 +	tag</command>, you'll see a corresponding changeset in the
 28.7605 +      output of <command role="hg-cmd" moreinfo="none">hg log</command>.</para>
 28.7606 +
 28.7607 +    <!-- BEGIN tag.tip -->
 28.7608 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput>
 28.7609 +changeset:   5:17e25cf010af
 28.7610 +tag:         tip
 28.7611 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.7612 +date:        Sun Aug 16 14:05:16 2009 +0000
 28.7613 +summary:     Added tag v1.1 for changeset 737882b3cc76
 28.7614 +
 28.7615 +</screen>
 28.7616 +<!-- END tag.tip -->
 28.7617 +
 28.7618 +
 28.7619 +    <sect2>
 28.7620 +      <title>Handling tag conflicts during a merge</title>
 28.7621 +
 28.7622 +      <para id="x_37d">You won't often need to care about the <filename role="special" moreinfo="none">.hgtags</filename> file, but it sometimes
 28.7623 +	makes its presence known during a merge.  The format of the
 28.7624 +	file is simple: it consists of a series of lines.  Each line
 28.7625 +	starts with a changeset hash, followed by a space, followed by
 28.7626 +	the name of a tag.</para>
 28.7627 +
 28.7628 +      <para id="x_37e">If you're resolving a conflict in the <filename role="special" moreinfo="none">.hgtags</filename> file during a merge,
 28.7629 +	there's one twist to modifying the <filename role="special" moreinfo="none">.hgtags</filename> file: when Mercurial is
 28.7630 +	parsing the tags in a repository, it
 28.7631 +	<emphasis>never</emphasis> reads the working copy of the
 28.7632 +	<filename role="special" moreinfo="none">.hgtags</filename> file.  Instead, it
 28.7633 +	reads the <emphasis>most recently committed</emphasis>
 28.7634 +	revision of the file.</para>
 28.7635 +
 28.7636 +      <para id="x_37f">An unfortunate consequence of this design is that you
 28.7637 +	can't actually verify that your merged <filename role="special" moreinfo="none">.hgtags</filename> file is correct until
 28.7638 +	<emphasis>after</emphasis> you've committed a change.  So if
 28.7639 +	you find yourself resolving a conflict on <filename role="special" moreinfo="none">.hgtags</filename> during a merge, be sure to
 28.7640 +	run <command role="hg-cmd" moreinfo="none">hg tags</command> after you commit.
 28.7641 +	If it finds an error in the <filename role="special" moreinfo="none">.hgtags</filename> file, it will report the
 28.7642 +	location of the error, which you can then fix and commit.  You
 28.7643 +	should then run <command role="hg-cmd" moreinfo="none">hg tags</command>
 28.7644 +	again, just to be sure that your fix is correct.</para>
 28.7645 +    </sect2>
 28.7646 +
 28.7647 +    <sect2>
 28.7648 +      <title>Tags and cloning</title>
 28.7649 +
 28.7650 +      <para id="x_380">You may have noticed that the <command role="hg-cmd" moreinfo="none">hg
 28.7651 +	  clone</command> command has a <option role="hg-opt-clone">-r</option> option that lets you clone
 28.7652 +	an exact copy of the repository as of a particular changeset.
 28.7653 +	The new clone will not contain any project history that comes
 28.7654 +	after the revision you specified.  This has an interaction
 28.7655 +	with tags that can surprise the unwary.</para>
 28.7656 +
 28.7657 +      <para id="x_381">Recall that a tag is stored as a revision to
 28.7658 +	the <filename role="special" moreinfo="none">.hgtags</filename> file. When you
 28.7659 +	create a tag, the changeset in which its recorded refers to an
 28.7660 +	older changeset.  When you run <command role="hg-cmd" moreinfo="none">hg clone
 28.7661 +	  -r foo</command> to clone a repository as of tag
 28.7662 +	<literal moreinfo="none">foo</literal>, the new clone <emphasis>will not
 28.7663 +	  contain any revision newer than the one the tag refers to,
 28.7664 +	  including the revision where the tag was created</emphasis>.
 28.7665 +	The result is that you'll get exactly the right subset of the
 28.7666 +	project's history in the new repository, but
 28.7667 +	<emphasis>not</emphasis> the tag you might have
 28.7668 +	expected.</para>
 28.7669 +    </sect2>
 28.7670 +
 28.7671 +    <sect2>
 28.7672 +      <title>When permanent tags are too much</title>
 28.7673 +
 28.7674 +      <para id="x_382">Since Mercurial's tags are revision controlled and carried
 28.7675 +	around with a project's history, everyone you work with will
 28.7676 +	see the tags you create.  But giving names to revisions has
 28.7677 +	uses beyond simply noting that revision
 28.7678 +	<literal moreinfo="none">4237e45506ee</literal> is really
 28.7679 +	<literal moreinfo="none">v2.0.2</literal>.  If you're trying to track down a
 28.7680 +	subtle bug, you might want a tag to remind you of something
 28.7681 +	like <quote>Anne saw the symptoms with this
 28.7682 +	  revision</quote>.</para>
 28.7683 +
 28.7684 +      <para id="x_383">For cases like this, what you might want to use are
 28.7685 +	<emphasis>local</emphasis> tags. You can create a local tag
 28.7686 +	with the <option role="hg-opt-tag">-l</option> option to the
 28.7687 +	<command role="hg-cmd" moreinfo="none">hg tag</command> command.  This will
 28.7688 +	store the tag in a file called <filename role="special" moreinfo="none">.hg/localtags</filename>.  Unlike <filename role="special" moreinfo="none">.hgtags</filename>, <filename role="special" moreinfo="none">.hg/localtags</filename> is not revision
 28.7689 +	controlled.  Any tags you create using <option role="hg-opt-tag">-l</option> remain strictly local to the
 28.7690 +	repository you're currently working in.</para>
 28.7691 +    </sect2>
 28.7692 +  </sect1>
 28.7693 +
 28.7694 +  <sect1>
 28.7695 +    <title>The flow of changes—big picture vs. little</title>
 28.7696 +
 28.7697 +    <para id="x_384">To return to the outline I sketched at the
 28.7698 +      beginning of the chapter, let's think about a project that has
 28.7699 +      multiple concurrent pieces of work under development at
 28.7700 +      once.</para>
 28.7701 +
 28.7702 +    <para id="x_385">There might be a push for a new <quote>main</quote> release;
 28.7703 +      a new minor bugfix release to the last main release; and an
 28.7704 +      unexpected <quote>hot fix</quote> to an old release that is now
 28.7705 +      in maintenance mode.</para>
 28.7706 +
 28.7707 +    <para id="x_386">The usual way people refer to these different concurrent
 28.7708 +      directions of development is as <quote>branches</quote>.
 28.7709 +      However, we've already seen numerous times that Mercurial treats
 28.7710 +      <emphasis>all of history</emphasis> as a series of branches and
 28.7711 +      merges.  Really, what we have here is two ideas that are
 28.7712 +      peripherally related, but which happen to share a name.</para>
 28.7713 +    <itemizedlist>
 28.7714 +      <listitem><para id="x_387"><quote>Big picture</quote> branches represent
 28.7715 +	  the sweep of a project's evolution; people give them names,
 28.7716 +	  and talk about them in conversation.</para>
 28.7717 +      </listitem>
 28.7718 +      <listitem><para id="x_388"><quote>Little picture</quote> branches are
 28.7719 +	  artefacts of the day-to-day activity of developing and
 28.7720 +	  merging changes.  They expose the narrative of how the code
 28.7721 +	  was developed.</para>
 28.7722 +      </listitem></itemizedlist>
 28.7723 +  </sect1>
 28.7724 +
 28.7725 +  <sect1>
 28.7726 +    <title>Managing big-picture branches in repositories</title>
 28.7727 +
 28.7728 +    <para id="x_389">The easiest way to isolate a <quote>big picture</quote>
 28.7729 +      branch in Mercurial is in a dedicated repository.  If you have
 28.7730 +      an existing shared repository—let's call it
 28.7731 +      <literal moreinfo="none">myproject</literal>—that reaches a
 28.7732 +      <quote>1.0</quote> milestone, you can start to prepare for
 28.7733 +      future maintenance releases on top of version 1.0 by tagging the
 28.7734 +      revision from which you prepared the 1.0 release.</para>
 28.7735 +
 28.7736 +    <!-- BEGIN branch-repo.tag -->
 28.7737 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd myproject</userinput>
 28.7738 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tag v1.0</userinput>
 28.7739 +</screen>
 28.7740 +<!-- END branch-repo.tag -->
 28.7741 +
 28.7742 +
 28.7743 +    <para id="x_38a">You can then clone a new shared
 28.7744 +      <literal moreinfo="none">myproject-1.0.1</literal> repository as of that
 28.7745 +      tag.</para>
 28.7746 +
 28.7747 +    <!-- BEGIN branch-repo.clone -->
 28.7748 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput>
 28.7749 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone myproject myproject-1.0.1</userinput>
 28.7750 +updating working directory
 28.7751 +2 files updated, 0 files merged, 0 files removed, 0 files unresolved
 28.7752 +</screen>
 28.7753 +<!-- END branch-repo.clone -->
 28.7754 +
 28.7755 +
 28.7756 +    <para id="x_38b">Afterwards, if someone needs to work on a bug fix that ought
 28.7757 +      to go into an upcoming 1.0.1 minor release, they clone the
 28.7758 +      <literal moreinfo="none">myproject-1.0.1</literal> repository, make their
 28.7759 +      changes, and push them back.</para>
 28.7760 +
 28.7761 +    <!-- BEGIN branch-repo.bugfix -->
 28.7762 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone myproject-1.0.1 my-1.0.1-bugfix</userinput>
 28.7763 +updating working directory
 28.7764 +2 files updated, 0 files merged, 0 files removed, 0 files unresolved
 28.7765 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd my-1.0.1-bugfix</userinput>
 28.7766 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'I fixed a bug using only echo!' &gt;&gt; myfile</userinput>
 28.7767 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Important fix for 1.0.1'</userinput>
 28.7768 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg push</userinput>
 28.7769 +pushing to /tmp/branch-repo3rVLLS/myproject-1.0.1
 28.7770 +searching for changes
 28.7771 +adding changesets
 28.7772 +adding manifests
 28.7773 +adding file changes
 28.7774 +added 1 changesets with 1 changes to 1 files
 28.7775 +</screen>
 28.7776 +<!-- END branch-repo.bugfix -->
 28.7777 +
 28.7778 +
 28.7779 +    <para id="x_38c">Meanwhile, development for
 28.7780 +      the next major release can continue, isolated and unabated, in
 28.7781 +      the <literal moreinfo="none">myproject</literal> repository.</para>
 28.7782 +
 28.7783 +    <!-- BEGIN branch-repo.new -->
 28.7784 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput>
 28.7785 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone myproject my-feature</userinput>
 28.7786 +updating working directory
 28.7787 +2 files updated, 0 files merged, 0 files removed, 0 files unresolved
 28.7788 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd my-feature</userinput>
 28.7789 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'This sure is an exciting new feature!' &gt; mynewfile</userinput>
 28.7790 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'New feature'</userinput>
 28.7791 +adding mynewfile
 28.7792 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg push</userinput>
 28.7793 +pushing to /tmp/branch-repo3rVLLS/myproject
 28.7794 +searching for changes
 28.7795 +adding changesets
 28.7796 +adding manifests
 28.7797 +adding file changes
 28.7798 +added 1 changesets with 1 changes to 1 files
 28.7799 +</screen>
 28.7800 +<!-- END branch-repo.new -->
 28.7801 +
 28.7802 +  </sect1>
 28.7803 +
 28.7804 +  <sect1>
 28.7805 +    <title>Don't repeat yourself: merging across branches</title>
 28.7806 +
 28.7807 +    <para id="x_38d">In many cases, if you have a bug to fix on a maintenance
 28.7808 +      branch, the chances are good that the bug exists on your
 28.7809 +      project's main branch (and possibly other maintenance branches,
 28.7810 +      too).  It's a rare developer who wants to fix the same bug
 28.7811 +      multiple times, so let's look at a few ways that Mercurial can
 28.7812 +      help you to manage these bugfixes without duplicating your
 28.7813 +      work.</para>
 28.7814 +
 28.7815 +    <para id="x_38e">In the simplest instance, all you need to do is pull changes
 28.7816 +      from your maintenance branch into your local clone of the target
 28.7817 +      branch.</para>
 28.7818 +
 28.7819 +    <!-- BEGIN branch-repo.pull -->
 28.7820 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput>
 28.7821 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone myproject myproject-merge</userinput>
 28.7822 +updating working directory
 28.7823 +3 files updated, 0 files merged, 0 files removed, 0 files unresolved
 28.7824 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd myproject-merge</userinput>
 28.7825 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull ../myproject-1.0.1</userinput>
 28.7826 +pulling from ../myproject-1.0.1
 28.7827 +searching for changes
 28.7828 +adding changesets
 28.7829 +adding manifests
 28.7830 +adding file changes
 28.7831 +added 1 changesets with 1 changes to 1 files (+1 heads)
 28.7832 +(run 'hg heads' to see heads, 'hg merge' to merge)
 28.7833 +</screen>
 28.7834 +<!-- END branch-repo.pull -->
 28.7835 +
 28.7836 +
 28.7837 +    <para id="x_38f">You'll then need to merge the heads of the two branches, and
 28.7838 +      push back to the main branch.</para>
 28.7839 +
 28.7840 +    <!-- BEGIN branch-repo.merge -->
 28.7841 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg merge</userinput>
 28.7842 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 28.7843 +(branch merge, don't forget to commit)
 28.7844 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Merge bugfix from 1.0.1 branch'</userinput>
 28.7845 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg push</userinput>
 28.7846 +pushing to /tmp/branch-repo3rVLLS/myproject
 28.7847 +searching for changes
 28.7848 +adding changesets
 28.7849 +adding manifests
 28.7850 +adding file changes
 28.7851 +added 2 changesets with 1 changes to 1 files
 28.7852 +</screen>
 28.7853 +<!-- END branch-repo.merge -->
 28.7854 +
 28.7855 +  </sect1>
 28.7856 +
 28.7857 +  <sect1>
 28.7858 +    <title>Naming branches within one repository</title>
 28.7859 +
 28.7860 +    <para id="x_390">In most instances, isolating branches in repositories is the
 28.7861 +      right approach.  Its simplicity makes it easy to understand; and
 28.7862 +      so it's hard to make mistakes.  There's a one-to-one
 28.7863 +      relationship between branches you're working in and directories
 28.7864 +      on your system.  This lets you use normal (non-Mercurial-aware)
 28.7865 +      tools to work on files within a branch/repository.</para>
 28.7866 +
 28.7867 +    <para id="x_391">If you're more in the <quote>power user</quote> category
 28.7868 +      (<emphasis>and</emphasis> your collaborators are too), there is
 28.7869 +      an alternative way of handling branches that you can consider.
 28.7870 +      I've already mentioned the human-level distinction between
 28.7871 +      <quote>small picture</quote> and <quote>big picture</quote>
 28.7872 +      branches.  While Mercurial works with multiple <quote>small
 28.7873 +	picture</quote> branches in a repository all the time (for
 28.7874 +      example after you pull changes in, but before you merge them),
 28.7875 +      it can <emphasis>also</emphasis> work with multiple <quote>big
 28.7876 +	picture</quote> branches.</para>
 28.7877 +
 28.7878 +    <para id="x_392">The key to working this way is that Mercurial lets you
 28.7879 +      assign a persistent <emphasis>name</emphasis> to a branch.
 28.7880 +      There always exists a branch named <literal moreinfo="none">default</literal>.
 28.7881 +      Even before you start naming branches yourself, you can find
 28.7882 +      traces of the <literal moreinfo="none">default</literal> branch if you look for
 28.7883 +      them.</para>
 28.7884 +
 28.7885 +    <para id="x_393">As an example, when you run the <command role="hg-cmd" moreinfo="none">hg
 28.7886 +	commit</command> command, and it pops up your editor so that
 28.7887 +      you can enter a commit message, look for a line that contains
 28.7888 +      the text <quote><literal moreinfo="none">HG: branch default</literal></quote> at
 28.7889 +      the bottom. This is telling you that your commit will occur on
 28.7890 +      the branch named <literal moreinfo="none">default</literal>.</para>
 28.7891 +
 28.7892 +    <para id="x_394">To start working with named branches, use the <command role="hg-cmd" moreinfo="none">hg branches</command> command.  This command
 28.7893 +      lists the named branches already present in your repository,
 28.7894 +      telling you which changeset is the tip of each.</para>
 28.7895 +
 28.7896 +    <!-- BEGIN branch-named.branches -->
 28.7897 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput>
 28.7898 +changeset:   0:90897f9e54e3
 28.7899 +tag:         tip
 28.7900 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.7901 +date:        Sun Aug 16 14:04:42 2009 +0000
 28.7902 +summary:     Initial commit
 28.7903 +
 28.7904 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg branches</userinput>
 28.7905 +default                        0:90897f9e54e3
 28.7906 +</screen>
 28.7907 +<!-- END branch-named.branches -->
 28.7908 +
 28.7909 +
 28.7910 +    <para id="x_395">Since you haven't created any named branches yet, the only
 28.7911 +      one that exists is <literal moreinfo="none">default</literal>.</para>
 28.7912 +
 28.7913 +    <para id="x_396">To find out what the <quote>current</quote> branch is, run
 28.7914 +      the <command role="hg-cmd" moreinfo="none">hg branch</command> command, giving
 28.7915 +      it no arguments.  This tells you what branch the parent of the
 28.7916 +      current changeset is on.</para>
 28.7917 +
 28.7918 +    <!-- BEGIN branch-named.branch -->
 28.7919 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg branch</userinput>
 28.7920 +default
 28.7921 +</screen>
 28.7922 +<!-- END branch-named.branch -->
 28.7923 +
 28.7924 +
 28.7925 +    <para id="x_397">To create a new branch, run the <command role="hg-cmd" moreinfo="none">hg
 28.7926 +	branch</command> command again.  This time, give it one
 28.7927 +      argument: the name of the branch you want to create.</para>
 28.7928 +
 28.7929 +    <!-- BEGIN branch-named.create -->
 28.7930 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg branch foo</userinput>
 28.7931 +marked working directory as branch foo
 28.7932 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg branch</userinput>
 28.7933 +foo
 28.7934 +</screen>
 28.7935 +<!-- END branch-named.create -->
 28.7936 +
 28.7937 +
 28.7938 +    <para id="x_398">After you've created a branch, you might wonder what effect
 28.7939 +      the <command role="hg-cmd" moreinfo="none">hg branch</command> command has had.
 28.7940 +      What do the <command role="hg-cmd" moreinfo="none">hg status</command> and
 28.7941 +      <command role="hg-cmd" moreinfo="none">hg tip</command> commands report?</para>
 28.7942 +
 28.7943 +    <!-- BEGIN branch-named.status -->
 28.7944 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
 28.7945 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput>
 28.7946 +changeset:   0:90897f9e54e3
 28.7947 +tag:         tip
 28.7948 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.7949 +date:        Sun Aug 16 14:04:42 2009 +0000
 28.7950 +summary:     Initial commit
 28.7951 +
 28.7952 +</screen>
 28.7953 +<!-- END branch-named.status -->
 28.7954 +
 28.7955 +
 28.7956 +    <para id="x_399">Nothing has changed in the
 28.7957 +      working directory, and there's been no new history created.  As
 28.7958 +      this suggests, running the <command role="hg-cmd" moreinfo="none">hg
 28.7959 +	branch</command> command has no permanent effect; it only
 28.7960 +      tells Mercurial what branch name to use the
 28.7961 +      <emphasis>next</emphasis> time you commit a changeset.</para>
 28.7962 +
 28.7963 +    <para id="x_39a">When you commit a change, Mercurial records the name of the
 28.7964 +      branch on which you committed.  Once you've switched from the
 28.7965 +      <literal moreinfo="none">default</literal> branch to another and committed,
 28.7966 +      you'll see the name of the new branch show up in the output of
 28.7967 +      <command role="hg-cmd" moreinfo="none">hg log</command>, <command role="hg-cmd" moreinfo="none">hg tip</command>, and other commands that
 28.7968 +      display the same kind of output.</para>
 28.7969 +
 28.7970 +    <!-- BEGIN branch-named.commit -->
 28.7971 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'hello again' &gt;&gt; myfile</userinput>
 28.7972 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Second commit'</userinput>
 28.7973 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput>
 28.7974 +changeset:   1:5656f8ffdd49
 28.7975 +branch:      foo
 28.7976 +tag:         tip
 28.7977 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.7978 +date:        Sun Aug 16 14:04:42 2009 +0000
 28.7979 +summary:     Second commit
 28.7980 +
 28.7981 +</screen>
 28.7982 +<!-- END branch-named.commit -->
 28.7983 +
 28.7984 +
 28.7985 +    <para id="x_39b">The <command role="hg-cmd" moreinfo="none">hg log</command>-like commands
 28.7986 +      will print the branch name of every changeset that's not on the
 28.7987 +      <literal moreinfo="none">default</literal> branch.  As a result, if you never
 28.7988 +      use named branches, you'll never see this information.</para>
 28.7989 +
 28.7990 +    <para id="x_39c">Once you've named a branch and committed a change with that
 28.7991 +      name, every subsequent commit that descends from that change
 28.7992 +      will inherit the same branch name.  You can change the name of a
 28.7993 +      branch at any time, using the <command role="hg-cmd" moreinfo="none">hg
 28.7994 +	branch</command> command.</para>
 28.7995 +
 28.7996 +    <!-- BEGIN branch-named.rebranch -->
 28.7997 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg branch</userinput>
 28.7998 +foo
 28.7999 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg branch bar</userinput>
 28.8000 +marked working directory as branch bar
 28.8001 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo new file &gt; newfile</userinput>
 28.8002 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'Third commit'</userinput>
 28.8003 +adding newfile
 28.8004 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput>
 28.8005 +changeset:   2:c59d680fc2ec
 28.8006 +branch:      bar
 28.8007 +tag:         tip
 28.8008 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.8009 +date:        Sun Aug 16 14:04:42 2009 +0000
 28.8010 +summary:     Third commit
 28.8011 +
 28.8012 +</screen>
 28.8013 +<!-- END branch-named.rebranch -->
 28.8014 +
 28.8015 +
 28.8016 +    <para id="x_39d">In practice, this is something you won't do very often, as
 28.8017 +      branch names tend to have fairly long lifetimes.  (This isn't a
 28.8018 +      rule, just an observation.)</para>
 28.8019 +  </sect1>
 28.8020 +
 28.8021 +  <sect1>
 28.8022 +    <title>Dealing with multiple named branches in a
 28.8023 +      repository</title>
 28.8024 +
 28.8025 +    <para id="x_39e">If you have more than one named branch in a repository,
 28.8026 +      Mercurial will remember the branch that your working directory
 28.8027 +      is on when you start a command like <command role="hg-cmd" moreinfo="none">hg
 28.8028 +	update</command> or <command role="hg-cmd" moreinfo="none">hg pull
 28.8029 +	-u</command>.  It will update the working directory to the tip
 28.8030 +      of this branch, no matter what the <quote>repo-wide</quote> tip
 28.8031 +      is.  To update to a revision that's on a different named branch,
 28.8032 +      you may need to use the <option role="hg-opt-update">-C</option>
 28.8033 +      option to <command role="hg-cmd" moreinfo="none">hg update</command>.</para>
 28.8034 +
 28.8035 +    <para id="x_39f">This behavior is a little subtle, so let's see it in
 28.8036 +      action.  First, let's remind ourselves what branch we're
 28.8037 +      currently on, and what branches are in our repository.</para>
 28.8038 +
 28.8039 +    <!-- BEGIN branch-named.parents -->
 28.8040 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg parents</userinput>
 28.8041 +changeset:   2:c59d680fc2ec
 28.8042 +branch:      bar
 28.8043 +tag:         tip
 28.8044 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.8045 +date:        Sun Aug 16 14:04:42 2009 +0000
 28.8046 +summary:     Third commit
 28.8047 +
 28.8048 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg branches</userinput>
 28.8049 +bar                            2:c59d680fc2ec
 28.8050 +foo                            1:5656f8ffdd49 (inactive)
 28.8051 +default                        0:90897f9e54e3 (inactive)
 28.8052 +</screen>
 28.8053 +<!-- END branch-named.parents -->
 28.8054 +
 28.8055 +
 28.8056 +    <para id="x_3a0">We're on the <literal moreinfo="none">bar</literal> branch, but there also
 28.8057 +      exists an older <command role="hg-cmd" moreinfo="none">hg foo</command>
 28.8058 +      branch.</para>
 28.8059 +
 28.8060 +    <para id="x_3a1">We can <command role="hg-cmd" moreinfo="none">hg update</command> back and
 28.8061 +      forth between the tips of the <literal moreinfo="none">foo</literal> and
 28.8062 +      <literal moreinfo="none">bar</literal> branches without needing to use the
 28.8063 +      <option role="hg-opt-update">-C</option> option, because this
 28.8064 +      only involves going backwards and forwards linearly through our
 28.8065 +      change history.</para>
 28.8066 +
 28.8067 +    <!-- BEGIN branch-named.update-switchy -->
 28.8068 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg update foo</userinput>
 28.8069 +0 files updated, 0 files merged, 1 files removed, 0 files unresolved
 28.8070 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg parents</userinput>
 28.8071 +changeset:   1:5656f8ffdd49
 28.8072 +branch:      foo
 28.8073 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.8074 +date:        Sun Aug 16 14:04:42 2009 +0000
 28.8075 +summary:     Second commit
 28.8076 +
 28.8077 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg update bar</userinput>
 28.8078 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 28.8079 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg parents</userinput>
 28.8080 +changeset:   2:c59d680fc2ec
 28.8081 +branch:      bar
 28.8082 +tag:         tip
 28.8083 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.8084 +date:        Sun Aug 16 14:04:42 2009 +0000
 28.8085 +summary:     Third commit
 28.8086 +
 28.8087 +</screen>
 28.8088 +<!-- END branch-named.update-switchy -->
 28.8089 +
 28.8090 +
 28.8091 +    <para id="x_3a2">If we go back to the <literal moreinfo="none">foo</literal> branch and then
 28.8092 +      run <command role="hg-cmd" moreinfo="none">hg update</command>, it will keep us
 28.8093 +      on <literal moreinfo="none">foo</literal>, not move us to the tip of
 28.8094 +      <literal moreinfo="none">bar</literal>.</para>
 28.8095 +
 28.8096 +    <!-- BEGIN branch-named.update-nothing -->
 28.8097 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg update foo</userinput>
 28.8098 +0 files updated, 0 files merged, 1 files removed, 0 files unresolved
 28.8099 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg update</userinput>
 28.8100 +0 files updated, 0 files merged, 0 files removed, 0 files unresolved
 28.8101 +</screen>
 28.8102 +<!-- END branch-named.update-nothing -->
 28.8103 +
 28.8104 +
 28.8105 +    <para id="x_3a3">Committing a new change on the <literal moreinfo="none">foo</literal> branch
 28.8106 +      introduces a new head.</para>
 28.8107 +
 28.8108 +    <!-- BEGIN branch-named.foo-commit -->
 28.8109 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo something &gt; somefile</userinput>
 28.8110 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'New file'</userinput>
 28.8111 +adding somefile
 28.8112 +created new head
 28.8113 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg heads</userinput>
 28.8114 +changeset:   3:4dd2f7a37288
 28.8115 +branch:      foo
 28.8116 +tag:         tip
 28.8117 +parent:      1:5656f8ffdd49
 28.8118 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.8119 +date:        Sun Aug 16 14:04:43 2009 +0000
 28.8120 +summary:     New file
 28.8121 +
 28.8122 +changeset:   2:c59d680fc2ec
 28.8123 +branch:      bar
 28.8124 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.8125 +date:        Sun Aug 16 14:04:42 2009 +0000
 28.8126 +summary:     Third commit
 28.8127 +
 28.8128 +</screen>
 28.8129 +<!-- END branch-named.foo-commit -->
 28.8130 +
 28.8131 +  </sect1>
 28.8132 +
 28.8133 +  <sect1>
 28.8134 +    <title>Branch names and merging</title>
 28.8135 +
 28.8136 +    <para id="x_3a4">As you've probably noticed, merges in Mercurial are not
 28.8137 +      symmetrical. Let's say our repository has two heads, 17 and 23.
 28.8138 +      If I <command role="hg-cmd" moreinfo="none">hg update</command> to 17 and then
 28.8139 +      <command role="hg-cmd" moreinfo="none">hg merge</command> with 23, Mercurial
 28.8140 +      records 17 as the first parent of the merge, and 23 as the
 28.8141 +      second.  Whereas if I <command role="hg-cmd" moreinfo="none">hg update</command>
 28.8142 +      to 23 and then <command role="hg-cmd" moreinfo="none">hg merge</command> with
 28.8143 +      17, it records 23 as the first parent, and 17 as the
 28.8144 +      second.</para>
 28.8145 +
 28.8146 +    <para id="x_3a5">This affects Mercurial's choice of branch name when you
 28.8147 +      merge.  After a merge, Mercurial will retain the branch name of
 28.8148 +      the first parent when you commit the result of the merge.  If
 28.8149 +      your first parent's branch name is <literal moreinfo="none">foo</literal>, and
 28.8150 +      you merge with <literal moreinfo="none">bar</literal>, the branch name will
 28.8151 +      still be <literal moreinfo="none">foo</literal> after you merge.</para>
 28.8152 +
 28.8153 +    <para id="x_3a6">It's not unusual for a repository to contain multiple heads,
 28.8154 +      each with the same branch name.  Let's say I'm working on the
 28.8155 +      <literal moreinfo="none">foo</literal> branch, and so are you.  We commit
 28.8156 +      different changes; I pull your changes; I now have two heads,
 28.8157 +      each claiming to be on the <literal moreinfo="none">foo</literal> branch.  The
 28.8158 +      result of a merge will be a single head on the
 28.8159 +      <literal moreinfo="none">foo</literal> branch, as you might hope.</para>
 28.8160 +
 28.8161 +    <para id="x_3a7">But if I'm working on the <literal moreinfo="none">bar</literal> branch, and
 28.8162 +      I merge work from the <literal moreinfo="none">foo</literal> branch, the result
 28.8163 +      will remain on the <literal moreinfo="none">bar</literal> branch.</para>
 28.8164 +
 28.8165 +    <!-- BEGIN branch-named.merge -->
 28.8166 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg branch</userinput>
 28.8167 +bar
 28.8168 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg merge foo</userinput>
 28.8169 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 28.8170 +(branch merge, don't forget to commit)
 28.8171 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Merge'</userinput>
 28.8172 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput>
 28.8173 +changeset:   4:9f05d4ef3efe
 28.8174 +branch:      bar
 28.8175 +tag:         tip
 28.8176 +parent:      2:c59d680fc2ec
 28.8177 +parent:      3:4dd2f7a37288
 28.8178 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.8179 +date:        Sun Aug 16 14:04:44 2009 +0000
 28.8180 +summary:     Merge
 28.8181 +
 28.8182 +</screen>
 28.8183 +<!-- END branch-named.merge -->
 28.8184 +
 28.8185 +
 28.8186 +    <para id="x_3a8">To give a more concrete example, if I'm working on the
 28.8187 +      <literal moreinfo="none">bleeding-edge</literal> branch, and I want to bring in
 28.8188 +      the latest fixes from the <literal moreinfo="none">stable</literal> branch,
 28.8189 +      Mercurial will choose the <quote>right</quote>
 28.8190 +      (<literal moreinfo="none">bleeding-edge</literal>) branch name when I pull and
 28.8191 +      merge from <literal moreinfo="none">stable</literal>.</para>
 28.8192 +  </sect1>
 28.8193 +
 28.8194 +  <sect1>
 28.8195 +    <title>Branch naming is generally useful</title>
 28.8196 +
 28.8197 +    <para id="x_3a9">You shouldn't think of named branches as applicable only to
 28.8198 +      situations where you have multiple long-lived branches
 28.8199 +      cohabiting in a single repository.  They're very useful even in
 28.8200 +      the one-branch-per-repository case.</para>
 28.8201 +
 28.8202 +    <para id="x_3aa">In the simplest case, giving a name to each branch gives you
 28.8203 +      a permanent record of which branch a changeset originated on.
 28.8204 +      This gives you more context when you're trying to follow the
 28.8205 +      history of a long-lived branchy project.</para>
 28.8206 +
 28.8207 +    <para id="x_3ab">If you're working with shared repositories, you can set up a
 28.8208 +      <literal role="hook" moreinfo="none">pretxnchangegroup</literal> hook on each
 28.8209 +      that will block incoming changes that have the
 28.8210 +      <quote>wrong</quote> branch name.  This provides a simple, but
 28.8211 +      effective, defence against people accidentally pushing changes
 28.8212 +      from a <quote>bleeding edge</quote> branch to a
 28.8213 +      <quote>stable</quote> branch.  Such a hook might look like this
 28.8214 +      inside the shared repo's <filename role="special" moreinfo="none">
 28.8215 +	/.hgrc</filename>.</para>
 28.8216 +    <programlisting format="linespecific">[hooks]
 28.8217 +pretxnchangegroup.branch = hg heads --template '{branches} ' | grep mybranch</programlisting>
 28.8218 +  </sect1>
 28.8219 +</chapter>
 28.8220 +
 28.8221 +<!--
 28.8222 +local variables: 
 28.8223 +sgml-parent-document: ("00book.xml" "book" "chapter")
 28.8224 +end:
 28.8225 +-->
 28.8226 +
 28.8227 +  <!-- BEGIN ch09 -->
 28.8228 +  <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
 28.8229 +
 28.8230 +<chapter id="chap:undo">
 28.8231 +  <?dbhtml filename="finding-and-fixing-mistakes.html"?>
 28.8232 +  <title>Finding and fixing mistakes</title>
 28.8233 +
 28.8234 +  <para id="x_d2">To err might be human, but to really handle the consequences
 28.8235 +    well takes a top-notch revision control system.  In this chapter,
 28.8236 +    we'll discuss some of the techniques you can use when you find
 28.8237 +    that a problem has crept into your project.  Mercurial has some
 28.8238 +    highly capable features that will help you to isolate the sources
 28.8239 +    of problems, and to handle them appropriately.</para>
 28.8240 +
 28.8241 +  <sect1>
 28.8242 +    <title>Erasing local history</title>
 28.8243 +
 28.8244 +    <sect2>
 28.8245 +      <title>The accidental commit</title>
 28.8246 +
 28.8247 +      <para id="x_d3">I have the occasional but persistent problem of typing
 28.8248 +	rather more quickly than I can think, which sometimes results
 28.8249 +	in me committing a changeset that is either incomplete or
 28.8250 +	plain wrong.  In my case, the usual kind of incomplete
 28.8251 +	changeset is one in which I've created a new source file, but
 28.8252 +	forgotten to <command role="hg-cmd" moreinfo="none">hg add</command> it.  A
 28.8253 +	<quote>plain wrong</quote> changeset is not as common, but no
 28.8254 +	less annoying.</para>
 28.8255 +
 28.8256 +    </sect2>
 28.8257 +    <sect2 id="sec:undo:rollback">
 28.8258 +      <title>Rolling back a transaction</title>
 28.8259 +
 28.8260 +      <para id="x_d4">In <xref linkend="sec:concepts:txn"/>, I
 28.8261 +	mentioned that Mercurial treats each modification of a
 28.8262 +	repository as a <emphasis>transaction</emphasis>.  Every time
 28.8263 +	you commit a changeset or pull changes from another
 28.8264 +	repository, Mercurial remembers what you did.  You can undo,
 28.8265 +	or <emphasis>roll back</emphasis>, exactly one of these
 28.8266 +	actions using the <command role="hg-cmd" moreinfo="none">hg rollback</command>
 28.8267 +	command.  (See <xref linkend="sec:undo:rollback-after-push"/>
 28.8268 +	for an important caveat about the use of this command.)</para>
 28.8269 +
 28.8270 +      <para id="x_d5">Here's a mistake that I often find myself making:
 28.8271 +	committing a change in which I've created a new file, but
 28.8272 +	forgotten to <command role="hg-cmd" moreinfo="none">hg add</command>
 28.8273 +	it.</para>
 28.8274 +
 28.8275 +      <!-- BEGIN rollback.commit -->
 28.8276 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
 28.8277 +M a
 28.8278 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo b &gt; b</userinput>
 28.8279 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Add file b'</userinput>
 28.8280 +</screen>
 28.8281 +<!-- END rollback.commit -->
 28.8282 +
 28.8283 +
 28.8284 +      <para id="x_d6">Looking at the output of <command role="hg-cmd" moreinfo="none">hg
 28.8285 +	  status</command> after the commit immediately confirms the
 28.8286 +	error.</para>
 28.8287 +
 28.8288 +      <!-- BEGIN rollback.status -->
 28.8289 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
 28.8290 +? b
 28.8291 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput>
 28.8292 +changeset:   1:246e2aada1c5
 28.8293 +tag:         tip
 28.8294 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.8295 +date:        Sun Aug 16 14:05:14 2009 +0000
 28.8296 +summary:     Add file b
 28.8297 +
 28.8298 +</screen>
 28.8299 +<!-- END rollback.status -->
 28.8300 +
 28.8301 +
 28.8302 +      <para id="x_d7">The commit captured the changes to the file
 28.8303 +	<filename moreinfo="none">a</filename>, but not the new file
 28.8304 +	<filename moreinfo="none">b</filename>.  If I were to push this changeset to a
 28.8305 +	repository that I shared with a colleague, the chances are
 28.8306 +	high that something in <filename moreinfo="none">a</filename> would refer to
 28.8307 +	<filename moreinfo="none">b</filename>, which would not be present in their
 28.8308 +	repository when they pulled my changes.  I would thus become
 28.8309 +	the object of some indignation.</para>
 28.8310 +
 28.8311 +      <para id="x_d8">However, luck is with me—I've caught my error
 28.8312 +	before I pushed the changeset.  I use the <command role="hg-cmd" moreinfo="none">hg rollback</command> command, and Mercurial
 28.8313 +	makes that last changeset vanish.</para>
 28.8314 +
 28.8315 +      <!-- BEGIN rollback.rollback -->
 28.8316 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg rollback</userinput>
 28.8317 +rolling back last transaction
 28.8318 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput>
 28.8319 +changeset:   0:c37ce4157509
 28.8320 +tag:         tip
 28.8321 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.8322 +date:        Sun Aug 16 14:05:14 2009 +0000
 28.8323 +summary:     First commit
 28.8324 +
 28.8325 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
 28.8326 +M a
 28.8327 +? b
 28.8328 +</screen>
 28.8329 +<!-- END rollback.rollback -->
 28.8330 +
 28.8331 +
 28.8332 +      <para id="x_d9">Notice that the changeset is no longer present in the
 28.8333 +	repository's history, and the working directory once again
 28.8334 +	thinks that the file <filename moreinfo="none">a</filename> is modified.  The
 28.8335 +	commit and rollback have left the working directory exactly as
 28.8336 +	it was prior to the commit; the changeset has been completely
 28.8337 +	erased.  I can now safely <command role="hg-cmd" moreinfo="none">hg
 28.8338 +	  add</command> the file <filename moreinfo="none">b</filename>, and rerun my
 28.8339 +	commit.</para>
 28.8340 +
 28.8341 +      <!-- BEGIN rollback.add -->
 28.8342 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add b</userinput>
 28.8343 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Add file b, this time for real'</userinput>
 28.8344 +</screen>
 28.8345 +<!-- END rollback.add -->
 28.8346 +
 28.8347 +
 28.8348 +    </sect2>
 28.8349 +    <sect2>
 28.8350 +      <title>The erroneous pull</title>
 28.8351 +
 28.8352 +      <para id="x_da">It's common practice with Mercurial to maintain separate
 28.8353 +	development branches of a project in different repositories.
 28.8354 +	Your development team might have one shared repository for
 28.8355 +	your project's <quote>0.9</quote> release, and another,
 28.8356 +	containing different changes, for the <quote>1.0</quote>
 28.8357 +	release.</para>
 28.8358 +
 28.8359 +      <para id="x_db">Given this, you can imagine that the consequences could be
 28.8360 +	messy if you had a local <quote>0.9</quote> repository, and
 28.8361 +	accidentally pulled changes from the shared <quote>1.0</quote>
 28.8362 +	repository into it.  At worst, you could be paying
 28.8363 +	insufficient attention, and push those changes into the shared
 28.8364 +	<quote>0.9</quote> tree, confusing your entire team (but don't
 28.8365 +	worry, we'll return to this horror scenario later).  However,
 28.8366 +	it's more likely that you'll notice immediately, because
 28.8367 +	Mercurial will display the URL it's pulling from, or you will
 28.8368 +	see it pull a suspiciously large number of changes into the
 28.8369 +	repository.</para>
 28.8370 +
 28.8371 +      <para id="x_dc">The <command role="hg-cmd" moreinfo="none">hg rollback</command> command
 28.8372 +	will work nicely to expunge all of the changesets that you
 28.8373 +	just pulled.  Mercurial groups all changes from one <command role="hg-cmd" moreinfo="none">hg pull</command> into a single transaction,
 28.8374 +	so one <command role="hg-cmd" moreinfo="none">hg rollback</command> is all you
 28.8375 +	need to undo this mistake.</para>
 28.8376 +
 28.8377 +    </sect2>
 28.8378 +    <sect2 id="sec:undo:rollback-after-push">
 28.8379 +      <title>Rolling back is useless once you've pushed</title>
 28.8380 +
 28.8381 +      <para id="x_dd">The value of the <command role="hg-cmd" moreinfo="none">hg
 28.8382 +	  rollback</command> command drops to zero once you've pushed
 28.8383 +	your changes to another repository.  Rolling back a change
 28.8384 +	makes it disappear entirely, but <emphasis>only</emphasis> in
 28.8385 +	the repository in which you perform the <command role="hg-cmd" moreinfo="none">hg rollback</command>.  Because a rollback
 28.8386 +	eliminates history, there's no way for the disappearance of a
 28.8387 +	change to propagate between repositories.</para>
 28.8388 +
 28.8389 +      <para id="x_de">If you've pushed a change to another
 28.8390 +	repository—particularly if it's a shared
 28.8391 +	repository—it has essentially <quote>escaped into the
 28.8392 +	  wild,</quote> and you'll have to recover from your mistake
 28.8393 +	in a different way.  If you push a changeset somewhere, then
 28.8394 +	roll it back, then pull from the repository you pushed to, the
 28.8395 +	changeset you thought you'd gotten rid of will simply reappear
 28.8396 +	in your repository.</para>
 28.8397 +
 28.8398 +      <para id="x_df">(If you absolutely know for sure that the change
 28.8399 +	you want to roll back is the most recent change in the
 28.8400 +	repository that you pushed to, <emphasis>and</emphasis> you
 28.8401 +	know that nobody else could have pulled it from that
 28.8402 +	repository, you can roll back the changeset there, too, but
 28.8403 +	you really should not expect this to work reliably.  Sooner or
 28.8404 +	later a change really will make it into a repository that you
 28.8405 +	don't directly control (or have forgotten about), and come
 28.8406 +	back to bite you.)</para>
 28.8407 +
 28.8408 +    </sect2>
 28.8409 +    <sect2>
 28.8410 +      <title>You can only roll back once</title>
 28.8411 +
 28.8412 +      <para id="x_e0">Mercurial stores exactly one transaction in its
 28.8413 +	transaction log; that transaction is the most recent one that
 28.8414 +	occurred in the repository. This means that you can only roll
 28.8415 +	back one transaction.  If you expect to be able to roll back
 28.8416 +	one transaction, then its predecessor, this is not the
 28.8417 +	behavior you will get.</para>
 28.8418 +
 28.8419 +      <!-- BEGIN rollback.twice -->
 28.8420 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg rollback</userinput>
 28.8421 +rolling back last transaction
 28.8422 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg rollback</userinput>
 28.8423 +no rollback information available
 28.8424 +</screen>
 28.8425 +<!-- END rollback.twice -->
 28.8426 +
 28.8427 +
 28.8428 +      <para id="x_e1">Once you've rolled back one transaction in a repository,
 28.8429 +	you can't roll back again in that repository until you perform
 28.8430 +	another commit or pull.</para>
 28.8431 +
 28.8432 +    </sect2>
 28.8433 +  </sect1>
 28.8434 +  <sect1>
 28.8435 +    <title>Reverting the mistaken change</title>
 28.8436 +
 28.8437 +    <para id="x_e2">If you make a modification to a file, and decide that you
 28.8438 +      really didn't want to change the file at all, and you haven't
 28.8439 +      yet committed your changes, the <command role="hg-cmd" moreinfo="none">hg
 28.8440 +	revert</command> command is the one you'll need.  It looks at
 28.8441 +      the changeset that's the parent of the working directory, and
 28.8442 +      restores the contents of the file to their state as of that
 28.8443 +      changeset. (That's a long-winded way of saying that, in the
 28.8444 +      normal case, it undoes your modifications.)</para>
 28.8445 +
 28.8446 +    <para id="x_e3">Let's illustrate how the <command role="hg-cmd" moreinfo="none">hg
 28.8447 +	revert</command> command works with yet another small example.
 28.8448 +      We'll begin by modifying a file that Mercurial is already
 28.8449 +      tracking.</para>
 28.8450 +
 28.8451 +    <!-- BEGIN daily.revert.modify -->
 28.8452 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat file</userinput>
 28.8453 +original content
 28.8454 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo unwanted change &gt;&gt; file</userinput>
 28.8455 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg diff file</userinput>
 28.8456 +diff -r 2eacf948d309 file
 28.8457 +--- a/file	Sun Aug 16 14:05:00 2009 +0000
 28.8458 ++++ b/file	Sun Aug 16 14:05:00 2009 +0000
 28.8459 +@@ -1,1 +1,2 @@
 28.8460 + original content
 28.8461 ++unwanted change
 28.8462 +</screen>
 28.8463 +<!-- END daily.revert.modify -->
 28.8464 +
 28.8465 +
 28.8466 +    <para id="x_e4">If we don't
 28.8467 +      want that change, we can simply <command role="hg-cmd" moreinfo="none">hg
 28.8468 +	revert</command> the file.</para>
 28.8469 +
 28.8470 +      <!-- BEGIN daily.revert.unmodify -->
 28.8471 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
 28.8472 +M file
 28.8473 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg revert file</userinput>
 28.8474 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat file</userinput>
 28.8475 +original content
 28.8476 +</screen>
 28.8477 +<!-- END daily.revert.unmodify -->
 28.8478 +
 28.8479 +
 28.8480 +    <para id="x_e5">The <command role="hg-cmd" moreinfo="none">hg revert</command> command
 28.8481 +      provides us with an extra degree of safety by saving our
 28.8482 +      modified file with a <filename moreinfo="none">.orig</filename>
 28.8483 +      extension.</para>
 28.8484 +
 28.8485 +    <!-- BEGIN daily.revert.status -->
 28.8486 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
 28.8487 +? file.orig
 28.8488 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat file.orig</userinput>
 28.8489 +original content
 28.8490 +unwanted change
 28.8491 +</screen>
 28.8492 +<!-- END daily.revert.status -->
 28.8493 +
 28.8494 +
 28.8495 +    <tip>
 28.8496 +      <title>Be careful with <filename moreinfo="none">.orig</filename> files</title>
 28.8497 +
 28.8498 +      <para id="x_6b8">It's extremely unlikely that you are either using
 28.8499 +	Mercurial to manage files with <filename moreinfo="none">.orig</filename>
 28.8500 +	extensions or that you even care about the contents of such
 28.8501 +	files.  Just in case, though, it's useful to remember that
 28.8502 +	<command role="hg-cmd" moreinfo="none">hg revert</command> will
 28.8503 +	unconditionally overwrite an existing file with a
 28.8504 +	<filename moreinfo="none">.orig</filename> extension. For instance, if you
 28.8505 +	already have a file named <filename moreinfo="none">foo.orig</filename> when
 28.8506 +	you revert <filename moreinfo="none">foo</filename>, the contents of
 28.8507 +	<filename moreinfo="none">foo.orig</filename> will be clobbered.</para>
 28.8508 +    </tip>
 28.8509 +
 28.8510 +    <para id="x_e6">Here is a summary of the cases that the <command role="hg-cmd" moreinfo="none">hg revert</command> command can deal with.  We
 28.8511 +      will describe each of these in more detail in the section that
 28.8512 +      follows.</para>
 28.8513 +    <itemizedlist>
 28.8514 +      <listitem><para id="x_e7">If you modify a file, it will restore the file
 28.8515 +	  to its unmodified state.</para>
 28.8516 +      </listitem>
 28.8517 +      <listitem><para id="x_e8">If you <command role="hg-cmd" moreinfo="none">hg add</command> a
 28.8518 +	  file, it will undo the <quote>added</quote> state of the
 28.8519 +	  file, but leave the file itself untouched.</para>
 28.8520 +      </listitem>
 28.8521 +      <listitem><para id="x_e9">If you delete a file without telling Mercurial,
 28.8522 +	  it will restore the file to its unmodified contents.</para>
 28.8523 +      </listitem>
 28.8524 +      <listitem><para id="x_ea">If you use the <command role="hg-cmd" moreinfo="none">hg
 28.8525 +	    remove</command> command to remove a file, it will undo
 28.8526 +	  the <quote>removed</quote> state of the file, and restore
 28.8527 +	  the file to its unmodified contents.</para>
 28.8528 +      </listitem></itemizedlist>
 28.8529 +
 28.8530 +    <sect2 id="sec:undo:mgmt">
 28.8531 +      <title>File management errors</title>
 28.8532 +
 28.8533 +      <para id="x_eb">The <command role="hg-cmd" moreinfo="none">hg revert</command> command is
 28.8534 +	useful for more than just modified files.  It lets you reverse
 28.8535 +	the results of all of Mercurial's file management
 28.8536 +	commands—<command role="hg-cmd" moreinfo="none">hg add</command>,
 28.8537 +	<command role="hg-cmd" moreinfo="none">hg remove</command>, and so on.</para>
 28.8538 +
 28.8539 +      <para id="x_ec">If you <command role="hg-cmd" moreinfo="none">hg add</command> a file,
 28.8540 +	then decide that in fact you don't want Mercurial to track it,
 28.8541 +	use <command role="hg-cmd" moreinfo="none">hg revert</command> to undo the
 28.8542 +	add.  Don't worry; Mercurial will not modify the file in any
 28.8543 +	way.  It will just <quote>unmark</quote> the file.</para>
 28.8544 +
 28.8545 +      <!-- BEGIN daily.revert.add -->
 28.8546 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo oops &gt; oops</userinput>
 28.8547 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add oops</userinput>
 28.8548 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status oops</userinput>
 28.8549 +A oops
 28.8550 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg revert oops</userinput>
 28.8551 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
 28.8552 +? oops
 28.8553 +</screen>
 28.8554 +<!-- END daily.revert.add -->
 28.8555 +
 28.8556 +
 28.8557 +      <para id="x_ed">Similarly, if you ask Mercurial to <command role="hg-cmd" moreinfo="none">hg remove</command> a file, you can use
 28.8558 +	<command role="hg-cmd" moreinfo="none">hg revert</command> to restore it to
 28.8559 +	the contents it had as of the parent of the working directory.
 28.8560 +	<!-- BEGIN daily.revert.remove -->
 28.8561 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg remove file</userinput>
 28.8562 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
 28.8563 +R file
 28.8564 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg revert file</userinput>
 28.8565 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
 28.8566 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls file</userinput>
 28.8567 +file
 28.8568 +</screen>
 28.8569 +<!-- END daily.revert.remove -->
 28.8570 + This works just as
 28.8571 +	well for a file that you deleted by hand, without telling
 28.8572 +	Mercurial (recall that in Mercurial terminology, this kind of
 28.8573 +	file is called <quote>missing</quote>).</para>
 28.8574 +
 28.8575 +      <!-- BEGIN daily.revert.missing -->
 28.8576 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">rm file</userinput>
 28.8577 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
 28.8578 +! file
 28.8579 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg revert file</userinput>
 28.8580 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls file</userinput>
 28.8581 +file
 28.8582 +</screen>
 28.8583 +<!-- END daily.revert.missing -->
 28.8584 +
 28.8585 +
 28.8586 +      <para id="x_ee">If you revert a <command role="hg-cmd" moreinfo="none">hg copy</command>,
 28.8587 +	the copied-to file remains in your working directory
 28.8588 +	afterwards, untracked.  Since a copy doesn't affect the
 28.8589 +	copied-from file in any way, Mercurial doesn't do anything
 28.8590 +	with the copied-from file.</para>
 28.8591 +
 28.8592 +      <!-- BEGIN daily.revert.copy -->
 28.8593 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg copy file new-file</userinput>
 28.8594 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg revert new-file</userinput>
 28.8595 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
 28.8596 +? new-file
 28.8597 +</screen>
 28.8598 +<!-- END daily.revert.copy -->
 28.8599 +
 28.8600 +    </sect2>
 28.8601 +  </sect1>
 28.8602 +
 28.8603 +  <sect1>
 28.8604 +    <title>Dealing with committed changes</title>
 28.8605 +
 28.8606 +    <para id="x_f5">Consider a case where you have committed a change
 28.8607 +      <emphasis>a</emphasis>, and another change
 28.8608 +      <emphasis>b</emphasis> on top of it; you then realise that
 28.8609 +      change <emphasis>a</emphasis> was incorrect.  Mercurial lets you
 28.8610 +      <quote>back out</quote> an entire changeset automatically, and
 28.8611 +      building blocks that let you reverse part of a changeset by
 28.8612 +      hand.</para>
 28.8613 +
 28.8614 +    <para id="x_f6">Before you read this section, here's something to
 28.8615 +      keep in mind: the <command role="hg-cmd" moreinfo="none">hg backout</command>
 28.8616 +      command undoes the effect of a change by
 28.8617 +      <emphasis>adding</emphasis> to your repository's history, not by
 28.8618 +      modifying or erasing it.  It's the right tool to use if you're
 28.8619 +      fixing bugs, but not if you're trying to undo some change that
 28.8620 +      has catastrophic consequences.  To deal with those, see
 28.8621 +      <xref linkend="sec:undo:aaaiiieee"/>.</para>
 28.8622 +
 28.8623 +    <sect2>
 28.8624 +      <title>Backing out a changeset</title>
 28.8625 +
 28.8626 +      <para id="x_f7">The <command role="hg-cmd" moreinfo="none">hg backout</command> command
 28.8627 +	lets you <quote>undo</quote> the effects of an entire
 28.8628 +	changeset in an automated fashion.  Because Mercurial's
 28.8629 +	history is immutable, this command <emphasis>does
 28.8630 +	  not</emphasis> get rid of the changeset you want to undo.
 28.8631 +	Instead, it creates a new changeset that
 28.8632 +	<emphasis>reverses</emphasis> the effect of the to-be-undone
 28.8633 +	changeset.</para>
 28.8634 +
 28.8635 +      <para id="x_f8">The operation of the <command role="hg-cmd" moreinfo="none">hg
 28.8636 +	  backout</command> command is a little intricate, so let's
 28.8637 +	illustrate it with some examples.  First, we'll create a
 28.8638 +	repository with some simple changes.</para>
 28.8639 +
 28.8640 +      <!-- BEGIN backout.init -->
 28.8641 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init myrepo</userinput>
 28.8642 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd myrepo</userinput>
 28.8643 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo first change &gt;&gt; myfile</userinput>
 28.8644 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add myfile</userinput>
 28.8645 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'first change'</userinput>
 28.8646 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo second change &gt;&gt; myfile</userinput>
 28.8647 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'second change'</userinput>
 28.8648 +</screen>
 28.8649 +<!-- END backout.init -->
 28.8650 +
 28.8651 +
 28.8652 +      <para id="x_f9">The <command role="hg-cmd" moreinfo="none">hg backout</command> command
 28.8653 +	takes a single changeset ID as its argument; this is the
 28.8654 +	changeset to back out.  Normally, <command role="hg-cmd" moreinfo="none">hg
 28.8655 +	  backout</command> will drop you into a text editor to write
 28.8656 +	a commit message, so you can record why you're backing the
 28.8657 +	change out.  In this example, we provide a commit message on
 28.8658 +	the command line using the <option role="hg-opt-backout">-m</option> option.</para>
 28.8659 +
 28.8660 +    </sect2>
 28.8661 +    <sect2>
 28.8662 +      <title>Backing out the tip changeset</title>
 28.8663 +
 28.8664 +      <para id="x_fa">We're going to start by backing out the last changeset we
 28.8665 +	committed.</para>
 28.8666 +
 28.8667 +      <!-- BEGIN backout.simple -->
 28.8668 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg backout -m 'back out second change' tip</userinput>
 28.8669 +reverting myfile
 28.8670 +changeset 2:611a0cae251c backs out changeset 1:43700a9b3ec8
 28.8671 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat myfile</userinput>
 28.8672 +first change
 28.8673 +</screen>
 28.8674 +<!-- END backout.simple -->
 28.8675 +
 28.8676 +
 28.8677 +      <para id="x_fb">You can see that the second line from
 28.8678 +	<filename moreinfo="none">myfile</filename> is no longer present.  Taking a
 28.8679 +	look at the output of <command role="hg-cmd" moreinfo="none">hg log</command>
 28.8680 +	gives us an idea of what the <command role="hg-cmd" moreinfo="none">hg
 28.8681 +	  backout</command> command has done.
 28.8682 +	<!-- BEGIN backout.simple.log -->
 28.8683 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log --style compact</userinput>
 28.8684 +2[tip]   611a0cae251c   2009-08-16 14:04 +0000   bos
 28.8685 +  back out second change
 28.8686 +
 28.8687 +1   43700a9b3ec8   2009-08-16 14:04 +0000   bos
 28.8688 +  second change
 28.8689 +
 28.8690 +0   f2ef23d503fd   2009-08-16 14:04 +0000   bos
 28.8691 +  first change
 28.8692 +
 28.8693 +</screen>
 28.8694 +<!-- END backout.simple.log -->
 28.8695 + Notice that the new changeset
 28.8696 +	that <command role="hg-cmd" moreinfo="none">hg backout</command> has created
 28.8697 +	is a child of the changeset we backed out.  It's easier to see
 28.8698 +	this in <xref linkend="fig:undo:backout"/>, which presents a
 28.8699 +	graphical view of the change history.  As you can see, the
 28.8700 +	history is nice and linear.</para>
 28.8701 +
 28.8702 +      <figure id="fig:undo:backout" float="0">
 28.8703 +	<title>Backing out a change using the <command role="hg-cmd" moreinfo="none">hg backout</command> command</title>
 28.8704 +	<mediaobject>
 28.8705 +	  <imageobject><imagedata fileref="figs/undo-simple.png"/></imageobject>
 28.8706 +	  <textobject><phrase>XXX add text</phrase></textobject>
 28.8707 +	</mediaobject>
 28.8708 +      </figure>
 28.8709 +
 28.8710 +    </sect2>
 28.8711 +    <sect2>
 28.8712 +      <title>Backing out a non-tip change</title>
 28.8713 +
 28.8714 +      <para id="x_fd">If you want to back out a change other than the last one
 28.8715 +	you committed, pass the <option role="hg-opt-backout">--merge</option> option to the
 28.8716 +	<command role="hg-cmd" moreinfo="none">hg backout</command> command.</para>
 28.8717 +
 28.8718 +      <!-- BEGIN backout.non-tip.clone -->
 28.8719 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput>
 28.8720 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone -r1 myrepo non-tip-repo</userinput>
 28.8721 +requesting all changes
 28.8722 +adding changesets
 28.8723 +adding manifests
 28.8724 +adding file changes
 28.8725 +added 2 changesets with 2 changes to 1 files
 28.8726 +updating working directory
 28.8727 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 28.8728 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd non-tip-repo</userinput>
 28.8729 +</screen>
 28.8730 +<!-- END backout.non-tip.clone -->
 28.8731 +
 28.8732 +
 28.8733 +      <para id="x_fe">This makes backing out any changeset a
 28.8734 +	<quote>one-shot</quote> operation that's usually simple and
 28.8735 +	fast.</para>
 28.8736 +
 28.8737 +      <!-- BEGIN backout.non-tip.backout -->
 28.8738 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo third change &gt;&gt; myfile</userinput>
 28.8739 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'third change'</userinput>
 28.8740 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg backout --merge -m 'back out second change' 1</userinput>
 28.8741 +reverting myfile
 28.8742 +created new head
 28.8743 +changeset 3:611a0cae251c backs out changeset 1:43700a9b3ec8
 28.8744 +merging with changeset 3:611a0cae251c
 28.8745 +merging myfile
 28.8746 +0 files updated, 1 files merged, 0 files removed, 0 files unresolved
 28.8747 +(branch merge, don't forget to commit)
 28.8748 +</screen>
 28.8749 +<!-- END backout.non-tip.backout -->
 28.8750 +
 28.8751 +
 28.8752 +      <para id="x_ff">If you take a look at the contents of
 28.8753 +	<filename moreinfo="none">myfile</filename> after the backout finishes, you'll
 28.8754 +	see that the first and third changes are present, but not the
 28.8755 +	second.</para>
 28.8756 +
 28.8757 +      <!-- BEGIN backout.non-tip.cat -->
 28.8758 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat myfile</userinput>
 28.8759 +first change
 28.8760 +third change
 28.8761 +</screen>
 28.8762 +<!-- END backout.non-tip.cat -->
 28.8763 +
 28.8764 +
 28.8765 +      <para id="x_100">As the graphical history in <xref linkend="fig:undo:backout-non-tip"/> illustrates, Mercurial
 28.8766 +	still commits one change in this kind of situation (the
 28.8767 +	box-shaped node is the ones that Mercurial commits
 28.8768 +	automatically), but the revision graph now looks different.
 28.8769 +	Before Mercurial begins the backout process, it first
 28.8770 +	remembers what the current parent of the working directory is.
 28.8771 +	It then backs out the target changeset, and commits that as a
 28.8772 +	changeset.  Finally, it merges back to the previous parent of
 28.8773 +	the working directory, but notice that it <emphasis>does not
 28.8774 +	  commit</emphasis> the result of the merge.  The repository
 28.8775 +	now contains two heads, and the working directory is in a
 28.8776 +	merge state.</para>
 28.8777 +
 28.8778 +      <figure id="fig:undo:backout-non-tip" float="0">
 28.8779 +	<title>Automated backout of a non-tip change using the
 28.8780 +	  <command role="hg-cmd" moreinfo="none">hg backout</command> command</title>
 28.8781 +	<mediaobject>
 28.8782 +	  <imageobject><imagedata fileref="figs/undo-non-tip.png"/></imageobject>
 28.8783 +	  <textobject><phrase>XXX add text</phrase></textobject>
 28.8784 +	</mediaobject>
 28.8785 +      </figure>
 28.8786 +
 28.8787 +      <para id="x_103">The result is that you end up <quote>back where you
 28.8788 +	  were</quote>, only with some extra history that undoes the
 28.8789 +	effect of the changeset you wanted to back out.</para>
 28.8790 +
 28.8791 +      <para id="x_6b9">You might wonder why Mercurial does not commit the result
 28.8792 +	of the merge that it performed.  The reason lies in Mercurial
 28.8793 +	behaving conservatively: a merge naturally has more scope for
 28.8794 +	error than simply undoing the effect of the tip changeset,
 28.8795 +	so your work will be safest if you first inspect (and test!)
 28.8796 +	the result of the merge, <emphasis>then</emphasis> commit
 28.8797 +	it.</para>
 28.8798 +
 28.8799 +      <sect3>
 28.8800 +	<title>Always use the <option role="hg-opt-backout">--merge</option> option</title>
 28.8801 +
 28.8802 +	<para id="x_104">In fact, since the <option role="hg-opt-backout">--merge</option> option will do the
 28.8803 +	  <quote>right thing</quote> whether or not the changeset
 28.8804 +	  you're backing out is the tip (i.e. it won't try to merge if
 28.8805 +	  it's backing out the tip, since there's no need), you should
 28.8806 +	  <emphasis>always</emphasis> use this option when you run the
 28.8807 +	  <command role="hg-cmd" moreinfo="none">hg backout</command> command.</para>
 28.8808 +
 28.8809 +      </sect3>
 28.8810 +    </sect2>
 28.8811 +    <sect2>
 28.8812 +      <title>Gaining more control of the backout process</title>
 28.8813 +
 28.8814 +      <para id="x_105">While I've recommended that you always use the <option role="hg-opt-backout">--merge</option> option when backing
 28.8815 +	out a change, the <command role="hg-cmd" moreinfo="none">hg backout</command>
 28.8816 +	command lets you decide how to merge a backout changeset.
 28.8817 +	Taking control of the backout process by hand is something you
 28.8818 +	will rarely need to do, but it can be useful to understand
 28.8819 +	what the <command role="hg-cmd" moreinfo="none">hg backout</command> command
 28.8820 +	is doing for you automatically.  To illustrate this, let's
 28.8821 +	clone our first repository, but omit the backout change that
 28.8822 +	it contains.</para>
 28.8823 +
 28.8824 +      <!-- BEGIN backout.manual.clone -->
 28.8825 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput>
 28.8826 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone -r1 myrepo newrepo</userinput>
 28.8827 +requesting all changes
 28.8828 +adding changesets
 28.8829 +adding manifests
 28.8830 +adding file changes
 28.8831 +added 2 changesets with 2 changes to 1 files
 28.8832 +updating working directory
 28.8833 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 28.8834 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd newrepo</userinput>
 28.8835 +</screen>
 28.8836 +<!-- END backout.manual.clone -->
 28.8837 +
 28.8838 +
 28.8839 +      <para id="x_106">As with our
 28.8840 +	earlier example, We'll commit a third changeset, then back out
 28.8841 +	its parent, and see what happens.</para>
 28.8842 +
 28.8843 +      <!-- BEGIN backout.manual.backout -->
 28.8844 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo third change &gt;&gt; myfile</userinput>
 28.8845 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'third change'</userinput>
 28.8846 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg backout -m 'back out second change' 1</userinput>
 28.8847 +reverting myfile
 28.8848 +created new head
 28.8849 +changeset 3:bf906ee0baae backs out changeset 1:43700a9b3ec8
 28.8850 +the backout changeset is a new head - do not forget to merge
 28.8851 +(use "backout --merge" if you want to auto-merge)
 28.8852 +</screen>
 28.8853 +<!-- END backout.manual.backout -->
 28.8854 +
 28.8855 +
 28.8856 +      <para id="x_107">Our new changeset is again a descendant of the changeset
 28.8857 +	we backout out; it's thus a new head, <emphasis>not</emphasis>
 28.8858 +	a descendant of the changeset that was the tip.  The <command role="hg-cmd" moreinfo="none">hg backout</command> command was quite
 28.8859 +	explicit in telling us this.</para>
 28.8860 +
 28.8861 +      <!-- BEGIN backout.manual.log -->
 28.8862 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log --style compact</userinput>
 28.8863 +3[tip]:1   bf906ee0baae   2009-08-16 14:04 +0000   bos
 28.8864 +  back out second change
 28.8865 +
 28.8866 +2   2521379001ad   2009-08-16 14:04 +0000   bos
 28.8867 +  third change
 28.8868 +
 28.8869 +1   43700a9b3ec8   2009-08-16 14:04 +0000   bos
 28.8870 +  second change
 28.8871 +
 28.8872 +0   f2ef23d503fd   2009-08-16 14:04 +0000   bos
 28.8873 +  first change
 28.8874 +
 28.8875 +</screen>
 28.8876 +<!-- END backout.manual.log -->
 28.8877 +
 28.8878 +
 28.8879 +      <para id="x_108">Again, it's easier to see what has happened by looking at
 28.8880 +	a graph of the revision history, in <xref linkend="fig:undo:backout-manual"/>.  This makes it clear
 28.8881 +	that when we use <command role="hg-cmd" moreinfo="none">hg backout</command>
 28.8882 +	to back out a change other than the tip, Mercurial adds a new
 28.8883 +	head to the repository (the change it committed is
 28.8884 +	box-shaped).</para>
 28.8885 +
 28.8886 +      <figure id="fig:undo:backout-manual" float="0">
 28.8887 +	<title>Backing out a change using the <command role="hg-cmd" moreinfo="none">hg backout</command> command</title>
 28.8888 +	<mediaobject>
 28.8889 +	  <imageobject><imagedata fileref="figs/undo-manual.png"/></imageobject>
 28.8890 +	  <textobject><phrase>XXX add text</phrase></textobject>
 28.8891 +	</mediaobject>
 28.8892 +      </figure>
 28.8893 +
 28.8894 +      <para id="x_10a">After the <command role="hg-cmd" moreinfo="none">hg backout</command>
 28.8895 +	command has completed, it leaves the new
 28.8896 +	<quote>backout</quote> changeset as the parent of the working
 28.8897 +	directory.</para>
 28.8898 +
 28.8899 +      <!-- BEGIN backout.manual.parents -->
 28.8900 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg parents</userinput>
 28.8901 +changeset:   2:2521379001ad
 28.8902 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.8903 +date:        Sun Aug 16 14:04:37 2009 +0000
 28.8904 +summary:     third change
 28.8905 +
 28.8906 +</screen>
 28.8907 +<!-- END backout.manual.parents -->
 28.8908 +
 28.8909 +
 28.8910 +      <para id="x_10b">Now we have two isolated sets of changes.</para>
 28.8911 +
 28.8912 +      <!-- BEGIN backout.manual.heads -->
 28.8913 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg heads</userinput>
 28.8914 +changeset:   3:bf906ee0baae
 28.8915 +tag:         tip
 28.8916 +parent:      1:43700a9b3ec8
 28.8917 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.8918 +date:        Sun Aug 16 14:04:37 2009 +0000
 28.8919 +summary:     back out second change
 28.8920 +
 28.8921 +changeset:   2:2521379001ad
 28.8922 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.8923 +date:        Sun Aug 16 14:04:37 2009 +0000
 28.8924 +summary:     third change
 28.8925 +
 28.8926 +</screen>
 28.8927 +<!-- END backout.manual.heads -->
 28.8928 +
 28.8929 +
 28.8930 +      <para id="x_10c">Let's think about what we expect to see as the contents of
 28.8931 +	<filename moreinfo="none">myfile</filename> now.  The first change should be
 28.8932 +	present, because we've never backed it out.  The second change
 28.8933 +	should be missing, as that's the change we backed out.  Since
 28.8934 +	the history graph shows the third change as a separate head,
 28.8935 +	we <emphasis>don't</emphasis> expect to see the third change
 28.8936 +	present in <filename moreinfo="none">myfile</filename>.</para>
 28.8937 +
 28.8938 +      <!-- BEGIN backout.manual.cat -->
 28.8939 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat myfile</userinput>
 28.8940 +first change
 28.8941 +</screen>
 28.8942 +<!-- END backout.manual.cat -->
 28.8943 +
 28.8944 +
 28.8945 +      <para id="x_10d">To get the third change back into the file, we just do a
 28.8946 +	normal merge of our two heads.</para>
 28.8947 +
 28.8948 +      <!-- BEGIN backout.manual.merge -->
 28.8949 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg merge</userinput>
 28.8950 +abort: outstanding uncommitted changes
 28.8951 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'merged backout with previous tip'</userinput>
 28.8952 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat myfile</userinput>
 28.8953 +first change
 28.8954 +</screen>
 28.8955 +<!-- END backout.manual.merge -->
 28.8956 +
 28.8957 +
 28.8958 +      <para id="x_10e">Afterwards, the graphical history of our
 28.8959 +	repository looks like
 28.8960 +	<xref linkend="fig:undo:backout-manual-merge"/>.</para>
 28.8961 +
 28.8962 +      <figure id="fig:undo:backout-manual-merge" float="0">
 28.8963 +	<title>Manually merging a backout change</title>
 28.8964 +	<mediaobject>
 28.8965 +	  <imageobject><imagedata fileref="figs/undo-manual-merge.png"/></imageobject>
 28.8966 +	  <textobject><phrase>XXX add text</phrase></textobject>
 28.8967 +	</mediaobject>
 28.8968 +      </figure>
 28.8969 +
 28.8970 +    </sect2>
 28.8971 +    <sect2>
 28.8972 +      <title>Why <command role="hg-cmd" moreinfo="none">hg backout</command> works as
 28.8973 +	it does</title>
 28.8974 +
 28.8975 +      <para id="x_110">Here's a brief description of how the <command role="hg-cmd" moreinfo="none">hg backout</command> command works.</para>
 28.8976 +      <orderedlist inheritnum="ignore" continuation="restarts">
 28.8977 +	<listitem><para id="x_111">It ensures that the working directory is
 28.8978 +	    <quote>clean</quote>, i.e. that the output of <command role="hg-cmd" moreinfo="none">hg status</command> would be empty.</para>
 28.8979 +	</listitem>
 28.8980 +	<listitem><para id="x_112">It remembers the current parent of the working
 28.8981 +	    directory.  Let's call this changeset
 28.8982 +	    <literal moreinfo="none">orig</literal>.</para>
 28.8983 +	</listitem>
 28.8984 +	<listitem><para id="x_113">It does the equivalent of a <command role="hg-cmd" moreinfo="none">hg update</command> to sync the working
 28.8985 +	    directory to the changeset you want to back out.  Let's
 28.8986 +	    call this changeset <literal moreinfo="none">backout</literal>.</para>
 28.8987 +	</listitem>
 28.8988 +	<listitem><para id="x_114">It finds the parent of that changeset.  Let's
 28.8989 +	    call that changeset <literal moreinfo="none">parent</literal>.</para>
 28.8990 +	</listitem>
 28.8991 +	<listitem><para id="x_115">For each file that the
 28.8992 +	    <literal moreinfo="none">backout</literal> changeset affected, it does the
 28.8993 +	    equivalent of a <command role="hg-cmd" moreinfo="none">hg revert -r
 28.8994 +	      parent</command> on that file, to restore it to the
 28.8995 +	    contents it had before that changeset was
 28.8996 +	    committed.</para>
 28.8997 +	</listitem>
 28.8998 +	<listitem><para id="x_116">It commits the result as a new changeset.
 28.8999 +	    This changeset has <literal moreinfo="none">backout</literal> as its
 28.9000 +	    parent.</para>
 28.9001 +	</listitem>
 28.9002 +	<listitem><para id="x_117">If you specify <option role="hg-opt-backout">--merge</option> on the command
 28.9003 +	    line, it merges with <literal moreinfo="none">orig</literal>, and commits
 28.9004 +	    the result of the merge.</para>
 28.9005 +	</listitem></orderedlist>
 28.9006 +
 28.9007 +      <para id="x_118">An alternative way to implement the <command role="hg-cmd" moreinfo="none">hg backout</command> command would be to
 28.9008 +	<command role="hg-cmd" moreinfo="none">hg export</command> the
 28.9009 +	to-be-backed-out changeset as a diff, then use the <option role="cmd-opt-patch">--reverse</option> option to the
 28.9010 +	<command moreinfo="none">patch</command> command to reverse the effect of the
 28.9011 +	change without fiddling with the working directory.  This
 28.9012 +	sounds much simpler, but it would not work nearly as
 28.9013 +	well.</para>
 28.9014 +
 28.9015 +      <para id="x_119">The reason that <command role="hg-cmd" moreinfo="none">hg
 28.9016 +	  backout</command> does an update, a commit, a merge, and
 28.9017 +	another commit is to give the merge machinery the best chance
 28.9018 +	to do a good job when dealing with all the changes
 28.9019 +	<emphasis>between</emphasis> the change you're backing out and
 28.9020 +	the current tip.</para>
 28.9021 +
 28.9022 +      <para id="x_11a">If you're backing out a changeset that's 100 revisions
 28.9023 +	back in your project's history, the chances that the
 28.9024 +	<command moreinfo="none">patch</command> command will be able to apply a
 28.9025 +	reverse diff cleanly are not good, because intervening changes
 28.9026 +	are likely to have <quote>broken the context</quote> that
 28.9027 +	<command moreinfo="none">patch</command> uses to determine whether it can
 28.9028 +	apply a patch (if this sounds like gibberish, see <xref linkend="sec:mq:patch"/> for a
 28.9029 +	discussion of the <command moreinfo="none">patch</command> command).  Also,
 28.9030 +	Mercurial's merge machinery will handle files and directories
 28.9031 +	being renamed, permission changes, and modifications to binary
 28.9032 +	files, none of which <command moreinfo="none">patch</command> can deal
 28.9033 +	with.</para>
 28.9034 +
 28.9035 +    </sect2>
 28.9036 +  </sect1>
 28.9037 +  <sect1 id="sec:undo:aaaiiieee">
 28.9038 +    <title>Changes that should never have been</title>
 28.9039 +
 28.9040 +    <para id="x_11b">Most of the time, the <command role="hg-cmd" moreinfo="none">hg
 28.9041 +	backout</command> command is exactly what you need if you want
 28.9042 +      to undo the effects of a change.  It leaves a permanent record
 28.9043 +      of exactly what you did, both when committing the original
 28.9044 +      changeset and when you cleaned up after it.</para>
 28.9045 +
 28.9046 +    <para id="x_11c">On rare occasions, though, you may find that you've
 28.9047 +      committed a change that really should not be present in the
 28.9048 +      repository at all.  For example, it would be very unusual, and
 28.9049 +      usually considered a mistake, to commit a software project's
 28.9050 +      object files as well as its source files.  Object files have
 28.9051 +      almost no intrinsic value, and they're <emphasis>big</emphasis>,
 28.9052 +      so they increase the size of the repository and the amount of
 28.9053 +      time it takes to clone or pull changes.</para>
 28.9054 +
 28.9055 +    <para id="x_11d">Before I discuss the options that you have if you commit a
 28.9056 +      <quote>brown paper bag</quote> change (the kind that's so bad
 28.9057 +      that you want to pull a brown paper bag over your head), let me
 28.9058 +      first discuss some approaches that probably won't work.</para>
 28.9059 +
 28.9060 +    <para id="x_11e">Since Mercurial treats history as
 28.9061 +      accumulative—every change builds on top of all changes
 28.9062 +      that preceded it—you generally can't just make disastrous
 28.9063 +      changes disappear.  The one exception is when you've just
 28.9064 +      committed a change, and it hasn't been pushed or pulled into
 28.9065 +      another repository.  That's when you can safely use the <command role="hg-cmd" moreinfo="none">hg rollback</command> command, as I detailed in
 28.9066 +      <xref linkend="sec:undo:rollback"/>.</para>
 28.9067 +
 28.9068 +    <para id="x_11f">After you've pushed a bad change to another repository, you
 28.9069 +      <emphasis>could</emphasis> still use <command role="hg-cmd" moreinfo="none">hg
 28.9070 +	rollback</command> to make your local copy of the change
 28.9071 +      disappear, but it won't have the consequences you want.  The
 28.9072 +      change will still be present in the remote repository, so it
 28.9073 +      will reappear in your local repository the next time you
 28.9074 +      pull.</para>
 28.9075 +
 28.9076 +    <para id="x_120">If a situation like this arises, and you know which
 28.9077 +      repositories your bad change has propagated into, you can
 28.9078 +      <emphasis>try</emphasis> to get rid of the change from
 28.9079 +      <emphasis>every</emphasis> one of those repositories.  This is,
 28.9080 +      of course, not a satisfactory solution: if you miss even a
 28.9081 +      single repository while you're expunging, the change is still
 28.9082 +      <quote>in the wild</quote>, and could propagate further.</para>
 28.9083 +
 28.9084 +    <para id="x_121">If you've committed one or more changes
 28.9085 +      <emphasis>after</emphasis> the change that you'd like to see
 28.9086 +      disappear, your options are further reduced. Mercurial doesn't
 28.9087 +      provide a way to <quote>punch a hole</quote> in history, leaving
 28.9088 +      changesets intact.</para>
 28.9089 +
 28.9090 +    <sect2>
 28.9091 +      <title>Backing out a merge</title>
 28.9092 +
 28.9093 +      <para id="x_6ba">Since merges are often complicated, it is not unheard of
 28.9094 +	for a merge to be mangled badly, but committed erroneously.
 28.9095 +	Mercurial provides an important safeguard against bad merges
 28.9096 +	by refusing to commit unresolved files, but human ingenuity
 28.9097 +	guarantees that it is still possible to mess a merge up and
 28.9098 +	commit it.</para>
 28.9099 +
 28.9100 +      <para id="x_6bb">Given a bad merge that has been committed, usually the
 28.9101 +	best way to approach it is to simply try to repair the damage
 28.9102 +	by hand.  A complete disaster that cannot be easily fixed up
 28.9103 +	by hand ought to be very rare, but the <command role="hg-cmd" moreinfo="none">hg backout</command> command may help in
 28.9104 +	making the cleanup easier. It offers a <option role="hg-opt-backout">--parent</option> option, which lets
 28.9105 +	you specify which parent to revert to when backing out a
 28.9106 +	merge.</para>
 28.9107 +
 28.9108 +      <figure id="fig:undo:bad-merge-1" float="0">
 28.9109 +	<title>A bad merge</title>
 28.9110 +	<mediaobject>
 28.9111 +	  <imageobject><imagedata fileref="figs/bad-merge-1.png"/></imageobject>
 28.9112 +	  <textobject><phrase>XXX add text</phrase></textobject>
 28.9113 +	</mediaobject>
 28.9114 +      </figure>
 28.9115 +
 28.9116 +      <para id="x_6bc">Suppose we have a revision graph like that in <xref linkend="fig:undo:bad-merge-1"/>.  What we'd like is to
 28.9117 +	<emphasis>redo</emphasis> the merge of revisions 2 and
 28.9118 +	3.</para>
 28.9119 +
 28.9120 +      <para id="x_6bd">One way to do so would be as follows.</para>
 28.9121 +
 28.9122 +      <orderedlist inheritnum="ignore" continuation="restarts">
 28.9123 +	<listitem>
 28.9124 +	  <para id="x_6be">Call <command role="hg-cmd" moreinfo="none">hg backout --rev=4
 28.9125 +	      --parent=2</command>.  This tells <command role="hg-cmd" moreinfo="none">hg backout</command> to back out revision
 28.9126 +	    4, which is the bad merge, and to when deciding which
 28.9127 +	    revision to prefer, to choose parent 2, one of the parents
 28.9128 +	    of the merge.  The effect can be seen in <xref linkend="fig:undo:bad-merge-2"/>.</para>
 28.9129 +	  <figure id="fig:undo:bad-merge-2" float="0">
 28.9130 +	    <title>Backing out the merge, favoring one parent</title>
 28.9131 +	    <mediaobject>
 28.9132 +	      <imageobject><imagedata fileref="figs/bad-merge-2.png"/></imageobject>
 28.9133 +	      <textobject><phrase>XXX add text</phrase></textobject>
 28.9134 +	    </mediaobject>
 28.9135 +	  </figure>
 28.9136 +	</listitem>
 28.9137 +
 28.9138 +	<listitem>
 28.9139 +	  <para id="x_6bf">Call <command role="hg-cmd" moreinfo="none">hg backout --rev=4
 28.9140 +	      --parent=3</command>.  This tells <command role="hg-cmd" moreinfo="none">hg backout</command> to back out revision
 28.9141 +	    4 again, but this time to choose parent 3, the other
 28.9142 +	    parent of the merge.  The result is visible in <xref linkend="fig:undo:bad-merge-3"/>, in which the repository
 28.9143 +	    now contains three heads.</para>
 28.9144 +	  <figure id="fig:undo:bad-merge-3" float="0">
 28.9145 +	    <title>Backing out the merge, favoring the other
 28.9146 +	      parent</title>
 28.9147 +	    <mediaobject>
 28.9148 +	      <imageobject><imagedata fileref="figs/bad-merge-3.png"/></imageobject>
 28.9149 +	      <textobject><phrase>XXX add text</phrase></textobject>
 28.9150 +	    </mediaobject>
 28.9151 +	  </figure>
 28.9152 +	</listitem>
 28.9153 +
 28.9154 +	<listitem>
 28.9155 +	  <para id="x_6c0">Redo the bad merge by merging the two backout heads,
 28.9156 +	    which reduces the number of heads in the repository to
 28.9157 +	    two, as can be seen in <xref linkend="fig:undo:bad-merge-4"/>.</para>
 28.9158 +	  <figure id="fig:undo:bad-merge-4" float="0">
 28.9159 +	    <title>Merging the backouts</title>
 28.9160 +	    <mediaobject>
 28.9161 +	      <imageobject><imagedata fileref="figs/bad-merge-4.png"/></imageobject>
 28.9162 +	      <textobject><phrase>XXX add text</phrase></textobject>
 28.9163 +	    </mediaobject>
 28.9164 +	  </figure>
 28.9165 +	</listitem>
 28.9166 +
 28.9167 +	<listitem>
 28.9168 +	  <para id="x_6c1">Merge with the commit that was made after the bad
 28.9169 +	    merge, as shown in <xref linkend="fig:undo:bad-merge-5"/>.</para>
 28.9170 +	  <figure id="fig:undo:bad-merge-5" float="0">
 28.9171 +	    <title>Merging the backouts</title>
 28.9172 +	    <mediaobject>
 28.9173 +	      <imageobject><imagedata fileref="figs/bad-merge-5.png"/></imageobject>
 28.9174 +	      <textobject><phrase>XXX add text</phrase></textobject>
 28.9175 +	    </mediaobject>
 28.9176 +	  </figure>
 28.9177 +	</listitem>
 28.9178 +      </orderedlist>
 28.9179 +    </sect2>
 28.9180 +
 28.9181 +    <sect2>
 28.9182 +      <title>Protect yourself from <quote>escaped</quote>
 28.9183 +	changes</title>
 28.9184 +
 28.9185 +      <para id="x_123">If you've committed some changes to your local repository
 28.9186 +	and they've been pushed or pulled somewhere else, this isn't
 28.9187 +	necessarily a disaster.  You can protect yourself ahead of
 28.9188 +	time against some classes of bad changeset.  This is
 28.9189 +	particularly easy if your team usually pulls changes from a
 28.9190 +	central repository.</para>
 28.9191 +
 28.9192 +      <para id="x_124">By configuring some hooks on that repository to validate
 28.9193 +	incoming changesets (see chapter <xref linkend="chap:hook"/>),
 28.9194 +	you can
 28.9195 +	automatically prevent some kinds of bad changeset from being
 28.9196 +	pushed to the central repository at all.  With such a
 28.9197 +	configuration in place, some kinds of bad changeset will
 28.9198 +	naturally tend to <quote>die out</quote> because they can't
 28.9199 +	propagate into the central repository.  Better yet, this
 28.9200 +	happens without any need for explicit intervention.</para>
 28.9201 +
 28.9202 +      <para id="x_125">For instance, an incoming change hook that
 28.9203 +	verifies that a changeset will actually compile can prevent
 28.9204 +	people from inadvertently <quote>breaking the
 28.9205 +	  build</quote>.</para>
 28.9206 +    </sect2>
 28.9207 +
 28.9208 +    <sect2>
 28.9209 +      <title>What to do about sensitive changes that escape</title>
 28.9210 +
 28.9211 +      <para id="x_6c2">Even a carefully run project can suffer an unfortunate
 28.9212 +	event such as the committing and uncontrolled propagation of a
 28.9213 +	file that contains important passwords.</para>
 28.9214 +
 28.9215 +      <para id="x_6c3">If something like this happens to you, and the information
 28.9216 +	that gets accidentally propagated is truly sensitive, your
 28.9217 +	first step should be to mitigate the effect of the leak
 28.9218 +	without trying to control the leak itself. If you are not 100%
 28.9219 +	certain that you know exactly who could have seen the changes,
 28.9220 +	you should immediately change passwords, cancel credit cards,
 28.9221 +	or find some other way to make sure that the information that
 28.9222 +	has leaked is no longer useful.  In other words, assume that
 28.9223 +	the change has propagated far and wide, and that there's
 28.9224 +	nothing more you can do.</para>
 28.9225 +
 28.9226 +      <para id="x_6c4">You might hope that there would be mechanisms you could
 28.9227 +	use to either figure out who has seen a change or to erase the
 28.9228 +	change permanently everywhere, but there are good reasons why
 28.9229 +	these are not possible.</para>
 28.9230 +
 28.9231 +      <para id="x_6c5">Mercurial does not provide an audit trail of who has
 28.9232 +	pulled changes from a repository, because it is usually either
 28.9233 +	impossible to record such information or trivial to spoof it.
 28.9234 +	In a multi-user or networked environment, you should thus be
 28.9235 +	extremely skeptical of yourself if you think that you have
 28.9236 +	identified every place that a sensitive changeset has
 28.9237 +	propagated to.  Don't forget that people can and will send
 28.9238 +	bundles by email, have their backup software save data
 28.9239 +	offsite, carry repositories on USB sticks, and find other
 28.9240 +	completely innocent ways to confound your attempts to track
 28.9241 +	down every copy of a problematic change.</para>
 28.9242 +
 28.9243 +      <para id="x_6c6">Mercurial also does not provide a way to make a file or
 28.9244 +	changeset completely disappear from history, because there is
 28.9245 +	no way to enforce its disappearance; someone could easily
 28.9246 +	modify their copy of Mercurial to ignore such directives. In
 28.9247 +	addition, even if Mercurial provided such a capability,
 28.9248 +	someone who simply hadn't pulled a <quote>make this file
 28.9249 +	  disappear</quote> changeset wouldn't be affected by it, nor
 28.9250 +	would web crawlers visiting at the wrong time, disk backups,
 28.9251 +	or other mechanisms.  Indeed, no distributed revision control
 28.9252 +	system can make data reliably vanish. Providing the illusion
 28.9253 +	of such control could easily give a false sense of security,
 28.9254 +	and be worse than not providing it at all.</para>
 28.9255 +    </sect2>
 28.9256 +  </sect1>
 28.9257 +
 28.9258 +  <sect1 id="sec:undo:bisect">
 28.9259 +    <title>Finding the source of a bug</title>
 28.9260 +
 28.9261 +    <para id="x_126">While it's all very well to be able to back out a changeset
 28.9262 +      that introduced a bug, this requires that you know which
 28.9263 +      changeset to back out.  Mercurial provides an invaluable
 28.9264 +      command, called <command role="hg-cmd" moreinfo="none">hg bisect</command>, that
 28.9265 +      helps you to automate this process and accomplish it very
 28.9266 +      efficiently.</para>
 28.9267 +
 28.9268 +    <para id="x_127">The idea behind the <command role="hg-cmd" moreinfo="none">hg
 28.9269 +	bisect</command> command is that a changeset has introduced
 28.9270 +      some change of behavior that you can identify with a simple
 28.9271 +      pass/fail test.  You don't know which piece of code introduced the
 28.9272 +      change, but you know how to test for the presence of the bug.
 28.9273 +      The <command role="hg-cmd" moreinfo="none">hg bisect</command> command uses your
 28.9274 +      test to direct its search for the changeset that introduced the
 28.9275 +      code that caused the bug.</para>
 28.9276 +
 28.9277 +    <para id="x_128">Here are a few scenarios to help you understand how you
 28.9278 +      might apply this command.</para>
 28.9279 +    <itemizedlist>
 28.9280 +      <listitem><para id="x_129">The most recent version of your software has a
 28.9281 +	  bug that you remember wasn't present a few weeks ago, but
 28.9282 +	  you don't know when it was introduced.  Here, your binary
 28.9283 +	  test checks for the presence of that bug.</para>
 28.9284 +      </listitem>
 28.9285 +      <listitem><para id="x_12a">You fixed a bug in a rush, and now it's time to
 28.9286 +	  close the entry in your team's bug database.  The bug
 28.9287 +	  database requires a changeset ID when you close an entry,
 28.9288 +	  but you don't remember which changeset you fixed the bug in.
 28.9289 +	  Once again, your binary test checks for the presence of the
 28.9290 +	  bug.</para>
 28.9291 +      </listitem>
 28.9292 +      <listitem><para id="x_12b">Your software works correctly, but runs 15%
 28.9293 +	  slower than the last time you measured it.  You want to know
 28.9294 +	  which changeset introduced the performance regression.  In
 28.9295 +	  this case, your binary test measures the performance of your
 28.9296 +	  software, to see whether it's <quote>fast</quote> or
 28.9297 +	  <quote>slow</quote>.</para>
 28.9298 +      </listitem>
 28.9299 +      <listitem><para id="x_12c">The sizes of the components of your project that
 28.9300 +	  you ship exploded recently, and you suspect that something
 28.9301 +	  changed in the way you build your project.</para>
 28.9302 +      </listitem></itemizedlist>
 28.9303 +
 28.9304 +    <para id="x_12d">From these examples, it should be clear that the <command role="hg-cmd" moreinfo="none">hg bisect</command> command is not useful only
 28.9305 +      for finding the sources of bugs.  You can use it to find any
 28.9306 +      <quote>emergent property</quote> of a repository (anything that
 28.9307 +      you can't find from a simple text search of the files in the
 28.9308 +      tree) for which you can write a binary test.</para>
 28.9309 +
 28.9310 +    <para id="x_12e">We'll introduce a little bit of terminology here, just to
 28.9311 +      make it clear which parts of the search process are your
 28.9312 +      responsibility, and which are Mercurial's.  A
 28.9313 +      <emphasis>test</emphasis> is something that
 28.9314 +      <emphasis>you</emphasis> run when <command role="hg-cmd" moreinfo="none">hg
 28.9315 +	bisect</command> chooses a changeset.  A
 28.9316 +      <emphasis>probe</emphasis> is what <command role="hg-cmd" moreinfo="none">hg
 28.9317 +	bisect</command> runs to tell whether a revision is good.
 28.9318 +      Finally, we'll use the word <quote>bisect</quote>, as both a
 28.9319 +      noun and a verb, to stand in for the phrase <quote>search using
 28.9320 +	the <command role="hg-cmd" moreinfo="none">hg bisect</command>
 28.9321 +	command</quote>.</para>
 28.9322 +
 28.9323 +    <para id="x_12f">One simple way to automate the searching process would be
 28.9324 +      simply to probe every changeset.  However, this scales poorly.
 28.9325 +      If it took ten minutes to test a single changeset, and you had
 28.9326 +      10,000 changesets in your repository, the exhaustive approach
 28.9327 +      would take on average 35 <emphasis>days</emphasis> to find the
 28.9328 +      changeset that introduced a bug.  Even if you knew that the bug
 28.9329 +      was introduced by one of the last 500 changesets, and limited
 28.9330 +      your search to those, you'd still be looking at over 40 hours to
 28.9331 +      find the changeset that introduced your bug.</para>
 28.9332 +
 28.9333 +    <para id="x_130">What the <command role="hg-cmd" moreinfo="none">hg bisect</command> command
 28.9334 +      does is use its knowledge of the <quote>shape</quote> of your
 28.9335 +      project's revision history to perform a search in time
 28.9336 +      proportional to the <emphasis>logarithm</emphasis> of the number
 28.9337 +      of changesets to check (the kind of search it performs is called
 28.9338 +      a dichotomic search).  With this approach, searching through
 28.9339 +      10,000 changesets will take less than three hours, even at ten
 28.9340 +      minutes per test (the search will require about 14 tests).
 28.9341 +      Limit your search to the last hundred changesets, and it will
 28.9342 +      take only about an hour (roughly seven tests).</para>
 28.9343 +
 28.9344 +    <para id="x_131">The <command role="hg-cmd" moreinfo="none">hg bisect</command> command is
 28.9345 +      aware of the <quote>branchy</quote> nature of a Mercurial
 28.9346 +      project's revision history, so it has no problems dealing with
 28.9347 +      branches, merges, or multiple heads in a repository.  It can
 28.9348 +      prune entire branches of history with a single probe, which is
 28.9349 +      how it operates so efficiently.</para>
 28.9350 +
 28.9351 +    <sect2>
 28.9352 +      <title>Using the <command role="hg-cmd" moreinfo="none">hg bisect</command>
 28.9353 +	command</title>
 28.9354 +
 28.9355 +      <para id="x_132">Here's an example of <command role="hg-cmd" moreinfo="none">hg
 28.9356 +	  bisect</command> in action.</para>
 28.9357 +
 28.9358 +      <note>
 28.9359 +	<para id="x_133">  In versions 0.9.5 and earlier of Mercurial, <command role="hg-cmd" moreinfo="none">hg bisect</command> was not a core command:
 28.9360 +	  it was distributed with Mercurial as an extension. This
 28.9361 +	  section describes the built-in command, not the old
 28.9362 +	  extension.</para>
 28.9363 +      </note>
 28.9364 +
 28.9365 +      <para id="x_134">Now let's create a repository, so that we can try out the
 28.9366 +	<command role="hg-cmd" moreinfo="none">hg bisect</command> command in
 28.9367 +	isolation.</para>
 28.9368 +
 28.9369 +      <!-- BEGIN bisect.init -->
 28.9370 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init mybug</userinput>
 28.9371 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd mybug</userinput>
 28.9372 +</screen>
 28.9373 +<!-- END bisect.init -->
 28.9374 +
 28.9375 +
 28.9376 +      <para id="x_135">We'll simulate a project that has a bug in it in a
 28.9377 +	simple-minded way: create trivial changes in a loop, and
 28.9378 +	nominate one specific change that will have the
 28.9379 +	<quote>bug</quote>.  This loop creates 35 changesets, each
 28.9380 +	adding a single file to the repository. We'll represent our
 28.9381 +	<quote>bug</quote> with a file that contains the text <quote>i
 28.9382 +	  have a gub</quote>.</para>
 28.9383 +
 28.9384 +      <!-- BEGIN bisect.commits -->
 28.9385 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">buggy_change=22</userinput>
 28.9386 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">for (( i = 0; i &lt; 35; i++ )); do</userinput>
 28.9387 +<prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">  if [[ $i = $buggy_change ]]; then</userinput>
 28.9388 +<prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">    echo 'i have a gub' &gt; myfile$i</userinput>
 28.9389 +<prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">    hg commit -q -A -m 'buggy changeset'</userinput>
 28.9390 +<prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">  else</userinput>
 28.9391 +<prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">    echo 'nothing to see here, move along' &gt; myfile$i</userinput>
 28.9392 +<prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">    hg commit -q -A -m 'normal changeset'</userinput>
 28.9393 +<prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">  fi</userinput>
 28.9394 +<prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">done</userinput>
 28.9395 +</screen>
 28.9396 +<!-- END bisect.commits -->
 28.9397 +
 28.9398 +
 28.9399 +      <para id="x_136">The next thing that we'd like to do is figure out how to
 28.9400 +	use the <command role="hg-cmd" moreinfo="none">hg bisect</command> command.
 28.9401 +	We can use Mercurial's normal built-in help mechanism for
 28.9402 +	this.</para>
 28.9403 +
 28.9404 +      <!-- BEGIN bisect.help -->
 28.9405 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg help bisect</userinput>
 28.9406 +hg bisect [-gbsr] [-c CMD] [REV]
 28.9407 +
 28.9408 +subdivision search of changesets
 28.9409 +
 28.9410 +    This command helps to find changesets which introduce problems.
 28.9411 +    To use, mark the earliest changeset you know exhibits the problem
 28.9412 +    as bad, then mark the latest changeset which is free from the
 28.9413 +    problem as good. Bisect will update your working directory to a
 28.9414 +    revision for testing (unless the --noupdate option is specified).
 28.9415 +    Once you have performed tests, mark the working directory as bad
 28.9416 +    or good and bisect will either update to another candidate changeset
 28.9417 +    or announce that it has found the bad revision.
 28.9418 +
 28.9419 +    As a shortcut, you can also use the revision argument to mark a
 28.9420 +    revision as good or bad without checking it out first.
 28.9421 +
 28.9422 +    If you supply a command it will be used for automatic bisection. Its exit
 28.9423 +    status will be used as flag to mark revision as bad or good. In case exit
 28.9424 +    status is 0 the revision is marked as good, 125 - skipped, 127 (command not
 28.9425 +    found) - bisection will be aborted; any other status bigger than 0 will
 28.9426 +    mark revision as bad.
 28.9427 +
 28.9428 +options:
 28.9429 +
 28.9430 + -r --reset     reset bisect state
 28.9431 + -g --good      mark changeset good
 28.9432 + -b --bad       mark changeset bad
 28.9433 + -s --skip      skip testing changeset
 28.9434 + -c --command   use command to check changeset state
 28.9435 + -U --noupdate  do not update to target
 28.9436 +
 28.9437 +use "hg -v help bisect" to show global options
 28.9438 +</screen>
 28.9439 +<!-- END bisect.help -->
 28.9440 +
 28.9441 +
 28.9442 +      <para id="x_137">The <command role="hg-cmd" moreinfo="none">hg bisect</command> command
 28.9443 +	works in steps.  Each step proceeds as follows.</para>
 28.9444 +      <orderedlist inheritnum="ignore" continuation="restarts">
 28.9445 +	<listitem><para id="x_138">You run your binary test.</para>
 28.9446 +	  <itemizedlist>
 28.9447 +	    <listitem><para id="x_139">If the test succeeded, you tell <command role="hg-cmd" moreinfo="none">hg bisect</command> by running the
 28.9448 +		<command role="hg-cmd" moreinfo="none">hg bisect --good</command>
 28.9449 +		command.</para>
 28.9450 +	    </listitem>
 28.9451 +	    <listitem><para id="x_13a">If it failed, run the <command role="hg-cmd" moreinfo="none">hg bisect --bad</command>
 28.9452 +		command.</para></listitem></itemizedlist>
 28.9453 +	</listitem>
 28.9454 +	<listitem><para id="x_13b">The command uses your information to decide
 28.9455 +	    which changeset to test next.</para>
 28.9456 +	</listitem>
 28.9457 +	<listitem><para id="x_13c">It updates the working directory to that
 28.9458 +	    changeset, and the process begins again.</para>
 28.9459 +	</listitem></orderedlist>
 28.9460 +      <para id="x_13d">The process ends when <command role="hg-cmd" moreinfo="none">hg
 28.9461 +	  bisect</command> identifies a unique changeset that marks
 28.9462 +	the point where your test transitioned from
 28.9463 +	<quote>succeeding</quote> to <quote>failing</quote>.</para>
 28.9464 +
 28.9465 +      <para id="x_13e">To start the search, we must run the <command role="hg-cmd" moreinfo="none">hg bisect --reset</command> command.</para>
 28.9466 +
 28.9467 +      <!-- BEGIN bisect.search.init -->
 28.9468 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg bisect --reset</userinput>
 28.9469 +</screen>
 28.9470 +<!-- END bisect.search.init -->
 28.9471 +
 28.9472 +
 28.9473 +      <para id="x_13f">In our case, the binary test we use is simple: we check to
 28.9474 +	see if any file in the repository contains the string <quote>i
 28.9475 +	  have a gub</quote>.  If it does, this changeset contains the
 28.9476 +	change that <quote>caused the bug</quote>.  By convention, a
 28.9477 +	changeset that has the property we're searching for is
 28.9478 +	<quote>bad</quote>, while one that doesn't is
 28.9479 +	<quote>good</quote>.</para>
 28.9480 +
 28.9481 +      <para id="x_140">Most of the time, the revision to which the working
 28.9482 +	directory is synced (usually the tip) already exhibits the
 28.9483 +	problem introduced by the buggy change, so we'll mark it as
 28.9484 +	<quote>bad</quote>.</para>
 28.9485 +
 28.9486 +      <!-- BEGIN bisect.search.bad-init -->
 28.9487 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg bisect --bad</userinput>
 28.9488 +</screen>
 28.9489 +<!-- END bisect.search.bad-init -->
 28.9490 +
 28.9491 +
 28.9492 +      <para id="x_141">Our next task is to nominate a changeset that we know
 28.9493 +	<emphasis>doesn't</emphasis> have the bug; the <command role="hg-cmd" moreinfo="none">hg bisect</command> command will
 28.9494 +	<quote>bracket</quote> its search between the first pair of
 28.9495 +	good and bad changesets.  In our case, we know that revision
 28.9496 +	10 didn't have the bug.  (I'll have more words about choosing
 28.9497 +	the first <quote>good</quote> changeset later.)</para>
 28.9498 +
 28.9499 +      <!-- BEGIN bisect.search.good-init -->
 28.9500 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg bisect --good 10</userinput>
 28.9501 +Testing changeset 22:69f52b967ab8 (24 changesets remaining, ~4 tests)
 28.9502 +0 files updated, 0 files merged, 12 files removed, 0 files unresolved
 28.9503 +</screen>
 28.9504 +<!-- END bisect.search.good-init -->
 28.9505 +
 28.9506 +
 28.9507 +      <para id="x_142">Notice that this command printed some output.</para>
 28.9508 +      <itemizedlist>
 28.9509 +	<listitem><para id="x_143">It told us how many changesets it must
 28.9510 +	    consider before it can identify the one that introduced
 28.9511 +	    the bug, and how many tests that will require.</para>
 28.9512 +	</listitem>
 28.9513 +	<listitem><para id="x_144">It updated the working directory to the next
 28.9514 +	    changeset to test, and told us which changeset it's
 28.9515 +	    testing.</para>
 28.9516 +	</listitem></itemizedlist>
 28.9517 +
 28.9518 +      <para id="x_145">We now run our test in the working directory.  We use the
 28.9519 +	<command moreinfo="none">grep</command> command to see if our
 28.9520 +	<quote>bad</quote> file is present in the working directory.
 28.9521 +	If it is, this revision is bad; if not, this revision is good.
 28.9522 +	<!-- BEGIN bisect.search.step1 -->
 28.9523 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">if grep -q 'i have a gub' *</userinput>
 28.9524 +<prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">then</userinput>
 28.9525 +<prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">  result=bad</userinput>
 28.9526 +<prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">else</userinput>
 28.9527 +<prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">  result=good</userinput>
 28.9528 +<prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">fi</userinput>
 28.9529 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo this revision is $result</userinput>
 28.9530 +this revision is bad
 28.9531 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg bisect --$result</userinput>
 28.9532 +Testing changeset 16:f1dd8bc690ae (12 changesets remaining, ~3 tests)
 28.9533 +0 files updated, 0 files merged, 6 files removed, 0 files unresolved
 28.9534 +</screen>
 28.9535 +<!-- END bisect.search.step1 -->
 28.9536 +</para>
 28.9537 +
 28.9538 +      <para id="x_146">This test looks like a perfect candidate for automation,
 28.9539 +	so let's turn it into a shell function.</para>
 28.9540 +      <!-- BEGIN bisect.search.mytest -->
 28.9541 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mytest() {</userinput>
 28.9542 +<prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">  if grep -q 'i have a gub' *</userinput>
 28.9543 +<prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">  then</userinput>
 28.9544 +<prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">    result=bad</userinput>
 28.9545 +<prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">  else</userinput>
 28.9546 +<prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">    result=good</userinput>
 28.9547 +<prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">  fi</userinput>
 28.9548 +<prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">  echo this revision is $result</userinput>
 28.9549 +<prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">  hg bisect --$result</userinput>
 28.9550 +<prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">}</userinput>
 28.9551 +</screen>
 28.9552 +<!-- END bisect.search.mytest -->
 28.9553 +
 28.9554 +
 28.9555 +      <para id="x_147">We can now run an entire test step with a single command,
 28.9556 +	<literal moreinfo="none">mytest</literal>.</para>
 28.9557 +
 28.9558 +      <!-- BEGIN bisect.search.step2 -->
 28.9559 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mytest</userinput>
 28.9560 +this revision is good
 28.9561 +Testing changeset 19:88d99d97058a (6 changesets remaining, ~2 tests)
 28.9562 +3 files updated, 0 files merged, 0 files removed, 0 files unresolved
 28.9563 +</screen>
 28.9564 +<!-- END bisect.search.step2 -->
 28.9565 +
 28.9566 +
 28.9567 +      <para id="x_148">A few more invocations of our canned test step command,
 28.9568 +	and we're done.</para>
 28.9569 +
 28.9570 +      <!-- BEGIN bisect.search.rest -->
 28.9571 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mytest</userinput>
 28.9572 +this revision is good
 28.9573 +Testing changeset 20:32a195a31d51 (3 changesets remaining, ~1 tests)
 28.9574 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 28.9575 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mytest</userinput>
 28.9576 +this revision is good
 28.9577 +Testing changeset 21:a2efe8e4f624 (2 changesets remaining, ~1 tests)
 28.9578 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 28.9579 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mytest</userinput>
 28.9580 +this revision is good
 28.9581 +The first bad revision is:
 28.9582 +changeset:   22:69f52b967ab8
 28.9583 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
 28.9584 +date:        Sun Aug 16 14:04:39 2009 +0000
 28.9585 +summary:     buggy changeset
 28.9586 +
 28.9587 +</screen>
 28.9588 +<!-- END bisect.search.rest -->
 28.9589 +
 28.9590 +
 28.9591 +      <para id="x_149">Even though we had 40 changesets to search through, the
 28.9592 +	<command role="hg-cmd" moreinfo="none">hg bisect</command> command let us find
 28.9593 +	the changeset that introduced our <quote>bug</quote> with only
 28.9594 +	five tests.  Because the number of tests that the <command role="hg-cmd" moreinfo="none">hg bisect</command> command performs grows
 28.9595 +	logarithmically with the number of changesets to search, the
 28.9596 +	advantage that it has over the <quote>brute force</quote>
 28.9597 +	search approach increases with every changeset you add.</para>
 28.9598 +
 28.9599 +    </sect2>
 28.9600 +    <sect2>
 28.9601 +      <title>Cleaning up after your search</title>
 28.9602 +
 28.9603 +      <para id="x_14a">When you're finished using the <command role="hg-cmd" moreinfo="none">hg
 28.9604 +	  bisect</command> command in a repository, you can use the
 28.9605 +	<command role="hg-cmd" moreinfo="none">hg bisect --reset</command> command to
 28.9606 +	drop the information it was using to drive your search.  The
 28.9607 +	command doesn't use much space, so it doesn't matter if you
 28.9608 +	forget to run this command.  However, <command role="hg-cmd" moreinfo="none">hg bisect</command> won't let you start a new
 28.9609 +	search in that repository until you do a <command role="hg-cmd" moreinfo="none">hg bisect --reset</command>.</para>
 28.9610 +
 28.9611 +      <!-- BEGIN bisect.search.reset -->
 28.9612 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg bisect --reset</userinput>
 28.9613 +</screen>
 28.9614 +<!-- END bisect.search.reset -->
 28.9615 +
 28.9616 +
 28.9617 +    </sect2>
 28.9618 +  </sect1>
 28.9619 +  <sect1>
 28.9620 +    <title>Tips for finding bugs effectively</title>
 28.9621 +
 28.9622 +    <sect2>
 28.9623 +      <title>Give consistent input</title>
 28.9624 +
 28.9625 +      <para id="x_14b">The <command role="hg-cmd" moreinfo="none">hg bisect</command> command
 28.9626 +	requires that you correctly report the result of every test
 28.9627 +	you perform.  If you tell it that a test failed when it really
 28.9628 +	succeeded, it <emphasis>might</emphasis> be able to detect the
 28.9629 +	inconsistency.  If it can identify an inconsistency in your
 28.9630 +	reports, it will tell you that a particular changeset is both
 28.9631 +	good and bad. However, it can't do this perfectly; it's about
 28.9632 +	as likely to report the wrong changeset as the source of the
 28.9633 +	bug.</para>
 28.9634 +
 28.9635 +    </sect2>
 28.9636 +    <sect2>
 28.9637 +      <title>Automate as much as possible</title>
 28.9638 +
 28.9639 +      <para id="x_14c">When I started using the <command role="hg-cmd" moreinfo="none">hg
 28.9640 +	  bisect</command> command, I tried a few times to run my
 28.9641 +	tests by hand, on the command line.  This is an approach that
 28.9642 +	I, at least, am not suited to.  After a few tries, I found
 28.9643 +	that I was making enough mistakes that I was having to restart
 28.9644 +	my searches several times before finally getting correct
 28.9645 +	results.</para>
 28.9646 +
 28.9647 +      <para id="x_14d">My initial problems with driving the <command role="hg-cmd" moreinfo="none">hg bisect</command> command by hand occurred
 28.9648 +	even with simple searches on small repositories; if the
 28.9649 +	problem you're looking for is more subtle, or the number of
 28.9650 +	tests that <command role="hg-cmd" moreinfo="none">hg bisect</command> must
 28.9651 +	perform increases, the likelihood of operator error ruining
 28.9652 +	the search is much higher.  Once I started automating my
 28.9653 +	tests, I had much better results.</para>
 28.9654 +
 28.9655 +      <para id="x_14e">The key to automated testing is twofold:</para>
 28.9656 +      <itemizedlist>
 28.9657 +	<listitem><para id="x_14f">always test for the same symptom, and</para>
 28.9658 +	</listitem>
 28.9659 +	<listitem><para id="x_150">always feed consistent input to the <command role="hg-cmd" moreinfo="none">hg bisect</command> command.</para>
 28.9660 +	</listitem></itemizedlist>
 28.9661 +      <para id="x_151">In my tutorial example above, the <command moreinfo="none">grep</command>
 28.9662 +	command tests for the symptom, and the <literal moreinfo="none">if</literal>
 28.9663 +	statement takes the result of this check and ensures that we
 28.9664 +	always feed the same input to the <command role="hg-cmd" moreinfo="none">hg
 28.9665 +	  bisect</command> command.  The <literal moreinfo="none">mytest</literal>
 28.9666 +	function marries these together in a reproducible way, so that
 28.9667 +	every test is uniform and consistent.</para>
 28.9668 +
 28.9669 +    </sect2>
 28.9670 +    <sect2>
 28.9671 +      <title>Check your results</title>
 28.9672 +
 28.9673 +      <para id="x_152">Because the output of a <command role="hg-cmd" moreinfo="none">hg
 28.9674 +	  bisect</command> search is only as good as the input you
 28.9675 +	give it, don't take the changeset it reports as the absolute
 28.9676 +	truth.  A simple way to cross-check its report is to manually
 28.9677 +	run your test at each of the following changesets:</para>
 28.9678 +      <itemizedlist>
 28.9679 +	<listitem><para id="x_153">The changeset that it reports as the first bad
 28.9680 +	    revision.  Your test should still report this as
 28.9681 +	    bad.</para>
 28.9682 +	</listitem>
 28.9683 +	<listitem><para id="x_154">The parent of that changeset (either parent,
 28.9684 +	    if it's a merge). Your test should report this changeset
 28.9685 +	    as good.</para>
 28.9686 +	</listitem>
 28.9687 +	<listitem><para id="x_155">A child of that changeset.  Your test should
 28.9688 +	    report this changeset as bad.</para>
 28.9689 +	</listitem></itemizedlist>
 28.9690 +
 28.9691 +    </sect2>
 28.9692 +    <sect2>
 28.9693 +      <title>Beware interference between bugs</title>
 28.9694 +
 28.9695 +      <para id="x_156">It's possible that your search for one bug could be
 28.9696 +	disrupted by the presence of another.  For example, let's say
 28.9697 +	your software crashes at revision 100, and worked correctly at
 28.9698 +	revision 50.  Unknown to you, someone else introduced a
 28.9699 +	different crashing bug at revision 60, and fixed it at
 28.9700 +	revision 80.  This could distort your results in one of
 28.9701 +	several ways.</para>
 28.9702 +
 28.9703 +      <para id="x_157">It is possible that this other bug completely
 28.9704 +	<quote>masks</quote> yours, which is to say that it occurs
 28.9705 +	before your bug has a chance to manifest itself.  If you can't
 28.9706 +	avoid that other bug (for example, it prevents your project
 28.9707 +	from building), and so can't tell whether your bug is present
 28.9708 +	in a particular changeset, the <command role="hg-cmd" moreinfo="none">hg
 28.9709 +	  bisect</command> command cannot help you directly.  Instead,
 28.9710 +	you can mark a changeset as untested by running <command role="hg-cmd" moreinfo="none">hg bisect --skip</command>.</para>
 28.9711 +
 28.9712 +      <para id="x_158">A different problem could arise if your test for a bug's
 28.9713 +	presence is not specific enough.  If you check for <quote>my
 28.9714 +	  program crashes</quote>, then both your crashing bug and an
 28.9715 +	unrelated crashing bug that masks it will look like the same
 28.9716 +	thing, and mislead <command role="hg-cmd" moreinfo="none">hg
 28.9717 +	  bisect</command>.</para>
 28.9718 +
 28.9719 +      <para id="x_159">Another useful situation in which to use <command role="hg-cmd" moreinfo="none">hg bisect --skip</command> is if you can't
 28.9720 +	test a revision because your project was in a broken and hence
 28.9721 +	untestable state at that revision, perhaps because someone
 28.9722 +	checked in a change that prevented the project from
 28.9723 +	building.</para>
 28.9724 +
 28.9725 +    </sect2>
 28.9726 +    <sect2>
 28.9727 +      <title>Bracket your search lazily</title>
 28.9728 +
 28.9729 +      <para id="x_15a">Choosing the first <quote>good</quote> and
 28.9730 +	<quote>bad</quote> changesets that will mark the end points of
 28.9731 +	your search is often easy, but it bears a little discussion
 28.9732 +	nevertheless.  From the perspective of <command role="hg-cmd" moreinfo="none">hg bisect</command>, the <quote>newest</quote>
 28.9733 +	changeset is conventionally <quote>bad</quote>, and the older
 28.9734 +	changeset is <quote>good</quote>.</para>
 28.9735 +
 28.9736 +      <para id="x_15b">If you're having trouble remembering when a suitable
 28.9737 +	<quote>good</quote> change was, so that you can tell <command role="hg-cmd" moreinfo="none">hg bisect</command>, you could do worse than
 28.9738 +	testing changesets at random.  Just remember to eliminate
 28.9739 +	contenders that can't possibly exhibit the bug (perhaps
 28.9740 +	because the feature with the bug isn't present yet) and those
 28.9741 +	where another problem masks the bug (as I discussed
 28.9742 +	above).</para>
 28.9743 +
 28.9744 +      <para id="x_15c">Even if you end up <quote>early</quote> by thousands of
 28.9745 +	changesets or months of history, you will only add a handful
 28.9746 +	of tests to the total number that <command role="hg-cmd" moreinfo="none">hg
 28.9747 +	  bisect</command> must perform, thanks to its logarithmic
 28.9748 +	behavior.</para>
 28.9749 +
 28.9750 +    </sect2>
 28.9751 +  </sect1>
 28.9752 +</chapter>
 28.9753 +
 28.9754 +<!--
 28.9755 +local variables: 
 28.9756 +sgml-parent-document: ("00book.xml" "book" "chapter")
 28.9757 +end:
 28.9758 +-->
 28.9759 +
 28.9760 +  <!-- BEGIN ch10 -->
 28.9761 +  <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
 28.9762 +
 28.9763 +<chapter id="chap:hook">
 28.9764 +  <?dbhtml filename="handling-repository-events-with-hooks.html"?>
 28.9765 +  <title>Handling repository events with hooks</title>
 28.9766 +
 28.9767 +  <para id="x_1e6">Mercurial offers a powerful mechanism to let you perform
 28.9768 +    automated actions in response to events that occur in a
 28.9769 +    repository.  In some cases, you can even control Mercurial's
 28.9770 +    response to those events.</para>
 28.9771 +
 28.9772 +  <para id="x_1e7">The name Mercurial uses for one of these actions is a
 28.9773 +    <emphasis>hook</emphasis>. Hooks are called
 28.9774 +    <quote>triggers</quote> in some revision control systems, but the
 28.9775 +    two names refer to the same idea.</para>
 28.9776 +
 28.9777 +  <sect1>
 28.9778 +    <title>An overview of hooks in Mercurial</title>
 28.9779 +
 28.9780 +    <para id="x_1e8">Here is a brief list of the hooks that Mercurial
 28.9781 +      supports. We will revisit each of these hooks in more detail
 28.9782 +      later, in <xref linkend="sec:hook:ref"/>.</para>
 28.9783 +
 28.9784 +    <para id="x_1f6">Each of the hooks whose description begins with the word
 28.9785 +      <quote>Controlling</quote> has the ability to determine whether
 28.9786 +      an activity can proceed.  If the hook succeeds, the activity may
 28.9787 +      proceed; if it fails, the activity is either not permitted or
 28.9788 +      undone, depending on the hook.</para>
 28.9789 +
 28.9790 +    <itemizedlist>
 28.9791 +      <listitem><para id="x_1e9"><literal role="hook" moreinfo="none">changegroup</literal>: This
 28.9792 +	  is run after a group of changesets has been brought into the
 28.9793 +	  repository from elsewhere.</para>
 28.9794 +      </listitem>
 28.9795 +      <listitem><para id="x_1ea"><literal role="hook" moreinfo="none">commit</literal>: This is
 28.9796 +	  run after a new changeset has been created in the local
 28.9797 +	  repository.</para>
 28.9798 +      </listitem>
 28.9799 +      <listitem><para id="x_1eb"><literal role="hook" moreinfo="none">incoming</literal>: This is
 28.9800 +	  run once for each new changeset that is brought into the
 28.9801 +	  repository from elsewhere.  Notice the difference from
 28.9802 +	  <literal role="hook" moreinfo="none">changegroup</literal>, which is run
 28.9803 +	  once per <emphasis>group</emphasis> of changesets brought
 28.9804 +	  in.</para>
 28.9805 +      </listitem>
 28.9806 +      <listitem><para id="x_1ec"><literal role="hook" moreinfo="none">outgoing</literal>: This is
 28.9807 +	  run after a group of changesets has been transmitted from
 28.9808 +	  this repository.</para>
 28.9809 +      </listitem>
 28.9810 +      <listitem><para id="x_1ed"><literal role="hook" moreinfo="none">prechangegroup</literal>:
 28.9811 +	  This is run before starting to bring a group of changesets
 28.9812 +	  into the repository.
 28.9813 +	</para>
 28.9814 +      </listitem>
 28.9815 +      <listitem><para id="x_1ee"><literal role="hook" moreinfo="none">precommit</literal>:
 28.9816 +	  Controlling. This is run before starting a commit.
 28.9817 +	</para>
 28.9818 +      </listitem>
 28.9819 +      <listitem><para id="x_1ef"><literal role="hook" moreinfo="none">preoutgoing</literal>:
 28.9820 +	  Controlling. This is run before starting to transmit a group
 28.9821 +	  of changesets from this repository.
 28.9822 +	</para>
 28.9823 +      </listitem>
 28.9824 +      <listitem><para id="x_1f0"><literal role="hook" moreinfo="none">pretag</literal>:
 28.9825 +	  Controlling. This is run before creating a tag.
 28.9826 +	</para>
 28.9827 +      </listitem>
 28.9828 +      <listitem><para id="x_1f1"><literal role="hook" moreinfo="none">pretxnchangegroup</literal>: Controlling. This
 28.9829 +	  is run after a group of changesets has been brought into the
 28.9830 +	  local repository from another, but before the transaction
 28.9831 +	  completes that will make the changes permanent in the
 28.9832 +	  repository.
 28.9833 +	</para>
 28.9834 +      </listitem>
 28.9835 +      <listitem><para id="x_1f2"><literal role="hook" moreinfo="none">pretxncommit</literal>:
 28.9836 +	  Controlling. This is run after a new changeset has been
 28.9837 +	  created in the local repository, but before the transaction
 28.9838 +	  completes that will make it permanent.
 28.9839 +	</para>
 28.9840 +      </listitem>
 28.9841 +      <listitem><para id="x_1f3"><literal role="hook" moreinfo="none">preupdate</literal>:
 28.9842 +	  Controlling. This is run before starting an update or merge
 28.9843 +	  of the working directory.
 28.9844 +	</para>
 28.9845 +      </listitem>
 28.9846 +      <listitem><para id="x_1f4"><literal role="hook" moreinfo="none">tag</literal>: This is run
 28.9847 +	  after a tag is created.
 28.9848 +	</para>
 28.9849 +      </listitem>
 28.9850 +      <listitem><para id="x_1f5"><literal role="hook" moreinfo="none">update</literal>: This is
 28.9851 +	  run after an update or merge of the working directory has
 28.9852 +	  finished.
 28.9853 +	</para>
 28.9854 +      </listitem></itemizedlist>
 28.9855 +
 28.9856 +  </sect1>
 28.9857 +  <sect1>
 28.9858 +    <title>Hooks and security</title>
 28.9859 +
 28.9860 +    <sect2>
 28.9861 +      <title>Hooks are run with your privileges</title>
 28.9862 +
 28.9863 +      <para id="x_1f7">When you run a Mercurial command in a repository, and the
 28.9864 +	command causes a hook to run, that hook runs on
 28.9865 +	<emphasis>your</emphasis> system, under
 28.9866 +	<emphasis>your</emphasis> user account, with
 28.9867 +	<emphasis>your</emphasis> privilege level.  Since hooks are
 28.9868 +	arbitrary pieces of executable code, you should treat them
 28.9869 +	with an appropriate level of suspicion.  Do not install a hook
 28.9870 +	unless you are confident that you know who created it and what
 28.9871 +	it does.
 28.9872 +      </para>
 28.9873 +
 28.9874 +      <para id="x_1f8">In some cases, you may be exposed to hooks that you did
 28.9875 +	not install yourself.  If you work with Mercurial on an
 28.9876 +	unfamiliar system, Mercurial will run hooks defined in that
 28.9877 +	system's global <filename role="special" moreinfo="none">~/.hgrc</filename>
 28.9878 +	file.
 28.9879 +      </para>
 28.9880 +
 28.9881 +      <para id="x_1f9">If you are working with a repository owned by another
 28.9882 +	user, Mercurial can run hooks defined in that user's
 28.9883 +	repository, but it will still run them as <quote>you</quote>.
 28.9884 +	For example, if you <command role="hg-cmd" moreinfo="none">hg pull</command>
 28.9885 +	from that repository, and its <filename role="special" moreinfo="none">.hg/hgrc</filename> defines a local <literal role="hook" moreinfo="none">outgoing</literal> hook, that hook will run
 28.9886 +	under your user account, even though you don't own that
 28.9887 +	repository.
 28.9888 +      </para>
 28.9889 +
 28.9890 +      <note>
 28.9891 +	<para id="x_1fa">  This only applies if you are pulling from a repository
 28.9892 +	  on a local or network filesystem.  If you're pulling over
 28.9893 +	  http or ssh, any <literal role="hook" moreinfo="none">outgoing</literal>
 28.9894 +	  hook will run under whatever account is executing the server
 28.9895 +	  process, on the server.
 28.9896 +	</para>
 28.9897 +      </note>
 28.9898 +
 28.9899 +      <para id="x_1fb">To see what hooks are defined in a repository,
 28.9900 +	use the <command role="hg-cmd" moreinfo="none">hg showconfig hooks</command>
 28.9901 +	command.  If you are working in one repository, but talking to
 28.9902 +	another that you do not own (e.g. using <command role="hg-cmd" moreinfo="none">hg pull</command> or <command role="hg-cmd" moreinfo="none">hg
 28.9903 +	  incoming</command>), remember that it is the other
 28.9904 +	repository's hooks you should be checking, not your own.
 28.9905 +      </para>
 28.9906 +    </sect2>
 28.9907 +
 28.9908 +    <sect2>
 28.9909 +      <title>Hooks do not propagate</title>
 28.9910 +
 28.9911 +      <para id="x_1fc">In Mercurial, hooks are not revision controlled, and do
 28.9912 +	not propagate when you clone, or pull from, a repository.  The
 28.9913 +	reason for this is simple: a hook is a completely arbitrary
 28.9914 +	piece of executable code.  It runs under your user identity,
 28.9915 +	with your privilege level, on your machine.
 28.9916 +      </para>
 28.9917 +
 28.9918 +      <para id="x_1fd">It would be extremely reckless for any distributed
 28.9919 +	revision control system to implement revision-controlled
 28.9920 +	hooks, as this would offer an easily exploitable way to
 28.9921 +	subvert the accounts of users of the revision control system.
 28.9922 +      </para>
 28.9923 +
 28.9924 +      <para id="x_1fe">Since Mercurial does not propagate hooks, if you are
 28.9925 +	collaborating with other people on a common project, you
 28.9926 +	should not assume that they are using the same Mercurial hooks
 28.9927 +	as you are, or that theirs are correctly configured.  You
 28.9928 +	should document the hooks you expect people to use.
 28.9929 +      </para>
 28.9930 +
 28.9931 +      <para id="x_1ff">In a corporate intranet, this is somewhat easier to
 28.9932 +	control, as you can for example provide a
 28.9933 +	<quote>standard</quote> installation of Mercurial on an NFS
 28.9934 +	filesystem, and use a site-wide <filename role="special" moreinfo="none">~/.hgrc</filename> file to define hooks that all users will
 28.9935 +	see.  However, this too has its limits; see below.
 28.9936 +      </para>
 28.9937 +    </sect2>
 28.9938 +
 28.9939 +    <sect2>
 28.9940 +      <title>Hooks can be overridden</title>
 28.9941 +
 28.9942 +      <para id="x_200">Mercurial allows you to override a hook definition by
 28.9943 +	redefining the hook.  You can disable it by setting its value
 28.9944 +	to the empty string, or change its behavior as you wish.
 28.9945 +      </para>
 28.9946 +
 28.9947 +      <para id="x_201">If you deploy a system- or site-wide <filename role="special" moreinfo="none">~/.hgrc</filename> file that defines some
 28.9948 +	hooks, you should thus understand that your users can disable
 28.9949 +	or override those hooks.
 28.9950 +      </para>
 28.9951 +    </sect2>
 28.9952 +
 28.9953 +    <sect2>
 28.9954 +      <title>Ensuring that critical hooks are run</title>
 28.9955 +
 28.9956 +      <para id="x_202">Sometimes you may want to enforce a policy that you do not
 28.9957 +	want others to be able to work around.  For example, you may
 28.9958 +	have a requirement that every changeset must pass a rigorous
 28.9959 +	set of tests.  Defining this requirement via a hook in a
 28.9960 +	site-wide <filename role="special" moreinfo="none">~/.hgrc</filename> won't
 28.9961 +	work for remote users on laptops, and of course local users
 28.9962 +	can subvert it at will by overriding the hook.
 28.9963 +      </para>
 28.9964 +
 28.9965 +      <para id="x_203">Instead, you can set up your policies for use of Mercurial
 28.9966 +	so that people are expected to propagate changes through a
 28.9967 +	well-known <quote>canonical</quote> server that you have
 28.9968 +	locked down and configured appropriately.
 28.9969 +      </para>
 28.9970 +
 28.9971 +      <para id="x_204">One way to do this is via a combination of social
 28.9972 +	engineering and technology.  Set up a restricted-access
 28.9973 +	account; users can push changes over the network to
 28.9974 +	repositories managed by this account, but they cannot log into
 28.9975 +	the account and run normal shell commands.  In this scenario,
 28.9976 +	a user can commit a changeset that contains any old garbage
 28.9977 +	they want.
 28.9978 +      </para>
 28.9979 +
 28.9980 +      <para id="x_205">When someone pushes a changeset to the server that
 28.9981 +	everyone pulls from, the server will test the changeset before
 28.9982 +	it accepts it as permanent, and reject it if it fails to pass
 28.9983 +	the test suite.  If people only pull changes from this
 28.9984 +	filtering server, it will serve to ensure that all changes
 28.9985 +	that people pull have been automatically vetted.
 28.9986 +      </para>
 28.9987 +
 28.9988 +    </sect2>
 28.9989 +  </sect1>
 28.9990 +
 28.9991 +  <sect1 id="sec:hook:simple">
 28.9992 +    <title>A short tutorial on using hooks</title>
 28.9993 +
 28.9994 +    <para id="x_212">It is easy to write a Mercurial hook.  Let's start with a
 28.9995 +      hook that runs when you finish a <command role="hg-cmd" moreinfo="none">hg
 28.9996 +	commit</command>, and simply prints the hash of the changeset
 28.9997 +      you just created.  The hook is called <literal role="hook" moreinfo="none">commit</literal>.
 28.9998 +    </para>
 28.9999 +
28.10000 +    <para id="x_213">All hooks follow the pattern in this example.</para>
28.10001 +
28.10002 +<!-- BEGIN hook.simple.init -->
28.10003 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init hook-test</userinput>
28.10004 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd hook-test</userinput>
28.10005 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo '[hooks]' &gt;&gt; .hg/hgrc</userinput>
28.10006 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'commit = echo committed $HG_NODE' &gt;&gt; .hg/hgrc</userinput>
28.10007 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat .hg/hgrc</userinput>
28.10008 +[hooks]
28.10009 +commit = echo committed $HG_NODE
28.10010 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a &gt; a</userinput>
28.10011 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add a</userinput>
28.10012 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'testing commit hook'</userinput>
28.10013 +committed 13a334d1e5ca83fea465aa779110eec3c5ddd6b1
28.10014 +</screen>
28.10015 +<!-- END hook.simple.init -->
28.10016 +
28.10017 +
28.10018 +    <para id="x_214">You add an entry to the <literal role="rc-hooks" moreinfo="none">hooks</literal> section of your <filename role="special" moreinfo="none">~/.hgrc</filename>.  On the left is the name of
28.10019 +      the event to trigger on; on the right is the action to take.  As
28.10020 +      you can see, you can run an arbitrary shell command in a hook.
28.10021 +      Mercurial passes extra information to the hook using environment
28.10022 +      variables (look for <envar>HG_NODE</envar> in the example).
28.10023 +    </para>
28.10024 +
28.10025 +    <sect2>
28.10026 +      <title>Performing multiple actions per event</title>
28.10027 +
28.10028 +      <para id="x_215">Quite often, you will want to define more than one hook
28.10029 +	for a particular kind of event, as shown below.</para>
28.10030 +
28.10031 +<!-- BEGIN hook.simple.ext -->
28.10032 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'commit.when = echo -n "date of commit: "; date' &gt;&gt; .hg/hgrc</userinput>
28.10033 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a &gt;&gt; a</userinput>
28.10034 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'i have two hooks'</userinput>
28.10035 +committed 3be6e2778fb853cbc7e5138d0b9c29386504670b
28.10036 +date of commit: Sun Aug 16 14:05:05 GMT 2009
28.10037 +</screen>
28.10038 +<!-- END hook.simple.ext -->
28.10039 +
28.10040 +
28.10041 +      <para id="x_216">Mercurial lets you do this by adding an
28.10042 +	<emphasis>extension</emphasis> to the end of a hook's name.
28.10043 +	You extend a hook's name by giving the name of the hook,
28.10044 +	followed by a full stop (the
28.10045 +	<quote><literal moreinfo="none">.</literal></quote> character), followed by
28.10046 +	some more text of your choosing.  For example, Mercurial will
28.10047 +	run both <literal moreinfo="none">commit.foo</literal> and
28.10048 +	<literal moreinfo="none">commit.bar</literal> when the
28.10049 +	<literal moreinfo="none">commit</literal> event occurs.
28.10050 +      </para>
28.10051 +
28.10052 +      <para id="x_217">To give a well-defined order of execution when there are
28.10053 +	multiple hooks defined for an event, Mercurial sorts hooks by
28.10054 +	extension, and executes the hook commands in this sorted
28.10055 +	order.  In the above example, it will execute
28.10056 +	<literal moreinfo="none">commit.bar</literal> before
28.10057 +	<literal moreinfo="none">commit.foo</literal>, and <literal moreinfo="none">commit</literal>
28.10058 +	before both.
28.10059 +      </para>
28.10060 +
28.10061 +      <para id="x_218">It is a good idea to use a somewhat descriptive
28.10062 +	extension when you define a new hook.  This will help you to
28.10063 +	remember what the hook was for.  If the hook fails, you'll get
28.10064 +	an error message that contains the hook name and extension, so
28.10065 +	using a descriptive extension could give you an immediate hint
28.10066 +	as to why the hook failed (see <xref linkend="sec:hook:perm"/> for an example).
28.10067 +      </para>
28.10068 +
28.10069 +    </sect2>
28.10070 +    <sect2 id="sec:hook:perm">
28.10071 +      <title>Controlling whether an activity can proceed</title>
28.10072 +
28.10073 +      <para id="x_219">In our earlier examples, we used the <literal role="hook" moreinfo="none">commit</literal> hook, which is run after a
28.10074 +	commit has completed.  This is one of several Mercurial hooks
28.10075 +	that run after an activity finishes.  Such hooks have no way
28.10076 +	of influencing the activity itself.
28.10077 +      </para>
28.10078 +
28.10079 +      <para id="x_21a">Mercurial defines a number of events that occur before an
28.10080 +	activity starts; or after it starts, but before it finishes.
28.10081 +	Hooks that trigger on these events have the added ability to
28.10082 +	choose whether the activity can continue, or will abort.
28.10083 +      </para>
28.10084 +
28.10085 +      <para id="x_21b">The <literal role="hook" moreinfo="none">pretxncommit</literal> hook runs
28.10086 +	after a commit has all but completed.  In other words, the
28.10087 +	metadata representing the changeset has been written out to
28.10088 +	disk, but the transaction has not yet been allowed to
28.10089 +	complete.  The <literal role="hook" moreinfo="none">pretxncommit</literal>
28.10090 +	hook has the ability to decide whether the transaction can
28.10091 +	complete, or must be rolled back.
28.10092 +      </para>
28.10093 +
28.10094 +      <para id="x_21c">If the <literal role="hook" moreinfo="none">pretxncommit</literal> hook
28.10095 +	exits with a status code of zero, the transaction is allowed
28.10096 +	to complete; the commit finishes; and the <literal role="hook" moreinfo="none">commit</literal> hook is run.  If the <literal role="hook" moreinfo="none">pretxncommit</literal> hook exits with a
28.10097 +	non-zero status code, the transaction is rolled back; the
28.10098 +	metadata representing the changeset is erased; and the
28.10099 +	<literal role="hook" moreinfo="none">commit</literal> hook is not run.
28.10100 +      </para>
28.10101 +
28.10102 +<!-- BEGIN hook.simple.pretxncommit -->
28.10103 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat check_bug_id</userinput>
28.10104 +#!/bin/sh
28.10105 +# check that a commit comment mentions a numeric bug id
28.10106 +hg log -r $1 --template {desc} | grep -q "\&lt;bug *[0-9]"
28.10107 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'pretxncommit.bug_id_required = ./check_bug_id $HG_NODE' &gt;&gt; .hg/hgrc</userinput>
28.10108 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a &gt;&gt; a</userinput>
28.10109 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'i am not mentioning a bug id'</userinput>
28.10110 +transaction abort!
28.10111 +rollback completed
28.10112 +abort: pretxncommit.bug_id_required hook exited with status 1
28.10113 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'i refer you to bug 666'</userinput>
28.10114 +committed 1a52be73a1ca4fa05e269f99003ed00912e8e836
28.10115 +date of commit: Sun Aug 16 14:05:05 GMT 2009
28.10116 +</screen>
28.10117 +<!-- END hook.simple.pretxncommit -->
28.10118 +
28.10119 +
28.10120 +      <para id="x_21d">The hook in the example above checks that a commit comment
28.10121 +	contains a bug ID.  If it does, the commit can complete.  If
28.10122 +	not, the commit is rolled back.
28.10123 +      </para>
28.10124 +
28.10125 +    </sect2>
28.10126 +  </sect1>
28.10127 +  <sect1>
28.10128 +    <title>Writing your own hooks</title>
28.10129 +
28.10130 +    <para id="x_21e">When you are writing a hook, you might find it useful to run
28.10131 +      Mercurial either with the <option role="hg-opt-global">-v</option> option, or the <envar role="rc-item-ui">verbose</envar> config item set to
28.10132 +      <quote>true</quote>.  When you do so, Mercurial will print a
28.10133 +      message before it calls each hook.
28.10134 +    </para>
28.10135 +
28.10136 +    <sect2 id="sec:hook:lang">
28.10137 +      <title>Choosing how your hook should run</title>
28.10138 +
28.10139 +      <para id="x_21f">You can write a hook either as a normal
28.10140 +	program—typically a shell script—or as a Python
28.10141 +	function that is executed within the Mercurial process.
28.10142 +      </para>
28.10143 +
28.10144 +      <para id="x_220">Writing a hook as an external program has the advantage
28.10145 +	that it requires no knowledge of Mercurial's internals.  You
28.10146 +	can call normal Mercurial commands to get any added
28.10147 +	information you need.  The trade-off is that external hooks
28.10148 +	are slower than in-process hooks.
28.10149 +      </para>
28.10150 +
28.10151 +      <para id="x_221">An in-process Python hook has complete access to the
28.10152 +	Mercurial API, and does not <quote>shell out</quote> to
28.10153 +	another process, so it is inherently faster than an external
28.10154 +	hook.  It is also easier to obtain much of the information
28.10155 +	that a hook requires by using the Mercurial API than by
28.10156 +	running Mercurial commands.
28.10157 +      </para>
28.10158 +
28.10159 +      <para id="x_222">If you are comfortable with Python, or require high
28.10160 +	performance, writing your hooks in Python may be a good
28.10161 +	choice.  However, when you have a straightforward hook to
28.10162 +	write and you don't need to care about performance (probably
28.10163 +	the majority of hooks), a shell script is perfectly fine.
28.10164 +      </para>
28.10165 +
28.10166 +    </sect2>
28.10167 +    <sect2 id="sec:hook:param">
28.10168 +      <title>Hook parameters</title>
28.10169 +
28.10170 +      <para id="x_223">Mercurial calls each hook with a set of well-defined
28.10171 +	parameters.  In Python, a parameter is passed as a keyword
28.10172 +	argument to your hook function.  For an external program, a
28.10173 +	parameter is passed as an environment variable.
28.10174 +      </para>
28.10175 +
28.10176 +      <para id="x_224">Whether your hook is written in Python or as a shell
28.10177 +	script, the hook-specific parameter names and values will be
28.10178 +	the same.  A boolean parameter will be represented as a
28.10179 +	boolean value in Python, but as the number 1 (for
28.10180 +	<quote>true</quote>) or 0 (for <quote>false</quote>) as an
28.10181 +	environment variable for an external hook.  If a hook
28.10182 +	parameter is named <literal moreinfo="none">foo</literal>, the keyword
28.10183 +	argument for a Python hook will also be named
28.10184 +	<literal moreinfo="none">foo</literal>, while the environment variable for an
28.10185 +	external hook will be named <literal moreinfo="none">HG_FOO</literal>.
28.10186 +      </para>
28.10187 +    </sect2>
28.10188 +
28.10189 +    <sect2>
28.10190 +      <title>Hook return values and activity control</title>
28.10191 +
28.10192 +      <para id="x_225">A hook that executes successfully must exit with a status
28.10193 +	of zero if external, or return boolean <quote>false</quote> if
28.10194 +	in-process.  Failure is indicated with a non-zero exit status
28.10195 +	from an external hook, or an in-process hook returning boolean
28.10196 +	<quote>true</quote>.  If an in-process hook raises an
28.10197 +	exception, the hook is considered to have failed.
28.10198 +      </para>
28.10199 +
28.10200 +      <para id="x_226">For a hook that controls whether an activity can proceed,
28.10201 +	zero/false means <quote>allow</quote>, while
28.10202 +	non-zero/true/exception means <quote>deny</quote>.
28.10203 +      </para>
28.10204 +    </sect2>
28.10205 +
28.10206 +    <sect2>
28.10207 +      <title>Writing an external hook</title>
28.10208 +
28.10209 +      <para id="x_227">When you define an external hook in your <filename role="special" moreinfo="none">~/.hgrc</filename> and the hook is run, its
28.10210 +	value is passed to your shell, which interprets it.  This
28.10211 +	means that you can use normal shell constructs in the body of
28.10212 +	the hook.
28.10213 +      </para>
28.10214 +
28.10215 +      <para id="x_228">An executable hook is always run with its current
28.10216 +	directory set to a repository's root directory.
28.10217 +      </para>
28.10218 +
28.10219 +      <para id="x_229">Each hook parameter is passed in as an environment
28.10220 +	variable; the name is upper-cased, and prefixed with the
28.10221 +	string <quote><literal moreinfo="none">HG_</literal></quote>.
28.10222 +      </para>
28.10223 +
28.10224 +      <para id="x_22a">With the exception of hook parameters, Mercurial does not
28.10225 +	set or modify any environment variables when running a hook.
28.10226 +	This is useful to remember if you are writing a site-wide hook
28.10227 +	that may be run by a number of different users with differing
28.10228 +	environment variables set. In multi-user situations, you
28.10229 +	should not rely on environment variables being set to the
28.10230 +	values you have in your environment when testing the hook.
28.10231 +      </para>
28.10232 +    </sect2>
28.10233 +
28.10234 +    <sect2>
28.10235 +      <title>Telling Mercurial to use an in-process hook</title>
28.10236 +
28.10237 +      <para id="x_22b">The <filename role="special" moreinfo="none">~/.hgrc</filename> syntax
28.10238 +	for defining an in-process hook is slightly different than for
28.10239 +	an executable hook.  The value of the hook must start with the
28.10240 +	text <quote><literal moreinfo="none">python:</literal></quote>, and continue
28.10241 +	with the fully-qualified name of a callable object to use as
28.10242 +	the hook's value.
28.10243 +      </para>
28.10244 +
28.10245 +      <para id="x_22c">The module in which a hook lives is automatically imported
28.10246 +	when a hook is run.  So long as you have the module name and
28.10247 +	<envar>PYTHONPATH</envar> right, it should <quote>just
28.10248 +	  work</quote>.
28.10249 +      </para>
28.10250 +
28.10251 +      <para id="x_22d">The following <filename role="special" moreinfo="none">~/.hgrc</filename>
28.10252 +	example snippet illustrates the syntax and meaning of the
28.10253 +	notions we just described.
28.10254 +      </para>
28.10255 +      <programlisting format="linespecific">[hooks]
28.10256 +commit.example = python:mymodule.submodule.myhook</programlisting>
28.10257 +      <para id="x_22e">When Mercurial runs the <literal moreinfo="none">commit.example</literal>
28.10258 +	hook, it imports <literal moreinfo="none">mymodule.submodule</literal>, looks
28.10259 +	for the callable object named <literal moreinfo="none">myhook</literal>, and
28.10260 +	calls it.
28.10261 +      </para>
28.10262 +    </sect2>
28.10263 +
28.10264 +    <sect2>
28.10265 +      <title>Writing an in-process hook</title>
28.10266 +
28.10267 +      <para id="x_22f">The simplest in-process hook does nothing, but illustrates
28.10268 +	the basic shape of the hook API:
28.10269 +      </para>
28.10270 +      <programlisting format="linespecific">def myhook(ui, repo, **kwargs):
28.10271 +    pass</programlisting>
28.10272 +      <para id="x_230">The first argument to a Python hook is always a <literal role="py-mod-mercurial.ui" moreinfo="none">ui</literal> object.  The second
28.10273 +	is a repository object; at the moment, it is always an
28.10274 +	instance of <literal role="py-mod-mercurial.localrepo" moreinfo="none">localrepository</literal>.
28.10275 +	Following these two arguments are other keyword arguments.
28.10276 +	Which ones are passed in depends on the hook being called, but
28.10277 +	a hook can ignore arguments it doesn't care about by dropping
28.10278 +	them into a keyword argument dict, as with
28.10279 +	<literal moreinfo="none">**kwargs</literal> above.
28.10280 +      </para>
28.10281 +
28.10282 +    </sect2>
28.10283 +  </sect1>
28.10284 +  <sect1>
28.10285 +    <title>Some hook examples</title>
28.10286 +
28.10287 +    <sect2>
28.10288 +      <title>Writing meaningful commit messages</title>
28.10289 +
28.10290 +      <para id="x_231">It's hard to imagine a useful commit message being very
28.10291 +	short. The simple <literal role="hook" moreinfo="none">pretxncommit</literal>
28.10292 +	hook of the example below will prevent you from committing a
28.10293 +	changeset with a message that is less than ten bytes long.
28.10294 +      </para>
28.10295 +
28.10296 +<!-- BEGIN hook.msglen.go -->
28.10297 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat .hg/hgrc</userinput>
28.10298 +[hooks]
28.10299 +pretxncommit.msglen = test `hg tip --template {desc} | wc -c` -ge 10
28.10300 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a &gt; a</userinput>
28.10301 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add a</userinput>
28.10302 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'too short'</userinput>
28.10303 +transaction abort!
28.10304 +rollback completed
28.10305 +abort: pretxncommit.msglen hook exited with status 1
28.10306 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'long enough'</userinput>
28.10307 +</screen>
28.10308 +<!-- END hook.msglen.go -->
28.10309 +
28.10310 +    </sect2>
28.10311 +
28.10312 +    <sect2>
28.10313 +      <title>Checking for trailing whitespace</title>
28.10314 +
28.10315 +      <para id="x_232">An interesting use of a commit-related hook is to help you
28.10316 +	to write cleaner code.  A simple example of <quote>cleaner
28.10317 +	  code</quote> is the dictum that a change should not add any
28.10318 +	new lines of text that contain <quote>trailing
28.10319 +	  whitespace</quote>.  Trailing whitespace is a series of
28.10320 +	space and tab characters at the end of a line of text.  In
28.10321 +	most cases, trailing whitespace is unnecessary, invisible
28.10322 +	noise, but it is occasionally problematic, and people often
28.10323 +	prefer to get rid of it.
28.10324 +      </para>
28.10325 +
28.10326 +      <para id="x_233">You can use either the <literal role="hook" moreinfo="none">precommit</literal> or <literal role="hook" moreinfo="none">pretxncommit</literal> hook to tell whether you
28.10327 +	have a trailing whitespace problem.  If you use the <literal role="hook" moreinfo="none">precommit</literal> hook, the hook will not know
28.10328 +	which files you are committing, so it will have to check every
28.10329 +	modified file in the repository for trailing white space.  If
28.10330 +	you want to commit a change to just the file
28.10331 +	<filename moreinfo="none">foo</filename>, but the file
28.10332 +	<filename moreinfo="none">bar</filename> contains trailing whitespace, doing a
28.10333 +	check in the <literal role="hook" moreinfo="none">precommit</literal> hook
28.10334 +	will prevent you from committing <filename moreinfo="none">foo</filename> due
28.10335 +	to the problem with <filename moreinfo="none">bar</filename>.  This doesn't
28.10336 +	seem right.
28.10337 +      </para>
28.10338 +
28.10339 +      <para id="x_234">Should you choose the <literal role="hook" moreinfo="none">pretxncommit</literal> hook, the check won't
28.10340 +	occur until just before the transaction for the commit
28.10341 +	completes.  This will allow you to check for problems only the
28.10342 +	exact files that are being committed.  However, if you entered
28.10343 +	the commit message interactively and the hook fails, the
28.10344 +	transaction will roll back; you'll have to re-enter the commit
28.10345 +	message after you fix the trailing whitespace and run <command role="hg-cmd" moreinfo="none">hg commit</command> again.
28.10346 +      </para>
28.10347 +
28.10348 +      <!-- BEGIN ch09/hook.ws.simple -->
28.10349 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat .hg/hgrc</userinput>
28.10350 +[hooks]
28.10351 +pretxncommit.whitespace = hg export tip | (! egrep -q '^\+.*[ \t]$')
28.10352 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'a ' &gt; a</userinput>
28.10353 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'test with trailing whitespace'</userinput>
28.10354 +adding a
28.10355 +transaction abort!
28.10356 +rollback completed
28.10357 +abort: pretxncommit.whitespace hook exited with status 1
28.10358 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'a' &gt; a</userinput>
28.10359 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'drop trailing whitespace and try again'</userinput>
28.10360 +</screen>
28.10361 +<!-- END ch09/hook.ws.simple -->
28.10362 +
28.10363 +
28.10364 +      <para id="x_235">In this example, we introduce a simple <literal role="hook" moreinfo="none">pretxncommit</literal> hook that checks for
28.10365 +	trailing whitespace.  This hook is short, but not very
28.10366 +	helpful.  It exits with an error status if a change adds a
28.10367 +	line with trailing whitespace to any file, but does not print
28.10368 +	any information that might help us to identify the offending
28.10369 +	file or line.  It also has the nice property of not paying
28.10370 +	attention to unmodified lines; only lines that introduce new
28.10371 +	trailing whitespace cause problems.
28.10372 +      </para>
28.10373 +
28.10374 +      <!-- BEGIN ch09/check_whitespace.py.lst -->
28.10375 +<programlisting format="linespecific">#!/usr/bin/env python
28.10376 +#
28.10377 +# save as .hg/check_whitespace.py and make executable
28.10378 +
28.10379 +import re
28.10380 +
28.10381 +def trailing_whitespace(difflines):
28.10382 +    # 
28.10383 +    linenum, header = 0, False
28.10384 +
28.10385 +    for line in difflines:
28.10386 +        if header:
28.10387 +            # remember the name of the file that this diff affects
28.10388 +            m = re.match(r'(?:---|\+\+\+) ([^\t]+)', line)
28.10389 +            if m and m.group(1) != '/dev/null':
28.10390 +                filename = m.group(1).split('/', 1)[-1]
28.10391 +            if line.startswith('+++ '):
28.10392 +                header = False
28.10393 +            continue
28.10394 +        if line.startswith('diff '):
28.10395 +            header = True
28.10396 +            continue
28.10397 +        # hunk header - save the line number
28.10398 +        m = re.match(r'@@ -\d+,\d+ \+(\d+),', line)
28.10399 +        if m:
28.10400 +            linenum = int(m.group(1))
28.10401 +            continue
28.10402 +        # hunk body - check for an added line with trailing whitespace
28.10403 +        m = re.match(r'\+.*\s$', line)
28.10404 +        if m:
28.10405 +            yield filename, linenum
28.10406 +        if line and line[0] in ' +':
28.10407 +            linenum += 1
28.10408 +
28.10409 +if __name__ == '__main__':
28.10410 +    import os, sys
28.10411 +    
28.10412 +    added = 0
28.10413 +    for filename, linenum in trailing_whitespace(os.popen('hg export tip')):
28.10414 +        print &gt;&gt; sys.stderr, ('%s, line %d: trailing whitespace added' %
28.10415 +                              (filename, linenum))
28.10416 +        added += 1
28.10417 +    if added:
28.10418 +        # save the commit message so we don't need to retype it
28.10419 +        os.system('hg tip --template "{desc}" &gt; .hg/commit.save')
28.10420 +        print &gt;&gt; sys.stderr, 'commit message saved to .hg/commit.save'
28.10421 +        sys.exit(1)</programlisting>
28.10422 +<!-- END ch09/check_whitespace.py.lst -->
28.10423 +
28.10424 +
28.10425 +      <para id="x_236">The above version is much more complex, but also more
28.10426 +	useful.  It parses a unified diff to see if any lines add
28.10427 +	trailing whitespace, and prints the name of the file and the
28.10428 +	line number of each such occurrence.  Even better, if the
28.10429 +	change adds trailing whitespace, this hook saves the commit
28.10430 +	comment and prints the name of the save file before exiting
28.10431 +	and telling Mercurial to roll the transaction back, so you can
28.10432 +	use the <option role="hg-opt-commit">-l filename</option>
28.10433 +	option to <command role="hg-cmd" moreinfo="none">hg commit</command> to reuse
28.10434 +	the saved commit message once you've corrected the problem.
28.10435 +      </para>
28.10436 +
28.10437 +      <!-- BEGIN ch09/hook.ws.better -->
28.10438 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat .hg/hgrc</userinput>
28.10439 +[hooks]
28.10440 +pretxncommit.whitespace = .hg/check_whitespace.py
28.10441 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'a ' &gt;&gt; a</userinput>
28.10442 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'add new line with trailing whitespace'</userinput>
28.10443 +a, line 2: trailing whitespace added
28.10444 +commit message saved to .hg/commit.save
28.10445 +transaction abort!
28.10446 +rollback completed
28.10447 +abort: pretxncommit.whitespace hook exited with status 1
28.10448 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">sed -i 's, *$,,' a</userinput>
28.10449 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'trimmed trailing whitespace'</userinput>
28.10450 +a, line 2: trailing whitespace added
28.10451 +commit message saved to .hg/commit.save
28.10452 +transaction abort!
28.10453 +rollback completed
28.10454 +abort: pretxncommit.whitespace hook exited with status 1
28.10455 +</screen>
28.10456 +<!-- END ch09/hook.ws.better -->
28.10457 +
28.10458 +
28.10459 +      <para id="x_237">As a final aside, note in the example above the
28.10460 +	use of <command moreinfo="none">sed</command>'s in-place editing feature to
28.10461 +	get rid of trailing whitespace from a file.  This is concise
28.10462 +	and useful enough that I will reproduce it here (using
28.10463 +	<command moreinfo="none">perl</command> for good measure).</para>
28.10464 +      <programlisting format="linespecific">perl -pi -e 's,\s+$,,' filename</programlisting>
28.10465 +
28.10466 +    </sect2>
28.10467 +  </sect1>
28.10468 +  <sect1>
28.10469 +    <title>Bundled hooks</title>
28.10470 +
28.10471 +    <para id="x_238">Mercurial ships with several bundled hooks.  You can find
28.10472 +      them in the <filename class="directory" moreinfo="none">hgext</filename>
28.10473 +      directory of a Mercurial source tree.  If you are using a
28.10474 +      Mercurial binary package, the hooks will be located in the
28.10475 +      <filename class="directory" moreinfo="none">hgext</filename> directory of
28.10476 +      wherever your package installer put Mercurial.
28.10477 +    </para>
28.10478 +
28.10479 +    <sect2>
28.10480 +      <title><literal role="hg-ext" moreinfo="none">acl</literal>—access
28.10481 +	control for parts of a repository</title>
28.10482 +
28.10483 +      <para id="x_239">The <literal role="hg-ext" moreinfo="none">acl</literal> extension lets
28.10484 +	you control which remote users are allowed to push changesets
28.10485 +	to a networked server.  You can protect any portion of a
28.10486 +	repository (including the entire repo), so that a specific
28.10487 +	remote user can push changes that do not affect the protected
28.10488 +	portion.
28.10489 +      </para>
28.10490 +
28.10491 +      <para id="x_23a">This extension implements access control based on the
28.10492 +	identity of the user performing a push,
28.10493 +	<emphasis>not</emphasis> on who committed the changesets
28.10494 +	they're pushing.  It makes sense to use this hook only if you
28.10495 +	have a locked-down server environment that authenticates
28.10496 +	remote users, and you want to be sure that only specific users
28.10497 +	are allowed to push changes to that server.
28.10498 +      </para>
28.10499 +
28.10500 +      <sect3>
28.10501 +	<title>Configuring the <literal role="hook" moreinfo="none">acl</literal>
28.10502 +	  hook</title>
28.10503 +
28.10504 +	<para id="x_23b">In order to manage incoming changesets, the <literal role="hg-ext" moreinfo="none">acl</literal> hook must be used as a
28.10505 +	  <literal role="hook" moreinfo="none">pretxnchangegroup</literal> hook.  This
28.10506 +	  lets it see which files are modified by each incoming
28.10507 +	  changeset, and roll back a group of changesets if they
28.10508 +	  modify <quote>forbidden</quote> files.  Example:
28.10509 +	</para>
28.10510 +	<programlisting format="linespecific">[hooks]
28.10511 +pretxnchangegroup.acl = python:hgext.acl.hook</programlisting>
28.10512 +
28.10513 +	<para id="x_23c">The <literal role="hg-ext" moreinfo="none">acl</literal> extension is
28.10514 +	  configured using three sections.
28.10515 +	</para>
28.10516 +
28.10517 +	<para id="x_23d">The <literal role="rc-acl" moreinfo="none">acl</literal> section has
28.10518 +	  only one entry, <envar role="rc-item-acl">sources</envar>,
28.10519 +	  which lists the sources of incoming changesets that the hook
28.10520 +	  should pay attention to.  You don't normally need to
28.10521 +	  configure this section.
28.10522 +	</para>
28.10523 +	<itemizedlist>
28.10524 +	  <listitem><para id="x_23e"><envar role="rc-item-acl">serve</envar>:
28.10525 +	      Control incoming changesets that are arriving from a
28.10526 +	      remote repository over http or ssh.  This is the default
28.10527 +	      value of <envar role="rc-item-acl">sources</envar>, and
28.10528 +	      usually the only setting you'll need for this
28.10529 +	      configuration item.
28.10530 +	    </para>
28.10531 +	  </listitem>
28.10532 +	  <listitem><para id="x_23f"><envar role="rc-item-acl">pull</envar>:
28.10533 +	      Control incoming changesets that are arriving via a pull
28.10534 +	      from a local repository.
28.10535 +	    </para>
28.10536 +	  </listitem>
28.10537 +	  <listitem><para id="x_240"><envar role="rc-item-acl">push</envar>:
28.10538 +	      Control incoming changesets that are arriving via a push
28.10539 +	      from a local repository.
28.10540 +	    </para>
28.10541 +	  </listitem>
28.10542 +	  <listitem><para id="x_241"><envar role="rc-item-acl">bundle</envar>:
28.10543 +	      Control incoming changesets that are arriving from
28.10544 +	      another repository via a bundle.
28.10545 +	    </para>
28.10546 +	  </listitem></itemizedlist>
28.10547 +
28.10548 +	<para id="x_242">The <literal role="rc-acl.allow" moreinfo="none">acl.allow</literal>
28.10549 +	  section controls the users that are allowed to add
28.10550 +	  changesets to the repository.  If this section is not
28.10551 +	  present, all users that are not explicitly denied are
28.10552 +	  allowed.  If this section is present, all users that are not
28.10553 +	  explicitly allowed are denied (so an empty section means
28.10554 +	  that all users are denied).
28.10555 +	</para>
28.10556 +
28.10557 +	<para id="x_243">The <literal role="rc-acl.deny" moreinfo="none">acl.deny</literal>
28.10558 +	  section determines which users are denied from adding
28.10559 +	  changesets to the repository.  If this section is not
28.10560 +	  present or is empty, no users are denied.
28.10561 +	</para>
28.10562 +
28.10563 +	<para id="x_244">The syntaxes for the <literal role="rc-acl.allow" moreinfo="none">acl.allow</literal> and <literal role="rc-acl.deny" moreinfo="none">acl.deny</literal> sections are
28.10564 +	  identical.  On the left of each entry is a glob pattern that
28.10565 +	  matches files or directories, relative to the root of the
28.10566 +	  repository; on the right, a user name.
28.10567 +	</para>
28.10568 +
28.10569 +	<para id="x_245">In the following example, the user
28.10570 +	  <literal moreinfo="none">docwriter</literal> can only push changes to the
28.10571 +	  <filename class="directory" moreinfo="none">docs</filename> subtree of the
28.10572 +	  repository, while <literal moreinfo="none">intern</literal> can push changes
28.10573 +	  to any file or directory except <filename class="directory" moreinfo="none">source/sensitive</filename>.
28.10574 +	</para>
28.10575 +	<programlisting format="linespecific">[acl.allow]
28.10576 +docs/** = docwriter
28.10577 +[acl.deny]
28.10578 +source/sensitive/** = intern</programlisting>
28.10579 +
28.10580 +      </sect3>
28.10581 +      <sect3>
28.10582 +	<title>Testing and troubleshooting</title>
28.10583 +
28.10584 +	<para id="x_246">If you want to test the <literal role="hg-ext" moreinfo="none">acl</literal> hook, run it with Mercurial's
28.10585 +	  debugging output enabled.  Since you'll probably be running
28.10586 +	  it on a server where it's not convenient (or sometimes
28.10587 +	  possible) to pass in the <option role="hg-opt-global">--debug</option> option, don't forget
28.10588 +	  that you can enable debugging output in your <filename role="special" moreinfo="none">~/.hgrc</filename>:
28.10589 +	</para>
28.10590 +	<programlisting format="linespecific">[ui]
28.10591 +debug = true</programlisting>
28.10592 +	<para id="x_247">With this enabled, the <literal role="hg-ext" moreinfo="none">acl</literal> hook will print enough
28.10593 +	  information to let you figure out why it is allowing or
28.10594 +	  forbidding pushes from specific users.
28.10595 +	</para>
28.10596 +
28.10597 +      </sect3>    </sect2>
28.10598 +
28.10599 +    <sect2>
28.10600 +      <title><literal role="hg-ext" moreinfo="none">bugzilla</literal>—integration with
28.10601 +	Bugzilla</title>
28.10602 +
28.10603 +      <para id="x_248">The <literal role="hg-ext" moreinfo="none">bugzilla</literal> extension
28.10604 +	adds a comment to a Bugzilla bug whenever it finds a reference
28.10605 +	to that bug ID in a commit comment.  You can install this hook
28.10606 +	on a shared server, so that any time a remote user pushes
28.10607 +	changes to this server, the hook gets run.
28.10608 +      </para>
28.10609 +
28.10610 +      <para id="x_249">It adds a comment to the bug that looks like this (you can
28.10611 +	configure the contents of the comment—see below):
28.10612 +      </para>
28.10613 +      <programlisting format="linespecific">Changeset aad8b264143a, made by Joe User
28.10614 +	&lt;joe.user@domain.com&gt; in the frobnitz repository, refers
28.10615 +	to this bug. For complete details, see
28.10616 +	http://hg.domain.com/frobnitz?cmd=changeset;node=aad8b264143a
28.10617 +	Changeset description: Fix bug 10483 by guarding against some
28.10618 +	NULL pointers</programlisting>
28.10619 +      <para id="x_24a">The value of this hook is that it automates the process of
28.10620 +	updating a bug any time a changeset refers to it.  If you
28.10621 +	configure the hook properly, it makes it easy for people to
28.10622 +	browse straight from a Bugzilla bug to a changeset that refers
28.10623 +	to that bug.
28.10624 +      </para>
28.10625 +
28.10626 +      <para id="x_24b">You can use the code in this hook as a starting point for
28.10627 +	some more exotic Bugzilla integration recipes.  Here are a few
28.10628 +	possibilities:
28.10629 +      </para>
28.10630 +      <itemizedlist>
28.10631 +	<listitem><para id="x_24c">Require that every changeset pushed to the
28.10632 +	    server have a valid bug ID in its commit comment.  In this
28.10633 +	    case, you'd want to configure the hook as a <literal role="hook" moreinfo="none">pretxncommit</literal> hook.  This would
28.10634 +	    allow the hook to reject changes that didn't contain bug
28.10635 +	    IDs.
28.10636 +	  </para>
28.10637 +	</listitem>
28.10638 +	<listitem><para id="x_24d">Allow incoming changesets to automatically
28.10639 +	    modify the <emphasis>state</emphasis> of a bug, as well as
28.10640 +	    simply adding a comment.  For example, the hook could
28.10641 +	    recognise the string <quote>fixed bug 31337</quote> as
28.10642 +	    indicating that it should update the state of bug 31337 to
28.10643 +	    <quote>requires testing</quote>.
28.10644 +	  </para>
28.10645 +	</listitem></itemizedlist>
28.10646 +
28.10647 +      <sect3 id="sec:hook:bugzilla:config">
28.10648 +	<title>Configuring the <literal role="hook" moreinfo="none">bugzilla</literal>
28.10649 +	  hook</title>
28.10650 +
28.10651 +	<para id="x_24e">You should configure this hook in your server's
28.10652 +	  <filename role="special" moreinfo="none">~/.hgrc</filename> as an <literal role="hook" moreinfo="none">incoming</literal> hook, for example as
28.10653 +	  follows:
28.10654 +	</para>
28.10655 +	<programlisting format="linespecific">[hooks]
28.10656 +incoming.bugzilla = python:hgext.bugzilla.hook</programlisting>
28.10657 +
28.10658 +	<para id="x_24f">Because of the specialised nature of this hook, and
28.10659 +	  because Bugzilla was not written with this kind of
28.10660 +	  integration in mind, configuring this hook is a somewhat
28.10661 +	  involved process.
28.10662 +	</para>
28.10663 +
28.10664 +	<para id="x_250">Before you begin, you must install the MySQL bindings
28.10665 +	  for Python on the host(s) where you'll be running the hook.
28.10666 +	  If this is not available as a binary package for your
28.10667 +	  system, you can download it from
28.10668 +	  <citation>web:mysql-python</citation>.
28.10669 +	</para>
28.10670 +
28.10671 +	<para id="x_251">Configuration information for this hook lives in the
28.10672 +	  <literal role="rc-bugzilla" moreinfo="none">bugzilla</literal> section of
28.10673 +	  your <filename role="special" moreinfo="none">~/.hgrc</filename>.
28.10674 +	</para>
28.10675 +	<itemizedlist>
28.10676 +	  <listitem><para id="x_252"><envar role="rc-item-bugzilla">version</envar>: The version
28.10677 +	      of Bugzilla installed on the server.  The database
28.10678 +	      schema that Bugzilla uses changes occasionally, so this
28.10679 +	      hook has to know exactly which schema to use.</para>
28.10680 +	  </listitem>
28.10681 +	  <listitem><para id="x_253"><envar role="rc-item-bugzilla">host</envar>:
28.10682 +	      The hostname of the MySQL server that stores your
28.10683 +	      Bugzilla data.  The database must be configured to allow
28.10684 +	      connections from whatever host you are running the
28.10685 +	      <literal role="hook" moreinfo="none">bugzilla</literal> hook on.
28.10686 +	    </para>
28.10687 +	  </listitem>
28.10688 +	  <listitem><para id="x_254"><envar role="rc-item-bugzilla">user</envar>:
28.10689 +	      The username with which to connect to the MySQL server.
28.10690 +	      The database must be configured to allow this user to
28.10691 +	      connect from whatever host you are running the <literal role="hook" moreinfo="none">bugzilla</literal> hook on.  This user
28.10692 +	      must be able to access and modify Bugzilla tables.  The
28.10693 +	      default value of this item is <literal moreinfo="none">bugs</literal>,
28.10694 +	      which is the standard name of the Bugzilla user in a
28.10695 +	      MySQL database.
28.10696 +	    </para>
28.10697 +	  </listitem>
28.10698 +	  <listitem><para id="x_255"><envar role="rc-item-bugzilla">password</envar>: The MySQL
28.10699 +	      password for the user you configured above.  This is
28.10700 +	      stored as plain text, so you should make sure that
28.10701 +	      unauthorised users cannot read the <filename role="special" moreinfo="none">~/.hgrc</filename> file where you
28.10702 +	      store this information.
28.10703 +	    </para>
28.10704 +	  </listitem>
28.10705 +	  <listitem><para id="x_256"><envar role="rc-item-bugzilla">db</envar>:
28.10706 +	      The name of the Bugzilla database on the MySQL server.
28.10707 +	      The default value of this item is
28.10708 +	      <literal moreinfo="none">bugs</literal>, which is the standard name of
28.10709 +	      the MySQL database where Bugzilla stores its data.
28.10710 +	    </para>
28.10711 +	  </listitem>
28.10712 +	  <listitem><para id="x_257"><envar role="rc-item-bugzilla">notify</envar>: If you want
28.10713 +	      Bugzilla to send out a notification email to subscribers
28.10714 +	      after this hook has added a comment to a bug, you will
28.10715 +	      need this hook to run a command whenever it updates the
28.10716 +	      database.  The command to run depends on where you have
28.10717 +	      installed Bugzilla, but it will typically look something
28.10718 +	      like this, if you have Bugzilla installed in <filename class="directory" moreinfo="none">/var/www/html/bugzilla</filename>:
28.10719 +	    </para>
28.10720 +	    <programlisting format="linespecific">cd /var/www/html/bugzilla &amp;&amp;
28.10721 +	      ./processmail %s nobody@nowhere.com</programlisting>
28.10722 +	  </listitem>
28.10723 +	  <listitem><para id="x_258">  The Bugzilla
28.10724 +	      <literal moreinfo="none">processmail</literal> program expects to be
28.10725 +	      given a bug ID (the hook replaces
28.10726 +	      <quote><literal moreinfo="none">%s</literal></quote> with the bug ID)
28.10727 +	      and an email address.  It also expects to be able to
28.10728 +	      write to some files in the directory that it runs in.
28.10729 +	      If Bugzilla and this hook are not installed on the same
28.10730 +	      machine, you will need to find a way to run
28.10731 +	      <literal moreinfo="none">processmail</literal> on the server where
28.10732 +	      Bugzilla is installed.
28.10733 +	    </para>
28.10734 +	  </listitem></itemizedlist>
28.10735 +
28.10736 +      </sect3>
28.10737 +      <sect3>
28.10738 +	<title>Mapping committer names to Bugzilla user names</title>
28.10739 +
28.10740 +	<para id="x_259">By default, the <literal role="hg-ext" moreinfo="none">bugzilla</literal> hook tries to use the
28.10741 +	  email address of a changeset's committer as the Bugzilla
28.10742 +	  user name with which to update a bug.  If this does not suit
28.10743 +	  your needs, you can map committer email addresses to
28.10744 +	  Bugzilla user names using a <literal role="rc-usermap" moreinfo="none">usermap</literal> section.
28.10745 +	</para>
28.10746 +
28.10747 +	<para id="x_25a">Each item in the <literal role="rc-usermap" moreinfo="none">usermap</literal> section contains an
28.10748 +	  email address on the left, and a Bugzilla user name on the
28.10749 +	  right.
28.10750 +	</para>
28.10751 +	<programlisting format="linespecific">[usermap]
28.10752 +jane.user@example.com = jane</programlisting>
28.10753 +	<para id="x_25b">You can either keep the <literal role="rc-usermap" moreinfo="none">usermap</literal> data in a normal
28.10754 +	  <filename role="special" moreinfo="none">~/.hgrc</filename>, or tell the
28.10755 +	  <literal role="hg-ext" moreinfo="none">bugzilla</literal> hook to read the
28.10756 +	  information from an external <filename moreinfo="none">usermap</filename>
28.10757 +	  file.  In the latter case, you can store
28.10758 +	  <filename moreinfo="none">usermap</filename> data by itself in (for example)
28.10759 +	  a user-modifiable repository.  This makes it possible to let
28.10760 +	  your users maintain their own <envar role="rc-item-bugzilla">usermap</envar> entries.  The main
28.10761 +	  <filename role="special" moreinfo="none">~/.hgrc</filename> file might look
28.10762 +	  like this:
28.10763 +	</para>
28.10764 +	<programlisting format="linespecific"># regular hgrc file refers to external usermap file
28.10765 +[bugzilla]
28.10766 +usermap = /home/hg/repos/userdata/bugzilla-usermap.conf</programlisting>
28.10767 +	<para id="x_25c">While the <filename moreinfo="none">usermap</filename> file that it
28.10768 +	  refers to might look like this:
28.10769 +	</para>
28.10770 +	<programlisting format="linespecific"># bugzilla-usermap.conf - inside a hg repository
28.10771 +[usermap] stephanie@example.com = steph</programlisting>
28.10772 +
28.10773 +      </sect3>
28.10774 +      <sect3>
28.10775 +	<title>Configuring the text that gets added to a bug</title>
28.10776 +
28.10777 +	<para id="x_25d">You can configure the text that this hook adds as a
28.10778 +	  comment; you specify it in the form of a Mercurial template.
28.10779 +	  Several <filename role="special" moreinfo="none">~/.hgrc</filename> entries
28.10780 +	  (still in the <literal role="rc-bugzilla" moreinfo="none">bugzilla</literal>
28.10781 +	  section) control this behavior.
28.10782 +	</para>
28.10783 +	<itemizedlist>
28.10784 +	  <listitem><para id="x_25e"><literal moreinfo="none">strip</literal>: The number of
28.10785 +	      leading path elements to strip from a repository's path
28.10786 +	      name to construct a partial path for a URL. For example,
28.10787 +	      if the repositories on your server live under <filename class="directory" moreinfo="none">/home/hg/repos</filename>, and you
28.10788 +	      have a repository whose path is <filename class="directory" moreinfo="none">/home/hg/repos/app/tests</filename>,
28.10789 +	      then setting <literal moreinfo="none">strip</literal> to
28.10790 +	      <literal moreinfo="none">4</literal> will give a partial path of
28.10791 +	      <filename class="directory" moreinfo="none">app/tests</filename>.  The
28.10792 +	      hook will make this partial path available when
28.10793 +	      expanding a template, as <literal moreinfo="none">webroot</literal>.
28.10794 +	    </para>
28.10795 +	  </listitem>
28.10796 +	  <listitem><para id="x_25f"><literal moreinfo="none">template</literal>: The text of the
28.10797 +	      template to use.  In addition to the usual
28.10798 +	      changeset-related variables, this template can use
28.10799 +	      <literal moreinfo="none">hgweb</literal> (the value of the
28.10800 +	      <literal moreinfo="none">hgweb</literal> configuration item above) and
28.10801 +	      <literal moreinfo="none">webroot</literal> (the path constructed using
28.10802 +	      <literal moreinfo="none">strip</literal> above).
28.10803 +	    </para>
28.10804 +	  </listitem></itemizedlist>
28.10805 +
28.10806 +	<para id="x_260">In addition, you can add a <envar role="rc-item-web">baseurl</envar> item to the <literal role="rc-web" moreinfo="none">web</literal> section of your <filename role="special" moreinfo="none">~/.hgrc</filename>.  The <literal role="hg-ext" moreinfo="none">bugzilla</literal> hook will make this
28.10807 +	  available when expanding a template, as the base string to
28.10808 +	  use when constructing a URL that will let users browse from
28.10809 +	  a Bugzilla comment to view a changeset.  Example:
28.10810 +	</para>
28.10811 +	<programlisting format="linespecific">[web]
28.10812 +baseurl = http://hg.domain.com/</programlisting>
28.10813 +
28.10814 +	<para id="x_261">Here is an example set of <literal role="hg-ext" moreinfo="none">bugzilla</literal> hook config information.
28.10815 +	</para>
28.10816 +
28.10817 +	<!-- BEGIN ch10/bugzilla-config.lst -->
28.10818 +<programlisting format="linespecific">[bugzilla]
28.10819 +host = bugzilla.example.com
28.10820 +password = mypassword version = 2.16
28.10821 +# server-side repos live in /home/hg/repos, so strip 4 leading
28.10822 +# separators
28.10823 +strip = 4
28.10824 +hgweb = http://hg.example.com/
28.10825 +usermap = /home/hg/repos/notify/bugzilla.conf
28.10826 +template = Changeset {node|short}, made by {author} in the {webroot}
28.10827 +  repo, refers to this bug.\n
28.10828 +  For complete details, see
28.10829 +  {hgweb}{webroot}?cmd=changeset;node={node|short}\n
28.10830 +  Changeset description:\n
28.10831 +  \t{desc|tabindent}</programlisting>
28.10832 +<!-- END ch10/bugzilla-config.lst -->
28.10833 +
28.10834 +
28.10835 +      </sect3>
28.10836 +      <sect3>
28.10837 +	<title>Testing and troubleshooting</title>
28.10838 +
28.10839 +	<para id="x_262">The most common problems with configuring the <literal role="hg-ext" moreinfo="none">bugzilla</literal> hook relate to running
28.10840 +	  Bugzilla's <filename moreinfo="none">processmail</filename> script and
28.10841 +	  mapping committer names to user names.
28.10842 +	</para>
28.10843 +
28.10844 +	<para id="x_263">Recall from <xref linkend="sec:hook:bugzilla:config"/> above that the user
28.10845 +	  that runs the Mercurial process on the server is also the
28.10846 +	  one that will run the <filename moreinfo="none">processmail</filename>
28.10847 +	  script.  The <filename moreinfo="none">processmail</filename> script
28.10848 +	  sometimes causes Bugzilla to write to files in its
28.10849 +	  configuration directory, and Bugzilla's configuration files
28.10850 +	  are usually owned by the user that your web server runs
28.10851 +	  under.
28.10852 +	</para>
28.10853 +
28.10854 +	<para id="x_264">You can cause <filename moreinfo="none">processmail</filename> to be run
28.10855 +	  with the suitable user's identity using the
28.10856 +	  <command moreinfo="none">sudo</command> command.  Here is an example entry
28.10857 +	  for a <filename moreinfo="none">sudoers</filename> file.
28.10858 +	</para>
28.10859 +	<programlisting format="linespecific">hg_user = (httpd_user)
28.10860 +NOPASSWD: /var/www/html/bugzilla/processmail-wrapper %s</programlisting>
28.10861 +	<para id="x_265">This allows the <literal moreinfo="none">hg_user</literal> user to run a
28.10862 +	  <filename moreinfo="none">processmail-wrapper</filename> program under the
28.10863 +	  identity of <literal moreinfo="none">httpd_user</literal>.
28.10864 +	</para>
28.10865 +
28.10866 +	<para id="x_266">This indirection through a wrapper script is necessary,
28.10867 +	  because <filename moreinfo="none">processmail</filename> expects to be run
28.10868 +	  with its current directory set to wherever you installed
28.10869 +	  Bugzilla; you can't specify that kind of constraint in a
28.10870 +	  <filename moreinfo="none">sudoers</filename> file.  The contents of the
28.10871 +	  wrapper script are simple:
28.10872 +	</para>
28.10873 +	<programlisting format="linespecific">#!/bin/sh
28.10874 +cd `dirname $0` &amp;&amp; ./processmail "$1" nobody@example.com</programlisting>
28.10875 +	<para id="x_267">It doesn't seem to matter what email address you pass to
28.10876 +	  <filename moreinfo="none">processmail</filename>.
28.10877 +	</para>
28.10878 +
28.10879 +	<para id="x_268">If your <literal role="rc-usermap" moreinfo="none">usermap</literal> is
28.10880 +	  not set up correctly, users will see an error message from
28.10881 +	  the <literal role="hg-ext" moreinfo="none">bugzilla</literal> hook when they
28.10882 +	  push changes to the server.  The error message will look
28.10883 +	  like this:
28.10884 +	</para>
28.10885 +	<programlisting format="linespecific">cannot find bugzilla user id for john.q.public@example.com</programlisting>
28.10886 +	<para id="x_269">What this means is that the committer's address,
28.10887 +	  <literal moreinfo="none">john.q.public@example.com</literal>, is not a valid
28.10888 +	  Bugzilla user name, nor does it have an entry in your
28.10889 +	  <literal role="rc-usermap" moreinfo="none">usermap</literal> that maps it to
28.10890 +	  a valid Bugzilla user name.
28.10891 +	</para>
28.10892 +
28.10893 +      </sect3>    </sect2>
28.10894 +
28.10895 +    <sect2>
28.10896 +      <title><literal role="hg-ext" moreinfo="none">notify</literal>—send email
28.10897 +	notifications</title>
28.10898 +
28.10899 +      <para id="x_26a">Although Mercurial's built-in web server provides RSS
28.10900 +	feeds of changes in every repository, many people prefer to
28.10901 +	receive change notifications via email.  The <literal role="hg-ext" moreinfo="none">notify</literal> hook lets you send out
28.10902 +	notifications to a set of email addresses whenever changesets
28.10903 +	arrive that those subscribers are interested in.
28.10904 +      </para>
28.10905 +
28.10906 +      <para id="x_26b">As with the <literal role="hg-ext" moreinfo="none">bugzilla</literal>
28.10907 +	hook, the <literal role="hg-ext" moreinfo="none">notify</literal> hook is
28.10908 +	template-driven, so you can customise the contents of the
28.10909 +	notification messages that it sends.
28.10910 +      </para>
28.10911 +
28.10912 +      <para id="x_26c">By default, the <literal role="hg-ext" moreinfo="none">notify</literal>
28.10913 +	hook includes a diff of every changeset that it sends out; you
28.10914 +	can limit the size of the diff, or turn this feature off
28.10915 +	entirely.  It is useful for letting subscribers review changes
28.10916 +	immediately, rather than clicking to follow a URL.
28.10917 +      </para>
28.10918 +
28.10919 +      <sect3>
28.10920 +	<title>Configuring the <literal role="hg-ext" moreinfo="none">notify</literal>
28.10921 +	  hook</title>
28.10922 +
28.10923 +	<para id="x_26d">You can set up the <literal role="hg-ext" moreinfo="none">notify</literal> hook to send one email
28.10924 +	  message per incoming changeset, or one per incoming group of
28.10925 +	  changesets (all those that arrived in a single pull or
28.10926 +	  push).
28.10927 +	</para>
28.10928 +	<programlisting format="linespecific">[hooks]
28.10929 +# send one email per group of changes
28.10930 +changegroup.notify = python:hgext.notify.hook
28.10931 +# send one email per change
28.10932 +incoming.notify = python:hgext.notify.hook</programlisting>
28.10933 +
28.10934 +	<para id="x_26e">Configuration information for this hook lives in the
28.10935 +	  <literal role="rc-notify" moreinfo="none">notify</literal> section of a
28.10936 +	  <filename role="special" moreinfo="none">~/.hgrc</filename> file.
28.10937 +	</para>
28.10938 +	<itemizedlist>
28.10939 +	  <listitem><para id="x_26f"><envar role="rc-item-notify">test</envar>:
28.10940 +	      By default, this hook does not send out email at all;
28.10941 +	      instead, it prints the message that it
28.10942 +	      <emphasis>would</emphasis> send.  Set this item to
28.10943 +	      <literal moreinfo="none">false</literal> to allow email to be sent. The
28.10944 +	      reason that sending of email is turned off by default is
28.10945 +	      that it takes several tries to configure this extension
28.10946 +	      exactly as you would like, and it would be bad form to
28.10947 +	      spam subscribers with a number of <quote>broken</quote>
28.10948 +	      notifications while you debug your configuration.
28.10949 +	    </para>
28.10950 +	  </listitem>
28.10951 +	  <listitem><para id="x_270"><envar role="rc-item-notify">config</envar>:
28.10952 +	      The path to a configuration file that contains
28.10953 +	      subscription information.  This is kept separate from
28.10954 +	      the main <filename role="special" moreinfo="none">~/.hgrc</filename> so
28.10955 +	      that you can maintain it in a repository of its own.
28.10956 +	      People can then clone that repository, update their
28.10957 +	      subscriptions, and push the changes back to your server.
28.10958 +	    </para>
28.10959 +	  </listitem>
28.10960 +	  <listitem><para id="x_271"><envar role="rc-item-notify">strip</envar>:
28.10961 +	      The number of leading path separator characters to strip
28.10962 +	      from a repository's path, when deciding whether a
28.10963 +	      repository has subscribers.  For example, if the
28.10964 +	      repositories on your server live in <filename class="directory" moreinfo="none">/home/hg/repos</filename>, and
28.10965 +	      <literal role="hg-ext" moreinfo="none">notify</literal> is considering a
28.10966 +	      repository named <filename class="directory" moreinfo="none">/home/hg/repos/shared/test</filename>, 
28.10967 +	      setting <envar role="rc-item-notify">strip</envar> to
28.10968 +	      <literal moreinfo="none">4</literal> will cause <literal role="hg-ext" moreinfo="none">notify</literal> to trim the path it
28.10969 +	      considers down to <filename class="directory" moreinfo="none">shared/test</filename>, and it will
28.10970 +	      match subscribers against that.
28.10971 +	    </para>
28.10972 +	  </listitem>
28.10973 +	  <listitem><para id="x_272"><envar role="rc-item-notify">template</envar>: The template
28.10974 +	      text to use when sending messages.  This specifies both
28.10975 +	      the contents of the message header and its body.
28.10976 +	    </para>
28.10977 +	  </listitem>
28.10978 +	  <listitem><para id="x_273"><envar role="rc-item-notify">maxdiff</envar>: The maximum
28.10979 +	      number of lines of diff data to append to the end of a
28.10980 +	      message.  If a diff is longer than this, it is
28.10981 +	      truncated.  By default, this is set to 300.  Set this to
28.10982 +	      <literal moreinfo="none">0</literal> to omit diffs from notification
28.10983 +	      emails.
28.10984 +	    </para>
28.10985 +	  </listitem>
28.10986 +	  <listitem><para id="x_274"><envar role="rc-item-notify">sources</envar>: A list of
28.10987 +	      sources of changesets to consider.  This lets you limit
28.10988 +	      <literal role="hg-ext" moreinfo="none">notify</literal> to only sending
28.10989 +	      out email about changes that remote users pushed into
28.10990 +	      this repository via a server, for example.  See 
28.10991 +	      <xref linkend="sec:hook:sources"/> for the sources you
28.10992 +	      can specify here.
28.10993 +	    </para>
28.10994 +	  </listitem></itemizedlist>
28.10995 +
28.10996 +	<para id="x_275">If you set the <envar role="rc-item-web">baseurl</envar>
28.10997 +	  item in the <literal role="rc-web" moreinfo="none">web</literal> section,
28.10998 +	  you can use it in a template; it will be available as
28.10999 +	  <literal moreinfo="none">webroot</literal>.
28.11000 +	</para>
28.11001 +
28.11002 +	<para id="x_276">Here is an example set of <literal role="hg-ext" moreinfo="none">notify</literal> configuration information.
28.11003 +	</para>
28.11004 +
28.11005 +	<!-- BEGIN ch10/notify-config.lst -->
28.11006 +<programlisting format="linespecific">[notify]
28.11007 +# really send email
28.11008 +test = false
28.11009 +# subscriber data lives in the notify repo
28.11010 +config = /home/hg/repos/notify/notify.conf
28.11011 +# repos live in /home/hg/repos on server, so strip 4 "/" chars
28.11012 +strip = 4
28.11013 +template = X-Hg-Repo: {webroot}\n
28.11014 +  Subject: {webroot}: {desc|firstline|strip}\n
28.11015 +  From: {author}
28.11016 +  \n\n
28.11017 +  changeset {node|short} in {root}
28.11018 +  \n\ndetails:
28.11019 +  {baseurl}{webroot}?cmd=changeset;node={node|short}
28.11020 +  description: {desc|tabindent|strip}
28.11021 +
28.11022 +[web]
28.11023 +baseurl =
28.11024 +http://hg.example.com/</programlisting>
28.11025 +<!-- END ch10/notify-config.lst -->
28.11026 +
28.11027 +
28.11028 +	<para id="x_277">This will produce a message that looks like the
28.11029 +	  following:
28.11030 +	</para>
28.11031 +
28.11032 +	<!-- BEGIN ch10/notify-config-mail.lst -->
28.11033 +<programlisting format="linespecific">X-Hg-Repo: tests/slave
28.11034 +Subject: tests/slave: Handle error case when slave has no buffers
28.11035 +Date: Wed,  2 Aug 2006 15:25:46 -0700 (PDT)
28.11036 +
28.11037 +changeset 3cba9bfe74b5 in /home/hg/repos/tests/slave
28.11038 +
28.11039 +details:
28.11040 +http://hg.example.com/tests/slave?cmd=changeset;node=3cba9bfe74b5 
28.11041 +
28.11042 +description: Handle error case when slave has no buffers
28.11043 +
28.11044 +diffs (54 lines):
28.11045 +diff -r 9d95df7cf2ad -r 3cba9bfe74b5 include/tests.h
28.11046 +--- a/include/tests.h      Wed Aug 02 15:19:52 2006 -0700
28.11047 ++++ b/include/tests.h      Wed Aug 02 15:25:26 2006 -0700
28.11048 +@@ -212,6 +212,15 @@ static __inline__
28.11049 +void test_headers(void *h)
28.11050 +[...snip...]</programlisting>
28.11051 +<!-- END ch10/notify-config-mail.lst -->
28.11052 +
28.11053 +
28.11054 +      </sect3>
28.11055 +      <sect3>
28.11056 +	<title>Testing and troubleshooting</title>
28.11057 +
28.11058 +	<para id="x_278">Do not forget that by default, the <literal role="hg-ext" moreinfo="none">notify</literal> extension <emphasis>will not
28.11059 +	  send any mail</emphasis> until you explicitly configure it to do so,
28.11060 +	  by setting <envar role="rc-item-notify">test</envar> to
28.11061 +	  <literal moreinfo="none">false</literal>.  Until you do that, it simply
28.11062 +	  prints the message it <emphasis>would</emphasis> send.
28.11063 +	</para>
28.11064 +
28.11065 +      </sect3>
28.11066 +    </sect2>
28.11067 +  </sect1>
28.11068 +  <sect1 id="sec:hook:ref">
28.11069 +    <title>Information for writers of hooks</title>
28.11070 +
28.11071 +    <sect2>
28.11072 +      <title>In-process hook execution</title>
28.11073 +
28.11074 +      <para id="x_279">An in-process hook is called with arguments of the
28.11075 +	following form:
28.11076 +      </para>
28.11077 +      <programlisting format="linespecific">def myhook(ui, repo, **kwargs): pass</programlisting>
28.11078 +      <para id="x_27a">The <literal moreinfo="none">ui</literal> parameter is a <literal role="py-mod-mercurial.ui" moreinfo="none">ui</literal> object. The
28.11079 +	<literal moreinfo="none">repo</literal> parameter is a <literal role="py-mod-mercurial.localrepo" moreinfo="none">localrepository</literal>
28.11080 +	object.  The names and values of the
28.11081 +	<literal moreinfo="none">**kwargs</literal> parameters depend on the hook
28.11082 +	being invoked, with the following common features:
28.11083 +      </para>
28.11084 +      <itemizedlist>
28.11085 +	<listitem><para id="x_27b">If a parameter is named
28.11086 +	    <literal moreinfo="none">node</literal> or <literal moreinfo="none">parentN</literal>, it
28.11087 +	    will contain a hexadecimal changeset ID. The empty string
28.11088 +	    is used to represent <quote>null changeset ID</quote>
28.11089 +	    instead of a string of zeroes.
28.11090 +	  </para>
28.11091 +	</listitem>
28.11092 +	<listitem><para id="x_27c">If a parameter is named
28.11093 +	    <literal moreinfo="none">url</literal>, it will contain the URL of a
28.11094 +	    remote repository, if that can be determined.
28.11095 +	  </para>
28.11096 +	</listitem>
28.11097 +	<listitem><para id="x_27d">Boolean-valued parameters are represented as
28.11098 +	    Python <literal moreinfo="none">bool</literal> objects.
28.11099 +	  </para>
28.11100 +	</listitem></itemizedlist>
28.11101 +
28.11102 +      <para id="x_27e">An in-process hook is called without a change to the
28.11103 +	process's working directory (unlike external hooks, which are
28.11104 +	run in the root of the repository).  It must not change the
28.11105 +	process's working directory, or it will cause any calls it
28.11106 +	makes into the Mercurial API to fail.
28.11107 +      </para>
28.11108 +
28.11109 +      <para id="x_27f">If a hook returns a boolean <quote>false</quote> value, it
28.11110 +	is considered to have succeeded.  If it returns a boolean
28.11111 +	<quote>true</quote> value or raises an exception, it is
28.11112 +	considered to have failed.  A useful way to think of the
28.11113 +	calling convention is <quote>tell me if you fail</quote>.
28.11114 +      </para>
28.11115 +
28.11116 +      <para id="x_280">Note that changeset IDs are passed into Python hooks as
28.11117 +	hexadecimal strings, not the binary hashes that Mercurial's
28.11118 +	APIs normally use.  To convert a hash from hex to binary, use
28.11119 +	the <literal moreinfo="none">bin</literal> function.
28.11120 +      </para>
28.11121 +    </sect2>
28.11122 +
28.11123 +    <sect2>
28.11124 +      <title>External hook execution</title>
28.11125 +
28.11126 +      <para id="x_281">An external hook is passed to the shell of the user
28.11127 +	running Mercurial. Features of that shell, such as variable
28.11128 +	substitution and command redirection, are available.  The hook
28.11129 +	is run in the root directory of the repository (unlike
28.11130 +	in-process hooks, which are run in the same directory that
28.11131 +	Mercurial was run in).
28.11132 +      </para>
28.11133 +
28.11134 +      <para id="x_282">Hook parameters are passed to the hook as environment
28.11135 +	variables.  Each environment variable's name is converted in
28.11136 +	upper case and prefixed with the string
28.11137 +	<quote><literal moreinfo="none">HG_</literal></quote>.  For example, if the
28.11138 +	name of a parameter is <quote><literal moreinfo="none">node</literal></quote>,
28.11139 +	the name of the environment variable representing that
28.11140 +	parameter will be <quote><literal moreinfo="none">HG_NODE</literal></quote>.
28.11141 +      </para>
28.11142 +
28.11143 +      <para id="x_283">A boolean parameter is represented as the string
28.11144 +	<quote><literal moreinfo="none">1</literal></quote> for <quote>true</quote>,
28.11145 +	<quote><literal moreinfo="none">0</literal></quote> for <quote>false</quote>.
28.11146 +	If an environment variable is named <envar>HG_NODE</envar>,
28.11147 +	<envar>HG_PARENT1</envar> or <envar>HG_PARENT2</envar>, it
28.11148 +	contains a changeset ID represented as a hexadecimal string.
28.11149 +	The empty string is used to represent <quote>null changeset
28.11150 +	  ID</quote> instead of a string of zeroes.  If an environment
28.11151 +	variable is named <envar>HG_URL</envar>, it will contain the
28.11152 +	URL of a remote repository, if that can be determined.
28.11153 +      </para>
28.11154 +
28.11155 +      <para id="x_284">If a hook exits with a status of zero, it is considered to
28.11156 +	have succeeded.  If it exits with a non-zero status, it is
28.11157 +	considered to have failed.
28.11158 +      </para>
28.11159 +    </sect2>
28.11160 +
28.11161 +    <sect2>
28.11162 +      <title>Finding out where changesets come from</title>
28.11163 +
28.11164 +      <para id="x_285">A hook that involves the transfer of changesets between a
28.11165 +	local repository and another may be able to find out
28.11166 +	information about the <quote>far side</quote>.  Mercurial
28.11167 +	knows <emphasis>how</emphasis> changes are being transferred,
28.11168 +	and in many cases <emphasis>where</emphasis> they are being
28.11169 +	transferred to or from.
28.11170 +      </para>
28.11171 +
28.11172 +      <sect3 id="sec:hook:sources">
28.11173 +	<title>Sources of changesets</title>
28.11174 +
28.11175 +	<para id="x_286">Mercurial will tell a hook what means are, or were, used
28.11176 +	  to transfer changesets between repositories.  This is
28.11177 +	  provided by Mercurial in a Python parameter named
28.11178 +	  <literal moreinfo="none">source</literal>, or an environment variable named
28.11179 +	  <envar>HG_SOURCE</envar>.
28.11180 +	</para>
28.11181 +
28.11182 +	<itemizedlist>
28.11183 +	  <listitem><para id="x_287"><literal moreinfo="none">serve</literal>: Changesets are
28.11184 +	      transferred to or from a remote repository over http or
28.11185 +	      ssh.
28.11186 +	    </para>
28.11187 +	  </listitem>
28.11188 +	  <listitem><para id="x_288"><literal moreinfo="none">pull</literal>: Changesets are
28.11189 +	      being transferred via a pull from one repository into
28.11190 +	      another.
28.11191 +	    </para>
28.11192 +	  </listitem>
28.11193 +	  <listitem><para id="x_289"><literal moreinfo="none">push</literal>: Changesets are
28.11194 +	      being transferred via a push from one repository into
28.11195 +	      another.
28.11196 +	    </para>
28.11197 +	  </listitem>
28.11198 +	  <listitem><para id="x_28a"><literal moreinfo="none">bundle</literal>: Changesets are
28.11199 +	      being transferred to or from a bundle.
28.11200 +	    </para>
28.11201 +	  </listitem></itemizedlist>
28.11202 +      </sect3>
28.11203 +
28.11204 +      <sect3 id="sec:hook:url">
28.11205 +	<title>Where changes are going—remote repository
28.11206 +	  URLs</title>
28.11207 +
28.11208 +	<para id="x_28b">When possible, Mercurial will tell a hook the location
28.11209 +	  of the <quote>far side</quote> of an activity that transfers
28.11210 +	  changeset data between repositories.  This is provided by
28.11211 +	  Mercurial in a Python parameter named
28.11212 +	  <literal moreinfo="none">url</literal>, or an environment variable named
28.11213 +	  <envar>HG_URL</envar>.
28.11214 +	</para>
28.11215 +
28.11216 +	<para id="x_28c">This information is not always known.  If a hook is
28.11217 +	  invoked in a repository that is being served via http or
28.11218 +	  ssh, Mercurial cannot tell where the remote repository is,
28.11219 +	  but it may know where the client is connecting from.  In
28.11220 +	  such cases, the URL will take one of the following forms:
28.11221 +	</para>
28.11222 +	<itemizedlist>
28.11223 +	  <listitem><para id="x_28d"><literal moreinfo="none">remote:ssh:1.2.3.4</literal>—remote 
28.11224 +	      ssh client, at the IP address
28.11225 +	      <literal moreinfo="none">1.2.3.4</literal>.
28.11226 +	    </para>
28.11227 +	  </listitem>
28.11228 +	  <listitem><para id="x_28e"><literal moreinfo="none">remote:http:1.2.3.4</literal>—remote 
28.11229 +	      http client, at the IP address
28.11230 +	      <literal moreinfo="none">1.2.3.4</literal>.  If the client is using SSL,
28.11231 +	      this will be of the form
28.11232 +	      <literal moreinfo="none">remote:https:1.2.3.4</literal>.
28.11233 +	    </para>
28.11234 +	  </listitem>
28.11235 +	  <listitem><para id="x_28f">Empty—no information could be
28.11236 +	      discovered about the remote client.
28.11237 +	    </para>
28.11238 +	  </listitem></itemizedlist>
28.11239 +      </sect3>
28.11240 +    </sect2>
28.11241 +  </sect1>
28.11242 +  <sect1>
28.11243 +    <title>Hook reference</title>
28.11244 +
28.11245 +    <sect2 id="sec:hook:changegroup">
28.11246 +      <title><literal role="hook" moreinfo="none">changegroup</literal>—after
28.11247 +	remote changesets added</title>
28.11248 +
28.11249 +      <para id="x_290">This hook is run after a group of pre-existing changesets
28.11250 +	has been added to the repository, for example via a <command role="hg-cmd" moreinfo="none">hg pull</command> or <command role="hg-cmd" moreinfo="none">hg
28.11251 +	  unbundle</command>.  This hook is run once per operation
28.11252 +	that added one or more changesets.  This is in contrast to the
28.11253 +	<literal role="hook" moreinfo="none">incoming</literal> hook, which is run
28.11254 +	once per changeset, regardless of whether the changesets
28.11255 +	arrive in a group.
28.11256 +      </para>
28.11257 +
28.11258 +      <para id="x_291">Some possible uses for this hook include kicking off an
28.11259 +	automated build or test of the added changesets, updating a
28.11260 +	bug database, or notifying subscribers that a repository
28.11261 +	contains new changes.
28.11262 +      </para>
28.11263 +
28.11264 +      <para id="x_292">Parameters to this hook:
28.11265 +      </para>
28.11266 +      <itemizedlist>
28.11267 +	<listitem><para id="x_293"><literal moreinfo="none">node</literal>: A changeset ID.  The
28.11268 +	    changeset ID of the first changeset in the group that was
28.11269 +	    added.  All changesets between this and
28.11270 +	    <literal role="tag" moreinfo="none">tip</literal>, inclusive, were added by a single
28.11271 +	    <command role="hg-cmd" moreinfo="none">hg pull</command>, <command role="hg-cmd" moreinfo="none">hg push</command> or <command role="hg-cmd" moreinfo="none">hg unbundle</command>.
28.11272 +	  </para>
28.11273 +	</listitem>
28.11274 +	<listitem><para id="x_294"><literal moreinfo="none">source</literal>: A
28.11275 +	    string.  The source of these changes.  See <xref linkend="sec:hook:sources"/> for details.
28.11276 +	  </para>
28.11277 +	</listitem>
28.11278 +	<listitem><para id="x_295"><literal moreinfo="none">url</literal>: A URL.  The
28.11279 +	    location of the remote repository, if known.  See <xref linkend="sec:hook:url"/> for more information.
28.11280 +	  </para>
28.11281 +	</listitem></itemizedlist>
28.11282 +
28.11283 +      <para id="x_296">See also: <literal role="hook" moreinfo="none">incoming</literal> (<xref linkend="sec:hook:incoming"/>), <literal role="hook" moreinfo="none">prechangegroup</literal> (<xref linkend="sec:hook:prechangegroup"/>), <literal role="hook" moreinfo="none">pretxnchangegroup</literal> (<xref linkend="sec:hook:pretxnchangegroup"/>)
28.11284 +      </para>
28.11285 +    </sect2>
28.11286 +
28.11287 +    <sect2 id="sec:hook:commit">
28.11288 +      <title><literal role="hook" moreinfo="none">commit</literal>—after a new
28.11289 +	changeset is created</title>
28.11290 +
28.11291 +      <para id="x_297">This hook is run after a new changeset has been created.
28.11292 +      </para>
28.11293 +
28.11294 +      <para id="x_298">Parameters to this hook:
28.11295 +      </para>
28.11296 +      <itemizedlist>
28.11297 +	<listitem><para id="x_299"><literal moreinfo="none">node</literal>: A changeset ID.  The
28.11298 +	    changeset ID of the newly committed changeset.
28.11299 +	  </para>
28.11300 +	</listitem>
28.11301 +	<listitem><para id="x_29a"><literal moreinfo="none">parent1</literal>: A changeset ID.
28.11302 +	    The changeset ID of the first parent of the newly
28.11303 +	    committed changeset.
28.11304 +	  </para>
28.11305 +	</listitem>
28.11306 +	<listitem><para id="x_29b"><literal moreinfo="none">parent2</literal>: A changeset ID.
28.11307 +	    The changeset ID of the second parent of the newly
28.11308 +	    committed changeset.
28.11309 +	  </para>
28.11310 +	</listitem></itemizedlist>
28.11311 +
28.11312 +      <para id="x_29c">See also: <literal role="hook" moreinfo="none">precommit</literal> (<xref linkend="sec:hook:precommit"/>), <literal role="hook" moreinfo="none">pretxncommit</literal> (<xref linkend="sec:hook:pretxncommit"/>)
28.11313 +      </para>
28.11314 +    </sect2>
28.11315 +
28.11316 +    <sect2 id="sec:hook:incoming">
28.11317 +      <title><literal role="hook" moreinfo="none">incoming</literal>—after one
28.11318 +	remote changeset is added</title>
28.11319 +
28.11320 +      <para id="x_29d">This hook is run after a pre-existing changeset has been
28.11321 +	added to the repository, for example via a <command role="hg-cmd" moreinfo="none">hg push</command>.  If a group of changesets
28.11322 +	was added in a single operation, this hook is called once for
28.11323 +	each added changeset.
28.11324 +      </para>
28.11325 +
28.11326 +      <para id="x_29e">You can use this hook for the same purposes as
28.11327 +	the <literal role="hook" moreinfo="none">changegroup</literal> hook (<xref linkend="sec:hook:changegroup"/>); it's simply more
28.11328 +	convenient sometimes to run a hook once per group of
28.11329 +	changesets, while other times it's handier once per changeset.
28.11330 +      </para>
28.11331 +
28.11332 +      <para id="x_29f">Parameters to this hook:
28.11333 +      </para>
28.11334 +      <itemizedlist>
28.11335 +	<listitem><para id="x_2a0"><literal moreinfo="none">node</literal>: A changeset ID.  The
28.11336 +	    ID of the newly added changeset.
28.11337 +	  </para>
28.11338 +	</listitem>
28.11339 +	<listitem><para id="x_2a1"><literal moreinfo="none">source</literal>: A
28.11340 +	    string.  The source of these changes.  See <xref linkend="sec:hook:sources"/> for details.
28.11341 +	  </para>
28.11342 +	</listitem>
28.11343 +	<listitem><para id="x_2a2"><literal moreinfo="none">url</literal>: A URL.  The
28.11344 +	    location of the remote repository, if known.  See <xref linkend="sec:hook:url"/> for more information.
28.11345 +	  </para>
28.11346 +	</listitem></itemizedlist>
28.11347 +
28.11348 +      <para id="x_2a3">See also: <literal role="hook" moreinfo="none">changegroup</literal> (<xref linkend="sec:hook:changegroup"/>) <literal role="hook" moreinfo="none">prechangegroup</literal> (<xref linkend="sec:hook:prechangegroup"/>), <literal role="hook" moreinfo="none">pretxnchangegroup</literal> (<xref linkend="sec:hook:pretxnchangegroup"/>)
28.11349 +      </para>
28.11350 +    </sect2>
28.11351 +
28.11352 +    <sect2 id="sec:hook:outgoing">
28.11353 +      <title><literal role="hook" moreinfo="none">outgoing</literal>—after
28.11354 +	changesets are propagated</title>
28.11355 +
28.11356 +      <para id="x_2a4">This hook is run after a group of changesets has been
28.11357 +	propagated out of this repository, for example by a <command role="hg-cmd" moreinfo="none">hg push</command> or <command role="hg-cmd" moreinfo="none">hg
28.11358 +	  bundle</command> command.
28.11359 +      </para>
28.11360 +
28.11361 +      <para id="x_2a5">One possible use for this hook is to notify administrators
28.11362 +	that changes have been pulled.
28.11363 +      </para>
28.11364 +
28.11365 +      <para id="x_2a6">Parameters to this hook:
28.11366 +      </para>
28.11367 +      <itemizedlist>
28.11368 +	<listitem><para id="x_2a7"><literal moreinfo="none">node</literal>: A changeset ID.  The
28.11369 +	    changeset ID of the first changeset of the group that was
28.11370 +	    sent.
28.11371 +	  </para>
28.11372 +	</listitem>
28.11373 +	<listitem><para id="x_2a8"><literal moreinfo="none">source</literal>: A string.  The
28.11374 +	    source of the of the operation (see <xref linkend="sec:hook:sources"/>).  If a remote
28.11375 +	    client pulled changes from this repository,
28.11376 +	    <literal moreinfo="none">source</literal> will be
28.11377 +	    <literal moreinfo="none">serve</literal>.  If the client that obtained
28.11378 +	    changes from this repository was local,
28.11379 +	    <literal moreinfo="none">source</literal> will be
28.11380 +	    <literal moreinfo="none">bundle</literal>, <literal moreinfo="none">pull</literal>, or
28.11381 +	    <literal moreinfo="none">push</literal>, depending on the operation the
28.11382 +	    client performed.
28.11383 +	  </para>
28.11384 +	</listitem>
28.11385 +	<listitem><para id="x_2a9"><literal moreinfo="none">url</literal>: A URL.  The
28.11386 +	    location of the remote repository, if known.  See <xref linkend="sec:hook:url"/> for more information.
28.11387 +	  </para>
28.11388 +	</listitem></itemizedlist>
28.11389 +
28.11390 +      <para id="x_2aa">See also: <literal role="hook" moreinfo="none">preoutgoing</literal> (<xref linkend="sec:hook:preoutgoing"/>)
28.11391 +      </para>
28.11392 +    </sect2>
28.11393 +
28.11394 +    <sect2 id="sec:hook:prechangegroup">
28.11395 +      <title><literal role="hook" moreinfo="none">prechangegroup</literal>—before starting
28.11396 +	to add remote changesets</title>
28.11397 +
28.11398 +      <para id="x_2ab">This controlling hook is run before Mercurial begins to
28.11399 +	add a group of changesets from another repository.
28.11400 +      </para>
28.11401 +
28.11402 +      <para id="x_2ac">This hook does not have any information about the
28.11403 +	changesets to be added, because it is run before transmission
28.11404 +	of those changesets is allowed to begin.  If this hook fails,
28.11405 +	the changesets will not be transmitted.
28.11406 +      </para>
28.11407 +
28.11408 +      <para id="x_2ad">One use for this hook is to prevent external changes from
28.11409 +	being added to a repository.  For example, you could use this
28.11410 +	to <quote>freeze</quote> a server-hosted branch temporarily or
28.11411 +	permanently so that users cannot push to it, while still
28.11412 +	allowing a local administrator to modify the repository.
28.11413 +      </para>
28.11414 +
28.11415 +      <para id="x_2ae">Parameters to this hook:
28.11416 +      </para>
28.11417 +      <itemizedlist>
28.11418 +	<listitem><para id="x_2af"><literal moreinfo="none">source</literal>: A string.  The
28.11419 +	    source of these changes.  See <xref linkend="sec:hook:sources"/> for details.
28.11420 +	  </para>
28.11421 +	</listitem>
28.11422 +	<listitem><para id="x_2b0"><literal moreinfo="none">url</literal>: A URL.  The
28.11423 +	    location of the remote repository, if known.  See <xref linkend="sec:hook:url"/> for more information.
28.11424 +	  </para>
28.11425 +	</listitem></itemizedlist>
28.11426 +
28.11427 +      <para id="x_2b1">See also: <literal role="hook" moreinfo="none">changegroup</literal> (<xref linkend="sec:hook:changegroup"/>), <literal role="hook" moreinfo="none">incoming</literal> (<xref linkend="sec:hook:incoming"/>), <literal role="hook" moreinfo="none">pretxnchangegroup</literal> (<xref linkend="sec:hook:pretxnchangegroup"/>)
28.11428 +      </para>
28.11429 +    </sect2>
28.11430 +
28.11431 +    <sect2 id="sec:hook:precommit">
28.11432 +      <title><literal role="hook" moreinfo="none">precommit</literal>—before
28.11433 +	starting to commit a changeset</title>
28.11434 +
28.11435 +      <para id="x_2b2">This hook is run before Mercurial begins to commit a new
28.11436 +	changeset. It is run before Mercurial has any of the metadata
28.11437 +	for the commit, such as the files to be committed, the commit
28.11438 +	message, or the commit date.
28.11439 +      </para>
28.11440 +
28.11441 +      <para id="x_2b3">One use for this hook is to disable the ability to commit
28.11442 +	new changesets, while still allowing incoming changesets.
28.11443 +	Another is to run a build or test, and only allow the commit
28.11444 +	to begin if the build or test succeeds.
28.11445 +      </para>
28.11446 +
28.11447 +      <para id="x_2b4">Parameters to this hook:
28.11448 +      </para>
28.11449 +      <itemizedlist>
28.11450 +	<listitem><para id="x_2b5"><literal moreinfo="none">parent1</literal>: A changeset ID.
28.11451 +	    The changeset ID of the first parent of the working
28.11452 +	    directory.
28.11453 +	  </para>
28.11454 +	</listitem>
28.11455 +	<listitem><para id="x_2b6"><literal moreinfo="none">parent2</literal>: A changeset ID.
28.11456 +	    The changeset ID of the second parent of the working
28.11457 +	    directory.
28.11458 +	  </para>
28.11459 +	</listitem></itemizedlist>
28.11460 +      <para id="x_2b7">If the commit proceeds, the parents of the working
28.11461 +	directory will become the parents of the new changeset.
28.11462 +      </para>
28.11463 +
28.11464 +      <para id="x_2b8">See also: <literal role="hook" moreinfo="none">commit</literal>
28.11465 +	(<xref linkend="sec:hook:commit"/>), <literal role="hook" moreinfo="none">pretxncommit</literal> (<xref linkend="sec:hook:pretxncommit"/>)
28.11466 +      </para>
28.11467 +    </sect2>
28.11468 +
28.11469 +    <sect2 id="sec:hook:preoutgoing">
28.11470 +      <title><literal role="hook" moreinfo="none">preoutgoing</literal>—before
28.11471 +	starting to propagate changesets</title>
28.11472 +
28.11473 +      <para id="x_2b9">This hook is invoked before Mercurial knows the identities
28.11474 +	of the changesets to be transmitted.
28.11475 +      </para>
28.11476 +
28.11477 +      <para id="x_2ba">One use for this hook is to prevent changes from being
28.11478 +	transmitted to another repository.
28.11479 +      </para>
28.11480 +
28.11481 +      <para id="x_2bb">Parameters to this hook:
28.11482 +      </para>
28.11483 +      <itemizedlist>
28.11484 +	<listitem><para id="x_2bc"><literal moreinfo="none">source</literal>: A
28.11485 +	    string.  The source of the operation that is attempting to
28.11486 +	    obtain changes from this repository (see <xref linkend="sec:hook:sources"/>).  See the documentation
28.11487 +	    for the <literal moreinfo="none">source</literal> parameter to the
28.11488 +	    <literal role="hook" moreinfo="none">outgoing</literal> hook, in
28.11489 +	    <xref linkend="sec:hook:outgoing"/>, for possible values
28.11490 +	    of this parameter.
28.11491 +	  </para>
28.11492 +	</listitem>
28.11493 +	<listitem><para id="x_2bd"><literal moreinfo="none">url</literal>: A URL.  The
28.11494 +	    location of the remote repository, if known.  See <xref linkend="sec:hook:url"/> for more information.
28.11495 +	  </para>
28.11496 +	</listitem></itemizedlist>
28.11497 +
28.11498 +      <para id="x_2be">See also: <literal role="hook" moreinfo="none">outgoing</literal> (<xref linkend="sec:hook:outgoing"/>)
28.11499 +      </para>
28.11500 +    </sect2>
28.11501 +
28.11502 +    <sect2 id="sec:hook:pretag">
28.11503 +      <title><literal role="hook" moreinfo="none">pretag</literal>—before
28.11504 +	tagging a changeset</title>
28.11505 +
28.11506 +      <para id="x_2bf">This controlling hook is run before a tag is created.  If
28.11507 +	the hook succeeds, creation of the tag proceeds.  If the hook
28.11508 +	fails, the tag is not created.
28.11509 +      </para>
28.11510 +
28.11511 +      <para id="x_2c0">Parameters to this hook:
28.11512 +      </para>
28.11513 +      <itemizedlist>
28.11514 +	<listitem><para id="x_2c1"><literal moreinfo="none">local</literal>: A boolean.  Whether
28.11515 +	    the tag is local to this repository instance (i.e. stored
28.11516 +	    in <filename role="special" moreinfo="none">.hg/localtags</filename>) or
28.11517 +	    managed by Mercurial (stored in <filename role="special" moreinfo="none">.hgtags</filename>).
28.11518 +	  </para>
28.11519 +	</listitem>
28.11520 +	<listitem><para id="x_2c2"><literal moreinfo="none">node</literal>: A changeset ID.  The
28.11521 +	    ID of the changeset to be tagged.
28.11522 +	  </para>
28.11523 +	</listitem>
28.11524 +	<listitem><para id="x_2c3"><literal moreinfo="none">tag</literal>: A string.  The name of
28.11525 +	    the tag to be created.
28.11526 +	  </para>
28.11527 +	</listitem></itemizedlist>
28.11528 +
28.11529 +      <para id="x_2c4">If the tag to be created is
28.11530 +	revision-controlled, the <literal role="hook" moreinfo="none">precommit</literal> and <literal role="hook" moreinfo="none">pretxncommit</literal> hooks (<xref linkend="sec:hook:commit"/> and <xref linkend="sec:hook:pretxncommit"/>) will also be run.
28.11531 +      </para>
28.11532 +
28.11533 +      <para id="x_2c5">See also: <literal role="hook" moreinfo="none">tag</literal>
28.11534 +	(<xref linkend="sec:hook:tag"/>)
28.11535 +      </para>
28.11536 +    </sect2>
28.11537 +
28.11538 +    <sect2 id="sec:hook:pretxnchangegroup">
28.11539 +      <title><literal role="hook" moreinfo="none">pretxnchangegroup</literal>—before
28.11540 +	completing addition of remote changesets</title>
28.11541 +
28.11542 +      <para id="x_2c6">This controlling hook is run before a
28.11543 +	transaction—that manages the addition of a group of new
28.11544 +	changesets from outside the repository—completes.  If
28.11545 +	the hook succeeds, the transaction completes, and all of the
28.11546 +	changesets become permanent within this repository.  If the
28.11547 +	hook fails, the transaction is rolled back, and the data for
28.11548 +	the changesets is erased.
28.11549 +      </para>
28.11550 +
28.11551 +      <para id="x_2c7">This hook can access the metadata associated with the
28.11552 +	almost-added changesets, but it should not do anything
28.11553 +	permanent with this data. It must also not modify the working
28.11554 +	directory.
28.11555 +      </para>
28.11556 +
28.11557 +      <para id="x_2c8">While this hook is running, if other Mercurial processes
28.11558 +	access this repository, they will be able to see the
28.11559 +	almost-added changesets as if they are permanent.  This may
28.11560 +	lead to race conditions if you do not take steps to avoid
28.11561 +	them.
28.11562 +      </para>
28.11563 +
28.11564 +      <para id="x_2c9">This hook can be used to automatically vet a group of
28.11565 +	changesets.  If the hook fails, all of the changesets are
28.11566 +	<quote>rejected</quote> when the transaction rolls back.
28.11567 +      </para>
28.11568 +
28.11569 +      <para id="x_2ca">Parameters to this hook:
28.11570 +      </para>
28.11571 +      <itemizedlist>
28.11572 +	<listitem><para id="x_2cb"><literal moreinfo="none">node</literal>: A changeset ID.  The
28.11573 +	    changeset ID of the first changeset in the group that was
28.11574 +	    added.  All changesets between this and
28.11575 +	    <literal role="tag" moreinfo="none">tip</literal>,
28.11576 +	    inclusive, were added by a single <command role="hg-cmd" moreinfo="none">hg pull</command>, <command role="hg-cmd" moreinfo="none">hg push</command> or <command role="hg-cmd" moreinfo="none">hg unbundle</command>.
28.11577 +	  </para>
28.11578 +	</listitem>
28.11579 +	<listitem><para id="x_2cc"><literal moreinfo="none">source</literal>: A
28.11580 +	    string.  The source of these changes.  See <xref linkend="sec:hook:sources"/> for details.
28.11581 +	  </para>
28.11582 +	</listitem>
28.11583 +	<listitem><para id="x_2cd"><literal moreinfo="none">url</literal>: A URL.  The
28.11584 +	    location of the remote repository, if known.  See <xref linkend="sec:hook:url"/> for more information.
28.11585 +	  </para>
28.11586 +	</listitem></itemizedlist>
28.11587 +
28.11588 +      <para id="x_2ce">See also: <literal role="hook" moreinfo="none">changegroup</literal> (<xref linkend="sec:hook:changegroup"/>), <literal role="hook" moreinfo="none">incoming</literal> (<xref linkend="sec:hook:incoming"/>), <literal role="hook" moreinfo="none">prechangegroup</literal> (<xref linkend="sec:hook:prechangegroup"/>)
28.11589 +      </para>
28.11590 +    </sect2>
28.11591 +
28.11592 +    <sect2 id="sec:hook:pretxncommit">
28.11593 +      <title><literal role="hook" moreinfo="none">pretxncommit</literal>—before
28.11594 +	completing commit of new changeset</title>
28.11595 +
28.11596 +      <para id="x_2cf">This controlling hook is run before a
28.11597 +	transaction—that manages a new commit—completes.
28.11598 +	If the hook succeeds, the transaction completes and the
28.11599 +	changeset becomes permanent within this repository.  If the
28.11600 +	hook fails, the transaction is rolled back, and the commit
28.11601 +	data is erased.
28.11602 +      </para>
28.11603 +
28.11604 +      <para id="x_2d0">This hook can access the metadata associated with the
28.11605 +	almost-new changeset, but it should not do anything permanent
28.11606 +	with this data.  It must also not modify the working
28.11607 +	directory.
28.11608 +      </para>
28.11609 +
28.11610 +      <para id="x_2d1">While this hook is running, if other Mercurial processes
28.11611 +	access this repository, they will be able to see the
28.11612 +	almost-new changeset as if it is permanent.  This may lead to
28.11613 +	race conditions if you do not take steps to avoid them.
28.11614 +      </para>
28.11615 +
28.11616 +      <para id="x_2d2">Parameters to this hook:</para>
28.11617 +
28.11618 +      <itemizedlist>
28.11619 +	<listitem><para id="x_2d3"><literal moreinfo="none">node</literal>: A changeset ID.  The
28.11620 +	    changeset ID of the newly committed changeset.
28.11621 +	  </para>
28.11622 +	</listitem>
28.11623 +	<listitem><para id="x_2d4"><literal moreinfo="none">parent1</literal>: A changeset ID.
28.11624 +	    The changeset ID of the first parent of the newly
28.11625 +	    committed changeset.
28.11626 +	  </para>
28.11627 +	</listitem>
28.11628 +	<listitem><para id="x_2d5"><literal moreinfo="none">parent2</literal>: A changeset ID.
28.11629 +	    The changeset ID of the second parent of the newly
28.11630 +	    committed changeset.
28.11631 +	  </para>
28.11632 +	</listitem></itemizedlist>
28.11633 +
28.11634 +      <para id="x_2d6">See also: <literal role="hook" moreinfo="none">precommit</literal> (<xref linkend="sec:hook:precommit"/>)
28.11635 +      </para>
28.11636 +    </sect2>
28.11637 +
28.11638 +    <sect2 id="sec:hook:preupdate">
28.11639 +      <title><literal role="hook" moreinfo="none">preupdate</literal>—before
28.11640 +	updating or merging working directory</title>
28.11641 +
28.11642 +      <para id="x_2d7">This controlling hook is run before an update
28.11643 +	or merge of the working directory begins.  It is run only if
28.11644 +	Mercurial's normal pre-update checks determine that the update
28.11645 +	or merge can proceed.  If the hook succeeds, the update or
28.11646 +	merge may proceed; if it fails, the update or merge does not
28.11647 +	start.
28.11648 +      </para>
28.11649 +
28.11650 +      <para id="x_2d8">Parameters to this hook:
28.11651 +      </para>
28.11652 +      <itemizedlist>
28.11653 +	<listitem><para id="x_2d9"><literal moreinfo="none">parent1</literal>: A
28.11654 +	    changeset ID. The ID of the parent that the working
28.11655 +	    directory is to be updated to.  If the working directory
28.11656 +	    is being merged, it will not change this parent.
28.11657 +	  </para>
28.11658 +	</listitem>
28.11659 +	<listitem><para id="x_2da"><literal moreinfo="none">parent2</literal>: A
28.11660 +	    changeset ID. Only set if the working directory is being
28.11661 +	    merged.  The ID of the revision that the working directory
28.11662 +	    is being merged with.
28.11663 +	  </para>
28.11664 +	</listitem></itemizedlist>
28.11665 +
28.11666 +      <para id="x_2db">See also: <literal role="hook" moreinfo="none">update</literal>
28.11667 +	(<xref linkend="sec:hook:update"/>)</para>
28.11668 +    </sect2>
28.11669 +
28.11670 +    <sect2 id="sec:hook:tag">
28.11671 +      <title><literal role="hook" moreinfo="none">tag</literal>—after tagging a
28.11672 +	changeset</title>
28.11673 +
28.11674 +      <para id="x_2dc">This hook is run after a tag has been created.
28.11675 +      </para>
28.11676 +
28.11677 +      <para id="x_2dd">Parameters to this hook:
28.11678 +      </para>
28.11679 +      <itemizedlist>
28.11680 +	<listitem><para id="x_2de"><literal moreinfo="none">local</literal>: A boolean.  Whether
28.11681 +	    the new tag is local to this repository instance (i.e.
28.11682 +	    stored in <filename role="special" moreinfo="none">.hg/localtags</filename>) or managed by
28.11683 +	    Mercurial (stored in <filename role="special" moreinfo="none">.hgtags</filename>).
28.11684 +	  </para>
28.11685 +	</listitem>
28.11686 +	<listitem><para id="x_2df"><literal moreinfo="none">node</literal>: A changeset ID.  The
28.11687 +	    ID of the changeset that was tagged.
28.11688 +	  </para>
28.11689 +	</listitem>
28.11690 +	<listitem><para id="x_2e0"><literal moreinfo="none">tag</literal>: A string.  The name of
28.11691 +	    the tag that was created.
28.11692 +	  </para>
28.11693 +	</listitem></itemizedlist>
28.11694 +
28.11695 +      <para id="x_2e1">If the created tag is revision-controlled, the <literal role="hook" moreinfo="none">commit</literal> hook (section <xref linkend="sec:hook:commit"/>) is run before this hook.
28.11696 +      </para>
28.11697 +
28.11698 +      <para id="x_2e2">See also: <literal role="hook" moreinfo="none">pretag</literal>
28.11699 +	(<xref linkend="sec:hook:pretag"/>)
28.11700 +      </para>
28.11701 +    </sect2>
28.11702 +
28.11703 +    <sect2 id="sec:hook:update">
28.11704 +      <title><literal role="hook" moreinfo="none">update</literal>—after
28.11705 +	updating or merging working directory</title>
28.11706 +
28.11707 +      <para id="x_2e3">This hook is run after an update or merge of the working
28.11708 +	directory completes.  Since a merge can fail (if the external
28.11709 +	<command moreinfo="none">hgmerge</command> command fails to resolve conflicts
28.11710 +	in a file), this hook communicates whether the update or merge
28.11711 +	completed cleanly.
28.11712 +      </para>
28.11713 +
28.11714 +      <itemizedlist>
28.11715 +	<listitem><para id="x_2e4"><literal moreinfo="none">error</literal>: A boolean.
28.11716 +	    Indicates whether the update or merge completed
28.11717 +	    successfully.
28.11718 +	  </para>
28.11719 +	</listitem>
28.11720 +	<listitem><para id="x_2e5"><literal moreinfo="none">parent1</literal>: A changeset ID.
28.11721 +	    The ID of the parent that the working directory was
28.11722 +	    updated to.  If the working directory was merged, it will
28.11723 +	    not have changed this parent.
28.11724 +	  </para>
28.11725 +	</listitem>
28.11726 +	<listitem><para id="x_2e6"><literal moreinfo="none">parent2</literal>: A changeset ID.
28.11727 +	    Only set if the working directory was merged.  The ID of
28.11728 +	    the revision that the working directory was merged with.
28.11729 +	  </para>
28.11730 +	</listitem></itemizedlist>
28.11731 +
28.11732 +      <para id="x_2e7">See also: <literal role="hook" moreinfo="none">preupdate</literal>
28.11733 +	(<xref linkend="sec:hook:preupdate"/>)
28.11734 +      </para>
28.11735 +
28.11736 +    </sect2>
28.11737 +  </sect1>
28.11738 +</chapter>
28.11739 +
28.11740 +<!--
28.11741 +local variables: 
28.11742 +sgml-parent-document: ("00book.xml" "book" "chapter")
28.11743 +end:
28.11744 +-->
28.11745 +
28.11746 +  <!-- BEGIN ch11 -->
28.11747 +  <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
28.11748 +
28.11749 +<chapter id="chap:template">
28.11750 +  <?dbhtml filename="customizing-the-output-of-mercurial.html"?>
28.11751 +  <title>Customizing the output of Mercurial</title>
28.11752 +
28.11753 +  <para id="x_578">Mercurial provides a powerful mechanism to let you control how
28.11754 +    it displays information.  The mechanism is based on templates.
28.11755 +    You can use templates to generate specific output for a single
28.11756 +    command, or to customize the entire appearance of the built-in web
28.11757 +    interface.</para>
28.11758 +
28.11759 +  <sect1 id="sec:style">
28.11760 +    <title>Using precanned output styles</title>
28.11761 +
28.11762 +    <para id="x_579">Packaged with Mercurial are some output styles that you can
28.11763 +      use immediately.  A style is simply a precanned template that
28.11764 +      someone wrote and installed somewhere that Mercurial can
28.11765 +      find.</para>
28.11766 +
28.11767 +    <para id="x_57a">Before we take a look at Mercurial's bundled styles, let's
28.11768 +      review its normal output.</para>
28.11769 +
28.11770 +    <!-- BEGIN template.simple.normal -->
28.11771 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1</userinput>
28.11772 +changeset:   1:e3d2468ca47c
28.11773 +tag:         mytag
28.11774 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
28.11775 +date:        Sun Aug 16 14:05:17 2009 +0000
28.11776 +summary:     added line to end of &lt;&lt;hello&gt;&gt; file.
28.11777 +
28.11778 +</screen>
28.11779 +<!-- END template.simple.normal -->
28.11780 +
28.11781 +
28.11782 +    <para id="x_57b">This is somewhat informative, but it takes up a lot of
28.11783 +      space—five lines of output per changeset.  The
28.11784 +      <literal moreinfo="none">compact</literal> style reduces this to three lines,
28.11785 +      presented in a sparse manner.</para>
28.11786 +
28.11787 +    <!-- BEGIN template.simple.compact -->
28.11788 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log --style compact</userinput>
28.11789 +3[tip]   d3cc7424d32c   2009-08-16 14:05 +0000   bos
28.11790 +  Added tag v0.1 for changeset a5dd5392119b
28.11791 +
28.11792 +2[v0.1]   a5dd5392119b   2009-08-16 14:05 +0000   bos
28.11793 +  Added tag mytag for changeset e3d2468ca47c
28.11794 +
28.11795 +1[mytag]   e3d2468ca47c   2009-08-16 14:05 +0000   bos
28.11796 +  added line to end of &lt;&lt;hello&gt;&gt; file.
28.11797 +
28.11798 +0   1cf727e9fc61   2009-08-16 14:05 +0000   bos
28.11799 +  added hello
28.11800 +
28.11801 +</screen>
28.11802 +<!-- END template.simple.compact -->
28.11803 +
28.11804 +
28.11805 +    <para id="x_57c">The <literal moreinfo="none">changelog</literal> style hints at the
28.11806 +      expressive power of Mercurial's templating engine.  This style
28.11807 +      attempts to follow the GNU Project's changelog
28.11808 +      guidelines<citation>web:changelog</citation>.</para>
28.11809 +
28.11810 +    <!-- BEGIN template.simple.changelog -->
28.11811 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log --style changelog</userinput>
28.11812 +2009-08-16  Bryan O'Sullivan  &lt;bos@serpentine.com&gt;
28.11813 +
28.11814 +	* .hgtags:
28.11815 +	Added tag v0.1 for changeset a5dd5392119b
28.11816 +	[d3cc7424d32c] [tip]
28.11817 +
28.11818 +	* .hgtags:
28.11819 +	Added tag mytag for changeset e3d2468ca47c
28.11820 +	[a5dd5392119b] [v0.1]
28.11821 +
28.11822 +	* goodbye, hello:
28.11823 +	added line to end of &lt;&lt;hello&gt;&gt; file.
28.11824 +
28.11825 +	in addition, added a file with the helpful name (at least i hope
28.11826 +	that some might consider it so) of goodbye.
28.11827 +	[e3d2468ca47c] [mytag]
28.11828 +
28.11829 +	* hello:
28.11830 +	added hello
28.11831 +	[1cf727e9fc61]
28.11832 +
28.11833 +</screen>
28.11834 +<!-- END template.simple.changelog -->
28.11835 +
28.11836 +
28.11837 +    <para id="x_57d">You will not be shocked to learn that Mercurial's default
28.11838 +      output style is named <literal moreinfo="none">default</literal>.</para>
28.11839 +
28.11840 +    <sect2>
28.11841 +      <title>Setting a default style</title>
28.11842 +
28.11843 +      <para id="x_57e">You can modify the output style that Mercurial will use
28.11844 +	for every command by editing your <filename role="special" moreinfo="none">~/.hgrc</filename> file, naming the style
28.11845 +	you would prefer to use.</para>
28.11846 +
28.11847 +      <programlisting format="linespecific">[ui]
28.11848 +style = compact</programlisting>
28.11849 +
28.11850 +      <para id="x_57f">If you write a style of your own, you can use it by either
28.11851 +	providing the path to your style file, or copying your style
28.11852 +	file into a location where Mercurial can find it (typically
28.11853 +	the <literal moreinfo="none">templates</literal> subdirectory of your
28.11854 +	Mercurial install directory).</para>
28.11855 +    </sect2>
28.11856 +  </sect1>
28.11857 +
28.11858 +  <sect1>
28.11859 +    <title>Commands that support styles and templates</title>
28.11860 +
28.11861 +    <para id="x_580">All of Mercurial's
28.11862 +      <quote><literal moreinfo="none">log</literal>-like</quote> commands let you use
28.11863 +      styles and templates: <command role="hg-cmd" moreinfo="none">hg
28.11864 +	incoming</command>, <command role="hg-cmd" moreinfo="none">hg log</command>,
28.11865 +      <command role="hg-cmd" moreinfo="none">hg outgoing</command>, and <command role="hg-cmd" moreinfo="none">hg tip</command>.</para>
28.11866 +
28.11867 +    <para id="x_581">As I write this manual, these are so far the only commands
28.11868 +      that support styles and templates.  Since these are the most
28.11869 +      important commands that need customizable output, there has been
28.11870 +      little pressure from the Mercurial user community to add style
28.11871 +      and template support to other commands.</para>
28.11872 +  </sect1>
28.11873 +
28.11874 +  <sect1>
28.11875 +    <title>The basics of templating</title>
28.11876 +
28.11877 +    <para id="x_582">At its simplest, a Mercurial template is a piece of text.
28.11878 +      Some of the text never changes, while other parts are
28.11879 +      <emphasis>expanded</emphasis>, or replaced with new text, when
28.11880 +      necessary.</para>
28.11881 +
28.11882 +    <para id="x_583">Before we continue, let's look again at a simple example of
28.11883 +      Mercurial's normal output.</para>
28.11884 +
28.11885 +    <!-- BEGIN template.simple.normal -->
28.11886 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1</userinput>
28.11887 +changeset:   1:e3d2468ca47c
28.11888 +tag:         mytag
28.11889 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
28.11890 +date:        Sun Aug 16 14:05:17 2009 +0000
28.11891 +summary:     added line to end of &lt;&lt;hello&gt;&gt; file.
28.11892 +
28.11893 +</screen>
28.11894 +<!-- END template.simple.normal -->
28.11895 +
28.11896 +
28.11897 +    <para id="x_584">Now, let's run the same command, but using a template to
28.11898 +      change its output.</para>
28.11899 +
28.11900 +    <!-- BEGIN template.simple.simplest -->
28.11901 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'i saw a changeset\n'</userinput>
28.11902 +i saw a changeset
28.11903 +</screen>
28.11904 +<!-- END template.simple.simplest -->
28.11905 +
28.11906 +
28.11907 +    <para id="x_585">The example above illustrates the simplest possible
28.11908 +      template; it's just a piece of static text, printed once for
28.11909 +      each changeset.  The <option role="hg-opt-log">--template</option> option to the <command role="hg-cmd" moreinfo="none">hg log</command> command tells Mercurial to use
28.11910 +      the given text as the template when printing each
28.11911 +      changeset.</para>
28.11912 +
28.11913 +    <para id="x_586">Notice that the template string above ends with the text
28.11914 +      <quote><literal moreinfo="none">\n</literal></quote>.  This is an
28.11915 +      <emphasis>escape sequence</emphasis>, telling Mercurial to print
28.11916 +      a newline at the end of each template item.  If you omit this
28.11917 +      newline, Mercurial will run each piece of output together.  See
28.11918 +      <xref linkend="sec:template:escape"/> for more details
28.11919 +      of escape sequences.</para>
28.11920 +
28.11921 +    <para id="x_587">A template that prints a fixed string of text all the time
28.11922 +      isn't very useful; let's try something a bit more
28.11923 +      complex.</para>
28.11924 +
28.11925 +    <!-- BEGIN template.simple.simplesub -->
28.11926 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log --template 'i saw a changeset: {desc}\n'</userinput>
28.11927 +i saw a changeset: Added tag v0.1 for changeset a5dd5392119b
28.11928 +i saw a changeset: Added tag mytag for changeset e3d2468ca47c
28.11929 +i saw a changeset: added line to end of &lt;&lt;hello&gt;&gt; file.
28.11930 +
28.11931 +in addition, added a file with the helpful name (at least i hope that some might consider it so) of goodbye.
28.11932 +i saw a changeset: added hello
28.11933 +</screen>
28.11934 +<!-- END template.simple.simplesub -->
28.11935 +
28.11936 +
28.11937 +    <para id="x_588">As you can see, the string
28.11938 +      <quote><literal moreinfo="none">{desc}</literal></quote> in the template has
28.11939 +      been replaced in the output with the description of each
28.11940 +      changeset.  Every time Mercurial finds text enclosed in curly
28.11941 +      braces (<quote><literal moreinfo="none">{</literal></quote> and
28.11942 +      <quote><literal moreinfo="none">}</literal></quote>), it will try to replace the
28.11943 +      braces and text with the expansion of whatever is inside.  To
28.11944 +      print a literal curly brace, you must escape it, as described in
28.11945 +      <xref linkend="sec:template:escape"/>.</para>
28.11946 +  </sect1>
28.11947 +
28.11948 +  <sect1 id="sec:template:keyword">
28.11949 +    <title>Common template keywords</title>
28.11950 +
28.11951 +    <para id="x_589">You can start writing simple templates immediately using the
28.11952 +      keywords below.</para>
28.11953 +
28.11954 +    <itemizedlist>
28.11955 +      <listitem><para id="x_58a"><literal role="template-keyword" moreinfo="none">author</literal>: String.  The
28.11956 +	  unmodified author of the changeset.</para>
28.11957 +      </listitem>
28.11958 +      <listitem><para id="x_58b"><literal role="template-keyword" moreinfo="none">branches</literal>: String.  The
28.11959 +	  name of the branch on which the changeset was committed.
28.11960 +	  Will be empty if the branch name was
28.11961 +	  <literal moreinfo="none">default</literal>.</para>
28.11962 +      </listitem>
28.11963 +      <listitem><para id="x_58c"><literal role="template-keyword" moreinfo="none">date</literal>:
28.11964 +	  Date information.  The date when the changeset was
28.11965 +	  committed.  This is <emphasis>not</emphasis> human-readable;
28.11966 +	  you must pass it through a filter that will render it
28.11967 +	  appropriately.  See <xref linkend="sec:template:filter"/> for more information
28.11968 +	  on filters. The date is expressed as a pair of numbers.  The
28.11969 +	  first number is a Unix UTC timestamp (seconds since January
28.11970 +	  1, 1970); the second is the offset of the committer's
28.11971 +	  timezone from UTC, in seconds.</para>
28.11972 +      </listitem>
28.11973 +      <listitem><para id="x_58d"><literal role="template-keyword" moreinfo="none">desc</literal>:
28.11974 +	  String.  The text of the changeset description.</para>
28.11975 +      </listitem>
28.11976 +      <listitem><para id="x_58e"><literal role="template-keyword" moreinfo="none">files</literal>: List of strings.
28.11977 +	  All files modified, added, or removed by this
28.11978 +	  changeset.</para>
28.11979 +      </listitem>
28.11980 +      <listitem><para id="x_58f"><literal role="template-keyword" moreinfo="none">file_adds</literal>: List of
28.11981 +	  strings.  Files added by this changeset.</para>
28.11982 +      </listitem>
28.11983 +      <listitem><para id="x_590"><literal role="template-keyword" moreinfo="none">file_dels</literal>: List of
28.11984 +	  strings.  Files removed by this changeset.</para>
28.11985 +      </listitem>
28.11986 +      <listitem><para id="x_591"><literal role="template-keyword" moreinfo="none">node</literal>:
28.11987 +	  String.  The changeset identification hash, as a
28.11988 +	  40-character hexadecimal string.</para>
28.11989 +      </listitem>
28.11990 +      <listitem><para id="x_592"><literal role="template-keyword" moreinfo="none">parents</literal>: List of
28.11991 +	  strings.  The parents of the changeset.</para>
28.11992 +      </listitem>
28.11993 +      <listitem><para id="x_593"><literal role="template-keyword" moreinfo="none">rev</literal>:
28.11994 +	  Integer.  The repository-local changeset revision
28.11995 +	  number.</para>
28.11996 +      </listitem>
28.11997 +      <listitem><para id="x_594"><literal role="template-keyword" moreinfo="none">tags</literal>:
28.11998 +	  List of strings.  Any tags associated with the
28.11999 +	  changeset.</para>
28.12000 +      </listitem>
28.12001 +    </itemizedlist>
28.12002 +
28.12003 +    <para id="x_595">A few simple experiments will show us what to expect when we
28.12004 +      use these keywords; you can see the results below.</para>
28.12005 +
28.12006 +    <!-- BEGIN template.simple.keywords -->
28.12007 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'author: {author}\n'</userinput>
28.12008 +author: Bryan O'Sullivan &lt;bos@serpentine.com&gt;
28.12009 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'desc:\n{desc}\n'</userinput>
28.12010 +desc:
28.12011 +added line to end of &lt;&lt;hello&gt;&gt; file.
28.12012 +
28.12013 +in addition, added a file with the helpful name (at least i hope that some might consider it so) of goodbye.
28.12014 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'files: {files}\n'</userinput>
28.12015 +files: goodbye hello
28.12016 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'file_adds: {file_adds}\n'</userinput>
28.12017 +file_adds: goodbye
28.12018 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'file_dels: {file_dels}\n'</userinput>
28.12019 +file_dels: 
28.12020 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'node: {node}\n'</userinput>
28.12021 +node: e3d2468ca47c10bdfbbb41b367a0c84509862197
28.12022 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'parents: {parents}\n'</userinput>
28.12023 +parents: 
28.12024 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'rev: {rev}\n'</userinput>
28.12025 +rev: 1
28.12026 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'tags: {tags}\n'</userinput>
28.12027 +tags: mytag
28.12028 +</screen>
28.12029 +<!-- END template.simple.keywords -->
28.12030 +
28.12031 +
28.12032 +    <para id="x_596">As we noted above, the date keyword does not produce
28.12033 +      human-readable output, so we must treat it specially.  This
28.12034 +      involves using a <emphasis>filter</emphasis>, about which more
28.12035 +      in <xref linkend="sec:template:filter"/>.</para>
28.12036 +
28.12037 +    <!-- BEGIN template.simple.datekeyword -->
28.12038 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'date: {date}\n'</userinput>
28.12039 +date: 1250431517.00
28.12040 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'date: {date|isodate}\n'</userinput>
28.12041 +date: 2009-08-16 14:05 +0000
28.12042 +</screen>
28.12043 +<!-- END template.simple.datekeyword -->
28.12044 +
28.12045 +  </sect1>
28.12046 +
28.12047 +  <sect1 id="sec:template:escape">
28.12048 +    <title>Escape sequences</title>
28.12049 +
28.12050 +    <para id="x_597">Mercurial's templating engine recognises the most commonly
28.12051 +      used escape sequences in strings.  When it sees a backslash
28.12052 +      (<quote><literal moreinfo="none">\</literal></quote>) character, it looks at the
28.12053 +      following character and substitutes the two characters with a
28.12054 +      single replacement, as described below.</para>
28.12055 +
28.12056 +    <itemizedlist>
28.12057 +      <listitem><para id="x_598"><literal moreinfo="none">\</literal>:
28.12058 +	  Backslash, <quote><literal moreinfo="none">\</literal></quote>, ASCII
28.12059 +	  134.</para>
28.12060 +      </listitem>
28.12061 +      <listitem><para id="x_599"><literal moreinfo="none">\n</literal>: Newline,
28.12062 +	  ASCII 12.</para>
28.12063 +      </listitem>
28.12064 +      <listitem><para id="x_59a"><literal moreinfo="none">\r</literal>: Carriage
28.12065 +	  return, ASCII 15.</para>
28.12066 +      </listitem>
28.12067 +      <listitem><para id="x_59b"><literal moreinfo="none">\t</literal>: Tab, ASCII
28.12068 +	  11.</para>
28.12069 +      </listitem>
28.12070 +      <listitem><para id="x_59c"><literal moreinfo="none">\v</literal>: Vertical
28.12071 +	  tab, ASCII 13.</para>
28.12072 +      </listitem>
28.12073 +      <listitem><para id="x_59d"><literal moreinfo="none">\{</literal>: Open curly
28.12074 +	  brace, <quote><literal moreinfo="none">{</literal></quote>, ASCII
28.12075 +	  173.</para>
28.12076 +      </listitem>
28.12077 +      <listitem><para id="x_59e"><literal moreinfo="none">\}</literal>: Close curly
28.12078 +	  brace, <quote><literal moreinfo="none">}</literal></quote>, ASCII
28.12079 +	  175.</para>
28.12080 +      </listitem></itemizedlist>
28.12081 +
28.12082 +    <para id="x_59f">As indicated above, if you want the expansion of a template
28.12083 +      to contain a literal <quote><literal moreinfo="none">\</literal></quote>,
28.12084 +      <quote><literal moreinfo="none">{</literal></quote>, or
28.12085 +      <quote><literal moreinfo="none">{</literal></quote> character, you must escape
28.12086 +      it.</para>
28.12087 +  </sect1>
28.12088 +
28.12089 +  <sect1 id="sec:template:filter">
28.12090 +    <title>Filtering keywords to change their results</title>
28.12091 +
28.12092 +    <para id="x_5a0">Some of the results of template expansion are not
28.12093 +      immediately easy to use.  Mercurial lets you specify an optional
28.12094 +      chain of <emphasis>filters</emphasis> to modify the result of
28.12095 +      expanding a keyword.  You have already seen a common filter,
28.12096 +      <literal role="template-kw-filt-date" moreinfo="none">isodate</literal>, in
28.12097 +      action above, to make a date readable.</para>
28.12098 +
28.12099 +    <para id="x_5a1">Below is a list of the most commonly used filters that
28.12100 +      Mercurial supports.  While some filters can be applied to any
28.12101 +      text, others can only be used in specific circumstances.  The
28.12102 +      name of each filter is followed first by an indication of where
28.12103 +      it can be used, then a description of its effect.</para>
28.12104 +
28.12105 +    <itemizedlist>
28.12106 +      <listitem><para id="x_5a2"><literal role="template-filter" moreinfo="none">addbreaks</literal>: Any text. Add
28.12107 +	  an XHTML <quote><literal moreinfo="none">&lt;br/&gt;</literal></quote> tag
28.12108 +	  before the end of every line except the last.  For example,
28.12109 +	  <quote><literal moreinfo="none">foo\nbar</literal></quote> becomes
28.12110 +	  <quote><literal moreinfo="none">foo&lt;br/&gt;\nbar</literal></quote>.</para>
28.12111 +      </listitem>
28.12112 +      <listitem><para id="x_5a3"><literal role="template-kw-filt-date" moreinfo="none">age</literal>: <literal role="template-keyword" moreinfo="none">date</literal> keyword.  Render
28.12113 +	  the age of the date, relative to the current time.  Yields a
28.12114 +	  string like <quote><literal moreinfo="none">10
28.12115 +	      minutes</literal></quote>.</para>
28.12116 +      </listitem>
28.12117 +      <listitem><para id="x_5a4"><literal role="template-filter" moreinfo="none">basename</literal>: Any text, but
28.12118 +	  most useful for the <literal role="template-keyword" moreinfo="none">files</literal> keyword and its
28.12119 +	  relatives.  Treat the text as a path, and return the
28.12120 +	  basename. For example,
28.12121 +	  <quote><literal moreinfo="none">foo/bar/baz</literal></quote> becomes
28.12122 +	  <quote><literal moreinfo="none">baz</literal></quote>.</para>
28.12123 +      </listitem>
28.12124 +      <listitem><para id="x_5a5"><literal role="template-kw-filt-date" moreinfo="none">date</literal>: <literal role="template-keyword" moreinfo="none">date</literal> keyword.  Render a
28.12125 +	  date in a similar format to the Unix <literal role="template-keyword" moreinfo="none">date</literal> command, but with
28.12126 +	  timezone included.  Yields a string like <quote><literal moreinfo="none">Mon
28.12127 +	      Sep 04 15:13:13 2006 -0700</literal></quote>.</para>
28.12128 +      </listitem>
28.12129 +      <listitem><para id="x_5a6"><literal role="template-kw-filt-author" moreinfo="none">domain</literal>: Any text,
28.12130 +	  but most useful for the <literal role="template-keyword" moreinfo="none">author</literal> keyword.  Finds
28.12131 +	  the first string that looks like an email address, and
28.12132 +	  extract just the domain component.  For example,
28.12133 +	  <quote><literal moreinfo="none">Bryan O'Sullivan
28.12134 +	      &lt;bos@serpentine.com&gt;</literal></quote> becomes
28.12135 +	  <quote><literal moreinfo="none">serpentine.com</literal></quote>.</para>
28.12136 +      </listitem>
28.12137 +      <listitem><para id="x_5a7"><literal role="template-kw-filt-author" moreinfo="none">email</literal>: Any text,
28.12138 +	  but most useful for the <literal role="template-keyword" moreinfo="none">author</literal> keyword.  Extract
28.12139 +	  the first string that looks like an email address.  For
28.12140 +	  example, <quote><literal moreinfo="none">Bryan O'Sullivan
28.12141 +	      &lt;bos@serpentine.com&gt;</literal></quote> becomes
28.12142 +	  <quote><literal moreinfo="none">bos@serpentine.com</literal></quote>.</para>
28.12143 +      </listitem>
28.12144 +      <listitem><para id="x_5a8"><literal role="template-filter" moreinfo="none">escape</literal>: Any text.
28.12145 +	  Replace the special XML/XHTML characters
28.12146 +	  <quote><literal moreinfo="none">&amp;</literal></quote>,
28.12147 +	  <quote><literal moreinfo="none">&lt;</literal></quote> and
28.12148 +	  <quote><literal moreinfo="none">&gt;</literal></quote> with XML
28.12149 +	  entities.</para>
28.12150 +      </listitem>
28.12151 +      <listitem><para id="x_5a9"><literal role="template-filter" moreinfo="none">fill68</literal>: Any text.  Wrap
28.12152 +	  the text to fit in 68 columns.  This is useful before you
28.12153 +	  pass text through the <literal role="template-filter" moreinfo="none">tabindent</literal> filter, and
28.12154 +	  still want it to fit in an 80-column fixed-font
28.12155 +	  window.</para>
28.12156 +      </listitem>
28.12157 +      <listitem><para id="x_5aa"><literal role="template-filter" moreinfo="none">fill76</literal>: Any text.  Wrap
28.12158 +	  the text to fit in 76 columns.</para>
28.12159 +      </listitem>
28.12160 +      <listitem><para id="x_5ab"><literal role="template-filter" moreinfo="none">firstline</literal>: Any text.
28.12161 +	  Yield the first line of text, without any trailing
28.12162 +	  newlines.</para>
28.12163 +      </listitem>
28.12164 +      <listitem><para id="x_5ac"><literal role="template-kw-filt-date" moreinfo="none">hgdate</literal>: <literal role="template-keyword" moreinfo="none">date</literal> keyword.  Render
28.12165 +	  the date as a pair of readable numbers.  Yields a string
28.12166 +	  like <quote><literal moreinfo="none">1157407993
28.12167 +	      25200</literal></quote>.</para>
28.12168 +      </listitem>
28.12169 +      <listitem><para id="x_5ad"><literal role="template-kw-filt-date" moreinfo="none">isodate</literal>: <literal role="template-keyword" moreinfo="none">date</literal> keyword.  Render
28.12170 +	  the date as a text string in ISO 8601 format.  Yields a
28.12171 +	  string like <quote><literal moreinfo="none">2006-09-04 15:13:13
28.12172 +	      -0700</literal></quote>.</para>
28.12173 +      </listitem>
28.12174 +      <listitem><para id="x_5ae"><literal role="template-filter" moreinfo="none">obfuscate</literal>: Any text, but
28.12175 +	  most useful for the <literal role="template-keyword" moreinfo="none">author</literal> keyword.  Yield
28.12176 +	  the input text rendered as a sequence of XML entities.  This
28.12177 +	  helps to defeat some particularly stupid screen-scraping
28.12178 +	  email harvesting spambots.</para>
28.12179 +      </listitem>
28.12180 +      <listitem><para id="x_5af"><literal role="template-kw-filt-author" moreinfo="none">person</literal>: Any text,
28.12181 +	  but most useful for the <literal role="template-keyword" moreinfo="none">author</literal> keyword.  Yield
28.12182 +	  the text before an email address. For example,
28.12183 +	  <quote><literal moreinfo="none">Bryan O'Sullivan
28.12184 +	      &lt;bos@serpentine.com&gt;</literal></quote> becomes
28.12185 +	  <quote><literal moreinfo="none">Bryan O'Sullivan</literal></quote>.</para>
28.12186 +      </listitem>
28.12187 +      <listitem><para id="x_5b0"><literal role="template-kw-filt-date" moreinfo="none">rfc822date</literal>:
28.12188 +	  <literal role="template-keyword" moreinfo="none">date</literal> keyword.
28.12189 +	  Render a date using the same format used in email headers.
28.12190 +	  Yields a string like <quote><literal moreinfo="none">Mon, 04 Sep 2006
28.12191 +	      15:13:13 -0700</literal></quote>.</para>
28.12192 +      </listitem>
28.12193 +      <listitem><para id="x_5b1"><literal role="template-kw-filt-node" moreinfo="none">short</literal>: Changeset
28.12194 +	  hash.  Yield the short form of a changeset hash, i.e. a
28.12195 +	  12-character hexadecimal string.</para>
28.12196 +      </listitem>
28.12197 +      <listitem><para id="x_5b2"><literal role="template-kw-filt-date" moreinfo="none">shortdate</literal>: <literal role="template-keyword" moreinfo="none">date</literal> keyword.  Render
28.12198 +	  the year, month, and day of the date.  Yields a string like
28.12199 +	  <quote><literal moreinfo="none">2006-09-04</literal></quote>.</para>
28.12200 +      </listitem>
28.12201 +      <listitem><para id="x_5b3"><literal role="template-filter" moreinfo="none">strip</literal>:
28.12202 +	  Any text.  Strip all leading and trailing whitespace from
28.12203 +	  the string.</para>
28.12204 +      </listitem>
28.12205 +      <listitem><para id="x_5b4"><literal role="template-filter" moreinfo="none">tabindent</literal>: Any text.
28.12206 +	  Yield the text, with every line except the first starting
28.12207 +	  with a tab character.</para>
28.12208 +      </listitem>
28.12209 +      <listitem><para id="x_5b5"><literal role="template-filter" moreinfo="none">urlescape</literal>: Any text.
28.12210 +	  Escape all characters that are considered
28.12211 +	  <quote>special</quote> by URL parsers.  For example,
28.12212 +	  <literal moreinfo="none">foo bar</literal> becomes
28.12213 +	  <literal moreinfo="none">foo%20bar</literal>.</para>
28.12214 +      </listitem>
28.12215 +      <listitem><para id="x_5b6"><literal role="template-kw-filt-author" moreinfo="none">user</literal>: Any text,
28.12216 +	  but most useful for the <literal role="template-keyword" moreinfo="none">author</literal> keyword.  Return
28.12217 +	  the <quote>user</quote> portion of an email address.  For
28.12218 +	  example, <quote><literal moreinfo="none">Bryan O'Sullivan
28.12219 +	      &lt;bos@serpentine.com&gt;</literal></quote> becomes
28.12220 +	  <quote><literal moreinfo="none">bos</literal></quote>.</para>
28.12221 +      </listitem>
28.12222 +    </itemizedlist>
28.12223 +
28.12224 +    <!-- BEGIN template.simple.manyfilters -->
28.12225 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{author}\n'</userinput>
28.12226 +Bryan O'Sullivan &lt;bos@serpentine.com&gt;
28.12227 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{author|domain}\n'</userinput>
28.12228 +serpentine.com
28.12229 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{author|email}\n'</userinput>
28.12230 +bos@serpentine.com
28.12231 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{author|obfuscate}\n' | cut -c-76</userinput>
28.12232 +&amp;#66;&amp;#114;&amp;#121;&amp;#97;&amp;#110;&amp;#32;&amp;#79;&amp;#39;&amp;#83;&amp;#117;&amp;#108;&amp;#108;&amp;#105;&amp;#11
28.12233 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{author|person}\n'</userinput>
28.12234 +Bryan O'Sullivan
28.12235 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{author|user}\n'</userinput>
28.12236 +bos
28.12237 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'looks almost right, but actually garbage: {date}\n'</userinput>
28.12238 +looks almost right, but actually garbage: 1250431517.00
28.12239 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{date|age}\n'</userinput>
28.12240 +3 seconds
28.12241 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{date|date}\n'</userinput>
28.12242 +Sun Aug 16 14:05:17 2009 +0000
28.12243 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{date|hgdate}\n'</userinput>
28.12244 +1250431517 0
28.12245 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{date|isodate}\n'</userinput>
28.12246 +2009-08-16 14:05 +0000
28.12247 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{date|rfc822date}\n'</userinput>
28.12248 +Sun, 16 Aug 2009 14:05:17 +0000
28.12249 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{date|shortdate}\n'</userinput>
28.12250 +2009-08-16
28.12251 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{desc}\n' | cut -c-76</userinput>
28.12252 +added line to end of &lt;&lt;hello&gt;&gt; file.
28.12253 +
28.12254 +in addition, added a file with the helpful name (at least i hope that some m
28.12255 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{desc|addbreaks}\n' | cut -c-76</userinput>
28.12256 +added line to end of &lt;&lt;hello&gt;&gt; file.&lt;br/&gt;
28.12257 +&lt;br/&gt;
28.12258 +in addition, added a file with the helpful name (at least i hope that some m
28.12259 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{desc|escape}\n' | cut -c-76</userinput>
28.12260 +added line to end of &amp;lt;&amp;lt;hello&amp;gt;&amp;gt; file.
28.12261 +
28.12262 +in addition, added a file with the helpful name (at least i hope that some m
28.12263 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{desc|fill68}\n'</userinput>
28.12264 +added line to end of &lt;&lt;hello&gt;&gt; file.
28.12265 +
28.12266 +in addition, added a file with the helpful name (at least i hope
28.12267 +that some might consider it so) of goodbye.
28.12268 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{desc|fill76}\n'</userinput>
28.12269 +added line to end of &lt;&lt;hello&gt;&gt; file.
28.12270 +
28.12271 +in addition, added a file with the helpful name (at least i hope that some
28.12272 +might consider it so) of goodbye.
28.12273 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{desc|firstline}\n'</userinput>
28.12274 +added line to end of &lt;&lt;hello&gt;&gt; file.
28.12275 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{desc|strip}\n' | cut -c-76</userinput>
28.12276 +added line to end of &lt;&lt;hello&gt;&gt; file.
28.12277 +
28.12278 +in addition, added a file with the helpful name (at least i hope that some m
28.12279 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{desc|tabindent}\n' | expand | cut -c-76</userinput>
28.12280 +added line to end of &lt;&lt;hello&gt;&gt; file.
28.12281 +
28.12282 +        in addition, added a file with the helpful name (at least i hope tha
28.12283 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{node}\n'</userinput>
28.12284 +e3d2468ca47c10bdfbbb41b367a0c84509862197
28.12285 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{node|short}\n'</userinput>
28.12286 +e3d2468ca47c
28.12287 +</screen>
28.12288 +<!-- END template.simple.manyfilters -->
28.12289 +
28.12290 +
28.12291 +    <note>
28.12292 +      <para id="x_5b7">  If you try to apply a filter to a piece of data that it
28.12293 +	cannot process, Mercurial will fail and print a Python
28.12294 +	exception.  For example, trying to run the output of the
28.12295 +	<literal role="template-keyword" moreinfo="none">desc</literal> keyword into
28.12296 +	the <literal role="template-kw-filt-date" moreinfo="none">isodate</literal>
28.12297 +	filter is not a good idea.</para>
28.12298 +    </note>
28.12299 +
28.12300 +    <sect2>
28.12301 +      <title>Combining filters</title>
28.12302 +
28.12303 +      <para id="x_5b8">It is easy to combine filters to yield output in the form
28.12304 +	you would like.  The following chain of filters tidies up a
28.12305 +	description, then makes sure that it fits cleanly into 68
28.12306 +	columns, then indents it by a further 8 characters (at least
28.12307 +	on Unix-like systems, where a tab is conventionally 8
28.12308 +	characters wide).</para>
28.12309 +
28.12310 +      <!-- BEGIN template.simple.combine -->
28.12311 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'description:\n\t{desc|strip|fill68|tabindent}\n'</userinput>
28.12312 +description:
28.12313 +	added line to end of &lt;&lt;hello&gt;&gt; file.
28.12314 +
28.12315 +	in addition, added a file with the helpful name (at least i hope
28.12316 +	that some might consider it so) of goodbye.
28.12317 +</screen>
28.12318 +<!-- END template.simple.combine -->
28.12319 +
28.12320 +
28.12321 +      <para id="x_5b9">Note the use of <quote><literal moreinfo="none">\t</literal></quote> (a
28.12322 +	tab character) in the template to force the first line to be
28.12323 +	indented; this is necessary since <literal role="template-keyword" moreinfo="none">tabindent</literal> indents all
28.12324 +	lines <emphasis>except</emphasis> the first.</para>
28.12325 +
28.12326 +      <para id="x_5ba">Keep in mind that the order of filters in a chain is
28.12327 +	significant.  The first filter is applied to the result of the
28.12328 +	keyword; the second to the result of the first filter; and so
28.12329 +	on.  For example, using <literal moreinfo="none">fill68|tabindent</literal>
28.12330 +	gives very different results from
28.12331 +	<literal moreinfo="none">tabindent|fill68</literal>.</para>
28.12332 +    </sect2>
28.12333 +  </sect1>
28.12334 +
28.12335 +  <sect1>
28.12336 +    <title>From templates to styles</title>
28.12337 +
28.12338 +    <para id="x_5bb">A command line template provides a quick and simple way to
28.12339 +      format some output.  Templates can become verbose, though, and
28.12340 +      it's useful to be able to give a template a name.  A style file
28.12341 +      is a template with a name, stored in a file.</para>
28.12342 +
28.12343 +    <para id="x_5bc">More than that, using a style file unlocks the power of
28.12344 +      Mercurial's templating engine in ways that are not possible
28.12345 +      using the command line <option role="hg-opt-log">--template</option> option.</para>
28.12346 +
28.12347 +    <sect2>
28.12348 +      <title>The simplest of style files</title>
28.12349 +
28.12350 +      <para id="x_5bd">Our simple style file contains just one line:</para>
28.12351 +
28.12352 +      <!-- BEGIN template.simple.rev -->
28.12353 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'changeset = "rev: {rev}\n"' &gt; rev</userinput>
28.12354 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -l1 --style ./rev</userinput>
28.12355 +rev: 3
28.12356 +</screen>
28.12357 +<!-- END template.simple.rev -->
28.12358 +
28.12359 +
28.12360 +      <para id="x_5be">This tells Mercurial, <quote>if you're printing a
28.12361 +	  changeset, use the text on the right as the
28.12362 +	  template</quote>.</para>
28.12363 +    </sect2>
28.12364 +
28.12365 +    <sect2>
28.12366 +      <title>Style file syntax</title>
28.12367 +
28.12368 +      <para id="x_5bf">The syntax rules for a style file are simple.</para>
28.12369 +
28.12370 +      <itemizedlist>
28.12371 +	<listitem><para id="x_5c0">The file is processed one line at a
28.12372 +	    time.</para>
28.12373 +	</listitem>
28.12374 +	<listitem><para id="x_5c1">Leading and trailing white space are
28.12375 +	    ignored.</para>
28.12376 +	</listitem>
28.12377 +	<listitem><para id="x_5c2">Empty lines are skipped.</para>
28.12378 +	</listitem>
28.12379 +	<listitem><para id="x_5c3">If a line starts with either of the characters
28.12380 +	    <quote><literal moreinfo="none">#</literal></quote> or
28.12381 +	    <quote><literal moreinfo="none">;</literal></quote>, the entire line is
28.12382 +	    treated as a comment, and skipped as if empty.</para>
28.12383 +	</listitem>
28.12384 +	<listitem><para id="x_5c4">A line starts with a keyword.  This must start
28.12385 +	    with an alphabetic character or underscore, and can
28.12386 +	    subsequently contain any alphanumeric character or
28.12387 +	    underscore.  (In regexp notation, a keyword must match
28.12388 +	    <literal moreinfo="none">[A-Za-z_][A-Za-z0-9_]*</literal>.)</para>
28.12389 +	</listitem>
28.12390 +	<listitem><para id="x_5c5">The next element must be an
28.12391 +	    <quote><literal moreinfo="none">=</literal></quote> character, which can
28.12392 +	    be preceded or followed by an arbitrary amount of white
28.12393 +	    space.</para>
28.12394 +	</listitem>
28.12395 +	<listitem><para id="x_5c6">If the rest of the line starts and ends with
28.12396 +	    matching quote characters (either single or double quote),
28.12397 +	    it is treated as a template body.</para>
28.12398 +	</listitem>
28.12399 +	<listitem><para id="x_5c7">If the rest of the line <emphasis>does
28.12400 +	      not</emphasis> start with a quote character, it is
28.12401 +	    treated as the name of a file; the contents of this file
28.12402 +	    will be read and used as a template body.</para>
28.12403 +	</listitem></itemizedlist>
28.12404 +    </sect2>
28.12405 +  </sect1>
28.12406 +
28.12407 +  <sect1>
28.12408 +    <title>Style files by example</title>
28.12409 +
28.12410 +    <para id="x_5c8">To illustrate how to write a style file, we will construct a
28.12411 +      few by example.  Rather than provide a complete style file and
28.12412 +      walk through it, we'll mirror the usual process of developing a
28.12413 +      style file by starting with something very simple, and walking
28.12414 +      through a series of successively more complete examples.</para>
28.12415 +
28.12416 +    <sect2>
28.12417 +      <title>Identifying mistakes in style files</title>
28.12418 +
28.12419 +      <para id="x_5c9">If Mercurial encounters a problem in a style file you are
28.12420 +	working on, it prints a terse error message that, once you
28.12421 +	figure out what it means, is actually quite useful.</para>
28.12422 +
28.12423 +<!-- BEGIN template.svnstyle.syntax.input -->
28.12424 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat broken.style</userinput>
28.12425 +changeset =
28.12426 +</screen>
28.12427 +<!-- END template.svnstyle.syntax.input -->
28.12428 +
28.12429 +
28.12430 +      <para id="x_5ca">Notice that <filename moreinfo="none">broken.style</filename> attempts to
28.12431 +	define a <literal moreinfo="none">changeset</literal> keyword, but forgets to
28.12432 +	give any content for it. When instructed to use this style
28.12433 +	file, Mercurial promptly complains.</para>
28.12434 +
28.12435 +      <!-- BEGIN template.svnstyle.syntax.error -->
28.12436 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --style broken.style</userinput>
28.12437 +abort: broken.style:1: parse error
28.12438 +</screen>
28.12439 +<!-- END template.svnstyle.syntax.error -->
28.12440 +
28.12441 +
28.12442 +      <para id="x_5cb">This error message looks intimidating, but it is not too
28.12443 +	hard to follow.</para>
28.12444 +
28.12445 +      <itemizedlist>
28.12446 +	<listitem><para id="x_5cc">The first component is simply Mercurial's way
28.12447 +	    of saying <quote>I am giving up</quote>.</para>
28.12448 +	  <programlisting format="linespecific">___abort___: broken.style:1: parse error</programlisting>
28.12449 +	</listitem>
28.12450 +	<listitem><para id="x_5cd">Next comes the name of the style file that
28.12451 +	    contains the error.</para>
28.12452 +	  <programlisting format="linespecific">abort: ___broken.style___:1: parse error</programlisting>
28.12453 +	</listitem>
28.12454 +	<listitem><para id="x_5ce">Following the file name is the line number
28.12455 +	    where the error was encountered.</para>
28.12456 +	  <programlisting format="linespecific">abort: broken.style:___1___: parse error</programlisting>
28.12457 +	</listitem>
28.12458 +	<listitem><para id="x_5cf">Finally, a description of what went
28.12459 +	    wrong.</para>
28.12460 +	  <programlisting format="linespecific">abort: broken.style:1: ___parse error___</programlisting>
28.12461 +	</listitem>
28.12462 +	<listitem><para id="x_5d0">The description of the problem is not always
28.12463 +	    clear (as in this case), but even when it is cryptic, it
28.12464 +	    is almost always trivial to visually inspect the offending
28.12465 +	    line in the style file and see what is wrong.</para>
28.12466 +	</listitem>
28.12467 +      </itemizedlist>
28.12468 +    </sect2>
28.12469 +
28.12470 +    <sect2>
28.12471 +      <title>Uniquely identifying a repository</title>
28.12472 +
28.12473 +      <para id="x_5d1">If you would like to be able to identify a Mercurial
28.12474 +	repository <quote>fairly uniquely</quote> using a short string
28.12475 +	as an identifier, you can use the first revision in the
28.12476 +	repository.</para>
28.12477 +
28.12478 +      <!-- BEGIN template.svnstyle.id -->
28.12479 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r0 --template '{node}'</userinput>
28.12480 +02b4f9d8a52a6da645e20fa7df0accc8aa33b650</screen>
28.12481 +<!-- END template.svnstyle.id -->
28.12482 +
28.12483 +
28.12484 +      <para id="x_5d2">This is likely to be unique, and so it is
28.12485 +	useful in many cases.  There are a few caveats.</para>
28.12486 +      <itemizedlist>
28.12487 +	<listitem><para id="x_5d3">It will not work in a completely empty
28.12488 +	    repository, because such a repository does not have a
28.12489 +	    revision zero.</para>
28.12490 +	</listitem>
28.12491 +	<listitem><para id="x_5d4">Neither will it work in the (extremely rare)
28.12492 +	    case where a repository is a merge of two or more formerly
28.12493 +	    independent repositories, and you still have those
28.12494 +	    repositories around.</para>
28.12495 +	</listitem></itemizedlist>
28.12496 +      <para id="x_5d5">Here are some uses to which you could put this
28.12497 +	identifier:</para>
28.12498 +      <itemizedlist>
28.12499 +	<listitem><para id="x_5d6">As a key into a table for a database that
28.12500 +	    manages repositories on a server.</para>
28.12501 +	</listitem>
28.12502 +	<listitem><para id="x_5d7">As half of a {<emphasis>repository
28.12503 +	      ID</emphasis>, <emphasis>revision ID</emphasis>} tuple.
28.12504 +	    Save this information away when you run an automated build
28.12505 +	    or other activity, so that you can <quote>replay</quote>
28.12506 +	    the build later if necessary.</para>
28.12507 +	</listitem>
28.12508 +      </itemizedlist>
28.12509 +    </sect2>
28.12510 +
28.12511 +    <sect2>
28.12512 +      <title>Listing files on multiple lines</title>
28.12513 +
28.12514 +      <para id="x_714">Suppose we want to list the files changed by a changeset,
28.12515 +	one per line, with a little indentation before each file
28.12516 +	name.</para>
28.12517 +
28.12518 +      <!-- BEGIN ch10/multiline.go -->
28.12519 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat &gt; multiline &lt;&lt; EOF</userinput>
28.12520 +<prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">changeset = "Changed in {node|short}:\n{files}"</userinput>
28.12521 +<prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">file = "  {file}\n"</userinput>
28.12522 +<prompt moreinfo="none">&gt;</prompt> <userinput moreinfo="none">EOF</userinput>
28.12523 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log --style multiline</userinput>
28.12524 +Changed in badb58085712:
28.12525 +  .bashrc
28.12526 +  .hgrc
28.12527 +  test.c
28.12528 +</screen>
28.12529 +<!-- END ch10/multiline.go -->
28.12530 +
28.12531 +    </sect2>
28.12532 +
28.12533 +    <sect2>
28.12534 +      <title>Mimicking Subversion's output</title>
28.12535 +
28.12536 +      <para id="x_5d8">Let's try to emulate the default output format used by
28.12537 +	another revision control tool, Subversion.</para>
28.12538 +
28.12539 +      <!-- BEGIN template.svnstyle.short -->
28.12540 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">svn log -r9653</userinput>
28.12541 +------------------------------------------------------------------------
28.12542 +r9653 | sean.hefty | 2006-09-27 14:39:55 -0700 (Wed, 27 Sep 2006) | 5 lines
28.12543 +
28.12544 +On reporting a route error, also include the status for the error,
28.12545 +rather than indicating a status of 0 when an error has occurred.
28.12546 +
28.12547 +Signed-off-by: Sean Hefty &lt;sean.hefty@intel.com&gt;
28.12548 +
28.12549 +------------------------------------------------------------------------
28.12550 +</screen>
28.12551 +<!-- END template.svnstyle.short -->
28.12552 +
28.12553 +
28.12554 +      <para id="x_5d9">Since Subversion's output style is fairly simple, it is
28.12555 +	easy to copy-and-paste a hunk of its output into a file, and
28.12556 +	replace the text produced above by Subversion with the
28.12557 +	template values we'd like to see expanded.</para>
28.12558 +
28.12559 +      <!-- BEGIN template.svnstyle.template -->
28.12560 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat svn.template</userinput>
28.12561 +r{rev} | {author|user} | {date|isodate} ({date|rfc822date})
28.12562 +
28.12563 +{desc|strip|fill76}
28.12564 +
28.12565 +------------------------------------------------------------------------
28.12566 +</screen>
28.12567 +<!-- END template.svnstyle.template -->
28.12568 +
28.12569 +
28.12570 +      <para id="x_5da">There are a few small ways in which this template deviates
28.12571 +	from the output produced by Subversion.</para>
28.12572 +      <itemizedlist>
28.12573 +	<listitem><para id="x_5db">Subversion prints a <quote>readable</quote>
28.12574 +	    date (the <quote><literal moreinfo="none">Wed, 27 Sep 2006</literal></quote> in the
28.12575 +	    example output above) in parentheses.  Mercurial's
28.12576 +	    templating engine does not provide a way to display a date
28.12577 +	    in this format without also printing the time and time
28.12578 +	    zone.</para>
28.12579 +	</listitem>
28.12580 +	<listitem><para id="x_5dc">We emulate Subversion's printing of
28.12581 +	    <quote>separator</quote> lines full of
28.12582 +	    <quote><literal moreinfo="none">-</literal></quote> characters by ending
28.12583 +	    the template with such a line. We use the templating
28.12584 +	    engine's <literal role="template-keyword" moreinfo="none">header</literal>
28.12585 +	    keyword to print a separator line as the first line of
28.12586 +	    output (see below), thus achieving similar output to
28.12587 +	    Subversion.</para>
28.12588 +	</listitem>
28.12589 +	<listitem><para id="x_5dd">Subversion's output includes a count in the
28.12590 +	    header of the number of lines in the commit message.  We
28.12591 +	    cannot replicate this in Mercurial; the templating engine
28.12592 +	    does not currently provide a filter that counts the number
28.12593 +	    of lines the template generates.</para>
28.12594 +	</listitem></itemizedlist>
28.12595 +      <para id="x_5de">It took me no more than a minute or two of work to replace
28.12596 +	literal text from an example of Subversion's output with some
28.12597 +	keywords and filters to give the template above.  The style
28.12598 +	file simply refers to the template.</para>
28.12599 +
28.12600 +      <!-- BEGIN template.svnstyle.style -->
28.12601 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat svn.style</userinput>
28.12602 +header = '------------------------------------------------------------------------\n\n'
28.12603 +changeset = svn.template
28.12604 +</screen>
28.12605 +<!-- END template.svnstyle.style -->
28.12606 +
28.12607 +
28.12608 +      <para id="x_5df">We could have included the text of the template file
28.12609 +	directly in the style file by enclosing it in quotes and
28.12610 +	replacing the newlines with
28.12611 +	<quote><literal moreinfo="none">\n</literal></quote> sequences, but it would
28.12612 +	have made the style file too difficult to read.  Readability
28.12613 +	is a good guide when you're trying to decide whether some text
28.12614 +	belongs in a style file, or in a template file that the style
28.12615 +	file points to.  If the style file will look too big or
28.12616 +	cluttered if you insert a literal piece of text, drop it into
28.12617 +	a template instead.</para>
28.12618 +    </sect2>
28.12619 +  </sect1>
28.12620 +</chapter>
28.12621 +
28.12622 +<!--
28.12623 +local variables: 
28.12624 +sgml-parent-document: ("00book.xml" "book" "chapter")
28.12625 +end:
28.12626 +-->
28.12627 +
28.12628 +  <!-- BEGIN ch12 -->
28.12629 +  <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
28.12630 +
28.12631 +<chapter id="chap:mq">
28.12632 +  <?dbhtml filename="managing-change-with-mercurial-queues.html"?>
28.12633 +  <title>Managing change with Mercurial Queues</title>
28.12634 +
28.12635 +  <sect1 id="sec:mq:patch-mgmt">
28.12636 +    <title>The patch management problem</title>
28.12637 +
28.12638 +    <para id="x_3ac">Here is a common scenario: you need to install a software
28.12639 +      package from source, but you find a bug that you must fix in the
28.12640 +      source before you can start using the package.  You make your
28.12641 +      changes, forget about the package for a while, and a few months
28.12642 +      later you need to upgrade to a newer version of the package.  If
28.12643 +      the newer version of the package still has the bug, you must
28.12644 +      extract your fix from the older source tree and apply it against
28.12645 +      the newer version.  This is a tedious task, and it's easy to
28.12646 +      make mistakes.</para>
28.12647 +
28.12648 +    <para id="x_3ad">This is a simple case of the <quote>patch management</quote>
28.12649 +      problem.  You have an <quote>upstream</quote> source tree that
28.12650 +      you can't change; you need to make some local changes on top of
28.12651 +      the upstream tree; and you'd like to be able to keep those
28.12652 +      changes separate, so that you can apply them to newer versions
28.12653 +      of the upstream source.</para>
28.12654 +
28.12655 +    <para id="x_3ae">The patch management problem arises in many situations.
28.12656 +      Probably the most visible is that a user of an open source
28.12657 +      software project will contribute a bug fix or new feature to the
28.12658 +      project's maintainers in the form of a patch.</para>
28.12659 +
28.12660 +    <para id="x_3af">Distributors of operating systems that include open source
28.12661 +      software often need to make changes to the packages they
28.12662 +      distribute so that they will build properly in their
28.12663 +      environments.</para>
28.12664 +
28.12665 +    <para id="x_3b0">When you have few changes to maintain, it is easy to manage
28.12666 +      a single patch using the standard <command moreinfo="none">diff</command> and
28.12667 +      <command moreinfo="none">patch</command> programs (see <xref linkend="sec:mq:patch"/> for a discussion of these
28.12668 +      tools). Once the number of changes grows, it starts to make
28.12669 +      sense to maintain patches as discrete <quote>chunks of
28.12670 +	work,</quote> so that for example a single patch will contain
28.12671 +      only one bug fix (the patch might modify several files, but it's
28.12672 +      doing <quote>only one thing</quote>), and you may have a number
28.12673 +      of such patches for different bugs you need fixed and local
28.12674 +      changes you require.  In this situation, if you submit a bug fix
28.12675 +      patch to the upstream maintainers of a package and they include
28.12676 +      your fix in a subsequent release, you can simply drop that
28.12677 +      single patch when you're updating to the newer release.</para>
28.12678 +
28.12679 +    <para id="x_3b1">Maintaining a single patch against an upstream tree is a
28.12680 +      little tedious and error-prone, but not difficult.  However, the
28.12681 +      complexity of the problem grows rapidly as the number of patches
28.12682 +      you have to maintain increases.  With more than a tiny number of
28.12683 +      patches in hand, understanding which ones you have applied and
28.12684 +      maintaining them moves from messy to overwhelming.</para>
28.12685 +
28.12686 +    <para id="x_3b2">Fortunately, Mercurial includes a powerful extension,
28.12687 +      Mercurial Queues (or simply <quote>MQ</quote>), that massively
28.12688 +      simplifies the patch management problem.</para>
28.12689 +
28.12690 +  </sect1>
28.12691 +  <sect1 id="sec:mq:history">
28.12692 +    <title>The prehistory of Mercurial Queues</title>
28.12693 +
28.12694 +    <para id="x_3b3">During the late 1990s, several Linux kernel developers
28.12695 +      started to maintain <quote>patch series</quote> that modified
28.12696 +      the behavior of the Linux kernel.  Some of these series were
28.12697 +      focused on stability, some on feature coverage, and others were
28.12698 +      more speculative.</para>
28.12699 +
28.12700 +    <para id="x_3b4">The sizes of these patch series grew rapidly.  In 2002,
28.12701 +      Andrew Morton published some shell scripts he had been using to
28.12702 +      automate the task of managing his patch queues.  Andrew was
28.12703 +      successfully using these scripts to manage hundreds (sometimes
28.12704 +      thousands) of patches on top of the Linux kernel.</para>
28.12705 +
28.12706 +    <sect2 id="sec:mq:quilt">
28.12707 +      <title>A patchwork quilt</title>
28.12708 +
28.12709 +      <para id="x_3b5">In early 2003, Andreas Gruenbacher and Martin Quinson
28.12710 +	borrowed the approach of Andrew's scripts and published a tool
28.12711 +	called <quote>patchwork quilt</quote>
28.12712 +	<citation>web:quilt</citation>, or simply <quote>quilt</quote>
28.12713 +	(see <citation>gruenbacher:2005</citation> for a paper
28.12714 +	describing it).  Because quilt substantially automated patch
28.12715 +	management, it rapidly gained a large following among open
28.12716 +	source software developers.</para>
28.12717 +
28.12718 +      <para id="x_3b6">Quilt manages a <emphasis>stack of patches</emphasis> on
28.12719 +	top of a directory tree. To begin, you tell quilt to manage a
28.12720 +	directory tree, and tell it which files you want to manage; it
28.12721 +	stores away the names and contents of those files.  To fix a
28.12722 +	bug, you create a new patch (using a single command), edit the
28.12723 +	files you need to fix, then <quote>refresh</quote> the
28.12724 +	patch.</para>
28.12725 +
28.12726 +      <para id="x_3b7">The refresh step causes quilt to scan the directory tree;
28.12727 +	it updates the patch with all of the changes you have made.
28.12728 +	You can create another patch on top of the first, which will
28.12729 +	track the changes required to modify the tree from <quote>tree
28.12730 +	  with one patch applied</quote> to <quote>tree with two
28.12731 +	  patches applied</quote>.</para>
28.12732 +
28.12733 +      <para id="x_3b8">You can <emphasis>change</emphasis> which patches are
28.12734 +	applied to the tree.  If you <quote>pop</quote> a patch, the
28.12735 +	changes made by that patch will vanish from the directory
28.12736 +	tree.  Quilt remembers which patches you have popped, though,
28.12737 +	so you can <quote>push</quote> a popped patch again, and the
28.12738 +	directory tree will be restored to contain the modifications
28.12739 +	in the patch.  Most importantly, you can run the
28.12740 +	<quote>refresh</quote> command at any time, and the topmost
28.12741 +	applied patch will be updated.  This means that you can, at
28.12742 +	any time, change both which patches are applied and what
28.12743 +	modifications those patches make.</para>
28.12744 +
28.12745 +      <para id="x_3b9">Quilt knows nothing about revision control tools, so it
28.12746 +	works equally well on top of an unpacked tarball or a
28.12747 +	Subversion working copy.</para>
28.12748 +    </sect2>
28.12749 +
28.12750 +    <sect2 id="sec:mq:quilt-mq">
28.12751 +      <title>From patchwork quilt to Mercurial Queues</title>
28.12752 +
28.12753 +      <para id="x_3ba">In mid-2005, Chris Mason took the features of quilt and
28.12754 +	wrote an extension that he called Mercurial Queues, which
28.12755 +	added quilt-like behavior to Mercurial.</para>
28.12756 +
28.12757 +      <para id="x_3bb">The key difference between quilt and MQ is that quilt
28.12758 +	knows nothing about revision control systems, while MQ is
28.12759 +	<emphasis>integrated</emphasis> into Mercurial.  Each patch
28.12760 +	that you push is represented as a Mercurial changeset.  Pop a
28.12761 +	patch, and the changeset goes away.</para>
28.12762 +
28.12763 +      <para id="x_3bc">Because quilt does not care about revision control tools,
28.12764 +	it is still a tremendously useful piece of software to know
28.12765 +	about for situations where you cannot use Mercurial and
28.12766 +	MQ.</para>
28.12767 +
28.12768 +    </sect2>
28.12769 +  </sect1>
28.12770 +  <sect1>
28.12771 +    <title>The huge advantage of MQ</title>
28.12772 +
28.12773 +    <para id="x_3bd">I cannot overstate the value that MQ offers through the
28.12774 +      unification of patches and revision control.</para>
28.12775 +
28.12776 +    <para id="x_3be">A major reason that patches have persisted in the free
28.12777 +      software and open source world—in spite of the
28.12778 +      availability of increasingly capable revision control tools over
28.12779 +      the years—is the <emphasis>agility</emphasis> they
28.12780 +      offer.</para>
28.12781 +
28.12782 +    <para id="x_3bf">Traditional revision control tools make a permanent,
28.12783 +      irreversible record of everything that you do.  While this has
28.12784 +      great value, it's also somewhat stifling.  If you want to
28.12785 +      perform a wild-eyed experiment, you have to be careful in how
28.12786 +      you go about it, or you risk leaving unneeded—or worse,
28.12787 +      misleading or destabilising—traces of your missteps and
28.12788 +      errors in the permanent revision record.</para>
28.12789 +
28.12790 +    <para id="x_3c0">By contrast, MQ's marriage of distributed revision control
28.12791 +      with patches makes it much easier to isolate your work.  Your
28.12792 +      patches live on top of normal revision history, and you can make
28.12793 +      them disappear or reappear at will.  If you don't like a patch,
28.12794 +      you can drop it.  If a patch isn't quite as you want it to be,
28.12795 +      simply fix it—as many times as you need to, until you
28.12796 +      have refined it into the form you desire.</para>
28.12797 +
28.12798 +    <para id="x_3c1">As an example, the integration of patches with revision
28.12799 +      control makes understanding patches and debugging their
28.12800 +      effects—and their interplay with the code they're based
28.12801 +      on—<emphasis>enormously</emphasis> easier. Since every
28.12802 +      applied patch has an associated changeset, you can give <command role="hg-cmd" moreinfo="none">hg log</command> a file name to see which
28.12803 +      changesets and patches affected the file.  You can use the
28.12804 +      <command role="hg-cmd" moreinfo="none">hg bisect</command> command to
28.12805 +      binary-search through all changesets and applied patches to see
28.12806 +      where a bug got introduced or fixed.  You can use the <command role="hg-cmd" moreinfo="none">hg annotate</command> command to see which
28.12807 +      changeset or patch modified a particular line of a source file.
28.12808 +      And so on.</para>
28.12809 +  </sect1>
28.12810 +
28.12811 +  <sect1 id="sec:mq:patch">
28.12812 +    <title>Understanding patches</title>
28.12813 +
28.12814 +    <para id="x_3c2">Because MQ doesn't hide its patch-oriented nature, it is
28.12815 +      helpful to understand what patches are, and a little about the
28.12816 +      tools that work with them.</para>
28.12817 +
28.12818 +    <para id="x_3c3">The traditional Unix <command moreinfo="none">diff</command> command
28.12819 +      compares two files, and prints a list of differences between
28.12820 +      them. The <command moreinfo="none">patch</command> command understands these
28.12821 +      differences as <emphasis>modifications</emphasis> to make to a
28.12822 +      file.  Take a look below for a simple example of these commands
28.12823 +      in action.</para>
28.12824 +
28.12825 +      <!-- BEGIN mq.dodiff.diff -->
28.12826 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'this is my original thought' &gt; oldfile</userinput>
28.12827 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'i have changed my mind' &gt; newfile</userinput>
28.12828 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">diff -u oldfile newfile &gt; tiny.patch</userinput>
28.12829 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat tiny.patch</userinput>
28.12830 +--- oldfile	2009-08-16 14:05:06.000000000 +0000
28.12831 ++++ newfile	2009-08-16 14:05:06.000000000 +0000
28.12832 +@@ -1 +1 @@
28.12833 +-this is my original thought
28.12834 ++i have changed my mind
28.12835 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">patch &lt; tiny.patch</userinput>
28.12836 +patching file oldfile
28.12837 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat oldfile</userinput>
28.12838 +i have changed my mind
28.12839 +</screen>
28.12840 +<!-- END mq.dodiff.diff -->
28.12841 +
28.12842 +
28.12843 +    <para id="x_3c4">The type of file that <command moreinfo="none">diff</command> generates (and
28.12844 +      <command moreinfo="none">patch</command> takes as input) is called a
28.12845 +      <quote>patch</quote> or a <quote>diff</quote>; there is no
28.12846 +      difference between a patch and a diff.  (We'll use the term
28.12847 +      <quote>patch</quote>, since it's more commonly used.)</para>
28.12848 +
28.12849 +    <para id="x_3c5">A patch file can start with arbitrary text; the
28.12850 +      <command moreinfo="none">patch</command> command ignores this text, but MQ uses
28.12851 +      it as the commit message when creating changesets.  To find the
28.12852 +      beginning of the patch content, <command moreinfo="none">patch</command>
28.12853 +      searches for the first line that starts with the string
28.12854 +      <quote><literal moreinfo="none">diff -</literal></quote>.</para>
28.12855 +
28.12856 +    <para id="x_3c6">MQ works with <emphasis>unified</emphasis> diffs
28.12857 +      (<command moreinfo="none">patch</command> can accept several other diff formats,
28.12858 +      but MQ doesn't).  A unified diff contains two kinds of header.
28.12859 +      The <emphasis>file header</emphasis> describes the file being
28.12860 +      modified; it contains the name of the file to modify.  When
28.12861 +      <command moreinfo="none">patch</command> sees a new file header, it looks for a
28.12862 +      file with that name to start modifying.</para>
28.12863 +
28.12864 +    <para id="x_3c7">After the file header comes a series of
28.12865 +      <emphasis>hunks</emphasis>.  Each hunk starts with a header;
28.12866 +      this identifies the range of line numbers within the file that
28.12867 +      the hunk should modify.  Following the header, a hunk starts and
28.12868 +      ends with a few (usually three) lines of text from the
28.12869 +      unmodified file; these are called the
28.12870 +      <emphasis>context</emphasis> for the hunk.  If there's only a
28.12871 +      small amount of context between successive hunks,
28.12872 +      <command moreinfo="none">diff</command> doesn't print a new hunk header; it just
28.12873 +      runs the hunks together, with a few lines of context between
28.12874 +      modifications.</para>
28.12875 +
28.12876 +    <para id="x_3c8">Each line of context begins with a space character.  Within
28.12877 +      the hunk, a line that begins with
28.12878 +      <quote><literal moreinfo="none">-</literal></quote> means <quote>remove this
28.12879 +	line,</quote> while a line that begins with
28.12880 +      <quote><literal moreinfo="none">+</literal></quote> means <quote>insert this
28.12881 +	line.</quote>  For example, a line that is modified is
28.12882 +      represented by one deletion and one insertion.</para>
28.12883 +
28.12884 +    <para id="x_3c9">We will return to some of the more subtle aspects of patches
28.12885 +      later (in <xref linkend="sec:mq:adv-patch"/>), but you
28.12886 +      should have
28.12887 +      enough information now to use MQ.</para>
28.12888 +  </sect1>
28.12889 +
28.12890 +  <sect1 id="sec:mq:start">
28.12891 +    <title>Getting started with Mercurial Queues</title>
28.12892 +
28.12893 +    <para id="x_3ca">Because MQ is implemented as an extension, you must
28.12894 +      explicitly enable before you can use it.  (You don't need to
28.12895 +      download anything; MQ ships with the standard Mercurial
28.12896 +      distribution.)  To enable MQ, edit your <filename role="home" moreinfo="none">~/.hgrc</filename> file, and add the lines
28.12897 +      below.</para>
28.12898 +
28.12899 +    <programlisting format="linespecific">[extensions]
28.12900 +hgext.mq =</programlisting>
28.12901 +
28.12902 +    <para id="x_3cb">Once the extension is enabled, it will make a number of new
28.12903 +      commands available.  To verify that the extension is working,
28.12904 +      you can use <command role="hg-cmd" moreinfo="none">hg help</command> to see if
28.12905 +      the <command role="hg-ext-mq" moreinfo="none">qinit</command> command is now
28.12906 +      available.</para>
28.12907 +
28.12908 +    <!-- BEGIN mq.qinit-help.help -->
28.12909 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg help qinit</userinput>
28.12910 +hg qinit [-c]
28.12911 +
28.12912 +init a new queue repository
28.12913 +
28.12914 +    The queue repository is unversioned by default. If -c is
28.12915 +    specified, qinit will create a separate nested repository
28.12916 +    for patches (qinit -c may also be run later to convert
28.12917 +    an unversioned patch repository into a versioned one).
28.12918 +    You can use qcommit to commit changes to this queue repository.
28.12919 +
28.12920 +options:
28.12921 +
28.12922 + -c --create-repo  create queue repository
28.12923 +
28.12924 +use "hg -v help qinit" to show global options
28.12925 +</screen>
28.12926 +<!-- END mq.qinit-help.help -->
28.12927 +
28.12928 +
28.12929 +    <para id="x_3cc">You can use MQ with <emphasis>any</emphasis> Mercurial
28.12930 +      repository, and its commands only operate within that
28.12931 +      repository.  To get started, simply prepare the repository using
28.12932 +      the <command role="hg-ext-mq" moreinfo="none">qinit</command> command.</para>
28.12933 +
28.12934 +    <!-- BEGIN mq.tutorial.qinit -->
28.12935 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init mq-sandbox</userinput>
28.12936 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd mq-sandbox</userinput>
28.12937 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'line 1' &gt; file1</userinput>
28.12938 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'another line 1' &gt; file2</userinput>
28.12939 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add file1 file2</userinput>
28.12940 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m'first change'</userinput>
28.12941 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qinit</userinput>
28.12942 +</screen>
28.12943 +<!-- END mq.tutorial.qinit -->
28.12944 +
28.12945 +
28.12946 +    <para id="x_3cd">This command creates an empty directory called <filename role="special" class="directory" moreinfo="none">.hg/patches</filename>, where
28.12947 +      MQ will keep its metadata.  As with many Mercurial commands, the
28.12948 +      <command role="hg-ext-mq" moreinfo="none">qinit</command> command prints nothing
28.12949 +      if it succeeds.</para>
28.12950 +
28.12951 +    <sect2>
28.12952 +      <title>Creating a new patch</title>
28.12953 +
28.12954 +      <para id="x_3ce">To begin work on a new patch, use the <command role="hg-ext-mq" moreinfo="none">qnew</command> command.  This command takes
28.12955 +	one argument, the name of the patch to create.</para>
28.12956 +
28.12957 +      <para id="x_3cf">MQ will use this as the name of an actual file in the
28.12958 +	<filename role="special" class="directory" moreinfo="none">.hg/patches</filename> directory, as you
28.12959 +	can see below.</para>
28.12960 +
28.12961 +      <!-- BEGIN mq.tutorial.qnew -->
28.12962 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput>
28.12963 +changeset:   0:5d84c303994b
28.12964 +tag:         tip
28.12965 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
28.12966 +date:        Sun Aug 16 14:05:11 2009 +0000
28.12967 +summary:     first change
28.12968 +
28.12969 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qnew first.patch</userinput>
28.12970 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput>
28.12971 +changeset:   1:ba4d7a3f2149
28.12972 +tag:         qtip
28.12973 +tag:         first.patch
28.12974 +tag:         tip
28.12975 +tag:         qbase
28.12976 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
28.12977 +date:        Sun Aug 16 14:05:11 2009 +0000
28.12978 +summary:     [mq]: first.patch
28.12979 +
28.12980 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls .hg/patches</userinput>
28.12981 +first.patch  series  status
28.12982 +</screen>
28.12983 +<!-- END mq.tutorial.qnew -->
28.12984 +
28.12985 +
28.12986 +      <para id="x_3d0">Also newly present in the <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> directory are two
28.12987 +	other files, <filename role="special" moreinfo="none">series</filename> and
28.12988 +	<filename role="special" moreinfo="none">status</filename>.  The <filename role="special" moreinfo="none">series</filename> file lists all of the
28.12989 +	patches that MQ knows about for this repository, with one
28.12990 +	patch per line.  Mercurial uses the <filename role="special" moreinfo="none">status</filename> file for internal
28.12991 +	book-keeping; it tracks all of the patches that MQ has
28.12992 +	<emphasis>applied</emphasis> in this repository.</para>
28.12993 +
28.12994 +      <note>
28.12995 +	<para id="x_3d1">  You may sometimes want to edit the <filename role="special" moreinfo="none">series</filename> file by hand; for
28.12996 +	  example, to change the sequence in which some patches are
28.12997 +	  applied.  However, manually editing the <filename role="special" moreinfo="none">status</filename> file is almost always a
28.12998 +	  bad idea, as it's easy to corrupt MQ's idea of what is
28.12999 +	  happening.</para>
28.13000 +      </note>
28.13001 +
28.13002 +      <para id="x_3d2">Once you have created your new patch, you can edit files
28.13003 +	in the working directory as you usually would.  All of the
28.13004 +	normal Mercurial commands, such as <command role="hg-cmd" moreinfo="none">hg
28.13005 +	  diff</command> and <command role="hg-cmd" moreinfo="none">hg
28.13006 +	  annotate</command>, work exactly as they did before.</para>
28.13007 +    </sect2>
28.13008 +
28.13009 +    <sect2>
28.13010 +      <title>Refreshing a patch</title>
28.13011 +
28.13012 +      <para id="x_3d3">When you reach a point where you want to save your work,
28.13013 +	use the <command role="hg-ext-mq" moreinfo="none">qrefresh</command> command
28.13014 +	to update the patch you are working on.</para>
28.13015 +
28.13016 +      <!-- BEGIN mq.tutorial.qrefresh -->
28.13017 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'line 2' &gt;&gt; file1</userinput>
28.13018 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg diff</userinput>
28.13019 +diff -r ba4d7a3f2149 file1
28.13020 +--- a/file1	Sun Aug 16 14:05:11 2009 +0000
28.13021 ++++ b/file1	Sun Aug 16 14:05:11 2009 +0000
28.13022 +@@ -1,1 +1,2 @@
28.13023 + line 1
28.13024 ++line 2
28.13025 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qrefresh</userinput>
28.13026 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg diff</userinput>
28.13027 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip --style=compact --patch</userinput>
28.13028 +1[qtip,first.patch,tip,qbase]   1aa236e17e55   2009-08-16 14:05 +0000   bos
28.13029 +  [mq]: first.patch
28.13030 +
28.13031 +diff -r 5d84c303994b -r 1aa236e17e55 file1
28.13032 +--- a/file1	Sun Aug 16 14:05:11 2009 +0000
28.13033 ++++ b/file1	Sun Aug 16 14:05:11 2009 +0000
28.13034 +@@ -1,1 +1,2 @@
28.13035 + line 1
28.13036 ++line 2
28.13037 +
28.13038 +</screen>
28.13039 +<!-- END mq.tutorial.qrefresh -->
28.13040 +
28.13041 +
28.13042 +      <para id="x_3d4">This command folds the changes you have made in the
28.13043 +	working directory into your patch, and updates its
28.13044 +	corresponding changeset to contain those changes.</para>
28.13045 +
28.13046 +      <para id="x_3d5">You can run <command role="hg-ext-mq" moreinfo="none">qrefresh</command>
28.13047 +	as often as you like, so it's a good way to
28.13048 +	<quote>checkpoint</quote> your work.  Refresh your patch at an
28.13049 +	opportune time; try an experiment; and if the experiment
28.13050 +	doesn't work out, <command role="hg-cmd" moreinfo="none">hg revert</command>
28.13051 +	your modifications back to the last time you refreshed.</para>
28.13052 +
28.13053 +      <!-- BEGIN mq.tutorial.qrefresh2 -->
28.13054 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'line 3' &gt;&gt; file1</userinput>
28.13055 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput>
28.13056 +M file1
28.13057 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qrefresh</userinput>
28.13058 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip --style=compact --patch</userinput>
28.13059 +1[qtip,first.patch,tip,qbase]   ebec7ce95e11   2009-08-16 14:05 +0000   bos
28.13060 +  [mq]: first.patch
28.13061 +
28.13062 +diff -r 5d84c303994b -r ebec7ce95e11 file1
28.13063 +--- a/file1	Sun Aug 16 14:05:11 2009 +0000
28.13064 ++++ b/file1	Sun Aug 16 14:05:12 2009 +0000
28.13065 +@@ -1,1 +1,3 @@
28.13066 + line 1
28.13067 ++line 2
28.13068 ++line 3
28.13069 +
28.13070 +</screen>
28.13071 +<!-- END mq.tutorial.qrefresh2 -->
28.13072 +
28.13073 +    </sect2>
28.13074 +
28.13075 +    <sect2>
28.13076 +      <title>Stacking and tracking patches</title>
28.13077 +
28.13078 +      <para id="x_3d6">Once you have finished working on a patch, or need to work
28.13079 +	on another, you can use the <command role="hg-ext-mq" moreinfo="none">qnew</command> command again to create a
28.13080 +	new patch. Mercurial will apply this patch on top of your
28.13081 +	existing patch.</para>
28.13082 +
28.13083 +      <!-- BEGIN mq.tutorial.qnew2 -->
28.13084 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qnew second.patch</userinput>
28.13085 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log --style=compact --limit=2</userinput>
28.13086 +2[qtip,second.patch,tip]   dffbc4265523   2009-08-16 14:05 +0000   bos
28.13087 +  [mq]: second.patch
28.13088 +
28.13089 +1[first.patch,qbase]   ebec7ce95e11   2009-08-16 14:05 +0000   bos
28.13090 +  [mq]: first.patch
28.13091 +
28.13092 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'line 4' &gt;&gt; file1</userinput>
28.13093 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qrefresh</userinput>
28.13094 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip --style=compact --patch</userinput>
28.13095 +2[qtip,second.patch,tip]   fdacb9b232ac   2009-08-16 14:05 +0000   bos
28.13096 +  [mq]: second.patch
28.13097 +
28.13098 +diff -r ebec7ce95e11 -r fdacb9b232ac file1
28.13099 +--- a/file1	Sun Aug 16 14:05:12 2009 +0000
28.13100 ++++ b/file1	Sun Aug 16 14:05:12 2009 +0000
28.13101 +@@ -1,3 +1,4 @@
28.13102 + line 1
28.13103 + line 2
28.13104 + line 3
28.13105 ++line 4
28.13106 +
28.13107 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg annotate file1</userinput>
28.13108 +0: line 1
28.13109 +1: line 2
28.13110 +1: line 3
28.13111 +2: line 4
28.13112 +</screen>
28.13113 +<!-- END mq.tutorial.qnew2 -->
28.13114 +
28.13115 +
28.13116 +      <para id="x_3d7">Notice that the patch contains the changes in our prior
28.13117 +	patch as part of its context (you can see this more clearly in
28.13118 +	the output of <command role="hg-cmd" moreinfo="none">hg
28.13119 +	  annotate</command>).</para>
28.13120 +
28.13121 +      <para id="x_3d8">So far, with the exception of <command role="hg-ext-mq" moreinfo="none">qnew</command> and <command role="hg-ext-mq" moreinfo="none">qrefresh</command>, we've been careful to
28.13122 +	only use regular Mercurial commands.  However, MQ provides
28.13123 +	many commands that are easier to use when you are thinking
28.13124 +	about patches, as illustrated below.</para>
28.13125 +
28.13126 +      <!-- BEGIN mq.tutorial.qseries -->
28.13127 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qseries</userinput>
28.13128 +first.patch
28.13129 +second.patch
28.13130 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qapplied</userinput>
28.13131 +first.patch
28.13132 +second.patch
28.13133 +</screen>
28.13134 +<!-- END mq.tutorial.qseries -->
28.13135 +
28.13136 +
28.13137 +      <itemizedlist>
28.13138 +	<listitem><para id="x_3d9">The <command role="hg-ext-mq" moreinfo="none">qseries</command> command lists every
28.13139 +	    patch that MQ knows about in this repository, from oldest
28.13140 +	    to newest (most recently
28.13141 +	    <emphasis>created</emphasis>).</para>
28.13142 +	</listitem>
28.13143 +	<listitem><para id="x_3da">The <command role="hg-ext-mq" moreinfo="none">qapplied</command> command lists every
28.13144 +	    patch that MQ has <emphasis>applied</emphasis> in this
28.13145 +	    repository, again from oldest to newest (most recently
28.13146 +	    applied).</para>
28.13147 +	</listitem></itemizedlist>
28.13148 +    </sect2>
28.13149 +
28.13150 +    <sect2>
28.13151 +      <title>Manipulating the patch stack</title>
28.13152 +
28.13153 +      <para id="x_3db">The previous discussion implied that there must be a
28.13154 +	difference between <quote>known</quote> and
28.13155 +	<quote>applied</quote> patches, and there is.  MQ can manage a
28.13156 +	patch without it being applied in the repository.</para>
28.13157 +
28.13158 +      <para id="x_3dc">An <emphasis>applied</emphasis> patch has a corresponding
28.13159 +	changeset in the repository, and the effects of the patch and
28.13160 +	changeset are visible in the working directory.  You can undo
28.13161 +	the application of a patch using the <command role="hg-ext-mq" moreinfo="none">qpop</command> command.  MQ still
28.13162 +	<emphasis>knows about</emphasis>, or manages, a popped patch,
28.13163 +	but the patch no longer has a corresponding changeset in the
28.13164 +	repository, and the working directory does not contain the
28.13165 +	changes made by the patch.  <xref linkend="fig:mq:stack"/> illustrates
28.13166 +	the difference between applied and tracked patches.</para>
28.13167 +
28.13168 +      <figure id="fig:mq:stack" float="0">
28.13169 +	<title>Applied and unapplied patches in the MQ patch
28.13170 +	  stack</title>
28.13171 +	<mediaobject>
28.13172 +	  <imageobject><imagedata fileref="figs/mq-stack.png"/></imageobject>
28.13173 +	  <textobject><phrase>XXX add text</phrase></textobject>
28.13174 +	</mediaobject>
28.13175 +      </figure>
28.13176 +
28.13177 +      <para id="x_3de">You can reapply an unapplied, or popped, patch using the
28.13178 +	<command role="hg-ext-mq" moreinfo="none">qpush</command> command.  This
28.13179 +	creates a new changeset to correspond to the patch, and the
28.13180 +	patch's changes once again become present in the working
28.13181 +	directory.  See below for examples of <command role="hg-ext-mq" moreinfo="none">qpop</command> and <command role="hg-ext-mq" moreinfo="none">qpush</command> in action.</para>
28.13182 +
28.13183 +      <!-- BEGIN mq.tutorial.qpop -->
28.13184 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qapplied</userinput>
28.13185 +first.patch
28.13186 +second.patch
28.13187 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpop</userinput>
28.13188 +now at: first.patch
28.13189 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qseries</userinput>
28.13190 +first.patch
28.13191 +second.patch
28.13192 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qapplied</userinput>
28.13193 +first.patch
28.13194 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat file1</userinput>
28.13195 +line 1
28.13196 +line 2
28.13197 +line 3
28.13198 +</screen>
28.13199 +<!-- END mq.tutorial.qpop -->
28.13200 +
28.13201 +
28.13202 +      <para id="x_3df">Notice that once we have popped a patch or two patches,
28.13203 +	the output of <command role="hg-ext-mq" moreinfo="none">qseries</command>
28.13204 +	remains the same, while that of <command role="hg-ext-mq" moreinfo="none">qapplied</command> has changed.</para>
28.13205 +
28.13206 +    </sect2>
28.13207 +
28.13208 +    <sect2>
28.13209 +      <title>Pushing and popping many patches</title>
28.13210 +
28.13211 +      <para id="x_3e0">While <command role="hg-ext-mq" moreinfo="none">qpush</command> and
28.13212 +	<command role="hg-ext-mq" moreinfo="none">qpop</command> each operate on a
28.13213 +	single patch at a time by default, you can push and pop many
28.13214 +	patches in one go.  The <option role="hg-ext-mq-cmd-qpush-opt">hg -a</option> option to
28.13215 +	<command role="hg-ext-mq" moreinfo="none">qpush</command> causes it to push
28.13216 +	all unapplied patches, while the <option role="hg-ext-mq-cmd-qpop-opt">-a</option> option to <command role="hg-ext-mq" moreinfo="none">qpop</command> causes it to pop all applied
28.13217 +	patches.  (For some more ways to push and pop many patches,
28.13218 +	see <xref linkend="sec:mq:perf"/> below.)</para>
28.13219 +
28.13220 +      <!-- BEGIN mq.tutorial.qpush-a -->
28.13221 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpush -a</userinput>
28.13222 +applying second.patch
28.13223 +now at: second.patch
28.13224 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat file1</userinput>
28.13225 +line 1
28.13226 +line 2
28.13227 +line 3
28.13228 +line 4
28.13229 +</screen>
28.13230 +<!-- END mq.tutorial.qpush-a -->
28.13231 +
28.13232 +    </sect2>
28.13233 +
28.13234 +    <sect2>
28.13235 +      <title>Safety checks, and overriding them</title>
28.13236 +
28.13237 +      <para id="x_3e1">Several MQ commands check the working directory before
28.13238 +	they do anything, and fail if they find any modifications.
28.13239 +	They do this to ensure that you won't lose any changes that
28.13240 +	you have made, but not yet incorporated into a patch.  The
28.13241 +	example below illustrates this; the <command role="hg-ext-mq" moreinfo="none">qnew</command> command will not create a
28.13242 +	new patch if there are outstanding changes, caused in this
28.13243 +	case by the <command role="hg-cmd" moreinfo="none">hg add</command> of
28.13244 +	<filename moreinfo="none">file3</filename>.</para>
28.13245 +
28.13246 +      <!-- BEGIN mq.tutorial.add -->
28.13247 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'file 3, line 1' &gt;&gt; file3</userinput>
28.13248 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qnew add-file3.patch</userinput>
28.13249 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qnew -f add-file3.patch</userinput>
28.13250 +abort: patch "add-file3.patch" already exists
28.13251 +</screen>
28.13252 +<!-- END mq.tutorial.add -->
28.13253 +
28.13254 +
28.13255 +      <para id="x_3e2">Commands that check the working directory all take an
28.13256 +	<quote>I know what I'm doing</quote> option, which is always
28.13257 +	named <option>-f</option>.  The exact meaning of
28.13258 +	<option>-f</option> depends on the command.  For example,
28.13259 +	<command role="hg-cmd" moreinfo="none">hg qnew <option role="hg-ext-mq-cmd-qnew-opt">hg -f</option></command>
28.13260 +	will incorporate any outstanding changes into the new patch it
28.13261 +	creates, but <command role="hg-cmd" moreinfo="none">hg qpop <option role="hg-ext-mq-cmd-qpop-opt">hg -f</option></command>
28.13262 +	will revert modifications to any files affected by the patch
28.13263 +	that it is popping.  Be sure to read the documentation for a
28.13264 +	command's <option>-f</option> option before you use it!</para>
28.13265 +    </sect2>
28.13266 +
28.13267 +    <sect2>
28.13268 +      <title>Working on several patches at once</title>
28.13269 +
28.13270 +      <para id="x_3e3">The <command role="hg-ext-mq" moreinfo="none">qrefresh</command> command
28.13271 +	always refreshes the <emphasis>topmost</emphasis> applied
28.13272 +	patch.  This means that you can suspend work on one patch (by
28.13273 +	refreshing it), pop or push to make a different patch the top,
28.13274 +	and work on <emphasis>that</emphasis> patch for a
28.13275 +	while.</para>
28.13276 +
28.13277 +      <para id="x_3e4">Here's an example that illustrates how you can use this
28.13278 +	ability. Let's say you're developing a new feature as two
28.13279 +	patches.  The first is a change to the core of your software,
28.13280 +	and the second—layered on top of the
28.13281 +	first—changes the user interface to use the code you
28.13282 +	just added to the core.  If you notice a bug in the core while
28.13283 +	you're working on the UI patch, it's easy to fix the core.
28.13284 +	Simply <command role="hg-ext-mq" moreinfo="none">qrefresh</command> the UI
28.13285 +	patch to save your in-progress changes, and <command role="hg-ext-mq" moreinfo="none">qpop</command> down to the core patch.  Fix
28.13286 +	the core bug, <command role="hg-ext-mq" moreinfo="none">qrefresh</command> the
28.13287 +	core patch, and <command role="hg-ext-mq" moreinfo="none">qpush</command> back
28.13288 +	to the UI patch to continue where you left off.</para>
28.13289 +    </sect2>
28.13290 +  </sect1>
28.13291 +
28.13292 +  <sect1 id="sec:mq:adv-patch">
28.13293 +    <title>More about patches</title>
28.13294 +
28.13295 +    <para id="x_3e5">MQ uses the GNU <command moreinfo="none">patch</command> command to apply
28.13296 +      patches, so it's helpful to know a few more detailed aspects of
28.13297 +      how <command moreinfo="none">patch</command> works, and about patches
28.13298 +      themselves.</para>
28.13299 +
28.13300 +    <sect2>
28.13301 +      <title>The strip count</title>
28.13302 +
28.13303 +      <para id="x_3e6">If you look at the file headers in a patch, you will
28.13304 +	notice that the pathnames usually have an extra component on
28.13305 +	the front that isn't present in the actual path name.  This is
28.13306 +	a holdover from the way that people used to generate patches
28.13307 +	(people still do this, but it's somewhat rare with modern
28.13308 +	revision control tools).</para>
28.13309 +
28.13310 +      <para id="x_3e7">Alice would unpack a tarball, edit her files, then decide
28.13311 +	that she wanted to create a patch.  So she'd rename her
28.13312 +	working directory, unpack the tarball again (hence the need
28.13313 +	for the rename), and use the <option role="cmd-opt-diff">-r</option> and <option role="cmd-opt-diff">-N</option> options to
28.13314 +	<command moreinfo="none">diff</command> to recursively generate a patch
28.13315 +	between the unmodified directory and the modified one.  The
28.13316 +	result would be that the name of the unmodified directory
28.13317 +	would be at the front of the left-hand path in every file
28.13318 +	header, and the name of the modified directory would be at the
28.13319 +	front of the right-hand path.</para>
28.13320 +
28.13321 +      <para id="x_3e8">Since someone receiving a patch from the Alices of the net
28.13322 +	would be unlikely to have unmodified and modified directories
28.13323 +	with exactly the same names, the <command moreinfo="none">patch</command>
28.13324 +	command has a <option role="cmd-opt-patch">-p</option> option
28.13325 +	that indicates the number of leading path name components to
28.13326 +	strip when trying to apply a patch.  This number is called the
28.13327 +	<emphasis>strip count</emphasis>.</para>
28.13328 +
28.13329 +      <para id="x_3e9">An option of <quote><literal moreinfo="none">-p1</literal></quote> means
28.13330 +	<quote>use a strip count of one</quote>.  If
28.13331 +	<command moreinfo="none">patch</command> sees a file name
28.13332 +	<filename moreinfo="none">foo/bar/baz</filename> in a file header, it will
28.13333 +	strip <filename moreinfo="none">foo</filename> and try to patch a file named
28.13334 +	<filename moreinfo="none">bar/baz</filename>.  (Strictly speaking, the strip
28.13335 +	count refers to the number of <emphasis>path
28.13336 +	  separators</emphasis> (and the components that go with them
28.13337 +	) to strip.  A strip count of one will turn
28.13338 +	<filename moreinfo="none">foo/bar</filename> into <filename moreinfo="none">bar</filename>,
28.13339 +	but <filename moreinfo="none">/foo/bar</filename> (notice the extra leading
28.13340 +	slash) into <filename moreinfo="none">foo/bar</filename>.)</para>
28.13341 +
28.13342 +      <para id="x_3ea">The <quote>standard</quote> strip count for patches is
28.13343 +	one; almost all patches contain one leading path name
28.13344 +	component that needs to be stripped. Mercurial's <command role="hg-cmd" moreinfo="none">hg diff</command> command generates path names
28.13345 +	in this form, and the <command role="hg-cmd" moreinfo="none">hg
28.13346 +	  import</command> command and MQ expect patches to have a
28.13347 +	strip count of one.</para>
28.13348 +
28.13349 +      <para id="x_3eb">If you receive a patch from someone that you want to add
28.13350 +	to your patch queue, and the patch needs a strip count other
28.13351 +	than one, you cannot just <command role="hg-ext-mq" moreinfo="none">qimport</command> the patch, because
28.13352 +	<command role="hg-ext-mq" moreinfo="none">qimport</command> does not yet have
28.13353 +	a <literal moreinfo="none">-p</literal> option (see <ulink role="hg-bug" url="http://www.selenic.com/mercurial/bts/issue311">issue
28.13354 +	  311</ulink>).  Your best bet is to <command role="hg-ext-mq" moreinfo="none">qnew</command> a patch of your own, then
28.13355 +	use <command moreinfo="none">patch -pN</command> to apply their patch,
28.13356 +	followed by <command role="hg-cmd" moreinfo="none">hg addremove</command> to
28.13357 +	pick up any files added or removed by the patch, followed by
28.13358 +	<command role="hg-ext-mq" moreinfo="none">hg qrefresh</command>. This
28.13359 +	complexity may become unnecessary; see <ulink role="hg-bug" url="http://www.selenic.com/mercurial/bts/issue311">issue
28.13360 +	  311</ulink> for details.
28.13361 +      </para>
28.13362 +    </sect2>
28.13363 +
28.13364 +    <sect2>
28.13365 +      <title>Strategies for applying a patch</title>
28.13366 +
28.13367 +      <para id="x_3ec">When <command moreinfo="none">patch</command> applies a hunk, it tries a
28.13368 +	handful of successively less accurate strategies to try to
28.13369 +	make the hunk apply. This falling-back technique often makes
28.13370 +	it possible to take a patch that was generated against an old
28.13371 +	version of a file, and apply it against a newer version of
28.13372 +	that file.</para>
28.13373 +
28.13374 +      <para id="x_3ed">First, <command moreinfo="none">patch</command> tries an exact match,
28.13375 +	where the line numbers, the context, and the text to be
28.13376 +	modified must apply exactly.  If it cannot make an exact
28.13377 +	match, it tries to find an exact match for the context,
28.13378 +	without honouring the line numbering information.  If this
28.13379 +	succeeds, it prints a line of output saying that the hunk was
28.13380 +	applied, but at some <emphasis>offset</emphasis> from the
28.13381 +	original line number.</para>
28.13382 +
28.13383 +      <para id="x_3ee">If a context-only match fails, <command moreinfo="none">patch</command>
28.13384 +	removes the first and last lines of the context, and tries a
28.13385 +	<emphasis>reduced</emphasis> context-only match.  If the hunk
28.13386 +	with reduced context succeeds, it prints a message saying that
28.13387 +	it applied the hunk with a <emphasis>fuzz factor</emphasis>
28.13388 +	(the number after the fuzz factor indicates how many lines of
28.13389 +	context <command moreinfo="none">patch</command> had to trim before the patch
28.13390 +	applied).</para>
28.13391 +
28.13392 +      <para id="x_3ef">When neither of these techniques works,
28.13393 +	<command moreinfo="none">patch</command> prints a message saying that the hunk
28.13394 +	in question was rejected.  It saves rejected hunks (also
28.13395 +	simply called <quote>rejects</quote>) to a file with the same
28.13396 +	name, and an added <filename role="special" moreinfo="none">.rej</filename>
28.13397 +	extension.  It also saves an unmodified copy of the file with
28.13398 +	a <filename role="special" moreinfo="none">.orig</filename> extension; the
28.13399 +	copy of the file without any extensions will contain any
28.13400 +	changes made by hunks that <emphasis>did</emphasis> apply
28.13401 +	cleanly.  If you have a patch that modifies
28.13402 +	<filename moreinfo="none">foo</filename> with six hunks, and one of them fails
28.13403 +	to apply, you will have: an unmodified
28.13404 +	<filename moreinfo="none">foo.orig</filename>, a <filename moreinfo="none">foo.rej</filename>
28.13405 +	containing one hunk, and <filename moreinfo="none">foo</filename>, containing
28.13406 +	the changes made by the five successful hunks.</para>
28.13407 +    </sect2>
28.13408 +
28.13409 +    <sect2>
28.13410 +      <title>Some quirks of patch representation</title>
28.13411 +
28.13412 +      <para id="x_3f0">There are a few useful things to know about how
28.13413 +	<command moreinfo="none">patch</command> works with files.</para>
28.13414 +      <itemizedlist>
28.13415 +	<listitem><para id="x_3f1">This should already be obvious, but
28.13416 +	    <command moreinfo="none">patch</command> cannot handle binary
28.13417 +	    files.</para>
28.13418 +	</listitem>
28.13419 +	<listitem><para id="x_3f2">Neither does it care about the executable bit;
28.13420 +	    it creates new files as readable, but not
28.13421 +	    executable.</para>
28.13422 +	</listitem>
28.13423 +	<listitem><para id="x_3f3"><command moreinfo="none">patch</command> treats the removal of
28.13424 +	    a file as a diff between the file to be removed and the
28.13425 +	    empty file.  So your idea of <quote>I deleted this
28.13426 +	      file</quote> looks like <quote>every line of this file
28.13427 +	      was deleted</quote> in a patch.</para>
28.13428 +	</listitem>
28.13429 +	<listitem><para id="x_3f4">It treats the addition of a file as a diff
28.13430 +	    between the empty file and the file to be added.  So in a
28.13431 +	    patch, your idea of <quote>I added this file</quote> looks
28.13432 +	    like <quote>every line of this file was
28.13433 +	      added</quote>.</para>
28.13434 +	</listitem>
28.13435 +	<listitem><para id="x_3f5">It treats a renamed file as the removal of the
28.13436 +	    old name, and the addition of the new name.  This means
28.13437 +	    that renamed files have a big footprint in patches.  (Note
28.13438 +	    also that Mercurial does not currently try to infer when
28.13439 +	    files have been renamed or copied in a patch.)</para>
28.13440 +	</listitem>
28.13441 +	<listitem><para id="x_3f6"><command moreinfo="none">patch</command> cannot represent
28.13442 +	    empty files, so you cannot use a patch to represent the
28.13443 +	    notion <quote>I added this empty file to the
28.13444 +	      tree</quote>.</para>
28.13445 +	</listitem></itemizedlist>
28.13446 +    </sect2>
28.13447 +
28.13448 +    <sect2>
28.13449 +      <title>Beware the fuzz</title>
28.13450 +
28.13451 +      <para id="x_3f7">While applying a hunk at an offset, or with a fuzz factor,
28.13452 +	will often be completely successful, these inexact techniques
28.13453 +	naturally leave open the possibility of corrupting the patched
28.13454 +	file.  The most common cases typically involve applying a
28.13455 +	patch twice, or at an incorrect location in the file.  If
28.13456 +	<command moreinfo="none">patch</command> or <command role="hg-ext-mq" moreinfo="none">qpush</command> ever mentions an offset or
28.13457 +	fuzz factor, you should make sure that the modified files are
28.13458 +	correct afterwards.</para>
28.13459 +
28.13460 +      <para id="x_3f8">It's often a good idea to refresh a patch that has applied
28.13461 +	with an offset or fuzz factor; refreshing the patch generates
28.13462 +	new context information that will make it apply cleanly.  I
28.13463 +	say <quote>often,</quote> not <quote>always,</quote> because
28.13464 +	sometimes refreshing a patch will make it fail to apply
28.13465 +	against a different revision of the underlying files.  In some
28.13466 +	cases, such as when you're maintaining a patch that must sit
28.13467 +	on top of multiple versions of a source tree, it's acceptable
28.13468 +	to have a patch apply with some fuzz, provided you've verified
28.13469 +	the results of the patching process in such cases.</para>
28.13470 +    </sect2>
28.13471 +
28.13472 +    <sect2>
28.13473 +      <title>Handling rejection</title>
28.13474 +
28.13475 +      <para id="x_3f9">If <command role="hg-ext-mq" moreinfo="none">qpush</command> fails to
28.13476 +	apply a patch, it will print an error message and exit.  If it
28.13477 +	has left <filename role="special" moreinfo="none">.rej</filename> files
28.13478 +	behind, it is usually best to fix up the rejected hunks before
28.13479 +	you push more patches or do any further work.</para>
28.13480 +
28.13481 +      <para id="x_3fa">If your patch <emphasis>used to</emphasis> apply cleanly,
28.13482 +	and no longer does because you've changed the underlying code
28.13483 +	that your patches are based on, Mercurial Queues can help; see
28.13484 +	<xref linkend="sec:mq:merge"/> for details.</para>
28.13485 +
28.13486 +      <para id="x_3fb">Unfortunately, there aren't any great techniques for
28.13487 +	dealing with rejected hunks.  Most often, you'll need to view
28.13488 +	the <filename role="special" moreinfo="none">.rej</filename> file and edit the
28.13489 +	target file, applying the rejected hunks by hand.</para>
28.13490 +
28.13491 +      <para id="x_3fd">A Linux kernel hacker, Chris Mason (the author
28.13492 +	of Mercurial Queues), wrote a tool called
28.13493 +	<command moreinfo="none">mpatch</command> (<ulink url="http://oss.oracle.com/~mason/mpatch/">http://oss.oracle.com/~mason/mpatch/</ulink>), 
28.13494 +	which takes a simple approach to automating the application of
28.13495 +	hunks rejected by <command moreinfo="none">patch</command>.  The
28.13496 +	<command moreinfo="none">mpatch</command> command can help with four common
28.13497 +	reasons that a hunk may be rejected:</para>
28.13498 +
28.13499 +      <itemizedlist>
28.13500 +	<listitem><para id="x_3fe">The context in the middle of a hunk has
28.13501 +	    changed.</para>
28.13502 +	</listitem>
28.13503 +	<listitem><para id="x_3ff">A hunk is missing some context at the
28.13504 +	    beginning or end.</para>
28.13505 +	</listitem>
28.13506 +	<listitem><para id="x_400">A large hunk might apply better—either
28.13507 +	    entirely or in part—if it was broken up into
28.13508 +	    smaller hunks.</para>
28.13509 +	</listitem>
28.13510 +	<listitem><para id="x_401">A hunk removes lines with slightly different
28.13511 +	    content than those currently present in the file.</para>
28.13512 +	</listitem></itemizedlist>
28.13513 +
28.13514 +      <para id="x_402">If you use <command moreinfo="none">mpatch</command>, you
28.13515 +	should be doubly careful to check your results when you're
28.13516 +	done.  In fact, <command moreinfo="none">mpatch</command> enforces this method
28.13517 +	of double-checking the tool's output, by automatically
28.13518 +	dropping you into a merge program when it has done its job, so
28.13519 +	that you can verify its work and finish off any remaining
28.13520 +	merges.</para>
28.13521 +    </sect2>
28.13522 +  </sect1>
28.13523 +
28.13524 +  <sect1>
28.13525 +    <title>More on patch management</title>
28.13526 +
28.13527 +    <para id="x_6db">As you grow familiar with MQ, you will find yourself wanting
28.13528 +      to perform other kinds of patch management operations.</para>
28.13529 +
28.13530 +    <sect2>
28.13531 +      <title>Deleting unwanted patches</title>
28.13532 +
28.13533 +      <para id="x_6dc">If you want to get rid of a patch, use the <command role="hg-ext-mq" moreinfo="none">hg qdelete</command> command to delete the
28.13534 +	patch file and remove its entry from the patch series.  If you
28.13535 +	try to delete a patch that is still applied, <command role="hg-ext-mq" moreinfo="none">hg qdelete</command> will refuse.</para>
28.13536 +
28.13537 +      <!-- BEGIN ch11/qdelete.go -->
28.13538 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init myrepo</userinput>
28.13539 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd myrepo</userinput>
28.13540 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qinit</userinput>
28.13541 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qnew bad.patch</userinput>
28.13542 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a &gt; a</userinput>
28.13543 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add a</userinput>
28.13544 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qrefresh</userinput>
28.13545 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qdelete bad.patch</userinput>
28.13546 +abort: cannot delete applied patch bad.patch
28.13547 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpop</userinput>
28.13548 +patch queue now empty
28.13549 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qdelete bad.patch</userinput>
28.13550 +</screen>
28.13551 +<!-- END ch11/qdelete.go -->
28.13552 +
28.13553 +    </sect2>
28.13554 +
28.13555 +    <sect2>
28.13556 +      <title>Converting to and from permanent revisions</title>
28.13557 +
28.13558 +      <para id="x_6dd">Once you're done working on a patch and want to
28.13559 +      turn it into a permanent changeset, use the <command role="hg-ext-mq" moreinfo="none">hg qfinish</command> command. Pass a revision
28.13560 +      to the command to identify the patch that you want to turn into
28.13561 +      a regular changeset; this patch must already be applied.</para>
28.13562 +
28.13563 +      <!-- BEGIN ch11/qdelete.convert -->
28.13564 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qnew good.patch</userinput>
28.13565 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a &gt; a</userinput>
28.13566 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add a</userinput>
28.13567 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qrefresh -m 'Good change'</userinput>
28.13568 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qfinish tip</userinput>
28.13569 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qapplied</userinput>
28.13570 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip --style=compact</userinput>
28.13571 +0[tip]   32fc5ce6b092   2009-08-16 14:04 +0000   bos
28.13572 +  Good change
28.13573 +
28.13574 +</screen>
28.13575 +<!-- END ch11/qdelete.convert -->
28.13576 +
28.13577 +
28.13578 +      <para id="x_6e0">The <command role="hg-ext-mq" moreinfo="none">hg qfinish</command> command
28.13579 +        accepts an <option>--all</option> or <option>-a</option>
28.13580 +        option, which turns all applied patches into regular
28.13581 +        changesets.</para>
28.13582 +
28.13583 +      <para id="x_6de">It is also possible to turn an existing changeset into a
28.13584 +	patch, by passing the <option>-r</option> option to <command role="hg-ext-mq" moreinfo="none">hg qimport</command>.</para>
28.13585 +
28.13586 +      <!-- BEGIN ch11/qdelete.import -->
28.13587 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qimport -r tip</userinput>
28.13588 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qapplied</userinput>
28.13589 +0.diff
28.13590 +</screen>
28.13591 +<!-- END ch11/qdelete.import -->
28.13592 +
28.13593 +
28.13594 +      <para id="x_6df">Note that it only makes sense to convert a changeset into
28.13595 +	a patch if you have not propagated that changeset into any
28.13596 +	other repositories.  The imported changeset's ID will change
28.13597 +	every time you refresh the patch, which will make Mercurial
28.13598 +	treat it as unrelated to the original changeset if you have
28.13599 +	pushed it somewhere else.</para>
28.13600 +    </sect2>
28.13601 +  </sect1>
28.13602 +
28.13603 +  <sect1 id="sec:mq:perf">
28.13604 +    <title>Getting the best performance out of MQ</title>
28.13605 +
28.13606 +    <para id="x_403">MQ is very efficient at handling a large number
28.13607 +      of patches. I ran some performance experiments in mid-2006 for a
28.13608 +      talk that I gave at the 2006 EuroPython conference (on modern
28.13609 +      hardware, you should expect better performance than you'll see
28.13610 +      below).  I used as my data set the Linux 2.6.17-mm1 patch
28.13611 +      series, which consists of 1,738 patches. I applied these on top
28.13612 +      of a Linux kernel repository containing all 27,472 revisions
28.13613 +      between Linux 2.6.12-rc2 and Linux 2.6.17.</para>
28.13614 +
28.13615 +    <para id="x_404">On my old, slow laptop, I was able to <command role="hg-cmd" moreinfo="none">hg qpush <option role="hg-ext-mq-cmd-qpush-opt">hg -a</option></command> all
28.13616 +      1,738 patches in 3.5 minutes, and <command role="hg-cmd" moreinfo="none">hg qpop
28.13617 +	<option role="hg-ext-mq-cmd-qpop-opt">hg -a</option></command>
28.13618 +      them all in 30 seconds.  (On a newer laptop, the time to push
28.13619 +      all patches dropped to two minutes.)  I could <command role="hg-ext-mq" moreinfo="none">qrefresh</command> one of the biggest patches
28.13620 +      (which made 22,779 lines of changes to 287 files) in 6.6
28.13621 +      seconds.</para>
28.13622 +
28.13623 +    <para id="x_405">Clearly, MQ is well suited to working in large trees, but
28.13624 +      there are a few tricks you can use to get the best performance
28.13625 +      of it.</para>
28.13626 +
28.13627 +    <para id="x_406">First of all, try to <quote>batch</quote> operations
28.13628 +      together.  Every time you run <command role="hg-ext-mq" moreinfo="none">qpush</command> or <command role="hg-ext-mq" moreinfo="none">qpop</command>, these commands scan the
28.13629 +      working directory once to make sure you haven't made some
28.13630 +      changes and then forgotten to run <command role="hg-ext-mq" moreinfo="none">qrefresh</command>.  On a small tree, the
28.13631 +      time that this scan takes is unnoticeable.  However, on a
28.13632 +      medium-sized tree (containing tens of thousands of files), it
28.13633 +      can take a second or more.</para>
28.13634 +
28.13635 +    <para id="x_407">The <command role="hg-ext-mq" moreinfo="none">qpush</command> and <command role="hg-ext-mq" moreinfo="none">qpop</command> commands allow you to push and
28.13636 +      pop multiple patches at a time.  You can identify the
28.13637 +      <quote>destination patch</quote> that you want to end up at.
28.13638 +      When you <command role="hg-ext-mq" moreinfo="none">qpush</command> with a
28.13639 +      destination specified, it will push patches until that patch is
28.13640 +      at the top of the applied stack.  When you <command role="hg-ext-mq" moreinfo="none">qpop</command> to a destination, MQ will pop
28.13641 +      patches until the destination patch is at the top.</para>
28.13642 +
28.13643 +    <para id="x_408">You can identify a destination patch using either the name
28.13644 +      of the patch, or by number.  If you use numeric addressing,
28.13645 +      patches are counted from zero; this means that the first patch
28.13646 +      is zero, the second is one, and so on.</para>
28.13647 +  </sect1>
28.13648 +
28.13649 +  <sect1 id="sec:mq:merge">
28.13650 +    <title>Updating your patches when the underlying code
28.13651 +      changes</title>
28.13652 +
28.13653 +    <para id="x_409">It's common to have a stack of patches on top of an
28.13654 +      underlying repository that you don't modify directly.  If you're
28.13655 +      working on changes to third-party code, or on a feature that is
28.13656 +      taking longer to develop than the rate of change of the code
28.13657 +      beneath, you will often need to sync up with the underlying
28.13658 +      code, and fix up any hunks in your patches that no longer apply.
28.13659 +      This is called <emphasis>rebasing</emphasis> your patch
28.13660 +      series.</para>
28.13661 +
28.13662 +    <para id="x_40a">The simplest way to do this is to <command role="hg-cmd" moreinfo="none">hg
28.13663 +	qpop <option role="hg-ext-mq-cmd-qpop-opt">hg
28.13664 +	  -a</option></command> your patches, then <command role="hg-cmd" moreinfo="none">hg pull</command> changes into the underlying
28.13665 +      repository, and finally <command role="hg-cmd" moreinfo="none">hg qpush <option role="hg-ext-mq-cmd-qpop-opt">hg -a</option></command> your
28.13666 +      patches again.  MQ will stop pushing any time it runs across a
28.13667 +      patch that fails to apply during conflicts, allowing you to fix
28.13668 +      your conflicts, <command role="hg-ext-mq" moreinfo="none">qrefresh</command> the
28.13669 +      affected patch, and continue pushing until you have fixed your
28.13670 +      entire stack.</para>
28.13671 +
28.13672 +    <para id="x_40b">This approach is easy to use and works well if you don't
28.13673 +      expect changes to the underlying code to affect how well your
28.13674 +      patches apply. If your patch stack touches code that is modified
28.13675 +      frequently or invasively in the underlying repository, however,
28.13676 +      fixing up rejected hunks by hand quickly becomes
28.13677 +      tiresome.</para>
28.13678 +
28.13679 +    <para id="x_40c">It's possible to partially automate the rebasing process.
28.13680 +      If your patches apply cleanly against some revision of the
28.13681 +      underlying repo, MQ can use this information to help you to
28.13682 +      resolve conflicts between your patches and a different
28.13683 +      revision.</para>
28.13684 +
28.13685 +    <para id="x_40d">The process is a little involved.</para>
28.13686 +    <orderedlist inheritnum="ignore" continuation="restarts">
28.13687 +      <listitem><para id="x_40e">To begin, <command role="hg-cmd" moreinfo="none">hg qpush
28.13688 +	    -a</command> all of your patches on top of the revision
28.13689 +	  where you know that they apply cleanly.</para>
28.13690 +      </listitem>
28.13691 +      <listitem><para id="x_40f">Save a backup copy of your patch directory using
28.13692 +	  <command role="hg-cmd" moreinfo="none">hg qsave <option role="hg-ext-mq-cmd-qsave-opt">hg -e</option> <option role="hg-ext-mq-cmd-qsave-opt">hg -c</option></command>.
28.13693 +	  This prints the name of the directory that it has saved the
28.13694 +	  patches in.  It will save the patches to a directory called
28.13695 +	  <filename role="special" class="directory" moreinfo="none">.hg/patches.N</filename>, where
28.13696 +	  <literal moreinfo="none">N</literal> is a small integer.  It also commits a
28.13697 +	  <quote>save changeset</quote> on top of your applied
28.13698 +	  patches; this is for internal book-keeping, and records the
28.13699 +	  states of the <filename role="special" moreinfo="none">series</filename> and
28.13700 +	  <filename role="special" moreinfo="none">status</filename> files.</para>
28.13701 +      </listitem>
28.13702 +      <listitem><para id="x_410">Use <command role="hg-cmd" moreinfo="none">hg pull</command> to
28.13703 +	  bring new changes into the underlying repository.  (Don't
28.13704 +	  run <command role="hg-cmd" moreinfo="none">hg pull -u</command>; see below
28.13705 +	  for why.)</para>
28.13706 +      </listitem>
28.13707 +      <listitem><para id="x_411">Update to the new tip revision, using <command role="hg-cmd" moreinfo="none">hg update <option role="hg-opt-update">-C</option></command> to override
28.13708 +	  the patches you have pushed.</para>
28.13709 +      </listitem>
28.13710 +      <listitem><para id="x_412">Merge all patches using <command moreinfo="none">hg qpush -m
28.13711 +	    -a</command>.  The <option role="hg-ext-mq-cmd-qpush-opt">-m</option> option to
28.13712 +	  <command role="hg-ext-mq" moreinfo="none">qpush</command> tells MQ to
28.13713 +	  perform a three-way merge if the patch fails to
28.13714 +	  apply.</para>
28.13715 +      </listitem></orderedlist>
28.13716 +
28.13717 +    <para id="x_413">During the <command role="hg-cmd" moreinfo="none">hg qpush <option role="hg-ext-mq-cmd-qpush-opt">hg -m</option></command>,
28.13718 +      each patch in the <filename role="special" moreinfo="none">series</filename>
28.13719 +      file is applied normally.  If a patch applies with fuzz or
28.13720 +      rejects, MQ looks at the queue you <command role="hg-ext-mq" moreinfo="none">qsave</command>d, and performs a three-way
28.13721 +      merge with the corresponding changeset.  This merge uses
28.13722 +      Mercurial's normal merge machinery, so it may pop up a GUI merge
28.13723 +      tool to help you to resolve problems.</para>
28.13724 +
28.13725 +    <para id="x_414">When you finish resolving the effects of a patch, MQ
28.13726 +      refreshes your patch based on the result of the merge.</para>
28.13727 +
28.13728 +    <para id="x_415">At the end of this process, your repository will have one
28.13729 +      extra head from the old patch queue, and a copy of the old patch
28.13730 +      queue will be in <filename role="special" class="directory" moreinfo="none">.hg/patches.N</filename>. You can remove the
28.13731 +      extra head using <command role="hg-cmd" moreinfo="none">hg qpop -a -n
28.13732 +	patches.N</command> or <command role="hg-cmd" moreinfo="none">hg
28.13733 +	strip</command>.  You can delete <filename role="special" class="directory" moreinfo="none">.hg/patches.N</filename> once you are sure
28.13734 +      that you no longer need it as a backup.</para>
28.13735 +  </sect1>
28.13736 +
28.13737 +  <sect1>
28.13738 +    <title>Identifying patches</title>
28.13739 +
28.13740 +    <para id="x_416">MQ commands that work with patches let you refer to a patch
28.13741 +      either by using its name or by a number.  By name is obvious
28.13742 +      enough; pass the name <filename moreinfo="none">foo.patch</filename> to <command role="hg-ext-mq" moreinfo="none">qpush</command>, for example, and it will
28.13743 +      push patches until <filename moreinfo="none">foo.patch</filename> is
28.13744 +      applied.</para>
28.13745 +
28.13746 +    <para id="x_417">As a shortcut, you can refer to a patch using both a name
28.13747 +      and a numeric offset; <literal moreinfo="none">foo.patch-2</literal> means
28.13748 +      <quote>two patches before <literal moreinfo="none">foo.patch</literal></quote>,
28.13749 +      while <literal moreinfo="none">bar.patch+4</literal> means <quote>four patches
28.13750 +	after <literal moreinfo="none">bar.patch</literal></quote>.</para>
28.13751 +
28.13752 +    <para id="x_418">Referring to a patch by index isn't much different.  The
28.13753 +      first patch printed in the output of <command role="hg-ext-mq" moreinfo="none">qseries</command> is patch zero (yes, it's
28.13754 +      one of those start-at-zero counting systems); the second is
28.13755 +      patch one; and so on.</para>
28.13756 +
28.13757 +    <para id="x_419">MQ also makes it easy to work with patches when you are
28.13758 +      using normal Mercurial commands.  Every command that accepts a
28.13759 +      changeset ID will also accept the name of an applied patch.  MQ
28.13760 +      augments the tags normally in the repository with an eponymous
28.13761 +      one for each applied patch.  In addition, the special tags
28.13762 +      <literal role="tag" moreinfo="none">qbase</literal> and
28.13763 +      <literal role="tag" moreinfo="none">qtip</literal> identify
28.13764 +      the <quote>bottom-most</quote> and topmost applied patches,
28.13765 +      respectively.</para>
28.13766 +
28.13767 +    <para id="x_41a">These additions to Mercurial's normal tagging capabilities
28.13768 +      make dealing with patches even more of a breeze.</para>
28.13769 +    <itemizedlist>
28.13770 +      <listitem><para id="x_41b">Want to patchbomb a mailing list with your
28.13771 +	  latest series of changes?</para>
28.13772 +	<programlisting format="linespecific">hg email qbase:qtip</programlisting>
28.13773 +	<para id="x_41c">  (Don't know what <quote>patchbombing</quote> is?  See
28.13774 +	  <xref linkend="sec:hgext:patchbomb"/>.)</para>
28.13775 +      </listitem>
28.13776 +      <listitem><para id="x_41d">Need to see all of the patches since
28.13777 +	  <literal moreinfo="none">foo.patch</literal> that have touched files in a
28.13778 +	  subdirectory of your tree?</para>
28.13779 +	<programlisting format="linespecific">hg log -r foo.patch:qtip subdir</programlisting>
28.13780 +      </listitem>
28.13781 +    </itemizedlist>
28.13782 +
28.13783 +    <para id="x_41e">Because MQ makes the names of patches available to the rest
28.13784 +      of Mercurial through its normal internal tag machinery, you
28.13785 +      don't need to type in the entire name of a patch when you want
28.13786 +      to identify it by name.</para>
28.13787 +
28.13788 +    <para id="x_41f">Another nice consequence of representing patch names as tags
28.13789 +      is that when you run the <command role="hg-cmd" moreinfo="none">hg log</command>
28.13790 +      command, it will display a patch's name as a tag, simply as part
28.13791 +      of its normal output.  This makes it easy to visually
28.13792 +      distinguish applied patches from underlying
28.13793 +      <quote>normal</quote> revisions.  The following example shows a
28.13794 +      few normal Mercurial commands in use with applied
28.13795 +      patches.</para>
28.13796 +
28.13797 +    <!-- BEGIN mq.id.output -->
28.13798 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qapplied</userinput>
28.13799 +first.patch
28.13800 +second.patch
28.13801 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r qbase:qtip</userinput>
28.13802 +changeset:   1:c3bcf3b7335a
28.13803 +tag:         first.patch
28.13804 +tag:         qbase
28.13805 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
28.13806 +date:        Sun Aug 16 14:05:08 2009 +0000
28.13807 +summary:     [mq]: first.patch
28.13808 +
28.13809 +changeset:   2:d189ba63b5f7
28.13810 +tag:         qtip
28.13811 +tag:         second.patch
28.13812 +tag:         tip
28.13813 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
28.13814 +date:        Sun Aug 16 14:05:09 2009 +0000
28.13815 +summary:     [mq]: second.patch
28.13816 +
28.13817 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg export second.patch</userinput>
28.13818 +# HG changeset patch
28.13819 +# User Bryan O'Sullivan &lt;bos@serpentine.com&gt;
28.13820 +# Date 1250431509 0
28.13821 +# Node ID d189ba63b5f7427f9644663c01fc16fe80399c65
28.13822 +# Parent  c3bcf3b7335afc0a250e85c51a1266d35d43a545
28.13823 +[mq]: second.patch
28.13824 +
28.13825 +diff -r c3bcf3b7335a -r d189ba63b5f7 other.c
28.13826 +--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
28.13827 ++++ b/other.c	Sun Aug 16 14:05:09 2009 +0000
28.13828 +@@ -0,0 +1,1 @@
28.13829 ++double u;
28.13830 +</screen>
28.13831 +<!-- END mq.id.output -->
28.13832 +
28.13833 +  </sect1>
28.13834 +
28.13835 +  <sect1>
28.13836 +    <title>Useful things to know about</title>
28.13837 +
28.13838 +    <para id="x_420">There are a number of aspects of MQ usage that don't fit
28.13839 +      tidily into sections of their own, but that are good to know.
28.13840 +      Here they are, in one place.</para>
28.13841 +
28.13842 +    <itemizedlist>
28.13843 +      <listitem><para id="x_421">Normally, when you <command role="hg-ext-mq" moreinfo="none">qpop</command> a patch and <command role="hg-ext-mq" moreinfo="none">qpush</command> it again, the changeset
28.13844 +	  that represents the patch after the pop/push will have a
28.13845 +	  <emphasis>different identity</emphasis> than the changeset
28.13846 +	  that represented the hash beforehand.  See <xref linkend="sec:mqref:cmd:qpush"/> for
28.13847 +	  information as to why this is.</para>
28.13848 +      </listitem>
28.13849 +      <listitem><para id="x_422">It's not a good idea to <command role="hg-cmd" moreinfo="none">hg merge</command> changes from another
28.13850 +	  branch with a patch changeset, at least if you want to
28.13851 +	  maintain the <quote>patchiness</quote> of that changeset and
28.13852 +	  changesets below it on the patch stack.  If you try to do
28.13853 +	  this, it will appear to succeed, but MQ will become
28.13854 +	  confused.</para>
28.13855 +      </listitem></itemizedlist>
28.13856 +  </sect1>
28.13857 +
28.13858 +  <sect1 id="sec:mq:repo">
28.13859 +    <title>Managing patches in a repository</title>
28.13860 +
28.13861 +    <para id="x_423">Because MQ's <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> directory resides
28.13862 +      outside a Mercurial repository's working directory, the
28.13863 +      <quote>underlying</quote> Mercurial repository knows nothing
28.13864 +      about the management or presence of patches.</para>
28.13865 +
28.13866 +    <para id="x_424">This presents the interesting possibility of managing the
28.13867 +      contents of the patch directory as a Mercurial repository in its
28.13868 +      own right.  This can be a useful way to work.  For example, you
28.13869 +      can work on a patch for a while, <command role="hg-ext-mq" moreinfo="none">qrefresh</command> it, then <command role="hg-cmd" moreinfo="none">hg commit</command> the current state of the
28.13870 +      patch.  This lets you <quote>roll back</quote> to that version
28.13871 +      of the patch later on.</para>
28.13872 +
28.13873 +    <para id="x_425">You can then share different versions of the same patch
28.13874 +      stack among multiple underlying repositories.  I use this when I
28.13875 +      am developing a Linux kernel feature.  I have a pristine copy of
28.13876 +      my kernel sources for each of several CPU architectures, and a
28.13877 +      cloned repository under each that contains the patches I am
28.13878 +      working on.  When I want to test a change on a different
28.13879 +      architecture, I push my current patches to the patch repository
28.13880 +      associated with that kernel tree, pop and push all of my
28.13881 +      patches, and build and test that kernel.</para>
28.13882 +
28.13883 +    <para id="x_426">Managing patches in a repository makes it possible for
28.13884 +      multiple developers to work on the same patch series without
28.13885 +      colliding with each other, all on top of an underlying source
28.13886 +      base that they may or may not control.</para>
28.13887 +
28.13888 +    <sect2>
28.13889 +      <title>MQ support for patch repositories</title>
28.13890 +
28.13891 +      <para id="x_427">MQ helps you to work with the <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> directory as a
28.13892 +	repository; when you prepare a repository for working with
28.13893 +	patches using <command role="hg-ext-mq" moreinfo="none">qinit</command>, you
28.13894 +	can pass the <option role="hg-ext-mq-cmd-qinit-opt">hg
28.13895 +	  -c</option> option to create the <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> directory as a
28.13896 +	Mercurial repository.</para>
28.13897 +
28.13898 +      <note>
28.13899 +	<para id="x_428">  If you forget to use the <option role="hg-ext-mq-cmd-qinit-opt">hg -c</option> option, you
28.13900 +	  can simply go into the <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> directory at any
28.13901 +	  time and run <command role="hg-cmd" moreinfo="none">hg init</command>.
28.13902 +	  Don't forget to add an entry for the <filename role="special" moreinfo="none">status</filename> file to the <filename role="special" moreinfo="none">.hgignore</filename> file, though</para>
28.13903 +
28.13904 +	<para id="x_429">  (<command role="hg-cmd" moreinfo="none">hg qinit <option role="hg-ext-mq-cmd-qinit-opt">hg -c</option></command>
28.13905 +	  does this for you automatically); you
28.13906 +	  <emphasis>really</emphasis> don't want to manage the
28.13907 +	  <filename role="special" moreinfo="none">status</filename> file.</para>
28.13908 +      </note>
28.13909 +
28.13910 +      <para id="x_42a">As a convenience, if MQ notices that the <filename class="directory" moreinfo="none">.hg/patches</filename> directory is a
28.13911 +	repository, it will automatically <command role="hg-cmd" moreinfo="none">hg
28.13912 +	  add</command> every patch that you create and import.</para>
28.13913 +
28.13914 +      <para id="x_42b">MQ provides a shortcut command, <command role="hg-ext-mq" moreinfo="none">qcommit</command>, that runs <command role="hg-cmd" moreinfo="none">hg commit</command> in the <filename role="special" class="directory" moreinfo="none">.hg/patches</filename>
28.13915 +	directory.  This saves some bothersome typing.</para>
28.13916 +
28.13917 +      <para id="x_42c">Finally, as a convenience to manage the patch directory,
28.13918 +	you can define the alias <command moreinfo="none">mq</command> on Unix
28.13919 +	systems. For example, on Linux systems using the
28.13920 +	<command moreinfo="none">bash</command> shell, you can include the following
28.13921 +	snippet in your <filename role="home" moreinfo="none">~/.bashrc</filename>.</para>
28.13922 +
28.13923 +      <programlisting format="linespecific">alias mq=`hg -R $(hg root)/.hg/patches'</programlisting>
28.13924 +
28.13925 +      <para id="x_42d">You can then issue commands of the form <command moreinfo="none">mq
28.13926 +	  pull</command> from the main repository.</para>
28.13927 +    </sect2>
28.13928 +
28.13929 +    <sect2>
28.13930 +      <title>A few things to watch out for</title>
28.13931 +
28.13932 +      <para id="x_42e">MQ's support for working with a repository full of patches
28.13933 +	is limited in a few small respects.</para>
28.13934 +
28.13935 +      <para id="x_42f">MQ cannot automatically detect changes that you make to
28.13936 +	the patch directory.  If you <command role="hg-cmd" moreinfo="none">hg
28.13937 +	  pull</command>, manually edit, or <command role="hg-cmd" moreinfo="none">hg
28.13938 +	  update</command> changes to patches or the <filename role="special" moreinfo="none">series</filename> file, you will have to
28.13939 +	<command role="hg-cmd" moreinfo="none">hg qpop <option role="hg-ext-mq-cmd-qpop-opt">hg -a</option></command> and
28.13940 +	then <command role="hg-cmd" moreinfo="none">hg qpush <option role="hg-ext-mq-cmd-qpush-opt">hg -a</option></command> in
28.13941 +	the underlying repository to see those changes show up there.
28.13942 +	If you forget to do this, you can confuse MQ's idea of which
28.13943 +	patches are applied.</para>
28.13944 +
28.13945 +    </sect2>
28.13946 +  </sect1>
28.13947 +  <sect1 id="sec:mq:tools">
28.13948 +    <title>Third party tools for working with patches</title>
28.13949 +
28.13950 +    <para id="x_430">Once you've been working with patches for a while, you'll
28.13951 +      find yourself hungry for tools that will help you to understand
28.13952 +      and manipulate the patches you're dealing with.</para>
28.13953 +
28.13954 +    <para id="x_431">The <command moreinfo="none">diffstat</command> command
28.13955 +      <citation>web:diffstat</citation> generates a histogram of the
28.13956 +      modifications made to each file in a patch.  It provides a good
28.13957 +      way to <quote>get a sense of</quote> a patch—which files
28.13958 +      it affects, and how much change it introduces to each file and
28.13959 +      as a whole.  (I find that it's a good idea to use
28.13960 +      <command moreinfo="none">diffstat</command>'s <option role="cmd-opt-diffstat">-p</option> option as a matter of
28.13961 +      course, as otherwise it will try to do clever things with
28.13962 +      prefixes of file names that inevitably confuse at least
28.13963 +      me.)</para>
28.13964 +
28.13965 +<!-- BEGIN mq.tools.tools -->
28.13966 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">diffstat -p1 remove-redundant-null-checks.patch</userinput>
28.13967 + drivers/char/agp/sgi-agp.c        |    5 ++---
28.13968 + drivers/char/hvcs.c               |   11 +++++------
28.13969 + drivers/message/fusion/mptfc.c    |    6 ++----
28.13970 + drivers/message/fusion/mptsas.c   |    3 +--
28.13971 + drivers/net/fs_enet/fs_enet-mii.c |    3 +--
28.13972 + drivers/net/wireless/ipw2200.c    |   22 ++++++----------------
28.13973 + drivers/scsi/libata-scsi.c        |    4 +---
28.13974 + drivers/video/au1100fb.c          |    3 +--
28.13975 + 8 files changed, 19 insertions(+), 38 deletions(-)
28.13976 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">filterdiff -i '*/video/*' remove-redundant-null-checks.patch</userinput>
28.13977 +--- a/drivers/video/au1100fb.c~remove-redundant-null-checks-before-free-in-drivers
28.13978 ++++ a/drivers/video/au1100fb.c
28.13979 +@@ -743,8 +743,7 @@ void __exit au1100fb_cleanup(void)
28.13980 + {
28.13981 + 	driver_unregister(&amp;au1100fb_driver);
28.13982 + 
28.13983 +-	if (drv_info.opt_mode)
28.13984 +-		kfree(drv_info.opt_mode);
28.13985 ++	kfree(drv_info.opt_mode);
28.13986 + }
28.13987 + 
28.13988 + module_init(au1100fb_init);
28.13989 +</screen>
28.13990 +<!-- END mq.tools.tools -->
28.13991 +
28.13992 +
28.13993 +    <para id="x_432">The <literal role="package" moreinfo="none">patchutils</literal> package
28.13994 +      <citation>web:patchutils</citation> is invaluable. It provides a
28.13995 +      set of small utilities that follow the <quote>Unix
28.13996 +	philosophy;</quote> each does one useful thing with a patch.
28.13997 +      The <literal role="package" moreinfo="none">patchutils</literal> command I use
28.13998 +      most is <command moreinfo="none">filterdiff</command>, which extracts subsets
28.13999 +      from a patch file.  For example, given a patch that modifies
28.14000 +      hundreds of files across dozens of directories, a single
28.14001 +      invocation of <command moreinfo="none">filterdiff</command> can generate a
28.14002 +      smaller patch that only touches files whose names match a
28.14003 +      particular glob pattern.  See <xref linkend="mq-collab:tips:interdiff"/> for another
28.14004 +      example.</para>
28.14005 +
28.14006 +  </sect1>
28.14007 +  <sect1>
28.14008 +    <title>Good ways to work with patches</title>
28.14009 +
28.14010 +    <para id="x_433">Whether you are working on a patch series to submit to a
28.14011 +      free software or open source project, or a series that you
28.14012 +      intend to treat as a sequence of regular changesets when you're
28.14013 +      done, you can use some simple techniques to keep your work well
28.14014 +      organized.</para>
28.14015 +
28.14016 +    <para id="x_434">Give your patches descriptive names.  A good name for a
28.14017 +      patch might be <filename moreinfo="none">rework-device-alloc.patch</filename>,
28.14018 +      because it will immediately give you a hint what the purpose of
28.14019 +      the patch is.  Long names shouldn't be a problem; you won't be
28.14020 +      typing the names often, but you <emphasis>will</emphasis> be
28.14021 +      running commands like <command role="hg-ext-mq" moreinfo="none">qapplied</command> and <command role="hg-ext-mq" moreinfo="none">qtop</command> over and over. Good naming
28.14022 +      becomes especially important when you have a number of patches
28.14023 +      to work with, or if you are juggling a number of different tasks
28.14024 +      and your patches only get a fraction of your attention.</para>
28.14025 +
28.14026 +    <para id="x_435">Be aware of what patch you're working on.  Use the <command role="hg-ext-mq" moreinfo="none">qtop</command> command and skim over the text
28.14027 +      of your patches frequently—for example, using <command role="hg-cmd" moreinfo="none">hg tip <option role="hg-opt-tip">-p</option></command>)—to be sure
28.14028 +      of where you stand.  I have several times worked on and <command role="hg-ext-mq" moreinfo="none">qrefresh</command>ed a patch other than the
28.14029 +      one I intended, and it's often tricky to migrate changes into
28.14030 +      the right patch after making them in the wrong one.</para>
28.14031 +
28.14032 +    <para id="x_436">For this reason, it is very much worth investing a little
28.14033 +      time to learn how to use some of the third-party tools I
28.14034 +      described in <xref linkend="sec:mq:tools"/>,
28.14035 +      particularly
28.14036 +      <command moreinfo="none">diffstat</command> and <command moreinfo="none">filterdiff</command>.
28.14037 +      The former will give you a quick idea of what changes your patch
28.14038 +      is making, while the latter makes it easy to splice hunks
28.14039 +      selectively out of one patch and into another.</para>
28.14040 +
28.14041 +  </sect1>
28.14042 +  <sect1>
28.14043 +    <title>MQ cookbook</title>
28.14044 +
28.14045 +    <sect2>
28.14046 +      <title>Manage <quote>trivial</quote> patches</title>
28.14047 +
28.14048 +      <para id="x_437">Because the overhead of dropping files into a new
28.14049 +	Mercurial repository is so low, it makes a lot of sense to
28.14050 +	manage patches this way even if you simply want to make a few
28.14051 +	changes to a source tarball that you downloaded.</para>
28.14052 +
28.14053 +      <para id="x_438">Begin by downloading and unpacking the source tarball, and
28.14054 +	turning it into a Mercurial repository.</para>
28.14055 +
28.14056 +      <!-- BEGIN mq.tarball.download -->
28.14057 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">download netplug-1.2.5.tar.bz2</userinput>
28.14058 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">tar jxf netplug-1.2.5.tar.bz2</userinput>
28.14059 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd netplug-1.2.5</userinput>
28.14060 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init</userinput>
28.14061 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -q --addremove --message netplug-1.2.5</userinput>
28.14062 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput>
28.14063 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone netplug-1.2.5 netplug</userinput>
28.14064 +updating working directory
28.14065 +18 files updated, 0 files merged, 0 files removed, 0 files unresolved
28.14066 +</screen>
28.14067 +<!-- END mq.tarball.download -->
28.14068 +
28.14069 +
28.14070 +      <para id="x_439">Continue by creating a patch stack and making your
28.14071 +	changes.</para>
28.14072 +
28.14073 +      <!-- BEGIN mq.tarball.qinit -->
28.14074 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd netplug</userinput>
28.14075 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qinit</userinput>
28.14076 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qnew -m 'fix build problem with gcc 4' build-fix.patch</userinput>
28.14077 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">perl -pi -e 's/int addr_len/socklen_t addr_len/' netlink.c</userinput>
28.14078 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qrefresh</userinput>
28.14079 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip -p</userinput>
28.14080 +changeset:   1:eeab56666c54
28.14081 +tag:         qtip
28.14082 +tag:         build-fix.patch
28.14083 +tag:         tip
28.14084 +tag:         qbase
28.14085 +user:        Bryan O'Sullivan &lt;bos@serpentine.com&gt;
28.14086 +date:        Sun Aug 16 14:05:10 2009 +0000
28.14087 +summary:     fix build problem with gcc 4
28.14088 +
28.14089 +diff -r 1f6afe9a2d68 -r eeab56666c54 netlink.c
28.14090 +--- a/netlink.c	Sun Aug 16 14:05:09 2009 +0000
28.14091 ++++ b/netlink.c	Sun Aug 16 14:05:10 2009 +0000
28.14092 +@@ -275,7 +275,7 @@
28.14093 +         exit(1);
28.14094 +     }
28.14095 + 
28.14096 +-    int addr_len = sizeof(addr);
28.14097 ++    socklen_t addr_len = sizeof(addr);
28.14098 + 
28.14099 +     if (getsockname(fd, (struct sockaddr *) &amp;addr, &amp;addr_len) == -1) {
28.14100 +         do_log(LOG_ERR, "Could not get socket details: %m");
28.14101 +
28.14102 +</screen>
28.14103 +<!-- END mq.tarball.qinit -->
28.14104 +
28.14105 +
28.14106 +      <para id="x_43a">Let's say a few weeks or months pass, and your package
28.14107 +	author releases a new version.  First, bring their changes
28.14108 +	into the repository.</para>
28.14109 +
28.14110 +      <!-- BEGIN mq.tarball.newsource -->
28.14111 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpop -a</userinput>
28.14112 +patch queue now empty
28.14113 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput>
28.14114 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">download netplug-1.2.8.tar.bz2</userinput>
28.14115 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone netplug-1.2.5 netplug-1.2.8</userinput>
28.14116 +updating working directory
28.14117 +18 files updated, 0 files merged, 0 files removed, 0 files unresolved
28.14118 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd netplug-1.2.8</userinput>
28.14119 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg locate -0 | xargs -0 rm</userinput>
28.14120 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput>
28.14121 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">tar jxf netplug-1.2.8.tar.bz2</userinput>
28.14122 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd netplug-1.2.8</userinput>
28.14123 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit --addremove --message netplug-1.2.8</userinput>
28.14124 +</screen>
28.14125 +<!-- END mq.tarball.newsource -->
28.14126 +
28.14127 +
28.14128 +      <para id="x_43b">The pipeline starting with <command role="hg-cmd" moreinfo="none">hg
28.14129 +	  locate</command> above deletes all files in the working
28.14130 +	directory, so that <command role="hg-cmd" moreinfo="none">hg
28.14131 +	  commit</command>'s <option role="hg-opt-commit">--addremove</option> option can
28.14132 +	actually tell which files have really been removed in the
28.14133 +	newer version of the source.</para>
28.14134 +
28.14135 +      <para id="x_43c">Finally, you can apply your patches on top of the new
28.14136 +	tree.</para>
28.14137 +
28.14138 +      <!-- BEGIN mq.tarball.repush -->
28.14139 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ../netplug</userinput>
28.14140 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull ../netplug-1.2.8</userinput>
28.14141 +pulling from ../netplug-1.2.8
28.14142 +searching for changes
28.14143 +adding changesets
28.14144 +adding manifests
28.14145 +adding file changes
28.14146 +added 1 changesets with 12 changes to 12 files
28.14147 +(run 'hg update' to get a working copy)
28.14148 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpush -a</userinput>
28.14149 +(working directory not at tip)
28.14150 +applying build-fix.patch
28.14151 +now at: build-fix.patch
28.14152 +</screen>
28.14153 +<!-- END mq.tarball.repush -->
28.14154 +
28.14155 +    </sect2>
28.14156 +
28.14157 +    <sect2 id="sec:mq:combine">
28.14158 +      <title>Combining entire patches</title>
28.14159 +
28.14160 +      <para id="x_43d">MQ provides a command, <command role="hg-ext-mq" moreinfo="none">qfold</command> that lets you combine
28.14161 +	entire patches.  This <quote>folds</quote> the patches you
28.14162 +	name, in the order you name them, into the topmost applied
28.14163 +	patch, and concatenates their descriptions onto the end of its
28.14164 +	description.  The patches that you fold must be unapplied
28.14165 +	before you fold them.</para>
28.14166 +
28.14167 +      <para id="x_43e">The order in which you fold patches matters.  If your
28.14168 +	topmost applied patch is <literal moreinfo="none">foo</literal>, and you
28.14169 +	<command role="hg-ext-mq" moreinfo="none">qfold</command>
28.14170 +	<literal moreinfo="none">bar</literal> and <literal moreinfo="none">quux</literal> into it,
28.14171 +	you will end up with a patch that has the same effect as if
28.14172 +	you applied first <literal moreinfo="none">foo</literal>, then
28.14173 +	<literal moreinfo="none">bar</literal>, followed by
28.14174 +	<literal moreinfo="none">quux</literal>.</para>
28.14175 +    </sect2>
28.14176 +
28.14177 +    <sect2>
28.14178 +      <title>Merging part of one patch into another</title>
28.14179 +
28.14180 +      <para id="x_43f">Merging <emphasis>part</emphasis> of one patch into
28.14181 +	another is more difficult than combining entire
28.14182 +	patches.</para>
28.14183 +
28.14184 +      <para id="x_440">If you want to move changes to entire files, you can use
28.14185 +	<command moreinfo="none">filterdiff</command>'s <option role="cmd-opt-filterdiff">-i</option> and <option role="cmd-opt-filterdiff">-x</option> options to choose the
28.14186 +	modifications to snip out of one patch, concatenating its
28.14187 +	output onto the end of the patch you want to merge into.  You
28.14188 +	usually won't need to modify the patch you've merged the
28.14189 +	changes from.  Instead, MQ will report some rejected hunks
28.14190 +	when you <command role="hg-ext-mq" moreinfo="none">qpush</command> it (from
28.14191 +	the hunks you moved into the other patch), and you can simply
28.14192 +	<command role="hg-ext-mq" moreinfo="none">qrefresh</command> the patch to drop
28.14193 +	the duplicate hunks.</para>
28.14194 +
28.14195 +      <para id="x_441">If you have a patch that has multiple hunks modifying a
28.14196 +	file, and you only want to move a few of those hunks, the job
28.14197 +	becomes more messy, but you can still partly automate it.  Use
28.14198 +	<command moreinfo="none">lsdiff -nvv</command> to print some metadata about
28.14199 +	the patch.</para>
28.14200 +
28.14201 +      <!-- BEGIN mq.tools.lsdiff -->
28.14202 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">lsdiff -nvv remove-redundant-null-checks.patch</userinput>
28.14203 +22	File #1  	a/drivers/char/agp/sgi-agp.c
28.14204 +	24	Hunk #1	static int __devinit agp_sgi_init(void)
28.14205 +37	File #2  	a/drivers/char/hvcs.c
28.14206 +	39	Hunk #1	static struct tty_operations hvcs_ops = 
28.14207 +	53	Hunk #2	static int hvcs_alloc_index_list(int n)
28.14208 +69	File #3  	a/drivers/message/fusion/mptfc.c
28.14209 +	71	Hunk #1	mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, in
28.14210 +85	File #4  	a/drivers/message/fusion/mptsas.c
28.14211 +	87	Hunk #1	mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
28.14212 +98	File #5  	a/drivers/net/fs_enet/fs_enet-mii.c
28.14213 +	100	Hunk #1	static struct fs_enet_mii_bus *create_bu
28.14214 +111	File #6  	a/drivers/net/wireless/ipw2200.c
28.14215 +	113	Hunk #1	static struct ipw_fw_error *ipw_alloc_er
28.14216 +	126	Hunk #2	static ssize_t clear_error(struct device
28.14217 +	140	Hunk #3	static void ipw_irq_tasklet(struct ipw_p
28.14218 +	150	Hunk #4	static void ipw_pci_remove(struct pci_de
28.14219 +164	File #7  	a/drivers/scsi/libata-scsi.c
28.14220 +	166	Hunk #1	int ata_cmd_ioctl(struct scsi_device *sc
28.14221 +178	File #8  	a/drivers/video/au1100fb.c
28.14222 +	180	Hunk #1	void __exit au1100fb_cleanup(void)
28.14223 +</screen>
28.14224 +<!-- END mq.tools.lsdiff -->
28.14225 +
28.14226 +
28.14227 +      <para id="x_442">This command prints three different kinds of
28.14228 +	number:</para>
28.14229 +      <itemizedlist>
28.14230 +	<listitem><para id="x_443">(in the first column) a <emphasis>file
28.14231 +	      number</emphasis> to identify each file modified in the
28.14232 +	    patch;</para>
28.14233 +	</listitem>
28.14234 +	<listitem><para id="x_444">(on the next line, indented) the line number
28.14235 +	    within a modified file where a hunk starts; and</para>
28.14236 +	</listitem>
28.14237 +	<listitem><para id="x_445">(on the same line) a <emphasis>hunk
28.14238 +	      number</emphasis> to identify that hunk.</para>
28.14239 +	</listitem></itemizedlist>
28.14240 +
28.14241 +      <para id="x_446">You'll have to use some visual inspection, and reading of
28.14242 +	the patch, to identify the file and hunk numbers you'll want,
28.14243 +	but you can then pass them to to
28.14244 +	<command moreinfo="none">filterdiff</command>'s <option role="cmd-opt-filterdiff">--files</option> and <option role="cmd-opt-filterdiff">--hunks</option> options, to
28.14245 +	select exactly the file and hunk you want to extract.</para>
28.14246 +
28.14247 +      <para id="x_447">Once you have this hunk, you can concatenate it onto the
28.14248 +	end of your destination patch and continue with the remainder
28.14249 +	of <xref linkend="sec:mq:combine"/>.</para>
28.14250 +
28.14251 +    </sect2>
28.14252 +  </sect1>
28.14253 +  <sect1>
28.14254 +    <title>Differences between quilt and MQ</title>
28.14255 +
28.14256 +    <para id="x_448">If you are already familiar with quilt, MQ provides a
28.14257 +      similar command set.  There are a few differences in the way
28.14258 +      that it works.</para>
28.14259 +
28.14260 +    <para id="x_449">You will already have noticed that most quilt commands have
28.14261 +      MQ counterparts that simply begin with a
28.14262 +      <quote><literal moreinfo="none">q</literal></quote>.  The exceptions are quilt's
28.14263 +      <literal moreinfo="none">add</literal> and <literal moreinfo="none">remove</literal> commands,
28.14264 +      the counterparts for which are the normal Mercurial <command role="hg-cmd" moreinfo="none">hg add</command> and <command role="hg-cmd" moreinfo="none">hg
28.14265 +	remove</command> commands.  There is no MQ equivalent of the
28.14266 +      quilt <literal moreinfo="none">edit</literal> command.</para>
28.14267 +
28.14268 +  </sect1>
28.14269 +</chapter>
28.14270 +
28.14271 +<!--
28.14272 +local variables: 
28.14273 +sgml-parent-document: ("00book.xml" "book" "chapter")
28.14274 +end:
28.14275 +-->
28.14276 +
28.14277 +  <!-- BEGIN ch13 -->
28.14278 +  <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
28.14279 +
28.14280 +<chapter id="chap:mq-collab">
28.14281 +  <?dbhtml filename="advanced-uses-of-mercurial-queues.html"?>
28.14282 +  <title>Advanced uses of Mercurial Queues</title>
28.14283 +
28.14284 +  <para id="x_15d">While it's easy to pick up straightforward uses of Mercurial
28.14285 +    Queues, use of a little discipline and some of MQ's less
28.14286 +    frequently used capabilities makes it possible to work in
28.14287 +    complicated development environments.</para>
28.14288 +
28.14289 +  <para id="x_15e">In this chapter, I will use as an example a technique I have
28.14290 +    used to manage the development of an Infiniband device driver for
28.14291 +    the Linux kernel.  The driver in question is large (at least as
28.14292 +    drivers go), with 25,000 lines of code spread across 35 source
28.14293 +    files.  It is maintained by a small team of developers.</para>
28.14294 +
28.14295 +  <para id="x_15f">While much of the material in this chapter is specific to
28.14296 +    Linux, the same principles apply to any code base for which you're
28.14297 +    not the primary owner, and upon which you need to do a lot of
28.14298 +    development.</para>
28.14299 +
28.14300 +  <sect1>
28.14301 +    <title>The problem of many targets</title>
28.14302 +
28.14303 +    <para id="x_160">The Linux kernel changes rapidly, and has never been
28.14304 +      internally stable; developers frequently make drastic changes
28.14305 +      between releases. This means that a version of the driver that
28.14306 +      works well with a particular released version of the kernel will
28.14307 +      not even <emphasis>compile</emphasis> correctly against,
28.14308 +      typically, any other version.</para>
28.14309 +
28.14310 +    <para id="x_161">To maintain a driver, we have to keep a number of distinct
28.14311 +      versions of Linux in mind.</para>
28.14312 +    <itemizedlist>
28.14313 +      <listitem><para id="x_162">One target is the main Linux kernel development
28.14314 +	  tree. Maintenance of the code is in this case partly shared
28.14315 +	  by other developers in the kernel community, who make
28.14316 +	  <quote>drive-by</quote> modifications to the driver as they
28.14317 +	  develop and refine kernel subsystems.</para>
28.14318 +      </listitem>
28.14319 +      <listitem><para id="x_163">We also maintain a number of
28.14320 +	  <quote>backports</quote> to older versions of the Linux
28.14321 +	  kernel, to support the needs of customers who are running
28.14322 +	  older Linux distributions that do not incorporate our
28.14323 +	  drivers.  (To <emphasis>backport</emphasis> a piece of code
28.14324 +	  is to modify it to work in an older version of its target
28.14325 +	  environment than the version it was developed for.)</para>
28.14326 +      </listitem>
28.14327 +      <listitem><para id="x_164">Finally, we make software releases on a schedule
28.14328 +	  that is necessarily not aligned with those used by Linux
28.14329 +	  distributors and kernel developers, so that we can deliver
28.14330 +	  new features to customers without forcing them to upgrade
28.14331 +	  their entire kernels or distributions.</para>
28.14332 +      </listitem></itemizedlist>
28.14333 +
28.14334 +    <sect2>
28.14335 +      <title>Tempting approaches that don't work well</title>
28.14336 +
28.14337 +      <para id="x_165">There are two <quote>standard</quote> ways to maintain a
28.14338 +	piece of software that has to target many different
28.14339 +	environments.</para>
28.14340 +
28.14341 +      <para id="x_166">The first is to maintain a number of branches, each
28.14342 +	intended for a single target.  The trouble with this approach
28.14343 +	is that you must maintain iron discipline in the flow of
28.14344 +	changes between repositories. A new feature or bug fix must
28.14345 +	start life in a <quote>pristine</quote> repository, then
28.14346 +	percolate out to every backport repository.  Backport changes
28.14347 +	are more limited in the branches they should propagate to; a
28.14348 +	backport change that is applied to a branch where it doesn't
28.14349 +	belong will probably stop the driver from compiling.</para>
28.14350 +
28.14351 +      <para id="x_167">The second is to maintain a single source tree filled with
28.14352 +	conditional statements that turn chunks of code on or off
28.14353 +	depending on the intended target.  Because these
28.14354 +	<quote>ifdefs</quote> are not allowed in the Linux kernel
28.14355 +	tree, a manual or automatic process must be followed to strip
28.14356 +	them out and yield a clean tree.  A code base maintained in
28.14357 +	this fashion rapidly becomes a rat's nest of conditional
28.14358 +	blocks that are difficult to understand and maintain.</para>
28.14359 +
28.14360 +      <para id="x_168">Neither of these approaches is well suited to a situation
28.14361 +	where you don't <quote>own</quote> the canonical copy of a
28.14362 +	source tree.  In the case of a Linux driver that is
28.14363 +	distributed with the standard kernel, Linus's tree contains
28.14364 +	the copy of the code that will be treated by the world as
28.14365 +	canonical.  The upstream version of <quote>my</quote> driver
28.14366 +	can be modified by people I don't know, without me even
28.14367 +	finding out about it until after the changes show up in
28.14368 +	Linus's tree.</para>
28.14369 +
28.14370 +      <para id="x_169">These approaches have the added weakness of making it
28.14371 +	difficult to generate well-formed patches to submit
28.14372 +	upstream.</para>
28.14373 +
28.14374 +      <para id="x_16a">In principle, Mercurial Queues seems like a good candidate
28.14375 +	to manage a development scenario such as the above.  While
28.14376 +	this is indeed the case, MQ contains a few added features that
28.14377 +	make the job more pleasant.</para>
28.14378 +
28.14379 +    </sect2>
28.14380 +  </sect1>
28.14381 +  <sect1>
28.14382 +    <title>Conditionally applying patches with guards</title>
28.14383 +
28.14384 +    <para id="x_16b">Perhaps the best way to maintain sanity with so many targets
28.14385 +      is to be able to choose specific patches to apply for a given
28.14386 +      situation.  MQ provides a feature called <quote>guards</quote>
28.14387 +      (which originates with quilt's <literal moreinfo="none">guards</literal>
28.14388 +      command) that does just this.  To start off, let's create a
28.14389 +      simple repository for experimenting in.</para>
28.14390 +
28.14391 +    <!-- BEGIN mq.guards.init -->
28.14392 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qinit</userinput>
28.14393 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qnew hello.patch</userinput>
28.14394 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo hello &gt; hello</userinput>
28.14395 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add hello</userinput>
28.14396 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qrefresh</userinput>
28.14397 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qnew goodbye.patch</userinput>
28.14398 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo goodbye &gt; goodbye</userinput>
28.14399 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add goodbye</userinput>
28.14400 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qrefresh</userinput>
28.14401 +</screen>
28.14402 +<!-- END mq.guards.init -->
28.14403 +
28.14404 +
28.14405 +    <para id="x_16c">This gives us a tiny repository that contains two patches
28.14406 +      that don't have any dependencies on each other, because they
28.14407 +      touch different files.</para>
28.14408 +
28.14409 +    <para id="x_16d">The idea behind conditional application is that you can
28.14410 +      <quote>tag</quote> a patch with a <emphasis>guard</emphasis>,
28.14411 +      which is simply a text string of your choosing, then tell MQ to
28.14412 +      select specific guards to use when applying patches.  MQ will
28.14413 +      then either apply, or skip over, a guarded patch, depending on
28.14414 +      the guards that you have selected.</para>
28.14415 +
28.14416 +    <para id="x_16e">A patch can have an arbitrary number of guards; each one is
28.14417 +      <emphasis>positive</emphasis> (<quote>apply this patch if this
28.14418 +	guard is selected</quote>) or <emphasis>negative</emphasis>
28.14419 +      (<quote>skip this patch if this guard is selected</quote>).  A
28.14420 +      patch with no guards is always applied.</para>
28.14421 +
28.14422 +  </sect1>
28.14423 +  <sect1>
28.14424 +    <title>Controlling the guards on a patch</title>
28.14425 +
28.14426 +    <para id="x_16f">The <command role="hg-ext-mq" moreinfo="none">qguard</command> command lets
28.14427 +      you determine which guards should apply to a patch, or display
28.14428 +      the guards that are already in effect. Without any arguments, it
28.14429 +      displays the guards on the current topmost patch.</para>
28.14430 +
28.14431 +      <!-- BEGIN mq.guards.qguard -->
28.14432 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qguard</userinput>
28.14433 +goodbye.patch: unguarded
28.14434 +</screen>
28.14435 +<!-- END mq.guards.qguard -->
28.14436 +
28.14437 +
28.14438 +    <para id="x_170">To set a positive guard on a patch, prefix the name of the
28.14439 +      guard with a <quote><literal moreinfo="none">+</literal></quote>.</para>
28.14440 +
28.14441 +      <!-- BEGIN mq.guards.qguard.pos -->
28.14442 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qguard +foo</userinput>
28.14443 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qguard</userinput>
28.14444 +goodbye.patch: +foo
28.14445 +</screen>
28.14446 +<!-- END mq.guards.qguard.pos -->
28.14447 +
28.14448 +
28.14449 +    <para id="x_171">To set a negative guard
28.14450 +      on a patch, prefix the name of the guard with a
28.14451 +      <quote><literal moreinfo="none">-</literal></quote>.</para>
28.14452 +
28.14453 +    <!-- BEGIN mq.guards.qguard.neg -->
28.14454 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qguard -- hello.patch -quux</userinput>
28.14455 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qguard hello.patch</userinput>
28.14456 +hello.patch: -quux
28.14457 +</screen>
28.14458 +<!-- END mq.guards.qguard.neg -->
28.14459 +
28.14460 +
28.14461 +    <para id="x_74a">Notice that we prefixed the arguments to the <command moreinfo="none">hg
28.14462 +	qguard</command> command with a <literal moreinfo="none">--</literal> here, so
28.14463 +      that Mercurial would not interpret the text
28.14464 +      <literal moreinfo="none">-quux</literal> as an option.</para>
28.14465 +
28.14466 +    <note>
28.14467 +      <title>Setting vs. modifying</title>
28.14468 +
28.14469 +      <para id="x_172">  The <command role="hg-ext-mq" moreinfo="none">qguard</command> command
28.14470 +	<emphasis>sets</emphasis> the guards on a patch; it doesn't
28.14471 +	<emphasis>modify</emphasis> them.  What this means is that if
28.14472 +	you run <command role="hg-cmd" moreinfo="none">hg qguard +a +b</command> on a
28.14473 +	patch, then <command role="hg-cmd" moreinfo="none">hg qguard +c</command> on
28.14474 +	the same patch, the <emphasis>only</emphasis> guard that will
28.14475 +	be set on it afterwards is <literal moreinfo="none">+c</literal>.</para>
28.14476 +    </note>
28.14477 +
28.14478 +    <para id="x_173">Mercurial stores guards in the <filename role="special" moreinfo="none">series</filename> file; the form in which they
28.14479 +      are stored is easy both to understand and to edit by hand. (In
28.14480 +      other words, you don't have to use the <command role="hg-ext-mq" moreinfo="none">qguard</command> command if you don't want
28.14481 +      to; it's okay to simply edit the <filename role="special" moreinfo="none">series</filename> file.)</para>
28.14482 +
28.14483 +    <!-- BEGIN mq.guards.series -->
28.14484 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat .hg/patches/series</userinput>
28.14485 +hello.patch #-quux
28.14486 +goodbye.patch #+foo
28.14487 +</screen>
28.14488 +<!-- END mq.guards.series -->
28.14489 +
28.14490 +
28.14491 +  </sect1>
28.14492 +  <sect1>
28.14493 +    <title>Selecting the guards to use</title>
28.14494 +
28.14495 +    <para id="x_174">The <command role="hg-ext-mq" moreinfo="none">qselect</command> command
28.14496 +      determines which guards are active at a given time.  The effect
28.14497 +      of this is to determine which patches MQ will apply the next
28.14498 +      time you run <command role="hg-ext-mq" moreinfo="none">qpush</command>.  It has
28.14499 +      no other effect; in particular, it doesn't do anything to
28.14500 +      patches that are already applied.</para>
28.14501 +
28.14502 +    <para id="x_175">With no arguments, the <command role="hg-ext-mq" moreinfo="none">qselect</command> command lists the guards
28.14503 +      currently in effect, one per line of output.  Each argument is
28.14504 +      treated as the name of a guard to apply.</para>
28.14505 +
28.14506 +      <!-- BEGIN mq.guards.qselect.foo -->
28.14507 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpop -a</userinput>
28.14508 +patch queue now empty
28.14509 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qselect</userinput>
28.14510 +no active guards
28.14511 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qselect foo</userinput>
28.14512 +number of unguarded, unapplied patches has changed from 1 to 2
28.14513 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qselect</userinput>
28.14514 +foo
28.14515 +</screen>
28.14516 +<!-- END mq.guards.qselect.foo -->
28.14517 +
28.14518 +
28.14519 +    <para id="x_176">In case you're interested, the currently selected guards are
28.14520 +      stored in the <filename role="special" moreinfo="none">guards</filename> file.</para>
28.14521 +
28.14522 +    <!-- BEGIN mq.guards.qselect.cat -->
28.14523 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat .hg/patches/guards</userinput>
28.14524 +foo
28.14525 +</screen>
28.14526 +<!-- END mq.guards.qselect.cat -->
28.14527 +
28.14528 +
28.14529 +    <para id="x_177">We can see the effect the selected guards have when we run
28.14530 +      <command role="hg-ext-mq" moreinfo="none">qpush</command>.</para>
28.14531 +
28.14532 +    <!-- BEGIN mq.guards.qselect.qpush -->
28.14533 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpush -a</userinput>
28.14534 +applying hello.patch
28.14535 +applying goodbye.patch
28.14536 +now at: goodbye.patch
28.14537 +</screen>
28.14538 +<!-- END mq.guards.qselect.qpush -->
28.14539 +
28.14540 +
28.14541 +    <para id="x_178">A guard cannot start with a
28.14542 +      <quote><literal moreinfo="none">+</literal></quote> or
28.14543 +      <quote><literal moreinfo="none">-</literal></quote> character.  The name of a
28.14544 +      guard must not contain white space, but most other characters
28.14545 +      are acceptable.  If you try to use a guard with an invalid name,
28.14546 +      MQ will complain:</para>
28.14547 +
28.14548 +    <!-- BEGIN mq.guards.qselect.error -->
28.14549 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qselect +foo</userinput>
28.14550 +abort: guard '+foo' starts with invalid character: '+'
28.14551 +</screen>
28.14552 +<!-- END mq.guards.qselect.error -->
28.14553 +
28.14554 +      
28.14555 +    <para id="x_179">Changing the selected guards changes the patches that are
28.14556 +      applied.</para>
28.14557 +
28.14558 +    <!-- BEGIN mq.guards.qselect.quux -->
28.14559 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qselect quux</userinput>
28.14560 +number of guarded, applied patches has changed from 0 to 2
28.14561 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpop -a</userinput>
28.14562 +patch queue now empty
28.14563 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpush -a</userinput>
28.14564 +patch series already fully applied
28.14565 +</screen>
28.14566 +<!-- END mq.guards.qselect.quux -->
28.14567 +
28.14568 +
28.14569 +    <para id="x_17a">You can see in the example below that negative guards take
28.14570 +      precedence over positive guards.</para>
28.14571 +
28.14572 +    <!-- BEGIN mq.guards.qselect.foobar -->
28.14573 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qselect foo bar</userinput>
28.14574 +number of unguarded, unapplied patches has changed from 0 to 2
28.14575 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpop -a</userinput>
28.14576 +no patches applied
28.14577 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpush -a</userinput>
28.14578 +applying hello.patch
28.14579 +applying goodbye.patch
28.14580 +now at: goodbye.patch
28.14581 +</screen>
28.14582 +<!-- END mq.guards.qselect.foobar -->
28.14583 +
28.14584 +
28.14585 +  </sect1>
28.14586 +  <sect1>
28.14587 +    <title>MQ's rules for applying patches</title>
28.14588 +
28.14589 +    <para id="x_17b">The rules that MQ uses when deciding whether to apply a
28.14590 +      patch are as follows.</para>
28.14591 +    <itemizedlist>
28.14592 +      <listitem><para id="x_17c">A patch that has no guards is always
28.14593 +	  applied.</para>
28.14594 +      </listitem>
28.14595 +      <listitem><para id="x_17d">If the patch has any negative guard that matches
28.14596 +	  any currently selected guard, the patch is skipped.</para>
28.14597 +      </listitem>
28.14598 +      <listitem><para id="x_17e">If the patch has any positive guard that matches
28.14599 +	  any currently selected guard, the patch is applied.</para>
28.14600 +      </listitem>
28.14601 +      <listitem><para id="x_17f">If the patch has positive or negative guards,
28.14602 +	  but none matches any currently selected guard, the patch is
28.14603 +	  skipped.</para>
28.14604 +      </listitem></itemizedlist>
28.14605 +
28.14606 +  </sect1>
28.14607 +  <sect1>
28.14608 +    <title>Trimming the work environment</title>
28.14609 +
28.14610 +    <para id="x_180">In working on the device driver I mentioned earlier, I don't
28.14611 +      apply the patches to a normal Linux kernel tree.  Instead, I use
28.14612 +      a repository that contains only a snapshot of the source files
28.14613 +      and headers that are relevant to Infiniband development.  This
28.14614 +      repository is 1% the size of a kernel repository, so it's easier
28.14615 +      to work with.</para>
28.14616 +
28.14617 +    <para id="x_181">I then choose a <quote>base</quote> version on top of which
28.14618 +      the patches are applied.  This is a snapshot of the Linux kernel
28.14619 +      tree as of a revision of my choosing.  When I take the snapshot,
28.14620 +      I record the changeset ID from the kernel repository in the
28.14621 +      commit message.  Since the snapshot preserves the
28.14622 +      <quote>shape</quote> and content of the relevant parts of the
28.14623 +      kernel tree, I can apply my patches on top of either my tiny
28.14624 +      repository or a normal kernel tree.</para>
28.14625 +
28.14626 +    <para id="x_182">Normally, the base tree atop which the patches apply should
28.14627 +      be a snapshot of a very recent upstream tree.  This best
28.14628 +      facilitates the development of patches that can easily be
28.14629 +      submitted upstream with few or no modifications.</para>
28.14630 +
28.14631 +  </sect1>
28.14632 +  <sect1>
28.14633 +    <title>Dividing up the <filename role="special" moreinfo="none">series</filename>
28.14634 +      file</title>
28.14635 +
28.14636 +    <para id="x_183">I categorise the patches in the <filename role="special" moreinfo="none">series</filename> file into a number of logical
28.14637 +      groups.  Each section of like patches begins with a block of
28.14638 +      comments that describes the purpose of the patches that
28.14639 +      follow.</para>
28.14640 +
28.14641 +    <para id="x_184">The sequence of patch groups that I maintain follows.  The
28.14642 +      ordering of these groups is important; I'll describe why after I
28.14643 +      introduce the groups.</para>
28.14644 +    <itemizedlist>
28.14645 +      <listitem><para id="x_185">The <quote>accepted</quote> group.  Patches that
28.14646 +	  the development team has submitted to the maintainer of the
28.14647 +	  Infiniband subsystem, and which he has accepted, but which
28.14648 +	  are not present in the snapshot that the tiny repository is
28.14649 +	  based on.  These are <quote>read only</quote> patches,
28.14650 +	  present only to transform the tree into a similar state as
28.14651 +	  it is in the upstream maintainer's repository.</para>
28.14652 +      </listitem>
28.14653 +      <listitem><para id="x_186">The <quote>rework</quote> group.  Patches that I
28.14654 +	  have submitted, but that the upstream maintainer has
28.14655 +	  requested modifications to before he will accept
28.14656 +	  them.</para>
28.14657 +      </listitem>
28.14658 +      <listitem><para id="x_187">The <quote>pending</quote> group.  Patches that
28.14659 +	  I have not yet submitted to the upstream maintainer, but
28.14660 +	  which we have finished working on. These will be <quote>read
28.14661 +	    only</quote> for a while.  If the upstream maintainer
28.14662 +	  accepts them upon submission, I'll move them to the end of
28.14663 +	  the <quote>accepted</quote> group.  If he requests that I
28.14664 +	  modify any, I'll move them to the beginning of the
28.14665 +	  <quote>rework</quote> group.</para>
28.14666 +      </listitem>
28.14667 +      <listitem><para id="x_188">The <quote>in progress</quote> group.  Patches
28.14668 +	  that are actively being developed, and should not be
28.14669 +	  submitted anywhere yet.</para>
28.14670 +      </listitem>
28.14671 +      <listitem><para id="x_189">The <quote>backport</quote> group.  Patches that
28.14672 +	  adapt the source tree to older versions of the kernel
28.14673 +	  tree.</para>
28.14674 +      </listitem>
28.14675 +      <listitem><para id="x_18a">The <quote>do not ship</quote> group.  Patches
28.14676 +	  that for some reason should never be submitted upstream.
28.14677 +	  For example, one such patch might change embedded driver
28.14678 +	  identification strings to make it easier to distinguish, in
28.14679 +	  the field, between an out-of-tree version of the driver and
28.14680 +	  a version shipped by a distribution vendor.</para>
28.14681 +      </listitem></itemizedlist>
28.14682 +
28.14683 +    <para id="x_18b">Now to return to the reasons for ordering groups of patches
28.14684 +      in this way.  We would like the lowest patches in the stack to
28.14685 +      be as stable as possible, so that we will not need to rework
28.14686 +      higher patches due to changes in context.  Putting patches that
28.14687 +      will never be changed first in the <filename role="special" moreinfo="none">series</filename> file serves this
28.14688 +      purpose.</para>
28.14689 +
28.14690 +    <para id="x_18c">We would also like the patches that we know we'll need to
28.14691 +      modify to be applied on top of a source tree that resembles the
28.14692 +      upstream tree as closely as possible.  This is why we keep
28.14693 +      accepted patches around for a while.</para>
28.14694 +
28.14695 +    <para id="x_18d">The <quote>backport</quote> and <quote>do not ship</quote>
28.14696 +      patches float at the end of the <filename role="special" moreinfo="none">series</filename> file.  The backport patches
28.14697 +      must be applied on top of all other patches, and the <quote>do
28.14698 +	not ship</quote> patches might as well stay out of harm's
28.14699 +      way.</para>
28.14700 +
28.14701 +  </sect1>
28.14702 +  <sect1>
28.14703 +    <title>Maintaining the patch series</title>
28.14704 +
28.14705 +    <para id="x_18e">In my work, I use a number of guards to control which
28.14706 +      patches are to be applied.</para>
28.14707 +
28.14708 +    <itemizedlist>
28.14709 +      <listitem><para id="x_18f"><quote>Accepted</quote> patches are guarded with
28.14710 +	  <literal moreinfo="none">accepted</literal>.  I enable this guard most of
28.14711 +	  the time.  When I'm applying the patches on top of a tree
28.14712 +	  where the patches are already present, I can turn this patch
28.14713 +	  off, and the patches that follow it will apply
28.14714 +	  cleanly.</para>
28.14715 +      </listitem>
28.14716 +      <listitem><para id="x_190">Patches that are <quote>finished</quote>, but
28.14717 +	  not yet submitted, have no guards.  If I'm applying the
28.14718 +	  patch stack to a copy of the upstream tree, I don't need to
28.14719 +	  enable any guards in order to get a reasonably safe source
28.14720 +	  tree.</para>
28.14721 +      </listitem>
28.14722 +      <listitem><para id="x_191">Those patches that need reworking before being
28.14723 +	  resubmitted are guarded with
28.14724 +	  <literal moreinfo="none">rework</literal>.</para>
28.14725 +      </listitem>
28.14726 +      <listitem><para id="x_192">For those patches that are still under
28.14727 +	  development, I use <literal moreinfo="none">devel</literal>.</para>
28.14728 +      </listitem>
28.14729 +      <listitem><para id="x_193">A backport patch may have several guards, one
28.14730 +	  for each version of the kernel to which it applies.  For
28.14731 +	  example, a patch that backports a piece of code to 2.6.9
28.14732 +	  will have a <literal moreinfo="none">2.6.9</literal> guard.</para>
28.14733 +      </listitem></itemizedlist>
28.14734 +    <para id="x_194">This variety of guards gives me considerable flexibility in
28.14735 +      determining what kind of source tree I want to end up with.  For
28.14736 +      most situations, the selection of appropriate guards is
28.14737 +      automated during the build process, but I can manually tune the
28.14738 +      guards to use for less common circumstances.</para>
28.14739 +
28.14740 +    <sect2>
28.14741 +      <title>The art of writing backport patches</title>
28.14742 +
28.14743 +      <para id="x_195">Using MQ, writing a backport patch is a simple process.
28.14744 +	All such a patch has to do is modify a piece of code that uses
28.14745 +	a kernel feature not present in the older version of the
28.14746 +	kernel, so that the driver continues to work correctly under
28.14747 +	that older version.</para>
28.14748 +
28.14749 +      <para id="x_196">A useful goal when writing a good backport patch is to
28.14750 +	make your code look as if it was written for the older version
28.14751 +	of the kernel you're targeting.  The less obtrusive the patch,
28.14752 +	the easier it will be to understand and maintain.  If you're
28.14753 +	writing a collection of backport patches to avoid the
28.14754 +	<quote>rat's nest</quote> effect of lots of
28.14755 +	<literal moreinfo="none">#ifdef</literal>s (hunks of source code that are only
28.14756 +	used conditionally) in your code, don't introduce
28.14757 +	version-dependent <literal moreinfo="none">#ifdef</literal>s into the patches.
28.14758 +	Instead, write several patches, each of which makes
28.14759 +	unconditional changes, and control their application using
28.14760 +	guards.</para>
28.14761 +
28.14762 +      <para id="x_197">There are two reasons to divide backport patches into a
28.14763 +	distinct group, away from the <quote>regular</quote> patches
28.14764 +	whose effects they modify. The first is that intermingling the
28.14765 +	two makes it more difficult to use a tool like the <literal role="hg-ext" moreinfo="none">patchbomb</literal> extension to automate the
28.14766 +	process of submitting the patches to an upstream maintainer.
28.14767 +	The second is that a backport patch could perturb the context
28.14768 +	in which a subsequent regular patch is applied, making it
28.14769 +	impossible to apply the regular patch cleanly
28.14770 +	<emphasis>without</emphasis> the earlier backport patch
28.14771 +	already being applied.</para>
28.14772 +
28.14773 +    </sect2>
28.14774 +  </sect1>
28.14775 +  <sect1>
28.14776 +    <title>Useful tips for developing with MQ</title>
28.14777 +
28.14778 +    <sect2>
28.14779 +      <title>Organising patches in directories</title>
28.14780 +
28.14781 +      <para id="x_198">If you're working on a substantial project with MQ, it's
28.14782 +	not difficult to accumulate a large number of patches.  For
28.14783 +	example, I have one patch repository that contains over 250
28.14784 +	patches.</para>
28.14785 +
28.14786 +      <para id="x_199">If you can group these patches into separate logical
28.14787 +	categories, you can if you like store them in different
28.14788 +	directories; MQ has no problems with patch names that contain
28.14789 +	path separators.</para>
28.14790 +
28.14791 +    </sect2>
28.14792 +    <sect2 id="mq-collab:tips:interdiff">
28.14793 +      <title>Viewing the history of a patch</title>
28.14794 +
28.14795 +      <para id="x_19a">If you're developing a set of patches over a long time,
28.14796 +	it's a good idea to maintain them in a repository, as
28.14797 +	discussed in <xref linkend="sec:mq:repo"/>.  If you do
28.14798 +	so, you'll quickly
28.14799 +	discover that using the <command role="hg-cmd" moreinfo="none">hg
28.14800 +	  diff</command> command to look at the history of changes to
28.14801 +	a patch is unworkable.  This is in part because you're looking
28.14802 +	at the second derivative of the real code (a diff of a diff),
28.14803 +	but also because MQ adds noise to the process by modifying
28.14804 +	time stamps and directory names when it updates a
28.14805 +	patch.</para>
28.14806 +
28.14807 +      <para id="x_19b">However, you can use the <literal role="hg-ext" moreinfo="none">extdiff</literal> extension, which is bundled
28.14808 +	with Mercurial, to turn a diff of two versions of a patch into
28.14809 +	something readable.  To do this, you will need a third-party
28.14810 +	package called <literal role="package" moreinfo="none">patchutils</literal>
28.14811 +	<citation>web:patchutils</citation>.  This provides a command
28.14812 +	named <command moreinfo="none">interdiff</command>, which shows the
28.14813 +	differences between two diffs as a diff.  Used on two versions
28.14814 +	of the same diff, it generates a diff that represents the diff
28.14815 +	from the first to the second version.</para>
28.14816 +
28.14817 +      <para id="x_19c">You can enable the <literal role="hg-ext" moreinfo="none">extdiff</literal> extension in the usual way,
28.14818 +	by adding a line to the <literal role="rc-extensions" moreinfo="none">extensions</literal> section of your
28.14819 +	<filename role="special" moreinfo="none">~/.hgrc</filename>.</para>
28.14820 +      <programlisting format="linespecific">[extensions]
28.14821 +extdiff =</programlisting>
28.14822 +      <para id="x_19d">The <command moreinfo="none">interdiff</command> command expects to be
28.14823 +	passed the names of two files, but the <literal role="hg-ext" moreinfo="none">extdiff</literal> extension passes the program
28.14824 +	it runs a pair of directories, each of which can contain an
28.14825 +	arbitrary number of files.  We thus need a small program that
28.14826 +	will run <command moreinfo="none">interdiff</command> on each pair of files in
28.14827 +	these two directories.  This program is available as <filename role="special" moreinfo="none">hg-interdiff</filename> in the <filename class="directory" moreinfo="none">examples</filename> directory of the
28.14828 +	source code repository that accompanies this book. <!--
28.14829 +	&example.hg-interdiff; --></para>
28.14830 +
28.14831 +      <para id="x_19e">With the <filename role="special" moreinfo="none">hg-interdiff</filename>
28.14832 +	program in your shell's search path, you can run it as
28.14833 +	follows, from inside an MQ patch directory:</para>
28.14834 +      <programlisting format="linespecific">hg extdiff -p hg-interdiff -r A:B my-change.patch</programlisting>
28.14835 +      <para id="x_19f">Since you'll probably want to use this long-winded command
28.14836 +	a lot, you can get <literal role="hg-ext" moreinfo="none">hgext</literal> to
28.14837 +	make it available as a normal Mercurial command, again by
28.14838 +	editing your <filename role="special" moreinfo="none">~/.hgrc</filename>.</para>
28.14839 +      <programlisting format="linespecific">[extdiff]
28.14840 +cmd.interdiff = hg-interdiff</programlisting>
28.14841 +      <para id="x_1a0">This directs <literal role="hg-ext" moreinfo="none">hgext</literal> to
28.14842 +	make an <literal moreinfo="none">interdiff</literal> command available, so you
28.14843 +	can now shorten the previous invocation of <command role="hg-ext-extdiff" moreinfo="none">extdiff</command> to something a
28.14844 +	little more wieldy.</para>
28.14845 +      <programlisting format="linespecific">hg interdiff -r A:B my-change.patch</programlisting>
28.14846 +
28.14847 +      <note>
28.14848 +	<para id="x_1a1">  The <command moreinfo="none">interdiff</command> command works well
28.14849 +	  only if the underlying files against which versions of a
28.14850 +	  patch are generated remain the same.  If you create a patch,
28.14851 +	  modify the underlying files, and then regenerate the patch,
28.14852 +	  <command moreinfo="none">interdiff</command> may not produce useful
28.14853 +	  output.</para>
28.14854 +      </note>
28.14855 +
28.14856 +      <para id="x_1a2">The <literal role="hg-ext" moreinfo="none">extdiff</literal> extension is
28.14857 +	useful for more than merely improving the presentation of MQ
28.14858 +	patches.  To read more about it, go to <xref linkend="sec:hgext:extdiff"/>.</para>
28.14859 +
28.14860 +    </sect2>
28.14861 +  </sect1>
28.14862 +</chapter>
28.14863 +
28.14864 +<!--
28.14865 +local variables: 
28.14866 +sgml-parent-document: ("00book.xml" "book" "chapter")
28.14867 +end:
28.14868 +-->
28.14869 +
28.14870 +  <!-- BEGIN ch14 -->
28.14871 +  <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
28.14872 +
28.14873 +<chapter id="chap:hgext">
28.14874 +  <?dbhtml filename="adding-functionality-with-extensions.html"?>
28.14875 +  <title>Adding functionality with extensions</title>
28.14876 +
28.14877 +  <para id="x_4fe">While the core of Mercurial is quite complete from a
28.14878 +    functionality standpoint, it's deliberately shorn of fancy
28.14879 +    features.  This approach of preserving simplicity keeps the
28.14880 +    software easy to deal with for both maintainers and users.</para>
28.14881 +
28.14882 +  <para id="x_4ff">However, Mercurial doesn't box you in with an inflexible
28.14883 +    command set: you can add features to it as
28.14884 +    <emphasis>extensions</emphasis> (sometimes known as
28.14885 +    <emphasis>plugins</emphasis>).  We've already discussed a few of
28.14886 +    these extensions in earlier chapters.</para>
28.14887 +  <itemizedlist>
28.14888 +    <listitem><para id="x_500"><xref linkend="sec:tour-merge:fetch"/>
28.14889 +	covers the <literal role="hg-ext" moreinfo="none">fetch</literal> extension;
28.14890 +	this combines pulling new changes and merging them with local
28.14891 +	changes into a single command, <command role="hg-ext-fetch" moreinfo="none">fetch</command>.</para>
28.14892 +    </listitem>
28.14893 +    <listitem><para id="x_501">In <xref linkend="chap:hook"/>, we covered
28.14894 +	several extensions that are useful for hook-related
28.14895 +	functionality: <literal role="hg-ext" moreinfo="none">acl</literal> adds
28.14896 +	access control lists; <literal role="hg-ext" moreinfo="none">bugzilla</literal> adds integration with the
28.14897 +	Bugzilla bug tracking system; and <literal role="hg-ext" moreinfo="none">notify</literal> sends notification emails on
28.14898 +	new changes.</para>
28.14899 +    </listitem>
28.14900 +    <listitem><para id="x_502">The Mercurial Queues patch management extension is
28.14901 +	so invaluable that it merits two chapters and an appendix all
28.14902 +	to itself. <xref linkend="chap:mq"/> covers the
28.14903 +	basics; <xref linkend="chap:mq-collab"/> discusses advanced topics;
28.14904 +	and <xref linkend="chap:mqref"/> goes into detail on
28.14905 +	each
28.14906 +	command.</para>
28.14907 +    </listitem></itemizedlist>
28.14908 +
28.14909 +  <para id="x_503">In this chapter, we'll cover some of the other extensions that
28.14910 +    are available for Mercurial, and briefly touch on some of the
28.14911 +    machinery you'll need to know about if you want to write an
28.14912 +    extension of your own.</para>
28.14913 +  <itemizedlist>
28.14914 +    <listitem><para id="x_504">In <xref linkend="sec:hgext:inotify"/>,
28.14915 +	we'll discuss the possibility of <emphasis>huge</emphasis>
28.14916 +	performance improvements using the <literal role="hg-ext" moreinfo="none">inotify</literal> extension.</para>
28.14917 +    </listitem></itemizedlist>
28.14918 +
28.14919 +  <sect1 id="sec:hgext:inotify">
28.14920 +    <title>Improve performance with the <literal role="hg-ext" moreinfo="none">inotify</literal> extension</title>
28.14921 +
28.14922 +    <para id="x_505">Are you interested in having some of the most common
28.14923 +      Mercurial operations run as much as a hundred times faster?
28.14924 +      Read on!</para>
28.14925 +
28.14926 +    <para id="x_506">Mercurial has great performance under normal circumstances.
28.14927 +      For example, when you run the <command role="hg-cmd" moreinfo="none">hg
28.14928 +	status</command> command, Mercurial has to scan almost every
28.14929 +      directory and file in your repository so that it can display
28.14930 +      file status.  Many other Mercurial commands need to do the same
28.14931 +      work behind the scenes; for example, the <command role="hg-cmd" moreinfo="none">hg diff</command> command uses the status
28.14932 +      machinery to avoid doing an expensive comparison operation on
28.14933 +      files that obviously haven't changed.</para>
28.14934 +
28.14935 +    <para id="x_507">Because obtaining file status is crucial to good
28.14936 +      performance, the authors of Mercurial have optimised this code
28.14937 +      to within an inch of its life.  However, there's no avoiding the
28.14938 +      fact that when you run <command role="hg-cmd" moreinfo="none">hg
28.14939 +	status</command>, Mercurial is going to have to perform at
28.14940 +      least one expensive system call for each managed file to
28.14941 +      determine whether it's changed since the last time Mercurial
28.14942 +      checked.  For a sufficiently large repository, this can take a
28.14943 +      long time.</para>
28.14944 +
28.14945 +    <para id="x_508">To put a number on the magnitude of this effect, I created a
28.14946 +      repository containing 150,000 managed files.  I timed <command role="hg-cmd" moreinfo="none">hg status</command> as taking ten seconds to
28.14947 +      run, even when <emphasis>none</emphasis> of those files had been
28.14948 +      modified.</para>
28.14949 +
28.14950 +    <para id="x_509">Many modern operating systems contain a file notification
28.14951 +      facility. If a program signs up to an appropriate service, the
28.14952 +      operating system will notify it every time a file of interest is
28.14953 +      created, modified, or deleted.  On Linux systems, the kernel
28.14954 +      component that does this is called
28.14955 +      <literal moreinfo="none">inotify</literal>.</para>
28.14956 +
28.14957 +    <para id="x_50a">Mercurial's <literal role="hg-ext" moreinfo="none">inotify</literal>
28.14958 +      extension talks to the kernel's <literal moreinfo="none">inotify</literal>
28.14959 +      component to optimise <command role="hg-cmd" moreinfo="none">hg status</command>
28.14960 +      commands.  The extension has two components.  A daemon sits in
28.14961 +      the background and receives notifications from the
28.14962 +      <literal moreinfo="none">inotify</literal> subsystem.  It also listens for
28.14963 +      connections from a regular Mercurial command.  The extension
28.14964 +      modifies Mercurial's behavior so that instead of scanning the
28.14965 +      filesystem, it queries the daemon.  Since the daemon has perfect
28.14966 +      information about the state of the repository, it can respond
28.14967 +      with a result instantaneously, avoiding the need to scan every
28.14968 +      directory and file in the repository.</para>
28.14969 +
28.14970 +    <para id="x_50b">Recall the ten seconds that I measured plain Mercurial as
28.14971 +      taking to run <command role="hg-cmd" moreinfo="none">hg status</command> on a
28.14972 +      150,000 file repository.  With the <literal role="hg-ext" moreinfo="none">inotify</literal> extension enabled, the time
28.14973 +      dropped to 0.1 seconds, a factor of <emphasis>one
28.14974 +	hundred</emphasis> faster.</para>
28.14975 +
28.14976 +    <para id="x_50c">Before we continue, please pay attention to some
28.14977 +      caveats.</para>
28.14978 +    <itemizedlist>
28.14979 +      <listitem><para id="x_50d">The <literal role="hg-ext" moreinfo="none">inotify</literal>
28.14980 +	  extension is Linux-specific.  Because it interfaces directly
28.14981 +	  to the Linux kernel's <literal moreinfo="none">inotify</literal> subsystem,
28.14982 +	  it does not work on other operating systems.</para>
28.14983 +      </listitem>
28.14984 +      <listitem><para id="x_50e">It should work on any Linux distribution that
28.14985 +	  was released after early 2005.  Older distributions are
28.14986 +	  likely to have a kernel that lacks
28.14987 +	  <literal moreinfo="none">inotify</literal>, or a version of
28.14988 +	  <literal moreinfo="none">glibc</literal> that does not have the necessary
28.14989 +	  interfacing support.</para>
28.14990 +      </listitem>
28.14991 +      <listitem><para id="x_50f">Not all filesystems are suitable for use with
28.14992 +	  the <literal role="hg-ext" moreinfo="none">inotify</literal> extension.
28.14993 +	  Network filesystems such as NFS are a non-starter, for
28.14994 +	  example, particularly if you're running Mercurial on several
28.14995 +	  systems, all mounting the same network filesystem.  The
28.14996 +	  kernel's <literal moreinfo="none">inotify</literal> system has no way of
28.14997 +	  knowing about changes made on another system.  Most local
28.14998 +	  filesystems (e.g. ext3, XFS, ReiserFS) should work
28.14999 +	  fine.</para>
28.15000 +      </listitem></itemizedlist>
28.15001 +
28.15002 +    <para id="x_510">The <literal role="hg-ext" moreinfo="none">inotify</literal> extension is
28.15003 +      not yet shipped with Mercurial as of May 2007, so it's a little
28.15004 +      more involved to set up than other extensions.  But the
28.15005 +      performance improvement is worth it!</para>
28.15006 +
28.15007 +    <para id="x_511">The extension currently comes in two parts: a set of patches
28.15008 +      to the Mercurial source code, and a library of Python bindings
28.15009 +      to the <literal moreinfo="none">inotify</literal> subsystem.</para>
28.15010 +    <note>
28.15011 +      <para id="x_512">  There are <emphasis>two</emphasis> Python
28.15012 +	<literal moreinfo="none">inotify</literal> binding libraries.  One of them is
28.15013 +	called <literal moreinfo="none">pyinotify</literal>, and is packaged by some
28.15014 +	Linux distributions as <literal moreinfo="none">python-inotify</literal>.
28.15015 +	This is <emphasis>not</emphasis> the one you'll need, as it is
28.15016 +	too buggy and inefficient to be practical.</para>
28.15017 +    </note>
28.15018 +    <para id="x_513">To get going, it's best to already have a functioning copy
28.15019 +      of Mercurial installed.</para>
28.15020 +    <note>
28.15021 +      <para id="x_514">  If you follow the instructions below, you'll be
28.15022 +	<emphasis>replacing</emphasis> and overwriting any existing
28.15023 +	installation of Mercurial that you might already have, using
28.15024 +	the latest <quote>bleeding edge</quote> Mercurial code. Don't
28.15025 +	say you weren't warned!</para>
28.15026 +    </note>
28.15027 +    <orderedlist inheritnum="ignore" continuation="restarts">
28.15028 +      <listitem><para id="x_515">Clone the Python <literal moreinfo="none">inotify</literal>
28.15029 +	  binding repository.  Build and install it.</para>
28.15030 +	<programlisting format="linespecific">hg clone http://hg.kublai.com/python/inotify
28.15031 +cd inotify
28.15032 +python setup.py build --force
28.15033 +sudo python setup.py install --skip-build</programlisting>
28.15034 +      </listitem>
28.15035 +      <listitem><para id="x_516">Clone the <filename class="directory" moreinfo="none">crew</filename> Mercurial repository.
28.15036 +	  Clone the <literal role="hg-ext" moreinfo="none">inotify</literal> patch
28.15037 +	  repository so that Mercurial Queues will be able to apply
28.15038 +	  patches to your cope of the <filename class="directory" moreinfo="none">crew</filename> repository.</para>
28.15039 +	<programlisting format="linespecific">hg clone http://hg.intevation.org/mercurial/crew
28.15040 +hg clone crew inotify
28.15041 +hg clone http://hg.kublai.com/mercurial/patches/inotify inotify/.hg/patches</programlisting>
28.15042 +      </listitem>
28.15043 +      <listitem><para id="x_517">Make sure that you have the Mercurial Queues
28.15044 +	  extension, <literal role="hg-ext" moreinfo="none">mq</literal>, enabled.  If
28.15045 +	  you've never used MQ, read <xref linkend="sec:mq:start"/> to get started
28.15046 +	  quickly.</para>
28.15047 +      </listitem>
28.15048 +      <listitem><para id="x_518">Go into the <filename class="directory" moreinfo="none">inotify</filename> repo, and apply all
28.15049 +	  of the <literal role="hg-ext" moreinfo="none">inotify</literal> patches
28.15050 +	  using the <option role="hg-ext-mq-cmd-qpush-opt">hg
28.15051 +	    -a</option> option to the <command role="hg-ext-mq" moreinfo="none">qpush</command> command.</para>
28.15052 +	<programlisting format="linespecific">cd inotify
28.15053 +hg qpush -a</programlisting>
28.15054 +      </listitem>
28.15055 +      <listitem><para id="x_519">  If you get an error message from <command role="hg-ext-mq" moreinfo="none">qpush</command>, you should not continue.
28.15056 +	  Instead, ask for help.</para>
28.15057 +      </listitem>
28.15058 +      <listitem><para id="x_51a">Build and install the patched version of
28.15059 +	  Mercurial.</para>
28.15060 +	<programlisting format="linespecific">python setup.py build --force
28.15061 +sudo python setup.py install --skip-build</programlisting>
28.15062 +      </listitem>
28.15063 +    </orderedlist>
28.15064 +    <para id="x_51b">Once you've build a suitably patched version of Mercurial,
28.15065 +      all you need to do to enable the <literal role="hg-ext" moreinfo="none">inotify</literal> extension is add an entry to
28.15066 +      your <filename role="special" moreinfo="none">~/.hgrc</filename>.</para>
28.15067 +    <programlisting format="linespecific">[extensions] inotify =</programlisting>
28.15068 +    <para id="x_51c">When the <literal role="hg-ext" moreinfo="none">inotify</literal> extension
28.15069 +      is enabled, Mercurial will automatically and transparently start
28.15070 +      the status daemon the first time you run a command that needs
28.15071 +      status in a repository.  It runs one status daemon per
28.15072 +      repository.</para>
28.15073 +
28.15074 +    <para id="x_51d">The status daemon is started silently, and runs in the
28.15075 +      background.  If you look at a list of running processes after
28.15076 +      you've enabled the <literal role="hg-ext" moreinfo="none">inotify</literal>
28.15077 +      extension and run a few commands in different repositories,
28.15078 +      you'll thus see a few <literal moreinfo="none">hg</literal> processes sitting
28.15079 +      around, waiting for updates from the kernel and queries from
28.15080 +      Mercurial.</para>
28.15081 +
28.15082 +    <para id="x_51e">The first time you run a Mercurial command in a repository
28.15083 +      when you have the <literal role="hg-ext" moreinfo="none">inotify</literal>
28.15084 +      extension enabled, it will run with about the same performance
28.15085 +      as a normal Mercurial command.  This is because the status
28.15086 +      daemon needs to perform a normal status scan so that it has a
28.15087 +      baseline against which to apply later updates from the kernel.
28.15088 +      However, <emphasis>every</emphasis> subsequent command that does
28.15089 +      any kind of status check should be noticeably faster on
28.15090 +      repositories of even fairly modest size.  Better yet, the bigger
28.15091 +      your repository is, the greater a performance advantage you'll
28.15092 +      see.  The <literal role="hg-ext" moreinfo="none">inotify</literal> daemon makes
28.15093 +      status operations almost instantaneous on repositories of all
28.15094 +      sizes!</para>
28.15095 +
28.15096 +    <para id="x_51f">If you like, you can manually start a status daemon using
28.15097 +      the <command role="hg-ext-inotify" moreinfo="none">inserve</command> command.
28.15098 +      This gives you slightly finer control over how the daemon ought
28.15099 +      to run.  This command will of course only be available when the
28.15100 +      <literal role="hg-ext" moreinfo="none">inotify</literal> extension is
28.15101 +      enabled.</para>
28.15102 +
28.15103 +    <para id="x_520">When you're using the <literal role="hg-ext" moreinfo="none">inotify</literal> extension, you should notice
28.15104 +      <emphasis>no difference at all</emphasis> in Mercurial's
28.15105 +      behavior, with the sole exception of status-related commands
28.15106 +      running a whole lot faster than they used to.  You should
28.15107 +      specifically expect that commands will not print different
28.15108 +      output; neither should they give different results. If either of
28.15109 +      these situations occurs, please report a bug.</para>
28.15110 +
28.15111 +  </sect1>
28.15112 +  <sect1 id="sec:hgext:extdiff">
28.15113 +    <title>Flexible diff support with the <literal role="hg-ext" moreinfo="none">extdiff</literal> extension</title>
28.15114 +
28.15115 +    <para id="x_521">Mercurial's built-in <command role="hg-cmd" moreinfo="none">hg
28.15116 +	diff</command> command outputs plaintext unified diffs.</para>
28.15117 +
28.15118 +    <!-- BEGIN extdiff.diff -->
28.15119 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg diff</userinput>
28.15120 +diff -r 801b35c37d8b myfile
28.15121 +--- a/myfile	Sun Aug 16 14:05:02 2009 +0000
28.15122 ++++ b/myfile	Sun Aug 16 14:05:02 2009 +0000
28.15123 +@@ -1,1 +1,2 @@
28.15124 + The first line.
28.15125 ++The second line.
28.15126 +</screen>
28.15127 +<!-- END extdiff.diff -->
28.15128 +
28.15129 +
28.15130 +    <para id="x_522">If you would like to use an external tool to display
28.15131 +      modifications, you'll want to use the <literal role="hg-ext" moreinfo="none">extdiff</literal> extension.  This will let you
28.15132 +      use, for example, a graphical diff tool.</para>
28.15133 +
28.15134 +    <para id="x_523">The <literal role="hg-ext" moreinfo="none">extdiff</literal> extension is
28.15135 +      bundled with Mercurial, so it's easy to set up.  In the <literal role="rc-extensions" moreinfo="none">extensions</literal> section of your
28.15136 +      <filename role="special" moreinfo="none">~/.hgrc</filename>, simply add a
28.15137 +      one-line entry to enable the extension.</para>
28.15138 +    <programlisting format="linespecific">[extensions]
28.15139 +extdiff =</programlisting>
28.15140 +    <para id="x_524">This introduces a command named <command role="hg-ext-extdiff" moreinfo="none">extdiff</command>, which by default uses
28.15141 +      your system's <command moreinfo="none">diff</command> command to generate a
28.15142 +      unified diff in the same form as the built-in <command role="hg-cmd" moreinfo="none">hg diff</command> command.</para>
28.15143 +    
28.15144 +    <!-- BEGIN extdiff.extdiff -->
28.15145 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg extdiff</userinput>
28.15146 +--- a.801b35c37d8b/myfile	2009-08-16 14:05:02.000000000 +0000
28.15147 ++++ /tmp/extdiffl1y_s9/a/myfile	2009-08-16 14:05:02.000000000 +0000
28.15148 +@@ -1 +1,2 @@
28.15149 + The first line.
28.15150 ++The second line.
28.15151 +</screen>
28.15152 +<!-- END extdiff.extdiff -->
28.15153 +
28.15154 +
28.15155 +    <para id="x_525">The result won't be exactly the same as with the built-in
28.15156 +      <command role="hg-cmd" moreinfo="none">hg diff</command> variations, because the
28.15157 +      output of <command moreinfo="none">diff</command> varies from one system to
28.15158 +      another, even when passed the same options.</para>
28.15159 +
28.15160 +    <para id="x_526">As the <quote><literal moreinfo="none">making snapshot</literal></quote>
28.15161 +      lines of output above imply, the <command role="hg-ext-extdiff" moreinfo="none">extdiff</command> command works by
28.15162 +      creating two snapshots of your source tree.  The first snapshot
28.15163 +      is of the source revision; the second, of the target revision or
28.15164 +      working directory.  The <command role="hg-ext-extdiff" moreinfo="none">extdiff</command> command generates
28.15165 +      these snapshots in a temporary directory, passes the name of
28.15166 +      each directory to an external diff viewer, then deletes the
28.15167 +      temporary directory.  For efficiency, it only snapshots the
28.15168 +      directories and files that have changed between the two
28.15169 +      revisions.</para>
28.15170 +
28.15171 +    <para id="x_527">Snapshot directory names have the same base name as your
28.15172 +      repository. If your repository path is <filename class="directory" moreinfo="none">/quux/bar/foo</filename>, then <filename class="directory" moreinfo="none">foo</filename> will be the name of each
28.15173 +      snapshot directory.  Each snapshot directory name has its
28.15174 +      changeset ID appended, if appropriate.  If a snapshot is of
28.15175 +      revision <literal moreinfo="none">a631aca1083f</literal>, the directory will be
28.15176 +      named <filename class="directory" moreinfo="none">foo.a631aca1083f</filename>.
28.15177 +      A snapshot of the working directory won't have a changeset ID
28.15178 +      appended, so it would just be <filename class="directory" moreinfo="none">foo</filename> in this example.  To see what
28.15179 +      this looks like in practice, look again at the <command role="hg-ext-extdiff" moreinfo="none">extdiff</command> example above.  Notice
28.15180 +      that the diff has the snapshot directory names embedded in its
28.15181 +      header.</para>
28.15182 +
28.15183 +    <para id="x_528">The <command role="hg-ext-extdiff" moreinfo="none">extdiff</command> command
28.15184 +      accepts two important options. The <option role="hg-ext-extdiff-cmd-extdiff-opt">hg -p</option> option
28.15185 +      lets you choose a program to view differences with, instead of
28.15186 +      <command moreinfo="none">diff</command>.  With the <option role="hg-ext-extdiff-cmd-extdiff-opt">hg -o</option> option,
28.15187 +      you can change the options that <command role="hg-ext-extdiff" moreinfo="none">extdiff</command> passes to the program
28.15188 +      (by default, these options are
28.15189 +      <quote><literal moreinfo="none">-Npru</literal></quote>, which only make sense
28.15190 +      if you're running <command moreinfo="none">diff</command>).  In other respects,
28.15191 +      the <command role="hg-ext-extdiff" moreinfo="none">extdiff</command> command
28.15192 +      acts similarly to the built-in <command role="hg-cmd" moreinfo="none">hg
28.15193 +	diff</command> command: you use the same option names, syntax,
28.15194 +      and arguments to specify the revisions you want, the files you
28.15195 +      want, and so on.</para>
28.15196 +
28.15197 +    <para id="x_529">As an example, here's how to run the normal system
28.15198 +      <command moreinfo="none">diff</command> command, getting it to generate context
28.15199 +      diffs (using the <option role="cmd-opt-diff">-c</option> option)
28.15200 +      instead of unified diffs, and five lines of context instead of
28.15201 +      the default three (passing <literal moreinfo="none">5</literal> as the argument
28.15202 +      to the <option role="cmd-opt-diff">-C</option> option).</para>
28.15203 +
28.15204 +      <!-- BEGIN extdiff.extdiff-ctx -->
28.15205 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg extdiff -o -NprcC5</userinput>
28.15206 +*** a.801b35c37d8b/myfile	Sun Aug 16 14:05:02 2009
28.15207 +--- /tmp/extdiffl1y_s9/a/myfile	Sun Aug 16 14:05:02 2009
28.15208 +***************
28.15209 +*** 1 ****
28.15210 +--- 1,2 ----
28.15211 +  The first line.
28.15212 ++ The second line.
28.15213 +</screen>
28.15214 +<!-- END extdiff.extdiff-ctx -->
28.15215 +
28.15216 +
28.15217 +    <para id="x_52a">Launching a visual diff tool is just as easy.  Here's how to
28.15218 +      launch the <command moreinfo="none">kdiff3</command> viewer.</para>
28.15219 +    <programlisting format="linespecific">hg extdiff -p kdiff3 -o</programlisting>
28.15220 +
28.15221 +    <para id="x_52b">If your diff viewing command can't deal with directories,
28.15222 +      you can easily work around this with a little scripting.  For an
28.15223 +      example of such scripting in action with the <literal role="hg-ext" moreinfo="none">mq</literal> extension and the
28.15224 +      <command moreinfo="none">interdiff</command> command, see <xref linkend="mq-collab:tips:interdiff"/>.</para>
28.15225 +
28.15226 +    <sect2>
28.15227 +      <title>Defining command aliases</title>
28.15228 +
28.15229 +      <para id="x_52c">It can be cumbersome to remember the options to both the
28.15230 +	<command role="hg-ext-extdiff" moreinfo="none">extdiff</command> command and
28.15231 +	the diff viewer you want to use, so the <literal role="hg-ext" moreinfo="none">extdiff</literal> extension lets you define
28.15232 +	<emphasis>new</emphasis> commands that will invoke your diff
28.15233 +	viewer with exactly the right options.</para>
28.15234 +
28.15235 +      <para id="x_52d">All you need to do is edit your <filename role="special" moreinfo="none">~/.hgrc</filename>, and add a section named
28.15236 +	<literal role="rc-extdiff" moreinfo="none">extdiff</literal>.  Inside this
28.15237 +	section, you can define multiple commands.  Here's how to add
28.15238 +	a <literal moreinfo="none">kdiff3</literal> command.  Once you've defined
28.15239 +	this, you can type <quote><literal moreinfo="none">hg kdiff3</literal></quote>
28.15240 +	and the <literal role="hg-ext" moreinfo="none">extdiff</literal> extension
28.15241 +	will run <command moreinfo="none">kdiff3</command> for you.</para>
28.15242 +      <programlisting format="linespecific">[extdiff]
28.15243 +cmd.kdiff3 =</programlisting>
28.15244 +      <para id="x_52e">If you leave the right hand side of the definition empty,
28.15245 +	as above, the <literal role="hg-ext" moreinfo="none">extdiff</literal>
28.15246 +	extension uses the name of the command you defined as the name
28.15247 +	of the external program to run.  But these names don't have to
28.15248 +	be the same.  Here, we define a command named
28.15249 +	<quote><literal moreinfo="none">hg wibble</literal></quote>, which runs
28.15250 +	<command moreinfo="none">kdiff3</command>.</para>
28.15251 +      <programlisting format="linespecific">[extdiff]
28.15252 + cmd.wibble = kdiff3</programlisting>
28.15253 +
28.15254 +      <para id="x_52f">You can also specify the default options that you want to
28.15255 +	invoke your diff viewing program with.  The prefix to use is
28.15256 +	<quote><literal moreinfo="none">opts.</literal></quote>, followed by the name
28.15257 +	of the command to which the options apply.  This example
28.15258 +	defines a <quote><literal moreinfo="none">hg vimdiff</literal></quote> command
28.15259 +	that runs the <command moreinfo="none">vim</command> editor's
28.15260 +	<literal moreinfo="none">DirDiff</literal> extension.</para>
28.15261 +      <programlisting format="linespecific">[extdiff]
28.15262 + cmd.vimdiff = vim
28.15263 +opts.vimdiff = -f '+next' '+execute "DirDiff" argv(0) argv(1)'</programlisting>
28.15264 +
28.15265 +    </sect2>
28.15266 +  </sect1>
28.15267 +  <sect1 id="sec:hgext:transplant">
28.15268 +    <title>Cherrypicking changes with the <literal role="hg-ext" moreinfo="none">transplant</literal> extension</title>
28.15269 +
28.15270 +    <para id="x_530">Need to have a long chat with Brendan about this.</para>
28.15271 +
28.15272 +  </sect1>
28.15273 +  <sect1 id="sec:hgext:patchbomb">
28.15274 +    <title>Send changes via email with the <literal role="hg-ext" moreinfo="none">patchbomb</literal> extension</title>
28.15275 +
28.15276 +    <para id="x_531">Many projects have a culture of <quote>change
28.15277 +	review</quote>, in which people send their modifications to a
28.15278 +      mailing list for others to read and comment on before they
28.15279 +      commit the final version to a shared repository.  Some projects
28.15280 +      have people who act as gatekeepers; they apply changes from
28.15281 +      other people to a repository to which those others don't have
28.15282 +      access.</para>
28.15283 +
28.15284 +    <para id="x_532">Mercurial makes it easy to send changes over email for
28.15285 +      review or application, via its <literal role="hg-ext" moreinfo="none">patchbomb</literal> extension.  The extension is
28.15286 +      so named because changes are formatted as patches, and it's usual
28.15287 +      to send one changeset per email message.  Sending a long series
28.15288 +      of changes by email is thus much like <quote>bombing</quote> the
28.15289 +      recipient's inbox, hence <quote>patchbomb</quote>.</para>
28.15290 +
28.15291 +    <para id="x_533">As usual, the basic configuration of the <literal role="hg-ext" moreinfo="none">patchbomb</literal> extension takes just one or
28.15292 +      two lines in your <filename role="special" moreinfo="none">
28.15293 +	/.hgrc</filename>.</para>
28.15294 +    <programlisting format="linespecific">[extensions]
28.15295 +patchbomb =</programlisting>
28.15296 +    <para id="x_534">Once you've enabled the extension, you will have a new
28.15297 +      command available, named <command role="hg-ext-patchbomb" moreinfo="none">email</command>.</para>
28.15298 +
28.15299 +    <para id="x_535">The safest and best way to invoke the <command role="hg-ext-patchbomb" moreinfo="none">email</command> command is to
28.15300 +      <emphasis>always</emphasis> run it first with the <option role="hg-ext-patchbomb-cmd-email-opt">hg -n</option> option.
28.15301 +      This will show you what the command <emphasis>would</emphasis>
28.15302 +      send, without actually sending anything.  Once you've had a
28.15303 +      quick glance over the changes and verified that you are sending
28.15304 +      the right ones, you can rerun the same command, with the <option role="hg-ext-patchbomb-cmd-email-opt">hg -n</option> option
28.15305 +      removed.</para>
28.15306 +
28.15307 +    <para id="x_536">The <command role="hg-ext-patchbomb" moreinfo="none">email</command> command
28.15308 +      accepts the same kind of revision syntax as every other
28.15309 +      Mercurial command.  For example, this command will send every
28.15310 +      revision between 7 and <literal moreinfo="none">tip</literal>, inclusive.</para>
28.15311 +    <programlisting format="linespecific">hg email -n 7:tip</programlisting>
28.15312 +    <para id="x_537">You can also specify a <emphasis>repository</emphasis> to
28.15313 +      compare with.  If you provide a repository but no revisions, the
28.15314 +      <command role="hg-ext-patchbomb" moreinfo="none">email</command> command will
28.15315 +      send all revisions in the local repository that are not present
28.15316 +      in the remote repository.  If you additionally specify revisions
28.15317 +      or a branch name (the latter using the <option role="hg-ext-patchbomb-cmd-email-opt">hg -b</option> option),
28.15318 +      this will constrain the revisions sent.</para>
28.15319 +
28.15320 +    <para id="x_538">It's perfectly safe to run the <command role="hg-ext-patchbomb" moreinfo="none">email</command> command without the
28.15321 +      names of the people you want to send to: if you do this, it will
28.15322 +      just prompt you for those values interactively.  (If you're
28.15323 +      using a Linux or Unix-like system, you should have enhanced
28.15324 +      <literal moreinfo="none">readline</literal>-style editing capabilities when
28.15325 +      entering those headers, too, which is useful.)</para>
28.15326 +
28.15327 +    <para id="x_539">When you are sending just one revision, the <command role="hg-ext-patchbomb" moreinfo="none">email</command> command will by
28.15328 +      default use the first line of the changeset description as the
28.15329 +      subject of the single email message it sends.</para>
28.15330 +
28.15331 +    <para id="x_53a">If you send multiple revisions, the <command role="hg-ext-patchbomb" moreinfo="none">email</command> command will usually
28.15332 +      send one message per changeset.  It will preface the series with
28.15333 +      an introductory message, in which you should describe the
28.15334 +      purpose of the series of changes you're sending.</para>
28.15335 +
28.15336 +    <sect2>
28.15337 +      <title>Changing the behavior of patchbombs</title>
28.15338 +
28.15339 +      <para id="x_53b">Not every project has exactly the same conventions for
28.15340 +	sending changes in email; the <literal role="hg-ext" moreinfo="none">patchbomb</literal> extension tries to
28.15341 +	accommodate a number of variations through command line
28.15342 +	options.</para>
28.15343 +      <itemizedlist>
28.15344 +	<listitem><para id="x_53c">You can write a subject for the introductory
28.15345 +	    message on the command line using the <option role="hg-ext-patchbomb-cmd-email-opt">hg -s</option>
28.15346 +	    option.  This takes one argument, the text of the subject
28.15347 +	    to use.</para>
28.15348 +	</listitem>
28.15349 +	<listitem><para id="x_53d">To change the email address from which the
28.15350 +	    messages originate, use the <option role="hg-ext-patchbomb-cmd-email-opt">hg -f</option>
28.15351 +	    option.  This takes one argument, the email address to
28.15352 +	    use.</para>
28.15353 +	</listitem>
28.15354 +	<listitem><para id="x_53e">The default behavior is to send unified diffs
28.15355 +	    (see <xref linkend="sec:mq:patch"/> for a
28.15356 +	    description of the
28.15357 +	    format), one per message.  You can send a binary bundle
28.15358 +	    instead with the <option role="hg-ext-patchbomb-cmd-email-opt">hg -b</option>
28.15359 +	    option.</para>
28.15360 +	</listitem>
28.15361 +	<listitem><para id="x_53f">Unified diffs are normally prefaced with a
28.15362 +	    metadata header.  You can omit this, and send unadorned
28.15363 +	    diffs, with the <option role="hg-ext-patchbomb-cmd-email-opt">hg
28.15364 +	      --plain</option> option.</para>
28.15365 +	</listitem>
28.15366 +	<listitem><para id="x_540">Diffs are normally sent <quote>inline</quote>,
28.15367 +	    in the same body part as the description of a patch.  This
28.15368 +	    makes it easiest for the largest number of readers to
28.15369 +	    quote and respond to parts of a diff, as some mail clients
28.15370 +	    will only quote the first MIME body part in a message. If
28.15371 +	    you'd prefer to send the description and the diff in
28.15372 +	    separate body parts, use the <option role="hg-ext-patchbomb-cmd-email-opt">hg -a</option>
28.15373 +	    option.</para>
28.15374 +	</listitem>
28.15375 +	<listitem><para id="x_541">Instead of sending mail messages, you can
28.15376 +	    write them to an <literal moreinfo="none">mbox</literal>-format mail
28.15377 +	    folder using the <option role="hg-ext-patchbomb-cmd-email-opt">hg -m</option>
28.15378 +	    option.  That option takes one argument, the name of the
28.15379 +	    file to write to.</para>
28.15380 +	</listitem>
28.15381 +	<listitem><para id="x_542">If you would like to add a
28.15382 +	    <command moreinfo="none">diffstat</command>-format summary to each patch,
28.15383 +	    and one to the introductory message, use the <option role="hg-ext-patchbomb-cmd-email-opt">hg -d</option>
28.15384 +	    option.  The <command moreinfo="none">diffstat</command> command displays
28.15385 +	    a table containing the name of each file patched, the
28.15386 +	    number of lines affected, and a histogram showing how much
28.15387 +	    each file is modified.  This gives readers a qualitative
28.15388 +	    glance at how complex a patch is.</para>
28.15389 +	</listitem></itemizedlist>
28.15390 +
28.15391 +    </sect2>
28.15392 +  </sect1>
28.15393 +</chapter>
28.15394 +
28.15395 +<!--
28.15396 +local variables: 
28.15397 +sgml-parent-document: ("00book.xml" "book" "chapter")
28.15398 +end:
28.15399 +-->
28.15400 +
28.15401 +  <!-- BEGIN appA -->
28.15402 +  
28.15403 +
28.15404 +<appendix id="svn">
28.15405 +  <?dbhtml filename="migrating-to-mercurial.html"?>
28.15406 +<title>Migrer vers Mercurial</title>
28.15407 +
28.15408 +  <para id="x_6e1">Une manière courante de s'essayer à un nouveau
28.15409 +  gestionnaire de révisions est d'expérimenter en migrant un
28.15410 +  projet existant, plutôt que le faire avec un nouveau projet.
28.15411 +  </para>
28.15412 +
28.15413 +  <para id="x_6e2">Dans cette annexe, nous discuterons comment importer
28.15414 +  l'historique d'un projet dans Mercurial, et à quoi faire attention
28.15415 +  si vous êtes habitués à un autre outil de gestion de révisions.
28.15416 +   </para>
28.15417 +
28.15418 +  <sect1>
28.15419 +    <title>Importer l'historique depuis un autre système</title>
28.15420 +
28.15421 +    <para id="x_6e3">Mercurial est livré avec une extension nommée
28.15422 +      <literal moreinfo="none">convert</literal>, qui permet d'importer un historique
28.15423 +      depuis les gestionnaire de révisions les plus courants. Au moment de 
28.15424 +      l'écriture de ce livre, il pouvait importer l'historique depuis:
28.15425 +      </para>
28.15426 +    <itemizedlist>
28.15427 +      <listitem>
28.15428 +	<para id="x_6e4">Subversion</para>
28.15429 +      </listitem>
28.15430 +      <listitem>
28.15431 +	<para id="x_6e5">CVS</para>
28.15432 +      </listitem>
28.15433 +      <listitem>
28.15434 +	<para id="x_6e6">git</para>
28.15435 +      </listitem>
28.15436 +      <listitem>
28.15437 +	<para id="x_6e7">Darcs</para>
28.15438 +      </listitem>
28.15439 +      <listitem>
28.15440 +	<para id="x_6e8">Bazaar</para>
28.15441 +      </listitem>
28.15442 +      <listitem>
28.15443 +	<para id="x_6e9">Monotone</para>
28.15444 +      </listitem>
28.15445 +      <listitem>
28.15446 +	<para id="x_6ea">GNU Arch</para>
28.15447 +      </listitem>
28.15448 +      <listitem>
28.15449 +	<para id="x_6eb">Mercurial</para>
28.15450 +      </listitem>
28.15451 +    </itemizedlist>
28.15452 +
28.15453 +    <para id="x_6ec">(Pour savoir pourquoi Mercurial lui même est supporté
28.15454 +    comme source, voir <xref linkend="svn.filemap"/>.)</para>
28.15455 +
28.15456 +    <para id="x_6ed">Vous pouvez activer l'extension de la manière
28.15457 +    habituelle, en éditant votre fichier <filename moreinfo="none">~/.hgrc</filename></para>
28.15458 +
28.15459 +    <programlisting format="linespecific">[extensions]
28.15460 +convert =</programlisting>
28.15461 +
28.15462 +    <para id="x_6ee">Ceci rendra la commande <command moreinfo="none">hg convert</command>
28.15463 +    disponible. La commande est facile à utiliser. Par exemple, la 
28.15464 +    commande suivante va importer l'historique Subversion du <emphasis remap="it">framework</emphasis> de test <quote>Nose Unit</quote> dans Mercurial.
28.15465 +      </para>
28.15466 +
28.15467 +    <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg convert http://python-nose.googlecode.com/svn/trunk</userinput></screen>
28.15468 +
28.15469 +    <para id="x_6ef">L'extension <literal moreinfo="none">convert</literal> opère de 
28.15470 +    manière incrémentale. En d'autres mots, après une première exécution de
28.15471 +    la commande <command moreinfo="none">hg convert</command>, les exécutions ultérieures
28.15472 +    importeront les révisions ultérieures à l'exécution précédente.
28.15473 +    La conversion incrémentale ne réussira que si
28.15474 +    vous exécutez <command moreinfo="none">hg convert</command> dans le même dépôt que vous
28.15475 +    aviez utilisé à l'origine, ceci parce que l'extension <literal moreinfo="none">convert</literal> 
28.15476 +    sauvegarde un certain nombre de méta-données privées dans le fichier
28.15477 +    <filename moreinfo="none">.hg/shamap</filename> (non versioné) au sein du dépôt cible.
28.15478 +    </para>
28.15479 +
28.15480 +    <para id="x_707">Lorsque vous voulez faire des modifications en utilisant
28.15481 +    Mercurial, le mieux est de faire un clone de l'ensemble de l'arborescence 
28.15482 +    que vous souhaitez convertir, et de laisser l'arborescence d'origine pour
28.15483 +    de futures conversions incrémentales. C'est la manière la plus sûre pour vous laisser
28.15484 +    récupérer et fusionner les modifications futures depuis l'outil de gestion
28.15485 +    de révisions dans votre nouveau dépôt Mercurial.</para>
28.15486 +
28.15487 +    <sect2>
28.15488 +      <title>Convertir plusieurs branches</title>
28.15489 +
28.15490 +      <para id="x_708">La commande <command moreinfo="none">hg convert</command> citée 
28.15491 +      ci-dessus convertit seulement l'historique de la <literal moreinfo="none">branche
28.15492 +      principale (trunk)</literal> du dépôt Subversion. Si nous utilisons
28.15493 +      à la place l'URL <literal moreinfo="none">http://python-nose.googlecode.com/svn</literal>,
28.15494 +      Mercurial va automatiquement détecter la  
28.15495 +      <literal moreinfo="none">branche principale (trunk)</literal>, les <literal moreinfo="none">étiquettes 
28.15496 +      (tags)</literal>, et les <literal moreinfo="none">branches</literal>  que les dépôts
28.15497 +      Subversion utilisent généralement, et les importera chacun dans
28.15498 +      une branche Mercurial distincte.</para>
28.15499 +
28.15500 +      <para id="x_709">Par défaut, chaque branche Subversion importée 
28.15501 +     dans Mercurial se voit attribuer un nom de branche. Une fois la
28.15502 +     conversion achevée, vous pouvez obtenir la liste des noms des branches 
28.15503 +     actives dans le dépôt Mercurial en utilisant la commande
28.15504 +     <command moreinfo="none">hg branches -a</command>. Si vous préférez importer les 
28.15505 +     branches Subversion sans noms, ajoutez l'option <option>--config
28.15506 +     convert.hg.usebranches=false</option> à la commande 
28.15507 +     <command moreinfo="none">hg convert</command>.</para>
28.15508 +
28.15509 +      <para id="x_70a">Une fois votre arborescence convertie, 
28.15510 +      si vous souhaitez travailler selon la pratique habituelle sous Mercurial
28.15511 +      avec une arborescence qui ne contient qu'une seule branche, vous pouvez cloner
28.15512 +      cette seule branche en utilisant 
28.15513 +      <command moreinfo="none">hg clone -r nomdemabranche</command>.</para>
28.15514 +    </sect2>
28.15515 +
28.15516 +    <sect2>
28.15517 +      <title>Associer les noms d'utilisateurs</title>
28.15518 +
28.15519 +      <para id="x_6f0">Certains outils de gestion de révisions
28.15520 +      ne sauvegardent, avec les modifications, que les noms 
28.15521 +      d'utilisateurs raccourcis. Ceux-ci peuvent être difficiles à 
28.15522 +      interpréter. La norme avec Mercurial est de sauvegarder le 
28.15523 +      nom du <emphasis remap="it">committeur</emphasis> et son adresse
28.15524 +      mail, ce qui est beaucoup plus utile pour discuter avec lui
28.15525 +      par la suite.</para>
28.15526 +
28.15527 +      <para id="x_6f1">Si vous convertissez une arborescence depuis
28.15528 +      un gestionnaire de révisions qui utilise seulement les noms
28.15529 +      raccourcis, vous pouvez associer ces noms à des équivalents 
28.15530 +      plus détaillés en passant l'option <option>--authors</option>
28.15531 +      à la commande <command moreinfo="none">hg convert</command>. Cette option
28.15532 +      attend un fichier qui contient des entrées sous la forme suivante:
28.15533 +      </para>
28.15534 +
28.15535 +      <programlisting format="linespecific">arist = Aristotle &lt;aristotle@phil.example.gr&gt;
28.15536 +soc = Socrates &lt;socrates@phil.example.gr&gt;</programlisting>
28.15537 +
28.15538 +      <para id="x_6f2">Quand <literal moreinfo="none">convert</literal> trouve une
28.15539 +      modification associée au nom <literal moreinfo="none">arist</literal> dans le
28.15540 +      dépôt de source, il va utiliser le nom <literal moreinfo="none">Aristotle
28.15541 +      &lt;aristotle@phil.example.gr&gt;</literal> dans les révisions
28.15542 +      Mercurial. Si aucune correspondance n'est trouvé, il utilise
28.15543 +      le nom tel quel.</para>
28.15544 +    </sect2>
28.15545 +
28.15546 +    <sect2 id="svn.filemap">
28.15547 +      <title>Nettoyer l'arboresence</title>
28.15548 +
28.15549 +      <para id="x_6f3">Tous les projets n'ont pas un historique parfait.
28.15550 +      Il peut y avoir des répertoires qui n'auraient jamais dû être ajoutés,
28.15551 +      un fichier qui est trop volumineux, ou même une partie de la
28.15552 +      hiérarchie qui devrait être réorganisée.</para>
28.15553 +
28.15554 +      <para id="x_6f4">L'extension <literal moreinfo="none">convert</literal> permet
28.15555 +      d'utiliser un <quote>fichier d'association</quote> qui peut 
28.15556 +      réorganiser les fichiers et les répertoires dans un projet lors de
28.15557 +      l'importation de son historique. Ceci est utile non seulement quand vous
28.15558 +      importez l'historique d'un autre gestionnaire de révisions, mais
28.15559 +      aussi pour nettoyer ou réorganiser l'arborescence d'un projet
28.15560 +      Mercurial.</para>
28.15561 +
28.15562 +      <para id="x_6f5">Pour indiquer le fichier d'association, on utilise
28.15563 +      l'option <option>--filemap</option> en lui fournissant un nom de
28.15564 +      fichier. Le fichier d'association contient des lignes de la forme
28.15565 +      suivante :</para>
28.15566 +
28.15567 +      <programlisting format="linespecific"># Ceci est un commentaire.
28.15568 +# Les lignes vides sont ignorées.
28.15569 +
28.15570 +include path/to/file
28.15571 +
28.15572 +exclude path/to/file
28.15573 +
28.15574 +rename from/some/path to/some/other/place
28.15575 +</programlisting>
28.15576 +      
28.15577 +      <para id="x_6f6">La directive <literal moreinfo="none">include</literal> inclut un
28.15578 +      fichier, ou l'ensemble des fichiers d'un répertoire, dans le dépôt
28.15579 +      de destination. La directive <literal moreinfo="none">exclude</literal> omet les
28.15580 +      fichiers ou répertoires du dépôt. Ceci inclut aussi les autres
28.15581 +      fichiers et répertoires qui ne sont pas explicitement inclus.
28.15582 +      La directive <literal moreinfo="none">exclude</literal> entraine l'omission
28.15583 +      des fichiers ou répertoires, et autres fichiers qui ne sont pas
28.15584 +      explicitement inclus.</para>
28.15585 +
28.15586 +      <para id="x_6f7">Pour déplacer un fichier ou un répertoire d'un
28.15587 +      emplacement à un autre, utilisez la directive
28.15588 +      <literal moreinfo="none">rename</literal>. Si vous avez besoin de déplacer un 
28.15589 +      fichier ou un répertoire depuis un sous répertoire dans la racine
28.15590 +      du dépôt, utilisez <literal moreinfo="none">.</literal> comme second argument de 
28.15591 +      la directive <literal moreinfo="none">rename</literal>.</para>
28.15592 +    </sect2>
28.15593 +
28.15594 +    <sect2>
28.15595 +      <title>Améliorer les performances de la conversion Subversion</title>
28.15596 +
28.15597 +      <para id="x_70b">Vous aurez souvent besoin de plusieurs essais
28.15598 +      avant d'arriver à la parfaite combinaison de fichier d'association de fichiers,
28.15599 +      de fichier d'association de noms d'utilisateurs et des autres paramètres. Or,
28.15600 +      convertir un dépôt Mercurial via un protocole comme <literal moreinfo="none">ssh</literal>
28.15601 +      ou <literal moreinfo="none">http</literal> peut être des milliers de fois plus long
28.15602 +      que ce dont le système d'exploitation est en fait capable de faire,
28.15603 +      à cause des latence réseau. Ceci peut rendre la conception de cette
28.15604 +      combinaison parfaite très douloureuse.</para>
28.15605 +
28.15606 +      <para id="x_70c">La commande <ulink url="http://svn.collab.net/repos/svn/trunk/notes/svnsync.txt"><command moreinfo="none">svnsync</command></ulink> 
28.15607 +	peut grandement améliorer la vitesse de conversion d'un dépôt
28.15608 +        Subversion. Il s'agit d'un programme de miroir de dépôt Subversion
28.15609 +        en lecture seule. L'idée est de créer un miroir local d'une
28.15610 +        arborescence Subversion, puis de convertir ce miroir en dépôt
28.15611 +        Mercurial.</para>
28.15612 +      
28.15613 +      <para id="x_70d">Supposez que nous voulions convertir le dépôt 
28.15614 +      Subversion du populaire projet Memcached en une arborescence Mercurial.
28.15615 +      Tout d'abord, nous créons un dépôt Subversion local.</para>
28.15616 +
28.15617 +      <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">svnadmin create memcached-mirror</userinput></screen>
28.15618 +
28.15619 +      <para id="x_70e">Puis, nous allons mettre en place un <quote>hook</quote> Subversion
28.15620 +      dont <command moreinfo="none">svnsync</command> a besoin.</para>
28.15621 +
28.15622 +      <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo '#!/bin/sh' &gt; memcached-mirror/hooks/pre-revprop-change</userinput>
28.15623 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">chmod +x memcached-mirror/hooks/pre-revprop-change</userinput></screen>
28.15624 +
28.15625 +      <para id="x_70f">Nous initialisons ensuite <command moreinfo="none">svnsync</command> dans ce
28.15626 +      dépôt.</para>
28.15627 +
28.15628 +      <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">svnsync --init file://`pwd`/memcached-mirror \
28.15629 +  http://code.sixapart.com/svn/memcached</userinput></screen>
28.15630 +
28.15631 +      <para id="x_710">La prochaine étape est de commencer le processus de
28.15632 +      mirroring de <command moreinfo="none">svnsync</command>.</para>
28.15633 +
28.15634 +      <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">svnsync sync file://`pwd`/memcached-mirror</userinput></screen>
28.15635 +
28.15636 +      <para id="x_711">Enfin, nous importons l'historique de notre dépôt
28.15637 +      local Subversion dans Mercurial.</para>
28.15638 +
28.15639 +      <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg convert memcached-mirror</userinput></screen>
28.15640 +      
28.15641 +      <para id="x_712">Nous pouvons utiliser ce processus de manière
28.15642 +      incrémentale, si le dépôt Subversion est toujours en activité.
28.15643 +      Il suffit d'exécuter de nouveau <command moreinfo="none">svnsync</command> pour
28.15644 +      récupérer les récentes modifications dans notre miroir, puis <command moreinfo="none">hg 
28.15645 +      convert</command>
28.15646 +      les importe dans notre arborescence Mercurial.</para>
28.15647 +
28.15648 +      <para id="x_713">Il y a deux avantages à utiliser un import à deux
28.15649 +      étages comme avec <command moreinfo="none">svnsync</command>. Le premier
28.15650 +      est qu'il utilise du code de synchronisation réseau de Subversion 
28.15651 +      plus efficace que la commande <command moreinfo="none">hg convert</command>,
28.15652 +      et donc transfère moins de données par le réseau. Le deuxième
28.15653 +      est que l'import depuis un dépôt Subversion local est si rapide que
28.15654 +      vous pouvez peaufiner et réitérer les paramètres de conversion de 
28.15655 +      ce dernier sans souffrir de la qualité de la connexion réseau.</para>
28.15656 +    </sect2>
28.15657 +  </sect1>
28.15658 +
28.15659 +  <sect1>
28.15660 +    <title>Migrer depuis Subversion</title>
28.15661 +
28.15662 +    <para id="x_6f8">Subversion est le système de gestion de versions
28.15663 +    open source le plus populaire aujourd'hui. Bien qu'il y ait des
28.15664 +    différences entre Mercurial et Subversion, faire la transition de
28.15665 +    l'un à l'autre n'est pas très difficile. Les deux disposent en effet 
28.15666 +    de jeux de commandes similaires et d'interfaces similaires.</para>
28.15667 +
28.15668 +    <sect2>
28.15669 +      <title>Différences philosophiques</title>
28.15670 +
28.15671 +      <para id="x_6f9">La différence fondamentale entre Subversion et
28.15672 +      Mercurial est bien évidement que Subversion est centralisé, alors 
28.15673 +      que Mercurial est distribué. Puisque que Mercurial enregistre tout
28.15674 +      l'historique d'un projet sur votre disque dur local, il n'a besoin
28.15675 +      d'effectuer des accès au réseau que lorsque vous voulez
28.15676 +      explicitement communiquer avec un autre dépôt. Subversion, par contre,
28.15677 +      ne conserve que peu d'informations localement, et le client
28.15678 +      doit donc communiquer avec le serveur central pour la
28.15679 +      plupart des opérations communes.</para>
28.15680 +
28.15681 +      <para id="x_6fa">Subversion s'en tire plus ou moins bien sans notion
28.15682 +      de branche réellement bien définie : quelle portion de l'espace de nommage
28.15683 +      du serveur est une branche est une simple question de convention, le
28.15684 +      logiciel n'imposant rien à ce sujet. Mercurial considère
28.15685 +      un dépôt comme un élément de la gestion des branches.</para>
28.15686 +      
28.15687 +      <sect3>
28.15688 +	<title>Portée des commandes</title>
28.15689 +
28.15690 +	<para id="x_6fb">Puisque que Subversion ne sait pas réellement
28.15691 +        quelle partie de son espace de nommage est en fait une branche, il
28.15692 +        traite la plupart des commandes comme des requêtes à exécuter sur le
28.15693 +        répertoire où vous vous situez, et ses sous répertoires. Par exemple,
28.15694 +        si vous exécutez <command moreinfo="none">svn log</command>, vous verrez l'historique 
28.15695 +        de la partie de l'arborescence où vous vous situez, et non de la
28.15696 +        hiérarchie entière.</para>
28.15697 +
28.15698 +	<para id="x_6fc">Les commandes de Mercurial ont un comportement
28.15699 +        différent : toutes les commandes s'appliquent à l'ensemble de l'arborescence
28.15700 +        du dépôt. Exécutez la commande <command moreinfo="none">hg log</command> et elle vous
28.15701 +        donnera l'historique de l'ensemble de l'arborescence, quel que soit le
28.15702 +        sous-répertoire où vous vous situez. Si
28.15703 +        vous souhaitez obtenir l'historique d'un répertoire ou seulement d'un
28.15704 +        fichier, ajouter simplement le nom de celui-ci à la commande, par
28.15705 +        exemple <command moreinfo="none">hg log src</command>.</para>
28.15706 +
28.15707 +	<para id="x_6fd">De ma propre expérience, cette différence dans leur
28.15708 +        comportement par défaut est probablement ce qui risque de vous
28.15709 +        surprendre le plus si vous passez régulièrement d'un outil à l'autre.</para>
28.15710 +      </sect3>
28.15711 +
28.15712 +      <sect3>
28.15713 +	<title>Opération multi utilisateur et sécurité</title>
28.15714 +
28.15715 +	<para id="x_6fe">Avec Subversion, il est normal (bien que légèrement
28.15716 +        désapprouvé) que différentes personnes collaborent sur une seule
28.15717 +        branche. Si Alice et Bob travaillent ensemble, et Alice ajoute ses
28.15718 +        modifications à leur branche partagée, Bob doit alors mettre à jour
28.15719 +        sa vue de la branche avant de pouvoir appliquer un commit.
28.15720 +        Puisqu'il n'a, à ce moment, pas effectué de commit
28.15721 +        des modifications qu'il a faites, il se peut qu'il ne corrompe 
28.15722 +        ou ne perde
28.15723 +        ses modifications pendant ou après la mise à jour.</para>
28.15724 +
28.15725 +	<para id="x_6ff">Mercurial encourage, à l'inverse, un modèle 
28.15726 +        "commit-puis-merge". Avant de récupérer des modifications depuis le 
28.15727 +        serveur, ou avant d'y envoyer les siennes, Bob enregistre ses 
28.15728 +        modifications de manière locale en appliquant un commit. C'est à dire
28.15729 +        que si Alice avait envoyé ses modifications sur le serveur avant
28.15730 +        que Bob n'envoie les siennes, ce dernier ne pourra le faire
28.15731 +        qu'après avoir récupéré et fusionné celles d'Alice avec les siennes. 
28.15732 +        Si Bob fait alors une
28.15733 +        erreur lors de la fusion, il pourra toujours restaurer sa version, pour
28.15734 +        laquelle il avait appliqué le commit.</para>
28.15735 +          
28.15736 +	<para id="x_700">Il est important de souligner qu'il s'agit de la
28.15737 +        manière habituelle de travailler avec ces outils. Subversion propose
28.15738 +        une manière plus sûre de "travailler-dans-votre-propre-branche", mais elle
28.15739 +        est assez complexe pour que, en pratique, elle ne soit que rarement utilisé.
28.15740 +        Mercurial propose de son côté un mode un peu moins sûr, permettant de
28.15741 +        récupérer des modifications par dessus des modifications non
28.15742 +        committées, qui reste toutefois très peu répandu.</para> 
28.15743 +      </sect3>
28.15744 +
28.15745 +      <sect3>
28.15746 +	<title>Publication vs changement locaux</title>
28.15747 +
28.15748 +	<para id="x_701">Une commande Subversion <command moreinfo="none">svn
28.15749 +        commit</command> publie immédiatement les modifications sur le
28.15750 +        serveur, où elles peuvent être vu par n'importe qui doté d'un privilège
28.15751 +        de lecture.</para>
28.15752 +
28.15753 +	<para id="x_702">Avec Mercurial, les modifications sont toujours d'abord
28.15754 +        enregistrées localement, et doivent être par la suite transférés par
28.15755 +        la commande <command moreinfo="none">hg push</command>.</para>
28.15756 +
28.15757 +	<para id="x_703">Chaque approche a ses avantages et ses inconvénients.
28.15758 +        Le modèle Subversion implique que les modifications soient publiées, et
28.15759 +        donc disponibles immédiatement. D'un autre coté, cela implique aussi
28.15760 +        que, pour pouvoir utiliser le logiciel normalement, un utilisateur doit 
28.15761 +        avoir les droits d'écriture dans le dépôt, et ce privilège n'est pas concédé 
28.15762 +        facilement par la plupart des projets Open Source.</para>
28.15763 +
28.15764 +	<para id="x_704">L'approche de Mercurial permet à quiconque de faire
28.15765 +        un clone du dépôt et d'y ajouter ses modifications sans jamais avoir
28.15766 +        besoin de la permission de quiconque, et l'on peut même publier ses
28.15767 +        modifications et continuer à participer comme on le désire. Toutefois, la
28.15768 +        distinction entre les commits et le transfert de ces derniers présente
28.15769 +        le risque que quelqu'un applique ses modifications par un commit local
28.15770 +        sur son portable et parte se promener pendant quelques jours en ayant
28.15771 +        oublié de les transférer, ce qui peut, dans certains rares cas,
28.15772 +        bloquer temporairement ses collaborateurs.</para>
28.15773 +      </sect3>
28.15774 +    </sect2>
28.15775 +
28.15776 +    <sect2>
28.15777 +      <title>Références des commandes</title>
28.15778 +
28.15779 +      <table>
28.15780 +	<title>Commandes Subversion et leurs équivalents Mercurial</title>
28.15781 +	<tgroup cols="3">
28.15782 +	  <thead>
28.15783 +	    <row>
28.15784 +	      <entry>Subversion</entry>
28.15785 +	      <entry>Mercurial</entry>
28.15786 +	      <entry>Notes</entry>
28.15787 +	    </row>
28.15788 +	  </thead>
28.15789 +	  <tbody>
28.15790 +	    <row>
28.15791 +	      <entry><command moreinfo="none">svn add</command></entry>
28.15792 +	      <entry><command moreinfo="none">hg add</command></entry>
28.15793 +	      <entry/>
28.15794 +	    </row>
28.15795 +	    <row>
28.15796 +	      <entry><command moreinfo="none">svn blame</command></entry>
28.15797 +	      <entry><command moreinfo="none">hg annotate</command></entry>
28.15798 +	      <entry/>
28.15799 +	    </row>
28.15800 +	    <row>
28.15801 +	      <entry><command moreinfo="none">svn cat</command></entry>
28.15802 +	      <entry><command moreinfo="none">hg cat</command></entry>
28.15803 +	      <entry/>
28.15804 +	    </row>
28.15805 +	    <row>
28.15806 +	      <entry><command moreinfo="none">svn checkout</command></entry>
28.15807 +	      <entry><command moreinfo="none">hg clone</command></entry>
28.15808 +	      <entry/>
28.15809 +	    </row>
28.15810 +	    <row>
28.15811 +	      <entry><command moreinfo="none">svn cleanup</command></entry>
28.15812 +	      <entry>n/a</entry>
28.15813 +	      <entry>Aucun nettoyage nécessaire.</entry>
28.15814 +	    </row>
28.15815 +	    <row>
28.15816 +	      <entry><command moreinfo="none">svn commit</command></entry>
28.15817 +	      <entry><command moreinfo="none">hg commit</command>; <command moreinfo="none">hg
28.15818 +		  push</command></entry>
28.15819 +	      <entry><command moreinfo="none">hg push</command> publie les modifications
28.15820 +              après un commit.</entry>
28.15821 +	    </row>
28.15822 +	    <row>
28.15823 +	      <entry><command moreinfo="none">svn copy</command></entry>
28.15824 +	      <entry><command moreinfo="none">hg clone</command></entry>
28.15825 +	      <entry>Pour créer une nouvelle branche</entry>
28.15826 +	    </row>
28.15827 +	    <row>
28.15828 +	      <entry><command moreinfo="none">svn copy</command></entry>
28.15829 +	      <entry><command moreinfo="none">hg copy</command></entry>
28.15830 +	      <entry>Pour copier des fichiers ou des répertoires</entry>
28.15831 +	    </row>
28.15832 +	    <row>
28.15833 +	      <entry><command moreinfo="none">svn delete</command> (<command moreinfo="none">svn
28.15834 +		  remove</command>)</entry>
28.15835 +	      <entry><command moreinfo="none">hg remove</command></entry>
28.15836 +	      <entry/>
28.15837 +	    </row>
28.15838 +	    <row>
28.15839 +	      <entry><command moreinfo="none">svn diff</command></entry>
28.15840 +	      <entry><command moreinfo="none">hg diff</command></entry>
28.15841 +	      <entry/>
28.15842 +	    </row>
28.15843 +	    <row>
28.15844 +	      <entry><command moreinfo="none">svn export</command></entry>
28.15845 +	      <entry><command moreinfo="none">hg archive</command></entry>
28.15846 +	      <entry/>
28.15847 +	    </row>
28.15848 +	    <row>
28.15849 +	      <entry><command moreinfo="none">svn help</command></entry>
28.15850 +	      <entry><command moreinfo="none">hg help</command></entry>
28.15851 +	      <entry/>
28.15852 +	    </row>
28.15853 +	    <row>
28.15854 +	      <entry><command moreinfo="none">svn import</command></entry>
28.15855 +	      <entry><command moreinfo="none">hg addremove</command>; <command moreinfo="none">hg
28.15856 +		  commit</command></entry>
28.15857 +	      <entry/>
28.15858 +	    </row>
28.15859 +	    <row>
28.15860 +	      <entry><command moreinfo="none">svn info</command></entry>
28.15861 +	      <entry><command moreinfo="none">hg parents</command></entry>
28.15862 +	      <entry>Affiche la version sur la base de laquelle on travaille</entry>
28.15863 +	    </row>
28.15864 +	    <row>
28.15865 +	      <entry><command moreinfo="none">svn info</command></entry>
28.15866 +	      <entry><command moreinfo="none">hg showconfig
28.15867 +		  paths.default</command></entry>
28.15868 +	      <entry>Affiche de quelle URL est extrait ce dépôt</entry>
28.15869 +	    </row>
28.15870 +	    <row>
28.15871 +	      <entry><command moreinfo="none">svn list</command></entry>
28.15872 +	      <entry><command moreinfo="none">hg manifest</command></entry>
28.15873 +	      <entry/>
28.15874 +	    </row>
28.15875 +	    <row>
28.15876 +	      <entry><command moreinfo="none">svn log</command></entry>
28.15877 +	      <entry><command moreinfo="none">hg log</command></entry>
28.15878 +	      <entry/>
28.15879 +	    </row>
28.15880 +	    <row>
28.15881 +	      <entry><command moreinfo="none">svn merge</command></entry>
28.15882 +	      <entry><command moreinfo="none">hg merge</command></entry>
28.15883 +	      <entry/>
28.15884 +	    </row>
28.15885 +	    <row>
28.15886 +	      <entry><command moreinfo="none">svn mkdir</command></entry>
28.15887 +	      <entry>n/a</entry>
28.15888 +	      <entry>Mercurial ne versionne pas les répertoires</entry>
28.15889 +	    </row>
28.15890 +	    <row>
28.15891 +	      <entry><command moreinfo="none">svn move</command> (<command moreinfo="none">svn
28.15892 +		  rename</command>)</entry>
28.15893 +	      <entry><command moreinfo="none">hg rename</command></entry>
28.15894 +	      <entry/>
28.15895 +	    </row>
28.15896 +	    <row>
28.15897 +	      <entry><command moreinfo="none">svn resolved</command></entry>
28.15898 +	      <entry><command moreinfo="none">hg resolve -m</command></entry>
28.15899 +	      <entry/>
28.15900 +	    </row>
28.15901 +	    <row>
28.15902 +	      <entry><command moreinfo="none">svn revert</command></entry>
28.15903 +	      <entry><command moreinfo="none">hg revert</command></entry>
28.15904 +	      <entry/>
28.15905 +	    </row>
28.15906 +	    <row>
28.15907 +	      <entry><command moreinfo="none">svn status</command></entry>
28.15908 +	      <entry><command moreinfo="none">hg status</command></entry>
28.15909 +	      <entry/>
28.15910 +	    </row>
28.15911 +	    <row>
28.15912 +	      <entry><command moreinfo="none">svn update</command></entry>
28.15913 +	      <entry><command moreinfo="none">hg pull -u</command></entry>
28.15914 +	      <entry/>
28.15915 +	    </row>
28.15916 +	  </tbody>
28.15917 +	</tgroup>
28.15918 +      </table>
28.15919 +    </sect2>
28.15920 +  </sect1>
28.15921 +
28.15922 +  <sect1>
28.15923 +    <title>Conseils utiles pour les débutants</title>
28.15924 +
28.15925 +    <para id="x_705">Avec la plupart des gestionnaire de versions, afficher
28.15926 +    un diff associé à une révision peut être assez douloureux. Par exemple,
28.15927 +    avec Subversion, pour voir ce qui a été modifiée dans la révision 104654,
28.15928 +    vous devez saisir <command moreinfo="none">svn diff -r104653:104654</command>. Mercurial
28.15929 +    élimine le besoin de saisir l'identifiant d'une révision deux fois dans
28.15930 +    ce cas classique. Pour un simple diff, <command moreinfo="none">hg
28.15931 +    export 104654</command> suffit. Pour obtenir une entrée du journal suivie d'un diff,
28.15932 +    <command moreinfo="none">hg log -r104654 -p</command>.</para>
28.15933 +
28.15934 +    <para id="x_706">Quand vous exécutez la commande <command moreinfo="none">hg status</command>
28.15935 +    sans aucun argument, elle affiche l'état de l'ensemble de l'arborescence,
28.15936 +    avec des chemins relatifs partant de la racine du dépôt. Ceci rend
28.15937 +    difficile de copier un nom de fichier depuis la sortie de la commande
28.15938 +    <command moreinfo="none">hg status</command> dans une autre ligne de commande. Si vous
28.15939 +    fournissez un fichier ou un répertoire à la commande <command moreinfo="none">hg
28.15940 +    status</command>, elle va afficher les chemins relatif depuis votre
28.15941 +    répertoire courant à la place. Ainsi, pour avoir un état sur l'ensemble
28.15942 +    de l'arborescence à l'aide  de <command moreinfo="none">hg status</command>, avec des
28.15943 +    chemins relatifs à votre répertoire courant, et non la racine du dépôt,
28.15944 +    ajoutez la sortie de <command moreinfo="none">hg root</command> à la commande
28.15945 +    <command moreinfo="none">hg status</command>. Vous pouvez le faire aisément sur un
28.15946 +    système Unix ainsi :</para>
28.15947 +
28.15948 +    <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status `hg root`</userinput></screen>
28.15949 +  </sect1>
28.15950 +</appendix>
28.15951 +
28.15952 +<!--
28.15953 +local variables: 
28.15954 +sgml-parent-document: ("00book.xml" "book" "appendix")
28.15955 +end:
28.15956 +-->
28.15957 +
28.15958 +  <!-- BEGIN appB -->
28.15959 +  <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
28.15960 +
28.15961 +<appendix id="chap:mqref">
28.15962 +  <?dbhtml filename="mercurial-queues-reference.html"?>
28.15963 +  <title>Mercurial Queues reference</title>
28.15964 +
28.15965 +  <sect1 id="sec:mqref:cmdref">
28.15966 +    <title>MQ command reference</title>
28.15967 +
28.15968 +    <para id="x_5e8">For an overview of the commands provided by MQ, use the
28.15969 +      command <command role="hg-cmd" moreinfo="none">hg help mq</command>.</para>
28.15970 +
28.15971 +    <sect2>
28.15972 +      <title><command role="hg-ext-mq" moreinfo="none">qapplied</command>—print
28.15973 +	applied patches</title>
28.15974 +
28.15975 +      <para id="x_5e9">The <command role="hg-ext-mq" moreinfo="none">qapplied</command> command
28.15976 +	prints the current stack of applied patches.  Patches are
28.15977 +	printed in oldest-to-newest order, so the last patch in the
28.15978 +	list is the <quote>top</quote> patch.</para>
28.15979 +
28.15980 +    </sect2>
28.15981 +    <sect2>
28.15982 +      <title><command role="hg-ext-mq" moreinfo="none">qcommit</command>—commit
28.15983 +	changes in the queue repository</title>
28.15984 +
28.15985 +      <para id="x_5ea">The <command role="hg-ext-mq" moreinfo="none">qcommit</command> command
28.15986 +	commits any outstanding changes in the <filename role="special" class="directory" moreinfo="none">.hg/patches</filename>
28.15987 +	repository.  This command only works if the <filename role="special" class="directory" moreinfo="none">.hg/patches</filename>
28.15988 +	directory is a repository, i.e. you created the directory
28.15989 +	using <command role="hg-cmd" moreinfo="none">hg qinit <option role="hg-ext-mq-cmd-qinit-opt">-c</option></command> or
28.15990 +	ran <command role="hg-cmd" moreinfo="none">hg init</command> in the directory
28.15991 +	after running <command role="hg-ext-mq" moreinfo="none">qinit</command>.</para>
28.15992 +
28.15993 +      <para id="x_5eb">This command is shorthand for <command role="hg-cmd" moreinfo="none">hg
28.15994 +	  commit --cwd .hg/patches</command>.</para>
28.15995 +    </sect2>
28.15996 +    <sect2>
28.15997 +	<title><command role="hg-ext-mq" moreinfo="none">qdelete</command>—delete a patch
28.15998 +	from the <filename role="special" moreinfo="none">series</filename>
28.15999 +	file</title>
28.16000 +
28.16001 +      <para id="x_5ec">The <command role="hg-ext-mq" moreinfo="none">qdelete</command> command
28.16002 +	removes the entry for a patch from the <filename role="special" moreinfo="none">series</filename> file in the <filename role="special" class="directory" moreinfo="none">.hg/patches</filename>
28.16003 +	directory.  It does not pop the patch if the patch is already
28.16004 +	applied.  By default, it does not delete the patch file; use
28.16005 +	the <option role="hg-ext-mq-cmd-qdel-opt">-f</option> option
28.16006 +	to do that.</para>
28.16007 +
28.16008 +      <para id="x_5ed">Options:</para>
28.16009 +      <itemizedlist>
28.16010 +	<listitem><para id="x_5ee"><option role="hg-ext-mq-cmd-qdel-opt">-f</option>: Delete the
28.16011 +	    patch file.</para>
28.16012 +	</listitem></itemizedlist>
28.16013 +
28.16014 +    </sect2>
28.16015 +    <sect2>
28.16016 +      <title><command role="hg-ext-mq" moreinfo="none">qdiff</command>—print a
28.16017 +	diff of the topmost applied patch</title>
28.16018 +
28.16019 +      <para id="x_5ef">The <command role="hg-ext-mq" moreinfo="none">qdiff</command> command
28.16020 +	prints a diff of the topmost applied patch. It is equivalent
28.16021 +	to <command role="hg-cmd" moreinfo="none">hg diff -r-2:-1</command>.</para>
28.16022 +
28.16023 +    </sect2>
28.16024 +    <sect2>
28.16025 +      <title><command role="hg-ext-mq" moreinfo="none">qfold</command>—move
28.16026 +	applied patches into repository history</title>
28.16027 +
28.16028 +      <para id="x_72d">The <command moreinfo="none">hg qfinish</command> command converts the
28.16029 +	specified applied patches into permanent changes by moving
28.16030 +	them out of MQ's control so that they will be treated as
28.16031 +	normal repository history.</para>
28.16032 +    </sect2>
28.16033 +
28.16034 +    <sect2>
28.16035 +      <title><command role="hg-ext-mq" moreinfo="none">qfold</command>—merge
28.16036 +	(<quote>fold</quote>) several patches into one</title>
28.16037 +
28.16038 +      <para id="x_5f0">The <command role="hg-ext-mq" moreinfo="none">qfold</command> command
28.16039 +	merges multiple patches into the topmost applied patch, so
28.16040 +	that the topmost applied patch makes the union of all of the
28.16041 +	changes in the patches in question.</para>
28.16042 +
28.16043 +      <para id="x_5f1">The patches to fold must not be applied; <command role="hg-ext-mq" moreinfo="none">qfold</command> will exit with an error if
28.16044 +	any is.  The order in which patches are folded is significant;
28.16045 +	<command role="hg-cmd" moreinfo="none">hg qfold a b</command> means
28.16046 +	<quote>apply the current topmost patch, followed by
28.16047 +	  <literal moreinfo="none">a</literal>, followed by
28.16048 +	  <literal moreinfo="none">b</literal></quote>.</para>
28.16049 +
28.16050 +      <para id="x_5f2">The comments from the folded patches are appended to the
28.16051 +	comments of the destination patch, with each block of comments
28.16052 +	separated by three asterisk
28.16053 +	(<quote><literal moreinfo="none">*</literal></quote>) characters.  Use the
28.16054 +	<option role="hg-ext-mq-cmd-qfold-opt">-e</option> option to
28.16055 +	edit the commit message for the combined patch/changeset after
28.16056 +	the folding has completed.</para>
28.16057 +
28.16058 +      <para id="x_5f3">Options:</para>
28.16059 +      <itemizedlist>
28.16060 +	<listitem><para id="x_5f4"><option role="hg-ext-mq-cmd-qfold-opt">-e</option>: Edit the
28.16061 +	    commit message and patch description for the newly folded
28.16062 +	    patch.</para>
28.16063 +	</listitem>
28.16064 +	<listitem><para id="x_5f5"><option role="hg-ext-mq-cmd-qfold-opt">-l</option>: Use the
28.16065 +	    contents of the given file as the new commit message and
28.16066 +	    patch description for the folded patch.</para>
28.16067 +	</listitem>
28.16068 +	<listitem><para id="x_5f6"><option role="hg-ext-mq-cmd-qfold-opt">-m</option>: Use the
28.16069 +	    given text as the new commit message and patch description
28.16070 +	    for the folded patch.</para>
28.16071 +	</listitem></itemizedlist>
28.16072 +
28.16073 +    </sect2>
28.16074 +    <sect2>
28.16075 +      <title><command role="hg-ext-mq" moreinfo="none">qheader</command>—display the
28.16076 +	header/description of a patch</title>
28.16077 +
28.16078 +      <para id="x_5f7">The <command role="hg-ext-mq" moreinfo="none">qheader</command> command
28.16079 +	prints the header, or description, of a patch.  By default, it
28.16080 +	prints the header of the topmost applied patch. Given an
28.16081 +	argument, it prints the header of the named patch.</para>
28.16082 +
28.16083 +    </sect2>
28.16084 +    <sect2>
28.16085 +      <title><command role="hg-ext-mq" moreinfo="none">qimport</command>—import
28.16086 +	a third-party patch into the queue</title>
28.16087 +
28.16088 +      <para id="x_5f8">The <command role="hg-ext-mq" moreinfo="none">qimport</command> command
28.16089 +	adds an entry for an external patch to the <filename role="special" moreinfo="none">series</filename> file, and copies the patch
28.16090 +	into the <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> directory.  It adds
28.16091 +	the entry immediately after the topmost applied patch, but
28.16092 +	does not push the patch.</para>
28.16093 +
28.16094 +      <para id="x_5f9">If the <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> directory is a
28.16095 +	repository, <command role="hg-ext-mq" moreinfo="none">qimport</command>
28.16096 +	automatically does an <command role="hg-cmd" moreinfo="none">hg add</command>
28.16097 +	of the imported patch.</para>
28.16098 +
28.16099 +    </sect2>
28.16100 +    <sect2>
28.16101 +      <title><command role="hg-ext-mq" moreinfo="none">qinit</command>—prepare
28.16102 +	a repository to work with MQ</title>
28.16103 +
28.16104 +      <para id="x_5fa">The <command role="hg-ext-mq" moreinfo="none">qinit</command> command
28.16105 +	prepares a repository to work with MQ.  It creates a directory
28.16106 +	called <filename role="special" class="directory" moreinfo="none">.hg/patches</filename>.</para>
28.16107 +
28.16108 +      <para id="x_5fb">Options:</para>
28.16109 +      <itemizedlist>
28.16110 +	<listitem><para id="x_5fc"><option role="hg-ext-mq-cmd-qinit-opt">-c</option>: Create
28.16111 +	    <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> as a repository
28.16112 +	    in its own right.  Also creates a <filename role="special" moreinfo="none">.hgignore</filename> file that will
28.16113 +	    ignore the <filename role="special" moreinfo="none">status</filename>
28.16114 +	    file.</para>
28.16115 +	</listitem></itemizedlist>
28.16116 +
28.16117 +      <para id="x_5fd">When the <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> directory is a
28.16118 +	repository, the <command role="hg-ext-mq" moreinfo="none">qimport</command>
28.16119 +	and <command role="hg-ext-mq" moreinfo="none">qnew</command> commands
28.16120 +	automatically <command role="hg-cmd" moreinfo="none">hg add</command> new
28.16121 +	patches.</para>
28.16122 +
28.16123 +    </sect2>
28.16124 +    <sect2>
28.16125 +      <title><command role="hg-ext-mq" moreinfo="none">qnew</command>—create a
28.16126 +	new patch</title>
28.16127 +
28.16128 +      <para id="x_5fe">The <command role="hg-ext-mq" moreinfo="none">qnew</command> command
28.16129 +	creates a new patch.  It takes one mandatory argument, the
28.16130 +	name to use for the patch file.  The newly created patch is
28.16131 +	created empty by default.  It is added to the <filename role="special" moreinfo="none">series</filename> file after the current
28.16132 +	topmost applied patch, and is immediately pushed on top of
28.16133 +	that patch.</para>
28.16134 +
28.16135 +      <para id="x_5ff">If <command role="hg-ext-mq" moreinfo="none">qnew</command> finds modified
28.16136 +	files in the working directory, it will refuse to create a new
28.16137 +	patch unless the <option role="hg-ext-mq-cmd-qnew-opt">-f</option> option is used
28.16138 +	(see below).  This behavior allows you to <command role="hg-ext-mq" moreinfo="none">qrefresh</command> your topmost applied
28.16139 +	patch before you apply a new patch on top of it.</para>
28.16140 +
28.16141 +      <para id="x_600">Options:</para>
28.16142 +      <itemizedlist>
28.16143 +	<listitem><para id="x_601"><option role="hg-ext-mq-cmd-qnew-opt">-f</option>: Create a new
28.16144 +	    patch if the contents of the working directory are
28.16145 +	    modified.  Any outstanding modifications are added to the
28.16146 +	    newly created patch, so after this command completes, the
28.16147 +	    working directory will no longer be modified.</para>
28.16148 +	</listitem>
28.16149 +	<listitem><para id="x_602"><option role="hg-ext-mq-cmd-qnew-opt">-m</option>: Use the given
28.16150 +	    text as the commit message. This text will be stored at
28.16151 +	    the beginning of the patch file, before the patch
28.16152 +	    data.</para>
28.16153 +	</listitem></itemizedlist>
28.16154 +
28.16155 +    </sect2>
28.16156 +    <sect2>
28.16157 +      <title><command role="hg-ext-mq" moreinfo="none">qnext</command>—print
28.16158 +	the name of the next patch</title>
28.16159 +
28.16160 +      <para id="x_603">The <command role="hg-ext-mq" moreinfo="none">qnext</command> command
28.16161 +	prints the name name of the next patch in the <filename role="special" moreinfo="none">series</filename> file after the topmost
28.16162 +	applied patch.  This patch will become the topmost applied
28.16163 +	patch if you run <command role="hg-ext-mq" moreinfo="none">qpush</command>.</para>
28.16164 +
28.16165 +    </sect2>
28.16166 +    <sect2>
28.16167 +      <title><command role="hg-ext-mq" moreinfo="none">qpop</command>—pop
28.16168 +	patches off the stack</title>
28.16169 +
28.16170 +      <para id="x_604">The <command role="hg-ext-mq" moreinfo="none">qpop</command> command
28.16171 +	removes applied patches from the top of the stack of applied
28.16172 +	patches.  By default, it removes only one patch.</para>
28.16173 +
28.16174 +      <para id="x_605">This command removes the changesets that represent the
28.16175 +	popped patches from the repository, and updates the working
28.16176 +	directory to undo the effects of the patches.</para>
28.16177 +
28.16178 +      <para id="x_606">This command takes an optional argument, which it uses as
28.16179 +	the name or index of the patch to pop to.  If given a name, it
28.16180 +	will pop patches until the named patch is the topmost applied
28.16181 +	patch.  If given a number, <command role="hg-ext-mq" moreinfo="none">qpop</command> treats the number as an
28.16182 +	index into the entries in the series file, counting from zero
28.16183 +	(empty lines and lines containing only comments do not count).
28.16184 +	It pops patches until the patch identified by the given index
28.16185 +	is the topmost applied patch.</para>
28.16186 +
28.16187 +      <para id="x_607">The <command role="hg-ext-mq" moreinfo="none">qpop</command> command does
28.16188 +	not read or write patches or the <filename role="special" moreinfo="none">series</filename> file.  It is thus safe to
28.16189 +	<command role="hg-ext-mq" moreinfo="none">qpop</command> a patch that you have
28.16190 +	removed from the <filename role="special" moreinfo="none">series</filename>
28.16191 +	file, or a patch that you have renamed or deleted entirely.
28.16192 +	In the latter two cases, use the name of the patch as it was
28.16193 +	when you applied it.</para>
28.16194 +
28.16195 +      <para id="x_608">By default, the <command role="hg-ext-mq" moreinfo="none">qpop</command>
28.16196 +	command will not pop any patches if the working directory has
28.16197 +	been modified.  You can override this behavior using the
28.16198 +	<option role="hg-ext-mq-cmd-qpop-opt">-f</option> option,
28.16199 +	which reverts all modifications in the working
28.16200 +	directory.</para>
28.16201 +
28.16202 +      <para id="x_609">Options:</para>
28.16203 +      <itemizedlist>
28.16204 +	<listitem><para id="x_60a"><option role="hg-ext-mq-cmd-qpop-opt">-a</option>: Pop all
28.16205 +	    applied patches.  This returns the repository to its state
28.16206 +	    before you applied any patches.</para>
28.16207 +	</listitem>
28.16208 +	<listitem><para id="x_60b"><option role="hg-ext-mq-cmd-qpop-opt">-f</option>: Forcibly
28.16209 +	    revert any modifications to the working directory when
28.16210 +	    popping.</para>
28.16211 +	</listitem>
28.16212 +	<listitem><para id="x_60c"><option role="hg-ext-mq-cmd-qpop-opt">-n</option>: Pop a patch
28.16213 +	    from the named queue.</para>
28.16214 +	</listitem></itemizedlist>
28.16215 +
28.16216 +      <para id="x_60d">The <command role="hg-ext-mq" moreinfo="none">qpop</command> command
28.16217 +	removes one line from the end of the <filename role="special" moreinfo="none">status</filename> file for each patch that it
28.16218 +	pops.</para>
28.16219 +
28.16220 +    </sect2>
28.16221 +    <sect2>
28.16222 +      <title><command role="hg-ext-mq" moreinfo="none">qprev</command>—print
28.16223 +	the name of the previous patch</title>
28.16224 +
28.16225 +      <para id="x_60e">The <command role="hg-ext-mq" moreinfo="none">qprev</command> command
28.16226 +	prints the name of the patch in the <filename role="special" moreinfo="none">series</filename> file that comes before the
28.16227 +	topmost applied patch. This will become the topmost applied
28.16228 +	patch if you run <command role="hg-ext-mq" moreinfo="none">qpop</command>.</para>
28.16229 +
28.16230 +    </sect2>
28.16231 +    <sect2 id="sec:mqref:cmd:qpush">
28.16232 +      <title><command role="hg-ext-mq" moreinfo="none">qpush</command>—push
28.16233 +	patches onto the stack</title>
28.16234 +
28.16235 +      <para id="x_60f">The <command role="hg-ext-mq" moreinfo="none">qpush</command> command adds
28.16236 +	patches onto the applied stack.  By default, it adds only one
28.16237 +	patch.</para>
28.16238 +
28.16239 +      <para id="x_610">This command creates a new changeset to represent each
28.16240 +	applied patch, and updates the working directory to apply the
28.16241 +	effects of the patches.</para>
28.16242 +
28.16243 +      <para id="x_611">The default data used when creating a changeset are as
28.16244 +	follows:</para>
28.16245 +      <itemizedlist>
28.16246 +	<listitem><para id="x_612">The commit date and time zone are the current
28.16247 +	    date and time zone.  Because these data are used to
28.16248 +	    compute the identity of a changeset, this means that if
28.16249 +	    you <command role="hg-ext-mq" moreinfo="none">qpop</command> a patch and
28.16250 +	    <command role="hg-ext-mq" moreinfo="none">qpush</command> it again, the
28.16251 +	    changeset that you push will have a different identity
28.16252 +	    than the changeset you popped.</para>
28.16253 +	</listitem>
28.16254 +	<listitem><para id="x_613">The author is the same as the default used by
28.16255 +	    the <command role="hg-cmd" moreinfo="none">hg commit</command>
28.16256 +	    command.</para>
28.16257 +	</listitem>
28.16258 +	<listitem><para id="x_614">The commit message is any text from the patch
28.16259 +	    file that comes before the first diff header.  If there is
28.16260 +	    no such text, a default commit message is used that
28.16261 +	    identifies the name of the patch.</para>
28.16262 +	</listitem></itemizedlist>
28.16263 +      <para id="x_615">If a patch contains a Mercurial patch header,
28.16264 +	the information in the patch header overrides these
28.16265 +	defaults.</para>
28.16266 +
28.16267 +      <para id="x_616">Options:</para>
28.16268 +      <itemizedlist>
28.16269 +	<listitem><para id="x_617"><option role="hg-ext-mq-cmd-qpush-opt">-a</option>: Push all
28.16270 +	    unapplied patches from the <filename role="special" moreinfo="none">series</filename> file until there are
28.16271 +	    none left to push.</para>
28.16272 +	</listitem>
28.16273 +	<listitem><para id="x_618"><option role="hg-ext-mq-cmd-qpush-opt">-l</option>: Add the name
28.16274 +	    of the patch to the end of the commit message.</para>
28.16275 +	</listitem>
28.16276 +	<listitem><para id="x_619"><option role="hg-ext-mq-cmd-qpush-opt">-m</option>: If a patch
28.16277 +	    fails to apply cleanly, use the entry for the patch in
28.16278 +	    another saved queue to compute the parameters for a
28.16279 +	    three-way merge, and perform a three-way merge using the
28.16280 +	    normal Mercurial merge machinery.  Use the resolution of
28.16281 +	    the merge as the new patch content.</para>
28.16282 +	</listitem>
28.16283 +	<listitem><para id="x_61a"><option role="hg-ext-mq-cmd-qpush-opt">-n</option>: Use the
28.16284 +	    named queue if merging while pushing.</para>
28.16285 +	</listitem></itemizedlist>
28.16286 +
28.16287 +      <para id="x_61b">The <command role="hg-ext-mq" moreinfo="none">qpush</command> command
28.16288 +	reads, but does not modify, the <filename role="special" moreinfo="none">series</filename> file.  It appends one line
28.16289 +	to the <command role="hg-cmd" moreinfo="none">hg status</command> file for
28.16290 +	each patch that it pushes.</para>
28.16291 +
28.16292 +    </sect2>
28.16293 +    <sect2>
28.16294 +      <title><command role="hg-ext-mq" moreinfo="none">qrefresh</command>—update the
28.16295 +	topmost applied patch</title>
28.16296 +
28.16297 +      <para id="x_61c">The <command role="hg-ext-mq" moreinfo="none">qrefresh</command> command
28.16298 +	updates the topmost applied patch.  It modifies the patch,
28.16299 +	removes the old changeset that represented the patch, and
28.16300 +	creates a new changeset to represent the modified
28.16301 +	patch.</para>
28.16302 +
28.16303 +      <para id="x_61d">The <command role="hg-ext-mq" moreinfo="none">qrefresh</command> command
28.16304 +	looks for the following modifications:</para>
28.16305 +      <itemizedlist>
28.16306 +	<listitem><para id="x_61e">Changes to the commit message, i.e. the text
28.16307 +	    before the first diff header in the patch file, are
28.16308 +	    reflected in the new changeset that represents the
28.16309 +	    patch.</para>
28.16310 +	</listitem>
28.16311 +	<listitem><para id="x_61f">Modifications to tracked files in the working
28.16312 +	    directory are added to the patch.</para>
28.16313 +	</listitem>
28.16314 +	<listitem><para id="x_620">Changes to the files tracked using <command role="hg-cmd" moreinfo="none">hg add</command>, <command role="hg-cmd" moreinfo="none">hg copy</command>, <command role="hg-cmd" moreinfo="none">hg remove</command>, or <command role="hg-cmd" moreinfo="none">hg rename</command>.  Added files and copy
28.16315 +	    and rename destinations are added to the patch, while
28.16316 +	    removed files and rename sources are removed.</para>
28.16317 +	</listitem></itemizedlist>
28.16318 +
28.16319 +      <para id="x_621">Even if <command role="hg-ext-mq" moreinfo="none">qrefresh</command>
28.16320 +	detects no changes, it still recreates the changeset that
28.16321 +	represents the patch.  This causes the identity of the
28.16322 +	changeset to differ from the previous changeset that
28.16323 +	identified the patch.</para>
28.16324 +
28.16325 +      <para id="x_622">Options:</para>
28.16326 +      <itemizedlist>
28.16327 +	<listitem><para id="x_623"><option role="hg-ext-mq-cmd-qrefresh-opt">-e</option>: Modify
28.16328 +	    the commit and patch description, using the preferred text
28.16329 +	    editor.</para>
28.16330 +	</listitem>
28.16331 +	<listitem><para id="x_624"><option role="hg-ext-mq-cmd-qrefresh-opt">-m</option>: Modify
28.16332 +	    the commit message and patch description, using the given
28.16333 +	    text.</para>
28.16334 +	</listitem>
28.16335 +	<listitem><para id="x_625"><option role="hg-ext-mq-cmd-qrefresh-opt">-l</option>: Modify
28.16336 +	    the commit message and patch description, using text from
28.16337 +	    the given file.</para>
28.16338 +	</listitem></itemizedlist>
28.16339 +
28.16340 +    </sect2>
28.16341 +    <sect2>
28.16342 +      <title><command role="hg-ext-mq" moreinfo="none">qrename</command>—rename
28.16343 +	a patch</title>
28.16344 +
28.16345 +      <para id="x_626">The <command role="hg-ext-mq" moreinfo="none">qrename</command> command
28.16346 +	renames a patch, and changes the entry for the patch in the
28.16347 +	<filename role="special" moreinfo="none">series</filename> file.</para>
28.16348 +
28.16349 +      <para id="x_627">With a single argument, <command role="hg-ext-mq" moreinfo="none">qrename</command> renames the topmost
28.16350 +	applied patch.  With two arguments, it renames its first
28.16351 +	argument to its second.</para>
28.16352 +
28.16353 +    </sect2>
28.16354 +    <sect2>
28.16355 +      <title><command role="hg-ext-mq" moreinfo="none">qseries</command>—print
28.16356 +	the entire patch series</title>
28.16357 +
28.16358 +      <para id="x_62a">The <command role="hg-ext-mq" moreinfo="none">qseries</command> command
28.16359 +	prints the entire patch series from the <filename role="special" moreinfo="none">series</filename> file.  It prints only patch
28.16360 +	names, not empty lines or comments.  It prints in order from
28.16361 +	first to be applied to last.</para>
28.16362 +
28.16363 +    </sect2>
28.16364 +    <sect2>
28.16365 +      <title><command role="hg-ext-mq" moreinfo="none">qtop</command>—print the
28.16366 +	name of the current patch</title>
28.16367 +
28.16368 +      <para id="x_62b">The <command role="hg-ext-mq" moreinfo="none">qtop</command> prints the
28.16369 +	name of the topmost currently applied patch.</para>
28.16370 +
28.16371 +    </sect2>
28.16372 +    <sect2>
28.16373 +      <title><command role="hg-ext-mq" moreinfo="none">qunapplied</command>—print patches
28.16374 +	not yet applied</title>
28.16375 +
28.16376 +      <para id="x_62c">The <command role="hg-ext-mq" moreinfo="none">qunapplied</command> command
28.16377 +	prints the names of patches from the <filename role="special" moreinfo="none">series</filename> file that are not yet
28.16378 +	applied.  It prints them in order from the next patch that
28.16379 +	will be pushed to the last.</para>
28.16380 +
28.16381 +    </sect2>
28.16382 +    <sect2>
28.16383 +      <title><command role="hg-cmd" moreinfo="none">hg strip</command>—remove a
28.16384 +	revision and descendants</title>
28.16385 +
28.16386 +      <para id="x_62d">The <command role="hg-cmd" moreinfo="none">hg strip</command> command
28.16387 +	removes a revision, and all of its descendants, from the
28.16388 +	repository.  It undoes the effects of the removed revisions
28.16389 +	from the repository, and updates the working directory to the
28.16390 +	first parent of the removed revision.</para>
28.16391 +
28.16392 +      <para id="x_62e">The <command role="hg-cmd" moreinfo="none">hg strip</command> command
28.16393 +	saves a backup of the removed changesets in a bundle, so that
28.16394 +	they can be reapplied if removed in error.</para>
28.16395 +
28.16396 +      <para id="x_62f">Options:</para>
28.16397 +      <itemizedlist>
28.16398 +	<listitem><para id="x_630"><option role="hg-opt-strip">-b</option>: Save
28.16399 +	    unrelated changesets that are intermixed with the stripped
28.16400 +	    changesets in the backup bundle.</para>
28.16401 +	</listitem>
28.16402 +	<listitem><para id="x_631"><option role="hg-opt-strip">-f</option>: If a
28.16403 +	    branch has multiple heads, remove all heads.</para>
28.16404 +	</listitem>
28.16405 +	<listitem><para id="x_632"><option role="hg-opt-strip">-n</option>: Do
28.16406 +	    not save a backup bundle.</para>
28.16407 +	</listitem></itemizedlist>
28.16408 +
28.16409 +    </sect2>
28.16410 +  </sect1>
28.16411 +  <sect1>
28.16412 +    <title>MQ file reference</title>
28.16413 +
28.16414 +    <sect2>
28.16415 +      <title>The <filename role="special" moreinfo="none">series</filename>
28.16416 +	file</title>
28.16417 +
28.16418 +      <para id="x_633">The <filename role="special" moreinfo="none">series</filename> file
28.16419 +	contains a list of the names of all patches that MQ can apply.
28.16420 +	It is represented as a list of names, with one name saved per
28.16421 +	line.  Leading and trailing white space in each line are
28.16422 +	ignored.</para>
28.16423 +
28.16424 +      <para id="x_634">Lines may contain comments.  A comment begins with the
28.16425 +	<quote><literal moreinfo="none">#</literal></quote> character, and extends to
28.16426 +	the end of the line.  Empty lines, and lines that contain only
28.16427 +	comments, are ignored.</para>
28.16428 +
28.16429 +      <para id="x_635">You will often need to edit the <filename role="special" moreinfo="none">series</filename> file by hand, hence the
28.16430 +	support for comments and empty lines noted above.  For
28.16431 +	example, you can comment out a patch temporarily, and <command role="hg-ext-mq" moreinfo="none">qpush</command> will skip over that patch
28.16432 +	when applying patches.  You can also change the order in which
28.16433 +	patches are applied by reordering their entries in the
28.16434 +	<filename role="special" moreinfo="none">series</filename> file.</para>
28.16435 +
28.16436 +      <para id="x_636">Placing the <filename role="special" moreinfo="none">series</filename>
28.16437 +	file under revision control is also supported; it is a good
28.16438 +	idea to place all of the patches that it refers to under
28.16439 +	revision control, as well.  If you create a patch directory
28.16440 +	using the <option role="hg-ext-mq-cmd-qinit-opt">-c</option>
28.16441 +	option to <command role="hg-ext-mq" moreinfo="none">qinit</command>, this will
28.16442 +	be done for you automatically.</para>
28.16443 +
28.16444 +    </sect2>
28.16445 +    <sect2>
28.16446 +      <title>The <filename role="special" moreinfo="none">status</filename>
28.16447 +	file</title>
28.16448 +
28.16449 +      <para id="x_637">The <filename role="special" moreinfo="none">status</filename> file
28.16450 +	contains the names and changeset hashes of all patches that MQ
28.16451 +	currently has applied.  Unlike the <filename role="special" moreinfo="none">series</filename> file, this file is not
28.16452 +	intended for editing.  You should not place this file under
28.16453 +	revision control, or modify it in any way.  It is used by MQ
28.16454 +	strictly for internal book-keeping.</para>
28.16455 +
28.16456 +    </sect2>
28.16457 +  </sect1>
28.16458 +</appendix>
28.16459 +
28.16460 +<!--
28.16461 +local variables: 
28.16462 +sgml-parent-document: ("00book.xml" "book" "appendix")
28.16463 +end:
28.16464 +-->
28.16465 +
28.16466 +  <!-- BEGIN appC -->
28.16467 +  <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
28.16468 +
28.16469 +<appendix id="chap:srcinstall">
28.16470 +  <?dbhtml filename="installing-mercurial-from-source.html"?>
28.16471 +  <title>Installer Mercurial à partir des sources</title>
28.16472 +
28.16473 +  <sect1 id="sec:srcinstall:unixlike">
28.16474 +    <title>Pour un système Unix ou similaire</title>
28.16475 +
28.16476 +    <para id="x_5e0">Si vous utilisez un système Unix ou similaire, pour lequel
28.16477 +      une version récente de Python (2.3 ou plus) est disponible, l'installation
28.16478 +      de Mercurial à partir des sources est simple.</para>
28.16479 +    <orderedlist inheritnum="ignore" continuation="restarts">
28.16480 +      <listitem><para id="x_5e1">Téléchargez un paquet récent depuis <ulink url="http://www.selenic.com/mercurial/download">http://www.selenic.com/mercurial/download</ulink>.</para>
28.16481 +      </listitem>
28.16482 +      <listitem><para id="x_5e2">Extrayez le paquet : </para>
28.16483 +	<programlisting format="linespecific">gzip -dc mercurial-MYVERSION.tar.gz | tar xf -</programlisting>
28.16484 +      </listitem>
28.16485 +      <listitem><para id="x_5e3">Allez dans le répertoires où les sources ont
28.16486 +    été extraites et exécutez le script d'installation. Ce dernier compilera
28.16487 +    Mercurial et l'installera dans votre répertoire utilisateur.</para>
28.16488 +	<programlisting format="linespecific">cd mercurial-MYVERSION
28.16489 +python setup.py install --force --home=$HOME</programlisting>
28.16490 +      </listitem>
28.16491 +    </orderedlist>
28.16492 +    <para id="x_5e4">Lorsque l'installation est terminée, Mercurial se
28.16493 +      trouvera dans le répertoire <literal moreinfo="none">bin</literal> de votre répertoire
28.16494 +      utilisateur.
28.16495 +      N'oubliez pas de vérifier que ce répertoire se trouve dans la liste
28.16496 +      des répertoires où votre shell recherche les exécutables.</para>
28.16497 +
28.16498 +    <para id="x_5e5">Vous devrez vraisemblablement définir la variable
28.16499 +      d'environnement <envar>PYTHONPATH</envar> de manière à ce que
28.16500 +      l'exécutable de Mercurial puisse trouver le reste des paquets logiciels.
28.16501 +      Par exemple, sur mon ordinateur portable, je dois le définir ainsi:
28.16502 +      <literal moreinfo="none">/home/bos/lib/python</literal>. Le chemin exact à utiliser
28.16503 +      dépendra de la manière dont Python aura été construit pour votre 
28.16504 +      système. Il ne devrait pas être difficile de le trouver. En cas de
28.16505 +      doute, lisez le texte généré lors de l'installation ci-dessus, et
28.16506 +      recherchez l'emplacement où le contenu du répertoire
28.16507 +      <literal moreinfo="none">mercurial</literal> a été installé.</para>
28.16508 +
28.16509 +  </sect1>
28.16510 +  <sect1>
28.16511 +    <title>Pour Windows</title>
28.16512 +
28.16513 +    <para id="x_5e6">Construire et installer Mercurial sous Windows nécessite
28.16514 +      des outils logiciels divers, une certaine connaissance technique et une
28.16515 +      bonne dose de patience. Je vous <emphasis>déconseille fortement</emphasis> 
28.16516 +      de tenter de le faire si vous êtes un <quote>simple utilisateur</quote>.
28.16517 +      A moins que vous n'ayez l'intention de "hacker" Mercurial, je vous
28.16518 +      suggère d'avoir recours à un paquet d'installation de la version binaire.</para>
28.16519 +
28.16520 +    <para id="x_5e7">Si vous avez vraiment l'intention de construire
28.16521 +      Mercurial à partir des sources sous Windows, suivez les indications pour 
28.16522 +      ce <quote>chemin laborieux</quote> sur le wiki de Mercurial : <ulink url="http://www.selenic.com/mercurial/wiki/index.cgi/WindowsInstall">http://www.selenic.com/mercurial/wiki/index.cgi/WindowsInstall</ulink>, 
28.16523 +      et préparez vous à un travail épineux.</para>
28.16524 +
28.16525 +  </sect1>
28.16526 +</appendix>
28.16527 +
28.16528 +<!--
28.16529 +local variables: 
28.16530 +sgml-parent-document: ("00book.xml" "book" "appendix")
28.16531 +end:
28.16532 +-->
28.16533 +
28.16534 +  <!-- BEGIN appD -->
28.16535 +  <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
28.16536 +
28.16537 +<appendix id="cha:opl">
28.16538 +  <?dbhtml filename="open-publication-license.html"?>
28.16539 +  <title>Open Publication License</title>
28.16540 +
28.16541 +  <para id="x_638">Version 1.0, 8 June 1999</para>
28.16542 +
28.16543 +  <sect1>
28.16544 +    <title>Requirements on both unmodified and modified
28.16545 +      versions</title>
28.16546 +
28.16547 +    <para id="x_639">The Open Publication works may be reproduced and distributed
28.16548 +      in whole or in part, in any medium physical or electronic,
28.16549 +      provided that the terms of this license are adhered to, and that
28.16550 +      this license or an incorporation of it by reference (with any
28.16551 +      options elected by the author(s) and/or publisher) is displayed
28.16552 +      in the reproduction.</para>
28.16553 +
28.16554 +    <para id="x_63a">Proper form for an incorporation by reference is as
28.16555 +      follows:</para>
28.16556 +
28.16557 +    <blockquote>
28.16558 +      <para id="x_63b">  Copyright (c) <emphasis>year</emphasis> by
28.16559 +	<emphasis>author's name or designee</emphasis>. This material
28.16560 +	may be distributed only subject to the terms and conditions
28.16561 +	set forth in the Open Publication License,
28.16562 +	v<emphasis>x.y</emphasis> or later (the latest version is
28.16563 +	presently available at <ulink url="http://www.opencontent.org/openpub/">http://www.opencontent.org/openpub/</ulink>).</para>
28.16564 +    </blockquote>
28.16565 +
28.16566 +    <para id="x_63c">The reference must be immediately followed with any options
28.16567 +      elected by the author(s) and/or publisher of the document (see
28.16568 +      <xref linkend="sec:opl:options"/>).</para>
28.16569 +
28.16570 +    <para id="x_63d">Commercial redistribution of Open Publication-licensed
28.16571 +      material is permitted.</para>
28.16572 +
28.16573 +    <para id="x_63e">Any publication in standard (paper) book form shall require
28.16574 +      the citation of the original publisher and author. The publisher
28.16575 +      and author's names shall appear on all outer surfaces of the
28.16576 +      book. On all outer surfaces of the book the original publisher's
28.16577 +      name shall be as large as the title of the work and cited as
28.16578 +      possessive with respect to the title.</para>
28.16579 +
28.16580 +  </sect1>
28.16581 +  <sect1>
28.16582 +    <title>Copyright</title>
28.16583 +
28.16584 +    <para id="x_63f">The copyright to each Open Publication is owned by its
28.16585 +      author(s) or designee.</para>
28.16586 +
28.16587 +  </sect1>
28.16588 +  <sect1>
28.16589 +    <title>Scope of license</title>
28.16590 +
28.16591 +    <para id="x_640">The following license terms apply to all Open Publication
28.16592 +      works, unless otherwise explicitly stated in the
28.16593 +      document.</para>
28.16594 +
28.16595 +    <para id="x_641">Mere aggregation of Open Publication works or a portion of
28.16596 +      an Open Publication work with other works or programs on the
28.16597 +      same media shall not cause this license to apply to those other
28.16598 +      works. The aggregate work shall contain a notice specifying the
28.16599 +      inclusion of the Open Publication material and appropriate
28.16600 +      copyright notice.</para>
28.16601 +
28.16602 +    <para id="x_642"><emphasis role="bold">Severability</emphasis>. If any part
28.16603 +      of this license is found to be unenforceable in any
28.16604 +      jurisdiction, the remaining portions of the license remain in
28.16605 +      force.</para>
28.16606 +
28.16607 +    <para id="x_643"><emphasis role="bold">No warranty</emphasis>. Open
28.16608 +      Publication works are licensed and provided <quote>as is</quote>
28.16609 +      without warranty of any kind, express or implied, including, but
28.16610 +      not limited to, the implied warranties of merchantability and
28.16611 +      fitness for a particular purpose or a warranty of
28.16612 +      non-infringement.</para>
28.16613 +
28.16614 +  </sect1>
28.16615 +  <sect1>
28.16616 +    <title>Requirements on modified works</title>
28.16617 +
28.16618 +    <para id="x_644">All modified versions of documents covered by this license,
28.16619 +      including translations, anthologies, compilations and partial
28.16620 +      documents, must meet the following requirements:</para>
28.16621 +
28.16622 +    <orderedlist inheritnum="ignore" continuation="restarts">
28.16623 +      <listitem><para id="x_645">The modified version must be labeled as
28.16624 +	  such.</para>
28.16625 +      </listitem>
28.16626 +      <listitem><para id="x_646">The person making the modifications must be
28.16627 +	  identified and the modifications dated.</para>
28.16628 +      </listitem>
28.16629 +      <listitem><para id="x_647">Acknowledgement of the original author and
28.16630 +	  publisher if applicable must be retained according to normal
28.16631 +	  academic citation practices.</para>
28.16632 +      </listitem>
28.16633 +      <listitem><para id="x_648">The location of the original unmodified document
28.16634 +	  must be identified.</para>
28.16635 +      </listitem>
28.16636 +      <listitem><para id="x_649">The original author's (or authors') name(s) may
28.16637 +	  not be used to assert or imply endorsement of the resulting
28.16638 +	  document without the original author's (or authors')
28.16639 +	  permission.</para>
28.16640 +      </listitem></orderedlist>
28.16641 +
28.16642 +  </sect1>
28.16643 +  <sect1>
28.16644 +    <title>Good-practice recommendations</title>
28.16645 +
28.16646 +    <para id="x_64a">In addition to the requirements of this license, it is
28.16647 +      requested from and strongly recommended of redistributors
28.16648 +      that:</para>
28.16649 +
28.16650 +    <orderedlist inheritnum="ignore" continuation="restarts">
28.16651 +      <listitem><para id="x_64b">If you are distributing Open Publication works
28.16652 +	  on hardcopy or CD-ROM, you provide email notification to the
28.16653 +	  authors of your intent to redistribute at least thirty days
28.16654 +	  before your manuscript or media freeze, to give the authors
28.16655 +	  time to provide updated documents. This notification should
28.16656 +	  describe modifications, if any, made to the document.</para>
28.16657 +      </listitem>
28.16658 +      <listitem><para id="x_64c">All substantive modifications (including
28.16659 +	  deletions) be either clearly marked up in the document or
28.16660 +	  else described in an attachment to the document.</para>
28.16661 +      </listitem>
28.16662 +      <listitem><para id="x_64d">Finally, while it is not mandatory under this
28.16663 +	  license, it is considered good form to offer a free copy of
28.16664 +	  any hardcopy and CD-ROM expression of an Open
28.16665 +	  Publication-licensed work to its author(s).</para>
28.16666 +      </listitem></orderedlist>
28.16667 +
28.16668 +  </sect1>
28.16669 +  <sect1 id="sec:opl:options">
28.16670 +    <title>License options</title>
28.16671 +
28.16672 +    <para id="x_64e">The author(s) and/or publisher of an Open
28.16673 +      Publication-licensed document may elect certain options by
28.16674 +      appending language to the reference to or copy of the license.
28.16675 +      These options are considered part of the license instance and
28.16676 +      must be included with the license (or its incorporation by
28.16677 +      reference) in derived works.</para>
28.16678 +
28.16679 +    <orderedlist inheritnum="ignore" continuation="restarts">
28.16680 +      <listitem><para id="x_64f">To prohibit distribution of substantively
28.16681 +	  modified versions without the explicit permission of the
28.16682 +	  author(s). <quote>Substantive modification</quote> is
28.16683 +	  defined as a change to the semantic content of the document,
28.16684 +	  and excludes mere changes in format or typographical
28.16685 +	  corrections.</para>
28.16686 +      </listitem>
28.16687 +      <listitem><para id="x_650">  To accomplish this, add the phrase
28.16688 +	  <quote>Distribution of substantively modified versions of
28.16689 +	    this document is prohibited without the explicit
28.16690 +	    permission of the copyright holder.</quote> to the license
28.16691 +	  reference or copy.</para>
28.16692 +      </listitem>
28.16693 +      <listitem><para id="x_651">To prohibit any publication of this work or
28.16694 +	  derivative works in whole or in part in standard (paper)
28.16695 +	  book form for commercial purposes is prohibited unless prior
28.16696 +	  permission is obtained from the copyright holder.</para>
28.16697 +      </listitem>
28.16698 +      <listitem><para id="x_652">To accomplish this, add the phrase
28.16699 +	  <quote>Distribution of the work or derivative of the work in
28.16700 +	    any standard (paper) book form is prohibited unless prior
28.16701 +	    permission is obtained from the copyright holder.</quote>
28.16702 +	  to the license reference or copy.</para>
28.16703 +      </listitem></orderedlist>
28.16704 +
28.16705 +  </sect1>
28.16706 +</appendix>
28.16707 +
28.16708 +<!--
28.16709 +local variables: 
28.16710 +sgml-parent-document: ("00book.xml" "book" "appendix")
28.16711 +end:
28.16712 +-->
28.16713 +
28.16714 +</book>
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/fr/examples/auto-snippets.xml	Sat Jul 10 06:24:49 2010 +0100
    29.3 @@ -0,0 +1,276 @@
    29.4 +<!ENTITY ch06-apache-config.lst SYSTEM "results/ch06-apache-config.lst.lxo">
    29.5 +<!ENTITY ch09-check_whitespace.py.lst SYSTEM "results/ch09-check_whitespace.py.lst.lxo">
    29.6 +<!ENTITY ch10-bugzilla-config.lst SYSTEM "results/ch10-bugzilla-config.lst.lxo">
    29.7 +<!ENTITY ch10-notify-config-mail.lst SYSTEM "results/ch10-notify-config-mail.lst.lxo">
    29.8 +<!ENTITY ch10-notify-config.lst SYSTEM "results/ch10-notify-config.lst.lxo">
    29.9 +<!ENTITY interaction.backout.init SYSTEM "results/backout.init.lxo">
   29.10 +<!ENTITY interaction.backout.manual.backout SYSTEM "results/backout.manual.backout.lxo">
   29.11 +<!ENTITY interaction.backout.manual.cat SYSTEM "results/backout.manual.cat.lxo">
   29.12 +<!ENTITY interaction.backout.manual.clone SYSTEM "results/backout.manual.clone.lxo">
   29.13 +<!ENTITY interaction.backout.manual.heads SYSTEM "results/backout.manual.heads.lxo">
   29.14 +<!ENTITY interaction.backout.manual.log SYSTEM "results/backout.manual.log.lxo">
   29.15 +<!ENTITY interaction.backout.manual.merge SYSTEM "results/backout.manual.merge.lxo">
   29.16 +<!ENTITY interaction.backout.manual.parents SYSTEM "results/backout.manual.parents.lxo">
   29.17 +<!ENTITY interaction.backout.non-tip.backout SYSTEM "results/backout.non-tip.backout.lxo">
   29.18 +<!ENTITY interaction.backout.non-tip.cat SYSTEM "results/backout.non-tip.cat.lxo">
   29.19 +<!ENTITY interaction.backout.non-tip.clone SYSTEM "results/backout.non-tip.clone.lxo">
   29.20 +<!ENTITY interaction.backout.simple SYSTEM "results/backout.simple.lxo">
   29.21 +<!ENTITY interaction.backout.simple.log SYSTEM "results/backout.simple.log.lxo">
   29.22 +<!ENTITY interaction.bisect.commits SYSTEM "results/bisect.commits.lxo">
   29.23 +<!ENTITY interaction.bisect.help SYSTEM "results/bisect.help.lxo">
   29.24 +<!ENTITY interaction.bisect.init SYSTEM "results/bisect.init.lxo">
   29.25 +<!ENTITY interaction.bisect.search.bad-init SYSTEM "results/bisect.search.bad-init.lxo">
   29.26 +<!ENTITY interaction.bisect.search.good-init SYSTEM "results/bisect.search.good-init.lxo">
   29.27 +<!ENTITY interaction.bisect.search.init SYSTEM "results/bisect.search.init.lxo">
   29.28 +<!ENTITY interaction.bisect.search.mytest SYSTEM "results/bisect.search.mytest.lxo">
   29.29 +<!ENTITY interaction.bisect.search.reset SYSTEM "results/bisect.search.reset.lxo">
   29.30 +<!ENTITY interaction.bisect.search.rest SYSTEM "results/bisect.search.rest.lxo">
   29.31 +<!ENTITY interaction.bisect.search.step1 SYSTEM "results/bisect.search.step1.lxo">
   29.32 +<!ENTITY interaction.bisect.search.step2 SYSTEM "results/bisect.search.step2.lxo">
   29.33 +<!ENTITY interaction.branch-named.branch SYSTEM "results/branch-named.branch.lxo">
   29.34 +<!ENTITY interaction.branch-named.branches SYSTEM "results/branch-named.branches.lxo">
   29.35 +<!ENTITY interaction.branch-named.commit SYSTEM "results/branch-named.commit.lxo">
   29.36 +<!ENTITY interaction.branch-named.create SYSTEM "results/branch-named.create.lxo">
   29.37 +<!ENTITY interaction.branch-named.foo-commit SYSTEM "results/branch-named.foo-commit.lxo">
   29.38 +<!ENTITY interaction.branch-named.merge SYSTEM "results/branch-named.merge.lxo">
   29.39 +<!ENTITY interaction.branch-named.parents SYSTEM "results/branch-named.parents.lxo">
   29.40 +<!ENTITY interaction.branch-named.rebranch SYSTEM "results/branch-named.rebranch.lxo">
   29.41 +<!ENTITY interaction.branch-named.status SYSTEM "results/branch-named.status.lxo">
   29.42 +<!ENTITY interaction.branch-named.update-bar SYSTEM "results/branch-named.update-bar.lxo">
   29.43 +<!ENTITY interaction.branch-named.update-nothing SYSTEM "results/branch-named.update-nothing.lxo">
   29.44 +<!ENTITY interaction.branch-named.update-switchy SYSTEM "results/branch-named.update-switchy.lxo">
   29.45 +<!ENTITY interaction.branch-repo.bugfix SYSTEM "results/branch-repo.bugfix.lxo">
   29.46 +<!ENTITY interaction.branch-repo.clone SYSTEM "results/branch-repo.clone.lxo">
   29.47 +<!ENTITY interaction.branch-repo.merge SYSTEM "results/branch-repo.merge.lxo">
   29.48 +<!ENTITY interaction.branch-repo.new SYSTEM "results/branch-repo.new.lxo">
   29.49 +<!ENTITY interaction.branch-repo.pull SYSTEM "results/branch-repo.pull.lxo">
   29.50 +<!ENTITY interaction.branch-repo.tag SYSTEM "results/branch-repo.tag.lxo">
   29.51 +<!ENTITY interaction.branching.clone SYSTEM "results/branching.clone.lxo">
   29.52 +<!ENTITY interaction.branching.init SYSTEM "results/branching.init.lxo">
   29.53 +<!ENTITY interaction.branching.main SYSTEM "results/branching.main.lxo">
   29.54 +<!ENTITY interaction.branching.merge SYSTEM "results/branching.merge.lxo">
   29.55 +<!ENTITY interaction.branching.stable SYSTEM "results/branching.stable.lxo">
   29.56 +<!ENTITY interaction.branching.tag SYSTEM "results/branching.tag.lxo">
   29.57 +<!ENTITY interaction.branching.update SYSTEM "results/branching.update.lxo">
   29.58 +<!ENTITY interaction.ch01-new.add SYSTEM "results/ch01-new.add.lxo">
   29.59 +<!ENTITY interaction.ch01-new.commit SYSTEM "results/ch01-new.commit.lxo">
   29.60 +<!ENTITY interaction.ch01-new.init SYSTEM "results/ch01-new.init.lxo">
   29.61 +<!ENTITY interaction.ch01-new.ls SYSTEM "results/ch01-new.ls.lxo">
   29.62 +<!ENTITY interaction.ch01-new.ls2 SYSTEM "results/ch01-new.ls2.lxo">
   29.63 +<!ENTITY interaction.ch02-rename.alice SYSTEM "results/ch02-rename.alice.lxo">
   29.64 +<!ENTITY interaction.ch02-rename.bob SYSTEM "results/ch02-rename.bob.lxo">
   29.65 +<!ENTITY interaction.ch02-rename.clone SYSTEM "results/ch02-rename.clone.lxo">
   29.66 +<!ENTITY interaction.ch02-rename.clone2 SYSTEM "results/ch02-rename.clone2.lxo">
   29.67 +<!ENTITY interaction.ch02-rename.init SYSTEM "results/ch02-rename.init.lxo">
   29.68 +<!ENTITY interaction.ch02-rename.merge SYSTEM "results/ch02-rename.merge.lxo">
   29.69 +<!ENTITY interaction.ch02-rename.merge2 SYSTEM "results/ch02-rename.merge2.lxo">
   29.70 +<!ENTITY interaction.ch02-rename.status SYSTEM "results/ch02-rename.status.lxo">
   29.71 +<!ENTITY interaction.ch02-rename.status2 SYSTEM "results/ch02-rename.status2.lxo">
   29.72 +<!ENTITY interaction.ch04-diff.chmod SYSTEM "results/ch04-diff.chmod.lxo">
   29.73 +<!ENTITY interaction.ch04-diff.chmod.git SYSTEM "results/ch04-diff.chmod.git.lxo">
   29.74 +<!ENTITY interaction.ch04-diff.rename.basic SYSTEM "results/ch04-diff.rename.basic.lxo">
   29.75 +<!ENTITY interaction.ch04-diff.rename.git SYSTEM "results/ch04-diff.rename.git.lxo">
   29.76 +<!ENTITY interaction.ch04-rename.basic SYSTEM "results/ch04-rename.basic.lxo">
   29.77 +<!ENTITY interaction.ch04-resolve.cifail SYSTEM "results/ch04-resolve.cifail.lxo">
   29.78 +<!ENTITY interaction.ch04-resolve.export SYSTEM "results/ch04-resolve.export.lxo">
   29.79 +<!ENTITY interaction.ch04-resolve.heads SYSTEM "results/ch04-resolve.heads.lxo">
   29.80 +<!ENTITY interaction.ch04-resolve.init SYSTEM "results/ch04-resolve.init.lxo">
   29.81 +<!ENTITY interaction.ch04-resolve.left SYSTEM "results/ch04-resolve.left.lxo">
   29.82 +<!ENTITY interaction.ch04-resolve.list SYSTEM "results/ch04-resolve.list.lxo">
   29.83 +<!ENTITY interaction.ch04-resolve.merge SYSTEM "results/ch04-resolve.merge.lxo">
   29.84 +<!ENTITY interaction.ch04-resolve.pull SYSTEM "results/ch04-resolve.pull.lxo">
   29.85 +<!ENTITY interaction.ch04-resolve.right SYSTEM "results/ch04-resolve.right.lxo">
   29.86 +<!ENTITY interaction.ch09-hook.ws.better SYSTEM "results/ch09-hook.ws.better.lxo">
   29.87 +<!ENTITY interaction.ch09-hook.ws.simple SYSTEM "results/ch09-hook.ws.simple.lxo">
   29.88 +<!ENTITY interaction.ch10-multiline.go SYSTEM "results/ch10-multiline.go.lxo">
   29.89 +<!ENTITY interaction.ch10-multiline.orig.go SYSTEM "results/ch10-multiline.orig.go.lxo">
   29.90 +<!ENTITY interaction.ch11-qdelete.convert SYSTEM "results/ch11-qdelete.convert.lxo">
   29.91 +<!ENTITY interaction.ch11-qdelete.go SYSTEM "results/ch11-qdelete.go.lxo">
   29.92 +<!ENTITY interaction.ch11-qdelete.import SYSTEM "results/ch11-qdelete.import.lxo">
   29.93 +<!ENTITY interaction.cmdref.diff-p SYSTEM "results/cmdref.diff-p.lxo">
   29.94 +<!ENTITY interaction.daily.copy.after SYSTEM "results/daily.copy.after.lxo">
   29.95 +<!ENTITY interaction.daily.copy.cat SYSTEM "results/daily.copy.cat.lxo">
   29.96 +<!ENTITY interaction.daily.copy.clone SYSTEM "results/daily.copy.clone.lxo">
   29.97 +<!ENTITY interaction.daily.copy.copy SYSTEM "results/daily.copy.copy.lxo">
   29.98 +<!ENTITY interaction.daily.copy.dir-dest SYSTEM "results/daily.copy.dir-dest.lxo">
   29.99 +<!ENTITY interaction.daily.copy.dir-src SYSTEM "results/daily.copy.dir-src.lxo">
  29.100 +<!ENTITY interaction.daily.copy.dir-src-dest SYSTEM "results/daily.copy.dir-src-dest.lxo">
  29.101 +<!ENTITY interaction.daily.copy.init SYSTEM "results/daily.copy.init.lxo">
  29.102 +<!ENTITY interaction.daily.copy.merge SYSTEM "results/daily.copy.merge.lxo">
  29.103 +<!ENTITY interaction.daily.copy.orig.after SYSTEM "results/daily.copy.orig.after.lxo">
  29.104 +<!ENTITY interaction.daily.copy.orig.cat SYSTEM "results/daily.copy.orig.cat.lxo">
  29.105 +<!ENTITY interaction.daily.copy.orig.clone SYSTEM "results/daily.copy.orig.clone.lxo">
  29.106 +<!ENTITY interaction.daily.copy.orig.copy SYSTEM "results/daily.copy.orig.copy.lxo">
  29.107 +<!ENTITY interaction.daily.copy.orig.dir-dest SYSTEM "results/daily.copy.orig.dir-dest.lxo">
  29.108 +<!ENTITY interaction.daily.copy.orig.dir-src SYSTEM "results/daily.copy.orig.dir-src.lxo">
  29.109 +<!ENTITY interaction.daily.copy.orig.dir-src-dest SYSTEM "results/daily.copy.orig.dir-src-dest.lxo">
  29.110 +<!ENTITY interaction.daily.copy.orig.init SYSTEM "results/daily.copy.orig.init.lxo">
  29.111 +<!ENTITY interaction.daily.copy.orig.merge SYSTEM "results/daily.copy.orig.merge.lxo">
  29.112 +<!ENTITY interaction.daily.copy.orig.other SYSTEM "results/daily.copy.orig.other.lxo">
  29.113 +<!ENTITY interaction.daily.copy.orig.simple SYSTEM "results/daily.copy.orig.simple.lxo">
  29.114 +<!ENTITY interaction.daily.copy.orig.status SYSTEM "results/daily.copy.orig.status.lxo">
  29.115 +<!ENTITY interaction.daily.copy.orig.status-copy SYSTEM "results/daily.copy.orig.status-copy.lxo">
  29.116 +<!ENTITY interaction.daily.copy.other SYSTEM "results/daily.copy.other.lxo">
  29.117 +<!ENTITY interaction.daily.copy.simple SYSTEM "results/daily.copy.simple.lxo">
  29.118 +<!ENTITY interaction.daily.copy.status SYSTEM "results/daily.copy.status.lxo">
  29.119 +<!ENTITY interaction.daily.copy.status-copy SYSTEM "results/daily.copy.status-copy.lxo">
  29.120 +<!ENTITY interaction.daily.files.add SYSTEM "results/daily.files.add.lxo">
  29.121 +<!ENTITY interaction.daily.files.add-dir SYSTEM "results/daily.files.add-dir.lxo">
  29.122 +<!ENTITY interaction.daily.files.addremove SYSTEM "results/daily.files.addremove.lxo">
  29.123 +<!ENTITY interaction.daily.files.commit-addremove SYSTEM "results/daily.files.commit-addremove.lxo">
  29.124 +<!ENTITY interaction.daily.files.hidden SYSTEM "results/daily.files.hidden.lxo">
  29.125 +<!ENTITY interaction.daily.files.missing SYSTEM "results/daily.files.missing.lxo">
  29.126 +<!ENTITY interaction.daily.files.recover-missing SYSTEM "results/daily.files.recover-missing.lxo">
  29.127 +<!ENTITY interaction.daily.files.remove SYSTEM "results/daily.files.remove.lxo">
  29.128 +<!ENTITY interaction.daily.files.remove-after SYSTEM "results/daily.files.remove-after.lxo">
  29.129 +<!ENTITY interaction.daily.rename.rename SYSTEM "results/daily.rename.rename.lxo">
  29.130 +<!ENTITY interaction.daily.rename.status SYSTEM "results/daily.rename.status.lxo">
  29.131 +<!ENTITY interaction.daily.rename.status-copy SYSTEM "results/daily.rename.status-copy.lxo">
  29.132 +<!ENTITY interaction.daily.revert.add SYSTEM "results/daily.revert.add.lxo">
  29.133 +<!ENTITY interaction.daily.revert.copy SYSTEM "results/daily.revert.copy.lxo">
  29.134 +<!ENTITY interaction.daily.revert.missing SYSTEM "results/daily.revert.missing.lxo">
  29.135 +<!ENTITY interaction.daily.revert.modify SYSTEM "results/daily.revert.modify.lxo">
  29.136 +<!ENTITY interaction.daily.revert.remove SYSTEM "results/daily.revert.remove.lxo">
  29.137 +<!ENTITY interaction.daily.revert.rename SYSTEM "results/daily.revert.rename.lxo">
  29.138 +<!ENTITY interaction.daily.revert.rename-orig SYSTEM "results/daily.revert.rename-orig.lxo">
  29.139 +<!ENTITY interaction.daily.revert.status SYSTEM "results/daily.revert.status.lxo">
  29.140 +<!ENTITY interaction.daily.revert.unmodify SYSTEM "results/daily.revert.unmodify.lxo">
  29.141 +<!ENTITY interaction.extdiff.diff SYSTEM "results/extdiff.diff.lxo">
  29.142 +<!ENTITY interaction.extdiff.extdiff SYSTEM "results/extdiff.extdiff.lxo">
  29.143 +<!ENTITY interaction.extdiff.extdiff-ctx SYSTEM "results/extdiff.extdiff-ctx.lxo">
  29.144 +<!ENTITY interaction.filenames.dirs SYSTEM "results/filenames.dirs.lxo">
  29.145 +<!ENTITY interaction.filenames.files SYSTEM "results/filenames.files.lxo">
  29.146 +<!ENTITY interaction.filenames.filter.exclude SYSTEM "results/filenames.filter.exclude.lxo">
  29.147 +<!ENTITY interaction.filenames.filter.include SYSTEM "results/filenames.filter.include.lxo">
  29.148 +<!ENTITY interaction.filenames.glob.group SYSTEM "results/filenames.glob.group.lxo">
  29.149 +<!ENTITY interaction.filenames.glob.question SYSTEM "results/filenames.glob.question.lxo">
  29.150 +<!ENTITY interaction.filenames.glob.range SYSTEM "results/filenames.glob.range.lxo">
  29.151 +<!ENTITY interaction.filenames.glob.star SYSTEM "results/filenames.glob.star.lxo">
  29.152 +<!ENTITY interaction.filenames.glob.star-starstar SYSTEM "results/filenames.glob.star-starstar.lxo">
  29.153 +<!ENTITY interaction.filenames.glob.starstar SYSTEM "results/filenames.glob.starstar.lxo">
  29.154 +<!ENTITY interaction.filenames.wdir-relname SYSTEM "results/filenames.wdir-relname.lxo">
  29.155 +<!ENTITY interaction.filenames.wdir-subdir SYSTEM "results/filenames.wdir-subdir.lxo">
  29.156 +<!ENTITY interaction.hook.msglen.go SYSTEM "results/hook.msglen.go.lxo">
  29.157 +<!ENTITY interaction.hook.simple.ext SYSTEM "results/hook.simple.ext.lxo">
  29.158 +<!ENTITY interaction.hook.simple.init SYSTEM "results/hook.simple.init.lxo">
  29.159 +<!ENTITY interaction.hook.simple.pretxncommit SYSTEM "results/hook.simple.pretxncommit.lxo">
  29.160 +<!ENTITY interaction.issue29.go SYSTEM "results/issue29.go.lxo">
  29.161 +<!ENTITY interaction.mq.dodiff.diff SYSTEM "results/mq.dodiff.diff.lxo">
  29.162 +<!ENTITY interaction.mq.guards.init SYSTEM "results/mq.guards.init.lxo">
  29.163 +<!ENTITY interaction.mq.guards.qguard SYSTEM "results/mq.guards.qguard.lxo">
  29.164 +<!ENTITY interaction.mq.guards.qguard.neg SYSTEM "results/mq.guards.qguard.neg.lxo">
  29.165 +<!ENTITY interaction.mq.guards.qguard.pos SYSTEM "results/mq.guards.qguard.pos.lxo">
  29.166 +<!ENTITY interaction.mq.guards.qselect.cat SYSTEM "results/mq.guards.qselect.cat.lxo">
  29.167 +<!ENTITY interaction.mq.guards.qselect.error SYSTEM "results/mq.guards.qselect.error.lxo">
  29.168 +<!ENTITY interaction.mq.guards.qselect.foo SYSTEM "results/mq.guards.qselect.foo.lxo">
  29.169 +<!ENTITY interaction.mq.guards.qselect.foobar SYSTEM "results/mq.guards.qselect.foobar.lxo">
  29.170 +<!ENTITY interaction.mq.guards.qselect.qpush SYSTEM "results/mq.guards.qselect.qpush.lxo">
  29.171 +<!ENTITY interaction.mq.guards.qselect.quux SYSTEM "results/mq.guards.qselect.quux.lxo">
  29.172 +<!ENTITY interaction.mq.guards.series SYSTEM "results/mq.guards.series.lxo">
  29.173 +<!ENTITY interaction.mq.id.lxoput SYSTEM "results/mq.id.lxoput.lxo">
  29.174 +<!ENTITY interaction.mq.id.output SYSTEM "results/mq.id.output.lxo">
  29.175 +<!ENTITY interaction.mq.qinit-help.help SYSTEM "results/mq.qinit-help.help.lxo">
  29.176 +<!ENTITY interaction.mq.tarball.download SYSTEM "results/mq.tarball.download.lxo">
  29.177 +<!ENTITY interaction.mq.tarball.newsource SYSTEM "results/mq.tarball.newsource.lxo">
  29.178 +<!ENTITY interaction.mq.tarball.qinit SYSTEM "results/mq.tarball.qinit.lxo">
  29.179 +<!ENTITY interaction.mq.tarball.repush SYSTEM "results/mq.tarball.repush.lxo">
  29.180 +<!ENTITY interaction.mq.tools.lsdiff SYSTEM "results/mq.tools.lsdiff.lxo">
  29.181 +<!ENTITY interaction.mq.tools.tools SYSTEM "results/mq.tools.tools.lxo">
  29.182 +<!ENTITY interaction.mq.tutorial.add SYSTEM "results/mq.tutorial.add.lxo">
  29.183 +<!ENTITY interaction.mq.tutorial.qinit SYSTEM "results/mq.tutorial.qinit.lxo">
  29.184 +<!ENTITY interaction.mq.tutorial.qnew SYSTEM "results/mq.tutorial.qnew.lxo">
  29.185 +<!ENTITY interaction.mq.tutorial.qnew2 SYSTEM "results/mq.tutorial.qnew2.lxo">
  29.186 +<!ENTITY interaction.mq.tutorial.qpop SYSTEM "results/mq.tutorial.qpop.lxo">
  29.187 +<!ENTITY interaction.mq.tutorial.qpush-a SYSTEM "results/mq.tutorial.qpush-a.lxo">
  29.188 +<!ENTITY interaction.mq.tutorial.qrefresh SYSTEM "results/mq.tutorial.qrefresh.lxo">
  29.189 +<!ENTITY interaction.mq.tutorial.qrefresh2 SYSTEM "results/mq.tutorial.qrefresh2.lxo">
  29.190 +<!ENTITY interaction.mq.tutorial.qseries SYSTEM "results/mq.tutorial.qseries.lxo">
  29.191 +<!ENTITY interaction.rename.divergent.clone SYSTEM "results/rename.divergent.clone.lxo">
  29.192 +<!ENTITY interaction.rename.divergent.merge SYSTEM "results/rename.divergent.merge.lxo">
  29.193 +<!ENTITY interaction.rename.divergent.rename.anne SYSTEM "results/rename.divergent.rename.anne.lxo">
  29.194 +<!ENTITY interaction.rename.divergent.rename.bob SYSTEM "results/rename.divergent.rename.bob.lxo">
  29.195 +<!ENTITY interaction.rollback.add SYSTEM "results/rollback.add.lxo">
  29.196 +<!ENTITY interaction.rollback.commit SYSTEM "results/rollback.commit.lxo">
  29.197 +<!ENTITY interaction.rollback.rollback SYSTEM "results/rollback.rollback.lxo">
  29.198 +<!ENTITY interaction.rollback.status SYSTEM "results/rollback.status.lxo">
  29.199 +<!ENTITY interaction.rollback.tip SYSTEM "results/rollback.tip.lxo">
  29.200 +<!ENTITY interaction.rollback.twice SYSTEM "results/rollback.twice.lxo">
  29.201 +<!ENTITY interaction.tag.init SYSTEM "results/tag.init.lxo">
  29.202 +<!ENTITY interaction.tag.log SYSTEM "results/tag.log.lxo">
  29.203 +<!ENTITY interaction.tag.log.v1.0 SYSTEM "results/tag.log.v1.0.lxo">
  29.204 +<!ENTITY interaction.tag.remove SYSTEM "results/tag.remove.lxo">
  29.205 +<!ENTITY interaction.tag.replace SYSTEM "results/tag.replace.lxo">
  29.206 +<!ENTITY interaction.tag.tag SYSTEM "results/tag.tag.lxo">
  29.207 +<!ENTITY interaction.tag.tags SYSTEM "results/tag.tags.lxo">
  29.208 +<!ENTITY interaction.tag.tip SYSTEM "results/tag.tip.lxo">
  29.209 +<!ENTITY interaction.template.simple.changelog SYSTEM "results/template.simple.changelog.lxo">
  29.210 +<!ENTITY interaction.template.simple.combine SYSTEM "results/template.simple.combine.lxo">
  29.211 +<!ENTITY interaction.template.simple.compact SYSTEM "results/template.simple.compact.lxo">
  29.212 +<!ENTITY interaction.template.simple.datekeyword SYSTEM "results/template.simple.datekeyword.lxo">
  29.213 +<!ENTITY interaction.template.simple.keywords SYSTEM "results/template.simple.keywords.lxo">
  29.214 +<!ENTITY interaction.template.simple.manyfilters SYSTEM "results/template.simple.manyfilters.lxo">
  29.215 +<!ENTITY interaction.template.simple.normal SYSTEM "results/template.simple.normal.lxo">
  29.216 +<!ENTITY interaction.template.simple.rev SYSTEM "results/template.simple.rev.lxo">
  29.217 +<!ENTITY interaction.template.simple.simplest SYSTEM "results/template.simple.simplest.lxo">
  29.218 +<!ENTITY interaction.template.simple.simplesub SYSTEM "results/template.simple.simplesub.lxo">
  29.219 +<!ENTITY interaction.template.svnstyle.id SYSTEM "results/template.svnstyle.id.lxo">
  29.220 +<!ENTITY interaction.template.svnstyle.result SYSTEM "results/template.svnstyle.result.lxo">
  29.221 +<!ENTITY interaction.template.svnstyle.short SYSTEM "results/template.svnstyle.short.lxo">
  29.222 +<!ENTITY interaction.template.svnstyle.simplest SYSTEM "results/template.svnstyle.simplest.lxo">
  29.223 +<!ENTITY interaction.template.svnstyle.style SYSTEM "results/template.svnstyle.style.lxo">
  29.224 +<!ENTITY interaction.template.svnstyle.syntax.error SYSTEM "results/template.svnstyle.syntax.error.lxo">
  29.225 +<!ENTITY interaction.template.svnstyle.syntax.input SYSTEM "results/template.svnstyle.syntax.input.lxo">
  29.226 +<!ENTITY interaction.template.svnstyle.template SYSTEM "results/template.svnstyle.template.lxo">
  29.227 +<!ENTITY interaction.tour-merge-conflict.commit SYSTEM "results/tour-merge-conflict.commit.lxo">
  29.228 +<!ENTITY interaction.tour-merge-conflict.cousin SYSTEM "results/tour-merge-conflict.cousin.lxo">
  29.229 +<!ENTITY interaction.tour-merge-conflict.merge SYSTEM "results/tour-merge-conflict.merge.lxo">
  29.230 +<!ENTITY interaction.tour-merge-conflict.pull SYSTEM "results/tour-merge-conflict.pull.lxo">
  29.231 +<!ENTITY interaction.tour-merge-conflict.son SYSTEM "results/tour-merge-conflict.son.lxo">
  29.232 +<!ENTITY interaction.tour-merge-conflict.wife SYSTEM "results/tour-merge-conflict.wife.lxo">
  29.233 +<!ENTITY interaction.tour.cat1 SYSTEM "results/tour.cat1.lxo">
  29.234 +<!ENTITY interaction.tour.cat2 SYSTEM "results/tour.cat2.lxo">
  29.235 +<!ENTITY interaction.tour.clone SYSTEM "results/tour.clone.lxo">
  29.236 +<!ENTITY interaction.tour.clone-pull SYSTEM "results/tour.clone-pull.lxo">
  29.237 +<!ENTITY interaction.tour.clone-push SYSTEM "results/tour.clone-push.lxo">
  29.238 +<!ENTITY interaction.tour.commit SYSTEM "results/tour.commit.lxo">
  29.239 +<!ENTITY interaction.tour.diff SYSTEM "results/tour.diff.lxo">
  29.240 +<!ENTITY interaction.tour.help SYSTEM "results/tour.help.lxo">
  29.241 +<!ENTITY interaction.tour.incoming SYSTEM "results/tour.incoming.lxo">
  29.242 +<!ENTITY interaction.tour.log SYSTEM "results/tour.log.lxo">
  29.243 +<!ENTITY interaction.tour.log-r SYSTEM "results/tour.log-r.lxo">
  29.244 +<!ENTITY interaction.tour.log-v SYSTEM "results/tour.log-v.lxo">
  29.245 +<!ENTITY interaction.tour.log-vp SYSTEM "results/tour.log-vp.lxo">
  29.246 +<!ENTITY interaction.tour.log.range SYSTEM "results/tour.log.range.lxo">
  29.247 +<!ENTITY interaction.tour.ls SYSTEM "results/tour.ls.lxo">
  29.248 +<!ENTITY interaction.tour.ls-a SYSTEM "results/tour.ls-a.lxo">
  29.249 +<!ENTITY interaction.tour.lxogoing SYSTEM "results/tour.lxogoing.lxo">
  29.250 +<!ENTITY interaction.tour.lxogoing.net SYSTEM "results/tour.lxogoing.net.lxo">
  29.251 +<!ENTITY interaction.tour.merge.cat SYSTEM "results/tour.merge.cat.lxo">
  29.252 +<!ENTITY interaction.tour.merge.cat1 SYSTEM "results/tour.merge.cat1.lxo">
  29.253 +<!ENTITY interaction.tour.merge.cat2 SYSTEM "results/tour.merge.cat2.lxo">
  29.254 +<!ENTITY interaction.tour.merge.clone SYSTEM "results/tour.merge.clone.lxo">
  29.255 +<!ENTITY interaction.tour.merge.commit SYSTEM "results/tour.merge.commit.lxo">
  29.256 +<!ENTITY interaction.tour.merge.dummy1 SYSTEM "results/tour.merge.dummy1.lxo">
  29.257 +<!ENTITY interaction.tour.merge.dummy2 SYSTEM "results/tour.merge.dummy2.lxo">
  29.258 +<!ENTITY interaction.tour.merge.dummy3 SYSTEM "results/tour.merge.dummy3.lxo">
  29.259 +<!ENTITY interaction.tour.merge.dummy4 SYSTEM "results/tour.merge.dummy4.lxo">
  29.260 +<!ENTITY interaction.tour.merge.heads SYSTEM "results/tour.merge.heads.lxo">
  29.261 +<!ENTITY interaction.tour.merge.merge SYSTEM "results/tour.merge.merge.lxo">
  29.262 +<!ENTITY interaction.tour.merge.parents SYSTEM "results/tour.merge.parents.lxo">
  29.263 +<!ENTITY interaction.tour.merge.pull SYSTEM "results/tour.merge.pull.lxo">
  29.264 +<!ENTITY interaction.tour.merge.tip SYSTEM "results/tour.merge.tip.lxo">
  29.265 +<!ENTITY interaction.tour.merge.update SYSTEM "results/tour.merge.update.lxo">
  29.266 +<!ENTITY interaction.tour.older SYSTEM "results/tour.older.lxo">
  29.267 +<!ENTITY interaction.tour.outgoing SYSTEM "results/tour.outgoing.lxo">
  29.268 +<!ENTITY interaction.tour.outgoing.net SYSTEM "results/tour.outgoing.net.lxo">
  29.269 +<!ENTITY interaction.tour.parents SYSTEM "results/tour.parents.lxo">
  29.270 +<!ENTITY interaction.tour.pull SYSTEM "results/tour.pull.lxo">
  29.271 +<!ENTITY interaction.tour.push SYSTEM "results/tour.push.lxo">
  29.272 +<!ENTITY interaction.tour.push.net SYSTEM "results/tour.push.net.lxo">
  29.273 +<!ENTITY interaction.tour.push.nothing SYSTEM "results/tour.push.nothing.lxo">
  29.274 +<!ENTITY interaction.tour.reclone SYSTEM "results/tour.reclone.lxo">
  29.275 +<!ENTITY interaction.tour.sed SYSTEM "results/tour.sed.lxo">
  29.276 +<!ENTITY interaction.tour.status SYSTEM "results/tour.status.lxo">
  29.277 +<!ENTITY interaction.tour.tip SYSTEM "results/tour.tip.lxo">
  29.278 +<!ENTITY interaction.tour.update SYSTEM "results/tour.update.lxo">
  29.279 +<!ENTITY interaction.tour.version SYSTEM "results/tour.version.lxo">
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/fr/examples/backout	Sat Jul 10 06:24:49 2010 +0100
    30.3 @@ -0,0 +1,87 @@
    30.4 +#!/bin/bash
    30.5 +
    30.6 +# We have to fake the merges here, because they cause conflicts with
    30.7 +# three-way command-line merge, and kdiff3 may not be available.
    30.8 +
    30.9 +export HGMERGE=$(mktemp)
   30.10 +echo '#!/bin/sh' >> $HGMERGE
   30.11 +echo 'echo first change > "$1"' >> $HGMERGE
   30.12 +echo 'echo third change >> "$1"' >> $HGMERGE
   30.13 +chmod 700 $HGMERGE
   30.14 +
   30.15 +#$ name: init
   30.16 +
   30.17 +hg init myrepo
   30.18 +cd myrepo
   30.19 +echo first change >> myfile
   30.20 +hg add myfile
   30.21 +hg commit -m 'first change'
   30.22 +echo second change >> myfile
   30.23 +hg commit -m 'second change'
   30.24 +
   30.25 +#$ name: simple
   30.26 +
   30.27 +hg backout -m 'back out second change' tip
   30.28 +cat myfile
   30.29 +
   30.30 +#$ name: simple.log
   30.31 +#$ ignore: \s+200[78]-.*
   30.32 +
   30.33 +hg log --style compact
   30.34 +
   30.35 +#$ name: non-tip.clone
   30.36 +
   30.37 +cd ..
   30.38 +hg clone -r1 myrepo non-tip-repo
   30.39 +cd non-tip-repo
   30.40 +
   30.41 +#$ name: non-tip.backout
   30.42 +
   30.43 +echo third change >> myfile
   30.44 +hg commit -m 'third change'
   30.45 +hg backout --merge -m 'back out second change' 1
   30.46 +
   30.47 +#$ name: non-tip.cat
   30.48 +cat myfile
   30.49 +
   30.50 +#$ name: manual.clone
   30.51 +
   30.52 +cd ..
   30.53 +hg clone -r1 myrepo newrepo
   30.54 +cd newrepo
   30.55 +
   30.56 +#$ name: manual.backout
   30.57 +
   30.58 +echo third change >> myfile
   30.59 +hg commit -m 'third change'
   30.60 +hg backout -m 'back out second change' 1
   30.61 +
   30.62 +#$ name: manual.log
   30.63 +
   30.64 +hg log --style compact
   30.65 +
   30.66 +#$ name: manual.parents
   30.67 +
   30.68 +hg parents
   30.69 +
   30.70 +#$ name: manual.heads
   30.71 +
   30.72 +hg heads
   30.73 +
   30.74 +#$ name:
   30.75 +
   30.76 +echo 'first change' > myfile
   30.77 +
   30.78 +#$ name: manual.cat
   30.79 +
   30.80 +cat myfile
   30.81 +
   30.82 +#$ name: manual.merge
   30.83 +
   30.84 +hg merge
   30.85 +hg commit -m 'merged backout with previous tip'
   30.86 +cat myfile
   30.87 +
   30.88 +#$ name:
   30.89 +
   30.90 +rm $HGMERGE
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/fr/examples/bisect	Sat Jul 10 06:24:49 2010 +0100
    31.3 @@ -0,0 +1,92 @@
    31.4 +#!/bin/bash
    31.5 +
    31.6 +if  hg -v | head -1 | grep -e "version 0.*"
    31.7 +then
    31.8 +#On mercurial 1.0 and later bisect is a builtin
    31.9 +echo '[extensions]' >> $HGRC
   31.10 +echo 'hbisect =' >> $HGRC
   31.11 +fi
   31.12 +
   31.13 +# XXX There's some kind of horrible nondeterminism in the execution of
   31.14 +# bisect at the moment.  Ugh.
   31.15 +
   31.16 +#$ ignore: .*
   31.17 +
   31.18 +#$ name: init
   31.19 +
   31.20 +hg init mybug
   31.21 +cd mybug
   31.22 +
   31.23 +#$ name: commits
   31.24 +
   31.25 +buggy_change=22
   31.26 +
   31.27 +for (( i = 0; i < 35; i++ )); do
   31.28 +  if [[ $i = $buggy_change ]]; then
   31.29 +    echo 'i have a gub' > myfile$i
   31.30 +    hg commit -q -A -m 'buggy changeset'
   31.31 +  else
   31.32 +    echo 'nothing to see here, move along' > myfile$i
   31.33 +    hg commit -q -A -m 'normal changeset'
   31.34 +  fi
   31.35 +done
   31.36 +
   31.37 +#$ name: help
   31.38 +
   31.39 +hg help bisect
   31.40 +
   31.41 +#$ name: search.init
   31.42 +
   31.43 +hg bisect --reset
   31.44 +
   31.45 +#$ name: search.bad-init
   31.46 +
   31.47 +hg bisect --bad
   31.48 +
   31.49 +#$ name: search.good-init
   31.50 +
   31.51 +hg bisect --good 10
   31.52 +
   31.53 +#$ name: search.step1
   31.54 +
   31.55 +if grep -q 'i have a gub' *
   31.56 +then
   31.57 +  result=bad
   31.58 +else
   31.59 +  result=good
   31.60 +fi
   31.61 +
   31.62 +echo this revision is $result
   31.63 +hg bisect --$result
   31.64 +
   31.65 +#$ name: search.mytest
   31.66 +
   31.67 +mytest() {
   31.68 +  if grep -q 'i have a gub' *
   31.69 +  then
   31.70 +    result=bad
   31.71 +  else
   31.72 +    result=good
   31.73 +  fi
   31.74 +
   31.75 +  echo this revision is $result
   31.76 +  hg bisect --$result
   31.77 +}
   31.78 +  
   31.79 +#$ name: search.step2
   31.80 +
   31.81 +mytest
   31.82 +
   31.83 +#$ name: search.rest
   31.84 +
   31.85 +mytest
   31.86 +mytest
   31.87 +mytest
   31.88 +
   31.89 +#$ name: search.reset
   31.90 +
   31.91 +hg bisect --reset
   31.92 +
   31.93 +#$ name:
   31.94 +
   31.95 +exit 0
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/fr/examples/branch-named	Sat Jul 10 06:24:49 2010 +0100
    32.3 @@ -0,0 +1,73 @@
    32.4 +#!/bin/bash
    32.5 +
    32.6 +hg init a
    32.7 +cd a
    32.8 +echo hello > myfile
    32.9 +hg commit -A -m 'Initial commit'
   32.10 +
   32.11 +#$ name: branches
   32.12 +
   32.13 +hg tip
   32.14 +hg branches
   32.15 +
   32.16 +#$ name: branch
   32.17 +
   32.18 +hg branch
   32.19 +
   32.20 +#$ name: create
   32.21 +
   32.22 +hg branch foo
   32.23 +hg branch
   32.24 +
   32.25 +#$ name: status
   32.26 +
   32.27 +hg status
   32.28 +hg tip
   32.29 +
   32.30 +#$ name: commit
   32.31 +
   32.32 +echo 'hello again' >> myfile
   32.33 +hg commit -m 'Second commit'
   32.34 +hg tip
   32.35 +
   32.36 +#$ name: rebranch
   32.37 +
   32.38 +hg branch
   32.39 +hg branch bar
   32.40 +echo new file > newfile
   32.41 +hg commit -A -m 'Third commit'
   32.42 +hg tip
   32.43 +
   32.44 +#$ name: parents
   32.45 +
   32.46 +hg parents
   32.47 +hg branches
   32.48 +
   32.49 +#$ name: update-switchy
   32.50 +
   32.51 +hg update foo
   32.52 +hg parents
   32.53 +hg update bar
   32.54 +hg parents
   32.55 +
   32.56 +#$ name: update-nothing
   32.57 +
   32.58 +hg update foo
   32.59 +hg update
   32.60 +
   32.61 +#$ name: foo-commit
   32.62 +
   32.63 +echo something > somefile
   32.64 +hg commit -A -m 'New file'
   32.65 +hg heads
   32.66 +
   32.67 +#$ name: update-bar
   32.68 +
   32.69 +hg update bar
   32.70 +
   32.71 +#$ name: merge
   32.72 +
   32.73 +hg branch
   32.74 +hg merge foo
   32.75 +hg commit -m 'Merge'
   32.76 +hg tip
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/fr/examples/branch-repo	Sat Jul 10 06:24:49 2010 +0100
    33.3 @@ -0,0 +1,48 @@
    33.4 +#!/bin/bash
    33.5 +
    33.6 +hg init myproject
    33.7 +cd myproject
    33.8 +echo hello > myfile
    33.9 +hg commit -A -m 'Initial commit'
   33.10 +cd ..
   33.11 +
   33.12 +#$ name: tag
   33.13 +
   33.14 +cd myproject
   33.15 +hg tag v1.0
   33.16 +
   33.17 +#$ name: clone
   33.18 +
   33.19 +cd ..
   33.20 +hg clone myproject myproject-1.0.1
   33.21 +
   33.22 +#$ name: bugfix
   33.23 +
   33.24 +hg clone myproject-1.0.1 my-1.0.1-bugfix
   33.25 +cd my-1.0.1-bugfix
   33.26 +echo 'I fixed a bug using only echo!' >> myfile
   33.27 +hg commit -m 'Important fix for 1.0.1'
   33.28 +#$ ignore: /tmp/branch-repo.*
   33.29 +hg push
   33.30 +
   33.31 +#$ name: new
   33.32 +
   33.33 +cd ..
   33.34 +hg clone myproject my-feature
   33.35 +cd my-feature
   33.36 +echo 'This sure is an exciting new feature!' > mynewfile
   33.37 +hg commit -A -m 'New feature'
   33.38 +hg push
   33.39 +
   33.40 +#$ name: pull
   33.41 +
   33.42 +cd ..
   33.43 +hg clone myproject myproject-merge
   33.44 +cd myproject-merge
   33.45 +hg pull ../myproject-1.0.1
   33.46 +
   33.47 +#$ name: merge
   33.48 +
   33.49 +hg merge
   33.50 +hg commit -m 'Merge bugfix from 1.0.1 branch'
   33.51 +hg push
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/fr/examples/branching	Sat Jul 10 06:24:49 2010 +0100
    34.3 @@ -0,0 +1,63 @@
    34.4 +#!/bin/bash
    34.5 +
    34.6 +#$ name: init
    34.7 +
    34.8 +hg init main
    34.9 +cd main
   34.10 +echo 'This is a boring feature.' > myfile
   34.11 +hg commit -A -m 'We have reached an important milestone!'
   34.12 +
   34.13 +#$ name: tag
   34.14 +
   34.15 +hg tag v1.0
   34.16 +hg tip
   34.17 +hg tags
   34.18 +
   34.19 +#$ name: main
   34.20 +
   34.21 +cd ../main
   34.22 +echo 'This is exciting and new!' >> myfile
   34.23 +hg commit -m 'Add a new feature'
   34.24 +cat myfile
   34.25 +
   34.26 +#$ name: update
   34.27 +
   34.28 +cd ..
   34.29 +hg clone -U main main-old
   34.30 +cd main-old
   34.31 +hg update v1.0
   34.32 +cat myfile
   34.33 +
   34.34 +#$ name: clone
   34.35 +
   34.36 +cd ..
   34.37 +hg clone -rv1.0 main stable
   34.38 +
   34.39 +#$ name: stable
   34.40 +
   34.41 +hg clone stable stable-fix
   34.42 +cd stable-fix
   34.43 +echo 'This is a fix to a boring feature.' > myfile
   34.44 +hg commit -m 'Fix a bug'
   34.45 +#$ ignore: /tmp/branching.*
   34.46 +hg push
   34.47 +
   34.48 +#$ name:
   34.49 +
   34.50 +export HGMERGE=$(mktemp)
   34.51 +echo '#!/bin/sh' > $HGMERGE
   34.52 +echo 'echo "This is a fix to a boring feature." > "$1"' >> $HGMERGE
   34.53 +echo 'echo "This is exciting and new!" >> "$1"' >> $HGMERGE
   34.54 +chmod 700 $HGMERGE
   34.55 +
   34.56 +#$ name: merge
   34.57 +
   34.58 +cd ../main
   34.59 +hg pull ../stable
   34.60 +hg merge
   34.61 +hg commit -m 'Bring in bugfix from stable branch'
   34.62 +cat myfile
   34.63 +
   34.64 +#$ name:
   34.65 +
   34.66 +rm $HGMERGE
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/fr/examples/ch01/new	Sat Jul 10 06:24:49 2010 +0100
    35.3 @@ -0,0 +1,39 @@
    35.4 +#!/bin/bash
    35.5 +
    35.6 +cat > hello.c <<EOF
    35.7 +int main()
    35.8 +{
    35.9 +    printf("hello world!\n");
   35.10 +}
   35.11 +EOF
   35.12 +
   35.13 +cat > goodbye.c <<EOF
   35.14 +int main()
   35.15 +{
   35.16 +    printf("goodbye world!\n");
   35.17 +}
   35.18 +EOF
   35.19 +
   35.20 +#$ name: init
   35.21 +
   35.22 +hg init myproject
   35.23 +
   35.24 +#$ name: ls
   35.25 +
   35.26 +ls -l
   35.27 +
   35.28 +#$ name: ls2
   35.29 +
   35.30 +ls -al myproject
   35.31 +
   35.32 +#$ name: add
   35.33 +
   35.34 +cd myproject
   35.35 +cp ../hello.c .
   35.36 +cp ../goodbye.c .
   35.37 +hg add
   35.38 +hg status
   35.39 +
   35.40 +#$ name: commit
   35.41 +
   35.42 +hg commit -m 'Initial commit'
    36.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.2 +++ b/fr/examples/ch04/diff	Sat Jul 10 06:24:49 2010 +0100
    36.3 @@ -0,0 +1,30 @@
    36.4 +#!/bin/bash
    36.5 +
    36.6 +hg init a
    36.7 +cd a
    36.8 +echo a > a
    36.9 +hg ci -Ama
   36.10 +
   36.11 +#$ name: rename.basic
   36.12 +
   36.13 +hg rename a b
   36.14 +hg diff
   36.15 +
   36.16 +#$ name: rename.git
   36.17 +
   36.18 +hg diff -g
   36.19 +
   36.20 +#$ name:
   36.21 +
   36.22 +hg revert -a
   36.23 +rm b
   36.24 +
   36.25 +#$ name: chmod
   36.26 +
   36.27 +chmod +x a
   36.28 +hg st
   36.29 +hg diff
   36.30 +
   36.31 +#$ name: chmod.git
   36.32 +
   36.33 +hg diff -g
    37.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.2 +++ b/fr/examples/ch04/resolve	Sat Jul 10 06:24:49 2010 +0100
    37.3 @@ -0,0 +1,38 @@
    37.4 +#$ name: init
    37.5 +hg init conflict
    37.6 +cd conflict
    37.7 +echo first > myfile.txt
    37.8 +hg ci -A -m first
    37.9 +cd ..
   37.10 +hg clone conflict left
   37.11 +hg clone conflict right
   37.12 +
   37.13 +#$ name: left
   37.14 +cd left
   37.15 +echo left >> myfile.txt
   37.16 +hg ci -m left
   37.17 +
   37.18 +#$ name: right
   37.19 +cd ../right
   37.20 +echo right >> myfile.txt
   37.21 +hg ci -m right
   37.22 +
   37.23 +#$ name: pull
   37.24 +cd ../conflict
   37.25 +hg pull -u ../left
   37.26 +hg pull -u ../right
   37.27 +
   37.28 +#$ name: heads
   37.29 +hg heads
   37.30 +
   37.31 +#$ name: export
   37.32 +export HGMERGE=false
   37.33 +
   37.34 +#$ name: merge
   37.35 +hg merge
   37.36 +
   37.37 +#$ name: cifail
   37.38 +hg commit -m 'Attempt to commit a failed merge'
   37.39 +
   37.40 +#$ name: list
   37.41 +hg resolve -l
    38.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.2 +++ b/fr/examples/ch06/apache-config.lst	Sat Jul 10 06:24:49 2010 +0100
    38.3 @@ -0,0 +1,11 @@
    38.4 +<Directory /home/*/public_html>
    38.5 +  AllowOverride FileInfo AuthConfig Limit
    38.6 +  Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
    38.7 +  <Limit GET POST OPTIONS>
    38.8 +    Order allow,deny
    38.9 +    Allow from all
   38.10 +  </Limit>
   38.11 +  <LimitExcept GET POST OPTIONS>
   38.12 +    Order deny,allow Deny from all
   38.13 +  </LimitExcept>
   38.14 +</Directory>
    39.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.2 +++ b/fr/examples/ch09/check_whitespace.py.lst	Sat Jul 10 06:24:49 2010 +0100
    39.3 @@ -0,0 +1,47 @@
    39.4 +#!/usr/bin/env python
    39.5 +#
    39.6 +# save as .hg/check_whitespace.py and make executable
    39.7 +
    39.8 +import re
    39.9 +
   39.10 +def trailing_whitespace(difflines):
   39.11 +    # 
   39.12 +    linenum, header = 0, False
   39.13 +
   39.14 +    for line in difflines:
   39.15 +        if header:
   39.16 +            # remember the name of the file that this diff affects
   39.17 +            m = re.match(r'(?:---|\+\+\+) ([^\t]+)', line)
   39.18 +            if m and m.group(1) != '/dev/null':
   39.19 +                filename = m.group(1).split('/', 1)[-1]
   39.20 +            if line.startswith('+++ '):
   39.21 +                header = False
   39.22 +            continue
   39.23 +        if line.startswith('diff '):
   39.24 +            header = True
   39.25 +            continue
   39.26 +        # hunk header - save the line number
   39.27 +        m = re.match(r'@@ -\d+,\d+ \+(\d+),', line)
   39.28 +        if m:
   39.29 +            linenum = int(m.group(1))
   39.30 +            continue
   39.31 +        # hunk body - check for an added line with trailing whitespace
   39.32 +        m = re.match(r'\+.*\s$', line)
   39.33 +        if m:
   39.34 +            yield filename, linenum
   39.35 +        if line and line[0] in ' +':
   39.36 +            linenum += 1
   39.37 +
   39.38 +if __name__ == '__main__':
   39.39 +    import os, sys
   39.40 +    
   39.41 +    added = 0
   39.42 +    for filename, linenum in trailing_whitespace(os.popen('hg export tip')):
   39.43 +        print >> sys.stderr, ('%s, line %d: trailing whitespace added' %
   39.44 +                              (filename, linenum))
   39.45 +        added += 1
   39.46 +    if added:
   39.47 +        # save the commit message so we don't need to retype it
   39.48 +        os.system('hg tip --template "{desc}" > .hg/commit.save')
   39.49 +        print >> sys.stderr, 'commit message saved to .hg/commit.save'
   39.50 +        sys.exit(1)
    40.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.2 +++ b/fr/examples/ch09/hook.ws	Sat Jul 10 06:24:49 2010 +0100
    40.3 @@ -0,0 +1,32 @@
    40.4 +#!/bin/bash
    40.5 +
    40.6 +hg init a
    40.7 +cd a
    40.8 +echo '[hooks]' > .hg/hgrc
    40.9 +echo "pretxncommit.whitespace = hg export tip | (! egrep -q '^\\+.*[ \\t]$')" >> .hg/hgrc
   40.10 +
   40.11 +#$ name: simple
   40.12 +
   40.13 +cat .hg/hgrc
   40.14 +echo 'a ' > a
   40.15 +hg commit -A -m 'test with trailing whitespace'
   40.16 +echo 'a' > a
   40.17 +hg commit -A -m 'drop trailing whitespace and try again'
   40.18 +
   40.19 +#$ name:
   40.20 +
   40.21 +echo '[hooks]' > .hg/hgrc
   40.22 +echo "pretxncommit.whitespace = .hg/check_whitespace.py" >> .hg/hgrc
   40.23 +cp $EXAMPLE_DIR/ch09/check_whitespace.py.lst .hg/check_whitespace.py
   40.24 +chmod +x .hg/check_whitespace.py
   40.25 +
   40.26 +#$ name: better
   40.27 +
   40.28 +cat .hg/hgrc
   40.29 +echo 'a ' >> a
   40.30 +hg commit -A -m 'add new line with trailing whitespace'
   40.31 +sed -i 's, *$,,' a
   40.32 +hg commit -A -m 'trimmed trailing whitespace'
   40.33 +
   40.34 +#$ name:
   40.35 +exit 0
    41.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    41.2 +++ b/fr/examples/ch10/bugzilla-config.lst	Sat Jul 10 06:24:49 2010 +0100
    41.3 @@ -0,0 +1,14 @@
    41.4 +[bugzilla]
    41.5 +host = bugzilla.example.com
    41.6 +password = mypassword version = 2.16
    41.7 +# server-side repos live in /home/hg/repos, so strip 4 leading
    41.8 +# separators
    41.9 +strip = 4
   41.10 +hgweb = http://hg.example.com/
   41.11 +usermap = /home/hg/repos/notify/bugzilla.conf
   41.12 +template = Changeset {node|short}, made by {author} in the {webroot}
   41.13 +  repo, refers to this bug.\n
   41.14 +  For complete details, see
   41.15 +  {hgweb}{webroot}?cmd=changeset;node={node|short}\n
   41.16 +  Changeset description:\n
   41.17 +  \t{desc|tabindent}
    42.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.2 +++ b/fr/examples/ch10/multiline	Sat Jul 10 06:24:49 2010 +0100
    42.3 @@ -0,0 +1,13 @@
    42.4 +#!/bin/sh
    42.5 +
    42.6 +hg init
    42.7 +echo a > test.c
    42.8 +hg ci -Am'First commit'
    42.9 +
   42.10 +#$ name: go
   42.11 +
   42.12 +cat > multiline << EOF
   42.13 +changeset = "Changed in {node|short}:\n{files}"
   42.14 +file = "  {file}\n"
   42.15 +EOF
   42.16 +hg log --style multiline
    43.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    43.2 +++ b/fr/examples/ch10/notify-config-mail.lst	Sat Jul 10 06:24:49 2010 +0100
    43.3 @@ -0,0 +1,18 @@
    43.4 +X-Hg-Repo: tests/slave
    43.5 +Subject: tests/slave: Handle error case when slave has no buffers
    43.6 +Date: Wed,  2 Aug 2006 15:25:46 -0700 (PDT)
    43.7 +
    43.8 +changeset 3cba9bfe74b5 in /home/hg/repos/tests/slave
    43.9 +
   43.10 +details:
   43.11 +http://hg.example.com/tests/slave?cmd=changeset;node=3cba9bfe74b5 
   43.12 +
   43.13 +description: Handle error case when slave has no buffers
   43.14 +
   43.15 +diffs (54 lines):
   43.16 +diff -r 9d95df7cf2ad -r 3cba9bfe74b5 include/tests.h
   43.17 +--- a/include/tests.h      Wed Aug 02 15:19:52 2006 -0700
   43.18 ++++ b/include/tests.h      Wed Aug 02 15:25:26 2006 -0700
   43.19 +@@ -212,6 +212,15 @@ static __inline__
   43.20 +void test_headers(void *h)
   43.21 +[...snip...]
    44.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    44.2 +++ b/fr/examples/ch10/notify-config.lst	Sat Jul 10 06:24:49 2010 +0100
    44.3 @@ -0,0 +1,19 @@
    44.4 +[notify]
    44.5 +# really send email
    44.6 +test = false
    44.7 +# subscriber data lives in the notify repo
    44.8 +config = /home/hg/repos/notify/notify.conf
    44.9 +# repos live in /home/hg/repos on server, so strip 4 "/" chars
   44.10 +strip = 4
   44.11 +template = X-Hg-Repo: {webroot}\n
   44.12 +  Subject: {webroot}: {desc|firstline|strip}\n
   44.13 +  From: {author}
   44.14 +  \n\n
   44.15 +  changeset {node|short} in {root}
   44.16 +  \n\ndetails:
   44.17 +  {baseurl}{webroot}?cmd=changeset;node={node|short}
   44.18 +  description: {desc|tabindent|strip}
   44.19 +
   44.20 +[web]
   44.21 +baseurl =
   44.22 +http://hg.example.com/
    45.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    45.2 +++ b/fr/examples/ch11/qdelete	Sat Jul 10 06:24:49 2010 +0100
    45.3 @@ -0,0 +1,32 @@
    45.4 +#!/bin/bash
    45.5 +
    45.6 +echo '[extensions]' >> $HGRC
    45.7 +echo 'hgext.mq =' >> $HGRC
    45.8 +
    45.9 +#$ name: go
   45.10 +
   45.11 +hg init myrepo
   45.12 +cd myrepo
   45.13 +hg qinit
   45.14 +hg qnew bad.patch
   45.15 +echo a > a
   45.16 +hg add a
   45.17 +hg qrefresh
   45.18 +hg qdelete bad.patch
   45.19 +hg qpop
   45.20 +hg qdelete bad.patch
   45.21 +
   45.22 +#$ name: convert
   45.23 +
   45.24 +hg qnew good.patch
   45.25 +echo a > a
   45.26 +hg add a
   45.27 +hg qrefresh -m 'Good change'
   45.28 +hg qfinish tip
   45.29 +hg qapplied
   45.30 +hg tip --style=compact
   45.31 +
   45.32 +#$ name: import
   45.33 +
   45.34 +hg qimport -r tip
   45.35 +hg qapplied
    46.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    46.2 +++ b/fr/examples/cmdref	Sat Jul 10 06:24:49 2010 +0100
    46.3 @@ -0,0 +1,22 @@
    46.4 +#!/bin/bash
    46.5 +
    46.6 +hg init diff
    46.7 +cd diff
    46.8 +cat > myfile.c <<EOF
    46.9 +int myfunc()
   46.10 +{
   46.11 +    return 1;
   46.12 +}
   46.13 +EOF
   46.14 +hg ci -Ama
   46.15 +
   46.16 +sed -ie 's/return 1/return 10/' myfile.c
   46.17 +
   46.18 +#$ name: diff-p
   46.19 +
   46.20 +echo '[diff]' >> $HGRC
   46.21 +echo 'showfunc = False' >> $HGRC
   46.22 +
   46.23 +hg diff
   46.24 +
   46.25 +hg diff -p
    47.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.2 +++ b/fr/examples/daily.copy	Sat Jul 10 06:24:49 2010 +0100
    47.3 @@ -0,0 +1,82 @@
    47.4 +#!/bin/bash
    47.5 +
    47.6 +#$ name: init
    47.7 +
    47.8 +hg init my-copy
    47.9 +cd my-copy
   47.10 +echo line > file
   47.11 +hg add file
   47.12 +hg commit -m 'Added a file'
   47.13 +
   47.14 +#$ name: clone
   47.15 +
   47.16 +cd ..
   47.17 +hg clone my-copy your-copy
   47.18 +
   47.19 +#$ name: copy
   47.20 +
   47.21 +cd my-copy
   47.22 +hg copy file new-file
   47.23 +
   47.24 +#$ name: status
   47.25 +
   47.26 +hg status
   47.27 +
   47.28 +#$ name: status-copy
   47.29 +
   47.30 +hg status -C
   47.31 +hg commit -m 'Copied file'
   47.32 +
   47.33 +#$ name: other
   47.34 +
   47.35 +cd ../your-copy
   47.36 +echo 'new contents' >> file
   47.37 +hg commit -m 'Changed file'
   47.38 +
   47.39 +#$ name: cat
   47.40 +
   47.41 +cat file
   47.42 +cat ../my-copy/new-file
   47.43 +
   47.44 +#$ name: merge
   47.45 +
   47.46 +hg pull ../my-copy
   47.47 +hg merge
   47.48 +cat new-file
   47.49 +
   47.50 +#$ name:
   47.51 +
   47.52 +cd ..
   47.53 +hg init copy-example
   47.54 +cd copy-example
   47.55 +echo a > a
   47.56 +echo b > b
   47.57 +mkdir z
   47.58 +mkdir z/a
   47.59 +echo c > z/a/c
   47.60 +hg ci -Ama
   47.61 +
   47.62 +#$ name: simple
   47.63 +
   47.64 +mkdir k
   47.65 +hg copy a k
   47.66 +ls k
   47.67 +
   47.68 +#$ name: dir-dest
   47.69 +
   47.70 +mkdir d
   47.71 +hg copy a b d
   47.72 +ls d
   47.73 +
   47.74 +#$ name: dir-src
   47.75 +
   47.76 +hg copy z e
   47.77 +
   47.78 +#$ name: dir-src-dest
   47.79 +
   47.80 +hg copy z d
   47.81 +
   47.82 +#$ name: after
   47.83 +
   47.84 +cp a n
   47.85 +hg copy --after a n
    48.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    48.2 +++ b/fr/examples/daily.files	Sat Jul 10 06:24:49 2010 +0100
    48.3 @@ -0,0 +1,93 @@
    48.4 +#!/bin/bash
    48.5 +
    48.6 +#$ name: add
    48.7 +
    48.8 +hg init add-example
    48.9 +cd add-example
   48.10 +echo a > myfile.txt
   48.11 +hg status
   48.12 +hg add myfile.txt
   48.13 +hg status
   48.14 +hg commit -m 'Added one file'
   48.15 +hg status
   48.16 +
   48.17 +#$ name: add-dir
   48.18 +
   48.19 +mkdir b
   48.20 +echo b > b/somefile.txt
   48.21 +echo c > b/source.cpp
   48.22 +mkdir b/d
   48.23 +echo d > b/d/test.h
   48.24 +hg add b
   48.25 +hg commit -m 'Added all files in subdirectory'
   48.26 +
   48.27 +#$ name:
   48.28 +
   48.29 +cd ..
   48.30 +
   48.31 +#$ name: hidden
   48.32 +
   48.33 +hg init hidden-example
   48.34 +cd hidden-example
   48.35 +mkdir empty
   48.36 +touch empty/.hidden
   48.37 +hg add empty/.hidden
   48.38 +hg commit -m 'Manage an empty-looking directory'
   48.39 +ls empty
   48.40 +cd ..
   48.41 +hg clone hidden-example tmp
   48.42 +ls tmp
   48.43 +ls tmp/empty
   48.44 +
   48.45 +#$ name: remove
   48.46 +
   48.47 +hg init remove-example
   48.48 +cd remove-example
   48.49 +echo a > a
   48.50 +mkdir b
   48.51 +echo b > b/b
   48.52 +hg add a b
   48.53 +hg commit -m 'Small example for file removal'
   48.54 +hg remove a
   48.55 +hg status
   48.56 +hg remove b
   48.57 +
   48.58 +#$ name:
   48.59 +
   48.60 +cd ..
   48.61 +
   48.62 +#$ name: missing
   48.63 +hg init missing-example
   48.64 +cd missing-example
   48.65 +echo a > a
   48.66 +hg add a
   48.67 +hg commit -m 'File about to be missing'
   48.68 +rm a
   48.69 +hg status
   48.70 +
   48.71 +#$ name: remove-after
   48.72 +
   48.73 +hg remove --after a
   48.74 +hg status
   48.75 +
   48.76 +#$ name: recover-missing
   48.77 +hg revert a
   48.78 +cat a
   48.79 +hg status
   48.80 +
   48.81 +#$ name:
   48.82 +
   48.83 +cd ..
   48.84 +
   48.85 +#$ name: addremove
   48.86 +
   48.87 +hg init addremove-example
   48.88 +cd addremove-example
   48.89 +echo a > a
   48.90 +echo b > b
   48.91 +hg addremove
   48.92 +
   48.93 +#$ name: commit-addremove
   48.94 +
   48.95 +echo c > c
   48.96 +hg commit -A -m 'Commit with addremove'
    49.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    49.2 +++ b/fr/examples/daily.rename	Sat Jul 10 06:24:49 2010 +0100
    49.3 @@ -0,0 +1,18 @@
    49.4 +#!/bin/bash
    49.5 +
    49.6 +hg init a
    49.7 +cd a
    49.8 +echo a > a
    49.9 +hg ci -Ama
   49.10 +
   49.11 +#$ name: rename
   49.12 +
   49.13 +hg rename a b
   49.14 +
   49.15 +#$ name: status
   49.16 +
   49.17 +hg status
   49.18 +
   49.19 +#$ name: status-copy
   49.20 +
   49.21 +hg status -C
    50.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    50.2 +++ b/fr/examples/daily.revert	Sat Jul 10 06:24:49 2010 +0100
    50.3 @@ -0,0 +1,74 @@
    50.4 +#!/bin/bash
    50.5 +
    50.6 +hg init a
    50.7 +cd a
    50.8 +echo 'original content' > file
    50.9 +hg ci -Ama
   50.10 +
   50.11 +#$ name: modify
   50.12 +
   50.13 +cat file
   50.14 +echo unwanted change >> file
   50.15 +hg diff file
   50.16 +
   50.17 +#$ name: unmodify
   50.18 +
   50.19 +hg status
   50.20 +hg revert file
   50.21 +cat file
   50.22 +
   50.23 +#$ name: status
   50.24 +
   50.25 +hg status
   50.26 +cat file.orig
   50.27 +
   50.28 +#$ name:
   50.29 +
   50.30 +rm file.orig
   50.31 +
   50.32 +#$ name: add
   50.33 +
   50.34 +echo oops > oops
   50.35 +hg add oops
   50.36 +hg status oops
   50.37 +hg revert oops
   50.38 +hg status
   50.39 +
   50.40 +#$ name:
   50.41 +
   50.42 +rm oops
   50.43 +
   50.44 +#$ name: remove
   50.45 +
   50.46 +hg remove file
   50.47 +hg status
   50.48 +hg revert file
   50.49 +hg status
   50.50 +ls file
   50.51 +
   50.52 +#$ name: missing
   50.53 +
   50.54 +rm file
   50.55 +hg status
   50.56 +hg revert file
   50.57 +ls file
   50.58 +
   50.59 +#$ name: copy
   50.60 +
   50.61 +hg copy file new-file
   50.62 +hg revert new-file
   50.63 +hg status
   50.64 +
   50.65 +#$ name:
   50.66 +
   50.67 +rm new-file
   50.68 +
   50.69 +#$ name: rename
   50.70 +
   50.71 +hg rename file new-file
   50.72 +hg revert new-file
   50.73 +hg status
   50.74 +
   50.75 +#$ name: rename-orig
   50.76 +hg revert file
   50.77 +hg status
    51.1 Binary file fr/examples/data/netplug-1.2.5.tar.bz2 has changed
    52.1 Binary file fr/examples/data/netplug-1.2.8.tar.bz2 has changed
    53.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    53.2 +++ b/fr/examples/data/remove-redundant-null-checks.patch	Sat Jul 10 06:24:49 2010 +0100
    53.3 @@ -0,0 +1,190 @@
    53.4 +
    53.5 +From: Jesper Juhl <jesper.juhl@gmail.com>
    53.6 +
    53.7 +Remove redundant NULL chck before kfree + tiny CodingStyle cleanup for
    53.8 +drivers/
    53.9 +
   53.10 +Signed-off-by: Jesper Juhl <jesper.juhl@gmail.com>
   53.11 +Signed-off-by: Andrew Morton <akpm@osdl.org>
   53.12 +---
   53.13 +
   53.14 + drivers/char/agp/sgi-agp.c        |    5 ++---
   53.15 + drivers/char/hvcs.c               |   11 +++++------
   53.16 + drivers/message/fusion/mptfc.c    |    6 ++----
   53.17 + drivers/message/fusion/mptsas.c   |    3 +--
   53.18 + drivers/net/fs_enet/fs_enet-mii.c |    3 +--
   53.19 + drivers/net/wireless/ipw2200.c    |   22 ++++++----------------
   53.20 + drivers/scsi/libata-scsi.c        |    4 +---
   53.21 + drivers/video/au1100fb.c          |    3 +--
   53.22 + 8 files changed, 19 insertions(+), 38 deletions(-)
   53.23 +
   53.24 +diff -puN drivers/char/agp/sgi-agp.c~remove-redundant-null-checks-before-free-in-drivers drivers/char/agp/sgi-agp.c
   53.25 +--- a/drivers/char/agp/sgi-agp.c~remove-redundant-null-checks-before-free-in-drivers
   53.26 ++++ a/drivers/char/agp/sgi-agp.c
   53.27 +@@ -329,9 +329,8 @@ static int __devinit agp_sgi_init(void)
   53.28 + 
   53.29 + static void __devexit agp_sgi_cleanup(void)
   53.30 + {
   53.31 +-	if (sgi_tioca_agp_bridges)
   53.32 +-		kfree(sgi_tioca_agp_bridges);
   53.33 +-	sgi_tioca_agp_bridges=NULL;
   53.34 ++	kfree(sgi_tioca_agp_bridges);
   53.35 ++	sgi_tioca_agp_bridges = NULL;
   53.36 + }
   53.37 + 
   53.38 + module_init(agp_sgi_init);
   53.39 +diff -puN drivers/char/hvcs.c~remove-redundant-null-checks-before-free-in-drivers drivers/char/hvcs.c
   53.40 +--- a/drivers/char/hvcs.c~remove-redundant-null-checks-before-free-in-drivers
   53.41 ++++ a/drivers/char/hvcs.c
   53.42 +@@ -1320,11 +1320,12 @@ static struct tty_operations hvcs_ops = 
   53.43 + static int hvcs_alloc_index_list(int n)
   53.44 + {
   53.45 + 	int i;
   53.46 ++
   53.47 + 	hvcs_index_list = kmalloc(n * sizeof(hvcs_index_count),GFP_KERNEL);
   53.48 + 	if (!hvcs_index_list)
   53.49 + 		return -ENOMEM;
   53.50 + 	hvcs_index_count = n;
   53.51 +-	for(i = 0; i < hvcs_index_count; i++)
   53.52 ++	for (i = 0; i < hvcs_index_count; i++)
   53.53 + 		hvcs_index_list[i] = -1;
   53.54 + 	return 0;
   53.55 + }
   53.56 +@@ -1332,11 +1333,9 @@ static int hvcs_alloc_index_list(int n)
   53.57 + static void hvcs_free_index_list(void)
   53.58 + {
   53.59 + 	/* Paranoia check to be thorough. */
   53.60 +-	if (hvcs_index_list) {
   53.61 +-		kfree(hvcs_index_list);
   53.62 +-		hvcs_index_list = NULL;
   53.63 +-		hvcs_index_count = 0;
   53.64 +-	}
   53.65 ++	kfree(hvcs_index_list);
   53.66 ++	hvcs_index_list = NULL;
   53.67 ++	hvcs_index_count = 0;
   53.68 + }
   53.69 + 
   53.70 + static int __init hvcs_module_init(void)
   53.71 +diff -puN drivers/message/fusion/mptfc.c~remove-redundant-null-checks-before-free-in-drivers drivers/message/fusion/mptfc.c
   53.72 +--- a/drivers/message/fusion/mptfc.c~remove-redundant-null-checks-before-free-in-drivers
   53.73 ++++ a/drivers/message/fusion/mptfc.c
   53.74 +@@ -305,10 +305,8 @@ mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, in
   53.75 + 	}
   53.76 + 
   53.77 +  out:
   53.78 +-	if (pp0_array)
   53.79 +-		kfree(pp0_array);
   53.80 +-	if (p0_array)
   53.81 +-		kfree(p0_array);
   53.82 ++	kfree(pp0_array);
   53.83 ++	kfree(p0_array);
   53.84 + 	return rc;
   53.85 + }
   53.86 + 
   53.87 +diff -puN drivers/message/fusion/mptsas.c~remove-redundant-null-checks-before-free-in-drivers drivers/message/fusion/mptsas.c
   53.88 +--- a/drivers/message/fusion/mptsas.c~remove-redundant-null-checks-before-free-in-drivers
   53.89 ++++ a/drivers/message/fusion/mptsas.c
   53.90 +@@ -1378,8 +1378,7 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
   53.91 + 	return 0;
   53.92 + 
   53.93 +  out_free_port_info:
   53.94 +-	if (hba)
   53.95 +-		kfree(hba);
   53.96 ++	kfree(hba);
   53.97 +  out:
   53.98 + 	return error;
   53.99 + }
  53.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
  53.101 +--- a/drivers/net/fs_enet/fs_enet-mii.c~remove-redundant-null-checks-before-free-in-drivers
  53.102 ++++ a/drivers/net/fs_enet/fs_enet-mii.c
  53.103 +@@ -431,8 +431,7 @@ static struct fs_enet_mii_bus *create_bu
  53.104 + 	return bus;
  53.105 + 
  53.106 + err:
  53.107 +-	if (bus)
  53.108 +-		kfree(bus);
  53.109 ++	kfree(bus);
  53.110 + 	return ERR_PTR(ret);
  53.111 + }
  53.112 + 
  53.113 +diff -puN drivers/net/wireless/ipw2200.c~remove-redundant-null-checks-before-free-in-drivers drivers/net/wireless/ipw2200.c
  53.114 +--- a/drivers/net/wireless/ipw2200.c~remove-redundant-null-checks-before-free-in-drivers
  53.115 ++++ a/drivers/net/wireless/ipw2200.c
  53.116 +@@ -1229,12 +1229,6 @@ static struct ipw_fw_error *ipw_alloc_er
  53.117 + 	return error;
  53.118 + }
  53.119 + 
  53.120 +-static void ipw_free_error_log(struct ipw_fw_error *error)
  53.121 +-{
  53.122 +-	if (error)
  53.123 +-		kfree(error);
  53.124 +-}
  53.125 +-
  53.126 + static ssize_t show_event_log(struct device *d,
  53.127 + 			      struct device_attribute *attr, char *buf)
  53.128 + {
  53.129 +@@ -1296,10 +1290,9 @@ static ssize_t clear_error(struct device
  53.130 + 			   const char *buf, size_t count)
  53.131 + {
  53.132 + 	struct ipw_priv *priv = dev_get_drvdata(d);
  53.133 +-	if (priv->error) {
  53.134 +-		ipw_free_error_log(priv->error);
  53.135 +-		priv->error = NULL;
  53.136 +-	}
  53.137 ++
  53.138 ++	kfree(priv->error);
  53.139 ++	priv->error = NULL;
  53.140 + 	return count;
  53.141 + }
  53.142 + 
  53.143 +@@ -1970,8 +1963,7 @@ static void ipw_irq_tasklet(struct ipw_p
  53.144 + 				struct ipw_fw_error *error =
  53.145 + 				    ipw_alloc_error_log(priv);
  53.146 + 				ipw_dump_error_log(priv, error);
  53.147 +-				if (error)
  53.148 +-					ipw_free_error_log(error);
  53.149 ++				kfree(error);
  53.150 + 			}
  53.151 + #endif
  53.152 + 		} else {
  53.153 +@@ -11693,10 +11685,8 @@ static void ipw_pci_remove(struct pci_de
  53.154 + 		}
  53.155 + 	}
  53.156 + 
  53.157 +-	if (priv->error) {
  53.158 +-		ipw_free_error_log(priv->error);
  53.159 +-		priv->error = NULL;
  53.160 +-	}
  53.161 ++	kfree(priv->error);
  53.162 ++	priv->error = NULL;
  53.163 + 
  53.164 + #ifdef CONFIG_IPW2200_PROMISCUOUS
  53.165 + 	ipw_prom_free(priv);
  53.166 +diff -puN drivers/scsi/libata-scsi.c~remove-redundant-null-checks-before-free-in-drivers drivers/scsi/libata-scsi.c
  53.167 +--- a/drivers/scsi/libata-scsi.c~remove-redundant-null-checks-before-free-in-drivers
  53.168 ++++ a/drivers/scsi/libata-scsi.c
  53.169 +@@ -222,9 +222,7 @@ int ata_cmd_ioctl(struct scsi_device *sc
  53.170 + 	 && copy_to_user(arg + sizeof(args), argbuf, argsize))
  53.171 + 		rc = -EFAULT;
  53.172 + error:
  53.173 +-	if (argbuf)
  53.174 +-		kfree(argbuf);
  53.175 +-
  53.176 ++	kfree(argbuf);
  53.177 + 	return rc;
  53.178 + }
  53.179 + 
  53.180 +diff -puN drivers/video/au1100fb.c~remove-redundant-null-checks-before-free-in-drivers drivers/video/au1100fb.c
  53.181 +--- a/drivers/video/au1100fb.c~remove-redundant-null-checks-before-free-in-drivers
  53.182 ++++ a/drivers/video/au1100fb.c
  53.183 +@@ -743,8 +743,7 @@ void __exit au1100fb_cleanup(void)
  53.184 + {
  53.185 + 	driver_unregister(&au1100fb_driver);
  53.186 + 
  53.187 +-	if (drv_info.opt_mode)
  53.188 +-		kfree(drv_info.opt_mode);
  53.189 ++	kfree(drv_info.opt_mode);
  53.190 + }
  53.191 + 
  53.192 + module_init(au1100fb_init);
  53.193 +_
    54.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    54.2 +++ b/fr/examples/extdiff	Sat Jul 10 06:24:49 2010 +0100
    54.3 @@ -0,0 +1,28 @@
    54.4 +#!/bin/bash
    54.5 +
    54.6 +echo '[extensions]' >> $HGRC
    54.7 +echo 'extdiff =' >> $HGRC
    54.8 +
    54.9 +hg init a
   54.10 +cd a
   54.11 +echo 'The first line.' > myfile
   54.12 +hg ci -Ama
   54.13 +echo 'The second line.' >> myfile
   54.14 +
   54.15 +#$ name: diff
   54.16 +
   54.17 +hg diff
   54.18 +
   54.19 +#$ name: extdiff
   54.20 +
   54.21 +hg extdiff
   54.22 +
   54.23 +#$ name: extdiff-ctx
   54.24 +
   54.25 +#$ ignore: ^\*\*\* a.*
   54.26 +
   54.27 +hg extdiff -o -NprcC5
   54.28 +
   54.29 +#$ name:
   54.30 +
   54.31 +exit 0
    55.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    55.2 +++ b/fr/examples/filenames	Sat Jul 10 06:24:49 2010 +0100
    55.3 @@ -0,0 +1,61 @@
    55.4 +#!/bin/bash
    55.5 +
    55.6 +hg init a
    55.7 +cd a
    55.8 +mkdir -p examples src/watcher
    55.9 +touch COPYING MANIFEST.in README setup.py
   55.10 +touch examples/performant.py examples/simple.py
   55.11 +touch src/main.py src/watcher/_watcher.c src/watcher/watcher.py src/xyzzy.txt
   55.12 +
   55.13 +#$ name: files
   55.14 +
   55.15 +hg add COPYING README examples/simple.py
   55.16 +
   55.17 +#$ name: dirs
   55.18 +
   55.19 +hg status src
   55.20 +
   55.21 +#$ name: wdir-subdir
   55.22 +
   55.23 +cd src
   55.24 +hg add -n
   55.25 +hg add -n .
   55.26 +
   55.27 +#$ name: wdir-relname
   55.28 +
   55.29 +hg status
   55.30 +hg status `hg root`
   55.31 +
   55.32 +#$ name: glob.star
   55.33 +
   55.34 +hg add 'glob:*.py'
   55.35 +
   55.36 +#$ name: glob.starstar
   55.37 +
   55.38 +cd ..
   55.39 +hg status 'glob:**.py'
   55.40 +
   55.41 +#$ name: glob.star-starstar
   55.42 +
   55.43 +hg status 'glob:*.py'
   55.44 +hg status 'glob:**.py'
   55.45 +
   55.46 +#$ name: glob.question
   55.47 +
   55.48 +hg status 'glob:**.?'
   55.49 +
   55.50 +#$ name: glob.range
   55.51 +
   55.52 +hg status 'glob:**[nr-t]'
   55.53 +
   55.54 +#$ name: glob.group
   55.55 +
   55.56 +hg status 'glob:*.{in,py}'
   55.57 +
   55.58 +#$ name: filter.include
   55.59 +
   55.60 +hg status -I '*.in'
   55.61 +
   55.62 +#$ name: filter.exclude
   55.63 +
   55.64 +hg status -X '**.py' src
    56.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    56.2 +++ b/fr/examples/hook.msglen	Sat Jul 10 06:24:49 2010 +0100
    56.3 @@ -0,0 +1,14 @@
    56.4 +#!/bin/sh
    56.5 +
    56.6 +hg init a
    56.7 +cd a
    56.8 +echo '[hooks]' > .hg/hgrc
    56.9 +echo 'pretxncommit.msglen = test `hg tip --template {desc} | wc -c` -ge 10' >> .hg/hgrc
   56.10 +
   56.11 +#$ name: go
   56.12 +
   56.13 +cat .hg/hgrc
   56.14 +echo a > a
   56.15 +hg add a
   56.16 +hg commit -A -m 'too short'
   56.17 +hg commit -A -m 'long enough'
    57.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    57.2 +++ b/fr/examples/hook.simple	Sat Jul 10 06:24:49 2010 +0100
    57.3 @@ -0,0 +1,37 @@
    57.4 +#!/bin/bash
    57.5 +
    57.6 +#$ name: init
    57.7 +
    57.8 +hg init hook-test
    57.9 +cd hook-test
   57.10 +echo '[hooks]' >> .hg/hgrc
   57.11 +echo 'commit = echo committed $HG_NODE' >> .hg/hgrc
   57.12 +cat .hg/hgrc
   57.13 +echo a > a
   57.14 +hg add a
   57.15 +hg commit -m 'testing commit hook'
   57.16 +
   57.17 +#$ name: ext
   57.18 +#$ ignore: ^date of commit.*
   57.19 +
   57.20 +echo 'commit.when = echo -n "date of commit: "; date' >> .hg/hgrc
   57.21 +echo a >> a
   57.22 +hg commit -m 'i have two hooks'
   57.23 +
   57.24 +#$ name:
   57.25 +
   57.26 +echo '#!/bin/sh' >> check_bug_id
   57.27 +echo '# check that a commit comment mentions a numeric bug id' >> check_bug_id
   57.28 +echo 'hg log -r $1 --template {desc} | grep -q "\<bug *[0-9]"' >> check_bug_id
   57.29 +chmod +x check_bug_id
   57.30 +
   57.31 +#$ name: pretxncommit
   57.32 +
   57.33 +cat check_bug_id
   57.34 +
   57.35 +echo 'pretxncommit.bug_id_required = ./check_bug_id $HG_NODE' >> .hg/hgrc
   57.36 +
   57.37 +echo a >> a
   57.38 +hg commit -m 'i am not mentioning a bug id'
   57.39 +
   57.40 +hg commit -m 'i refer you to bug 666'
    58.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    58.2 +++ b/fr/examples/issue29	Sat Jul 10 06:24:49 2010 +0100
    58.3 @@ -0,0 +1,22 @@
    58.4 +#!/bin/bash
    58.5 +
    58.6 +#$ name: go
    58.7 +
    58.8 +hg init issue29
    58.9 +cd issue29
   58.10 +echo a > a
   58.11 +hg ci -Ama
   58.12 +echo b > b
   58.13 +hg ci -Amb
   58.14 +hg up 0
   58.15 +mkdir b
   58.16 +echo b > b/b
   58.17 +hg ci -Amc
   58.18 +
   58.19 +#$ ignore: abort: Is a directory: .*
   58.20 +hg merge
   58.21 +
   58.22 +#$ name:
   58.23 +# This error is expected from the failed merge.
   58.24 +
   58.25 +exit 0
    59.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    59.2 +++ b/fr/examples/mq.dodiff	Sat Jul 10 06:24:49 2010 +0100
    59.3 @@ -0,0 +1,14 @@
    59.4 +#!/bin/bash
    59.5 +
    59.6 +#$ name: diff
    59.7 +
    59.8 +echo 'this is my original thought' > oldfile
    59.9 +echo 'i have changed my mind' > newfile
   59.10 +
   59.11 +diff -u oldfile newfile > tiny.patch
   59.12 +
   59.13 +cat tiny.patch
   59.14 +
   59.15 +patch < tiny.patch
   59.16 +
   59.17 +cat oldfile
    60.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    60.2 +++ b/fr/examples/mq.guards	Sat Jul 10 06:24:49 2010 +0100
    60.3 @@ -0,0 +1,67 @@
    60.4 +#!/bin/bash
    60.5 +
    60.6 +echo '[extensions]' >> $HGRC
    60.7 +echo 'hgext.mq =' >> $HGRC
    60.8 +
    60.9 +hg init a
   60.10 +cd a
   60.11 +
   60.12 +#$ name: init
   60.13 +
   60.14 +hg qinit
   60.15 +hg qnew hello.patch
   60.16 +echo hello > hello
   60.17 +hg add hello
   60.18 +hg qrefresh
   60.19 +hg qnew goodbye.patch
   60.20 +echo goodbye > goodbye
   60.21 +hg add goodbye
   60.22 +hg qrefresh
   60.23 +
   60.24 +#$ name: qguard
   60.25 +
   60.26 +hg qguard
   60.27 +
   60.28 +#$ name: qguard.pos
   60.29 +
   60.30 +hg qguard +foo
   60.31 +hg qguard
   60.32 +
   60.33 +#$ name: qguard.neg
   60.34 +
   60.35 +hg qguard -- hello.patch -quux
   60.36 +hg qguard hello.patch
   60.37 +
   60.38 +#$ name: series
   60.39 +
   60.40 +cat .hg/patches/series
   60.41 +
   60.42 +#$ name: qselect.foo
   60.43 +
   60.44 +hg qpop -a
   60.45 +hg qselect
   60.46 +hg qselect foo
   60.47 +hg qselect
   60.48 +
   60.49 +#$ name: qselect.cat
   60.50 +
   60.51 +cat .hg/patches/guards
   60.52 +
   60.53 +#$ name: qselect.qpush
   60.54 +hg qpush -a
   60.55 +
   60.56 +#$ name: qselect.error
   60.57 +
   60.58 +hg qselect +foo
   60.59 +
   60.60 +#$ name: qselect.quux
   60.61 +
   60.62 +hg qselect quux
   60.63 +hg qpop -a
   60.64 +hg qpush -a
   60.65 +
   60.66 +#$ name: qselect.foobar
   60.67 +
   60.68 +hg qselect foo bar
   60.69 +hg qpop -a
   60.70 +hg qpush -a
    61.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    61.2 +++ b/fr/examples/mq.id	Sat Jul 10 06:24:49 2010 +0100
    61.3 @@ -0,0 +1,28 @@
    61.4 +#!/bin/sh
    61.5 +
    61.6 +echo '[extensions]' >> $HGRC
    61.7 +echo 'hgext.mq =' >> $HGRC
    61.8 +
    61.9 +hg init a
   61.10 +cd a
   61.11 +hg qinit
   61.12 +echo 'int x;' > test.c
   61.13 +hg ci -Ama
   61.14 +
   61.15 +hg qnew first.patch
   61.16 +echo 'float c;' >> test.c
   61.17 +hg qrefresh
   61.18 +
   61.19 +hg qnew second.patch
   61.20 +echo 'double u;' > other.c
   61.21 +hg add other.c
   61.22 +hg qrefresh
   61.23 +
   61.24 +#$ name: output
   61.25 +
   61.26 +hg qapplied
   61.27 +hg log -r qbase:qtip
   61.28 +hg export second.patch
   61.29 +
   61.30 +#$ name:
   61.31 +exit 0
    62.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    62.2 +++ b/fr/examples/mq.qinit-help	Sat Jul 10 06:24:49 2010 +0100
    62.3 @@ -0,0 +1,7 @@
    62.4 +#!/bin/bash
    62.5 +
    62.6 +echo '[extensions]' >> $HGRC
    62.7 +echo 'hgext.mq =' >> $HGRC
    62.8 +
    62.9 +#$ name: help
   62.10 +hg help qinit
    63.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    63.2 +++ b/fr/examples/mq.tarball	Sat Jul 10 06:24:49 2010 +0100
    63.3 @@ -0,0 +1,51 @@
    63.4 +#!/bin/bash
    63.5 +
    63.6 +cp $EXAMPLE_DIR/data/netplug-*.tar.bz2 .
    63.7 +ln -s /bin/true download
    63.8 +export PATH=`pwd`:$PATH
    63.9 +
   63.10 +#$ name: download
   63.11 +
   63.12 +download netplug-1.2.5.tar.bz2
   63.13 +tar jxf netplug-1.2.5.tar.bz2
   63.14 +cd netplug-1.2.5
   63.15 +hg init
   63.16 +hg commit -q --addremove --message netplug-1.2.5
   63.17 +cd ..
   63.18 +hg clone netplug-1.2.5 netplug
   63.19 +
   63.20 +#$ name:
   63.21 +
   63.22 +cd netplug
   63.23 +echo '[extensions]' >> $HGRC
   63.24 +echo 'hgext.mq =' >> $HGRC
   63.25 +cd ..
   63.26 +
   63.27 +#$ name: qinit
   63.28 +
   63.29 +cd netplug
   63.30 +hg qinit
   63.31 +hg qnew -m 'fix build problem with gcc 4' build-fix.patch
   63.32 +perl -pi -e 's/int addr_len/socklen_t addr_len/' netlink.c
   63.33 +hg qrefresh
   63.34 +hg tip -p
   63.35 +
   63.36 +#$ name: newsource
   63.37 +
   63.38 +hg qpop -a
   63.39 +cd ..
   63.40 +download netplug-1.2.8.tar.bz2
   63.41 +hg clone netplug-1.2.5 netplug-1.2.8
   63.42 +cd netplug-1.2.8
   63.43 +hg locate -0 | xargs -0 rm
   63.44 +cd ..
   63.45 +tar jxf netplug-1.2.8.tar.bz2
   63.46 +cd netplug-1.2.8
   63.47 +hg commit --addremove --message netplug-1.2.8
   63.48 +
   63.49 +#$ name: repush
   63.50 +
   63.51 +cd ../netplug
   63.52 +hg pull ../netplug-1.2.8
   63.53 +hg qpush -a
   63.54 +
    64.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    64.2 +++ b/fr/examples/mq.tools	Sat Jul 10 06:24:49 2010 +0100
    64.3 @@ -0,0 +1,11 @@
    64.4 +#!/bin/bash
    64.5 +
    64.6 +cp $EXAMPLE_DIR/data/remove-redundant-null-checks.patch .
    64.7 +
    64.8 +#$ name: tools
    64.9 +diffstat -p1 remove-redundant-null-checks.patch
   64.10 +
   64.11 +filterdiff -i '*/video/*' remove-redundant-null-checks.patch
   64.12 +
   64.13 +#$ name: lsdiff
   64.14 +lsdiff -nvv remove-redundant-null-checks.patch
    65.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    65.2 +++ b/fr/examples/mq.tutorial	Sat Jul 10 06:24:49 2010 +0100
    65.3 @@ -0,0 +1,74 @@
    65.4 +#!/bin/bash
    65.5 +
    65.6 +echo '[extensions]' >> $HGRC
    65.7 +echo 'hgext.mq =' >> $HGRC
    65.8 +
    65.9 +#$ name: qinit
   65.10 +
   65.11 +hg init mq-sandbox
   65.12 +cd mq-sandbox
   65.13 +echo 'line 1' > file1
   65.14 +echo 'another line 1' > file2
   65.15 +hg add file1 file2
   65.16 +hg commit -m'first change'
   65.17 +
   65.18 +hg qinit
   65.19 +
   65.20 +#$ name: qnew
   65.21 +
   65.22 +hg tip
   65.23 +hg qnew first.patch
   65.24 +hg tip
   65.25 +ls .hg/patches
   65.26 +
   65.27 +#$ name: qrefresh
   65.28 +#$ ignore: \s+200[78]-.*
   65.29 +
   65.30 +echo 'line 2' >> file1
   65.31 +hg diff
   65.32 +hg qrefresh
   65.33 +hg diff
   65.34 +hg tip --style=compact --patch
   65.35 +
   65.36 +#$ name: qrefresh2
   65.37 +
   65.38 +echo 'line 3' >> file1
   65.39 +hg status
   65.40 +hg qrefresh
   65.41 +hg tip --style=compact --patch
   65.42 +
   65.43 +#$ name: qnew2
   65.44 +
   65.45 +hg qnew second.patch
   65.46 +hg log --style=compact --limit=2
   65.47 +echo 'line 4' >> file1
   65.48 +hg qrefresh
   65.49 +hg tip --style=compact --patch
   65.50 +hg annotate file1
   65.51 +
   65.52 +#$ name: qseries
   65.53 +
   65.54 +hg qseries
   65.55 +hg qapplied
   65.56 +
   65.57 +#$ name: qpop
   65.58 +
   65.59 +hg qapplied
   65.60 +hg qpop
   65.61 +hg qseries
   65.62 +hg qapplied
   65.63 +cat file1
   65.64 +
   65.65 +#$ name: qpush-a
   65.66 +
   65.67 +hg qpush -a
   65.68 +cat file1
   65.69 +
   65.70 +#$ name: add
   65.71 +
   65.72 +echo 'file 3, line 1' >> file3
   65.73 +hg qnew add-file3.patch
   65.74 +hg qnew -f add-file3.patch
   65.75 +
   65.76 +#$ name:
   65.77 +exit 0
    66.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    66.2 +++ b/fr/examples/rename.divergent	Sat Jul 10 06:24:49 2010 +0100
    66.3 @@ -0,0 +1,33 @@
    66.4 +#!/bin/bash
    66.5 +
    66.6 +hg init orig
    66.7 +cd orig
    66.8 +echo foo > foo
    66.9 +hg ci -A -m 'First commit'
   66.10 +cd ..
   66.11 +
   66.12 +#$ name: clone
   66.13 +
   66.14 +hg clone orig anne
   66.15 +hg clone orig bob
   66.16 +
   66.17 +#$ name: rename.anne
   66.18 +
   66.19 +cd anne
   66.20 +hg rename foo bar
   66.21 +hg ci -m 'Rename foo to bar'
   66.22 +
   66.23 +#$ name: rename.bob
   66.24 +
   66.25 +cd ../bob
   66.26 +hg mv foo quux
   66.27 +hg ci -m 'Rename foo to quux'
   66.28 +
   66.29 +#$ name: merge
   66.30 +# See http://www.selenic.com/mercurial/bts/issue455
   66.31 +
   66.32 +cd ../orig
   66.33 +hg pull -u ../anne
   66.34 +hg pull ../bob
   66.35 +hg merge
   66.36 +ls
    67.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    67.2 +++ b/fr/examples/rollback	Sat Jul 10 06:24:49 2010 +0100
    67.3 @@ -0,0 +1,37 @@
    67.4 +#!/bin/bash
    67.5 +
    67.6 +hg init a
    67.7 +cd a
    67.8 +echo a > a
    67.9 +hg ci -A -m 'First commit'
   67.10 +
   67.11 +echo a >> a
   67.12 +
   67.13 +#$ name: tip
   67.14 +
   67.15 +#$ name: commit
   67.16 +
   67.17 +hg status
   67.18 +echo b > b
   67.19 +hg commit -m 'Add file b'
   67.20 +
   67.21 +#$ name: status
   67.22 +
   67.23 +hg status
   67.24 +hg tip
   67.25 +
   67.26 +#$ name: rollback
   67.27 +
   67.28 +hg rollback
   67.29 +hg tip
   67.30 +hg status
   67.31 +
   67.32 +#$ name: add
   67.33 +
   67.34 +hg add b
   67.35 +hg commit -m 'Add file b, this time for real'
   67.36 +
   67.37 +#$ name: twice
   67.38 +
   67.39 +hg rollback
   67.40 +hg rollback
    68.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    68.2 +++ b/fr/examples/run-example	Sat Jul 10 06:24:49 2010 +0100
    68.3 @@ -0,0 +1,465 @@
    68.4 +#!/usr/bin/env python
    68.5 +#
    68.6 +# This program takes something that resembles a shell script and runs
    68.7 +# it, spitting input (commands from the script) and output into text
    68.8 +# files, for use in examples.
    68.9 +
   68.10 +import cStringIO
   68.11 +import errno
   68.12 +import getopt
   68.13 +import glob
   68.14 +import os
   68.15 +import pty
   68.16 +import re
   68.17 +import select
   68.18 +import shutil
   68.19 +import signal
   68.20 +import stat
   68.21 +import sys
   68.22 +import tempfile
   68.23 +import time
   68.24 +
   68.25 +xml_subs = {
   68.26 +    '<': '&lt;',
   68.27 +    '>': '&gt;',
   68.28 +    '&': '&amp;',
   68.29 +    }
   68.30 +
   68.31 +def gensubs(s):
   68.32 +    start = 0
   68.33 +    for i, c in enumerate(s):
   68.34 +        sub = xml_subs.get(c)
   68.35 +        if sub:
   68.36 +            yield s[start:i]
   68.37 +            start = i + 1
   68.38 +            yield sub
   68.39 +    yield s[start:]
   68.40 +
   68.41 +def xml_escape(s):
   68.42 +    return ''.join(gensubs(s))
   68.43 +        
   68.44 +def maybe_unlink(name):
   68.45 +    try:
   68.46 +        os.unlink(name)
   68.47 +        return True
   68.48 +    except OSError, err:
   68.49 +        if err.errno != errno.ENOENT:
   68.50 +            raise
   68.51 +    return False
   68.52 +
   68.53 +def find_path_to(program):
   68.54 +    for p in os.environ.get('PATH', os.defpath).split(os.pathsep):
   68.55 +        name = os.path.join(p, program)
   68.56 +        if os.access(name, os.X_OK):
   68.57 +            return p
   68.58 +    return None
   68.59 +        
   68.60 +def result_name(name):
   68.61 +    return os.path.normpath(os.path.join('results', name.replace(os.sep, '-')))
   68.62 +
   68.63 +def wopen(name):
   68.64 +    path = os.path.dirname(name)
   68.65 +    if path:
   68.66 +        try:
   68.67 +            os.makedirs(path)
   68.68 +        except OSError, err:
   68.69 +            if err.errno != errno.EEXIST:
   68.70 +                raise
   68.71 +    return open(name, 'w')
   68.72 +
   68.73 +class example:
   68.74 +    entities = dict.fromkeys(l.rstrip() for l in open('auto-snippets.xml'))
   68.75 +
   68.76 +    def __init__(self, name, verbose, keep_change):
   68.77 +        self.name = os.path.normpath(name)
   68.78 +        self.verbose = verbose
   68.79 +        self.keep_change = keep_change
   68.80 +        
   68.81 +    def status(self, s):
   68.82 +        sys.stdout.write(s)
   68.83 +        if not s.endswith('\n'):
   68.84 +            sys.stdout.flush()
   68.85 +
   68.86 +    def rename_output(self, base, ignore=[]):
   68.87 +        mangle_re = re.compile('(?:' + '|'.join(ignore) + ')')
   68.88 +        def mangle(s):
   68.89 +            return mangle_re.sub('', s)
   68.90 +        def matchfp(fp1, fp2):
   68.91 +            while True:
   68.92 +                s1 = mangle(fp1.readline())
   68.93 +                s2 = mangle(fp2.readline())
   68.94 +                if cmp(s1, s2):
   68.95 +                    break
   68.96 +                if not s1:
   68.97 +                    return True
   68.98 +            return False
   68.99 +
  68.100 +        oldname = result_name(base + '.out')
  68.101 +        tmpname = result_name(base + '.tmp')
  68.102 +        errname = result_name(base + '.err')
  68.103 +        errfp = open(errname, 'w+')
  68.104 +        for line in open(tmpname):
  68.105 +            errfp.write(mangle_re.sub('', line))
  68.106 +        os.rename(tmpname, result_name(base + '.lxo'))
  68.107 +        errfp.seek(0)
  68.108 +        try:
  68.109 +            oldfp = open(oldname)
  68.110 +        except IOError, err:
  68.111 +            if err.errno != errno.ENOENT:
  68.112 +                raise
  68.113 +            os.rename(errname, oldname)
  68.114 +            return False
  68.115 +        if matchfp(oldfp, errfp):
  68.116 +            os.unlink(errname)
  68.117 +            return False
  68.118 +        else:
  68.119 +            print >> sys.stderr, '\nOutput of %s has changed!' % base
  68.120 +            if self.keep_change:
  68.121 +                os.rename(errname, oldname)
  68.122 +                return False
  68.123 +            else:
  68.124 +                os.system('diff -u %s %s 1>&2' % (oldname, errname))
  68.125 +            return True
  68.126 +
  68.127 +class static_example(example):
  68.128 +    def run(self):
  68.129 +        self.status('running %s\n' % self.name)
  68.130 +        s = open(self.name).read().rstrip()
  68.131 +        s = s.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;')
  68.132 +        ofp = wopen(result_name(self.name + '.tmp'))
  68.133 +        ofp.write('<!-- BEGIN %s -->\n' % self.name)
  68.134 +        ofp.write('<programlisting>')
  68.135 +        ofp.write(s)
  68.136 +        ofp.write('</programlisting>\n')
  68.137 +        ofp.write('<!-- END %s -->\n' % self.name)
  68.138 +        ofp.close()
  68.139 +        self.rename_output(self.name)
  68.140 +        norm = self.name.replace(os.sep, '-')
  68.141 +        example.entities[
  68.142 +            '<!ENTITY %s SYSTEM "results/%s.lxo">' % (norm, norm)] = 1
  68.143 +
  68.144 +
  68.145 +class shell_example(example):
  68.146 +    shell = '/usr/bin/env bash'
  68.147 +    ps1 = '__run_example_ps1__ '
  68.148 +    ps2 = '__run_example_ps2__ '
  68.149 +    pi_re = re.compile(r'#\$\s*(name|ignore):\s*(.*)$')
  68.150 +    
  68.151 +    timeout = 10
  68.152 +
  68.153 +    def __init__(self, name, verbose, keep_change):
  68.154 +        example.__init__(self, name, verbose, keep_change)
  68.155 +        self.poll = select.poll()
  68.156 +
  68.157 +    def parse(self):
  68.158 +        '''yield each hunk of input from the file.'''
  68.159 +        fp = open(self.name)
  68.160 +        cfp = cStringIO.StringIO()
  68.161 +        for line in fp:
  68.162 +            cfp.write(line)
  68.163 +            if not line.rstrip().endswith('\\'):
  68.164 +                yield cfp.getvalue()
  68.165 +                cfp.seek(0)
  68.166 +                cfp.truncate()
  68.167 +
  68.168 +    def send(self, s):
  68.169 +        if self.verbose:
  68.170 +            print >> sys.stderr, '>', self.debugrepr(s)
  68.171 +        while s:
  68.172 +            count = os.write(self.cfd, s)
  68.173 +            s = s[count:]
  68.174 +
  68.175 +    def debugrepr(self, s):
  68.176 +        rs = repr(s)
  68.177 +        limit = 60
  68.178 +        if len(rs) > limit:
  68.179 +            return ('%s%s ... [%d bytes]' % (rs[:limit], rs[0], len(s)))
  68.180 +        else:
  68.181 +            return rs
  68.182 +            
  68.183 +    timeout = 5
  68.184 +
  68.185 +    def read(self, hint):
  68.186 +        events = self.poll.poll(self.timeout * 1000)
  68.187 +        if not events:
  68.188 +            print >> sys.stderr, ('[%stimed out after %d seconds]' %
  68.189 +                                  (hint, self.timeout))
  68.190 +            os.kill(self.pid, signal.SIGHUP)
  68.191 +            return ''
  68.192 +        return os.read(self.cfd, 1024)
  68.193 +        
  68.194 +    def receive(self, hint):
  68.195 +        out = cStringIO.StringIO()
  68.196 +        while True:
  68.197 +            try:
  68.198 +                if self.verbose:
  68.199 +                    sys.stderr.write('< ')
  68.200 +                s = self.read(hint)
  68.201 +            except OSError, err:
  68.202 +                if err.errno == errno.EIO:
  68.203 +                    return '', ''
  68.204 +                raise
  68.205 +            if self.verbose:
  68.206 +                print >> sys.stderr, self.debugrepr(s)
  68.207 +            out.write(s)
  68.208 +            s = out.getvalue()
  68.209 +            if s.endswith(self.ps1):
  68.210 +                return self.ps1, s.replace('\r\n', '\n')[:-len(self.ps1)]
  68.211 +            if s.endswith(self.ps2):
  68.212 +                return self.ps2, s.replace('\r\n', '\n')[:-len(self.ps2)]
  68.213 +        
  68.214 +    def sendreceive(self, s, hint):
  68.215 +        self.send(s)
  68.216 +        ps, r = self.receive(hint)
  68.217 +        if r.startswith(s):
  68.218 +            r = r[len(s):]
  68.219 +        return ps, r
  68.220 +    
  68.221 +    def run(self):
  68.222 +        ofp = None
  68.223 +        basename = os.path.basename(self.name)
  68.224 +        self.status('running %s ' % basename)
  68.225 +        tmpdir = tempfile.mkdtemp(prefix=basename)
  68.226 +
  68.227 +        # remove the marker file that we tell make to use to see if
  68.228 +        # this run succeeded
  68.229 +        maybe_unlink(self.name + '.run')
  68.230 +
  68.231 +        rcfile = os.path.join(tmpdir, '.hgrc')
  68.232 +        rcfp = wopen(rcfile)
  68.233 +        print >> rcfp, '[ui]'
  68.234 +        print >> rcfp, "username = Bryan O'Sullivan <bos@serpentine.com>"
  68.235 +        
  68.236 +        rcfile = os.path.join(tmpdir, '.bashrc')
  68.237 +        rcfp = wopen(rcfile)
  68.238 +        print >> rcfp, 'PS1="%s"' % self.ps1
  68.239 +        print >> rcfp, 'PS2="%s"' % self.ps2
  68.240 +        print >> rcfp, 'unset HISTFILE'
  68.241 +        path = ['/usr/bin', '/bin']
  68.242 +        hg = find_path_to('hg')
  68.243 +        if hg and hg not in path:
  68.244 +            path.append(hg)
  68.245 +        def re_export(envar):
  68.246 +            v = os.getenv(envar)
  68.247 +            if v is not None:
  68.248 +                print >> rcfp, 'export ' + envar + '=' + v
  68.249 +        print >> rcfp, 'export PATH=' + ':'.join(path)
  68.250 +        re_export('PYTHONPATH')
  68.251 +        print >> rcfp, 'export EXAMPLE_DIR="%s"' % os.getcwd()
  68.252 +        print >> rcfp, 'export HGMERGE=merge'
  68.253 +        print >> rcfp, 'export LANG=C'
  68.254 +        print >> rcfp, 'export LC_ALL=C'
  68.255 +        print >> rcfp, 'export TZ=GMT'
  68.256 +        print >> rcfp, 'export HGRC="%s/.hgrc"' % tmpdir
  68.257 +        print >> rcfp, 'export HGRCPATH=$HGRC'
  68.258 +        print >> rcfp, 'cd %s' % tmpdir
  68.259 +        rcfp.close()
  68.260 +        sys.stdout.flush()
  68.261 +        sys.stderr.flush()
  68.262 +        self.pid, self.cfd = pty.fork()
  68.263 +        if self.pid == 0:
  68.264 +            cmdline = ['/usr/bin/env', '-i', 'bash', '--noediting',
  68.265 +                       '--noprofile', '--norc']
  68.266 +            try:
  68.267 +                os.execv(cmdline[0], cmdline)
  68.268 +            except OSError, err:
  68.269 +                print >> sys.stderr, '%s: %s' % (cmdline[0], err.strerror)
  68.270 +                sys.stderr.flush()
  68.271 +                os._exit(0)
  68.272 +        self.poll.register(self.cfd, select.POLLIN | select.POLLERR |
  68.273 +                           select.POLLHUP)
  68.274 +
  68.275 +        prompts = {
  68.276 +            '': '',
  68.277 +            self.ps1: '$',
  68.278 +            self.ps2: '>',
  68.279 +            }
  68.280 +
  68.281 +        ignore = [
  68.282 +            r'\d+:[0-9a-f]{12}', # changeset number:hash
  68.283 +            r'[0-9a-f]{40}', # long changeset hash
  68.284 +            r'[0-9a-f]{12}', # short changeset hash
  68.285 +            r'^(?:---|\+\+\+) .*', # diff header with dates
  68.286 +            r'^date:.*', # date
  68.287 +            #r'^diff -r.*', # "diff -r" is followed by hash
  68.288 +            r'^# Date \d+ \d+', # hg patch header
  68.289 +            ]
  68.290 +
  68.291 +        err = False
  68.292 +        read_hint = ''
  68.293 +
  68.294 +        try:
  68.295 +            try:
  68.296 +                # eat first prompt string from shell
  68.297 +                self.read(read_hint)
  68.298 +                # setup env and prompt
  68.299 +                ps, output = self.sendreceive('source %s\n' % rcfile,
  68.300 +                                              read_hint)
  68.301 +                for hunk in self.parse():
  68.302 +                    # is this line a processing instruction?
  68.303 +                    m = self.pi_re.match(hunk)
  68.304 +                    if m:
  68.305 +                        pi, rest = m.groups()
  68.306 +                        if pi == 'name':
  68.307 +                            self.status('.')
  68.308 +                            out = rest
  68.309 +                            if out in ('err', 'lxo', 'out', 'run', 'tmp'):
  68.310 +                                print >> sys.stderr, ('%s: illegal section '
  68.311 +                                                      'name %r' %
  68.312 +                                                      (self.name, out))
  68.313 +                                return 1
  68.314 +                            assert os.sep not in out
  68.315 +                            if ofp is not None:
  68.316 +                                ofp.write('</screen>\n')
  68.317 +                                ofp.write('<!-- END %s -->\n' % ofp_basename)
  68.318 +                                ofp.close()
  68.319 +                                err |= self.rename_output(ofp_basename, ignore)
  68.320 +                            if out:
  68.321 +                                ofp_basename = '%s.%s' % (self.name, out)
  68.322 +                                norm = os.path.normpath(ofp_basename)
  68.323 +                                norm = norm.replace(os.sep, '-')
  68.324 +                                example.entities[
  68.325 +                                    '<!ENTITY interaction.%s '
  68.326 +                                    'SYSTEM "results/%s.lxo">'
  68.327 +                                    % (norm, norm)] = 1
  68.328 +                                read_hint = ofp_basename + ' '
  68.329 +                                ofp = wopen(result_name(ofp_basename + '.tmp'))
  68.330 +                                ofp.write('<!-- BEGIN %s -->\n' % ofp_basename)
  68.331 +                                ofp.write('<screen>')
  68.332 +                            else:
  68.333 +                                ofp = None
  68.334 +                        elif pi == 'ignore':
  68.335 +                            ignore.append(rest)
  68.336 +                    elif hunk.strip():
  68.337 +                        # it's something we should execute
  68.338 +                        newps, output = self.sendreceive(hunk, read_hint)
  68.339 +                        if not ofp:
  68.340 +                            continue
  68.341 +                        # first, print the command we ran
  68.342 +                        if not hunk.startswith('#'):
  68.343 +                            nl = hunk.endswith('\n')
  68.344 +                            hunk = ('<prompt>%s</prompt> '
  68.345 +                                    '<userinput>%s</userinput>' %
  68.346 +                                    (prompts[ps],
  68.347 +                                     xml_escape(hunk.rstrip('\n'))))
  68.348 +                            if nl: hunk += '\n'
  68.349 +                        ofp.write(hunk)
  68.350 +                        # then its output
  68.351 +                        ofp.write(xml_escape(output))
  68.352 +                        ps = newps
  68.353 +                self.status('\n')
  68.354 +            except:
  68.355 +                print >> sys.stderr, '(killed)'
  68.356 +                os.kill(self.pid, signal.SIGKILL)
  68.357 +                pid, rc = os.wait()
  68.358 +                raise
  68.359 +            else:
  68.360 +                try:
  68.361 +                    ps, output = self.sendreceive('exit\n', read_hint)
  68.362 +                    if ofp is not None:
  68.363 +                        ofp.write(output)
  68.364 +                        ofp.write('</screen>\n')
  68.365 +                        ofp.write('<!-- END %s -->\n' % ofp_basename)
  68.366 +                        ofp.close()
  68.367 +                        err |= self.rename_output(ofp_basename, ignore)
  68.368 +                    os.close(self.cfd)
  68.369 +                except IOError:
  68.370 +                    pass
  68.371 +                os.kill(self.pid, signal.SIGTERM)
  68.372 +                pid, rc = os.wait()
  68.373 +                err = err or rc
  68.374 +                if err:
  68.375 +                    if os.WIFEXITED(rc):
  68.376 +                        print >> sys.stderr, '(exit %s)' % os.WEXITSTATUS(rc)
  68.377 +                    elif os.WIFSIGNALED(rc):
  68.378 +                        print >> sys.stderr, '(signal %s)' % os.WTERMSIG(rc)
  68.379 +                else:
  68.380 +                    wopen(result_name(self.name + '.run'))
  68.381 +                return err
  68.382 +        finally:
  68.383 +            shutil.rmtree(tmpdir)
  68.384 +
  68.385 +def print_help(exit, msg=None):
  68.386 +    if msg:
  68.387 +        print >> sys.stderr, 'Error:', msg
  68.388 +    print >> sys.stderr, 'Usage: run-example [options] [test...]'
  68.389 +    print >> sys.stderr, 'Options:'
  68.390 +    print >> sys.stderr, '  -a --all       run all examples in this directory'
  68.391 +    print >> sys.stderr, '  -h --help      print this help message'
  68.392 +    print >> sys.stderr, '     --keep      keep new output as desired output'
  68.393 +    print >> sys.stderr, '  -v --verbose   display extra debug output'
  68.394 +    sys.exit(exit)
  68.395 +
  68.396 +def main(path='.'):
  68.397 +    if os.path.realpath(path).split(os.sep)[-1] != 'examples':
  68.398 +        print >> sys.stderr, 'Not being run from the examples directory!'
  68.399 +        sys.exit(1)
  68.400 +
  68.401 +    opts, args = getopt.getopt(sys.argv[1:], '?ahv',
  68.402 +                               ['all', 'help', 'keep', 'verbose'])
  68.403 +    verbose = False
  68.404 +    run_all = False
  68.405 +    keep_change = False
  68.406 +
  68.407 +    for o, a in opts:
  68.408 +        if o in ('-h', '-?', '--help'):
  68.409 +            print_help(0)
  68.410 +        if o in ('-a', '--all'):
  68.411 +            run_all = True
  68.412 +        if o in ('--keep',):
  68.413 +            keep_change = True
  68.414 +        if o in ('-v', '--verbose'):
  68.415 +            verbose = True
  68.416 +    errs = 0
  68.417 +    if args:
  68.418 +        for a in args:
  68.419 +            try:
  68.420 +                st = os.lstat(a)
  68.421 +            except OSError, err:
  68.422 +                print >> sys.stderr, '%s: %s' % (a, err.strerror)
  68.423 +                errs += 1
  68.424 +                continue
  68.425 +            if stat.S_ISREG(st.st_mode):
  68.426 +                if st.st_mode & 0111:
  68.427 +                    if shell_example(a, verbose, keep_change).run():
  68.428 +                        errs += 1
  68.429 +                elif a.endswith('.lst'):
  68.430 +                    static_example(a, verbose, keep_change).run()
  68.431 +            else:
  68.432 +                print >> sys.stderr, '%s: not a file, or not executable' % a
  68.433 +                errs += 1
  68.434 +    elif run_all:
  68.435 +        names = glob.glob("*") + glob.glob("app*/*") + glob.glob("ch*/*")
  68.436 +        names.sort()
  68.437 +        for name in names:
  68.438 +            if name == 'run-example' or name.endswith('~'): continue
  68.439 +            pathname = os.path.join(path, name)
  68.440 +            try:
  68.441 +                st = os.lstat(pathname)
  68.442 +            except OSError, err:
  68.443 +                # could be an output file that was removed while we ran
  68.444 +                if err.errno != errno.ENOENT:
  68.445 +                    raise
  68.446 +                continue
  68.447 +            if stat.S_ISREG(st.st_mode):
  68.448 +                if st.st_mode & 0111:
  68.449 +                    if shell_example(pathname, verbose, keep_change).run():
  68.450 +                        errs += 1
  68.451 +                elif pathname.endswith('.lst'):
  68.452 +                    static_example(pathname, verbose, keep_change).run()
  68.453 +        print >> wopen(os.path.join(path, '.run')), time.asctime()
  68.454 +    else:
  68.455 +        print_help(1, msg='no test names given, and --all not provided')
  68.456 +
  68.457 +    fp = wopen('auto-snippets.xml')
  68.458 +    for key in sorted(example.entities.iterkeys()):
  68.459 +        print >> fp, key
  68.460 +    fp.close()
  68.461 +    return errs
  68.462 +
  68.463 +if __name__ == '__main__':
  68.464 +    try:
  68.465 +        sys.exit(main())
  68.466 +    except KeyboardInterrupt:
  68.467 +        print >> sys.stderr, 'interrupted!'
  68.468 +        sys.exit(1)
    69.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    69.2 +++ b/fr/examples/svn-long.txt	Sat Jul 10 06:24:49 2010 +0100
    69.3 @@ -0,0 +1,11 @@
    69.4 +------------------------------------------------------------------------
    69.5 +r9653 | sean.hefty | 2006-09-27 14:39:55 -0700 (Wed, 27 Sep 2006) | 5 lines
    69.6 +Changed paths:
    69.7 +   M /gen2/trunk/src/linux-kernel/infiniband/core/cma.c
    69.8 +
    69.9 +On reporting a route error, also include the status for the error,
   69.10 +rather than indicating a status of 0 when an error has occurred.
   69.11 +
   69.12 +Signed-off-by: Sean Hefty <sean.hefty@intel.com>
   69.13 +
   69.14 +------------------------------------------------------------------------
    70.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    70.2 +++ b/fr/examples/svn-short.txt	Sat Jul 10 06:24:49 2010 +0100
    70.3 @@ -0,0 +1,9 @@
    70.4 +------------------------------------------------------------------------
    70.5 +r9653 | sean.hefty | 2006-09-27 14:39:55 -0700 (Wed, 27 Sep 2006) | 5 lines
    70.6 +
    70.7 +On reporting a route error, also include the status for the error,
    70.8 +rather than indicating a status of 0 when an error has occurred.
    70.9 +
   70.10 +Signed-off-by: Sean Hefty <sean.hefty@intel.com>
   70.11 +
   70.12 +------------------------------------------------------------------------
    71.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    71.2 +++ b/fr/examples/svn.style	Sat Jul 10 06:24:49 2010 +0100
    71.3 @@ -0,0 +1,2 @@
    71.4 +header = '------------------------------------------------------------------------\n\n'
    71.5 +changeset = svn.template
    72.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    72.2 +++ b/fr/examples/svn.template	Sat Jul 10 06:24:49 2010 +0100
    72.3 @@ -0,0 +1,5 @@
    72.4 +r{rev} | {author|user} | {date|isodate} ({date|rfc822date})
    72.5 +
    72.6 +{desc|strip|fill76}
    72.7 +
    72.8 +------------------------------------------------------------------------
    73.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    73.2 +++ b/fr/examples/tag	Sat Jul 10 06:24:49 2010 +0100
    73.3 @@ -0,0 +1,44 @@
    73.4 +#!/bin/bash
    73.5 +
    73.6 +#$ name: init
    73.7 +
    73.8 +hg init mytag
    73.9 +cd mytag
   73.10 +
   73.11 +echo hello > myfile
   73.12 +hg commit -A -m 'Initial commit'
   73.13 +
   73.14 +#$ name: tag
   73.15 +
   73.16 +hg tag v1.0
   73.17 +
   73.18 +#$ name: tags
   73.19 +
   73.20 +hg tags
   73.21 +
   73.22 +#$ name: log
   73.23 +
   73.24 +hg log
   73.25 +
   73.26 +#$ name: log.v1.0
   73.27 +
   73.28 +echo goodbye > myfile2
   73.29 +hg commit -A -m 'Second commit'
   73.30 +hg log -r v1.0
   73.31 +
   73.32 +#$ name: remove
   73.33 +
   73.34 +hg tag --remove v1.0
   73.35 +hg tags
   73.36 +
   73.37 +#$ name: replace
   73.38 +
   73.39 +hg tag -r 1 v1.1
   73.40 +hg tags
   73.41 +hg tag -r 2 v1.1
   73.42 +hg tag -f -r 2 v1.1
   73.43 +hg tags
   73.44 +
   73.45 +#$ name: tip
   73.46 +
   73.47 +hg tip
    74.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    74.2 +++ b/fr/examples/template.simple	Sat Jul 10 06:24:49 2010 +0100
    74.3 @@ -0,0 +1,96 @@
    74.4 +#!/bin/bash
    74.5 +
    74.6 +# So many different bits of random output, it would be a nightmare to
    74.7 +# ignore each individually.
    74.8 +#$ ignore: .*
    74.9 +
   74.10 +hg init myrepo
   74.11 +cd myrepo
   74.12 +echo hello > hello
   74.13 +hg commit -Am'added hello'
   74.14 +
   74.15 +echo hello >> hello
   74.16 +echo goodbye > goodbye
   74.17 +echo '   added line to end of <<hello>> file.' > ../msg
   74.18 +echo '' >> ../msg
   74.19 +echo 'in addition, added a file with the helpful name (at least i hope that some might consider it so) of goodbye.' >> ../msg
   74.20 +
   74.21 +hg commit -Al../msg
   74.22 +
   74.23 +hg tag mytag
   74.24 +hg tag v0.1
   74.25 +
   74.26 +#$ name: normal
   74.27 +
   74.28 +hg log -r1
   74.29 +
   74.30 +#$ name: compact
   74.31 +
   74.32 +hg log --style compact
   74.33 +
   74.34 +#$ name: changelog
   74.35 +
   74.36 +hg log --style changelog
   74.37 +
   74.38 +#$ name: simplest
   74.39 +
   74.40 +hg log -r1 --template 'i saw a changeset\n'
   74.41 +
   74.42 +#$ name: simplesub
   74.43 +
   74.44 +hg log --template 'i saw a changeset: {desc}\n'
   74.45 +
   74.46 +#$ name: keywords
   74.47 +
   74.48 +hg log -r1 --template 'author: {author}\n'
   74.49 +hg log -r1 --template 'desc:\n{desc}\n'
   74.50 +hg log -r1 --template 'files: {files}\n'
   74.51 +hg log -r1 --template 'file_adds: {file_adds}\n'
   74.52 +hg log -r1 --template 'file_dels: {file_dels}\n'
   74.53 +hg log -r1 --template 'node: {node}\n'
   74.54 +hg log -r1 --template 'parents: {parents}\n'
   74.55 +hg log -r1 --template 'rev: {rev}\n'
   74.56 +hg log -r1 --template 'tags: {tags}\n'
   74.57 +
   74.58 +#$ name: datekeyword
   74.59 +
   74.60 +hg log -r1 --template 'date: {date}\n'
   74.61 +hg log -r1 --template 'date: {date|isodate}\n'
   74.62 +
   74.63 +#$ name: manyfilters
   74.64 +
   74.65 +hg log -r1 --template '{author}\n'
   74.66 +hg log -r1 --template '{author|domain}\n'
   74.67 +hg log -r1 --template '{author|email}\n'
   74.68 +hg log -r1 --template '{author|obfuscate}\n' | cut -c-76
   74.69 +hg log -r1 --template '{author|person}\n'
   74.70 +hg log -r1 --template '{author|user}\n'
   74.71 +
   74.72 +hg log -r1 --template 'looks almost right, but actually garbage: {date}\n'
   74.73 +hg log -r1 --template '{date|age}\n'
   74.74 +hg log -r1 --template '{date|date}\n'
   74.75 +hg log -r1 --template '{date|hgdate}\n'
   74.76 +hg log -r1 --template '{date|isodate}\n'
   74.77 +hg log -r1 --template '{date|rfc822date}\n'
   74.78 +hg log -r1 --template '{date|shortdate}\n'
   74.79 +
   74.80 +hg log -r1 --template '{desc}\n' | cut -c-76
   74.81 +hg log -r1 --template '{desc|addbreaks}\n' | cut -c-76
   74.82 +hg log -r1 --template '{desc|escape}\n' | cut -c-76
   74.83 +hg log -r1 --template '{desc|fill68}\n'
   74.84 +hg log -r1 --template '{desc|fill76}\n'
   74.85 +hg log -r1 --template '{desc|firstline}\n'
   74.86 +hg log -r1 --template '{desc|strip}\n' | cut -c-76
   74.87 +hg log -r1 --template '{desc|tabindent}\n' | expand | cut -c-76
   74.88 +
   74.89 +hg log -r1 --template '{node}\n'
   74.90 +hg log -r1 --template '{node|short}\n'
   74.91 +
   74.92 +#$ name: combine
   74.93 +
   74.94 +hg log -r1 --template 'description:\n\t{desc|strip|fill68|tabindent}\n'
   74.95 +
   74.96 +#$ name: rev
   74.97 +
   74.98 +echo 'changeset = "rev: {rev}\n"' > rev
   74.99 +hg log -l1 --style ./rev
    75.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    75.2 +++ b/fr/examples/template.svnstyle	Sat Jul 10 06:24:49 2010 +0100
    75.3 @@ -0,0 +1,71 @@
    75.4 +#!/bin/bash
    75.5 +
    75.6 +svn() {
    75.7 +  cat $EXAMPLE_DIR/svn-short.txt
    75.8 +}
    75.9 +
   75.10 +#$ name: short
   75.11 +
   75.12 +svn log -r9653
   75.13 +
   75.14 +#$ name:
   75.15 +
   75.16 +hg init myrepo
   75.17 +cd myrepo
   75.18 +
   75.19 +echo hello > hello
   75.20 +hg commit -Am'added hello'
   75.21 +
   75.22 +echo hello >> hello
   75.23 +echo goodbye > goodbye
   75.24 +echo '   added line to end of <<hello>> file.' > ../msg
   75.25 +echo '' >> ../msg
   75.26 +echo 'in addition, added a file with the helpful name (at least i hope that some might consider it so) of goodbye.' >> ../msg
   75.27 +
   75.28 +hg commit -Al../msg
   75.29 +
   75.30 +hg tag mytag
   75.31 +hg tag v0.1
   75.32 +
   75.33 +echo 'changeset = "{node|short}\n"' > svn.style
   75.34 +
   75.35 +#$ name: id
   75.36 +
   75.37 +hg log -r0 --template '{node}'
   75.38 +
   75.39 +#$ name: simplest
   75.40 +#$ ignore: \d+-\d+-\d+ \d+:\d+ \+.*
   75.41 +
   75.42 +cat svn.style
   75.43 +hg log -r1 --style svn.style
   75.44 +
   75.45 +#$ name:
   75.46 +
   75.47 +echo 'changeset =' > broken.style
   75.48 +
   75.49 +#$ name: syntax.input
   75.50 +
   75.51 +cat broken.style
   75.52 +
   75.53 +#$ name: syntax.error
   75.54 +
   75.55 +hg log -r1 --style broken.style
   75.56 +
   75.57 +#$ name:
   75.58 +
   75.59 +cp $EXAMPLE_DIR/svn.style .
   75.60 +cp $EXAMPLE_DIR/svn.template .
   75.61 +
   75.62 +#$ name: template
   75.63 +
   75.64 +cat svn.template
   75.65 +
   75.66 +#$ name: style
   75.67 +
   75.68 +cat svn.style
   75.69 +
   75.70 +#$ name: result
   75.71 +#$ ignore: \| 200[78].*
   75.72 +
   75.73 +hg log -r1 --style svn.style
   75.74 +
    76.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    76.2 +++ b/fr/examples/tour	Sat Jul 10 06:24:49 2010 +0100
    76.3 @@ -0,0 +1,215 @@
    76.4 +#!/bin/bash
    76.5 +
    76.6 +#$ name: version
    76.7 +
    76.8 +hg version
    76.9 +
   76.10 +#$ name: help
   76.11 +
   76.12 +hg help init
   76.13 +
   76.14 +#$ name: clone
   76.15 +
   76.16 +hg clone http://hg.serpentine.com/tutorial/hello
   76.17 +
   76.18 +#$ name: ls
   76.19 +#$ ignore: ^drwx.*
   76.20 +#$ ignore: ^total \d+
   76.21 +
   76.22 +ls -l
   76.23 +ls hello
   76.24 +
   76.25 +#$ name: ls-a
   76.26 +
   76.27 +cd hello
   76.28 +ls -a
   76.29 +
   76.30 +#$ name: log
   76.31 +
   76.32 +hg log
   76.33 +
   76.34 +#$ name: log-r
   76.35 +
   76.36 +hg log -r 3
   76.37 +hg log -r 0272e0d5a517
   76.38 +hg log -r 1 -r 4
   76.39 +
   76.40 +#$ name: log.range
   76.41 +
   76.42 +hg log -r 2:4
   76.43 +
   76.44 +#$ name: log-v
   76.45 +
   76.46 +hg log -v -r 3
   76.47 +
   76.48 +#$ name: log-vp
   76.49 +
   76.50 +hg log -v -p -r 2
   76.51 +
   76.52 +#$ name: reclone
   76.53 +
   76.54 +cd ..
   76.55 +hg clone hello my-hello
   76.56 +cd my-hello
   76.57 +
   76.58 +#$ name: cat1
   76.59 +cat hello.c
   76.60 +
   76.61 +#$ name:
   76.62 +
   76.63 +sed -i '/printf/a\\tprintf("hello again!\\n");' hello.c
   76.64 +
   76.65 +#$ name: cat2
   76.66 +# ... edit edit edit ...
   76.67 +cat hello.c
   76.68 +
   76.69 +#$ name: status
   76.70 +
   76.71 +ls
   76.72 +hg status
   76.73 +
   76.74 +#$ name: diff
   76.75 +
   76.76 +hg diff
   76.77 +
   76.78 +#$ name:
   76.79 +
   76.80 +export HGEDITOR='echo Added an extra line of output >'
   76.81 +
   76.82 +#$ name: commit
   76.83 +
   76.84 +hg commit
   76.85 +
   76.86 +#$ name: merge.dummy1
   76.87 +
   76.88 +hg log -r 5 | grep changeset | cut -c 16-19 2>/dev/null > /tmp/REV5.my-hello
   76.89 +
   76.90 +#$ name: tip
   76.91 +
   76.92 +hg tip -vp
   76.93 +
   76.94 +#$ name: clone-pull
   76.95 +
   76.96 +cd ..
   76.97 +hg clone hello hello-pull
   76.98 +
   76.99 +#$ name: incoming
  76.100 +
  76.101 +cd hello-pull
  76.102 +hg incoming ../my-hello
  76.103 +
  76.104 +#$ name: pull
  76.105 +
  76.106 +hg tip
  76.107 +hg pull ../my-hello
  76.108 +hg tip
  76.109 +
  76.110 +#$ name: update
  76.111 +
  76.112 +grep printf hello.c
  76.113 +hg update tip
  76.114 +grep printf hello.c
  76.115 +
  76.116 +#$ name: parents
  76.117 +
  76.118 +hg parents
  76.119 +
  76.120 +#$ name: older
  76.121 +
  76.122 +hg update 2
  76.123 +hg parents
  76.124 +hg update
  76.125 +hg parents
  76.126 +
  76.127 +#$ name: clone-push
  76.128 +
  76.129 +cd ..
  76.130 +hg clone hello hello-push
  76.131 +
  76.132 +#$ name: outgoing
  76.133 +
  76.134 +cd my-hello
  76.135 +hg outgoing ../hello-push
  76.136 +
  76.137 +#$ name: push
  76.138 +
  76.139 +hg push ../hello-push
  76.140 +
  76.141 +#$ name: push.nothing
  76.142 +
  76.143 +hg push ../hello-push
  76.144 +
  76.145 +#$ name: outgoing.net
  76.146 +
  76.147 +hg outgoing http://hg.serpentine.com/tutorial/hello
  76.148 +
  76.149 +#$ name: push.net
  76.150 +
  76.151 +hg push http://hg.serpentine.com/tutorial/hello
  76.152 +
  76.153 +#$ name:
  76.154 +cp hello.c ../new-hello.c
  76.155 +sed -i '/printf("hello,/i\\tprintf("once more, hello.\\n");' ../new-hello.c
  76.156 +
  76.157 +my-text-editor()
  76.158 +{
  76.159 +cp ../new-hello.c hello.c
  76.160 +}
  76.161 +
  76.162 +#$ name: merge.clone
  76.163 +
  76.164 +cd ..
  76.165 +hg clone hello my-new-hello
  76.166 +cd my-new-hello
  76.167 +# Make some simple edits to hello.c.
  76.168 +my-text-editor hello.c
  76.169 +hg commit -m 'A new hello for a new day.'
  76.170 +
  76.171 +#$ name: merge.dummy2
  76.172 +
  76.173 +hg log -r 5 | grep changeset | cut -c 16-19 2>/dev/null > /tmp/REV5.my-new-hello
  76.174 +
  76.175 +#$ name: merge.cat1
  76.176 +
  76.177 +cat hello.c
  76.178 +
  76.179 +#$ name: merge.cat2
  76.180 +
  76.181 +cat ../my-hello/hello.c
  76.182 +
  76.183 +#$ name: merge.pull
  76.184 +
  76.185 +hg pull ../my-hello
  76.186 +
  76.187 +#$ name: merge.dummy3
  76.188 +
  76.189 +hg log -r 6 | grep changeset | cut -c 16-19 2>/dev/null > /tmp/REV6.my-new-hello
  76.190 +
  76.191 +#$ name: merge.heads
  76.192 +
  76.193 +hg heads
  76.194 +
  76.195 +#$ name: merge.update
  76.196 +
  76.197 +hg update
  76.198 +
  76.199 +#$ name: merge.merge
  76.200 +
  76.201 +hg merge
  76.202 +
  76.203 +#$ name: merge.parents
  76.204 +
  76.205 +hg parents
  76.206 +cat hello.c
  76.207 +
  76.208 +#$ name: merge.commit
  76.209 +
  76.210 +hg commit -m 'Merged changes'
  76.211 +
  76.212 +#$ name: merge.dummy4
  76.213 +
  76.214 +hg log -r 7 | grep changeset | cut -c 16-19 2>/dev/null > /tmp/REV7.my-new-hello
  76.215 +
  76.216 +#$ name: merge.tip
  76.217 +
  76.218 +hg tip
    77.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    77.2 +++ b/fr/examples/tour-merge-conflict	Sat Jul 10 06:24:49 2010 +0100
    77.3 @@ -0,0 +1,73 @@
    77.4 +#!/bin/bash
    77.5 +
    77.6 +hg init scam
    77.7 +cd scam
    77.8 +
    77.9 +#$ name: wife
   77.10 +
   77.11 +cat > letter.txt <<EOF
   77.12 +Greetings!
   77.13 +
   77.14 +I am Mariam Abacha, the wife of former
   77.15 +Nigerian dictator Sani Abacha.
   77.16 +EOF
   77.17 +
   77.18 +hg add letter.txt
   77.19 +hg commit -m '419 scam, first draft'
   77.20 +
   77.21 +#$ name: cousin
   77.22 +
   77.23 +cd ..
   77.24 +hg clone scam scam-cousin
   77.25 +cd scam-cousin
   77.26 +
   77.27 +cat > letter.txt <<EOF
   77.28 +Greetings!
   77.29 +
   77.30 +I am Shehu Musa Abacha, cousin to the former
   77.31 +Nigerian dictator Sani Abacha.
   77.32 +EOF
   77.33 +
   77.34 +hg commit -m '419 scam, with cousin'
   77.35 +
   77.36 +#$ name: son
   77.37 +
   77.38 +cd ..
   77.39 +hg clone scam scam-son
   77.40 +cd scam-son
   77.41 +
   77.42 +cat > letter.txt <<EOF
   77.43 +Greetings!
   77.44 +
   77.45 +I am Alhaji Abba Abacha, son of the former
   77.46 +Nigerian dictator Sani Abacha.
   77.47 +EOF
   77.48 +
   77.49 +hg commit -m '419 scam, with son'
   77.50 +
   77.51 +#$ name: pull
   77.52 +
   77.53 +cd ..
   77.54 +hg clone scam-cousin scam-merge
   77.55 +cd scam-merge
   77.56 +hg pull -u ../scam-son
   77.57 +
   77.58 +#$ name: merge
   77.59 +#$ ignore: [<>]{7} /tmp/.*
   77.60 +
   77.61 +export HGMERGE=merge
   77.62 +hg merge
   77.63 +cat letter.txt
   77.64 +
   77.65 +#$ name: commit
   77.66 +
   77.67 +cat > letter.txt <<EOF
   77.68 +Greetings!
   77.69 +
   77.70 +I am Bryan O'Sullivan, no relation of the former
   77.71 +Nigerian dictator Sani Abacha.
   77.72 +EOF
   77.73 +
   77.74 +hg resolve -m letter.txt
   77.75 +hg commit -m 'Send me your money'
   77.76 +hg tip
    78.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    78.2 +++ b/fr/fblinks	Sat Jul 10 06:24:49 2010 +0100
    78.3 @@ -0,0 +1,67 @@
    78.4 +#!/usr/bin/python
    78.5 +
    78.6 +import errno
    78.7 +import os
    78.8 +import re
    78.9 +import sys
   78.10 +
   78.11 +hg_id = sys.argv[1]
   78.12 +
   78.13 +dest_dir = sys.argv[2]
   78.14 +
   78.15 +empty_re = re.compile(r'^\s*$')
   78.16 +line_re = re.compile(r'^(\w+)(.*)')
   78.17 +
   78.18 +try:
   78.19 +    os.makedirs(dest_dir)
   78.20 +except OSError, err:
   78.21 +    if err.errno != errno.EEXIST:
   78.22 +        raise
   78.23 +
   78.24 +def feedback(name, text, ctx_id):
   78.25 +    return r'\marginpar{\scriptsize \href{http://demesne:8000/book/feedback/submit/%s/%s/%d/}{Feedback}}' % (hg_id, name, ctx_id)
   78.26 +
   78.27 +ctxs = {}
   78.28 +try:
   78.29 +    cfp = open(os.path.join(dest_dir, 'rev-' + hg_id + '.ctx'), 'r+')
   78.30 +    for line in cfp:
   78.31 +        f, l, c = line.split(':', 2)
   78.32 +        ctxs[(f, int(l))] = c.strip()
   78.33 +except IOError, err:
   78.34 +    if err.errno != errno.ENOENT: raise
   78.35 +    cfp = open(os.path.join(dest_dir, 'rev-' + hg_id + '.ctx'), 'w+')
   78.36 +
   78.37 +changes = 0
   78.38 +
   78.39 +for name in sys.argv[3:]:
   78.40 +    if not name.endswith('.tex'):
   78.41 +        continue
   78.42 +    dest_name = os.path.join(dest_dir, name)
   78.43 +    ifp = open(name)
   78.44 +    ofp = open(dest_name, 'w')
   78.45 +    new_par = True
   78.46 +    line_num = 0
   78.47 +    par_num = 0
   78.48 +    for line in ifp:
   78.49 +        line_num += 1
   78.50 +        if new_par:
   78.51 +            m = line_re.match(line)
   78.52 +            if m:
   78.53 +                par_num += 1
   78.54 +                ls = line.strip()
   78.55 +                if ctxs.get((name, par_num)) != ls:
   78.56 +                    ctxs[(name, par_num)] = ls
   78.57 +                    changes += 1
   78.58 +                line = m.group(1) + feedback(name, line, par_num) + m.group(2)
   78.59 +                new_par = False
   78.60 +        elif not line.strip():
   78.61 +            new_par = True
   78.62 +        ofp.write(line)
   78.63 +
   78.64 +if changes:
   78.65 +    cfp.seek(0)
   78.66 +    print '%s: %d changes' % (cfp.name, changes)
   78.67 +    ctxs = ctxs.items()
   78.68 +    ctxs.sort()
   78.69 +    for ((file, line), content) in ctxs:
   78.70 +        cfp.write('%s:%d: %s\n' % (file, line, content))
    79.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    79.2 +++ b/fr/figs/bad-merge-1.dot	Sat Jul 10 06:24:49 2010 +0100
    79.3 @@ -0,0 +1,13 @@
    79.4 +digraph bad_merge_1 {
    79.5 +	ancestor [label="1: ancestor"];
    79.6 +	left [label="2: my change"];
    79.7 +	right [label="3: your change"];
    79.8 +	bad [label="4: bad merge"];
    79.9 +	new [label="5: new change"];
   79.10 +
   79.11 +	ancestor -> left;
   79.12 +	ancestor -> right;
   79.13 +	left -> bad;
   79.14 +	right -> bad;
   79.15 +	bad -> new;
   79.16 +}
    80.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    80.2 +++ b/fr/figs/bad-merge-2.dot	Sat Jul 10 06:24:49 2010 +0100
    80.3 @@ -0,0 +1,18 @@
    80.4 +digraph bad_merge_2 {
    80.5 +	ancestor [label="1: ancestor",color=grey,fontcolor=grey];
    80.6 +	left [label="2: my change",color=grey,fontcolor=grey];
    80.7 +	right [label="3: your change",color=grey,fontcolor=grey];
    80.8 +	bad [label="4: bad merge",color=grey,fontcolor=grey];
    80.9 +	new [label="5: new change",color=grey,fontcolor=grey];
   80.10 +
   80.11 +	bak_left [label="6: backout 1 of\nbad merge",shape=box];
   80.12 +
   80.13 +	ancestor -> left [color=grey];
   80.14 +	ancestor -> right [color=grey];
   80.15 +	left -> bad [color=grey];
   80.16 +	right -> bad [color=grey];
   80.17 +	bad -> new [color=grey];
   80.18 +
   80.19 +	bad -> bak_left;
   80.20 +	left -> bak_left [style=dotted,label="--parent=2"];
   80.21 +}
    81.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    81.2 +++ b/fr/figs/bad-merge-3.dot	Sat Jul 10 06:24:49 2010 +0100
    81.3 @@ -0,0 +1,22 @@
    81.4 +digraph bad_merge_3 {
    81.5 +	ancestor [label="1: ancestor",color="#bbbbbb",fontcolor="#bbbbbb"];
    81.6 +	left [label="2: my change",color="#bbbbbb",fontcolor="#bbbbbb"];
    81.7 +	right [label="3: your change",color="#bbbbbb",fontcolor="#bbbbbb"];
    81.8 +	bad [label="4: bad merge",color="#bbbbbb",fontcolor="#bbbbbb"];
    81.9 +	new [label="5: new change",color="#bbbbbb",fontcolor="#bbbbbb"];
   81.10 +
   81.11 +	bak_left [label="6: backout 1 of\nbad merge",color=grey,shape=box];
   81.12 +	bak_right [label="8: backout 2 of\nbad merge",shape=box];
   81.13 +
   81.14 +	ancestor -> left [color="#bbbbbb"];
   81.15 +	ancestor -> right [color="#bbbbbb"];
   81.16 +	left -> bad [color="#bbbbbb"];
   81.17 +	right -> bad [color="#bbbbbb"];
   81.18 +	bad -> new [color="#bbbbbb"];
   81.19 +
   81.20 +	bad -> bak_left [color=grey];
   81.21 +	left -> bak_left [style=dotted,label="--parent=2",color=grey,fontcolor=grey];
   81.22 +
   81.23 +	bad -> bak_right;
   81.24 +	right -> bak_right [style=dotted,label="--parent=3"];
   81.25 +}
    82.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    82.2 +++ b/fr/figs/bad-merge-4.dot	Sat Jul 10 06:24:49 2010 +0100
    82.3 @@ -0,0 +1,26 @@
    82.4 +digraph bad_merge_4 {
    82.5 +	ancestor [label="1: ancestor",color="#bbbbbb",fontcolor="#bbbbbb"];
    82.6 +	left [label="2: my change",color="#bbbbbb",fontcolor="#bbbbbb"];
    82.7 +	right [label="3: your change",color="#bbbbbb",fontcolor="#bbbbbb"];
    82.8 +	bad [label="4: bad merge",color="#bbbbbb",fontcolor="#bbbbbb"];
    82.9 +	new [label="5: new change",color="#bbbbbb",fontcolor="#bbbbbb"];
   82.10 +
   82.11 +	bak_left [label="6: backout 1 of\nbad merge",color=grey,fontcolor=grey,shape=box];
   82.12 +	bak_right [label="7: backout 2 of\nbad merge",color=grey,fontcolor=grey,shape=box];
   82.13 +	good [label="8: merge\nof backouts",shape=box];
   82.14 +
   82.15 +	ancestor -> left [color="#bbbbbb"];
   82.16 +	ancestor -> right [color="#bbbbbb"];
   82.17 +	left -> bad [color="#bbbbbb"];
   82.18 +	right -> bad [color="#bbbbbb"];
   82.19 +	bad -> new [color="#bbbbbb"];
   82.20 +
   82.21 +	bad -> bak_left [color=grey];
   82.22 +	left -> bak_left [style=dotted,label="--parent=2",color=grey,fontcolor=grey];
   82.23 +
   82.24 +	bad -> bak_right [color=grey];
   82.25 +	right -> bak_right [style=dotted,label="--parent=3",color=grey,fontcolor=grey];
   82.26 +
   82.27 +	bak_left -> good;
   82.28 +	bak_right -> good;
   82.29 +}
    83.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    83.2 +++ b/fr/figs/bad-merge-5.dot	Sat Jul 10 06:24:49 2010 +0100
    83.3 @@ -0,0 +1,30 @@
    83.4 +digraph bad_merge_5 {
    83.5 +	ancestor [label="1: ancestor",color="#bbbbbb",fontcolor="#bbbbbb"];
    83.6 +	left [label="2: my change",color="#bbbbbb",fontcolor="#bbbbbb"];
    83.7 +	right [label="3: your change",color="#bbbbbb",fontcolor="#bbbbbb"];
    83.8 +	bad [label="4: bad merge",color="#bbbbbb",fontcolor="#bbbbbb"];
    83.9 +	new [label="5: new change",color=grey,fontcolor=grey];
   83.10 +
   83.11 +	bak_left [label="6: backout 1 of\nbad merge",color="#bbbbbb",fontcolor="#bbbbbb",shape=box];
   83.12 +	bak_right [label="7: backout 2 of\nbad merge",color="#bbbbbb",fontcolor="#bbbbbb",shape=box];
   83.13 +	good [label="8: merge\nof backouts",color=grey,fontcolor=grey,shape=box];
   83.14 +	last [label="9: merge with\nnew change",shape=box];
   83.15 +
   83.16 +	ancestor -> left [color="#bbbbbb"];
   83.17 +	ancestor -> right [color="#bbbbbb"];
   83.18 +	left -> bad [color="#bbbbbb"];
   83.19 +	right -> bad [color="#bbbbbb"];
   83.20 +	bad -> new [color="#bbbbbb"];
   83.21 +
   83.22 +	bad -> bak_left [color="#bbbbbb"];
   83.23 +	left -> bak_left [style=dotted,label="--parent=2",color="#bbbbbb",fontcolor="#bbbbbb"];
   83.24 +
   83.25 +	bad -> bak_right [color="#bbbbbb"];
   83.26 +	right -> bak_right [style=dotted,label="--parent=3",color="#bbbbbb",fontcolor="#bbbbbb"];
   83.27 +
   83.28 +	bak_left -> good [color=grey];
   83.29 +	bak_right -> good [color=grey];
   83.30 +
   83.31 +	good -> last;
   83.32 +	new -> last;
   83.33 +}
    84.1 Binary file fr/figs/caution.png has changed
    85.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    85.2 +++ b/fr/figs/feature-branches.dot	Sat Jul 10 06:24:49 2010 +0100
    85.3 @@ -0,0 +1,8 @@
    85.4 +digraph feature_branches {
    85.5 +	master -> crypto;
    85.6 +	master -> filesystems;
    85.7 +	master -> ipc;
    85.8 +	master -> memory;
    85.9 +	master -> network;
   85.10 +	master -> security;
   85.11 +}
    86.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    86.2 +++ b/fr/figs/filelog.svg	Sat Jul 10 06:24:49 2010 +0100
    86.3 @@ -0,0 +1,381 @@
    86.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
    86.5 +<!-- Created with Inkscape (http://www.inkscape.org/) -->
    86.6 +<svg
    86.7 +   xmlns:dc="http://purl.org/dc/elements/1.1/"
    86.8 +   xmlns:cc="http://creativecommons.org/ns#"
    86.9 +   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   86.10 +   xmlns:svg="http://www.w3.org/2000/svg"
   86.11 +   xmlns="http://www.w3.org/2000/svg"
   86.12 +   xmlns:xlink="http://www.w3.org/1999/xlink"
   86.13 +   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   86.14 +   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   86.15 +   width="744.09448819"
   86.16 +   height="1052.3622047"
   86.17 +   id="svg2"
   86.18 +   sodipodi:version="0.32"
   86.19 +   inkscape:version="0.46"
   86.20 +   sodipodi:docname="filelog.svg"
   86.21 +   sodipodi:docbase="/home/arun/hgbook/en"
   86.22 +   inkscape:output_extension="org.inkscape.output.svg.inkscape">
   86.23 +  <defs
   86.24 +     id="defs4">
   86.25 +    <inkscape:perspective
   86.26 +       sodipodi:type="inkscape:persp3d"
   86.27 +       inkscape:vp_x="0 : 526.18109 : 1"
   86.28 +       inkscape:vp_y="0 : 1000 : 0"
   86.29 +       inkscape:vp_z="744.09448 : 526.18109 : 1"
   86.30 +       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
   86.31 +       id="perspective57" />
   86.32 +    <marker
   86.33 +       inkscape:stockid="Arrow1Mend"
   86.34 +       orient="auto"
   86.35 +       refY="0.0"
   86.36 +       refX="0.0"
   86.37 +       id="Arrow1Mend"
   86.38 +       style="overflow:visible;">
   86.39 +      <path
   86.40 +         id="path3128"
   86.41 +         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 "
   86.42 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
   86.43 +         transform="scale(0.4) rotate(180) translate(10,0)" />
   86.44 +    </marker>
   86.45 +    <linearGradient
   86.46 +       id="linearGradient2887">
   86.47 +      <stop
   86.48 +         style="stop-color:#91cfcf;stop-opacity:1;"
   86.49 +         offset="0"
   86.50 +         id="stop2889" />
   86.51 +      <stop
   86.52 +         style="stop-color:aqua;stop-opacity:0;"
   86.53 +         offset="1"
   86.54 +         id="stop2891" />
   86.55 +    </linearGradient>
   86.56 +    <linearGradient
   86.57 +       id="linearGradient2795">
   86.58 +      <stop
   86.59 +         style="stop-color:#ccc;stop-opacity:1;"
   86.60 +         offset="0"
   86.61 +         id="stop2797" />
   86.62 +      <stop
   86.63 +         style="stop-color:#ccc;stop-opacity:0;"
   86.64 +         offset="1"
   86.65 +         id="stop2799" />
   86.66 +    </linearGradient>
   86.67 +    <linearGradient
   86.68 +       inkscape:collect="always"
   86.69 +       xlink:href="#linearGradient2795"
   86.70 +       id="linearGradient3170"
   86.71 +       gradientUnits="userSpaceOnUse"
   86.72 +       gradientTransform="translate(121.2183,94.95434)"
   86.73 +       x1="81.322357"
   86.74 +       y1="404.34424"
   86.75 +       x2="201.52036"
   86.76 +       y2="373.03967" />
   86.77 +    <linearGradient
   86.78 +       inkscape:collect="always"
   86.79 +       xlink:href="#linearGradient2887"
   86.80 +       id="linearGradient3172"
   86.81 +       gradientUnits="userSpaceOnUse"
   86.82 +       gradientTransform="translate(0,12)"
   86.83 +       x1="62.634491"
   86.84 +       y1="503.3392"
   86.85 +       x2="248.49242"
   86.86 +       y2="462.94327" />
   86.87 +    <linearGradient
   86.88 +       inkscape:collect="always"
   86.89 +       xlink:href="#linearGradient2795"
   86.90 +       id="linearGradient3174"
   86.91 +       gradientUnits="userSpaceOnUse"
   86.92 +       gradientTransform="matrix(1.001035,0,0,0.653159,236.7075,153.0415)"
   86.93 +       x1="81.322357"
   86.94 +       y1="404.34424"
   86.95 +       x2="201.52036"
   86.96 +       y2="373.03967" />
   86.97 +    <linearGradient
   86.98 +       inkscape:collect="always"
   86.99 +       xlink:href="#linearGradient2887"
  86.100 +       id="linearGradient3176"
  86.101 +       gradientUnits="userSpaceOnUse"
  86.102 +       gradientTransform="translate(0,12)"
  86.103 +       x1="62.634491"
  86.104 +       y1="503.3392"
  86.105 +       x2="248.49242"
  86.106 +       y2="462.94327" />
  86.107 +    <linearGradient
  86.108 +       inkscape:collect="always"
  86.109 +       xlink:href="#linearGradient2795"
  86.110 +       id="linearGradient3208"
  86.111 +       gradientUnits="userSpaceOnUse"
  86.112 +       gradientTransform="matrix(1.001035,0,0,0.653159,236.7075,153.0415)"
  86.113 +       x1="81.322357"
  86.114 +       y1="404.34424"
  86.115 +       x2="201.52036"
  86.116 +       y2="373.03967" />
  86.117 +    <linearGradient
  86.118 +       inkscape:collect="always"
  86.119 +       xlink:href="#linearGradient2887"
  86.120 +       id="linearGradient3210"
  86.121 +       gradientUnits="userSpaceOnUse"
  86.122 +       gradientTransform="translate(0,12)"
  86.123 +       x1="62.634491"
  86.124 +       y1="503.3392"
  86.125 +       x2="248.49242"
  86.126 +       y2="462.94327" />
  86.127 +    <linearGradient
  86.128 +       inkscape:collect="always"
  86.129 +       xlink:href="#linearGradient2795"
  86.130 +       id="linearGradient3212"
  86.131 +       gradientUnits="userSpaceOnUse"
  86.132 +       gradientTransform="translate(121.2183,94.95434)"
  86.133 +       x1="81.322357"
  86.134 +       y1="404.34424"
  86.135 +       x2="201.52036"
  86.136 +       y2="373.03967" />
  86.137 +    <linearGradient
  86.138 +       inkscape:collect="always"
  86.139 +       xlink:href="#linearGradient2887"
  86.140 +       id="linearGradient3214"
  86.141 +       gradientUnits="userSpaceOnUse"
  86.142 +       gradientTransform="translate(0,12)"
  86.143 +       x1="62.634491"
  86.144 +       y1="503.3392"
  86.145 +       x2="248.49242"
  86.146 +       y2="462.94327" />
  86.147 +    <linearGradient
  86.148 +       inkscape:collect="always"
  86.149 +       xlink:href="#linearGradient2795"
  86.150 +       id="linearGradient3256"
  86.151 +       gradientUnits="userSpaceOnUse"
  86.152 +       gradientTransform="matrix(1.2343775,0,0,0.9981848,103.25588,95.681888)"
  86.153 +       x1="74.301666"
  86.154 +       y1="431.67441"
  86.155 +       x2="260.05884"
  86.156 +       y2="369.95322" />
  86.157 +    <linearGradient
  86.158 +       inkscape:collect="always"
  86.159 +       xlink:href="#linearGradient2887"
  86.160 +       id="linearGradient3258"
  86.161 +       gradientUnits="userSpaceOnUse"
  86.162 +       gradientTransform="matrix(1.228929,0,0,0.9972824,-62.037003,13.312997)"
  86.163 +       x1="62.634491"
  86.164 +       y1="503.3392"
  86.165 +       x2="248.49242"
  86.166 +       y2="462.94327" />
  86.167 +    <linearGradient
  86.168 +       inkscape:collect="always"
  86.169 +       xlink:href="#linearGradient2795"
  86.170 +       id="linearGradient3260"
  86.171 +       gradientUnits="userSpaceOnUse"
  86.172 +       gradientTransform="matrix(1.2300738,0,0,0.6517275,219.97511,153.61527)"
  86.173 +       x1="74.387527"
  86.174 +       y1="431.80576"
  86.175 +       x2="259.97339"
  86.176 +       y2="369.82224" />
  86.177 +    <linearGradient
  86.178 +       inkscape:collect="always"
  86.179 +       xlink:href="#linearGradient2887"
  86.180 +       id="linearGradient3262"
  86.181 +       gradientUnits="userSpaceOnUse"
  86.182 +       gradientTransform="matrix(1.2289272,0,0,0.9972824,-62.036756,13.312985)"
  86.183 +       x1="62.634491"
  86.184 +       y1="503.3392"
  86.185 +       x2="248.49242"
  86.186 +       y2="462.94327" />
  86.187 +  </defs>
  86.188 +  <sodipodi:namedview
  86.189 +     id="base"
  86.190 +     pagecolor="#ffffff"
  86.191 +     bordercolor="#666666"
  86.192 +     borderopacity="1.0"
  86.193 +     gridtolerance="10000"
  86.194 +     guidetolerance="10"
  86.195 +     objecttolerance="10"
  86.196 +     inkscape:pageopacity="0.0"
  86.197 +     inkscape:pageshadow="2"
  86.198 +     inkscape:zoom="1.4"
  86.199 +     inkscape:cx="455.8122"
  86.200 +     inkscape:cy="520"
  86.201 +     inkscape:document-units="px"
  86.202 +     inkscape:current-layer="g2940"
  86.203 +     inkscape:window-width="1680"
  86.204 +     inkscape:window-height="970"
  86.205 +     inkscape:window-x="3"
  86.206 +     inkscape:window-y="46"
  86.207 +     showgrid="false" />
  86.208 +  <metadata
  86.209 +     id="metadata7">
  86.210 +    <rdf:RDF>
  86.211 +      <cc:Work
  86.212 +         rdf:about="">
  86.213 +        <dc:format>image/svg+xml</dc:format>
  86.214 +        <dc:type
  86.215 +           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
  86.216 +      </cc:Work>
  86.217 +    </rdf:RDF>
  86.218 +  </metadata>
  86.219 +  <g
  86.220 +     inkscape:label="Layer 1"
  86.221 +     inkscape:groupmode="layer"
  86.222 +     id="layer1">
  86.223 +    <rect
  86.224 +       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"
  86.225 +       id="rect3180"
  86.226 +       width="273.81375"
  86.227 +       height="199.06245"
  86.228 +       x="369.1796"
  86.229 +       y="351.79019" />
  86.230 +    <rect
  86.231 +       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"
  86.232 +       id="rect3178"
  86.233 +       width="273.81339"
  86.234 +       height="199.06233"
  86.235 +       x="72.699799"
  86.236 +       y="351.78983" />
  86.237 +    <g
  86.238 +       id="g3144"
  86.239 +       transform="translate(80.467048,0.71578)">
  86.240 +      <g
  86.241 +         id="g2940">
  86.242 +        <rect
  86.243 +           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"
  86.244 +           id="rect2914"
  86.245 +           width="227.38896"
  86.246 +           height="39.500999"
  86.247 +           x="311.92496"
  86.248 +           y="395.08627" />
  86.249 +        <text
  86.250 +           xml:space="preserve"
  86.251 +           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"
  86.252 +           x="323.72824"
  86.253 +           y="416.7626"
  86.254 +           id="text2918"><tspan
  86.255 +             sodipodi:role="line"
  86.256 +             id="tspan2920"
  86.257 +             x="323.72824"
  86.258 +             y="416.7626"
  86.259 +             style="font-family:Courier">.hg/store/data/_r_e_a_d_m_e.i</tspan></text>
  86.260 +      </g>
  86.261 +      <g
  86.262 +         transform="translate(3.79093e-5,-80.1853)"
  86.263 +         id="g2945">
  86.264 +        <g
  86.265 +           id="g2955">
  86.266 +          <rect
  86.267 +             y="475.4968"
  86.268 +             x="15.550935"
  86.269 +             height="39.500999"
  86.270 +             width="227.17694"
  86.271 +             id="rect2947"
  86.272 +             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" />
  86.273 +          <text
  86.274 +             id="text2949"
  86.275 +             y="498.35123"
  86.276 +             x="31.230644"
  86.277 +             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"
  86.278 +             xml:space="preserve"><tspan
  86.279 +               style="font-family:Courier"
  86.280 +               y="498.35123"
  86.281 +               x="31.230644"
  86.282 +               id="tspan2951"
  86.283 +               sodipodi:role="line">README</tspan></text>
  86.284 +        </g>
  86.285 +      </g>
  86.286 +      <path
  86.287 +         inkscape:connector-type="polyline"
  86.288 +         id="path2960"
  86.289 +         d="M 242.94685,414.91115 C 242.94685,414.91115 293.61127,415.26754 310.16269,415.38633"
  86.290 +         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"
  86.291 +         sodipodi:nodetypes="cz" />
  86.292 +    </g>
  86.293 +    <g
  86.294 +       id="g3156"
  86.295 +       transform="translate(80.467048,0.71578)">
  86.296 +      <g
  86.297 +         transform="translate(116,0)"
  86.298 +         id="g2831">
  86.299 +        <rect
  86.300 +           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"
  86.301 +           id="rect1906"
  86.302 +           width="228.18446"
  86.303 +           height="60.499123"
  86.304 +           x="195.52719"
  86.305 +           y="465.51859" />
  86.306 +        <g
  86.307 +           id="g2803"
  86.308 +           transform="translate(-0.893671,1.833581)">
  86.309 +          <text
  86.310 +             id="text1884"
  86.311 +             y="483.92801"
  86.312 +             x="208.95944"
  86.313 +             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"
  86.314 +             xml:space="preserve"><tspan
  86.315 +               style="font-family:Courier"
  86.316 +               y="483.92801"
  86.317 +               x="208.95944"
  86.318 +               id="tspan1886"
  86.319 +               sodipodi:role="line">.hg/store/data/src/hello.c.d</tspan></text>
  86.320 +          <text
  86.321 +             id="text1888"
  86.322 +             y="507.79309"
  86.323 +             x="208.95944"
  86.324 +             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"
  86.325 +             xml:space="preserve"><tspan
  86.326 +               style="font-family:Courier"
  86.327 +               y="507.79309"
  86.328 +               x="208.95944"
  86.329 +               id="tspan1890"
  86.330 +               sodipodi:role="line">.hg/store/data/src/hello.c.i</tspan></text>
  86.331 +        </g>
  86.332 +      </g>
  86.333 +      <g
  86.334 +         id="g2907">
  86.335 +        <rect
  86.336 +           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"
  86.337 +           id="rect2843"
  86.338 +           width="227.17728"
  86.339 +           height="39.500999"
  86.340 +           x="15.550805"
  86.341 +           y="475.4968" />
  86.342 +        <text
  86.343 +           xml:space="preserve"
  86.344 +           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"
  86.345 +           x="31.230644"
  86.346 +           y="498.35123"
  86.347 +           id="text2847"><tspan
  86.348 +             sodipodi:role="line"
  86.349 +             id="tspan2849"
  86.350 +             x="31.230644"
  86.351 +             y="498.35123"
  86.352 +             style="font-family:Courier">src/hello.c</tspan></text>
  86.353 +      </g>
  86.354 +      <path
  86.355 +         inkscape:connection-end="#g2831"
  86.356 +         inkscape:connection-start="#g2907"
  86.357 +         inkscape:connector-type="polyline"
  86.358 +         id="path2962"
  86.359 +         d="M 242.4315,495.88043 C 242.4315,495.88043 292.8861,495.99942 310.04102,496.03909"
  86.360 +         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"
  86.361 +         sodipodi:nodetypes="cs" />
  86.362 +    </g>
  86.363 +    <text
  86.364 +       xml:space="preserve"
  86.365 +       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"
  86.366 +       x="98.496666"
  86.367 +       y="373.96353"
  86.368 +       id="text3216"><tspan
  86.369 +         sodipodi:role="line"
  86.370 +         id="tspan3218"
  86.371 +         x="98.496666"
  86.372 +         y="373.96353">Working directory</tspan></text>
  86.373 +    <text
  86.374 +       xml:space="preserve"
  86.375 +       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"
  86.376 +       x="391.39197"
  86.377 +       y="373.96353"
  86.378 +       id="text3228"><tspan
  86.379 +         sodipodi:role="line"
  86.380 +         id="tspan3230"
  86.381 +         x="391.39197"
  86.382 +         y="373.96353">Repository</tspan></text>
  86.383 +  </g>
  86.384 +</svg>
    87.1 Binary file fr/figs/kdiff3.png has changed
    88.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    88.2 +++ b/fr/figs/metadata.svg	Sat Jul 10 06:24:49 2010 +0100
    88.3 @@ -0,0 +1,328 @@
    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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   88.13 +   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   88.14 +   width="744.09448819"
   88.15 +   height="1052.3622047"
   88.16 +   id="svg2"
   88.17 +   sodipodi:version="0.32"
   88.18 +   inkscape:version="0.44.1"
   88.19 +   sodipodi:docname="metadata.svg"
   88.20 +   sodipodi:docbase="/home/bos/hg/hgbook/en">
   88.21 +  <defs
   88.22 +     id="defs4">
   88.23 +    <marker
   88.24 +       inkscape:stockid="Arrow1Mend"
   88.25 +       orient="auto"
   88.26 +       refY="0.0"
   88.27 +       refX="0.0"
   88.28 +       id="Arrow1Mend"
   88.29 +       style="overflow:visible;">
   88.30 +      <path
   88.31 +         id="path2944"
   88.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 "
   88.33 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
   88.34 +         transform="scale(0.4) rotate(180) translate(10,0)" />
   88.35 +    </marker>
   88.36 +  </defs>
   88.37 +  <sodipodi:namedview
   88.38 +     id="base"
   88.39 +     pagecolor="#ffffff"
   88.40 +     bordercolor="#666666"
   88.41 +     borderopacity="1.0"
   88.42 +     gridtolerance="10000"
   88.43 +     guidetolerance="10"
   88.44 +     objecttolerance="10"
   88.45 +     inkscape:pageopacity="0.0"
   88.46 +     inkscape:pageshadow="2"
   88.47 +     inkscape:zoom="1.4"
   88.48 +     inkscape:cx="232.14286"
   88.49 +     inkscape:cy="490.68696"
   88.50 +     inkscape:document-units="px"
   88.51 +     inkscape:current-layer="layer1"
   88.52 +     inkscape:window-width="906"
   88.53 +     inkscape:window-height="620"
   88.54 +     inkscape:window-x="181"
   88.55 +     inkscape:window-y="58" />
   88.56 +  <metadata
   88.57 +     id="metadata7">
   88.58 +    <rdf:RDF>
   88.59 +      <cc:Work
   88.60 +         rdf:about="">
   88.61 +        <dc:format>image/svg+xml</dc:format>
   88.62 +        <dc:type
   88.63 +           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
   88.64 +      </cc:Work>
   88.65 +    </rdf:RDF>
   88.66 +  </metadata>
   88.67 +  <g
   88.68 +     inkscape:label="Layer 1"
   88.69 +     inkscape:groupmode="layer"
   88.70 +     id="layer1">
   88.71 +    <path
   88.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"
   88.73 +       d="M 326.94646,467.18359 L 326.94646,510.98123"
   88.74 +       id="path1910"
   88.75 +       inkscape:connector-type="polyline"
   88.76 +       inkscape:connection-end="#rect2962"
   88.77 +       inkscape:connection-start="#rect2764" />
   88.78 +    <path
   88.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"
   88.80 +       d="M 326.94646,531.98123 L 326.94646,591.77887"
   88.81 +       id="path1912"
   88.82 +       inkscape:connector-type="polyline"
   88.83 +       inkscape:connection-start="#rect2962"
   88.84 +       inkscape:connection-end="#rect3000" />
   88.85 +    <path
   88.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"
   88.87 +       d="M 316.1622,531.98123 L 192.30212,652.57648"
   88.88 +       id="path1916"
   88.89 +       inkscape:connector-type="polyline"
   88.90 +       inkscape:connection-end="#rect3038"
   88.91 +       inkscape:connection-start="#rect2962" />
   88.92 +    <path
   88.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"
   88.94 +       d="M 254.23217,467.18359 L 254.23216,510.98123"
   88.95 +       id="path3088"
   88.96 +       inkscape:connector-type="polyline"
   88.97 +       inkscape:connection-start="#rect1872"
   88.98 +       inkscape:connection-end="#rect2960" />
   88.99 +    <path
  88.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"
  88.101 +       d="M 254.23215,531.98123 L 254.23215,591.77887"
  88.102 +       id="path3090"
  88.103 +       inkscape:connector-type="polyline"
  88.104 +       inkscape:connection-start="#rect2960"
  88.105 +       inkscape:connection-end="#rect2998" />
  88.106 +    <path
  88.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"
  88.108 +       d="M 248.84002,531.98123 L 186.90999,652.57648"
  88.109 +       id="path3092"
  88.110 +       inkscape:connector-type="polyline"
  88.111 +       inkscape:connection-start="#rect2960"
  88.112 +       inkscape:connection-end="#rect3038" />
  88.113 +    <rect
  88.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"
  88.115 +       id="rect1872"
  88.116 +       width="51.42857"
  88.117 +       height="20"
  88.118 +       x="228.51788"
  88.119 +       y="446.68359" />
  88.120 +    <rect
  88.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"
  88.122 +       id="rect2764"
  88.123 +       width="51.42857"
  88.124 +       height="20"
  88.125 +       x="301.23218"
  88.126 +       y="446.68359" />
  88.127 +    <rect
  88.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"
  88.129 +       id="rect2766"
  88.130 +       width="51.42857"
  88.131 +       height="20"
  88.132 +       x="155.80359"
  88.133 +       y="446.68359" />
  88.134 +    <rect
  88.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"
  88.136 +       id="rect2768"
  88.137 +       width="51.42857"
  88.138 +       height="20"
  88.139 +       x="83.089294"
  88.140 +       y="446.68359" />
  88.141 +    <path
  88.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"
  88.143 +       d="M 135.01786,456.68359 L 155.30359,456.68359"
  88.144 +       id="path2770"
  88.145 +       inkscape:connector-type="polyline"
  88.146 +       inkscape:connection-start="#rect2768"
  88.147 +       inkscape:connection-end="#rect2766" />
  88.148 +    <path
  88.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"
  88.150 +       d="M 207.73216,456.68359 L 228.01788,456.68359"
  88.151 +       id="path2772"
  88.152 +       inkscape:connector-type="polyline"
  88.153 +       inkscape:connection-start="#rect2766"
  88.154 +       inkscape:connection-end="#rect1872" />
  88.155 +    <path
  88.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"
  88.157 +       d="M 280.44645,456.68359 L 300.73218,456.68359"
  88.158 +       id="path2774"
  88.159 +       inkscape:connector-type="polyline"
  88.160 +       inkscape:connection-start="#rect1872"
  88.161 +       inkscape:connection-end="#rect2764" />
  88.162 +    <path
  88.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"
  88.164 +       d="M 62.303571,456.68359 L 82.589294,456.68359"
  88.165 +       id="path2778"
  88.166 +       inkscape:connector-type="polyline"
  88.167 +       inkscape:connection-end="#rect2768" />
  88.168 +    <rect
  88.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"
  88.170 +       id="rect2960"
  88.171 +       width="51.42857"
  88.172 +       height="20"
  88.173 +       x="228.51787"
  88.174 +       y="511.48123" />
  88.175 +    <rect
  88.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"
  88.177 +       id="rect2962"
  88.178 +       width="51.42857"
  88.179 +       height="20"
  88.180 +       x="301.23218"
  88.181 +       y="511.48123" />
  88.182 +    <rect
  88.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"
  88.184 +       id="rect2964"
  88.185 +       width="51.42857"
  88.186 +       height="20"
  88.187 +       x="155.80357"
  88.188 +       y="511.48123" />
  88.189 +    <rect
  88.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"
  88.191 +       id="rect2966"
  88.192 +       width="51.42857"
  88.193 +       height="20"
  88.194 +       x="83.089287"
  88.195 +       y="511.48123" />
  88.196 +    <path
  88.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"
  88.198 +       d="M 135.01786,521.48121 L 155.30359,521.48121"
  88.199 +       id="path2968"
  88.200 +       inkscape:connector-type="polyline" />
  88.201 +    <path
  88.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"
  88.203 +       d="M 207.73216,521.48121 L 228.01788,521.48121"
  88.204 +       id="path2970"
  88.205 +       inkscape:connector-type="polyline" />
  88.206 +    <path
  88.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"
  88.208 +       d="M 280.44645,521.48121 L 300.73218,521.48121"
  88.209 +       id="path2972"
  88.210 +       inkscape:connector-type="polyline" />
  88.211 +    <path
  88.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"
  88.213 +       d="M 62.30358,521.48121 L 82.5893,521.48121"
  88.214 +       id="path2974"
  88.215 +       inkscape:connector-type="polyline" />
  88.216 +    <rect
  88.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"
  88.218 +       id="rect2998"
  88.219 +       width="51.42857"
  88.220 +       height="20"
  88.221 +       x="228.51787"
  88.222 +       y="592.27887" />
  88.223 +    <rect
  88.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"
  88.225 +       id="rect3000"
  88.226 +       width="51.42857"
  88.227 +       height="20"
  88.228 +       x="301.23218"
  88.229 +       y="592.27887" />
  88.230 +    <rect
  88.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"
  88.232 +       id="rect3002"
  88.233 +       width="51.42857"
  88.234 +       height="20"
  88.235 +       x="155.80357"
  88.236 +       y="592.27887" />
  88.237 +    <rect
  88.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"
  88.239 +       id="rect3004"
  88.240 +       width="51.42857"
  88.241 +       height="20"
  88.242 +       x="83.089287"
  88.243 +       y="592.27887" />
  88.244 +    <path
  88.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"
  88.246 +       d="M 135.01786,602.27884 L 155.30359,602.27884"
  88.247 +       id="path3006"
  88.248 +       inkscape:connector-type="polyline" />
  88.249 +    <path
  88.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"
  88.251 +       d="M 207.73216,602.27884 L 228.01788,602.27884"
  88.252 +       id="path3008"
  88.253 +       inkscape:connector-type="polyline" />
  88.254 +    <path
  88.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"
  88.256 +       d="M 280.44645,602.27884 L 300.73218,602.27884"
  88.257 +       id="path3010"
  88.258 +       inkscape:connector-type="polyline" />
  88.259 +    <path
  88.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"
  88.261 +       d="M 62.30358,602.27884 L 82.5893,602.27884"
  88.262 +       id="path3012"
  88.263 +       inkscape:connector-type="polyline" />
  88.264 +    <rect
  88.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"
  88.266 +       id="rect3034"
  88.267 +       width="51.42857"
  88.268 +       height="20"
  88.269 +       x="228.51787"
  88.270 +       y="653.07648" />
  88.271 +    <rect
  88.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"
  88.273 +       id="rect3038"
  88.274 +       width="51.42857"
  88.275 +       height="20"
  88.276 +       x="155.80357"
  88.277 +       y="653.07648" />
  88.278 +    <rect
  88.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"
  88.280 +       id="rect3040"
  88.281 +       width="51.42857"
  88.282 +       height="20"
  88.283 +       x="83.089287"
  88.284 +       y="653.07648" />
  88.285 +    <path
  88.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"
  88.287 +       d="M 135.01786,663.07646 L 155.30359,663.07646"
  88.288 +       id="path3042"
  88.289 +       inkscape:connector-type="polyline" />
  88.290 +    <path
  88.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"
  88.292 +       d="M 207.73216,663.07646 L 228.01788,663.07646"
  88.293 +       id="path3044"
  88.294 +       inkscape:connector-type="polyline" />
  88.295 +    <path
  88.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"
  88.297 +       d="M 62.30358,663.07646 L 82.5893,663.07646"
  88.298 +       id="path3048"
  88.299 +       inkscape:connector-type="polyline" />
  88.300 +    <text
  88.301 +       xml:space="preserve"
  88.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"
  88.303 +       x="82.072548"
  88.304 +       y="432.64789"
  88.305 +       id="text3094"><tspan
  88.306 +         sodipodi:role="line"
  88.307 +         id="tspan3096"
  88.308 +         x="82.072548"
  88.309 +         y="432.64789">Changelog</tspan></text>
  88.310 +    <text
  88.311 +       xml:space="preserve"
  88.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"
  88.313 +       x="82.306923"
  88.314 +       y="498.97327"
  88.315 +       id="text3098"><tspan
  88.316 +         sodipodi:role="line"
  88.317 +         id="tspan3100"
  88.318 +         x="82.306923"
  88.319 +         y="498.97327">Manifest</tspan></text>
  88.320 +    <text
  88.321 +       xml:space="preserve"
  88.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"
  88.323 +       x="82.14286"
  88.324 +       y="580.08569"
  88.325 +       id="text3102"><tspan
  88.326 +         sodipodi:role="line"
  88.327 +         id="tspan3104"
  88.328 +         x="82.14286"
  88.329 +         y="580.08569">Filelogs</tspan></text>
  88.330 +  </g>
  88.331 +</svg>
    89.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    89.2 +++ b/fr/figs/mq-stack.svg	Sat Jul 10 06:24:49 2010 +0100
    89.3 @@ -0,0 +1,270 @@
    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:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
   89.13 +   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   89.14 +   width="744.09448819"
   89.15 +   height="1052.3622047"
   89.16 +   id="svg2"
   89.17 +   sodipodi:version="0.32"
   89.18 +   inkscape:version="0.43"
   89.19 +   sodipodi:docname="mq-stack.svg"
   89.20 +   sodipodi:docbase="/home/bos/hg/hgbook/en">
   89.21 +  <defs
   89.22 +     id="defs4" />
   89.23 +  <sodipodi:namedview
   89.24 +     id="base"
   89.25 +     pagecolor="#ffffff"
   89.26 +     bordercolor="#666666"
   89.27 +     borderopacity="1.0"
   89.28 +     inkscape:pageopacity="0.0"
   89.29 +     inkscape:pageshadow="2"
   89.30 +     inkscape:zoom="1.4142136"
   89.31 +     inkscape:cx="299.33323"
   89.32 +     inkscape:cy="815.646"
   89.33 +     inkscape:document-units="px"
   89.34 +     inkscape:current-layer="layer1"
   89.35 +     inkscape:window-width="1014"
   89.36 +     inkscape:window-height="689"
   89.37 +     inkscape:window-x="0"
   89.38 +     inkscape:window-y="25" />
   89.39 +  <metadata
   89.40 +     id="metadata7">
   89.41 +    <rdf:RDF>
   89.42 +      <cc:Work
   89.43 +         rdf:about="">
   89.44 +        <dc:format>image/svg+xml</dc:format>
   89.45 +        <dc:type
   89.46 +           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
   89.47 +      </cc:Work>
   89.48 +    </rdf:RDF>
   89.49 +  </metadata>
   89.50 +  <g
   89.51 +     inkscape:label="Layer 1"
   89.52 +     inkscape:groupmode="layer"
   89.53 +     id="layer1">
   89.54 +    <rect
   89.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"
   89.56 +       id="rect1307"
   89.57 +       width="202.93683"
   89.58 +       height="24.243662"
   89.59 +       x="230.01944"
   89.60 +       y="221.70146" />
   89.61 +    <text
   89.62 +       xml:space="preserve"
   89.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"
   89.64 +       x="237.89606"
   89.65 +       y="237.13383"
   89.66 +       id="text1309"><tspan
   89.67 +         sodipodi:role="line"
   89.68 +         id="tspan1311"
   89.69 +         x="237.89606"
   89.70 +         y="237.13383">prevent-compiler-reorder.patch</tspan></text>
   89.71 +    <rect
   89.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"
   89.73 +       id="rect1320"
   89.74 +       width="202.93683"
   89.75 +       height="24.243662"
   89.76 +       x="230.01936"
   89.77 +       y="251.34325" />
   89.78 +    <text
   89.79 +       xml:space="preserve"
   89.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"
   89.81 +       x="237.89598"
   89.82 +       y="266.77563"
   89.83 +       id="text1322"><tspan
   89.84 +         sodipodi:role="line"
   89.85 +         id="tspan1324"
   89.86 +         x="237.89598"
   89.87 +         y="266.77563">namespace-cleanup.patch</tspan></text>
   89.88 +    <rect
   89.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"
   89.90 +       id="rect2217"
   89.91 +       width="202.93683"
   89.92 +       height="24.243662"
   89.93 +       x="230.01936"
   89.94 +       y="280.98505" />
   89.95 +    <text
   89.96 +       xml:space="preserve"
   89.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"
   89.98 +       x="237.89598"
   89.99 +       y="296.41742"
  89.100 +       id="text2219"><tspan
  89.101 +         sodipodi:role="line"
  89.102 +         id="tspan2221"
  89.103 +         x="237.89598"
  89.104 +         y="296.41742">powerpc-port-fixes.patch</tspan></text>
  89.105 +    <rect
  89.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"
  89.107 +       id="rect3114"
  89.108 +       width="202.93683"
  89.109 +       height="24.243662"
  89.110 +       x="230.01936"
  89.111 +       y="310.6268" />
  89.112 +    <text
  89.113 +       xml:space="preserve"
  89.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"
  89.115 +       x="237.89598"
  89.116 +       y="326.05917"
  89.117 +       id="text3116"><tspan
  89.118 +         sodipodi:role="line"
  89.119 +         id="tspan3118"
  89.120 +         x="237.89598"
  89.121 +         y="326.05917">report-devinfo-correctly.patch</tspan></text>
  89.122 +    <text
  89.123 +       xml:space="preserve"
  89.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"
  89.125 +       x="200.01021"
  89.126 +       y="191.68094"
  89.127 +       id="text3170"
  89.128 +       sodipodi:linespacing="125%"><tspan
  89.129 +         sodipodi:role="line"
  89.130 +         id="tspan3172"
  89.131 +         x="200.01021"
  89.132 +         y="191.68094"
  89.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>
  89.134 +    <text
  89.135 +       xml:space="preserve"
  89.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"
  89.137 +       x="255.26627"
  89.138 +       y="248.79449"
  89.139 +       id="text3190"
  89.140 +       sodipodi:linespacing="125%"
  89.141 +       transform="scale(0.786716,1.271107)"><tspan
  89.142 +         sodipodi:role="line"
  89.143 +         id="tspan3192"
  89.144 +         x="255.26627"
  89.145 +         y="248.79449"
  89.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>
  89.147 +    <text
  89.148 +       xml:space="preserve"
  89.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"
  89.150 +       x="195.86807"
  89.151 +       y="173.17117"
  89.152 +       id="text4085"
  89.153 +       sodipodi:linespacing="125%"><tspan
  89.154 +         sodipodi:role="line"
  89.155 +         id="tspan4087"
  89.156 +         x="195.86807"
  89.157 +         y="173.17117"
  89.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
  89.159 +         sodipodi:role="line"
  89.160 +         x="195.86807"
  89.161 +         y="188.17117"
  89.162 +         id="tspan4089"
  89.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>
  89.164 +    <text
  89.165 +       xml:space="preserve"
  89.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"
  89.167 +       x="195.0712"
  89.168 +       y="288.91745"
  89.169 +       id="text4091"
  89.170 +       sodipodi:linespacing="125%"><tspan
  89.171 +         sodipodi:role="line"
  89.172 +         id="tspan4093"
  89.173 +         x="195.0712"
  89.174 +         y="288.91745"
  89.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
  89.176 +         sodipodi:role="line"
  89.177 +         x="195.0712"
  89.178 +         y="303.91745"
  89.179 +         id="tspan4111"
  89.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>
  89.181 +    <text
  89.182 +       xml:space="preserve"
  89.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"
  89.184 +       x="195.0712"
  89.185 +       y="229.28813"
  89.186 +       id="text4095"
  89.187 +       sodipodi:linespacing="125%"><tspan
  89.188 +         sodipodi:role="line"
  89.189 +         id="tspan4097"
  89.190 +         x="195.0712"
  89.191 +         y="229.28813"
  89.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
  89.193 +         sodipodi:role="line"
  89.194 +         x="195.0712"
  89.195 +         y="244.28813"
  89.196 +         id="tspan4109"
  89.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>
  89.198 +    <text
  89.199 +       xml:space="preserve"
  89.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"
  89.201 +       x="450.4975"
  89.202 +       y="238.29692"
  89.203 +       id="text4137"><tspan
  89.204 +         sodipodi:role="line"
  89.205 +         id="tspan4139"
  89.206 +         x="450.4975"
  89.207 +         y="238.29692">201ad3209902</tspan></text>
  89.208 +    <text
  89.209 +       xml:space="preserve"
  89.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"
  89.211 +       x="450.05804"
  89.212 +       y="267.93872"
  89.213 +       id="text4141"><tspan
  89.214 +         sodipodi:role="line"
  89.215 +         id="tspan4143"
  89.216 +         x="450.05804"
  89.217 +         y="267.93872">126b84e593ae</tspan></text>
  89.218 +    <text
  89.219 +       xml:space="preserve"
  89.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"
  89.221 +       x="450.6557"
  89.222 +       y="297.58051"
  89.223 +       id="text4145"><tspan
  89.224 +         sodipodi:role="line"
  89.225 +         id="tspan4147"
  89.226 +         x="450.6557"
  89.227 +         y="297.58051">a655daf15409</tspan></text>
  89.228 +    <text
  89.229 +       xml:space="preserve"
  89.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"
  89.231 +       x="450.71429"
  89.232 +       y="327.22226"
  89.233 +       id="text4149"><tspan
  89.234 +         sodipodi:role="line"
  89.235 +         id="tspan4151"
  89.236 +         x="450.71429"
  89.237 +         y="327.22226">e50d59aaea3a</tspan></text>
  89.238 +    <rect
  89.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"
  89.240 +       id="rect3106"
  89.241 +       width="202.93683"
  89.242 +       height="24.243662"
  89.243 +       x="230.01936"
  89.244 +       y="150.41792" />
  89.245 +    <text
  89.246 +       xml:space="preserve"
  89.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"
  89.248 +       x="237.89598"
  89.249 +       y="165.8503"
  89.250 +       id="text3108"><tspan
  89.251 +         sodipodi:role="line"
  89.252 +         id="tspan3110"
  89.253 +         x="237.89598"
  89.254 +         y="165.8503">forbid-illegal-params.patch</tspan></text>
  89.255 +    <rect
  89.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"
  89.257 +       id="rect2241"
  89.258 +       width="202.93683"
  89.259 +       height="24.243662"
  89.260 +       x="230.16466"
  89.261 +       y="180.05968" />
  89.262 +    <text
  89.263 +       xml:space="preserve"
  89.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"
  89.265 +       x="238.04128"
  89.266 +       y="195.49205"
  89.267 +       id="text2243"><tspan
  89.268 +         sodipodi:role="line"
  89.269 +         id="tspan2245"
  89.270 +         x="238.04128"
  89.271 +         y="195.49205">fix-memory-leak.patch</tspan></text>
  89.272 +  </g>
  89.273 +</svg>
    90.1 Binary file fr/figs/note.png has changed
    91.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    91.2 +++ b/fr/figs/revlog.svg	Sat Jul 10 06:24:49 2010 +0100
    91.3 @@ -0,0 +1,1155 @@
    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="svg2"
   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="revlog.svg">
   91.22 +  <defs
   91.23 +     id="defs4">
   91.24 +    <marker
   91.25 +       inkscape:stockid="Arrow1Mend"
   91.26 +       orient="auto"
   91.27 +       refY="0.0"
   91.28 +       refX="0.0"
   91.29 +       id="Arrow1Mend"
   91.30 +       style="overflow:visible;">
   91.31 +      <path
   91.32 +         id="path4852"
   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) rotate(180) translate(10,0)" />
   91.36 +    </marker>
   91.37 +    <linearGradient
   91.38 +       id="linearGradient3092">
   91.39 +      <stop
   91.40 +         style="stop-color:#44436f;stop-opacity:1;"
   91.41 +         offset="0"
   91.42 +         id="stop3094" />
   91.43 +      <stop
   91.44 +         style="stop-color:#abade5;stop-opacity:1;"
   91.45 +         offset="1"
   91.46 +         id="stop3096" />
   91.47 +    </linearGradient>
   91.48 +    <linearGradient
   91.49 +       inkscape:collect="always"
   91.50 +       xlink:href="#linearGradient3092"
   91.51 +       id="linearGradient3118"
   91.52 +       gradientUnits="userSpaceOnUse"
   91.53 +       x1="176.16635"
   91.54 +       y1="405.21934"
   91.55 +       x2="417.11935"
   91.56 +       y2="405.21934" />
   91.57 +    <linearGradient
   91.58 +       inkscape:collect="always"
   91.59 +       xlink:href="#linearGradient3092"
   91.60 +       id="linearGradient3120"
   91.61 +       gradientUnits="userSpaceOnUse"
   91.62 +       x1="176.16635"
   91.63 +       y1="405.21934"
   91.64 +       x2="417.11935"
   91.65 +       y2="405.21934" />
   91.66 +    <linearGradient
   91.67 +       inkscape:collect="always"
   91.68 +       xlink:href="#linearGradient3092"
   91.69 +       id="linearGradient3129"
   91.70 +       gradientUnits="userSpaceOnUse"
   91.71 +       x1="176.16635"
   91.72 +       y1="405.21934"
   91.73 +       x2="417.11935"
   91.74 +       y2="405.21934"
   91.75 +       gradientTransform="translate(-0.928574,-1.428574)" />
   91.76 +    <linearGradient
   91.77 +       inkscape:collect="always"
   91.78 +       xlink:href="#linearGradient3092"
   91.79 +       id="linearGradient3133"
   91.80 +       gradientUnits="userSpaceOnUse"
   91.81 +       x1="176.16635"
   91.82 +       y1="405.21934"
   91.83 +       x2="417.11935"
   91.84 +       y2="405.21934"
   91.85 +       gradientTransform="translate(-0.928574,-1.428574)" />
   91.86 +    <linearGradient
   91.87 +       inkscape:collect="always"
   91.88 +       xlink:href="#linearGradient3092"
   91.89 +       id="linearGradient3708"
   91.90 +       gradientUnits="userSpaceOnUse"
   91.91 +       gradientTransform="matrix(0.423343,0,0,0.423343,138.874,-67.01732)"
   91.92 +       x1="175.23776"
   91.93 +       y1="509.98154"
   91.94 +       x2="416.29077"
   91.95 +       y2="297.49997" />
   91.96 +    <linearGradient
   91.97 +       inkscape:collect="always"
   91.98 +       xlink:href="#linearGradient3092"
   91.99 +       id="linearGradient5164"
  91.100 +       gradientUnits="userSpaceOnUse"
  91.101 +       gradientTransform="matrix(0.423343,0,0,0.423343,198.249,247.4358)"
  91.102 +       x1="175.23776"
  91.103 +       y1="509.98154"
  91.104 +       x2="416.29077"
  91.105 +       y2="297.49997" />
  91.106 +    <linearGradient
  91.107 +       inkscape:collect="always"
  91.108 +       xlink:href="#linearGradient3092"
  91.109 +       id="linearGradient5584"
  91.110 +       gradientUnits="userSpaceOnUse"
  91.111 +       gradientTransform="matrix(0.423343,0,0,0.423343,143.9081,371.2915)"
  91.112 +       x1="175.23776"
  91.113 +       y1="509.98154"
  91.114 +       x2="416.29077"
  91.115 +       y2="297.49997" />
  91.116 +    <linearGradient
  91.117 +       inkscape:collect="always"
  91.118 +       xlink:href="#linearGradient3092"
  91.119 +       id="linearGradient5784"
  91.120 +       gradientUnits="userSpaceOnUse"
  91.121 +       gradientTransform="matrix(0.423343,0,0,0.423343,76.37397,152.137)"
  91.122 +       x1="175.23776"
  91.123 +       y1="509.98154"
  91.124 +       x2="416.29077"
  91.125 +       y2="297.49997" />
  91.126 +    <linearGradient
  91.127 +       inkscape:collect="always"
  91.128 +       xlink:href="#linearGradient3092"
  91.129 +       id="linearGradient5786"
  91.130 +       gradientUnits="userSpaceOnUse"
  91.131 +       gradientTransform="matrix(0.423343,0,0,0.423343,198.249,152.137)"
  91.132 +       x1="175.23776"
  91.133 +       y1="509.98154"
  91.134 +       x2="416.29077"
  91.135 +       y2="297.49997" />
  91.136 +    <linearGradient
  91.137 +       inkscape:collect="always"
  91.138 +       xlink:href="#linearGradient3092"
  91.139 +       id="linearGradient5895"
  91.140 +       gradientUnits="userSpaceOnUse"
  91.141 +       gradientTransform="matrix(0.423343,0,0,0.423343,198.0215,261.7142)"
  91.142 +       x1="175.23776"
  91.143 +       y1="509.98154"
  91.144 +       x2="416.29077"
  91.145 +       y2="297.49997" />
  91.146 +    <linearGradient
  91.147 +       inkscape:collect="always"
  91.148 +       xlink:href="#linearGradient3092"
  91.149 +       id="linearGradient5958"
  91.150 +       gradientUnits="userSpaceOnUse"
  91.151 +       gradientTransform="matrix(0.423343,0,0,0.423343,137.1978,42.55987)"
  91.152 +       x1="175.23776"
  91.153 +       y1="509.98154"
  91.154 +       x2="416.29077"
  91.155 +       y2="297.49997" />
  91.156 +  </defs>
  91.157 +  <sodipodi:namedview
  91.158 +     id="base"
  91.159 +     pagecolor="#ffffff"
  91.160 +     bordercolor="#666666"
  91.161 +     borderopacity="1.0"
  91.162 +     gridtolerance="10000"
  91.163 +     guidetolerance="10"
  91.164 +     objecttolerance="10"
  91.165 +     inkscape:pageopacity="0.0"
  91.166 +     inkscape:pageshadow="2"
  91.167 +     inkscape:zoom="0.64"
  91.168 +     inkscape:cx="566.02368"
  91.169 +     inkscape:cy="688.16826"
  91.170 +     inkscape:document-units="px"
  91.171 +     inkscape:current-layer="layer1"
  91.172 +     inkscape:window-width="906"
  91.173 +     inkscape:window-height="620"
  91.174 +     inkscape:window-x="29"
  91.175 +     inkscape:window-y="79"
  91.176 +     inkscape:connector-spacing="11" />
  91.177 +  <metadata
  91.178 +     id="metadata7">
  91.179 +    <rdf:RDF>
  91.180 +      <cc:Work
  91.181 +         rdf:about="">
  91.182 +        <dc:format>image/svg+xml</dc:format>
  91.183 +        <dc:type
  91.184 +           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
  91.185 +      </cc:Work>
  91.186 +    </rdf:RDF>
  91.187 +  </metadata>
  91.188 +  <g
  91.189 +     inkscape:label="Layer 1"
  91.190 +     inkscape:groupmode="layer"
  91.191 +     id="layer1">
  91.192 +    <rect
  91.193 +       y="168.74846"
  91.194 +       x="211.58516"
  91.195 +       height="89.506805"
  91.196 +       width="101.60232"
  91.197 +       id="rect3068"
  91.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" />
  91.199 +    <g
  91.200 +       id="g3215"
  91.201 +       transform="matrix(0.423343,0,0,0.423343,137.1977,42.55985)">
  91.202 +      <rect
  91.203 +         y="447.71451"
  91.204 +         x="299.67859"
  91.205 +         height="48.571426"
  91.206 +         width="103.14286"
  91.207 +         id="rect2899"
  91.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" />
  91.209 +      <text
  91.210 +         id="text2903"
  91.211 +         y="464.8139"
  91.212 +         x="308.89639"
  91.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"
  91.214 +         xml:space="preserve"><tspan
  91.215 +           y="464.8139"
  91.216 +           x="308.89639"
  91.217 +           sodipodi:role="line"
  91.218 +           id="tspan2905">Second parent</tspan></text>
  91.219 +      <text
  91.220 +         id="text2907"
  91.221 +         y="485.50256"
  91.222 +         x="308.20175"
  91.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"
  91.224 +         xml:space="preserve"><tspan
  91.225 +           style="font-family:Courier"
  91.226 +           y="485.50256"
  91.227 +           x="308.20175"
  91.228 +           id="tspan2909"
  91.229 +           sodipodi:role="line">32bf9a5f22c0</tspan></text>
  91.230 +    </g>
  91.231 +    <g
  91.232 +       id="g3250"
  91.233 +       transform="matrix(0.423343,0,0,0.423343,137.1977,42.55986)">
  91.234 +      <rect
  91.235 +         y="311.28598"
  91.236 +         x="188.6071"
  91.237 +         height="48.571426"
  91.238 +         width="103.14286"
  91.239 +         id="rect2936"
  91.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" />
  91.241 +      <text
  91.242 +         id="text2940"
  91.243 +         y="328.38538"
  91.244 +         x="197.82495"
  91.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"
  91.246 +         xml:space="preserve"><tspan
  91.247 +           y="328.38538"
  91.248 +           x="197.82495"
  91.249 +           sodipodi:role="line"
  91.250 +           id="tspan2942">Revision hash</tspan></text>
  91.251 +      <text
  91.252 +         id="text2944"
  91.253 +         y="349.07404"
  91.254 +         x="197.13031"
  91.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"
  91.256 +         xml:space="preserve"><tspan
  91.257 +           style="font-family:Courier"
  91.258 +           y="349.07404"
  91.259 +           x="197.13031"
  91.260 +           id="tspan2946"
  91.261 +           sodipodi:role="line">34b8b7a15ea1</tspan></text>
  91.262 +    </g>
  91.263 +    <g
  91.264 +       id="g3243"
  91.265 +       transform="matrix(0.423343,0,0,0.423343,137.6664,43.91853)">
  91.266 +      <rect
  91.267 +         y="363.07654"
  91.268 +         x="187.5"
  91.269 +         height="75"
  91.270 +         width="213.85715"
  91.271 +         id="rect2950"
  91.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" />
  91.273 +      <text
  91.274 +         id="text2958"
  91.275 +         y="400.86459"
  91.276 +         x="196.02321"
  91.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"
  91.278 +         xml:space="preserve"><tspan
  91.279 +           style="fill:black;fill-opacity:1;font-family:Courier"
  91.280 +           y="400.86459"
  91.281 +           x="196.02321"
  91.282 +           id="tspan2960"
  91.283 +           sodipodi:role="line">...</tspan></text>
  91.284 +      <text
  91.285 +         id="text2954"
  91.286 +         y="380.17593"
  91.287 +         x="196.71785"
  91.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"
  91.289 +         xml:space="preserve"><tspan
  91.290 +           y="380.17593"
  91.291 +           x="196.71785"
  91.292 +           sodipodi:role="line"
  91.293 +           id="tspan2956"
  91.294 +           style="fill:black;fill-opacity:1">Revision data (delta or snapshot)</tspan></text>
  91.295 +    </g>
  91.296 +    <g
  91.297 +       id="g5529"
  91.298 +       transform="translate(-6.710312,-8.165836e-6)">
  91.299 +      <rect
  91.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"
  91.301 +         id="rect3509"
  91.302 +         width="101.60232"
  91.303 +         height="89.506805"
  91.304 +         x="218.29547"
  91.305 +         y="497.4801" />
  91.306 +      <g
  91.307 +         transform="matrix(0.423343,0,0,0.423343,143.908,371.2915)"
  91.308 +         id="g3513">
  91.309 +        <g
  91.310 +           id="g3515">
  91.311 +          <rect
  91.312 +             y="447.72418"
  91.313 +             x="188.6071"
  91.314 +             height="48.571426"
  91.315 +             width="103.14286"
  91.316 +             id="rect3517"
  91.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" />
  91.318 +          <text
  91.319 +             id="text3519"
  91.320 +             y="464.82358"
  91.321 +             x="197.82495"
  91.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"
  91.323 +             xml:space="preserve"><tspan
  91.324 +               y="464.82358"
  91.325 +               x="197.82495"
  91.326 +               sodipodi:role="line"
  91.327 +               id="tspan3521">First parent</tspan></text>
  91.328 +          <text
  91.329 +             id="text3523"
  91.330 +             y="485.51224"
  91.331 +             x="197.13031"
  91.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"
  91.333 +             xml:space="preserve"><tspan
  91.334 +               style="font-family:Courier"
  91.335 +               y="485.51224"
  91.336 +               x="197.13031"
  91.337 +               id="tspan3525"
  91.338 +               sodipodi:role="line">000000000000</tspan></text>
  91.339 +        </g>
  91.340 +        <g
  91.341 +           id="g3527">
  91.342 +          <rect
  91.343 +             y="447.71451"
  91.344 +             x="299.67859"
  91.345 +             height="48.571426"
  91.346 +             width="103.14286"
  91.347 +             id="rect3529"
  91.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" />
  91.349 +          <text
  91.350 +             id="text3531"
  91.351 +             y="464.8139"
  91.352 +             x="308.89639"
  91.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"
  91.354 +             xml:space="preserve"><tspan
  91.355 +               y="464.8139"
  91.356 +               x="308.89639"
  91.357 +               sodipodi:role="line"
  91.358 +               id="tspan3533">Second parent</tspan></text>
  91.359 +          <text
  91.360 +             id="text3535"
  91.361 +             y="485.50256"
  91.362 +             x="308.20175"
  91.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"
  91.364 +             xml:space="preserve"><tspan
  91.365 +               style="font-family:Courier"
  91.366 +               y="485.50256"
  91.367 +               x="308.20175"
  91.368 +               id="tspan3537"
  91.369 +               sodipodi:role="line">000000000000</tspan></text>
  91.370 +        </g>
  91.371 +      </g>
  91.372 +      <g
  91.373 +         transform="matrix(0.423343,0,0,0.423343,143.908,371.2915)"
  91.374 +         id="g3539">
  91.375 +        <rect
  91.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"
  91.377 +           id="rect3541"
  91.378 +           width="103.14286"
  91.379 +           height="48.571426"
  91.380 +           x="188.6071"
  91.381 +           y="311.28598" />
  91.382 +        <text
  91.383 +           xml:space="preserve"
  91.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"
  91.385 +           x="197.82495"
  91.386 +           y="328.38538"
  91.387 +           id="text3543"><tspan
  91.388 +             id="tspan3545"
  91.389 +             sodipodi:role="line"
  91.390 +             x="197.82495"
  91.391 +             y="328.38538">Revision hash</tspan></text>
  91.392 +        <text
  91.393 +           xml:space="preserve"
  91.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"
  91.395 +           x="197.13031"
  91.396 +           y="349.07404"
  91.397 +           id="text3547"><tspan
  91.398 +             sodipodi:role="line"
  91.399 +             id="tspan3549"
  91.400 +             x="197.13031"
  91.401 +             y="349.07404"
  91.402 +             style="font-family:Courier">ff9dc8bc2a8b</tspan></text>
  91.403 +      </g>
  91.404 +      <g
  91.405 +         transform="matrix(0.423343,0,0,0.423343,144.3767,372.6502)"
  91.406 +         id="g3551">
  91.407 +        <rect
  91.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"
  91.409 +           id="rect3553"
  91.410 +           width="213.85715"
  91.411 +           height="75"
  91.412 +           x="187.5"
  91.413 +           y="363.07654" />
  91.414 +        <text
  91.415 +           xml:space="preserve"
  91.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"
  91.417 +           x="196.02321"
  91.418 +           y="400.86459"
  91.419 +           id="text3555"><tspan
  91.420 +             sodipodi:role="line"
  91.421 +             id="tspan3557"
  91.422 +             x="196.02321"
  91.423 +             y="400.86459"
  91.424 +             style="fill:black;fill-opacity:1;font-family:Courier">...</tspan></text>
  91.425 +        <text
  91.426 +           xml:space="preserve"
  91.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"
  91.428 +           x="196.71785"
  91.429 +           y="380.17593"
  91.430 +           id="text3559"><tspan
  91.431 +             style="fill:black;fill-opacity:1"
  91.432 +             id="tspan3561"
  91.433 +             sodipodi:role="line"
  91.434 +             x="196.71785"
  91.435 +             y="380.17593">Revision data (delta or snapshot)</tspan></text>
  91.436 +      </g>
  91.437 +    </g>
  91.438 +    <g
  91.439 +       id="g4868"
  91.440 +       transform="translate(-1.676208,-2.342463e-5)">
  91.441 +      <rect
  91.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"
  91.443 +         id="rect3567"
  91.444 +         width="101.60232"
  91.445 +         height="89.506805"
  91.446 +         x="213.26137"
  91.447 +         y="59.171272" />
  91.448 +      <g
  91.449 +         transform="matrix(0.423343,0,0,0.423343,138.8739,-67.01734)"
  91.450 +         id="g3573">
  91.451 +        <rect
  91.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"
  91.453 +           id="rect3575"
  91.454 +           width="103.14286"
  91.455 +           height="48.571426"
  91.456 +           x="188.6071"
  91.457 +           y="447.72418" />
  91.458 +        <text
  91.459 +           xml:space="preserve"
  91.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"
  91.461 +           x="197.82495"
  91.462 +           y="464.82358"
  91.463 +           id="text3577"><tspan
  91.464 +             id="tspan3579"
  91.465 +             sodipodi:role="line"
  91.466 +             x="197.82495"
  91.467 +             y="464.82358">First parent</tspan></text>
  91.468 +        <text
  91.469 +           xml:space="preserve"
  91.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"
  91.471 +           x="197.13031"
  91.472 +           y="485.51224"
  91.473 +           id="text3581"><tspan
  91.474 +             sodipodi:role="line"
  91.475 +             id="tspan3583"
  91.476 +             x="197.13031"
  91.477 +             y="485.51224"
  91.478 +             style="font-family:Courier">34b8b7a15ea1</tspan></text>
  91.479 +      </g>
  91.480 +      <g
  91.481 +         transform="matrix(0.423343,0,0,0.423343,138.8739,-67.01734)"
  91.482 +         id="g3585">
  91.483 +        <rect
  91.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"
  91.485 +           id="rect3587"
  91.486 +           width="103.14286"
  91.487 +           height="48.571426"
  91.488 +           x="299.67859"
  91.489 +           y="447.71451" />
  91.490 +        <text
  91.491 +           xml:space="preserve"
  91.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"
  91.493 +           x="308.89639"
  91.494 +           y="464.8139"
  91.495 +           id="text3589"><tspan
  91.496 +             id="tspan3591"
  91.497 +             sodipodi:role="line"
  91.498 +             x="308.89639"
  91.499 +             y="464.8139">Second parent</tspan></text>
  91.500 +        <text
  91.501 +           xml:space="preserve"
  91.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"
  91.503 +           x="308.20175"
  91.504 +           y="485.50256"
  91.505 +           id="text3593"><tspan
  91.506 +             sodipodi:role="line"
  91.507 +             id="tspan3595"
  91.508 +             x="308.20175"
  91.509 +             y="485.50256"
  91.510 +             style="font-family:Courier">000000000000</tspan></text>
  91.511 +      </g>
  91.512 +      <g
  91.513 +         transform="matrix(0.423343,0,0,0.423343,138.8739,-67.01733)"
  91.514 +         id="g3597">
  91.515 +        <rect
  91.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"
  91.517 +           id="rect3599"
  91.518 +           width="103.14286"
  91.519 +           height="48.571426"
  91.520 +           x="188.6071"
  91.521 +           y="311.28598" />
  91.522 +        <text
  91.523 +           xml:space="preserve"
  91.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"
  91.525 +           x="197.82495"
  91.526 +           y="328.38538"
  91.527 +           id="text3601"><tspan
  91.528 +             id="tspan3603"
  91.529 +             sodipodi:role="line"
  91.530 +             x="197.82495"
  91.531 +             y="328.38538">Revision hash</tspan></text>
  91.532 +        <text
  91.533 +           xml:space="preserve"
  91.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"
  91.535 +           x="197.13031"
  91.536 +           y="349.07404"
  91.537 +           id="text3605"><tspan
  91.538 +             sodipodi:role="line"
  91.539 +             id="tspan3607"
  91.540 +             x="197.13031"
  91.541 +             y="349.07404"
  91.542 +             style="font-family:Courier">1b67dc96f27a</tspan></text>
  91.543 +      </g>
  91.544 +      <g
  91.545 +         transform="matrix(0.423343,0,0,0.423343,139.3426,-65.65866)"
  91.546 +         id="g3609">
  91.547 +        <rect
  91.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"
  91.549 +           id="rect3611"
  91.550 +           width="213.85715"
  91.551 +           height="75"
  91.552 +           x="187.5"
  91.553 +           y="363.07654" />
  91.554 +        <text
  91.555 +           xml:space="preserve"
  91.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"
  91.557 +           x="196.02321"
  91.558 +           y="400.86459"
  91.559 +           id="text3613"><tspan
  91.560 +             sodipodi:role="line"
  91.561 +             id="tspan3615"
  91.562 +             x="196.02321"
  91.563 +             y="400.86459"
  91.564 +             style="fill:black;fill-opacity:1;font-family:Courier">...</tspan></text>
  91.565 +        <text
  91.566 +           xml:space="preserve"
  91.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"
  91.568 +           x="196.71785"
  91.569 +           y="380.17593"
  91.570 +           id="text3617"><tspan
  91.571 +             style="fill:black;fill-opacity:1"
  91.572 +             id="tspan3619"
  91.573 +             sodipodi:role="line"
  91.574 +             x="196.71785"
  91.575 +             y="380.17593">Revision data (delta or snapshot)</tspan></text>
  91.576 +      </g>
  91.577 +    </g>
  91.578 +    <path
  91.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)"
  91.580 +       d="M 240.78255,143.08593 L 241.42595,171.75349"
  91.581 +       id="path3801"
  91.582 +       inkscape:connector-type="polyline"
  91.583 +       inkscape:connection-start="#g3573"
  91.584 +       inkscape:connection-end="#g3250" />
  91.585 +    <g
  91.586 +       id="g5677">
  91.587 +      <rect
  91.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"
  91.589 +         id="rect3393"
  91.590 +         width="101.60232"
  91.591 +         height="89.506805"
  91.592 +         x="150.76137"
  91.593 +         y="278.32565" />
  91.594 +      <g
  91.595 +         transform="matrix(0.423343,0,0,0.423343,76.37397,152.137)"
  91.596 +         id="g3399">
  91.597 +        <rect
  91.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"
  91.599 +           id="rect3401"
  91.600 +           width="103.14286"
  91.601 +           height="48.571426"
  91.602 +           x="188.6071"
  91.603 +           y="447.72418" />
  91.604 +        <text
  91.605 +           xml:space="preserve"
  91.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"
  91.607 +           x="197.82495"
  91.608 +           y="464.82358"
  91.609 +           id="text3403"><tspan
  91.610 +             id="tspan3405"
  91.611 +             sodipodi:role="line"
  91.612 +             x="197.82495"
  91.613 +             y="464.82358">First parent</tspan></text>
  91.614 +        <text
  91.615 +           xml:space="preserve"
  91.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"
  91.617 +           x="197.13031"
  91.618 +           y="485.51224"
  91.619 +           id="text3407"><tspan
  91.620 +             sodipodi:role="line"
  91.621 +             id="tspan3409"
  91.622 +             x="197.13031"
  91.623 +             y="485.51224"
  91.624 +             style="font-family:Courier">ff9dc8bc2a8b</tspan></text>
  91.625 +      </g>
  91.626 +      <g
  91.627 +         transform="matrix(0.423343,0,0,0.423343,76.37397,152.137)"
  91.628 +         id="g3411">
  91.629 +        <rect
  91.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"
  91.631 +           id="rect3413"
  91.632 +           width="103.14286"
  91.633 +           height="48.571426"
  91.634 +           x="299.67859"
  91.635 +           y="447.71451" />
  91.636 +        <text
  91.637 +           xml:space="preserve"
  91.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"
  91.639 +           x="308.89639"
  91.640 +           y="464.8139"
  91.641 +           id="text3415"><tspan
  91.642 +             id="tspan3417"
  91.643 +             sodipodi:role="line"
  91.644 +             x="308.89639"
  91.645 +             y="464.8139">Second parent</tspan></text>
  91.646 +        <text
  91.647 +           xml:space="preserve"
  91.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"
  91.649 +           x="308.20175"
  91.650 +           y="485.50256"
  91.651 +           id="text3419"><tspan
  91.652 +             sodipodi:role="line"
  91.653 +             id="tspan3421"
  91.654 +             x="308.20175"
  91.655 +             y="485.50256"
  91.656 +             style="font-family:Courier">000000000000</tspan></text>
  91.657 +      </g>
  91.658 +      <g
  91.659 +         transform="matrix(0.423343,0,0,0.423343,76.37397,152.137)"
  91.660 +         id="g3423">
  91.661 +        <rect
  91.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"
  91.663 +           id="rect3425"
  91.664 +           width="103.14286"
  91.665 +           height="48.571426"
  91.666 +           x="188.6071"
  91.667 +           y="311.28598" />
  91.668 +        <text
  91.669 +           xml:space="preserve"
  91.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"
  91.671 +           x="197.82495"
  91.672 +           y="328.38538"
  91.673 +           id="text3427"><tspan
  91.674 +             id="tspan3429"
  91.675 +             sodipodi:role="line"
  91.676 +             x="197.82495"
  91.677 +             y="328.38538">Revision hash</tspan></text>
  91.678 +        <text
  91.679 +           xml:space="preserve"
  91.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"
  91.681 +           x="197.13031"
  91.682 +           y="349.07404"
  91.683 +           id="text3431"><tspan
  91.684 +             sodipodi:role="line"
  91.685 +             id="tspan3433"
  91.686 +             x="197.13031"
  91.687 +             y="349.07404"
  91.688 +             style="font-family:Courier">5b80c922ebdd</tspan></text>
  91.689 +      </g>
  91.690 +      <g
  91.691 +         transform="matrix(0.423343,0,0,0.423343,76.84265,153.4957)"
  91.692 +         id="g3435">
  91.693 +        <rect
  91.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"
  91.695 +           id="rect3437"
  91.696 +           width="213.85715"
  91.697 +           height="75"
  91.698 +           x="187.5"
  91.699 +           y="363.07654" />
  91.700 +        <text
  91.701 +           xml:space="preserve"
  91.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"
  91.703 +           x="196.02321"
  91.704 +           y="400.86459"
  91.705 +           id="text3439"><tspan
  91.706 +             sodipodi:role="line"
  91.707 +             id="tspan3441"
  91.708 +             x="196.02321"
  91.709 +             y="400.86459"
  91.710 +             style="fill:black;fill-opacity:1;font-family:Courier">...</tspan></text>
  91.711 +        <text
  91.712 +           xml:space="preserve"
  91.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"
  91.714 +           x="196.71785"
  91.715 +           y="380.17593"
  91.716 +           id="text3443"><tspan
  91.717 +             style="fill:black;fill-opacity:1"
  91.718 +             id="tspan3445"
  91.719 +             sodipodi:role="line"
  91.720 +             x="196.71785"
  91.721 +             y="380.17593">Revision data (delta or snapshot)</tspan></text>
  91.722 +      </g>
  91.723 +    </g>
  91.724 +    <g
  91.725 +       id="g5646"
  91.726 +       transform="translate(-0.227432,0)">
  91.727 +      <rect
  91.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"
  91.729 +         id="rect3451"
  91.730 +         width="101.60232"
  91.731 +         height="89.506805"
  91.732 +         x="272.63638"
  91.733 +         y="278.32565" />
  91.734 +      <g
  91.735 +         transform="matrix(0.423343,0,0,0.423343,198.2489,152.137)"
  91.736 +         id="g3457">
  91.737 +        <rect
  91.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"
  91.739 +           id="rect3459"
  91.740 +           width="103.14286"
  91.741 +           height="48.571426"
  91.742 +           x="188.6071"
  91.743 +           y="447.72418" />
  91.744 +        <text
  91.745 +           xml:space="preserve"
  91.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"
  91.747 +           x="197.82495"
  91.748 +           y="464.82358"
  91.749 +           id="text3461"><tspan
  91.750 +             id="tspan3463"
  91.751 +             sodipodi:role="line"
  91.752 +             x="197.82495"
  91.753 +             y="464.82358">First parent</tspan></text>
  91.754 +        <text
  91.755 +           xml:space="preserve"
  91.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"
  91.757 +           x="197.13031"
  91.758 +           y="485.51224"
  91.759 +           id="text3465"><tspan
  91.760 +             sodipodi:role="line"
  91.761 +             id="tspan3467"
  91.762 +             x="197.13031"
  91.763 +             y="485.51224"
  91.764 +             style="font-family:Courier">ecacb6b4c9fd</tspan></text>
  91.765 +      </g>
  91.766 +      <g
  91.767 +         transform="matrix(0.423343,0,0,0.423343,198.2489,152.137)"
  91.768 +         id="g3469">
  91.769 +        <rect
  91.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"
  91.771 +           id="rect3471"
  91.772 +           width="103.14286"
  91.773 +           height="48.571426"
  91.774 +           x="299.67859"
  91.775 +           y="447.71451" />
  91.776 +        <text
  91.777 +           xml:space="preserve"
  91.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"
  91.779 +           x="308.89639"
  91.780 +           y="464.8139"
  91.781 +           id="text3473"><tspan
  91.782 +             id="tspan3475"
  91.783 +             sodipodi:role="line"
  91.784 +             x="308.89639"
  91.785 +             y="464.8139">Second parent</tspan></text>
  91.786 +        <text
  91.787 +           xml:space="preserve"
  91.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"
  91.789 +           x="308.20175"
  91.790 +           y="485.50256"
  91.791 +           id="text3477"><tspan
  91.792 +             sodipodi:role="line"
  91.793 +             id="tspan3479"
  91.794 +             x="308.20175"
  91.795 +             y="485.50256"
  91.796 +             style="font-family:Courier">000000000000</tspan></text>
  91.797 +      </g>
  91.798 +      <g
  91.799 +         transform="matrix(0.423343,0,0,0.423343,198.2489,152.137)"
  91.800 +         id="g3481">
  91.801 +        <rect
  91.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"
  91.803 +           id="rect3483"
  91.804 +           width="103.14286"
  91.805 +           height="48.571426"
  91.806 +           x="188.6071"
  91.807 +           y="311.28598" />
  91.808 +        <text
  91.809 +           xml:space="preserve"
  91.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"
  91.811 +           x="197.82495"
  91.812 +           y="328.38538"
  91.813 +           id="text3485"><tspan
  91.814 +             id="tspan3487"
  91.815 +             sodipodi:role="line"
  91.816 +             x="197.82495"
  91.817 +             y="328.38538">Revision hash</tspan></text>
  91.818 +        <text
  91.819 +           xml:space="preserve"
  91.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"
  91.821 +           x="197.13031"
  91.822 +           y="349.07404"
  91.823 +           id="text3489"><tspan
  91.824 +             sodipodi:role="line"
  91.825 +             id="tspan3491"
  91.826 +             x="197.13031"
  91.827 +             y="349.07404"
  91.828 +             style="font-family:Courier">32bf9a5f22c0</tspan></text>
  91.829 +      </g>
  91.830 +      <g
  91.831 +         transform="matrix(0.423343,0,0,0.423343,198.7176,153.4957)"
  91.832 +         id="g3493">
  91.833 +        <rect
  91.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"
  91.835 +           id="rect3495"
  91.836 +           width="213.85715"
  91.837 +           height="75"
  91.838 +           x="187.5"
  91.839 +           y="363.07654" />
  91.840 +        <text
  91.841 +           xml:space="preserve"
  91.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"
  91.843 +           x="196.02321"
  91.844 +           y="400.86459"
  91.845 +           id="text3497"><tspan
  91.846 +             sodipodi:role="line"
  91.847 +             id="tspan3499"
  91.848 +             x="196.02321"
  91.849 +             y="400.86459"
  91.850 +             style="fill:black;fill-opacity:1;font-family:Courier">...</tspan></text>
  91.851 +        <text
  91.852 +           xml:space="preserve"
  91.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"
  91.854 +           x="196.71785"
  91.855 +           y="380.17593"
  91.856 +           id="text3501"><tspan
  91.857 +             style="fill:black;fill-opacity:1"
  91.858 +             id="tspan3503"
  91.859 +             sodipodi:role="line"
  91.860 +             x="196.71785"
  91.861 +             y="380.17593">Revision data (delta or snapshot)</tspan></text>
  91.862 +      </g>
  91.863 +    </g>
  91.864 +    <rect
  91.865 +       y="387.90286"
  91.866 +       x="272.40894"
  91.867 +       height="89.506805"
  91.868 +       width="101.60232"
  91.869 +       id="rect5081"
  91.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" />
  91.871 +    <g
  91.872 +       id="g5087"
  91.873 +       transform="matrix(0.423343,0,0,0.423343,198.0214,261.7142)">
  91.874 +      <rect
  91.875 +         y="447.72418"
  91.876 +         x="188.6071"
  91.877 +         height="48.571426"
  91.878 +         width="103.14286"
  91.879 +         id="rect5089"
  91.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" />
  91.881 +      <text
  91.882 +         id="text5091"
  91.883 +         y="464.82358"
  91.884 +         x="197.82495"
  91.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"
  91.886 +         xml:space="preserve"><tspan
  91.887 +           y="464.82358"
  91.888 +           x="197.82495"
  91.889 +           sodipodi:role="line"
  91.890 +           id="tspan5093">First parent</tspan></text>
  91.891 +      <text
  91.892 +         id="text5095"
  91.893 +         y="485.51224"
  91.894 +         x="197.13031"
  91.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"
  91.896 +         xml:space="preserve"><tspan
  91.897 +           style="font-family:Courier"
  91.898 +           y="485.51224"
  91.899 +           x="197.13031"
  91.900 +           id="tspan5097"
  91.901 +           sodipodi:role="line">ff9dc8bc2a8b</tspan></text>
  91.902 +    </g>
  91.903 +    <g
  91.904 +       id="g5099"
  91.905 +       transform="matrix(0.423343,0,0,0.423343,198.0214,261.7142)">
  91.906 +      <rect
  91.907 +         y="447.71451"
  91.908 +         x="299.67859"
  91.909 +         height="48.571426"
  91.910 +         width="103.14286"
  91.911 +         id="rect5101"
  91.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" />
  91.913 +      <text
  91.914 +         id="text5103"
  91.915 +         y="464.8139"
  91.916 +         x="308.89639"
  91.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"
  91.918 +         xml:space="preserve"><tspan
  91.919 +           y="464.8139"
  91.920 +           x="308.89639"
  91.921 +           sodipodi:role="line"
  91.922 +           id="tspan5105">Second parent</tspan></text>
  91.923 +      <text
  91.924 +         id="text5107"
  91.925 +         y="485.50256"
  91.926 +         x="308.20175"
  91.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"
  91.928 +         xml:space="preserve"><tspan
  91.929 +           style="font-family:Courier"
  91.930 +           y="485.50256"
  91.931 +           x="308.20175"
  91.932 +           id="tspan5109"
  91.933 +           sodipodi:role="line">000000000000</tspan></text>
  91.934 +    </g>
  91.935 +    <g
  91.936 +       id="g5111"
  91.937 +       transform="matrix(0.423343,0,0,0.423343,198.0214,261.7142)">
  91.938 +      <rect
  91.939 +         y="311.28598"
  91.940 +         x="188.6071"
  91.941 +         height="48.571426"
  91.942 +         width="103.14286"
  91.943 +         id="rect5113"
  91.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" />
  91.945 +      <text
  91.946 +         id="text5115"
  91.947 +         y="328.38538"
  91.948 +         x="197.82495"
  91.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"
  91.950 +         xml:space="preserve"><tspan
  91.951 +           y="328.38538"
  91.952 +           x="197.82495"
  91.953 +           sodipodi:role="line"
  91.954 +           id="tspan5117">Revision hash</tspan></text>
  91.955 +      <text
  91.956 +         id="text5119"
  91.957 +         y="349.07404"
  91.958 +         x="197.13031"
  91.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"
  91.960 +         xml:space="preserve"><tspan
  91.961 +           style="font-family:Courier"
  91.962 +           y="349.07404"
  91.963 +           x="197.13031"
  91.964 +           id="tspan5121"
  91.965 +           sodipodi:role="line">ecacb6b4c9fd</tspan></text>
  91.966 +    </g>
  91.967 +    <g
  91.968 +       id="g5123"
  91.969 +       transform="matrix(0.423343,0,0,0.423343,198.4901,263.0729)">
  91.970 +      <rect
  91.971 +         y="363.07654"
  91.972 +         x="187.5"
  91.973 +         height="75"
  91.974 +         width="213.85715"
  91.975 +         id="rect5125"
  91.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" />
  91.977 +      <text
  91.978 +         id="text5127"
  91.979 +         y="400.86459"
  91.980 +         x="196.02321"
  91.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"
  91.982 +         xml:space="preserve"><tspan
  91.983 +           style="fill:black;fill-opacity:1;font-family:Courier"
  91.984 +           y="400.86459"
  91.985 +           x="196.02321"
  91.986 +           id="tspan5129"
  91.987 +           sodipodi:role="line">...</tspan></text>
  91.988 +      <text
  91.989 +         id="text5131"
  91.990 +         y="380.17593"
  91.991 +         x="196.71785"
  91.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"
  91.993 +         xml:space="preserve"><tspan
  91.994 +           y="380.17593"
  91.995 +           x="196.71785"
  91.996 +           sodipodi:role="line"
  91.997 +           id="tspan5133"
  91.998 +           style="fill:black;fill-opacity:1">Revision data (delta or snapshot)</tspan></text>
  91.999 +    </g>
 91.1000 +    <path
 91.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"
 91.1002 +       d="M 299.69935,362.24027 L 299.69931,393.49494"
 91.1003 +       id="path5203"
 91.1004 +       inkscape:connector-type="polyline"
 91.1005 +       inkscape:connection-start="#g3457"
 91.1006 +       inkscape:connection-end="#g5111" />
 91.1007 +    <path
 91.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"
 91.1009 +       d="M 182.35357,362.22647 L 241.2842,503.07224"
 91.1010 +       id="path5271"
 91.1011 +       inkscape:connector-type="polyline"
 91.1012 +       inkscape:connection-start="#g3399"
 91.1013 +       inkscape:connection-end="#g3539" />
 91.1014 +    <path
 91.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"
 91.1016 +       d="M 287.63109,471.81747 L 250.9438,503.07223"
 91.1017 +       id="path5285"
 91.1018 +       inkscape:connector-type="polyline"
 91.1019 +       inkscape:connection-start="#g5087"
 91.1020 +       inkscape:connection-end="#g3539" />
 91.1021 +    <path
 91.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)"
 91.1023 +       d="M 290.80419,250.07192 L 297.80065,283.90394"
 91.1024 +       id="path5077"
 91.1025 +       inkscape:connector-type="polyline"
 91.1026 +       inkscape:connection-start="#g3215"
 91.1027 +       inkscape:connection-end="#g3481" />
 91.1028 +    <path
 91.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)"
 91.1030 +       d="M 229.63373,250.07601 L 190.07484,283.90394"
 91.1031 +       id="path5075"
 91.1032 +       inkscape:connector-type="polyline"
 91.1033 +       inkscape:connection-end="#g3423" />
 91.1034 +    <text
 91.1035 +       xml:space="preserve"
 91.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"
 91.1037 +       x="131.5625"
 91.1038 +       y="100.79968"
 91.1039 +       id="text5897"><tspan
 91.1040 +         sodipodi:role="line"
 91.1041 +         id="tspan5899"
 91.1042 +         x="131.5625"
 91.1043 +         y="100.79968"
 91.1044 +         style="text-align:end;text-anchor:end">Head revision</tspan><tspan
 91.1045 +         sodipodi:role="line"
 91.1046 +         x="131.5625"
 91.1047 +         y="115.79968"
 91.1048 +         id="tspan5901"
 91.1049 +         style="text-align:end;text-anchor:end">(no children)</tspan></text>
 91.1050 +    <text
 91.1051 +       xml:space="preserve"
 91.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"
 91.1053 +       x="131.5625"
 91.1054 +       y="207.04968"
 91.1055 +       id="text5903"><tspan
 91.1056 +         sodipodi:role="line"
 91.1057 +         id="tspan5905"
 91.1058 +         x="131.5625"
 91.1059 +         y="207.04968"
 91.1060 +         style="text-align:end;text-anchor:end">Merge revision</tspan><tspan
 91.1061 +         sodipodi:role="line"
 91.1062 +         x="131.5625"
 91.1063 +         y="222.04968"
 91.1064 +         id="tspan5907"
 91.1065 +         style="text-align:end;text-anchor:end">(two parents)</tspan></text>
 91.1066 +    <text
 91.1067 +       xml:space="preserve"
 91.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"
 91.1069 +       x="131.92578"
 91.1070 +       y="451.58093"
 91.1071 +       id="text5909"><tspan
 91.1072 +         sodipodi:role="line"
 91.1073 +         id="tspan5911"
 91.1074 +         x="131.92578"
 91.1075 +         y="451.58093"
 91.1076 +         style="text-align:end;text-anchor:end">Branches</tspan><tspan
 91.1077 +         sodipodi:role="line"
 91.1078 +         x="131.92578"
 91.1079 +         y="466.58093"
 91.1080 +         id="tspan5913"
 91.1081 +         style="text-align:end;text-anchor:end">(two revisions,</tspan><tspan
 91.1082 +         sodipodi:role="line"
 91.1083 +         x="131.92578"
 91.1084 +         y="481.58093"
 91.1085 +         id="tspan5915"
 91.1086 +         style="text-align:end;text-anchor:end">same parent)</tspan></text>
 91.1087 +    <path
 91.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"
 91.1089 +       d="M 111.71875,433.61218 L 154.7268,368.52294"
 91.1090 +       id="path5917"
 91.1091 +       inkscape:connector-type="polyline" />
 91.1092 +    <path
 91.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"
 91.1094 +       d="M 134.375,464.86218 L 277.86691,440.37816"
 91.1095 +       id="path5919"
 91.1096 +       inkscape:connector-type="polyline"
 91.1097 +       inkscape:connection-end="#g5123" />
 91.1098 +    <text
 91.1099 +       xml:space="preserve"
 91.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"
 91.1101 +       x="131.5625"
 91.1102 +       y="536.73718"
 91.1103 +       id="text5927"><tspan
 91.1104 +         sodipodi:role="line"
 91.1105 +         id="tspan5929"
 91.1106 +         x="131.5625"
 91.1107 +         y="536.73718">First revision</tspan><tspan
 91.1108 +         sodipodi:role="line"
 91.1109 +         x="131.5625"
 91.1110 +         y="551.73718"
 91.1111 +         id="tspan5931">(both parents null)</tspan></text>
 91.1112 +    <rect
 91.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"
 91.1114 +       id="rect2830"
 91.1115 +       width="43.664806"
 91.1116 +       height="20.562374"
 91.1117 +       x="217.0432"
 91.1118 +       y="232.10075" />
 91.1119 +    <text
 91.1120 +       xml:space="preserve"
 91.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"
 91.1122 +       x="220.94551"
 91.1123 +       y="239.33966"
 91.1124 +       id="text2832"><tspan
 91.1125 +         id="tspan2836"
 91.1126 +         sodipodi:role="line"
 91.1127 +         x="220.94551"
 91.1128 +         y="239.33966">First parent</tspan></text>
 91.1129 +    <text
 91.1130 +       xml:space="preserve"
 91.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"
 91.1132 +       x="220.65144"
 91.1133 +       y="248.09805"
 91.1134 +       id="text2879"><tspan
 91.1135 +         sodipodi:role="line"
 91.1136 +         id="tspan2881"
 91.1137 +         x="220.65144"
 91.1138 +         y="248.09805"
 91.1139 +         style="font-family:Courier">5b80c922ebdd</tspan></text>
 91.1140 +    <path
 91.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"
 91.1142 +       d="M 139.84375,107.83093 L 210.15625,107.83093"
 91.1143 +       id="path5965"
 91.1144 +       inkscape:connector-type="polyline" />
 91.1145 +    <path
 91.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"
 91.1147 +       d="M 137.5,213.29968 L 210.49036,214.09055"
 91.1148 +       id="path5967"
 91.1149 +       inkscape:connector-type="polyline" />
 91.1150 +    <path
 91.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"
 91.1152 +       d="M 136.34375,544.54968 L 206.65625,544.54968"
 91.1153 +       id="path5969"
 91.1154 +       inkscape:connector-type="polyline"
 91.1155 +       inkscape:transform-center-y="-171.09375"
 91.1156 +       inkscape:transform-center-x="53.90625" />
 91.1157 +  </g>
 91.1158 +</svg>
    92.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    92.2 +++ b/fr/figs/snapshot.svg	Sat Jul 10 06:24:49 2010 +0100
    92.3 @@ -0,0 +1,202 @@
    92.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
    92.5 +<!-- Created with Inkscape (http://www.inkscape.org/) -->
    92.6 +<svg
    92.7 +   xmlns:dc="http://purl.org/dc/elements/1.1/"
    92.8 +   xmlns:cc="http://web.resource.org/cc/"
    92.9 +   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   92.10 +   xmlns:svg="http://www.w3.org/2000/svg"
   92.11 +   xmlns="http://www.w3.org/2000/svg"
   92.12 +   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   92.13 +   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   92.14 +   width="744.09448819"
   92.15 +   height="1052.3622047"
   92.16 +   id="svg2807"
   92.17 +   sodipodi:version="0.32"
   92.18 +   inkscape:version="0.44.1"
   92.19 +   sodipodi:docbase="/home/bos/hg/hgbook/en"
   92.20 +   sodipodi:docname="snapshots.svg">
   92.21 +  <defs
   92.22 +     id="defs2809" />
   92.23 +  <sodipodi:namedview
   92.24 +     id="base"
   92.25 +     pagecolor="#ffffff"
   92.26 +     bordercolor="#666666"
   92.27 +     borderopacity="1.0"
   92.28 +     gridtolerance="10000"
   92.29 +     guidetolerance="10"
   92.30 +     objecttolerance="10"
   92.31 +     inkscape:pageopacity="0.0"
   92.32 +     inkscape:pageshadow="2"
   92.33 +     inkscape:zoom="1.4"
   92.34 +     inkscape:cx="252.04111"
   92.35 +     inkscape:cy="605.75448"
   92.36 +     inkscape:document-units="px"
   92.37 +     inkscape:current-layer="layer1"
   92.38 +     inkscape:window-width="906"
   92.39 +     inkscape:window-height="721"
   92.40 +     inkscape:window-x="0"
   92.41 +     inkscape:window-y="25" />
   92.42 +  <metadata
   92.43 +     id="metadata2812">
   92.44 +    <rdf:RDF>
   92.45 +      <cc:Work
   92.46 +         rdf:about="">
   92.47 +        <dc:format>image/svg+xml</dc:format>
   92.48 +        <dc:type
   92.49 +           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
   92.50 +      </cc:Work>
   92.51 +    </rdf:RDF>
   92.52 +  </metadata>
   92.53 +  <g
   92.54 +     inkscape:label="Layer 1"
   92.55 +     inkscape:groupmode="layer"
   92.56 +     id="layer1">
   92.57 +    <rect
   92.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"
   92.59 +       id="rect2817"
   92.60 +       width="118.18347"
   92.61 +       height="245.32632"
   92.62 +       x="243.05112"
   92.63 +       y="315.4133"
   92.64 +       inkscape:transform-center-x="136.84403"
   92.65 +       inkscape:transform-center-y="-66.529183" />
   92.66 +    <rect
   92.67 +       y="315.04153"
   92.68 +       x="46.965065"
   92.69 +       height="97.803009"
   92.70 +       width="108.92702"
   92.71 +       id="rect2815"
   92.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" />
   92.73 +    <g
   92.74 +       id="g3814">
   92.75 +      <rect
   92.76 +         y="348.94302"
   92.77 +         x="59.285713"
   92.78 +         height="30"
   92.79 +         width="84.285713"
   92.80 +         id="rect2819"
   92.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"
   92.82 +         ry="0" />
   92.83 +      <text
   92.84 +         id="text2821"
   92.85 +         y="368.02701"
   92.86 +         x="72.717636"
   92.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"
   92.88 +         xml:space="preserve"><tspan
   92.89 +           y="368.02701"
   92.90 +           x="72.717636"
   92.91 +           id="tspan2823"
   92.92 +           sodipodi:role="line">Index, rev 7</tspan></text>
   92.93 +    </g>
   92.94 +    <text
   92.95 +       id="text3722"
   92.96 +       y="301.29074"
   92.97 +       x="46.187778"
   92.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"
   92.99 +       xml:space="preserve"><tspan
  92.100 +         y="301.29074"
  92.101 +         x="46.187778"
  92.102 +         id="tspan3724"
  92.103 +         sodipodi:role="line">Revlog index (.i file)</tspan></text>
  92.104 +    <text
  92.105 +       id="text3726"
  92.106 +       y="301.29074"
  92.107 +       x="241.90207"
  92.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"
  92.109 +       xml:space="preserve"><tspan
  92.110 +         y="301.29074"
  92.111 +         x="241.90207"
  92.112 +         id="tspan3728"
  92.113 +         sodipodi:role="line">Revlog data (.d file)</tspan></text>
  92.114 +    <path
  92.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"
  92.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 "
  92.117 +       id="path3839"
  92.118 +       sodipodi:nodetypes="ccccc" />
  92.119 +    <rect
  92.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"
  92.121 +       id="rect3752"
  92.122 +       width="92.720184"
  92.123 +       height="67.005905"
  92.124 +       x="255.42564"
  92.125 +       y="368.64264" />
  92.126 +    <text
  92.127 +       xml:space="preserve"
  92.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"
  92.129 +       x="264.45859"
  92.130 +       y="387.30099"
  92.131 +       id="text3754"><tspan
  92.132 +         sodipodi:role="line"
  92.133 +         id="tspan3756"
  92.134 +         x="264.45859"
  92.135 +         y="387.30099">Snapshot, rev 4</tspan></text>
  92.136 +    <rect
  92.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"
  92.138 +       id="rect3761"
  92.139 +       width="93.49366"
  92.140 +       height="29.922237"
  92.141 +       x="255.03891"
  92.142 +       y="442.04395" />
  92.143 +    <text
  92.144 +       xml:space="preserve"
  92.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"
  92.146 +       x="263.2662"
  92.147 +       y="460.17206"
  92.148 +       id="text3763"><tspan
  92.149 +         sodipodi:role="line"
  92.150 +         id="tspan3765"
  92.151 +         x="263.2662"
  92.152 +         y="460.17206">Delta, rev 4 to 5</tspan></text>
  92.153 +    <rect
  92.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"
  92.155 +       id="rect3774"
  92.156 +       width="93.49366"
  92.157 +       height="29.922237"
  92.158 +       x="255.03891"
  92.159 +       y="477.97485" />
  92.160 +    <text
  92.161 +       xml:space="preserve"
  92.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"
  92.163 +       x="263.2662"
  92.164 +       y="496.10297"
  92.165 +       id="text3776"><tspan
  92.166 +         sodipodi:role="line"
  92.167 +         id="tspan3778"
  92.168 +         x="263.2662"
  92.169 +         y="496.10297">Delta, rev 5 to 6</tspan></text>
  92.170 +    <rect
  92.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"
  92.172 +       id="rect3782"
  92.173 +       width="93.49366"
  92.174 +       height="29.922237"
  92.175 +       x="255.03891"
  92.176 +       y="513.90576" />
  92.177 +    <text
  92.178 +       xml:space="preserve"
  92.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"
  92.180 +       x="263.2662"
  92.181 +       y="532.03387"
  92.182 +       id="text3784"><tspan
  92.183 +         sodipodi:role="line"
  92.184 +         id="tspan3786"
  92.185 +         x="263.2662"
  92.186 +         y="532.03387">Delta, rev 6 to 7</tspan></text>
  92.187 +    <rect
  92.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"
  92.189 +       id="rect3889"
  92.190 +       width="93.49366"
  92.191 +       height="29.922237"
  92.192 +       x="255.03891"
  92.193 +       y="332.32489" />
  92.194 +    <text
  92.195 +       xml:space="preserve"
  92.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"
  92.197 +       x="263.2662"
  92.198 +       y="350.453"
  92.199 +       id="text3891"><tspan
  92.200 +         sodipodi:role="line"
  92.201 +         id="tspan3893"
  92.202 +         x="263.2662"
  92.203 +         y="350.453">Delta, rev 2 to 3</tspan></text>
  92.204 +  </g>
  92.205 +</svg>
    93.1 Binary file fr/figs/throbber.gif has changed
    94.1 Binary file fr/figs/tip.png has changed
    95.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    95.2 +++ b/fr/figs/tour-history.svg	Sat Jul 10 06:24:49 2010 +0100
    95.3 @@ -0,0 +1,289 @@
    95.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
    95.5 +<!-- Created with Inkscape (http://www.inkscape.org/) -->
    95.6 +<svg
    95.7 +   xmlns:dc="http://purl.org/dc/elements/1.1/"
    95.8 +   xmlns:cc="http://web.resource.org/cc/"
    95.9 +   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   95.10 +   xmlns:svg="http://www.w3.org/2000/svg"
   95.11 +   xmlns="http://www.w3.org/2000/svg"
   95.12 +   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   95.13 +   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   95.14 +   width="744.09448819"
   95.15 +   height="1052.3622047"
   95.16 +   id="svg2"
   95.17 +   sodipodi:version="0.32"
   95.18 +   inkscape:version="0.44.1"
   95.19 +   sodipodi:docname="tour-history.svg">
   95.20 +  <defs
   95.21 +     id="defs4">
   95.22 +    <marker
   95.23 +       inkscape:stockid="Arrow1Mstart"
   95.24 +       orient="auto"
   95.25 +       refY="0.0"
   95.26 +       refX="0.0"
   95.27 +       id="Arrow1Mstart"
   95.28 +       style="overflow:visible">
   95.29 +      <path
   95.30 +         id="path2973"
   95.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 "
   95.32 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
   95.33 +         transform="scale(0.4) translate(10,0)" />
   95.34 +    </marker>
   95.35 +    <marker
   95.36 +       inkscape:stockid="Arrow1Mend"
   95.37 +       orient="auto"
   95.38 +       refY="0.0"
   95.39 +       refX="0.0"
   95.40 +       id="Arrow1Mend"
   95.41 +       style="overflow:visible;">
   95.42 +      <path
   95.43 +         id="path3066"
   95.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 "
   95.45 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
   95.46 +         transform="scale(0.4) rotate(180) translate(10,0)" />
   95.47 +    </marker>
   95.48 +  </defs>
   95.49 +  <sodipodi:namedview
   95.50 +     id="base"
   95.51 +     pagecolor="#ffffff"
   95.52 +     bordercolor="#666666"
   95.53 +     borderopacity="1.0"
   95.54 +     gridtolerance="10000"
   95.55 +     guidetolerance="10"
   95.56 +     objecttolerance="10"
   95.57 +     inkscape:pageopacity="0.0"
   95.58 +     inkscape:pageshadow="2"
   95.59 +     inkscape:zoom="1.4"
   95.60 +     inkscape:cx="232.14286"
   95.61 +     inkscape:cy="672.75296"
   95.62 +     inkscape:document-units="px"
   95.63 +     inkscape:current-layer="layer1"
   95.64 +     inkscape:window-width="906"
   95.65 +     inkscape:window-height="620"
   95.66 +     inkscape:window-x="5"
   95.67 +     inkscape:window-y="49" />
   95.68 +  <metadata
   95.69 +     id="metadata7">
   95.70 +    <rdf:RDF>
   95.71 +      <cc:Work
   95.72 +         rdf:about="">
   95.73 +        <dc:format>image/svg+xml</dc:format>
   95.74 +        <dc:type
   95.75 +           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
   95.76 +      </cc:Work>
   95.77 +    </rdf:RDF>
   95.78 +  </metadata>
   95.79 +  <g
   95.80 +     inkscape:label="Layer 1"
   95.81 +     inkscape:groupmode="layer"
   95.82 +     id="layer1">
   95.83 +    <rect
   95.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"
   95.85 +       id="rect1878"
   95.86 +       width="94.285713"
   95.87 +       height="20.714285"
   95.88 +       x="138"
   95.89 +       y="479.50504" />
   95.90 +    <text
   95.91 +       xml:space="preserve"
   95.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"
   95.93 +       x="162.09892"
   95.94 +       y="493.12619"
   95.95 +       id="text1872"><tspan
   95.96 +         sodipodi:role="line"
   95.97 +         id="tspan1874"
   95.98 +         x="162.09892"
   95.99 +         y="493.12619"
  95.100 +         style="font-family:Courier"><tspan
  95.101 +   style="font-weight:bold"
  95.102 +   id="tspan1876">0</tspan>: REV0</tspan></text>
  95.103 +    <rect
  95.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"
  95.105 +       id="rect2800"
  95.106 +       width="94.285713"
  95.107 +       height="20.714285"
  95.108 +       x="138"
  95.109 +       y="432.63004" />
  95.110 +    <text
  95.111 +       xml:space="preserve"
  95.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"
  95.113 +       x="162.09892"
  95.114 +       y="446.25119"
  95.115 +       id="text2794"><tspan
  95.116 +         sodipodi:role="line"
  95.117 +         id="tspan2796"
  95.118 +         x="162.09892"
  95.119 +         y="446.25119"
  95.120 +         style="font-family:Courier"><tspan
  95.121 +   id="tspan2868"
  95.122 +   style="font-weight:bold">1</tspan>: REV1</tspan></text>
  95.123 +    <rect
  95.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"
  95.125 +       id="rect2810"
  95.126 +       width="94.285713"
  95.127 +       height="20.714285"
  95.128 +       x="138"
  95.129 +       y="385.75504" />
  95.130 +    <text
  95.131 +       xml:space="preserve"
  95.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"
  95.133 +       x="162.09892"
  95.134 +       y="399.37619"
  95.135 +       id="text2804"><tspan
  95.136 +         sodipodi:role="line"
  95.137 +         id="tspan2806"
  95.138 +         x="162.09892"
  95.139 +         y="399.37619"
  95.140 +         style="font-family:Courier"><tspan
  95.141 +   style="font-weight:bold"
  95.142 +   id="tspan2866">2</tspan>: REV2</tspan></text>
  95.143 +    <rect
  95.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"
  95.145 +       id="rect2820"
  95.146 +       width="94.285713"
  95.147 +       height="20.714285"
  95.148 +       x="138"
  95.149 +       y="338.88007" />
  95.150 +    <text
  95.151 +       xml:space="preserve"
  95.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"
  95.153 +       x="162.09892"
  95.154 +       y="352.50122"
  95.155 +       id="text2814"><tspan
  95.156 +         sodipodi:role="line"
  95.157 +         id="tspan2816"
  95.158 +         x="162.09892"
  95.159 +         y="352.50122"
  95.160 +         style="font-family:Courier"><tspan
  95.161 +   style="font-weight:bold"
  95.162 +   id="tspan2864">3</tspan>: REV3</tspan></text>
  95.163 +    <rect
  95.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"
  95.165 +       id="rect2830"
  95.166 +       width="94.285713"
  95.167 +       height="20.714285"
  95.168 +       x="138"
  95.169 +       y="292.00504" />
  95.170 +    <text
  95.171 +       xml:space="preserve"
  95.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"
  95.173 +       x="162.09892"
  95.174 +       y="305.62619"
  95.175 +       id="text2824"><tspan
  95.176 +         sodipodi:role="line"
  95.177 +         id="tspan2826"
  95.178 +         x="162.09892"
  95.179 +         y="305.62619"
  95.180 +         style="font-family:Courier"><tspan
  95.181 +   style="font-weight:bold"
  95.182 +   id="tspan2862">4</tspan>: REV4</tspan></text>
  95.183 +    <text
  95.184 +       xml:space="preserve"
  95.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"
  95.186 +       x="173.57143"
  95.187 +       y="443.79074"
  95.188 +       id="text2832"><tspan
  95.189 +         sodipodi:role="line"
  95.190 +         id="tspan2834"
  95.191 +         x="173.57143"
  95.192 +         y="443.79074" /></text>
  95.193 +    <path
  95.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)"
  95.195 +       d="M 185.14286,478.50504 L 185.14286,454.34432"
  95.196 +       id="path2894"
  95.197 +       inkscape:connector-type="polyline" />
  95.198 +    <path
  95.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)"
  95.200 +       d="M 185.14286,431.63004 L 185.14286,407.46932"
  95.201 +       id="path2896"
  95.202 +       inkscape:connector-type="polyline" />
  95.203 +    <path
  95.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)"
  95.205 +       d="M 185.14286,384.75504 L 185.14286,360.59435"
  95.206 +       id="path2898"
  95.207 +       inkscape:connector-type="polyline" />
  95.208 +    <path
  95.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)"
  95.210 +       d="M 185.14286,337.88007 L 185.14286,313.71932"
  95.211 +       id="path2900"
  95.212 +       inkscape:connector-type="polyline" />
  95.213 +    <text
  95.214 +       xml:space="preserve"
  95.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"
  95.216 +       x="244.60992"
  95.217 +       y="305.245"
  95.218 +       id="text1902"><tspan
  95.219 +         sodipodi:role="line"
  95.220 +         id="tspan1904"
  95.221 +         x="244.60992"
  95.222 +         y="305.245">(newest)</tspan></text>
  95.223 +    <text
  95.224 +       xml:space="preserve"
  95.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"
  95.226 +       x="244.60992"
  95.227 +       y="492.745"
  95.228 +       id="text1906"><tspan
  95.229 +         sodipodi:role="line"
  95.230 +         id="tspan1908"
  95.231 +         x="244.60992"
  95.232 +         y="492.745">(oldest)</tspan></text>
  95.233 +    <rect
  95.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"
  95.235 +       id="rect1907"
  95.236 +       width="94.285713"
  95.237 +       height="20.714285"
  95.238 +       x="309.28571"
  95.239 +       y="324.86218" />
  95.240 +    <text
  95.241 +       xml:space="preserve"
  95.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"
  95.243 +       x="333.38464"
  95.244 +       y="338.48334"
  95.245 +       id="text1909"><tspan
  95.246 +         sodipodi:role="line"
  95.247 +         id="tspan1911"
  95.248 +         x="333.38464"
  95.249 +         y="338.48334"
  95.250 +         style="font-family:Courier"><tspan
  95.251 +   style="font-weight:bold"
  95.252 +   id="tspan1913">4</tspan>: REV4</tspan></text>
  95.253 +    <path
  95.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"
  95.255 +       d="M 332.14286,375.21932 L 335.71429,347.36218"
  95.256 +       id="path2802" />
  95.257 +    <path
  95.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"
  95.259 +       d="M 372.69968,375.21932 L 369.12825,347.36218"
  95.260 +       id="path2986" />
  95.261 +    <text
  95.262 +       xml:space="preserve"
  95.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"
  95.264 +       x="335.14285"
  95.265 +       y="387.21933"
  95.266 +       id="text2988"><tspan
  95.267 +         sodipodi:role="line"
  95.268 +         x="335.14285"
  95.269 +         y="387.21933"
  95.270 +         id="tspan3020"
  95.271 +         style="text-align:end;text-anchor:end">revision</tspan><tspan
  95.272 +         sodipodi:role="line"
  95.273 +         x="335.14285"
  95.274 +         y="402.21933"
  95.275 +         id="tspan3014"
  95.276 +         style="text-align:end;text-anchor:end">number</tspan></text>
  95.277 +    <text
  95.278 +       xml:space="preserve"
  95.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"
  95.280 +       x="368.71429"
  95.281 +       y="387.21933"
  95.282 +       id="text2994"><tspan
  95.283 +         sodipodi:role="line"
  95.284 +         id="tspan2996"
  95.285 +         x="368.71429"
  95.286 +         y="387.21933">changeset</tspan><tspan
  95.287 +         sodipodi:role="line"
  95.288 +         x="368.71429"
  95.289 +         y="402.21933"
  95.290 +         id="tspan2998">identifier</tspan></text>
  95.291 +  </g>
  95.292 +</svg>
    96.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    96.2 +++ b/fr/figs/tour-merge-conflict.svg	Sat Jul 10 06:24:49 2010 +0100
    96.3 @@ -0,0 +1,210 @@
    96.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
    96.5 +<!-- Created with Inkscape (http://www.inkscape.org/) -->
    96.6 +<svg
    96.7 +   xmlns:dc="http://purl.org/dc/elements/1.1/"
    96.8 +   xmlns:cc="http://web.resource.org/cc/"
    96.9 +   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   96.10 +   xmlns:svg="http://www.w3.org/2000/svg"
   96.11 +   xmlns="http://www.w3.org/2000/svg"
   96.12 +   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   96.13 +   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   96.14 +   width="744.09448819"
   96.15 +   height="1052.3622047"
   96.16 +   id="svg2"
   96.17 +   sodipodi:version="0.32"
   96.18 +   inkscape:version="0.44.1"
   96.19 +   sodipodi:docname="tour-merge-conflict.svg">
   96.20 +  <defs
   96.21 +     id="defs4">
   96.22 +    <marker
   96.23 +       inkscape:stockid="Arrow1Mend"
   96.24 +       orient="auto"
   96.25 +       refY="0.0"
   96.26 +       refX="0.0"
   96.27 +       id="Arrow1Mend"
   96.28 +       style="overflow:visible;">
   96.29 +      <path
   96.30 +         id="path3053"
   96.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 "
   96.32 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
   96.33 +         transform="scale(0.4) rotate(180) translate(10,0)" />
   96.34 +    </marker>
   96.35 +  </defs>
   96.36 +  <sodipodi:namedview
   96.37 +     id="base"
   96.38 +     pagecolor="#ffffff"
   96.39 +     bordercolor="#666666"
   96.40 +     borderopacity="1.0"
   96.41 +     gridtolerance="10000"
   96.42 +     guidetolerance="10"
   96.43 +     objecttolerance="10"
   96.44 +     inkscape:pageopacity="0.0"
   96.45 +     inkscape:pageshadow="2"
   96.46 +     inkscape:zoom="1.4"
   96.47 +     inkscape:cx="164.78349"
   96.48 +     inkscape:cy="590.07679"
   96.49 +     inkscape:document-units="px"
   96.50 +     inkscape:current-layer="layer1"
   96.51 +     inkscape:window-width="906"
   96.52 +     inkscape:window-height="620"
   96.53 +     inkscape:window-x="5"
   96.54 +     inkscape:window-y="49" />
   96.55 +  <metadata
   96.56 +     id="metadata7">
   96.57 +    <rdf:RDF>
   96.58 +      <cc:Work
   96.59 +         rdf:about="">
   96.60 +        <dc:format>image/svg+xml</dc:format>
   96.61 +        <dc:type
   96.62 +           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
   96.63 +      </cc:Work>
   96.64 +    </rdf:RDF>
   96.65 +  </metadata>
   96.66 +  <g
   96.67 +     inkscape:label="Layer 1"
   96.68 +     inkscape:groupmode="layer"
   96.69 +     id="layer1">
   96.70 +    <g
   96.71 +       id="g1988"
   96.72 +       transform="translate(84.85711,0)">
   96.73 +      <g
   96.74 +         id="g1876">
   96.75 +        <path
   96.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"
   96.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 "
   96.78 +           id="path1872"
   96.79 +           sodipodi:nodetypes="cccccc" />
   96.80 +        <path
   96.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"
   96.82 +           d="M 191.55484,563.36862 L 191.6923,560.98794 L 192.69126,552.44884 L 203.80416,551.31242"
   96.83 +           id="path1874"
   96.84 +           sodipodi:nodetypes="cccc" />
   96.85 +      </g>
   96.86 +      <flowRoot
   96.87 +         style="font-size:8px;font-family:Times New Roman"
   96.88 +         id="flowRoot1898"
   96.89 +         xml:space="preserve"><flowRegion
   96.90 +           id="flowRegion1900"><rect
   96.91 +             style="font-size:8px;font-family:Times New Roman"
   96.92 +             y="464.50504"
   96.93 +             x="122.85714"
   96.94 +             height="93.571426"
   96.95 +             width="76.428574"
   96.96 +             id="rect1902" /></flowRegion><flowPara
   96.97 +           id="flowPara1904">Greetings!</flowPara><flowPara
   96.98 +           id="flowPara1906" /><flowPara
   96.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>
  96.100 +    <g
  96.101 +       id="g1966"
  96.102 +       transform="translate(82,0.35715)">
  96.103 +      <g
  96.104 +         transform="translate(-77.85718,-140.0714)"
  96.105 +         id="g1910">
  96.106 +        <path
  96.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"
  96.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 "
  96.109 +           id="path1912"
  96.110 +           sodipodi:nodetypes="cccccc" />
  96.111 +        <path
  96.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"
  96.113 +           d="M 191.55484,563.36862 L 191.6923,560.98794 L 192.69126,552.44884 L 203.80416,551.31242"
  96.114 +           id="path1914"
  96.115 +           sodipodi:nodetypes="cccc" />
  96.116 +      </g>
  96.117 +      <flowRoot
  96.118 +         transform="translate(-77.85718,-140.0714)"
  96.119 +         style="font-size:8px;font-family:Times New Roman"
  96.120 +         id="flowRoot1916"
  96.121 +         xml:space="preserve"><flowRegion
  96.122 +           id="flowRegion1918"><rect
  96.123 +             style="font-size:8px;font-family:Times New Roman"
  96.124 +             y="464.50504"
  96.125 +             x="122.85714"
  96.126 +             height="93.571426"
  96.127 +             width="76.428574"
  96.128 +             id="rect1920" /></flowRegion><flowPara
  96.129 +           id="flowPara1922">Greetings!</flowPara><flowPara
  96.130 +           id="flowPara1924" /><flowPara
  96.131 +           id="flowPara1926">I am <flowSpan
  96.132 +   style="font-style:italic;fill:red"
  96.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>
  96.134 +    <g
  96.135 +       id="g1977"
  96.136 +       transform="translate(81.99999,-0.35715)">
  96.137 +      <g
  96.138 +         transform="translate(83.57141,-139.3571)"
  96.139 +         id="g1932">
  96.140 +        <path
  96.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"
  96.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 "
  96.143 +           id="path1934"
  96.144 +           sodipodi:nodetypes="cccccc" />
  96.145 +        <path
  96.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"
  96.147 +           d="M 191.55484,563.36862 L 191.6923,560.98794 L 192.69126,552.44884 L 203.80416,551.31242"
  96.148 +           id="path1936"
  96.149 +           sodipodi:nodetypes="cccc" />
  96.150 +      </g>
  96.151 +      <flowRoot
  96.152 +         transform="translate(83.57141,-139.3571)"
  96.153 +         style="font-size:8px;font-family:Times New Roman"
  96.154 +         id="flowRoot1938"
  96.155 +         xml:space="preserve"><flowRegion
  96.156 +           id="flowRegion1940"><rect
  96.157 +             style="font-size:8px;font-family:Times New Roman"
  96.158 +             y="464.50504"
  96.159 +             x="122.85714"
  96.160 +             height="93.571426"
  96.161 +             width="76.428574"
  96.162 +             id="rect1942" /></flowRegion><flowPara
  96.163 +           id="flowPara1944">Greetings!</flowPara><flowPara
  96.164 +           id="flowPara1946" /><flowPara
  96.165 +           id="flowPara1948">I am <flowSpan
  96.166 +   style="font-style:italic;fill:red"
  96.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>
  96.168 +    <path
  96.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"
  96.170 +       d="M 215.502,457.71933 L 196.35507,424.5765"
  96.171 +       id="path1999"
  96.172 +       inkscape:connector-type="polyline"
  96.173 +       inkscape:connection-start="#g1988"
  96.174 +       inkscape:connection-end="#g1966" />
  96.175 +    <path
  96.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"
  96.177 +       d="M 277.06936,457.71933 L 296.21629,424.5765"
  96.178 +       id="path2001"
  96.179 +       inkscape:connector-type="polyline"
  96.180 +       inkscape:connection-start="#g1988"
  96.181 +       inkscape:connection-end="#g1977" />
  96.182 +    <text
  96.183 +       xml:space="preserve"
  96.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"
  96.185 +       x="302.42859"
  96.186 +       y="515.08905"
  96.187 +       id="text1905"><tspan
  96.188 +         sodipodi:role="line"
  96.189 +         id="tspan1907"
  96.190 +         x="302.42859"
  96.191 +         y="515.08905">Base version</tspan></text>
  96.192 +    <text
  96.193 +       xml:space="preserve"
  96.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"
  96.195 +       x="45.57143"
  96.196 +       y="374.1619"
  96.197 +       id="text1917"><tspan
  96.198 +         sodipodi:role="line"
  96.199 +         id="tspan1919"
  96.200 +         x="45.57143"
  96.201 +         y="374.1619">Our changes</tspan></text>
  96.202 +    <text
  96.203 +       xml:space="preserve"
  96.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"
  96.205 +       x="385.71429"
  96.206 +       y="374.1619"
  96.207 +       id="text1921"><tspan
  96.208 +         sodipodi:role="line"
  96.209 +         id="tspan1923"
  96.210 +         x="385.71429"
  96.211 +         y="374.1619">Their changes</tspan></text>
  96.212 +  </g>
  96.213 +</svg>
    97.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    97.2 +++ b/fr/figs/tour-merge-merge.svg	Sat Jul 10 06:24:49 2010 +0100
    97.3 @@ -0,0 +1,380 @@
    97.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
    97.5 +<!-- Created with Inkscape (http://www.inkscape.org/) -->
    97.6 +<svg
    97.7 +   xmlns:dc="http://purl.org/dc/elements/1.1/"
    97.8 +   xmlns:cc="http://web.resource.org/cc/"
    97.9 +   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   97.10 +   xmlns:svg="http://www.w3.org/2000/svg"
   97.11 +   xmlns="http://www.w3.org/2000/svg"
   97.12 +   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   97.13 +   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   97.14 +   width="744.09448819"
   97.15 +   height="1052.3622047"
   97.16 +   id="svg2"
   97.17 +   sodipodi:version="0.32"
   97.18 +   inkscape:version="0.44.1"
   97.19 +   sodipodi:docname="tour-merge-merge.svg">
   97.20 +  <defs
   97.21 +     id="defs4">
   97.22 +    <marker
   97.23 +       inkscape:stockid="Arrow1Mstart"
   97.24 +       orient="auto"
   97.25 +       refY="0.0"
   97.26 +       refX="0.0"
   97.27 +       id="Arrow1Mstart"
   97.28 +       style="overflow:visible">
   97.29 +      <path
   97.30 +         id="path2973"
   97.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 "
   97.32 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
   97.33 +         transform="scale(0.4) translate(10,0)" />
   97.34 +    </marker>
   97.35 +    <marker
   97.36 +       inkscape:stockid="Arrow1Mend"
   97.37 +       orient="auto"
   97.38 +       refY="0.0"
   97.39 +       refX="0.0"
   97.40 +       id="Arrow1Mend"
   97.41 +       style="overflow:visible;">
   97.42 +      <path
   97.43 +         id="path3066"
   97.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 "
   97.45 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
   97.46 +         transform="scale(0.4) rotate(180) translate(10,0)" />
   97.47 +    </marker>
   97.48 +  </defs>
   97.49 +  <sodipodi:namedview
   97.50 +     id="base"
   97.51 +     pagecolor="#ffffff"
   97.52 +     bordercolor="#666666"
   97.53 +     borderopacity="1.0"
   97.54 +     gridtolerance="10000"
   97.55 +     guidetolerance="10"
   97.56 +     objecttolerance="10"
   97.57 +     inkscape:pageopacity="0.0"
   97.58 +     inkscape:pageshadow="2"
   97.59 +     inkscape:zoom="1.4"
   97.60 +     inkscape:cx="247.53795"
   97.61 +     inkscape:cy="871.05738"
   97.62 +     inkscape:document-units="px"
   97.63 +     inkscape:current-layer="layer1"
   97.64 +     inkscape:window-width="906"
   97.65 +     inkscape:window-height="620"
   97.66 +     inkscape:window-x="38"
   97.67 +     inkscape:window-y="95" />
   97.68 +  <metadata
   97.69 +     id="metadata7">
   97.70 +    <rdf:RDF>
   97.71 +      <cc:Work
   97.72 +         rdf:about="">
   97.73 +        <dc:format>image/svg+xml</dc:format>
   97.74 +        <dc:type
   97.75 +           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
   97.76 +      </cc:Work>
   97.77 +    </rdf:RDF>
   97.78 +  </metadata>
   97.79 +  <g
   97.80 +     inkscape:label="Layer 1"
   97.81 +     inkscape:groupmode="layer"
   97.82 +     id="layer1">
   97.83 +    <rect
   97.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"
   97.85 +       id="rect2995"
   97.86 +       width="94.285713"
   97.87 +       height="20.714285"
   97.88 +       x="532.85718"
   97.89 +       y="203.0479" />
   97.90 +    <text
   97.91 +       xml:space="preserve"
   97.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"
   97.93 +       x="173.57143"
   97.94 +       y="443.79074"
   97.95 +       id="text2832"><tspan
   97.96 +         sodipodi:role="line"
   97.97 +         id="tspan2834"
   97.98 +         x="173.57143"
   97.99 +         y="443.79074" /></text>
  97.100 +    <rect
  97.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"
  97.102 +       id="rect2830"
  97.103 +       width="94.285713"
  97.104 +       height="20.714285"
  97.105 +       x="138"
  97.106 +       y="297.76227" />
  97.107 +    <text
  97.108 +       xml:space="preserve"
  97.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"
  97.110 +       x="162.09892"
  97.111 +       y="311.38342"
  97.112 +       id="text2824"><tspan
  97.113 +         sodipodi:role="line"
  97.114 +         id="tspan2826"
  97.115 +         x="162.09892"
  97.116 +         y="311.38342"
  97.117 +         style="font-family:Courier"><tspan
  97.118 +   style="font-weight:bold"
  97.119 +   id="tspan2862">4</tspan>: REV4</tspan></text>
  97.120 +    <path
  97.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"
  97.122 +       d="M 185.14286,343.63731 L 185.14286,319.47656"
  97.123 +       id="path2900"
  97.124 +       inkscape:connector-type="polyline" />
  97.125 +    <rect
  97.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"
  97.127 +       id="rect2863"
  97.128 +       width="94.285713"
  97.129 +       height="20.714285"
  97.130 +       x="91.428574"
  97.131 +       y="250.47656" />
  97.132 +    <text
  97.133 +       xml:space="preserve"
  97.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"
  97.135 +       x="116.09886"
  97.136 +       y="264.56592"
  97.137 +       id="text1965"
  97.138 +       transform="scale(1.000002,0.999998)"><tspan
  97.139 +         sodipodi:role="line"
  97.140 +         id="tspan1967"
  97.141 +         x="116.09886"
  97.142 +         y="264.56592"
  97.143 +         style="font-family:Courier"><tspan
  97.144 +   style="font-weight:bold"
  97.145 +   id="tspan1973">5</tspan>: REV_my_new_hello</tspan></text>
  97.146 +    <path
  97.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"
  97.148 +       d="M 173.95727,296.76228 L 149.75702,272.19085"
  97.149 +       id="path1971"
  97.150 +       inkscape:connector-type="polyline"
  97.151 +       inkscape:connection-end="#rect2863"
  97.152 +       inkscape:connection-start="#rect2830" />
  97.153 +    <rect
  97.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"
  97.155 +       id="rect2911"
  97.156 +       width="94.285995"
  97.157 +       height="20.714283"
  97.158 +       x="186.71414"
  97.159 +       y="204.40514" />
  97.160 +    <text
  97.161 +       xml:space="preserve"
  97.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"
  97.163 +       x="210.81311"
  97.164 +       y="218.02673"
  97.165 +       id="text2913"
  97.166 +       transform="scale(1.000002,0.999998)"><tspan
  97.167 +         sodipodi:role="line"
  97.168 +         id="tspan2915"
  97.169 +         x="210.81311"
  97.170 +         y="218.02673"
  97.171 +         style="font-family:Courier"><tspan
  97.172 +   id="tspan1966"
  97.173 +   style="font-weight:bold">6</tspan>: REV6_my_new_hello</tspan></text>
  97.174 +    <path
  97.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"
  97.176 +       d="M 191.06908,296.76228 L 227.93092,226.11942"
  97.177 +       id="path2919"
  97.178 +       inkscape:connector-type="polyline"
  97.179 +       inkscape:connection-start="#rect2830" />
  97.180 +    <text
  97.181 +       xml:space="preserve"
  97.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"
  97.183 +       x="295.28571"
  97.184 +       y="217.56711"
  97.185 +       id="text2871"><tspan
  97.186 +         sodipodi:role="line"
  97.187 +         id="tspan2873"
  97.188 +         x="295.28571"
  97.189 +         y="217.56711">tip (and head)</tspan></text>
  97.190 +    <text
  97.191 +       xml:space="preserve"
  97.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"
  97.193 +       x="76"
  97.194 +       y="264.91769"
  97.195 +       id="text2875"><tspan
  97.196 +         sodipodi:role="line"
  97.197 +         id="tspan2877"
  97.198 +         x="76"
  97.199 +         y="264.91769"
  97.200 +         style="text-align:end;text-anchor:end">head</tspan></text>
  97.201 +    <rect
  97.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"
  97.203 +       id="rect1913"
  97.204 +       width="94.285713"
  97.205 +       height="20.714285"
  97.206 +       x="138"
  97.207 +       y="156.90514" />
  97.208 +    <path
  97.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"
  97.210 +       d="M 144.22399,249.47657 L 179.49029,178.61943"
  97.211 +       id="path1915"
  97.212 +       inkscape:connector-type="polyline"
  97.213 +       inkscape:connection-start="#rect2863"
  97.214 +       inkscape:connection-end="#rect1913" />
  97.215 +    <path
  97.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"
  97.217 +       d="M 222.20966,203.40514 L 196.79033,178.61943"
  97.218 +       id="path1917"
  97.219 +       inkscape:connector-type="polyline"
  97.220 +       inkscape:connection-start="#rect2911"
  97.221 +       inkscape:connection-end="#rect1913" />
  97.222 +    <text
  97.223 +       xml:space="preserve"
  97.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"
  97.225 +       x="166.16823"
  97.226 +       y="168.52228"
  97.227 +       id="text2806"><tspan
  97.228 +         sodipodi:role="line"
  97.229 +         id="tspan2808"
  97.230 +         x="166.16823"
  97.231 +         y="168.52228"
  97.232 +         style="font-family:Courier">merge</tspan></text>
  97.233 +    <text
  97.234 +       xml:space="preserve"
  97.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"
  97.236 +       x="246"
  97.237 +       y="162.63338"
  97.238 +       id="text2810"><tspan
  97.239 +         sodipodi:role="line"
  97.240 +         id="tspan2812"
  97.241 +         x="246"
  97.242 +         y="162.63338">working directory</tspan><tspan
  97.243 +         sodipodi:role="line"
  97.244 +         x="246"
  97.245 +         y="177.63338"
  97.246 +         id="tspan2814">during merge</tspan></text>
  97.247 +    <rect
  97.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"
  97.249 +       id="rect2816"
  97.250 +       width="94.285713"
  97.251 +       height="20.714285"
  97.252 +       x="483.14636"
  97.253 +       y="297.76227" />
  97.254 +    <text
  97.255 +       xml:space="preserve"
  97.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"
  97.257 +       x="507.24527"
  97.258 +       y="311.38342"
  97.259 +       id="text2818"><tspan
  97.260 +         sodipodi:role="line"
  97.261 +         id="tspan2820"
  97.262 +         x="507.24527"
  97.263 +         y="311.38342"
  97.264 +         style="font-family:Courier"><tspan
  97.265 +   style="font-weight:bold"
  97.266 +   id="tspan2822">4</tspan>: REV4</tspan></text>
  97.267 +    <path
  97.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"
  97.269 +       d="M 530.28921,343.6373 L 530.28921,319.47655"
  97.270 +       id="path2824"
  97.271 +       inkscape:connector-type="polyline" />
  97.272 +    <rect
  97.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"
  97.274 +       id="rect2826"
  97.275 +       width="94.285713"
  97.276 +       height="20.714285"
  97.277 +       x="436.57492"
  97.278 +       y="250.47656" />
  97.279 +    <text
  97.280 +       xml:space="preserve"
  97.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"
  97.282 +       x="461.24484"
  97.283 +       y="264.56613"
  97.284 +       id="text2828"
  97.285 +       transform="scale(1.000002,0.999998)"><tspan
  97.286 +         sodipodi:role="line"
  97.287 +         id="tspan2830"
  97.288 +         x="461.24484"
  97.289 +         y="264.56613"
  97.290 +         style="font-family:Courier"><tspan
  97.291 +   style="font-weight:bold"
  97.292 +   id="tspan2832">5</tspan>: REV_my_new_hello</tspan></text>
  97.293 +    <path
  97.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"
  97.295 +       d="M 519.10362,296.76227 L 494.90337,272.19084"
  97.296 +       id="path2834"
  97.297 +       inkscape:connector-type="polyline" />
  97.298 +    <rect
  97.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"
  97.300 +       id="rect2836"
  97.301 +       width="94.285995"
  97.302 +       height="20.714283"
  97.303 +       x="483.14001"
  97.304 +       y="156.548" />
  97.305 +    <text
  97.306 +       xml:space="preserve"
  97.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"
  97.308 +       x="555.95911"
  97.309 +       y="218.02698"
  97.310 +       id="text2838"
  97.311 +       transform="scale(1.000002,0.999998)"><tspan
  97.312 +         sodipodi:role="line"
  97.313 +         id="tspan2840"
  97.314 +         x="555.95911"
  97.315 +         y="218.02698"
  97.316 +         style="font-family:Courier"><tspan
  97.317 +   id="tspan2842"
  97.318 +   style="font-weight:bold">6</tspan>: REV6_my_new_hello</tspan></text>
  97.319 +    <path
  97.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"
  97.321 +       d="M 536.21543,296.76227 L 574.03453,224.76218"
  97.322 +       id="path2844"
  97.323 +       inkscape:connector-type="polyline" />
  97.324 +    <text
  97.325 +       xml:space="preserve"
  97.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"
  97.327 +       x="594.43207"
  97.328 +       y="169.78796"
  97.329 +       id="text2846"><tspan
  97.330 +         sodipodi:role="line"
  97.331 +         id="tspan2848"
  97.332 +         x="594.43207"
  97.333 +         y="169.78796">tip</tspan></text>
  97.334 +    <path
  97.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"
  97.336 +       d="M 489.37034,249.47656 L 524.65575,178.26229"
  97.337 +       id="path2856"
  97.338 +       inkscape:connector-type="polyline"
  97.339 +       inkscape:connection-end="#rect2836" />
  97.340 +    <path
  97.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"
  97.342 +       d="M 567.85714,202.0479 L 542.42591,178.26229"
  97.343 +       id="path2858"
  97.344 +       inkscape:connector-type="polyline"
  97.345 +       inkscape:connection-end="#rect2836"
  97.346 +       inkscape:connection-start="#rect2995" />
  97.347 +    <text
  97.348 +       xml:space="preserve"
  97.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"
  97.350 +       x="504.54507"
  97.351 +       y="170.39714"
  97.352 +       id="text2860"><tspan
  97.353 +         sodipodi:role="line"
  97.354 +         id="tspan2863"
  97.355 +         x="504.54507"
  97.356 +         y="170.39714"
  97.357 +         style="font-family:Courier"><tspan
  97.358 +   style="font-weight:bold"
  97.359 +   id="tspan2997">7</tspan>: REV7_my_new_hello</tspan></text>
  97.360 +    <text
  97.361 +       xml:space="preserve"
  97.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"
  97.363 +       x="90.323105"
  97.364 +       y="120.21933"
  97.365 +       id="text2929"><tspan
  97.366 +         sodipodi:role="line"
  97.367 +         id="tspan2931"
  97.368 +         x="90.323105"
  97.369 +         y="120.21933"
  97.370 +         style="font-weight:bold">Working directory during merge</tspan></text>
  97.371 +    <text
  97.372 +       xml:space="preserve"
  97.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"
  97.374 +       x="435.35226"
  97.375 +       y="120.21933"
  97.376 +       id="text2937"><tspan
  97.377 +         sodipodi:role="line"
  97.378 +         id="tspan2939"
  97.379 +         x="435.35226"
  97.380 +         y="120.21933"
  97.381 +         style="font-weight:bold">Repository after merge committed</tspan></text>
  97.382 +  </g>
  97.383 +</svg>
    98.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    98.2 +++ b/fr/figs/tour-merge-pull.svg	Sat Jul 10 06:24:49 2010 +0100
    98.3 @@ -0,0 +1,288 @@
    98.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
    98.5 +<!-- Created with Inkscape (http://www.inkscape.org/) -->
    98.6 +<svg
    98.7 +   xmlns:dc="http://purl.org/dc/elements/1.1/"
    98.8 +   xmlns:cc="http://web.resource.org/cc/"
    98.9 +   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   98.10 +   xmlns:svg="http://www.w3.org/2000/svg"
   98.11 +   xmlns="http://www.w3.org/2000/svg"
   98.12 +   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   98.13 +   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   98.14 +   width="744.09448819"
   98.15 +   height="1052.3622047"
   98.16 +   id="svg2"
   98.17 +   sodipodi:version="0.32"
   98.18 +   inkscape:version="0.44.1"
   98.19 +   sodipodi:docname="tour-merge-pull.svg"
   98.20 +   sodipodi:docbase="/home/bos/hg/hgbook/en">
   98.21 +  <defs
   98.22 +     id="defs4">
   98.23 +    <marker
   98.24 +       inkscape:stockid="Arrow1Mstart"
   98.25 +       orient="auto"
   98.26 +       refY="0.0"
   98.27 +       refX="0.0"
   98.28 +       id="Arrow1Mstart"
   98.29 +       style="overflow:visible">
   98.30 +      <path
   98.31 +         id="path2973"
   98.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 "
   98.33 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
   98.34 +         transform="scale(0.4) translate(10,0)" />
   98.35 +    </marker>
   98.36 +    <marker
   98.37 +       inkscape:stockid="Arrow1Mend"
   98.38 +       orient="auto"
   98.39 +       refY="0.0"
   98.40 +       refX="0.0"
   98.41 +       id="Arrow1Mend"
   98.42 +       style="overflow:visible;">
   98.43 +      <path
   98.44 +         id="path3066"
   98.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 "
   98.46 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
   98.47 +         transform="scale(0.4) rotate(180) translate(10,0)" />
   98.48 +    </marker>
   98.49 +  </defs>
   98.50 +  <sodipodi:namedview
   98.51 +     id="base"
   98.52 +     pagecolor="#ffffff"
   98.53 +     bordercolor="#666666"
   98.54 +     borderopacity="1.0"
   98.55 +     gridtolerance="10000"
   98.56 +     guidetolerance="10"
   98.57 +     objecttolerance="10"
   98.58 +     inkscape:pageopacity="0.0"
   98.59 +     inkscape:pageshadow="2"
   98.60 +     inkscape:zoom="1.4"
   98.61 +     inkscape:cx="233.63208"
   98.62 +     inkscape:cy="832.54381"
   98.63 +     inkscape:document-units="px"
   98.64 +     inkscape:current-layer="layer1"
   98.65 +     inkscape:window-width="906"
   98.66 +     inkscape:window-height="620"
   98.67 +     inkscape:window-x="237"
   98.68 +     inkscape:window-y="103" />
   98.69 +  <metadata
   98.70 +     id="metadata7">
   98.71 +    <rdf:RDF>
   98.72 +      <cc:Work
   98.73 +         rdf:about="">
   98.74 +        <dc:format>image/svg+xml</dc:format>
   98.75 +        <dc:type
   98.76 +           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
   98.77 +      </cc:Work>
   98.78 +    </rdf:RDF>
   98.79 +  </metadata>
   98.80 +  <g
   98.81 +     inkscape:label="Layer 1"
   98.82 +     inkscape:groupmode="layer"
   98.83 +     id="layer1">
   98.84 +    <text
   98.85 +       xml:space="preserve"
   98.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"
   98.87 +       x="173.57143"
   98.88 +       y="443.79074"
   98.89 +       id="text2832"><tspan
   98.90 +         sodipodi:role="line"
   98.91 +         id="tspan2834"
   98.92 +         x="173.57143"
   98.93 +         y="443.79074" /></text>
   98.94 +    <rect
   98.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"
   98.96 +       id="rect1878"
   98.97 +       width="94.285713"
   98.98 +       height="20.714285"
   98.99 +       x="138"
  98.100 +       y="479.50504" />
  98.101 +    <text
  98.102 +       xml:space="preserve"
  98.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"
  98.104 +       x="162.09892"
  98.105 +       y="493.12619"
  98.106 +       id="text1872"><tspan
  98.107 +         sodipodi:role="line"
  98.108 +         id="tspan1874"
  98.109 +         x="162.09892"
  98.110 +         y="493.12619"
  98.111 +         style="font-family:Courier"><tspan
  98.112 +   style="font-weight:bold"
  98.113 +   id="tspan1876">0</tspan>: REV0</tspan></text>
  98.114 +    <rect
  98.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"
  98.116 +       id="rect2800"
  98.117 +       width="94.285713"
  98.118 +       height="20.714285"
  98.119 +       x="138"
  98.120 +       y="432.63004" />
  98.121 +    <text
  98.122 +       xml:space="preserve"
  98.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"
  98.124 +       x="162.09892"
  98.125 +       y="446.25119"
  98.126 +       id="text2794"><tspan
  98.127 +         sodipodi:role="line"
  98.128 +         id="tspan2796"
  98.129 +         x="162.09892"
  98.130 +         y="446.25119"
  98.131 +         style="font-family:Courier"><tspan
  98.132 +   id="tspan2868"
  98.133 +   style="font-weight:bold">1</tspan>: REV1</tspan></text>
  98.134 +    <rect
  98.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"
  98.136 +       id="rect2810"
  98.137 +       width="94.285713"
  98.138 +       height="20.714285"
  98.139 +       x="138"
  98.140 +       y="385.75504" />
  98.141 +    <text
  98.142 +       xml:space="preserve"
  98.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"
  98.144 +       x="162.09892"
  98.145 +       y="399.37619"
  98.146 +       id="text2804"><tspan
  98.147 +         sodipodi:role="line"
  98.148 +         id="tspan2806"
  98.149 +         x="162.09892"
  98.150 +         y="399.37619"
  98.151 +         style="font-family:Courier"><tspan
  98.152 +   style="font-weight:bold"
  98.153 +   id="tspan2866">2</tspan>: REV2</tspan></text>
  98.154 +    <rect
  98.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"
  98.156 +       id="rect2820"
  98.157 +       width="94.285713"
  98.158 +       height="20.714285"
  98.159 +       x="138"
  98.160 +       y="338.88007" />
  98.161 +    <text
  98.162 +       xml:space="preserve"
  98.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"
  98.164 +       x="162.09892"
  98.165 +       y="352.50122"
  98.166 +       id="text2814"><tspan
  98.167 +         sodipodi:role="line"
  98.168 +         id="tspan2816"
  98.169 +         x="162.09892"
  98.170 +         y="352.50122"
  98.171 +         style="font-family:Courier"><tspan
  98.172 +   style="font-weight:bold"
  98.173 +   id="tspan2864">3</tspan>: REV3</tspan></text>
  98.174 +    <rect
  98.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"
  98.176 +       id="rect2830"
  98.177 +       width="94.285713"
  98.178 +       height="20.714285"
  98.179 +       x="138"
  98.180 +       y="292.00504" />
  98.181 +    <text
  98.182 +       xml:space="preserve"
  98.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"
  98.184 +       x="162.09892"
  98.185 +       y="305.62619"
  98.186 +       id="text2824"><tspan
  98.187 +         sodipodi:role="line"
  98.188 +         id="tspan2826"
  98.189 +         x="162.09892"
  98.190 +         y="305.62619"
  98.191 +         style="font-family:Courier"><tspan
  98.192 +   style="font-weight:bold"
  98.193 +   id="tspan2862">4</tspan>: REV4</tspan></text>
  98.194 +    <path
  98.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"
  98.196 +       d="M 185.14286,478.50504 L 185.14286,454.34432"
  98.197 +       id="path2894"
  98.198 +       inkscape:connector-type="polyline" />
  98.199 +    <path
  98.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"
  98.201 +       d="M 185.14286,431.63004 L 185.14286,407.46932"
  98.202 +       id="path2896"
  98.203 +       inkscape:connector-type="polyline" />
  98.204 +    <path
  98.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"
  98.206 +       d="M 185.14286,384.75504 L 185.14286,360.59435"
  98.207 +       id="path2898"
  98.208 +       inkscape:connector-type="polyline" />
  98.209 +    <path
  98.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"
  98.211 +       d="M 185.14286,337.88007 L 185.14286,313.71932"
  98.212 +       id="path2900"
  98.213 +       inkscape:connector-type="polyline" />
  98.214 +    <rect
  98.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"
  98.216 +       id="rect2863"
  98.217 +       width="94.285713"
  98.218 +       height="20.714285"
  98.219 +       x="91.428574"
  98.220 +       y="244.71933" />
  98.221 +    <text
  98.222 +       xml:space="preserve"
  98.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"
  98.224 +       x="116.09886"
  98.225 +       y="258.80865"
  98.226 +       id="text1965"
  98.227 +       transform="scale(1.000002,0.999998)"><tspan
  98.228 +         sodipodi:role="line"
  98.229 +         id="tspan1967"
  98.230 +         x="116.09886"
  98.231 +         y="258.80865"
  98.232 +         style="font-family:Courier"><tspan
  98.233 +   style="font-weight:bold"
  98.234 +   id="tspan1973">5</tspan>: REV_my_new_hello</tspan></text>
  98.235 +    <path
  98.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"
  98.237 +       d="M 173.95727,291.00504 L 149.75702,266.43361"
  98.238 +       id="path1971"
  98.239 +       inkscape:connector-type="polyline"
  98.240 +       inkscape:connection-end="#rect2863"
  98.241 +       inkscape:connection-start="#rect2830" />
  98.242 +    <rect
  98.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"
  98.244 +       id="rect2911"
  98.245 +       width="94.285995"
  98.246 +       height="20.714283"
  98.247 +       x="186.71414"
  98.248 +       y="198.6479" />
  98.249 +    <text
  98.250 +       xml:space="preserve"
  98.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"
  98.252 +       x="210.81311"
  98.253 +       y="212.26949"
  98.254 +       id="text2913"
  98.255 +       transform="scale(1.000002,0.999998)"><tspan
  98.256 +         sodipodi:role="line"
  98.257 +         id="tspan2915"
  98.258 +         x="210.81311"
  98.259 +         y="212.26949"
  98.260 +         style="font-family:Courier"><tspan
  98.261 +   id="tspan1966"
  98.262 +   style="font-weight:bold">6</tspan>: REV6_my_new_hello</tspan></text>
  98.263 +    <path
  98.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"
  98.265 +       d="M 191.06908,291.00504 L 227.93092,220.36218"
  98.266 +       id="path2919"
  98.267 +       inkscape:connector-type="polyline"
  98.268 +       inkscape:connection-start="#rect2830" />
  98.269 +    <text
  98.270 +       xml:space="preserve"
  98.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"
  98.272 +       x="295.28571"
  98.273 +       y="211.80988"
  98.274 +       id="text2871"><tspan
  98.275 +         sodipodi:role="line"
  98.276 +         id="tspan2873"
  98.277 +         x="295.28571"
  98.278 +         y="211.80988">tip (and head)</tspan></text>
  98.279 +    <text
  98.280 +       xml:space="preserve"
  98.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"
  98.282 +       x="76"
  98.283 +       y="259.16046"
  98.284 +       id="text2875"><tspan
  98.285 +         sodipodi:role="line"
  98.286 +         id="tspan2877"
  98.287 +         x="76"
  98.288 +         y="259.16046"
  98.289 +         style="text-align:end;text-anchor:end">head</tspan></text>
  98.290 +  </g>
  98.291 +</svg>
    99.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    99.2 +++ b/fr/figs/tour-merge-sep-repos.svg	Sat Jul 10 06:24:49 2010 +0100
    99.3 @@ -0,0 +1,466 @@
    99.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
    99.5 +<!-- Created with Inkscape (http://www.inkscape.org/) -->
    99.6 +<svg
    99.7 +   xmlns:dc="http://purl.org/dc/elements/1.1/"
    99.8 +   xmlns:cc="http://web.resource.org/cc/"
    99.9 +   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   99.10 +   xmlns:svg="http://www.w3.org/2000/svg"
   99.11 +   xmlns="http://www.w3.org/2000/svg"
   99.12 +   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   99.13 +   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   99.14 +   width="744.09448819"
   99.15 +   height="1052.3622047"
   99.16 +   id="svg2"
   99.17 +   sodipodi:version="0.32"
   99.18 +   inkscape:version="0.44.1"
   99.19 +   sodipodi:docname="tour-merge-sep-repos.svg">
   99.20 +  <defs
   99.21 +     id="defs4">
   99.22 +    <marker
   99.23 +       inkscape:stockid="Arrow1Mstart"
   99.24 +       orient="auto"
   99.25 +       refY="0.0"
   99.26 +       refX="0.0"
   99.27 +       id="Arrow1Mstart"
   99.28 +       style="overflow:visible">
   99.29 +      <path
   99.30 +         id="path2973"
   99.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 "
   99.32 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
   99.33 +         transform="scale(0.4) translate(10,0)" />
   99.34 +    </marker>
   99.35 +    <marker
   99.36 +       inkscape:stockid="Arrow1Mend"
   99.37 +       orient="auto"
   99.38 +       refY="0.0"
   99.39 +       refX="0.0"
   99.40 +       id="Arrow1Mend"
   99.41 +       style="overflow:visible;">
   99.42 +      <path
   99.43 +         id="path3066"
   99.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 "
   99.45 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
   99.46 +         transform="scale(0.4) rotate(180) translate(10,0)" />
   99.47 +    </marker>
   99.48 +  </defs>
   99.49 +  <sodipodi:namedview
   99.50 +     id="base"
   99.51 +     pagecolor="#ffffff"
   99.52 +     bordercolor="#666666"
   99.53 +     borderopacity="1.0"
   99.54 +     gridtolerance="10000"
   99.55 +     guidetolerance="10"
   99.56 +     objecttolerance="10"
   99.57 +     inkscape:pageopacity="0.0"
   99.58 +     inkscape:pageshadow="2"
   99.59 +     inkscape:zoom="1.4"
   99.60 +     inkscape:cx="307.20351"
   99.61 +     inkscape:cy="716.87911"
   99.62 +     inkscape:document-units="px"
   99.63 +     inkscape:current-layer="layer1"
   99.64 +     inkscape:window-width="906"
   99.65 +     inkscape:window-height="620"
   99.66 +     inkscape:window-x="5"
   99.67 +     inkscape:window-y="49" />
   99.68 +  <metadata
   99.69 +     id="metadata7">
   99.70 +    <rdf:RDF>
   99.71 +      <cc:Work
   99.72 +         rdf:about="">
   99.73 +        <dc:format>image/svg+xml</dc:format>
   99.74 +        <dc:type
   99.75 +           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
   99.76 +      </cc:Work>
   99.77 +    </rdf:RDF>
   99.78 +  </metadata>
   99.79 +  <g
   99.80 +     inkscape:label="Layer 1"
   99.81 +     inkscape:groupmode="layer"
   99.82 +     id="layer1">
   99.83 +    <text
   99.84 +       xml:space="preserve"
   99.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"
   99.86 +       x="173.57143"
   99.87 +       y="443.79074"
   99.88 +       id="text2832"><tspan
   99.89 +         sodipodi:role="line"
   99.90 +         id="tspan2834"
   99.91 +         x="173.57143"
   99.92 +         y="443.79074" /></text>
   99.93 +    <rect
   99.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"
   99.95 +       id="rect1878"
   99.96 +       width="94.285713"
   99.97 +       height="20.714285"
   99.98 +       x="138"
   99.99 +       y="479.50504" />
  99.100 +    <text
  99.101 +       xml:space="preserve"
  99.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"
  99.103 +       x="162.09892"
  99.104 +       y="493.12619"
  99.105 +       id="text1872"><tspan
  99.106 +         sodipodi:role="line"
  99.107 +         id="tspan1874"
  99.108 +         x="162.09892"
  99.109 +         y="493.12619"
  99.110 +         style="font-family:Courier"><tspan
  99.111 +   style="font-weight:bold"
  99.112 +   id="tspan1876">0</tspan>: REV0</tspan></text>
  99.113 +    <rect
  99.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"
  99.115 +       id="rect2800"
  99.116 +       width="94.285713"
  99.117 +       height="20.714285"
  99.118 +       x="138"
  99.119 +       y="432.63004" />
  99.120 +    <text
  99.121 +       xml:space="preserve"
  99.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"
  99.123 +       x="162.09892"
  99.124 +       y="446.25119"
  99.125 +       id="text2794"><tspan
  99.126 +         sodipodi:role="line"
  99.127 +         id="tspan2796"
  99.128 +         x="162.09892"
  99.129 +         y="446.25119"
  99.130 +         style="font-family:Courier"><tspan
  99.131 +   id="tspan2868"
  99.132 +   style="font-weight:bold">1</tspan>: REV1</tspan></text>
  99.133 +    <rect
  99.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"
  99.135 +       id="rect2810"
  99.136 +       width="94.285713"
  99.137 +       height="20.714285"
  99.138 +       x="138"
  99.139 +       y="385.75504" />
  99.140 +    <text
  99.141 +       xml:space="preserve"
  99.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"
  99.143 +       x="162.09892"
  99.144 +       y="399.37619"
  99.145 +       id="text2804"><tspan
  99.146 +         sodipodi:role="line"
  99.147 +         id="tspan2806"
  99.148 +         x="162.09892"
  99.149 +         y="399.37619"
  99.150 +         style="font-family:Courier"><tspan
  99.151 +   style="font-weight:bold"
  99.152 +   id="tspan2866">2</tspan>: REV2</tspan></text>
  99.153 +    <rect
  99.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"
  99.155 +       id="rect2820"
  99.156 +       width="94.285713"
  99.157 +       height="20.714285"
  99.158 +       x="138"
  99.159 +       y="338.88007" />
  99.160 +    <text
  99.161 +       xml:space="preserve"
  99.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"
  99.163 +       x="162.09892"
  99.164 +       y="352.50122"
  99.165 +       id="text2814"><tspan
  99.166 +         sodipodi:role="line"
  99.167 +         id="tspan2816"
  99.168 +         x="162.09892"
  99.169 +         y="352.50122"
  99.170 +         style="font-family:Courier"><tspan
  99.171 +   style="font-weight:bold"
  99.172 +   id="tspan2864">3</tspan>: REV3</tspan></text>
  99.173 +    <rect
  99.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"
  99.175 +       id="rect2830"
  99.176 +       width="94.285713"
  99.177 +       height="20.714285"
  99.178 +       x="138"
  99.179 +       y="292.00504" />
  99.180 +    <text
  99.181 +       xml:space="preserve"
  99.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"
  99.183 +       x="162.09892"
  99.184 +       y="305.62619"
  99.185 +       id="text2824"><tspan
  99.186 +         sodipodi:role="line"
  99.187 +         id="tspan2826"
  99.188 +         x="162.09892"
  99.189 +         y="305.62619"
  99.190 +         style="font-family:Courier"><tspan
  99.191 +   style="font-weight:bold"
  99.192 +   id="tspan2862">4</tspan>: REV4</tspan></text>
  99.193 +    <path
  99.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"
  99.195 +       d="M 185.14286,478.50504 L 185.14286,454.34432"
  99.196 +       id="path2894"
  99.197 +       inkscape:connector-type="polyline" />
  99.198 +    <path
  99.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"
  99.200 +       d="M 185.14286,431.63004 L 185.14286,407.46932"
  99.201 +       id="path2896"
  99.202 +       inkscape:connector-type="polyline" />
  99.203 +    <path
  99.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"
  99.205 +       d="M 185.14286,384.75504 L 185.14286,360.59435"
  99.206 +       id="path2898"
  99.207 +       inkscape:connector-type="polyline" />
  99.208 +    <path
  99.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"
  99.210 +       d="M 185.14286,337.88007 L 185.14286,313.71932"
  99.211 +       id="path2900"
  99.212 +       inkscape:connector-type="polyline" />
  99.213 +    <rect
  99.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"
  99.215 +       id="rect1963"
  99.216 +       width="94.285995"
  99.217 +       height="20.714283"
  99.218 +       x="138"
  99.219 +       y="245.18723" />
  99.220 +    <text
  99.221 +       xml:space="preserve"
  99.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"
  99.223 +       x="162.09877"
  99.224 +       y="258.80865"
  99.225 +       id="text1965"
  99.226 +       transform="scale(1.000002,0.999998)"><tspan
  99.227 +         sodipodi:role="line"
  99.228 +         id="tspan1967"
  99.229 +         x="162.09877"
  99.230 +         y="258.80865"
  99.231 +         style="font-family:Courier"><tspan
  99.232 +   style="font-weight:bold"
  99.233 +   id="tspan1973">5</tspan>: REV_my_hello</tspan></text>
  99.234 +    <path
  99.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"
  99.236 +       d="M 185.143,291.06218 L 185.143,266.90143"
  99.237 +       id="path1971"
  99.238 +       inkscape:connector-type="polyline" />
  99.239 +    <text
  99.240 +       xml:space="preserve"
  99.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"
  99.242 +       x="136.90039"
  99.243 +       y="232.25546"
  99.244 +       id="text2921"><tspan
  99.245 +         sodipodi:role="line"
  99.246 +         id="tspan2923"
  99.247 +         x="136.90039"
  99.248 +         y="232.25546">my-hello</tspan></text>
  99.249 +    <rect
  99.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"
  99.251 +       id="rect2863"
  99.252 +       width="94.285713"
  99.253 +       height="20.714285"
  99.254 +       x="370.71414"
  99.255 +       y="479.49289" />
  99.256 +    <text
  99.257 +       xml:space="preserve"
  99.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"
  99.259 +       x="394.81305"
  99.260 +       y="493.11404"
  99.261 +       id="text2865"><tspan
  99.262 +         sodipodi:role="line"
  99.263 +         id="tspan2867"
  99.264 +         x="394.81305"
  99.265 +         y="493.11404"
  99.266 +         style="font-family:Courier"><tspan
  99.267 +   style="font-weight:bold"
  99.268 +   id="tspan2869">0</tspan>: REV0</tspan></text>
  99.269 +    <rect
  99.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"
  99.271 +       id="rect2871"
  99.272 +       width="94.285713"
  99.273 +       height="20.714285"
  99.274 +       x="370.71414"
  99.275 +       y="432.61789" />
  99.276 +    <text
  99.277 +       xml:space="preserve"
  99.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"
  99.279 +       x="394.81305"
  99.280 +       y="446.23904"
  99.281 +       id="text2873"><tspan
  99.282 +         sodipodi:role="line"
  99.283 +         id="tspan2875"
  99.284 +         x="394.81305"
  99.285 +         y="446.23904"
  99.286 +         style="font-family:Courier"><tspan
  99.287 +   id="tspan2877"
  99.288 +   style="font-weight:bold">1</tspan>: REV1</tspan></text>
  99.289 +    <rect
  99.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"
  99.291 +       id="rect2879"
  99.292 +       width="94.285713"
  99.293 +       height="20.714285"
  99.294 +       x="370.71414"
  99.295 +       y="385.74289" />
  99.296 +    <text
  99.297 +       xml:space="preserve"
  99.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"
  99.299 +       x="394.81305"
  99.300 +       y="399.36404"
  99.301 +       id="text2881"><tspan
  99.302 +         sodipodi:role="line"
  99.303 +         id="tspan2883"
  99.304 +         x="394.81305"
  99.305 +         y="399.36404"
  99.306 +         style="font-family:Courier"><tspan
  99.307 +   style="font-weight:bold"
  99.308 +   id="tspan2885">2</tspan>: REV2</tspan></text>
  99.309 +    <rect
  99.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"
  99.311 +       id="rect2887"
  99.312 +       width="94.285713"
  99.313 +       height="20.714285"
  99.314 +       x="370.71414"
  99.315 +       y="338.86792" />
  99.316 +    <text
  99.317 +       xml:space="preserve"
  99.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"
  99.319 +       x="394.81305"
  99.320 +       y="352.48907"
  99.321 +       id="text2889"><tspan
  99.322 +         sodipodi:role="line"
  99.323 +         id="tspan2891"
  99.324 +         x="394.81305"
  99.325 +         y="352.48907"
  99.326 +         style="font-family:Courier"><tspan
  99.327 +   style="font-weight:bold"
  99.328 +   id="tspan2893">3</tspan>: REV3</tspan></text>
  99.329 +    <rect
  99.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"
  99.331 +       id="rect2895"
  99.332 +       width="94.285713"
  99.333 +       height="20.714285"
  99.334 +       x="370.71414"
  99.335 +       y="291.99289" />
  99.336 +    <text
  99.337 +       xml:space="preserve"
  99.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"
  99.339 +       x="394.81305"
  99.340 +       y="305.61404"
  99.341 +       id="text2897"><tspan
  99.342 +         sodipodi:role="line"
  99.343 +         id="tspan2899"
  99.344 +         x="394.81305"
  99.345 +         y="305.61404"
  99.346 +         style="font-family:Courier"><tspan
  99.347 +   style="font-weight:bold"
  99.348 +   id="tspan2901">4</tspan>: REV4</tspan></text>
  99.349 +    <path
  99.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"
  99.351 +       d="M 417.85701,478.4929 L 417.85701,454.33218"
  99.352 +       id="path2903"
  99.353 +       inkscape:connector-type="polyline" />
  99.354 +    <path
  99.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"
  99.356 +       d="M 417.85701,431.6179 L 417.85701,407.45718"
  99.357 +       id="path2905"
  99.358 +       inkscape:connector-type="polyline" />
  99.359 +    <path
  99.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"
  99.361 +       d="M 417.85701,384.7429 L 417.85701,360.58221"
  99.362 +       id="path2907"
  99.363 +       inkscape:connector-type="polyline" />
  99.364 +    <path
  99.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"
  99.366 +       d="M 417.85701,337.86793 L 417.85701,313.70718"
  99.367 +       id="path2909"
  99.368 +       inkscape:connector-type="polyline" />
  99.369 +    <rect
  99.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"
  99.371 +       id="rect2911"
  99.372 +       width="94.285995"
  99.373 +       height="20.714283"
  99.374 +       x="370.71414"
  99.375 +       y="245.17511" />
  99.376 +    <text
  99.377 +       xml:space="preserve"
  99.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"
  99.379 +       x="394.81274"
  99.380 +       y="258.79678"
  99.381 +       id="text2913"
  99.382 +       transform="scale(1.000002,0.999998)"><tspan
  99.383 +         sodipodi:role="line"
  99.384 +         id="tspan2915"
  99.385 +         x="394.81274"
  99.386 +         y="258.79678"
  99.387 +         style="font-family:Courier"><tspan
  99.388 +   style="font-weight:bold"
  99.389 +   id="tspan2917">5</tspan>: REV_my_new_hello</tspan></text>
  99.390 +    <path
  99.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"
  99.392 +       d="M 417.85715,291.05004 L 417.85715,266.88929"
  99.393 +       id="path2919"
  99.394 +       inkscape:connector-type="polyline" />
  99.395 +    <text
  99.396 +       xml:space="preserve"
  99.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"
  99.398 +       x="369.61453"
  99.399 +       y="232.25546"
  99.400 +       id="text2925"><tspan
  99.401 +         sodipodi:role="line"
  99.402 +         id="tspan2927"
  99.403 +         x="369.61453"
  99.404 +         y="232.25546">my-new-hello</tspan></text>
  99.405 +    <text
  99.406 +       xml:space="preserve"
  99.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"
  99.408 +       x="300.54352"
  99.409 +       y="252.12723"
  99.410 +       id="text2933"><tspan
  99.411 +         sodipodi:role="line"
  99.412 +         id="tspan2935"
  99.413 +         x="300.54352"
  99.414 +         y="252.12723"
  99.415 +         style="text-align:center;text-anchor:middle">newest changes</tspan><tspan
  99.416 +         sodipodi:role="line"
  99.417 +         x="300.54352"
  99.418 +         y="267.12723"
  99.419 +         style="text-align:center;text-anchor:middle"
  99.420 +         id="tspan3132">differ</tspan></text>
  99.421 +    <text
  99.422 +       xml:space="preserve"
  99.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"
  99.424 +       x="262.15436"
  99.425 +       y="398.37112"
  99.426 +       id="text2929"><tspan
  99.427 +         sodipodi:role="line"
  99.428 +         x="262.15436"
  99.429 +         y="398.37112"
  99.430 +         id="tspan3013"
  99.431 +         style="text-align:start;text-anchor:start">common history</tspan></text>
  99.432 +    <g
  99.433 +       id="g3107"
  99.434 +       transform="translate(0,0.855744)">
  99.435 +      <path
  99.436 +         id="path3101"
  99.437 +         d="M 300.35713,381.29075 L 300.35713,304.50504"
  99.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" />
  99.439 +      <path
  99.440 +         id="path3105"
  99.441 +         d="M 291.07142,301.64789 L 309.28571,301.64789"
  99.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" />
  99.443 +    </g>
  99.444 +    <path
  99.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"
  99.446 +       d="M 300.53571,486.38926 L 300.53571,409.60355"
  99.447 +       id="path3113" />
  99.448 +    <path
  99.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"
  99.450 +       d="M 291.25,488.49641 L 309.46429,488.49641"
  99.451 +       id="path3115" />
  99.452 +    <text
  99.453 +       xml:space="preserve"
  99.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"
  99.455 +       x="480.71429"
  99.456 +       y="250.91507"
  99.457 +       id="text1949"><tspan
  99.458 +         sodipodi:role="line"
  99.459 +         id="tspan1951"
  99.460 +         x="480.71429"
  99.461 +         y="250.91507"
  99.462 +         style="text-align:start;text-anchor:start">head revision</tspan><tspan
  99.463 +         sodipodi:role="line"
  99.464 +         x="480.71429"
  99.465 +         y="265.91507"
  99.466 +         id="tspan1953"
  99.467 +         style="text-align:start;text-anchor:start">(has no children)</tspan></text>
  99.468 +  </g>
  99.469 +</svg>
   100.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   100.2 +++ b/fr/figs/undo-manual-merge.dot	Sat Jul 10 06:24:49 2010 +0100
   100.3 @@ -0,0 +1,8 @@
   100.4 +digraph undo_manual {
   100.5 +	"first change" -> "second change";
   100.6 +	"second change" -> "third change";
   100.7 +	backout [label="back out\nsecond change", shape=box];
   100.8 +	"second change" -> backout;
   100.9 +	"third change" -> "manual\nmerge";
  100.10 +	backout -> "manual\nmerge";
  100.11 +}
   101.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   101.2 +++ b/fr/figs/undo-manual.dot	Sat Jul 10 06:24:49 2010 +0100
   101.3 @@ -0,0 +1,6 @@
   101.4 +digraph undo_manual {
   101.5 +	"first change" -> "second change";
   101.6 +	"second change" -> "third change";
   101.7 +	backout [label="back out\nsecond change", shape=box];
   101.8 +	"second change" -> backout;
   101.9 +}
   102.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   102.2 +++ b/fr/figs/undo-non-tip.dot	Sat Jul 10 06:24:49 2010 +0100
   102.3 @@ -0,0 +1,9 @@
   102.4 +digraph undo_non_tip {
   102.5 +	"first change" -> "second change";
   102.6 +	"second change" -> "third change";
   102.7 +	backout [label="back out\nsecond change", shape=box];
   102.8 +	"second change" -> backout;
   102.9 +	merge [label="automated\nmerge", shape=box];
  102.10 +	"third change" -> merge;
  102.11 +	backout -> merge;
  102.12 +}
   103.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   103.2 +++ b/fr/figs/undo-simple.dot	Sat Jul 10 06:24:49 2010 +0100
   103.3 @@ -0,0 +1,4 @@
   103.4 +digraph undo_simple {
   103.5 +	"first change" -> "second change";
   103.6 +	"second change" -> "back out\nsecond change";
   103.7 +}
   104.1 Binary file fr/figs/warning.png has changed
   105.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   105.2 +++ b/fr/figs/wdir-after-commit.svg	Sat Jul 10 06:24:49 2010 +0100
   105.3 @@ -0,0 +1,394 @@
   105.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
   105.5 +<!-- Created with Inkscape (http://www.inkscape.org/) -->
   105.6 +<svg
   105.7 +   xmlns:dc="http://purl.org/dc/elements/1.1/"
   105.8 +   xmlns:cc="http://web.resource.org/cc/"
   105.9 +   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  105.10 +   xmlns:svg="http://www.w3.org/2000/svg"
  105.11 +   xmlns="http://www.w3.org/2000/svg"
  105.12 +   xmlns:xlink="http://www.w3.org/1999/xlink"
  105.13 +   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
  105.14 +   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
  105.15 +   width="744.09448819"
  105.16 +   height="1052.3622047"
  105.17 +   id="svg5971"
  105.18 +   sodipodi:version="0.32"
  105.19 +   inkscape:version="0.44.1"
  105.20 +   sodipodi:docbase="/home/bos/hg/hgbook/en"
  105.21 +   sodipodi:docname="wdir-after-commit.svg">
  105.22 +  <defs
  105.23 +     id="defs5973">
  105.24 +    <linearGradient
  105.25 +       inkscape:collect="always"
  105.26 +       xlink:href="#linearGradient6049"
  105.27 +       id="linearGradient6445"
  105.28 +       gradientUnits="userSpaceOnUse"
  105.29 +       gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)"
  105.30 +       x1="333.91171"
  105.31 +       y1="488.79077"
  105.32 +       x2="508.94543"
  105.33 +       y2="263.79077" />
  105.34 +    <marker
  105.35 +       inkscape:stockid="Arrow1Mstart"
  105.36 +       orient="auto"
  105.37 +       refY="0.0"
  105.38 +       refX="0.0"
  105.39 +       id="Arrow1Mstart"
  105.40 +       style="overflow:visible">
  105.41 +      <path
  105.42 +         id="path4855"
  105.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 "
  105.44 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
  105.45 +         transform="scale(0.4) translate(10,0)" />
  105.46 +    </marker>
  105.47 +    <linearGradient
  105.48 +       id="linearGradient6049">
  105.49 +      <stop
  105.50 +         style="stop-color:#686868;stop-opacity:1;"
  105.51 +         offset="0"
  105.52 +         id="stop6051" />
  105.53 +      <stop
  105.54 +         style="stop-color:#f0f0f0;stop-opacity:1;"
  105.55 +         offset="1"
  105.56 +         id="stop6053" />
  105.57 +    </linearGradient>
  105.58 +    <marker
  105.59 +       inkscape:stockid="Arrow1Mend"
  105.60 +       orient="auto"
  105.61 +       refY="0.0"
  105.62 +       refX="0.0"
  105.63 +       id="Arrow1Mend"
  105.64 +       style="overflow:visible;">
  105.65 +      <path
  105.66 +         id="path4852"
  105.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 "
  105.68 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
  105.69 +         transform="scale(0.4) rotate(180) translate(10,0)" />
  105.70 +    </marker>
  105.71 +    <linearGradient
  105.72 +       inkscape:collect="always"
  105.73 +       xlink:href="#linearGradient6049"
  105.74 +       id="linearGradient6083"
  105.75 +       gradientUnits="userSpaceOnUse"
  105.76 +       gradientTransform="translate(-240.0462,-8.633237e-6)"
  105.77 +       x1="333.91171"
  105.78 +       y1="488.79077"
  105.79 +       x2="508.94543"
  105.80 +       y2="263.79077" />
  105.81 +    <linearGradient
  105.82 +       inkscape:collect="always"
  105.83 +       xlink:href="#linearGradient6049"
  105.84 +       id="linearGradient6142"
  105.85 +       gradientUnits="userSpaceOnUse"
  105.86 +       gradientTransform="translate(-42.00893,-30.49544)"
  105.87 +       x1="333.91171"
  105.88 +       y1="488.79077"
  105.89 +       x2="508.94543"
  105.90 +       y2="263.79077" />
  105.91 +    <linearGradient
  105.92 +       inkscape:collect="always"
  105.93 +       xlink:href="#linearGradient6049"
  105.94 +       id="linearGradient6193"
  105.95 +       gradientUnits="userSpaceOnUse"
  105.96 +       gradientTransform="translate(-240.0462,-8.633237e-6)"
  105.97 +       x1="333.91171"
  105.98 +       y1="488.79077"
  105.99 +       x2="508.94543"
 105.100 +       y2="263.79077" />
 105.101 +    <linearGradient
 105.102 +       inkscape:collect="always"
 105.103 +       xlink:href="#linearGradient6049"
 105.104 +       id="linearGradient6216"
 105.105 +       gradientUnits="userSpaceOnUse"
 105.106 +       gradientTransform="translate(-6.0462,-0.664361)"
 105.107 +       x1="333.91171"
 105.108 +       y1="488.79077"
 105.109 +       x2="508.94543"
 105.110 +       y2="263.79077" />
 105.111 +    <linearGradient
 105.112 +       inkscape:collect="always"
 105.113 +       xlink:href="#linearGradient6049"
 105.114 +       id="linearGradient6232"
 105.115 +       gradientUnits="userSpaceOnUse"
 105.116 +       gradientTransform="matrix(1.000474,0,0,0.790947,222.8399,50.85693)"
 105.117 +       x1="333.91171"
 105.118 +       y1="488.79077"
 105.119 +       x2="508.94543"
 105.120 +       y2="263.79077" />
 105.121 +    <linearGradient
 105.122 +       inkscape:collect="always"
 105.123 +       xlink:href="#linearGradient6049"
 105.124 +       id="linearGradient6772"
 105.125 +       gradientUnits="userSpaceOnUse"
 105.126 +       gradientTransform="matrix(1.000474,0,0,0.790947,222.8399,50.85693)"
 105.127 +       x1="333.91171"
 105.128 +       y1="488.79077"
 105.129 +       x2="508.94543"
 105.130 +       y2="263.79077" />
 105.131 +  </defs>
 105.132 +  <sodipodi:namedview
 105.133 +     id="base"
 105.134 +     pagecolor="#ffffff"
 105.135 +     bordercolor="#666666"
 105.136 +     borderopacity="1.0"
 105.137 +     gridtolerance="10000"
 105.138 +     guidetolerance="10"
 105.139 +     objecttolerance="10"
 105.140 +     inkscape:pageopacity="0.0"
 105.141 +     inkscape:pageshadow="2"
 105.142 +     inkscape:zoom="0.90509668"
 105.143 +     inkscape:cx="390.0539"
 105.144 +     inkscape:cy="690.49342"
 105.145 +     inkscape:document-units="px"
 105.146 +     inkscape:current-layer="layer1"
 105.147 +     showguides="true"
 105.148 +     inkscape:guide-bbox="true"
 105.149 +     inkscape:window-width="906"
 105.150 +     inkscape:window-height="620"
 105.151 +     inkscape:window-x="0"
 105.152 +     inkscape:window-y="25">
 105.153 +    <sodipodi:guide
 105.154 +       orientation="vertical"
 105.155 +       position="-1.4285714"
 105.156 +       id="guide6022" />
 105.157 +  </sodipodi:namedview>
 105.158 +  <metadata
 105.159 +     id="metadata5976">
 105.160 +    <rdf:RDF>
 105.161 +      <cc:Work
 105.162 +         rdf:about="">
 105.163 +        <dc:format>image/svg+xml</dc:format>
 105.164 +        <dc:type
 105.165 +           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
 105.166 +      </cc:Work>
 105.167 +    </rdf:RDF>
 105.168 +  </metadata>
 105.169 +  <g
 105.170 +     inkscape:label="Layer 1"
 105.171 +     inkscape:groupmode="layer"
 105.172 +     id="layer1">
 105.173 +    <rect
 105.174 +       y="245.98355"
 105.175 +       x="328.23956"
 105.176 +       height="258.57144"
 105.177 +       width="174.28572"
 105.178 +       id="rect6047"
 105.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" />
 105.180 +    <g
 105.181 +       id="g6261"
 105.182 +       transform="translate(234,0)">
 105.183 +      <rect
 105.184 +         y="258.7149"
 105.185 +         x="114.11369"
 105.186 +         height="44.537449"
 105.187 +         width="134.53746"
 105.188 +         id="rect5983"
 105.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" />
 105.190 +      <text
 105.191 +         id="text5985"
 105.192 +         y="284.47562"
 105.193 +         x="138.7962"
 105.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"
 105.195 +         xml:space="preserve"><tspan
 105.196 +           style="font-family:Courier"
 105.197 +           y="284.47562"
 105.198 +           x="138.7962"
 105.199 +           id="tspan5987"
 105.200 +           sodipodi:role="line">dfbbb33f3fa3</tspan></text>
 105.201 +    </g>
 105.202 +    <rect
 105.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"
 105.204 +       id="rect5996"
 105.205 +       width="134.53746"
 105.206 +       height="44.537449"
 105.207 +       x="348.11371"
 105.208 +       y="320.38159" />
 105.209 +    <text
 105.210 +       xml:space="preserve"
 105.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"
 105.212 +       x="372.7962"
 105.213 +       y="346.1423"
 105.214 +       id="text5998"><tspan
 105.215 +         sodipodi:role="line"
 105.216 +         id="tspan6000"
 105.217 +         x="372.7962"
 105.218 +         y="346.1423"
 105.219 +         style="font-family:Courier">e7639888bb2f</tspan></text>
 105.220 +    <rect
 105.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"
 105.222 +       id="rect6004"
 105.223 +       width="134.53746"
 105.224 +       height="44.537449"
 105.225 +       x="348.11371"
 105.226 +       y="382.04825" />
 105.227 +    <text
 105.228 +       xml:space="preserve"
 105.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"
 105.230 +       x="370.65421"
 105.231 +       y="407.80896"
 105.232 +       id="text6006"><tspan
 105.233 +         sodipodi:role="line"
 105.234 +         id="tspan6008"
 105.235 +         x="370.65421"
 105.236 +         y="407.80896"
 105.237 +         style="font-family:Courier">7b064d8bac5e</tspan></text>
 105.238 +    <path
 105.239 +       inkscape:connector-type="polyline"
 105.240 +       id="path6018"
 105.241 +       d="M 415.38242,303.62646 L 415.38242,320.00744"
 105.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" />
 105.243 +    <path
 105.244 +       inkscape:connection-end="#rect6004"
 105.245 +       inkscape:connector-type="polyline"
 105.246 +       id="path6020"
 105.247 +       d="M 415.38242,365.29315 L 415.38243,381.67412"
 105.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" />
 105.249 +    <rect
 105.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"
 105.251 +       id="rect6039"
 105.252 +       width="134.53746"
 105.253 +       height="44.537449"
 105.254 +       x="348.11359"
 105.255 +       y="443.71487" />
 105.256 +    <text
 105.257 +       xml:space="preserve"
 105.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"
 105.259 +       x="372.79706"
 105.260 +       y="469.47556"
 105.261 +       id="text6041"><tspan
 105.262 +         sodipodi:role="line"
 105.263 +         id="tspan6043"
 105.264 +         x="372.79706"
 105.265 +         y="469.47556"
 105.266 +         style="fill:#979797;fill-opacity:1;font-family:Courier">000000000000</tspan></text>
 105.267 +    <path
 105.268 +       inkscape:connection-end="#rect6039"
 105.269 +       inkscape:connector-type="polyline"
 105.270 +       id="path6045"
 105.271 +       d="M 415.38238,426.95981 L 415.38235,443.34087"
 105.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" />
 105.273 +    <text
 105.274 +       xml:space="preserve"
 105.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"
 105.276 +       x="327.66046"
 105.277 +       y="231.36218"
 105.278 +       id="text6102"><tspan
 105.279 +         sodipodi:role="line"
 105.280 +         id="tspan6104"
 105.281 +         x="327.66046"
 105.282 +         y="231.36218">History in repository</tspan></text>
 105.283 +    <rect
 105.284 +       y="245.94225"
 105.285 +       x="557.28418"
 105.286 +       height="204.51619"
 105.287 +       width="174.36833"
 105.288 +       id="rect6140"
 105.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" />
 105.290 +    <g
 105.291 +       id="g6130"
 105.292 +       transform="translate(262.3254,24.38544)">
 105.293 +      <rect
 105.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"
 105.295 +         id="rect6106"
 105.296 +         width="134.53746"
 105.297 +         height="44.537449"
 105.298 +         x="314.87415"
 105.299 +         y="257.95059" />
 105.300 +      <text
 105.301 +         xml:space="preserve"
 105.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"
 105.303 +         x="339.55664"
 105.304 +         y="283.7113"
 105.305 +         id="text6108"><tspan
 105.306 +           sodipodi:role="line"
 105.307 +           id="tspan6110"
 105.308 +           x="339.55664"
 105.309 +           y="283.7113"
 105.310 +           style="font-family:Courier">dfbbb33f3fa3</tspan></text>
 105.311 +    </g>
 105.312 +    <g
 105.313 +       id="g6135"
 105.314 +       transform="translate(263.0396,49.83106)">
 105.315 +      <rect
 105.316 +         inkscape:transform-center-y="102.85714"
 105.317 +         inkscape:transform-center-x="129.28571"
 105.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"
 105.319 +         id="rect6112"
 105.320 +         width="134.53746"
 105.321 +         height="44.537449"
 105.322 +         x="314.15985"
 105.323 +         y="326.52203" />
 105.324 +      <text
 105.325 +         inkscape:transform-center-y="102.7311"
 105.326 +         inkscape:transform-center-x="128.69672"
 105.327 +         xml:space="preserve"
 105.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"
 105.329 +         x="338.84335"
 105.330 +         y="352.28271"
 105.331 +         id="text6114"><tspan
 105.332 +           sodipodi:role="line"
 105.333 +           id="tspan6116"
 105.334 +           x="338.84335"
 105.335 +           y="352.28271"
 105.336 +           style="fill:#979797;fill-opacity:1;font-family:Courier">000000000000</tspan></text>
 105.337 +    </g>
 105.338 +    <text
 105.339 +       xml:space="preserve"
 105.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"
 105.341 +       x="576.63208"
 105.342 +       y="270.479"
 105.343 +       id="text6118"><tspan
 105.344 +         sodipodi:role="line"
 105.345 +         id="tspan6120"
 105.346 +         x="576.63208"
 105.347 +         y="270.479">First parent</tspan></text>
 105.348 +    <text
 105.349 +       xml:space="preserve"
 105.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"
 105.351 +       x="576.07544"
 105.352 +       y="364.49615"
 105.353 +       id="text6122"><tspan
 105.354 +         sodipodi:role="line"
 105.355 +         id="tspan6124"
 105.356 +         x="576.07544"
 105.357 +         y="364.49615">Second parent</tspan></text>
 105.358 +    <text
 105.359 +       xml:space="preserve"
 105.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"
 105.361 +       x="556.61743"
 105.362 +       y="231.36218"
 105.363 +       id="text6195"><tspan
 105.364 +         sodipodi:role="line"
 105.365 +         id="tspan6197"
 105.366 +         x="556.61743"
 105.367 +         y="231.36218">Parents of working directory</tspan></text>
 105.368 +    <path
 105.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"
 105.370 +       d="M 576.82542,297.63008 L 483.02528,287.95831"
 105.371 +       id="path6266"
 105.372 +       inkscape:connector-type="polyline"
 105.373 +       inkscape:connection-start="#g6130"
 105.374 +       inkscape:connection-end="#g6261" />
 105.375 +    <path
 105.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"
 105.377 +       d="M 665.12232,418.17579 L 665.12232,418.17579"
 105.378 +       id="path6270"
 105.379 +       inkscape:connector-type="polyline" />
 105.380 +    <text
 105.381 +       xml:space="preserve"
 105.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"
 105.383 +       x="316.86407"
 105.384 +       y="275.6496"
 105.385 +       id="text6573"><tspan
 105.386 +         sodipodi:role="line"
 105.387 +         id="tspan6575"
 105.388 +         x="316.86407"
 105.389 +         y="275.6496"
 105.390 +         style="text-align:end;text-anchor:end">New</tspan><tspan
 105.391 +         sodipodi:role="line"
 105.392 +         x="316.86407"
 105.393 +         y="290.6496"
 105.394 +         id="tspan6577"
 105.395 +         style="text-align:end;text-anchor:end">changeset</tspan></text>
 105.396 +  </g>
 105.397 +</svg>
   106.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   106.2 +++ b/fr/figs/wdir-branch.svg	Sat Jul 10 06:24:49 2010 +0100
   106.3 @@ -0,0 +1,418 @@
   106.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
   106.5 +<!-- Created with Inkscape (http://www.inkscape.org/) -->
   106.6 +<svg
   106.7 +   xmlns:dc="http://purl.org/dc/elements/1.1/"
   106.8 +   xmlns:cc="http://web.resource.org/cc/"
   106.9 +   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  106.10 +   xmlns:svg="http://www.w3.org/2000/svg"
  106.11 +   xmlns="http://www.w3.org/2000/svg"
  106.12 +   xmlns:xlink="http://www.w3.org/1999/xlink"
  106.13 +   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
  106.14 +   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
  106.15 +   width="744.09448819"
  106.16 +   height="1052.3622047"
  106.17 +   id="svg5971"
  106.18 +   sodipodi:version="0.32"
  106.19 +   inkscape:version="0.44.1"
  106.20 +   sodipodi:docbase="/home/bos/hg/hgbook/en"
  106.21 +   sodipodi:docname="wdir-branch.svg">
  106.22 +  <defs
  106.23 +     id="defs5973">
  106.24 +    <marker
  106.25 +       inkscape:stockid="Arrow1Mstart"
  106.26 +       orient="auto"
  106.27 +       refY="0.0"
  106.28 +       refX="0.0"
  106.29 +       id="Arrow1Mstart"
  106.30 +       style="overflow:visible">
  106.31 +      <path
  106.32 +         id="path4855"
  106.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 "
  106.34 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
  106.35 +         transform="scale(0.4) translate(10,0)" />
  106.36 +    </marker>
  106.37 +    <linearGradient
  106.38 +       id="linearGradient6049">
  106.39 +      <stop
  106.40 +         style="stop-color:#686868;stop-opacity:1;"
  106.41 +         offset="0"
  106.42 +         id="stop6051" />
  106.43 +      <stop
  106.44 +         style="stop-color:#f0f0f0;stop-opacity:1;"
  106.45 +         offset="1"
  106.46 +         id="stop6053" />
  106.47 +    </linearGradient>
  106.48 +    <marker
  106.49 +       inkscape:stockid="Arrow1Mend"
  106.50 +       orient="auto"
  106.51 +       refY="0.0"
  106.52 +       refX="0.0"
  106.53 +       id="Arrow1Mend"
  106.54 +       style="overflow:visible;">
  106.55 +      <path
  106.56 +         id="path4852"
  106.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 "
  106.58 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
  106.59 +         transform="scale(0.4) rotate(180) translate(10,0)" />
  106.60 +    </marker>
  106.61 +    <linearGradient
  106.62 +       inkscape:collect="always"
  106.63 +       xlink:href="#linearGradient6049"
  106.64 +       id="linearGradient6083"
  106.65 +       gradientUnits="userSpaceOnUse"
  106.66 +       gradientTransform="translate(-240.0462,-8.633237e-6)"
  106.67 +       x1="333.91171"
  106.68 +       y1="488.79077"
  106.69 +       x2="508.94543"
  106.70 +       y2="263.79077" />
  106.71 +    <linearGradient
  106.72 +       inkscape:collect="always"
  106.73 +       xlink:href="#linearGradient6049"
  106.74 +       id="linearGradient6142"
  106.75 +       gradientUnits="userSpaceOnUse"
  106.76 +       gradientTransform="translate(-42.00893,-30.49544)"
  106.77 +       x1="333.91171"
  106.78 +       y1="488.79077"
  106.79 +       x2="508.94543"
  106.80 +       y2="263.79077" />
  106.81 +    <linearGradient
  106.82 +       inkscape:collect="always"
  106.83 +       xlink:href="#linearGradient6049"
  106.84 +       id="linearGradient6193"
  106.85 +       gradientUnits="userSpaceOnUse"
  106.86 +       gradientTransform="translate(-240.0462,-8.633237e-6)"
  106.87 +       x1="333.91171"
  106.88 +       y1="488.79077"
  106.89 +       x2="508.94543"
  106.90 +       y2="263.79077" />
  106.91 +    <linearGradient
  106.92 +       inkscape:collect="always"
  106.93 +       xlink:href="#linearGradient6049"
  106.94 +       id="linearGradient6216"
  106.95 +       gradientUnits="userSpaceOnUse"
  106.96 +       gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)"
  106.97 +       x1="333.91171"
  106.98 +       y1="488.79077"
  106.99 +       x2="508.94543"
 106.100 +       y2="263.79077" />
 106.101 +    <linearGradient
 106.102 +       inkscape:collect="always"
 106.103 +       xlink:href="#linearGradient6049"
 106.104 +       id="linearGradient6232"
 106.105 +       gradientUnits="userSpaceOnUse"
 106.106 +       gradientTransform="matrix(1.000473,0,0,0.790947,-11.16012,50.85693)"
 106.107 +       x1="333.91171"
 106.108 +       y1="488.79077"
 106.109 +       x2="508.94543"
 106.110 +       y2="263.79077" />
 106.111 +    <linearGradient
 106.112 +       inkscape:collect="always"
 106.113 +       xlink:href="#linearGradient6049"
 106.114 +       id="linearGradient6445"
 106.115 +       gradientUnits="userSpaceOnUse"
 106.116 +       gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)"
 106.117 +       x1="333.91171"
 106.118 +       y1="488.79077"
 106.119 +       x2="508.94543"
 106.120 +       y2="263.79077" />
 106.121 +    <linearGradient
 106.122 +       inkscape:collect="always"
 106.123 +       xlink:href="#linearGradient6049"
 106.124 +       id="linearGradient6974"
 106.125 +       gradientUnits="userSpaceOnUse"
 106.126 +       gradientTransform="matrix(1.911882,0,0,0.789965,-574.7896,51.22599)"
 106.127 +       x1="333.91171"
 106.128 +       y1="488.79077"
 106.129 +       x2="508.94543"
 106.130 +       y2="263.79077" />
 106.131 +    <linearGradient
 106.132 +       inkscape:collect="always"
 106.133 +       xlink:href="#linearGradient6049"
 106.134 +       id="linearGradient6996"
 106.135 +       gradientUnits="userSpaceOnUse"
 106.136 +       gradientTransform="matrix(1.000473,0,0,0.790947,112.8399,50.85693)"
 106.137 +       x1="333.91171"
 106.138 +       y1="488.79077"
 106.139 +       x2="508.94543"
 106.140 +       y2="263.79077" />
 106.141 +  </defs>
 106.142 +  <sodipodi:namedview
 106.143 +     id="base"
 106.144 +     pagecolor="#ffffff"
 106.145 +     bordercolor="#666666"
 106.146 +     borderopacity="1.0"
 106.147 +     gridtolerance="10000"
 106.148 +     guidetolerance="10"
 106.149 +     objecttolerance="10"
 106.150 +     inkscape:pageopacity="0.0"
 106.151 +     inkscape:pageshadow="2"
 106.152 +     inkscape:zoom="0.90509668"
 106.153 +     inkscape:cx="345.85973"
 106.154 +     inkscape:cy="690.49342"
 106.155 +     inkscape:document-units="px"
 106.156 +     inkscape:current-layer="layer1"
 106.157 +     showguides="true"
 106.158 +     inkscape:guide-bbox="true"
 106.159 +     inkscape:window-width="906"
 106.160 +     inkscape:window-height="620"
 106.161 +     inkscape:window-x="0"
 106.162 +     inkscape:window-y="25">
 106.163 +    <sodipodi:guide
 106.164 +       orientation="vertical"
 106.165 +       position="-1.4285714"
 106.166 +       id="guide6022" />
 106.167 +  </sodipodi:namedview>
 106.168 +  <metadata
 106.169 +     id="metadata5976">
 106.170 +    <rdf:RDF>
 106.171 +      <cc:Work
 106.172 +         rdf:about="">
 106.173 +        <dc:format>image/svg+xml</dc:format>
 106.174 +        <dc:type
 106.175 +           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
 106.176 +      </cc:Work>
 106.177 +    </rdf:RDF>
 106.178 +  </metadata>
 106.179 +  <g
 106.180 +     inkscape:label="Layer 1"
 106.181 +     inkscape:groupmode="layer"
 106.182 +     id="layer1">
 106.183 +    <rect
 106.184 +       y="246.06918"
 106.185 +       x="64.325172"
 106.186 +       height="204.26233"
 106.187 +       width="333.2135"
 106.188 +       id="rect6047"
 106.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" />
 106.190 +    <g
 106.191 +       id="g1935">
 106.192 +      <rect
 106.193 +         y="266.24374"
 106.194 +         x="84.113708"
 106.195 +         height="44.537449"
 106.196 +         width="134.53746"
 106.197 +         id="rect5996"
 106.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" />
 106.199 +      <text
 106.200 +         id="text5998"
 106.201 +         y="292.00446"
 106.202 +         x="108.7962"
 106.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"
 106.204 +         xml:space="preserve"><tspan
 106.205 +           style="font-family:Courier"
 106.206 +           y="292.00446"
 106.207 +           x="108.7962"
 106.208 +           id="tspan6000"
 106.209 +           sodipodi:role="line">e7639888bb2f</tspan></text>
 106.210 +    </g>
 106.211 +    <g
 106.212 +       id="g6976"
 106.213 +       transform="translate(70,0)">
 106.214 +      <rect
 106.215 +         y="327.9104"
 106.216 +         x="40.113693"
 106.217 +         height="44.537449"
 106.218 +         width="134.53746"
 106.219 +         id="rect6004"
 106.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" />
 106.221 +      <text
 106.222 +         id="text6006"
 106.223 +         y="353.67111"
 106.224 +         x="62.654205"
 106.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"
 106.226 +         xml:space="preserve"><tspan
 106.227 +           style="font-family:Courier"
 106.228 +           y="353.67111"
 106.229 +           x="62.654205"
 106.230 +           id="tspan6008"
 106.231 +           sodipodi:role="line">7b064d8bac5e</tspan></text>
 106.232 +    </g>
 106.233 +    <path
 106.234 +       inkscape:connector-type="polyline"
 106.235 +       id="path6020"
 106.236 +       d="M 160.92915,311.15532 L 167.83571,327.53627"
 106.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"
 106.238 +       inkscape:connection-end="#g6976"
 106.239 +       inkscape:connection-start="#g1935" />
 106.240 +    <rect
 106.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"
 106.242 +       id="rect6039"
 106.243 +       width="134.53746"
 106.244 +       height="44.537449"
 106.245 +       x="110.11359"
 106.246 +       y="389.57703" />
 106.247 +    <text
 106.248 +       xml:space="preserve"
 106.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"
 106.250 +       x="134.79706"
 106.251 +       y="415.33771"
 106.252 +       id="text6041"><tspan
 106.253 +         sodipodi:role="line"
 106.254 +         id="tspan6043"
 106.255 +         x="134.79706"
 106.256 +         y="415.33771"
 106.257 +         style="fill:#979797;fill-opacity:1;font-family:Courier">000000000000</tspan></text>
 106.258 +    <path
 106.259 +       inkscape:connection-end="#rect6039"
 106.260 +       inkscape:connector-type="polyline"
 106.261 +       id="path6045"
 106.262 +       d="M 177.38238,372.82195 L 177.38235,389.20303"
 106.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" />
 106.264 +    <rect
 106.265 +       y="245.94225"
 106.266 +       x="447.28412"
 106.267 +       height="204.51619"
 106.268 +       width="174.36833"
 106.269 +       id="rect6140"
 106.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" />
 106.271 +    <g
 106.272 +       id="g6130"
 106.273 +       transform="translate(152.3254,24.38544)">
 106.274 +      <rect
 106.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"
 106.276 +         id="rect6106"
 106.277 +         width="134.53746"
 106.278 +         height="44.537449"
 106.279 +         x="314.87415"
 106.280 +         y="257.95059" />
 106.281 +      <text
 106.282 +         xml:space="preserve"
 106.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"
 106.284 +         x="339.55664"
 106.285 +         y="283.7113"
 106.286 +         id="text6108"><tspan
 106.287 +           sodipodi:role="line"
 106.288 +           id="tspan6110"
 106.289 +           x="339.55664"
 106.290 +           y="283.7113"
 106.291 +           style="font-family:Courier">ffb20e1701ea</tspan></text>
 106.292 +    </g>
 106.293 +    <g
 106.294 +       id="g6135"
 106.295 +       transform="translate(153.0396,49.83106)">
 106.296 +      <rect
 106.297 +         inkscape:transform-center-y="102.85714"
 106.298 +         inkscape:transform-center-x="129.28571"
 106.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"
 106.300 +         id="rect6112"
 106.301 +         width="134.53746"
 106.302 +         height="44.537449"
 106.303 +         x="314.15985"
 106.304 +         y="326.52203" />
 106.305 +      <text
 106.306 +         inkscape:transform-center-y="102.7311"
 106.307 +         inkscape:transform-center-x="128.69672"
 106.308 +         xml:space="preserve"
 106.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"
 106.310 +         x="338.84335"
 106.311 +         y="352.28271"
 106.312 +         id="text6114"><tspan
 106.313 +           sodipodi:role="line"
 106.314 +           id="tspan6116"
 106.315 +           x="338.84335"
 106.316 +           y="352.28271"
 106.317 +           style="fill:#979797;fill-opacity:1;font-family:Courier">000000000000</tspan></text>
 106.318 +    </g>
 106.319 +    <text
 106.320 +       xml:space="preserve"
 106.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"
 106.322 +       x="466.63208"
 106.323 +       y="270.479"
 106.324 +       id="text6118"><tspan
 106.325 +         sodipodi:role="line"
 106.326 +         id="tspan6120"
 106.327 +         x="466.63208"
 106.328 +         y="270.479">First parent</tspan></text>
 106.329 +    <text
 106.330 +       xml:space="preserve"
 106.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"
 106.332 +       x="466.07544"
 106.333 +       y="364.49615"
 106.334 +       id="text6122"><tspan
 106.335 +         sodipodi:role="line"
 106.336 +         id="tspan6124"
 106.337 +         x="466.07544"
 106.338 +         y="364.49615">Second parent</tspan></text>
 106.339 +    <text
 106.340 +       xml:space="preserve"
 106.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"
 106.342 +       x="446.61743"
 106.343 +       y="231.36218"
 106.344 +       id="text6195"><tspan
 106.345 +         sodipodi:role="line"
 106.346 +         id="tspan6197"
 106.347 +         x="446.61743"
 106.348 +         y="231.36218">Parents of working directory</tspan></text>
 106.349 +    <path
 106.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"
 106.351 +       d="M 466.82542,300.21999 L 377.00207,294.39744"
 106.352 +       id="path6266"
 106.353 +       inkscape:connector-type="polyline"
 106.354 +       inkscape:connection-start="#g6130"
 106.355 +       inkscape:connection-end="#rect1925" />
 106.356 +    <path
 106.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"
 106.358 +       d="M 665.12232,418.17579 L 665.12232,418.17579"
 106.359 +       id="path6270"
 106.360 +       inkscape:connector-type="polyline" />
 106.361 +    <g
 106.362 +       id="g2845">
 106.363 +      <rect
 106.364 +         y="266.24374"
 106.365 +         x="242.09048"
 106.366 +         height="44.537449"
 106.367 +         width="134.53746"
 106.368 +         id="rect1925"
 106.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" />
 106.370 +      <text
 106.371 +         id="text1927"
 106.372 +         y="292.00446"
 106.373 +         x="266.77298"
 106.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"
 106.375 +         xml:space="preserve"><tspan
 106.376 +           style="font-family:Courier"
 106.377 +           y="292.00446"
 106.378 +           x="266.77298"
 106.379 +           id="tspan1929"
 106.380 +           sodipodi:role="line">ffb20e1701ea</tspan></text>
 106.381 +    </g>
 106.382 +    <path
 106.383 +       inkscape:connector-type="polyline"
 106.384 +       id="path1933"
 106.385 +       d="M 260.89978,311.15532 L 225.84185,327.53627"
 106.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"
 106.387 +       inkscape:connection-end="#g6976" />
 106.388 +    <text
 106.389 +       xml:space="preserve"
 106.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"
 106.391 +       x="109.45568"
 106.392 +       y="231.4554"
 106.393 +       id="text2837"><tspan
 106.394 +         sodipodi:role="line"
 106.395 +         id="tspan2839"
 106.396 +         x="109.45568"
 106.397 +         y="231.4554">Pre-existing head</tspan></text>
 106.398 +    <text
 106.399 +       xml:space="preserve"
 106.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"
 106.401 +       x="237.54184"
 106.402 +       y="231.4554"
 106.403 +       id="text2841"><tspan
 106.404 +         sodipodi:role="line"
 106.405 +         id="tspan2843"
 106.406 +         x="237.54184"
 106.407 +         y="231.4554">Newly created head (and tip)</tspan></text>
 106.408 +    <path
 106.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)"
 106.410 +       d="M 148.05048,235.87482 L 149.94915,265.86962"
 106.411 +       id="path2850"
 106.412 +       inkscape:connector-type="polyline"
 106.413 +       inkscape:connection-end="#g1935" />
 106.414 +    <path
 106.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)"
 106.416 +       d="M 303.83495,238.08453 L 306.87874,265.86962"
 106.417 +       id="path2852"
 106.418 +       inkscape:connector-type="polyline"
 106.419 +       inkscape:connection-end="#g2845" />
 106.420 +  </g>
 106.421 +</svg>
   107.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   107.2 +++ b/fr/figs/wdir-merge.svg	Sat Jul 10 06:24:49 2010 +0100
   107.3 @@ -0,0 +1,425 @@
   107.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
   107.5 +<!-- Created with Inkscape (http://www.inkscape.org/) -->
   107.6 +<svg
   107.7 +   xmlns:dc="http://purl.org/dc/elements/1.1/"
   107.8 +   xmlns:cc="http://web.resource.org/cc/"
   107.9 +   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  107.10 +   xmlns:svg="http://www.w3.org/2000/svg"
  107.11 +   xmlns="http://www.w3.org/2000/svg"
  107.12 +   xmlns:xlink="http://www.w3.org/1999/xlink"
  107.13 +   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
  107.14 +   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
  107.15 +   width="744.09448819"
  107.16 +   height="1052.3622047"
  107.17 +   id="svg5971"
  107.18 +   sodipodi:version="0.32"
  107.19 +   inkscape:version="0.44.1"
  107.20 +   sodipodi:docbase="/home/bos/hg/hgbook/en"
  107.21 +   sodipodi:docname="wdir-merge.svg">
  107.22 +  <defs
  107.23 +     id="defs5973">
  107.24 +    <marker
  107.25 +       inkscape:stockid="Arrow1Mstart"
  107.26 +       orient="auto"
  107.27 +       refY="0.0"
  107.28 +       refX="0.0"
  107.29 +       id="Arrow1Mstart"
  107.30 +       style="overflow:visible">
  107.31 +      <path
  107.32 +         id="path4855"
  107.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 "
  107.34 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
  107.35 +         transform="scale(0.4) translate(10,0)" />
  107.36 +    </marker>
  107.37 +    <linearGradient
  107.38 +       id="linearGradient6049">
  107.39 +      <stop
  107.40 +         style="stop-color:#686868;stop-opacity:1;"
  107.41 +         offset="0"
  107.42 +         id="stop6051" />
  107.43 +      <stop
  107.44 +         style="stop-color:#f0f0f0;stop-opacity:1;"
  107.45 +         offset="1"
  107.46 +         id="stop6053" />
  107.47 +    </linearGradient>
  107.48 +    <marker
  107.49 +       inkscape:stockid="Arrow1Mend"
  107.50 +       orient="auto"
  107.51 +       refY="0.0"
  107.52 +       refX="0.0"
  107.53 +       id="Arrow1Mend"
  107.54 +       style="overflow:visible;">
  107.55 +      <path
  107.56 +         id="path4852"
  107.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 "
  107.58 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
  107.59 +         transform="scale(0.4) rotate(180) translate(10,0)" />
  107.60 +    </marker>
  107.61 +    <linearGradient
  107.62 +       inkscape:collect="always"
  107.63 +       xlink:href="#linearGradient6049"
  107.64 +       id="linearGradient6083"
  107.65 +       gradientUnits="userSpaceOnUse"
  107.66 +       gradientTransform="translate(-240.0462,-8.633237e-6)"
  107.67 +       x1="333.91171"
  107.68 +       y1="488.79077"
  107.69 +       x2="508.94543"
  107.70 +       y2="263.79077" />
  107.71 +    <linearGradient
  107.72 +       inkscape:collect="always"
  107.73 +       xlink:href="#linearGradient6049"
  107.74 +       id="linearGradient6142"
  107.75 +       gradientUnits="userSpaceOnUse"
  107.76 +       gradientTransform="translate(-42.00893,-30.49544)"
  107.77 +       x1="333.91171"
  107.78 +       y1="488.79077"
  107.79 +       x2="508.94543"
  107.80 +       y2="263.79077" />
  107.81 +    <linearGradient
  107.82 +       inkscape:collect="always"
  107.83 +       xlink:href="#linearGradient6049"
  107.84 +       id="linearGradient6193"
  107.85 +       gradientUnits="userSpaceOnUse"
  107.86 +       gradientTransform="translate(-240.0462,-8.633237e-6)"
  107.87 +       x1="333.91171"
  107.88 +       y1="488.79077"
  107.89 +       x2="508.94543"
  107.90 +       y2="263.79077" />
  107.91 +    <linearGradient
  107.92 +       inkscape:collect="always"
  107.93 +       xlink:href="#linearGradient6049"
  107.94 +       id="linearGradient6216"
  107.95 +       gradientUnits="userSpaceOnUse"
  107.96 +       gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)"
  107.97 +       x1="333.91171"
  107.98 +       y1="488.79077"
  107.99 +       x2="508.94543"
 107.100 +       y2="263.79077" />
 107.101 +    <linearGradient
 107.102 +       inkscape:collect="always"
 107.103 +       xlink:href="#linearGradient6049"
 107.104 +       id="linearGradient6232"
 107.105 +       gradientUnits="userSpaceOnUse"
 107.106 +       gradientTransform="matrix(1.000473,0,0,0.790947,-11.16012,50.85693)"
 107.107 +       x1="333.91171"
 107.108 +       y1="488.79077"
 107.109 +       x2="508.94543"
 107.110 +       y2="263.79077" />
 107.111 +    <linearGradient
 107.112 +       inkscape:collect="always"
 107.113 +       xlink:href="#linearGradient6049"
 107.114 +       id="linearGradient6445"
 107.115 +       gradientUnits="userSpaceOnUse"
 107.116 +       gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)"
 107.117 +       x1="333.91171"
 107.118 +       y1="488.79077"
 107.119 +       x2="508.94543"
 107.120 +       y2="263.79077" />
 107.121 +    <linearGradient
 107.122 +       inkscape:collect="always"
 107.123 +       xlink:href="#linearGradient6049"
 107.124 +       id="linearGradient6974"
 107.125 +       gradientUnits="userSpaceOnUse"
 107.126 +       gradientTransform="matrix(1.911882,0,0,0.789965,-574.7896,51.22599)"
 107.127 +       x1="333.91171"
 107.128 +       y1="488.79077"
 107.129 +       x2="508.94543"
 107.130 +       y2="263.79077" />
 107.131 +    <linearGradient
 107.132 +       inkscape:collect="always"
 107.133 +       xlink:href="#linearGradient6049"
 107.134 +       id="linearGradient6996"
 107.135 +       gradientUnits="userSpaceOnUse"
 107.136 +       gradientTransform="matrix(1.000473,0,0,0.790947,112.8399,50.85693)"
 107.137 +       x1="333.91171"
 107.138 +       y1="488.79077"
 107.139 +       x2="508.94543"
 107.140 +       y2="263.79077" />
 107.141 +  </defs>
 107.142 +  <sodipodi:namedview
 107.143 +     id="base"
 107.144 +     pagecolor="#ffffff"
 107.145 +     bordercolor="#666666"
 107.146 +     borderopacity="1.0"
 107.147 +     gridtolerance="10000"
 107.148 +     guidetolerance="10"
 107.149 +     objecttolerance="10"
 107.150 +     inkscape:pageopacity="0.0"
 107.151 +     inkscape:pageshadow="2"
 107.152 +     inkscape:zoom="1.28"
 107.153 +     inkscape:cx="345.85973"
 107.154 +     inkscape:cy="690.49342"
 107.155 +     inkscape:document-units="px"
 107.156 +     inkscape:current-layer="layer1"
 107.157 +     showguides="true"
 107.158 +     inkscape:guide-bbox="true"
 107.159 +     inkscape:window-width="906"
 107.160 +     inkscape:window-height="620"
 107.161 +     inkscape:window-x="0"
 107.162 +     inkscape:window-y="25">
 107.163 +    <sodipodi:guide
 107.164 +       orientation="vertical"
 107.165 +       position="-1.4285714"
 107.166 +       id="guide6022" />
 107.167 +  </sodipodi:namedview>
 107.168 +  <metadata
 107.169 +     id="metadata5976">
 107.170 +    <rdf:RDF>
 107.171 +      <cc:Work
 107.172 +         rdf:about="">
 107.173 +        <dc:format>image/svg+xml</dc:format>
 107.174 +        <dc:type
 107.175 +           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
 107.176 +      </cc:Work>
 107.177 +    </rdf:RDF>
 107.178 +  </metadata>
 107.179 +  <g
 107.180 +     inkscape:label="Layer 1"
 107.181 +     inkscape:groupmode="layer"
 107.182 +     id="layer1">
 107.183 +    <rect
 107.184 +       y="246.06918"
 107.185 +       x="64.325172"
 107.186 +       height="204.26233"
 107.187 +       width="333.2135"
 107.188 +       id="rect6047"
 107.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" />
 107.190 +    <g
 107.191 +       id="g6976"
 107.192 +       transform="translate(70,0)">
 107.193 +      <rect
 107.194 +         y="327.9104"
 107.195 +         x="40.113693"
 107.196 +         height="44.537449"
 107.197 +         width="134.53746"
 107.198 +         id="rect6004"
 107.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" />
 107.200 +      <text
 107.201 +         id="text6006"
 107.202 +         y="353.67111"
 107.203 +         x="62.654205"
 107.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"
 107.205 +         xml:space="preserve"><tspan
 107.206 +           style="font-family:Courier"
 107.207 +           y="353.67111"
 107.208 +           x="62.654205"
 107.209 +           id="tspan6008"
 107.210 +           sodipodi:role="line">7b064d8bac5e</tspan></text>
 107.211 +    </g>
 107.212 +    <path
 107.213 +       inkscape:connector-type="polyline"
 107.214 +       id="path6020"
 107.215 +       d="M 160.92915,311.15532 L 167.83571,327.53627"
 107.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"
 107.217 +       inkscape:connection-end="#g6976"
 107.218 +       inkscape:connection-start="#g1935" />
 107.219 +    <rect
 107.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"
 107.221 +       id="rect6039"
 107.222 +       width="134.53746"
 107.223 +       height="44.537449"
 107.224 +       x="110.11359"
 107.225 +       y="389.57703" />
 107.226 +    <text
 107.227 +       xml:space="preserve"
 107.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"
 107.229 +       x="134.79706"
 107.230 +       y="415.33771"
 107.231 +       id="text6041"><tspan
 107.232 +         sodipodi:role="line"
 107.233 +         id="tspan6043"
 107.234 +         x="134.79706"
 107.235 +         y="415.33771"
 107.236 +         style="fill:#979797;fill-opacity:1;font-family:Courier">000000000000</tspan></text>
 107.237 +    <path
 107.238 +       inkscape:connection-end="#rect6039"
 107.239 +       inkscape:connector-type="polyline"
 107.240 +       id="path6045"
 107.241 +       d="M 177.38238,372.82195 L 177.38235,389.20303"
 107.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" />
 107.243 +    <rect
 107.244 +       y="245.94225"
 107.245 +       x="447.28412"
 107.246 +       height="204.51619"
 107.247 +       width="174.36833"
 107.248 +       id="rect6140"
 107.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" />
 107.250 +    <g
 107.251 +       id="g6130"
 107.252 +       transform="translate(152.3254,24.38544)">
 107.253 +      <rect
 107.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"
 107.255 +         id="rect6106"
 107.256 +         width="134.53746"
 107.257 +         height="44.537449"
 107.258 +         x="314.87415"
 107.259 +         y="257.95059" />
 107.260 +      <text
 107.261 +         xml:space="preserve"
 107.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"
 107.263 +         x="339.55664"
 107.264 +         y="283.7113"
 107.265 +         id="text6108"><tspan
 107.266 +           sodipodi:role="line"
 107.267 +           id="tspan6110"
 107.268 +           x="339.55664"
 107.269 +           y="283.7113"
 107.270 +           style="font-family:Courier">ffb20e1701ea</tspan></text>
 107.271 +    </g>
 107.272 +    <g
 107.273 +       id="g6135"
 107.274 +       transform="translate(153.0396,49.83106)">
 107.275 +      <rect
 107.276 +         inkscape:transform-center-y="102.85714"
 107.277 +         inkscape:transform-center-x="129.28571"
 107.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"
 107.279 +         id="rect6112"
 107.280 +         width="134.53746"
 107.281 +         height="44.537449"
 107.282 +         x="314.15985"
 107.283 +         y="326.52203" />
 107.284 +      <text
 107.285 +         inkscape:transform-center-y="102.7311"
 107.286 +         inkscape:transform-center-x="128.69672"
 107.287 +         xml:space="preserve"
 107.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"
 107.289 +         x="338.84335"
 107.290 +         y="352.28271"
 107.291 +         id="text6114"><tspan
 107.292 +           sodipodi:role="line"
 107.293 +           id="tspan6116"
 107.294 +           x="338.84335"
 107.295 +           y="352.28271"
 107.296 +           style="fill:black;fill-opacity:1;font-family:Courier">e7639888bb2f</tspan></text>
 107.297 +    </g>
 107.298 +    <text
 107.299 +       xml:space="preserve"
 107.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"
 107.301 +       x="466.63208"
 107.302 +       y="270.479"
 107.303 +       id="text6118"><tspan
 107.304 +         sodipodi:role="line"
 107.305 +         id="tspan6120"
 107.306 +         x="466.63208"
 107.307 +         y="270.479">First parent (unchanged)</tspan></text>
 107.308 +    <text
 107.309 +       xml:space="preserve"
 107.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"
 107.311 +       x="466.07544"
 107.312 +       y="364.49615"
 107.313 +       id="text6122"><tspan
 107.314 +         sodipodi:role="line"
 107.315 +         id="tspan6124"
 107.316 +         x="466.07544"
 107.317 +         y="364.49615">Second parent</tspan></text>
 107.318 +    <text
 107.319 +       xml:space="preserve"
 107.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"
 107.321 +       x="446.61743"
 107.322 +       y="231.36218"
 107.323 +       id="text6195"><tspan
 107.324 +         sodipodi:role="line"
 107.325 +         id="tspan6197"
 107.326 +         x="446.61743"
 107.327 +         y="231.36218">Parents of working directory</tspan></text>
 107.328 +    <path
 107.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"
 107.330 +       d="M 466.82542,300.21999 L 377.00207,294.39744"
 107.331 +       id="path6266"
 107.332 +       inkscape:connector-type="polyline"
 107.333 +       inkscape:connection-start="#g6130"
 107.334 +       inkscape:connection-end="#rect1925" />
 107.335 +    <path
 107.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"
 107.337 +       d="M 665.12232,418.17579 L 665.12232,418.17579"
 107.338 +       id="path6270"
 107.339 +       inkscape:connector-type="polyline" />
 107.340 +    <g
 107.341 +       id="g2845">
 107.342 +      <rect
 107.343 +         y="266.24374"
 107.344 +         x="242.09048"
 107.345 +         height="44.537449"
 107.346 +         width="134.53746"
 107.347 +         id="rect1925"
 107.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" />
 107.349 +      <text
 107.350 +         id="text1927"
 107.351 +         y="292.00446"
 107.352 +         x="266.77298"
 107.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"
 107.354 +         xml:space="preserve"><tspan
 107.355 +           style="font-family:Courier"
 107.356 +           y="292.00446"
 107.357 +           x="266.77298"
 107.358 +           id="tspan1929"
 107.359 +           sodipodi:role="line">ffb20e1701ea</tspan></text>
 107.360 +    </g>
 107.361 +    <path
 107.362 +       inkscape:connector-type="polyline"
 107.363 +       id="path1933"
 107.364 +       d="M 260.89978,311.15532 L 225.84185,327.53627"
 107.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"
 107.366 +       inkscape:connection-end="#g6976" />
 107.367 +    <text
 107.368 +       xml:space="preserve"
 107.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"
 107.370 +       x="109.45568"
 107.371 +       y="231.4554"
 107.372 +       id="text2837"><tspan
 107.373 +         sodipodi:role="line"
 107.374 +         id="tspan2839"
 107.375 +         x="109.45568"
 107.376 +         y="231.4554">Pre-existing head</tspan></text>
 107.377 +    <text
 107.378 +       xml:space="preserve"
 107.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"
 107.380 +       x="237.54184"
 107.381 +       y="231.4554"
 107.382 +       id="text2841"><tspan
 107.383 +         sodipodi:role="line"
 107.384 +         id="tspan2843"
 107.385 +         x="237.54184"
 107.386 +         y="231.4554">Newly created head (and tip)</tspan></text>
 107.387 +    <path
 107.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)"
 107.389 +       d="M 148.05048,235.87482 L 149.94915,265.86962"
 107.390 +       id="path2850"
 107.391 +       inkscape:connector-type="polyline"
 107.392 +       inkscape:connection-end="#g1935" />
 107.393 +    <path
 107.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)"
 107.395 +       d="M 303.83495,238.08453 L 306.87874,265.86962"
 107.396 +       id="path2852"
 107.397 +       inkscape:connector-type="polyline"
 107.398 +       inkscape:connection-end="#g2845" />
 107.399 +    <path
 107.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"
 107.401 +       d="M 466.82545,379.17944 L 219.0253,307.95488"
 107.402 +       id="path3016"
 107.403 +       inkscape:connector-type="polyline"
 107.404 +       inkscape:connection-start="#g6135"
 107.405 +       inkscape:connection-end="#g1935" />
 107.406 +    <g
 107.407 +       id="g1935">
 107.408 +      <rect
 107.409 +         y="266.24374"
 107.410 +         x="84.113708"
 107.411 +         height="44.537449"
 107.412 +         width="134.53746"
 107.413 +         id="rect5996"
 107.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" />
 107.415 +      <text
 107.416 +         id="text5998"
 107.417 +         y="292.00446"
 107.418 +         x="108.7962"
 107.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"
 107.420 +         xml:space="preserve"><tspan
 107.421 +           style="font-family:Courier"
 107.422 +           y="292.00446"
 107.423 +           x="108.7962"
 107.424 +           id="tspan6000"
 107.425 +           sodipodi:role="line">e7639888bb2f</tspan></text>
 107.426 +    </g>
 107.427 +  </g>
 107.428 +</svg>
   108.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   108.2 +++ b/fr/figs/wdir-pre-branch.svg	Sat Jul 10 06:24:49 2010 +0100
   108.3 @@ -0,0 +1,364 @@
   108.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
   108.5 +<!-- Created with Inkscape (http://www.inkscape.org/) -->
   108.6 +<svg
   108.7 +   xmlns:dc="http://purl.org/dc/elements/1.1/"
   108.8 +   xmlns:cc="http://web.resource.org/cc/"
   108.9 +   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  108.10 +   xmlns:svg="http://www.w3.org/2000/svg"
  108.11 +   xmlns="http://www.w3.org/2000/svg"
  108.12 +   xmlns:xlink="http://www.w3.org/1999/xlink"
  108.13 +   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
  108.14 +   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
  108.15 +   width="744.09448819"
  108.16 +   height="1052.3622047"
  108.17 +   id="svg5971"
  108.18 +   sodipodi:version="0.32"
  108.19 +   inkscape:version="0.44.1"
  108.20 +   sodipodi:docbase="/home/bos/hg/hgbook/en"
  108.21 +   sodipodi:docname="wdir-branch.svg">
  108.22 +  <defs
  108.23 +     id="defs5973">
  108.24 +    <marker
  108.25 +       inkscape:stockid="Arrow1Mstart"
  108.26 +       orient="auto"
  108.27 +       refY="0.0"
  108.28 +       refX="0.0"
  108.29 +       id="Arrow1Mstart"
  108.30 +       style="overflow:visible">
  108.31 +      <path
  108.32 +         id="path4855"
  108.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 "
  108.34 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
  108.35 +         transform="scale(0.4) translate(10,0)" />
  108.36 +    </marker>
  108.37 +    <linearGradient
  108.38 +       id="linearGradient6049">
  108.39 +      <stop
  108.40 +         style="stop-color:#686868;stop-opacity:1;"
  108.41 +         offset="0"
  108.42 +         id="stop6051" />
  108.43 +      <stop
  108.44 +         style="stop-color:#f0f0f0;stop-opacity:1;"
  108.45 +         offset="1"
  108.46 +         id="stop6053" />
  108.47 +    </linearGradient>
  108.48 +    <marker
  108.49 +       inkscape:stockid="Arrow1Mend"
  108.50 +       orient="auto"
  108.51 +       refY="0.0"
  108.52 +       refX="0.0"
  108.53 +       id="Arrow1Mend"
  108.54 +       style="overflow:visible;">
  108.55 +      <path
  108.56 +         id="path4852"
  108.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 "
  108.58 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
  108.59 +         transform="scale(0.4) rotate(180) translate(10,0)" />
  108.60 +    </marker>
  108.61 +    <linearGradient
  108.62 +       inkscape:collect="always"
  108.63 +       xlink:href="#linearGradient6049"
  108.64 +       id="linearGradient6083"
  108.65 +       gradientUnits="userSpaceOnUse"
  108.66 +       gradientTransform="translate(-240.0462,-8.633237e-6)"
  108.67 +       x1="333.91171"
  108.68 +       y1="488.79077"
  108.69 +       x2="508.94543"
  108.70 +       y2="263.79077" />
  108.71 +    <linearGradient
  108.72 +       inkscape:collect="always"
  108.73 +       xlink:href="#linearGradient6049"
  108.74 +       id="linearGradient6142"
  108.75 +       gradientUnits="userSpaceOnUse"
  108.76 +       gradientTransform="translate(-42.00893,-30.49544)"
  108.77 +       x1="333.91171"
  108.78 +       y1="488.79077"
  108.79 +       x2="508.94543"
  108.80 +       y2="263.79077" />
  108.81 +    <linearGradient
  108.82 +       inkscape:collect="always"
  108.83 +       xlink:href="#linearGradient6049"
  108.84 +       id="linearGradient6193"
  108.85 +       gradientUnits="userSpaceOnUse"
  108.86 +       gradientTransform="translate(-240.0462,-8.633237e-6)"
  108.87 +       x1="333.91171"
  108.88 +       y1="488.79077"
  108.89 +       x2="508.94543"
  108.90 +       y2="263.79077" />
  108.91 +    <linearGradient
  108.92 +       inkscape:collect="always"
  108.93 +       xlink:href="#linearGradient6049"
  108.94 +       id="linearGradient6216"
  108.95 +       gradientUnits="userSpaceOnUse"
  108.96 +       gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)"
  108.97 +       x1="333.91171"
  108.98 +       y1="488.79077"
  108.99 +       x2="508.94543"
 108.100 +       y2="263.79077" />
 108.101 +    <linearGradient
 108.102 +       inkscape:collect="always"
 108.103 +       xlink:href="#linearGradient6049"
 108.104 +       id="linearGradient6232"
 108.105 +       gradientUnits="userSpaceOnUse"
 108.106 +       gradientTransform="matrix(1.000473,0,0,0.790947,-11.16012,50.85693)"
 108.107 +       x1="333.91171"
 108.108 +       y1="488.79077"
 108.109 +       x2="508.94543"
 108.110 +       y2="263.79077" />
 108.111 +    <linearGradient
 108.112 +       inkscape:collect="always"
 108.113 +       xlink:href="#linearGradient6049"
 108.114 +       id="linearGradient6445"
 108.115 +       gradientUnits="userSpaceOnUse"
 108.116 +       gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)"
 108.117 +       x1="333.91171"
 108.118 +       y1="488.79077"
 108.119 +       x2="508.94543"
 108.120 +       y2="263.79077" />
 108.121 +    <linearGradient
 108.122 +       inkscape:collect="always"
 108.123 +       xlink:href="#linearGradient6049"
 108.124 +       id="linearGradient6974"
 108.125 +       gradientUnits="userSpaceOnUse"
 108.126 +       gradientTransform="matrix(1.000474,0,0,0.790947,-314.246,50.85694)"
 108.127 +       x1="333.91171"
 108.128 +       y1="488.79077"
 108.129 +       x2="508.94543"
 108.130 +       y2="263.79077" />
 108.131 +    <linearGradient
 108.132 +       inkscape:collect="always"
 108.133 +       xlink:href="#linearGradient6049"
 108.134 +       id="linearGradient6996"
 108.135 +       gradientUnits="userSpaceOnUse"
 108.136 +       gradientTransform="matrix(1.000473,0,0,0.790947,-85.16012,50.85693)"
 108.137 +       x1="333.91171"
 108.138 +       y1="488.79077"
 108.139 +       x2="508.94543"
 108.140 +       y2="263.79077" />
 108.141 +  </defs>
 108.142 +  <sodipodi:namedview
 108.143 +     id="base"
 108.144 +     pagecolor="#ffffff"
 108.145 +     bordercolor="#666666"
 108.146 +     borderopacity="1.0"
 108.147 +     gridtolerance="10000"
 108.148 +     guidetolerance="10"
 108.149 +     objecttolerance="10"
 108.150 +     inkscape:pageopacity="0.0"
 108.151 +     inkscape:pageshadow="2"
 108.152 +     inkscape:zoom="0.90509668"
 108.153 +     inkscape:cx="390.0539"
 108.154 +     inkscape:cy="690.49342"
 108.155 +     inkscape:document-units="px"
 108.156 +     inkscape:current-layer="layer1"
 108.157 +     showguides="true"
 108.158 +     inkscape:guide-bbox="true"
 108.159 +     inkscape:window-width="906"
 108.160 +     inkscape:window-height="620"
 108.161 +     inkscape:window-x="0"
 108.162 +     inkscape:window-y="25">
 108.163 +    <sodipodi:guide
 108.164 +       orientation="vertical"
 108.165 +       position="-1.4285714"
 108.166 +       id="guide6022" />
 108.167 +  </sodipodi:namedview>
 108.168 +  <metadata
 108.169 +     id="metadata5976">
 108.170 +    <rdf:RDF>
 108.171 +      <cc:Work
 108.172 +         rdf:about="">
 108.173 +        <dc:format>image/svg+xml</dc:format>
 108.174 +        <dc:type
 108.175 +           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
 108.176 +      </cc:Work>
 108.177 +    </rdf:RDF>
 108.178 +  </metadata>
 108.179 +  <g
 108.180 +     inkscape:label="Layer 1"
 108.181 +     inkscape:groupmode="layer"
 108.182 +     id="layer1">
 108.183 +    <rect
 108.184 +       y="245.94225"
 108.185 +       x="20.198257"
 108.186 +       height="204.51619"
 108.187 +       width="174.36833"
 108.188 +       id="rect6047"
 108.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" />
 108.190 +    <rect
 108.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"
 108.192 +       id="rect5996"
 108.193 +       width="134.53746"
 108.194 +       height="44.537449"
 108.195 +       x="40.113693"
 108.196 +       y="266.24374" />
 108.197 +    <text
 108.198 +       xml:space="preserve"
 108.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"
 108.200 +       x="64.796204"
 108.201 +       y="292.00446"
 108.202 +       id="text5998"><tspan
 108.203 +         sodipodi:role="line"
 108.204 +         id="tspan6000"
 108.205 +         x="64.796204"
 108.206 +         y="292.00446"
 108.207 +         style="font-family:Courier">e7639888bb2f</tspan></text>
 108.208 +    <g
 108.209 +       id="g6976">
 108.210 +      <rect
 108.211 +         y="327.9104"
 108.212 +         x="40.113693"
 108.213 +         height="44.537449"
 108.214 +         width="134.53746"
 108.215 +         id="rect6004"
 108.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" />
 108.217 +      <text
 108.218 +         id="text6006"
 108.219 +         y="353.67111"
 108.220 +         x="62.654205"
 108.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"
 108.222 +         xml:space="preserve"><tspan
 108.223 +           style="font-family:Courier"
 108.224 +           y="353.67111"
 108.225 +           x="62.654205"
 108.226 +           id="tspan6008"
 108.227 +           sodipodi:role="line">7b064d8bac5e</tspan></text>
 108.228 +    </g>
 108.229 +    <path
 108.230 +       inkscape:connection-end="#rect6004"
 108.231 +       inkscape:connector-type="polyline"
 108.232 +       id="path6020"
 108.233 +       d="M 107.38242,311.15529 L 107.38242,327.53626"
 108.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" />
 108.235 +    <rect
 108.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"
 108.237 +       id="rect6039"
 108.238 +       width="134.53746"
 108.239 +       height="44.537449"
 108.240 +       x="40.113571"
 108.241 +       y="389.57703" />
 108.242 +    <text
 108.243 +       xml:space="preserve"
 108.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"
 108.245 +       x="64.797073"
 108.246 +       y="415.33771"
 108.247 +       id="text6041"><tspan
 108.248 +         sodipodi:role="line"
 108.249 +         id="tspan6043"
 108.250 +         x="64.797073"
 108.251 +         y="415.33771"
 108.252 +         style="fill:#979797;fill-opacity:1;font-family:Courier">000000000000</tspan></text>
 108.253 +    <path
 108.254 +       inkscape:connection-end="#rect6039"
 108.255 +       inkscape:connector-type="polyline"
 108.256 +       id="path6045"
 108.257 +       d="M 107.38238,372.82195 L 107.38235,389.20301"
 108.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" />
 108.259 +    <text
 108.260 +       xml:space="preserve"
 108.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"
 108.262 +       x="19.660461"
 108.263 +       y="231.36218"
 108.264 +       id="text6102"><tspan
 108.265 +         sodipodi:role="line"
 108.266 +         id="tspan6104"
 108.267 +         x="19.660461"
 108.268 +         y="231.36218">History in repository</tspan></text>
 108.269 +    <rect
 108.270 +       y="245.94225"
 108.271 +       x="249.28412"
 108.272 +       height="204.51619"
 108.273 +       width="174.36833"
 108.274 +       id="rect6140"
 108.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" />
 108.276 +    <g
 108.277 +       id="g6130"
 108.278 +       transform="translate(-45.67459,24.38544)">
 108.279 +      <rect
 108.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"
 108.281 +         id="rect6106"
 108.282 +         width="134.53746"
 108.283 +         height="44.537449"
 108.284 +         x="314.87415"
 108.285 +         y="257.95059" />
 108.286 +      <text
 108.287 +         xml:space="preserve"
 108.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"
 108.289 +         x="339.55664"
 108.290 +         y="283.7113"
 108.291 +         id="text6108"><tspan
 108.292 +           sodipodi:role="line"
 108.293 +           id="tspan6110"
 108.294 +           x="339.55664"
 108.295 +           y="283.7113"
 108.296 +           style="font-family:Courier">7b064d8bac5e</tspan></text>
 108.297 +    </g>
 108.298 +    <g
 108.299 +       id="g6135"
 108.300 +       transform="translate(-44.96042,49.83106)">
 108.301 +      <rect
 108.302 +         inkscape:transform-center-y="102.85714"
 108.303 +         inkscape:transform-center-x="129.28571"
 108.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"
 108.305 +         id="rect6112"
 108.306 +         width="134.53746"
 108.307 +         height="44.537449"
 108.308 +         x="314.15985"
 108.309 +         y="326.52203" />
 108.310 +      <text
 108.311 +         inkscape:transform-center-y="102.7311"
 108.312 +         inkscape:transform-center-x="128.69672"
 108.313 +         xml:space="preserve"
 108.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"
 108.315 +         x="338.84335"
 108.316 +         y="352.28271"
 108.317 +         id="text6114"><tspan
 108.318 +           sodipodi:role="line"
 108.319 +           id="tspan6116"
 108.320 +           x="338.84335"
 108.321 +           y="352.28271"
 108.322 +           style="fill:#979797;fill-opacity:1;font-family:Courier">000000000000</tspan></text>
 108.323 +    </g>
 108.324 +    <text
 108.325 +       xml:space="preserve"
 108.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"
 108.327 +       x="268.63208"
 108.328 +       y="270.479"
 108.329 +       id="text6118"><tspan
 108.330 +         sodipodi:role="line"
 108.331 +         id="tspan6120"
 108.332 +         x="268.63208"
 108.333 +         y="270.479">First parent</tspan></text>
 108.334 +    <text
 108.335 +       xml:space="preserve"
 108.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"
 108.337 +       x="268.07544"
 108.338 +       y="364.49615"
 108.339 +       id="text6122"><tspan
 108.340 +         sodipodi:role="line"
 108.341 +         id="tspan6124"
 108.342 +         x="268.07544"
 108.343 +         y="364.49615">Second parent</tspan></text>
 108.344 +    <text
 108.345 +       xml:space="preserve"
 108.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"
 108.347 +       x="248.61746"
 108.348 +       y="231.36218"
 108.349 +       id="text6195"><tspan
 108.350 +         sodipodi:role="line"
 108.351 +         id="tspan6197"
 108.352 +         x="248.61746"
 108.353 +         y="231.36218">Parents of working directory</tspan></text>
 108.354 +    <path
 108.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"
 108.356 +       d="M 268.82543,318.06163 L 175.02528,336.72225"
 108.357 +       id="path6266"
 108.358 +       inkscape:connector-type="polyline"
 108.359 +       inkscape:connection-end="#g6976"
 108.360 +       inkscape:connection-start="#g6130" />
 108.361 +    <path
 108.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"
 108.363 +       d="M 665.12232,418.17579 L 665.12232,418.17579"
 108.364 +       id="path6270"
 108.365 +       inkscape:connector-type="polyline" />
 108.366 +  </g>
 108.367 +</svg>
   109.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   109.2 +++ b/fr/figs/wdir.svg	Sat Jul 10 06:24:49 2010 +0100
   109.3 @@ -0,0 +1,348 @@
   109.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
   109.5 +<!-- Created with Inkscape (http://www.inkscape.org/) -->
   109.6 +<svg
   109.7 +   xmlns:dc="http://purl.org/dc/elements/1.1/"
   109.8 +   xmlns:cc="http://web.resource.org/cc/"
   109.9 +   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  109.10 +   xmlns:svg="http://www.w3.org/2000/svg"
  109.11 +   xmlns="http://www.w3.org/2000/svg"
  109.12 +   xmlns:xlink="http://www.w3.org/1999/xlink"
  109.13 +   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
  109.14 +   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
  109.15 +   width="744.09448819"
  109.16 +   height="1052.3622047"
  109.17 +   id="svg5971"
  109.18 +   sodipodi:version="0.32"
  109.19 +   inkscape:version="0.44.1"
  109.20 +   sodipodi:docbase="/home/bos/hg/hgbook/en"
  109.21 +   sodipodi:docname="wdir.svg">
  109.22 +  <defs
  109.23 +     id="defs5973">
  109.24 +    <marker
  109.25 +       inkscape:stockid="Arrow1Mstart"
  109.26 +       orient="auto"
  109.27 +       refY="0.0"
  109.28 +       refX="0.0"
  109.29 +       id="Arrow1Mstart"
  109.30 +       style="overflow:visible">
  109.31 +      <path
  109.32 +         id="path4855"
  109.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 "
  109.34 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
  109.35 +         transform="scale(0.4) translate(10,0)" />
  109.36 +    </marker>
  109.37 +    <linearGradient
  109.38 +       id="linearGradient6049">
  109.39 +      <stop
  109.40 +         style="stop-color:#686868;stop-opacity:1;"
  109.41 +         offset="0"
  109.42 +         id="stop6051" />
  109.43 +      <stop
  109.44 +         style="stop-color:#f0f0f0;stop-opacity:1;"
  109.45 +         offset="1"
  109.46 +         id="stop6053" />
  109.47 +    </linearGradient>
  109.48 +    <marker
  109.49 +       inkscape:stockid="Arrow1Mend"
  109.50 +       orient="auto"
  109.51 +       refY="0.0"
  109.52 +       refX="0.0"
  109.53 +       id="Arrow1Mend"
  109.54 +       style="overflow:visible;">
  109.55 +      <path
  109.56 +         id="path4852"
  109.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 "
  109.58 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
  109.59 +         transform="scale(0.4) rotate(180) translate(10,0)" />
  109.60 +    </marker>
  109.61 +    <linearGradient
  109.62 +       inkscape:collect="always"
  109.63 +       xlink:href="#linearGradient6049"
  109.64 +       id="linearGradient6083"
  109.65 +       gradientUnits="userSpaceOnUse"
  109.66 +       gradientTransform="translate(-240.0462,-8.633237e-6)"
  109.67 +       x1="333.91171"
  109.68 +       y1="488.79077"
  109.69 +       x2="508.94543"
  109.70 +       y2="263.79077" />
  109.71 +    <linearGradient
  109.72 +       inkscape:collect="always"
  109.73 +       xlink:href="#linearGradient6049"
  109.74 +       id="linearGradient6142"
  109.75 +       gradientUnits="userSpaceOnUse"
  109.76 +       gradientTransform="translate(-42.00893,-30.49544)"
  109.77 +       x1="333.91171"
  109.78 +       y1="488.79077"
  109.79 +       x2="508.94543"
  109.80 +       y2="263.79077" />
  109.81 +    <linearGradient
  109.82 +       inkscape:collect="always"
  109.83 +       xlink:href="#linearGradient6049"
  109.84 +       id="linearGradient6193"
  109.85 +       gradientUnits="userSpaceOnUse"
  109.86 +       gradientTransform="translate(-240.0462,-8.633237e-6)"
  109.87 +       x1="333.91171"
  109.88 +       y1="488.79077"
  109.89 +       x2="508.94543"
  109.90 +       y2="263.79077" />
  109.91 +    <linearGradient
  109.92 +       inkscape:collect="always"
  109.93 +       xlink:href="#linearGradient6049"
  109.94 +       id="linearGradient6216"
  109.95 +       gradientUnits="userSpaceOnUse"
  109.96 +       gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)"
  109.97 +       x1="333.91171"
  109.98 +       y1="488.79077"
  109.99 +       x2="508.94543"
 109.100 +       y2="263.79077" />
 109.101 +    <linearGradient
 109.102 +       inkscape:collect="always"
 109.103 +       xlink:href="#linearGradient6049"
 109.104 +       id="linearGradient6232"
 109.105 +       gradientUnits="userSpaceOnUse"
 109.106 +       gradientTransform="matrix(1.000473,0,0,0.790947,-11.16012,50.85693)"
 109.107 +       x1="333.91171"
 109.108 +       y1="488.79077"
 109.109 +       x2="508.94543"
 109.110 +       y2="263.79077" />
 109.111 +    <linearGradient
 109.112 +       inkscape:collect="always"
 109.113 +       xlink:href="#linearGradient6049"
 109.114 +       id="linearGradient6445"
 109.115 +       gradientUnits="userSpaceOnUse"
 109.116 +       gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)"
 109.117 +       x1="333.91171"
 109.118 +       y1="488.79077"
 109.119 +       x2="508.94543"
 109.120 +       y2="263.79077" />
 109.121 +  </defs>
 109.122 +  <sodipodi:namedview
 109.123 +     id="base"
 109.124 +     pagecolor="#ffffff"
 109.125 +     bordercolor="#666666"
 109.126 +     borderopacity="1.0"
 109.127 +     gridtolerance="10000"
 109.128 +     guidetolerance="10"
 109.129 +     objecttolerance="10"
 109.130 +     inkscape:pageopacity="0.0"
 109.131 +     inkscape:pageshadow="2"
 109.132 +     inkscape:zoom="0.90509668"
 109.133 +     inkscape:cx="390.0539"
 109.134 +     inkscape:cy="690.49342"
 109.135 +     inkscape:document-units="px"
 109.136 +     inkscape:current-layer="layer1"
 109.137 +     showguides="true"
 109.138 +     inkscape:guide-bbox="true"
 109.139 +     inkscape:window-width="906"
 109.140 +     inkscape:window-height="620"
 109.141 +     inkscape:window-x="0"
 109.142 +     inkscape:window-y="25">
 109.143 +    <sodipodi:guide
 109.144 +       orientation="vertical"
 109.145 +       position="-1.4285714"
 109.146 +       id="guide6022" />
 109.147 +  </sodipodi:namedview>
 109.148 +  <metadata
 109.149 +     id="metadata5976">
 109.150 +    <rdf:RDF>
 109.151 +      <cc:Work
 109.152 +         rdf:about="">
 109.153 +        <dc:format>image/svg+xml</dc:format>
 109.154 +        <dc:type
 109.155 +           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
 109.156 +      </cc:Work>
 109.157 +    </rdf:RDF>
 109.158 +  </metadata>
 109.159 +  <g
 109.160 +     inkscape:label="Layer 1"
 109.161 +     inkscape:groupmode="layer"
 109.162 +     id="layer1">
 109.163 +    <g
 109.164 +       id="g6431"
 109.165 +       transform="translate(0,-0.137863)">
 109.166 +      <rect
 109.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"
 109.168 +         id="rect6047"
 109.169 +         width="174.36833"
 109.170 +         height="204.51619"
 109.171 +         x="94.198257"
 109.172 +         y="246.08011" />
 109.173 +      <rect
 109.174 +         y="266.38159"
 109.175 +         x="114.11369"
 109.176 +         height="44.537449"
 109.177 +         width="134.53746"
 109.178 +         id="rect5996"
 109.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" />
 109.180 +      <text
 109.181 +         id="text5998"
 109.182 +         y="292.1423"
 109.183 +         x="138.7962"
 109.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"
 109.185 +         xml:space="preserve"><tspan
 109.186 +           style="font-family:Courier"
 109.187 +           y="292.1423"
 109.188 +           x="138.7962"
 109.189 +           id="tspan6000"
 109.190 +           sodipodi:role="line">e7639888bb2f</tspan></text>
 109.191 +      <rect
 109.192 +         y="328.04825"
 109.193 +         x="114.11369"
 109.194 +         height="44.537449"
 109.195 +         width="134.53746"
 109.196 +         id="rect6004"
 109.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" />
 109.198 +      <text
 109.199 +         id="text6006"
 109.200 +         y="353.80896"
 109.201 +         x="136.65421"
 109.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"
 109.203 +         xml:space="preserve"><tspan
 109.204 +           style="font-family:Courier"
 109.205 +           y="353.80896"
 109.206 +           x="136.65421"
 109.207 +           id="tspan6008"
 109.208 +           sodipodi:role="line">7b064d8bac5e</tspan></text>
 109.209 +      <path
 109.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"
 109.211 +         d="M 181.38242,311.29315 L 181.38242,327.67412"
 109.212 +         id="path6020"
 109.213 +         inkscape:connector-type="polyline"
 109.214 +         inkscape:connection-end="#rect6004" />
 109.215 +      <rect
 109.216 +         y="389.71487"
 109.217 +         x="114.11357"
 109.218 +         height="44.537449"
 109.219 +         width="134.53746"
 109.220 +         id="rect6039"
 109.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" />
 109.222 +      <text
 109.223 +         id="text6041"
 109.224 +         y="415.47556"
 109.225 +         x="138.79707"
 109.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"
 109.227 +         xml:space="preserve"><tspan
 109.228 +           style="fill:#979797;fill-opacity:1;font-family:Courier"
 109.229 +           y="415.47556"
 109.230 +           x="138.79707"
 109.231 +           id="tspan6043"
 109.232 +           sodipodi:role="line">000000000000</tspan></text>
 109.233 +      <path
 109.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"
 109.235 +         d="M 181.38238,372.95981 L 181.38235,389.34087"
 109.236 +         id="path6045"
 109.237 +         inkscape:connector-type="polyline"
 109.238 +         inkscape:connection-end="#rect6039" />
 109.239 +    </g>
 109.240 +    <text
 109.241 +       xml:space="preserve"
 109.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"
 109.243 +       x="93.660484"
 109.244 +       y="231.36218"
 109.245 +       id="text6102"><tspan
 109.246 +         sodipodi:role="line"
 109.247 +         id="tspan6104"
 109.248 +         x="93.660484"
 109.249 +         y="231.36218">History in repository</tspan></text>
 109.250 +    <g
 109.251 +       id="g6416">
 109.252 +      <rect
 109.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"
 109.254 +         id="rect6140"
 109.255 +         width="174.36833"
 109.256 +         height="204.51619"
 109.257 +         x="323.28412"
 109.258 +         y="245.94225" />
 109.259 +      <g
 109.260 +         transform="translate(28.32541,24.38544)"
 109.261 +         id="g6130">
 109.262 +        <rect
 109.263 +           y="257.95059"
 109.264 +           x="314.87415"
 109.265 +           height="44.537449"
 109.266 +           width="134.53746"
 109.267 +           id="rect6106"
 109.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" />
 109.269 +        <text
 109.270 +           id="text6108"
 109.271 +           y="283.7113"
 109.272 +           x="339.55664"
 109.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"
 109.274 +           xml:space="preserve"><tspan
 109.275 +             style="font-family:Courier"
 109.276 +             y="283.7113"
 109.277 +             x="339.55664"
 109.278 +             id="tspan6110"
 109.279 +             sodipodi:role="line">e7639888bb2f</tspan></text>
 109.280 +      </g>
 109.281 +      <g
 109.282 +         transform="translate(29.03958,49.83106)"
 109.283 +         id="g6135">
 109.284 +        <rect
 109.285 +           y="326.52203"
 109.286 +           x="314.15985"
 109.287 +           height="44.537449"
 109.288 +           width="134.53746"
 109.289 +           id="rect6112"
 109.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"
 109.291 +           inkscape:transform-center-x="129.28571"
 109.292 +           inkscape:transform-center-y="102.85714" />
 109.293 +        <text
 109.294 +           id="text6114"
 109.295 +           y="352.28271"
 109.296 +           x="338.84335"
 109.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"
 109.298 +           xml:space="preserve"
 109.299 +           inkscape:transform-center-x="128.69672"
 109.300 +           inkscape:transform-center-y="102.7311"><tspan
 109.301 +             style="fill:#979797;fill-opacity:1;font-family:Courier"
 109.302 +             y="352.28271"
 109.303 +             x="338.84335"
 109.304 +             id="tspan6116"
 109.305 +             sodipodi:role="line">000000000000</tspan></text>
 109.306 +      </g>
 109.307 +      <text
 109.308 +         id="text6118"
 109.309 +         y="270.479"
 109.310 +         x="342.63208"
 109.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"
 109.312 +         xml:space="preserve"><tspan
 109.313 +           y="270.479"
 109.314 +           x="342.63208"
 109.315 +           id="tspan6120"
 109.316 +           sodipodi:role="line">First parent</tspan></text>
 109.317 +      <text
 109.318 +         id="text6122"
 109.319 +         y="364.49615"
 109.320 +         x="342.07544"
 109.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"
 109.322 +         xml:space="preserve"><tspan
 109.323 +           y="364.49615"
 109.324 +           x="342.07544"
 109.325 +           id="tspan6124"
 109.326 +           sodipodi:role="line">Second parent</tspan></text>
 109.327 +    </g>
 109.328 +    <text
 109.329 +       xml:space="preserve"
 109.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"
 109.331 +       x="322.61746"
 109.332 +       y="231.36218"
 109.333 +       id="text6195"><tspan
 109.334 +         sodipodi:role="line"
 109.335 +         id="tspan6197"
 109.336 +         x="322.61746"
 109.337 +         y="231.36218">Parents of working directory</tspan></text>
 109.338 +    <path
 109.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"
 109.340 +       d="M 342.82543,299.89384 L 249.02528,293.36123"
 109.341 +       id="path6266"
 109.342 +       inkscape:connector-type="polyline"
 109.343 +       inkscape:connection-start="#g6130"
 109.344 +       inkscape:connection-end="#rect5996" />
 109.345 +    <path
 109.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"
 109.347 +       d="M 665.12232,418.17579 L 665.12232,418.17579"
 109.348 +       id="path6270"
 109.349 +       inkscape:connector-type="polyline" />
 109.350 +  </g>
 109.351 +</svg>
   110.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   110.2 +++ b/fr/fixsvg	Sat Jul 10 06:24:49 2010 +0100
   110.3 @@ -0,0 +1,29 @@
   110.4 +#!/bin/bash
   110.5 +
   110.6 +test -d hello || hg clone http://hg.serpentine.com/tutorial/hello
   110.7 +
   110.8 +set -e
   110.9 +
  110.10 +for i in 0 1 2 3 4
  110.11 +do
  110.12 +  export REV$i=$(hg --cwd hello log -r $i --template '{node|short}' | cut -c1-4)
  110.13 +done
  110.14 +export REV_my_hello=$(cat /tmp/REV5.my-hello)
  110.15 +export REV_my_new_hello=$(cat /tmp/REV5.my-new-hello)
  110.16 +export REV6_my_new_hello=$(cat /tmp/REV6.my-new-hello)
  110.17 +export REV7_my_new_hello=$(cat /tmp/REV7.my-new-hello)
  110.18 +
  110.19 +FILE=$1
  110.20 +OUTFILE=$FILE-tmp.svg
  110.21 +rm -f $OUTFILE
  110.22 +echo "Fixing $FILE"
  110.23 +cp $FILE $OUTFILE
  110.24 +perl -p -i -e "s#REV0#$REV0#" $OUTFILE
  110.25 +perl -p -i -e "s#REV1#$REV1#" $OUTFILE
  110.26 +perl -p -i -e "s#REV2#$REV2#" $OUTFILE
  110.27 +perl -p -i -e "s#REV3#$REV3#" $OUTFILE
  110.28 +perl -p -i -e "s#REV4#$REV4#" $OUTFILE
  110.29 +perl -p -i -e "s#REV_my_hello#$REV_my_hello#" $OUTFILE
  110.30 +perl -p -i -e "s#REV_my_new_hello#$REV_my_new_hello#" $OUTFILE
  110.31 +perl -p -i -e "s#REV6_my_new_hello#$REV6_my_new_hello#" $OUTFILE
  110.32 +perl -p -i -e "s#REV7_my_new_hello#$REV7_my_new_hello#" $OUTFILE
   111.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   111.2 +++ b/stylesheets/fr/fo.xsl	Sat Jul 10 06:24:49 2010 +0100
   111.3 @@ -0,0 +1,10 @@
   111.4 +<?xml version="1.0"?>
   111.5 +<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   111.6 +                xmlns:fo="http://www.w3.org/1999/XSL/Format"
   111.7 +                version='1.0'>
   111.8 +
   111.9 +  <xsl:import href="../fo.xsl"/>
  111.10 +
  111.11 +  <xsl:param name="l10n.gentext.language" select="'en'"/>
  111.12 +
  111.13 +</xsl:stylesheet>
   112.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   112.2 +++ b/stylesheets/fr/html-single.xsl	Sat Jul 10 06:24:49 2010 +0100
   112.3 @@ -0,0 +1,8 @@
   112.4 +<?xml version="1.0"?>
   112.5 +<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version='1.0'>
   112.6 +
   112.7 +  <xsl:import href="../html-single.xsl"/>
   112.8 +
   112.9 +  <xsl:param name="l10n.gentext.language" select="'en'"/>
  112.10 +
  112.11 +</xsl:stylesheet>
   113.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   113.2 +++ b/stylesheets/fr/html.xsl	Sat Jul 10 06:24:49 2010 +0100
   113.3 @@ -0,0 +1,8 @@
   113.4 +<?xml version="1.0"?>
   113.5 +<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version='1.0'>
   113.6 +
   113.7 +  <xsl:import href="../html.xsl"/>
   113.8 +
   113.9 +  <xsl:param name="l10n.gentext.language" select="'en'"/>
  113.10 +
  113.11 +</xsl:stylesheet>