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 --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 <aristotle@phil.example.gr> 6.139 +soc = Socrates <socrates@phil.example.gr></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 + <aristotle@phil.example.gr></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 "—">
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/<catalog 12.248 + page>"></ulink></member> 12.249 + </simplelist> 12.250 + 12.251 + <remark>N'oubliez pas de mettre à jour l'attribut <url> 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 <email.address@domain.net></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 <bos@serpentine.com> 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 <censored.person@example.org> 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" => "" )</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 + <joe.user@domain.com> 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 && 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` && ./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><br/></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<br/>\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 + <bos@serpentine.com></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 + <bos@serpentine.com></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>&</literal></quote>, 23.321 + <quote><literal><</literal></quote> and 23.322 + <quote><literal>></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 + <bos@serpentine.com></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 + <bos@serpentine.com></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 --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/<catalog page>"/></member> 28.283 + </simplelist> 28.284 + 28.285 + <remark>N'oubliez pas de mettre à jour l'attribut <url> 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 <mpm@selenic.com> 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 <bos@serpentine.com> 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 <bos@serpentine.com> 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 <bos@serpentine.com> 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 <bos@serpentine.com> 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 <bos@serpentine.com> 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 <bos@serpentine.com> 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 <bos@serpentine.com> 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 <bos@serpentine.com> 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 <bos@serpentine.com> 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 <bos@serpentine.com> 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 <bos@serpentine.com> 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 <stdio.h> 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 <stdio.h> 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 <email.address@domain.net></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 <bos@serpentine.com> 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 <censored.person@example.org> 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 <bos@serpentine.com> 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 <bos@serpentine.com> 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 <bos@serpentine.com> 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 <bos@serpentine.com> 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 <bos@serpentine.com> 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 <bos@serpentine.com> 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 <bos@serpentine.com> 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 <bos@serpentine.com> 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 <bos@serpentine.com> 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 <stdio.h> 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 <stdio.h> 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 <bos@serpentine.com> 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 <bos@serpentine.com> 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 <bos@serpentine.com> 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 <bos@serpentine.com> 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 <stdio.h> 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 <bos@serpentine.com> 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 > letter.txt <<EOF</userinput> 28.3001 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none">Greetings!</userinput> 28.3002 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none">I am Mariam Abacha, the wife of former</userinput> 28.3003 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none">Nigerian dictator Sani Abacha.</userinput> 28.3004 +<prompt moreinfo="none">></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 > letter.txt <<EOF</userinput> 28.3021 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none">Greetings!</userinput> 28.3022 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none">I am Shehu Musa Abacha, cousin to the former</userinput> 28.3023 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none">Nigerian dictator Sani Abacha.</userinput> 28.3024 +<prompt moreinfo="none">></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 > letter.txt <<EOF</userinput> 28.3043 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none">Greetings!</userinput> 28.3044 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none">I am Alhaji Abba Abacha, son of the former</userinput> 28.3045 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none">Nigerian dictator Sani Abacha.</userinput> 28.3046 +<prompt moreinfo="none">></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 +<<<<<<< /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 +>>>>>>> /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 > letter.txt <<EOF</userinput> 28.3128 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none">Greetings!</userinput> 28.3129 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none">I am Bryan O'Sullivan, no relation of the former</userinput> 28.3130 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none">Nigerian dictator Sani Abacha.</userinput> 28.3131 +<prompt moreinfo="none">></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 <bos@serpentine.com> 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 > 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 > b/somefile.txt</userinput> 28.4073 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo c > 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 > 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 > 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 > 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 > 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 > a</userinput> 28.4302 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo b > 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 > 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 > 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' >> 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 > 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 > 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 > 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 > 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 >> 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 >> 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 <bos@serpentine.com> 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 <bos@serpentine.com> 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.' > 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 <bos@serpentine.com> 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!' >> 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.' > 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"><Directory /home/*/public_html> 28.6391 + AllowOverride FileInfo AuthConfig Limit 28.6392 + Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec 28.6393 + <Limit GET POST OPTIONS> 28.6394 + Order allow,deny 28.6395 + Allow from all 28.6396 + </Limit> 28.6397 + <LimitExcept GET POST OPTIONS> 28.6398 + Order deny,allow Deny from all 28.6399 + </LimitExcept> 28.6400 +</Directory></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" => "" )</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 > 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 <bos@serpentine.com> 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 <bos@serpentine.com> 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 > 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 <bos@serpentine.com> 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 <bos@serpentine.com> 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!' >> 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!' > 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 <bos@serpentine.com> 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 <bos@serpentine.com> 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' >> 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 <bos@serpentine.com> 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 > 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 <bos@serpentine.com> 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 <bos@serpentine.com> 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 <bos@serpentine.com> 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 <bos@serpentine.com> 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 > 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 <bos@serpentine.com> 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 <bos@serpentine.com> 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 <bos@serpentine.com> 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 > 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 <bos@serpentine.com> 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 <bos@serpentine.com> 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 >> 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 > 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 >> 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 >> 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 >> 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 >> 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 <bos@serpentine.com> 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 <bos@serpentine.com> 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 <bos@serpentine.com> 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 < 35; i++ )); do</userinput> 28.9387 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none"> if [[ $i = $buggy_change ]]; then</userinput> 28.9388 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none"> echo 'i have a gub' > myfile$i</userinput> 28.9389 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none"> hg commit -q -A -m 'buggy changeset'</userinput> 28.9390 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none"> else</userinput> 28.9391 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none"> echo 'nothing to see here, move along' > myfile$i</userinput> 28.9392 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none"> hg commit -q -A -m 'normal changeset'</userinput> 28.9393 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none"> fi</userinput> 28.9394 +<prompt moreinfo="none">></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">></prompt> <userinput moreinfo="none">then</userinput> 28.9525 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none"> result=bad</userinput> 28.9526 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none">else</userinput> 28.9527 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none"> result=good</userinput> 28.9528 +<prompt moreinfo="none">></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">></prompt> <userinput moreinfo="none"> if grep -q 'i have a gub' *</userinput> 28.9543 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none"> then</userinput> 28.9544 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none"> result=bad</userinput> 28.9545 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none"> else</userinput> 28.9546 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none"> result=good</userinput> 28.9547 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none"> fi</userinput> 28.9548 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none"> echo this revision is $result</userinput> 28.9549 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none"> hg bisect --$result</userinput> 28.9550 +<prompt moreinfo="none">></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 <bos@serpentine.com> 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]' >> .hg/hgrc</userinput> 28.10006 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'commit = echo committed $HG_NODE' >> .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 > 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' >> .hg/hgrc</userinput> 28.10033 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a >> 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 "\<bug *[0-9]" 28.10107 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'pretxncommit.bug_id_required = ./check_bug_id $HG_NODE' >> .hg/hgrc</userinput> 28.10108 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a >> 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 > 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 ' > 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' > 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 >> 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}" > .hg/commit.save') 28.10420 + print >> 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 ' >> 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 + <joe.user@domain.com> 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 && 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` && ./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 <bos@serpentine.com> 28.11775 +date: Sun Aug 16 14:05:17 2009 +0000 28.11776 +summary: added line to end of <<hello>> 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 <<hello>> 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 <bos@serpentine.com> 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 <<hello>> 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 <bos@serpentine.com> 28.11890 +date: Sun Aug 16 14:05:17 2009 +0000 28.11891 +summary: added line to end of <<hello>> 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 <<hello>> 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 <bos@serpentine.com> 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 <<hello>> 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"><br/></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<br/>\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 + <bos@serpentine.com></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 + <bos@serpentine.com></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">&</literal></quote>, 28.12147 + <quote><literal moreinfo="none"><</literal></quote> and 28.12148 + <quote><literal moreinfo="none">></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 + <bos@serpentine.com></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 + <bos@serpentine.com></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 <bos@serpentine.com> 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 +&#66;&#114;&#121;&#97;&#110;&#32;&#79;&#39;&#83;&#117;&#108;&#108;&#105;&#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 <<hello>> 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 <<hello>> file.<br/> 28.12257 +<br/> 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 &lt;&lt;hello&gt;&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 <<hello>> 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 <<hello>> 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 <<hello>> 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 <<hello>> 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 <<hello>> 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 <<hello>> 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"' > 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 > multiline << EOF</userinput> 28.12520 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none">changeset = "Changed in {node|short}:\n{files}"</userinput> 28.12521 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none">file = " {file}\n"</userinput> 28.12522 +<prompt moreinfo="none">></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 <sean.hefty@intel.com> 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' > oldfile</userinput> 28.12827 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'i have changed my mind' > newfile</userinput> 28.12828 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">diff -u oldfile newfile > 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 < 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' > file1</userinput> 28.12938 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'another line 1' > 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 <bos@serpentine.com> 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 <bos@serpentine.com> 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' >> 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' >> 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' >> 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' >> 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 > 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 > 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 <bos@serpentine.com> 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 <bos@serpentine.com> 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 <bos@serpentine.com> 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(&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 <bos@serpentine.com> 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 *) &addr, &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 > 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 > 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 <aristotle@phil.example.gr> 28.15536 +soc = Socrates <socrates@phil.example.gr></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 + <aristotle@phil.example.gr></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' > 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 + '<': '<', 68.27 + '>': '>', 68.28 + '&': '&', 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('&', '&').replace('<', '<').replace('>', '>') 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>