hgbook
changeset 964:6b680d569bb4
deleting a bunch of files not longer necessary to build the documentation.
Adding missing newly files needed to build the documentation
Adding missing newly files needed to build the documentation
line diff
1.1 --- a/fr/00book.tex Sun Aug 16 03:41:39 2009 +0200 1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 1.3 @@ -1,80 +0,0 @@ 1.4 -% The use of oneside here is a temporary hack; \marginpar entries 1.5 -% don't show up on odd pages of PDF output without it. Sigh. 1.6 -\documentclass[oneside]{book} 1.7 -\usepackage{enumerate} 1.8 -\usepackage{fullpage} 1.9 -\usepackage{makeidx} 1.10 -\usepackage{ifpdf} 1.11 -\usepackage{graphicx} 1.12 -\usepackage{pslatex} 1.13 -\usepackage{fancyvrb} 1.14 -% adding package specific to the french version 1.15 -\usepackage[french]{babel} 1.16 -\usepackage[utf8]{inputenc} 1.17 -% leave hyperref until last 1.18 -\usepackage[colorlinks=true,bookmarks=true,pdftitle={Distributed 1.19 - revision control with Mercurial},pdfsubject={Revision 1.20 - control},pdfkeywords={Mercurial, Revision control, Distributed 1.21 - revision control},pdfauthor={Bryan O'Sullivan}]{hyperref} 1.22 - 1.23 -\include{99defs} 1.24 - 1.25 -\title{Gestion de source distribué avec Mercurial} \author{Bryan 1.26 - O'Sullivan} 1.27 -\date{Copyright \copyright\ 2006, 2007 Bryan O'Sullivan.\\ 1.28 - Ce document peut être librement distribué selon les termes et 1.29 - les conditions décrites dans la version 1.0 de la licence Open Publication. 1.30 - La licence est en annexe~\ref{cha:opl} de ce document.\\ 1.31 - 1.32 - Cette traduction a été généré depuis 1.33 - \href{http://hg.serpentine.com/mercurial/book/}{rev~\input{build_id}} 1.34 - avec \href{http://www.selenic.com/hg/}{rev~\input{hg_id}} of Mercurial.} 1.35 - 1.36 -\makeindex 1.37 - 1.38 -\begin{document} 1.39 - 1.40 -\maketitle 1.41 - 1.42 -\addcontentsline{toc}{chapter}{Contents} 1.43 -\pagenumbering{roman} 1.44 -\tableofcontents 1.45 -\listoffigures 1.46 -%\listoftables 1.47 - 1.48 -\pagenumbering{arabic} 1.49 - 1.50 -\include{preface} 1.51 -\include{intro} 1.52 -\include{tour-basic} 1.53 -\include{tour-merge} 1.54 -\include{concepts} 1.55 -\include{daily} 1.56 -\include{collab} 1.57 -\include{filenames} 1.58 -\include{branch} 1.59 -\include{undo} 1.60 -\include{hook} 1.61 -\include{template} 1.62 -\include{mq} 1.63 -\include{mq-collab} 1.64 -\include{hgext} 1.65 - 1.66 -\appendix 1.67 -\include{cmdref} 1.68 -\include{mq-ref} 1.69 -\include{srcinstall} 1.70 -\include{license} 1.71 -\addcontentsline{toc}{chapter}{Bibliography} 1.72 -\bibliographystyle{alpha} 1.73 -\bibliography{99book} 1.74 - 1.75 -\addcontentsline{toc}{chapter}{Index} 1.76 -\printindex 1.77 - 1.78 -\end{document} 1.79 - 1.80 -%%% Local Variables: 1.81 -%%% mode: latex 1.82 -%%% TeX-master: t 1.83 -%%% End:
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/fr/00book.xml Sun Aug 16 04:58:01 2009 +0200 2.3 @@ -0,0 +1,110 @@ 2.4 +<?xml version="1.0" encoding="UTF-8"?> 2.5 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 2.6 +<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" 2.7 + "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" 2.8 +[ 2.9 +<!-- Below are references to files in this directory. --> 2.10 + 2.11 +<!-- Chapters. --> 2.12 + 2.13 +<!ENTITY ch00 SYSTEM "ch00-preface.xml"> 2.14 +<!ENTITY ch01 SYSTEM "ch01-intro.xml"> 2.15 +<!ENTITY ch02 SYSTEM "ch02-tour-basic.xml"> 2.16 +<!ENTITY ch03 SYSTEM "ch03-tour-merge.xml"> 2.17 +<!ENTITY ch04 SYSTEM "ch04-concepts.xml"> 2.18 +<!ENTITY ch05 SYSTEM "ch05-daily.xml"> 2.19 +<!ENTITY ch06 SYSTEM "ch06-collab.xml"> 2.20 +<!ENTITY ch07 SYSTEM "ch07-filenames.xml"> 2.21 +<!ENTITY ch08 SYSTEM "ch08-branch.xml"> 2.22 +<!ENTITY ch09 SYSTEM "ch09-undo.xml"> 2.23 +<!ENTITY ch10 SYSTEM "ch10-hook.xml"> 2.24 +<!ENTITY ch11 SYSTEM "ch11-template.xml"> 2.25 +<!ENTITY ch12 SYSTEM "ch12-mq.xml"> 2.26 +<!ENTITY ch13 SYSTEM "ch13-mq-collab.xml"> 2.27 +<!ENTITY ch14 SYSTEM "ch14-hgext.xml"> 2.28 +<!ENTITY appA SYSTEM "appA-svn.xml"> 2.29 +<!ENTITY appB SYSTEM "appB-mq-ref.xml"> 2.30 +<!ENTITY appC SYSTEM "appC-srcinstall.xml"> 2.31 +<!ENTITY appD SYSTEM "appD-license.xml"> 2.32 + 2.33 +<!-- Include our standard shortcuts. --> 2.34 + 2.35 +<!ENTITY % SHORTCUTS SYSTEM "book-shortcuts.xml"> 2.36 +%SHORTCUTS; 2.37 + 2.38 +<!-- Include automatically and manually generated code snippets. --> 2.39 + 2.40 +<!ENTITY % AUTOSNIPPETS SYSTEM "examples/auto-snippets.xml"> 2.41 +%AUTOSNIPPETS; 2.42 +]> 2.43 + 2.44 +<book id="hg"> 2.45 + <title>Mercurial: The Definitive Guide</title> 2.46 + 2.47 + <!-- hg parents --template '{node|short} ({date|shortdate})' 2.48 + <subtitle>Compiled from 8a1d3f1aff17 (2009-03-10)</subtitle> 2.49 + --> 2.50 + <subtitle>Compiled from $rev_id$</subtitle> 2.51 + <bookinfo> 2.52 + <edition>1</edition> 2.53 + <isbn>9780596800673</isbn> 2.54 + <authorgroup> 2.55 + <author> 2.56 + <firstname>Bryan</firstname> 2.57 + <surname>O'Sullivan</surname> 2.58 + </author> 2.59 + </authorgroup> 2.60 + 2.61 + <editor> 2.62 + <firstname>Mike</firstname> 2.63 + <surname>Loukides</surname> 2.64 + </editor> 2.65 + 2.66 + <copyright> 2.67 + <year>2006</year> 2.68 + <year>2007</year> 2.69 + <year>2008</year> 2.70 + <year>2009</year> 2.71 + <holder>Bryan O'Sullivan</holder> 2.72 + </copyright> 2.73 + </bookinfo> 2.74 + 2.75 + <!-- BEGIN ch00 --> 2.76 + &ch00; 2.77 + <!-- BEGIN ch01 --> 2.78 + &ch01; 2.79 + <!-- BEGIN ch02 --> 2.80 + &ch02; 2.81 + <!-- BEGIN ch03 --> 2.82 + &ch03; 2.83 + <!-- BEGIN ch04 --> 2.84 + &ch04; 2.85 + <!-- BEGIN ch05 --> 2.86 + &ch05; 2.87 + <!-- BEGIN ch06 --> 2.88 + &ch06; 2.89 + <!-- BEGIN ch07 --> 2.90 + &ch07; 2.91 + <!-- BEGIN ch08 --> 2.92 + &ch08; 2.93 + <!-- BEGIN ch09 --> 2.94 + &ch09; 2.95 + <!-- BEGIN ch10 --> 2.96 + &ch10; 2.97 + <!-- BEGIN ch11 --> 2.98 + &ch11; 2.99 + <!-- BEGIN ch12 --> 2.100 + &ch12; 2.101 + <!-- BEGIN ch13 --> 2.102 + &ch13; 2.103 + <!-- BEGIN ch14 --> 2.104 + &ch14; 2.105 + <!-- BEGIN appA --> 2.106 + &appA; 2.107 + <!-- BEGIN appB --> 2.108 + &appB; 2.109 + <!-- BEGIN appC --> 2.110 + &appC; 2.111 + <!-- BEGIN appD --> 2.112 + &appD; 2.113 +</book>
3.1 --- a/fr/99book.bib Sun Aug 16 03:41:39 2009 +0200 3.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 3.3 @@ -1,76 +0,0 @@ 3.4 -@Unpublished{gruenbacher:2005, 3.5 - author = {Andreas Gruenbacher}, 3.6 - title = {How To Survive With Many Patches (Introduction to \texttt{quilt})}, 3.7 - year = {2005}, 3.8 - month = {June}, 3.9 - note = {\url{http://www.suse.de/~agruen/quilt.pdf}}, 3.10 -} 3.11 - 3.12 -@InProceedings{web:europython, 3.13 - author = {Bryan O'Sullivan}, 3.14 - title = {Achieving High Performance in Mercurial}, 3.15 - booktitle = {EuroPython Conference}, 3.16 - year = {2006}, 3.17 - month = {July}, 3.18 - note = {\url{XXX}}, 3.19 -} 3.20 - 3.21 -@Misc{web:diffstat, 3.22 - author = {Thomas Dickey}, 3.23 - title = {\texttt{diffstat}--make a histogram of \texttt{diff} output}, 3.24 - note = {\url{http://dickey.his.com/diffstat/diffstat.html}}, 3.25 -} 3.26 - 3.27 -@Misc{web:quilt, 3.28 - author = {Andreas Gruenbacher, Martin Quinson, Jean Delvare}, 3.29 - title = {Patchwork Quilt}, 3.30 - note = {\url{http://savannah.nongnu.org/projects/quilt}}, 3.31 -} 3.32 - 3.33 -@Misc{web:patchutils, 3.34 - author = {Tim Waugh}, 3.35 - title = {\texttt{patchutils}--programs that operate on patch files}, 3.36 - note = {\url{http://cyberelk.net/tim/patchutils/}}, 3.37 -} 3.38 - 3.39 -@Misc{web:mpatch, 3.40 - author = {Chris Mason}, 3.41 - title = {\texttt{mpatch}--help solve patch rejects}, 3.42 - note = {\url{http://oss.oracle.com/~mason/mpatch/}}, 3.43 -} 3.44 - 3.45 -@Misc{web:wiggle, 3.46 - author = {Neil Brown}, 3.47 - title = {\texttt{wiggle}--apply conflicting patches}, 3.48 - note = {\url{http://cgi.cse.unsw.edu.au/~neilb/source/wiggle/}}, 3.49 -} 3.50 - 3.51 -@Misc{web:mysql-python, 3.52 - author = {Andy Dustman}, 3.53 - title = {MySQL for Python}, 3.54 - note = {\url{http://sourceforge.net/projects/mysql-python}}, 3.55 -} 3.56 - 3.57 -@Misc{web:changelog, 3.58 - author = {Richard Stallman, GNU Project volunteers}, 3.59 - title = {GNU Coding Standards---Change Logs}, 3.60 - note = {\url{http://www.gnu.org/prep/standards/html_node/Change-Logs.html}}, 3.61 -} 3.62 - 3.63 -@Misc{web:macpython, 3.64 - author = {Bob Ippolito, Ronald Oussoren}, 3.65 - title = {Universal MacPython}, 3.66 - note = {\url{http://bob.pythonmac.org/archives/2006/04/10/python-and-universal-binaries-on-mac-os-x/}}, 3.67 -} 3.68 - 3.69 -@Misc{web:putty, 3.70 - author = {Simon Tatham}, 3.71 - title = {PuTTY---open source ssh client for Windows}, 3.72 - note = {\url{http://www.chiark.greenend.org.uk/~sgtatham/putty/}}, 3.73 -} 3.74 - 3.75 -@Misc{web:configparser, 3.76 - author = {Python.org}, 3.77 - title = {\texttt{ConfigParser}---Configuration file parser}, 3.78 - note = {\url{http://docs.python.org/lib/module-ConfigParser.html}}, 3.79 -}
4.1 --- a/fr/99defs.tex Sun Aug 16 03:41:39 2009 +0200 4.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 4.3 @@ -1,146 +0,0 @@ 4.4 -% Bug ID. 4.5 -\newcommand{\bug}[1]{\index{Mercurial bug 4.6 - database!\href{http://www.selenic.com/mercurial/bts/issue#1}{bug 4.7 - ~#1}}\href{http://www.selenic.com/mercurial/bts/issue#1}{Mercurial 4.8 - bug no.~#1}} 4.9 - 4.10 -% File name in the user's home directory. 4.11 -\newcommand{\tildefile}[1]{\texttt{\~{}/#1}} 4.12 - 4.13 -% File name. 4.14 -\newcommand{\filename}[1]{\texttt{#1}} 4.15 - 4.16 -% Directory name. 4.17 -\newcommand{\dirname}[1]{\texttt{#1}} 4.18 - 4.19 -% File name, with index entry. 4.20 -% The ``s'' prefix comes from ``special''. 4.21 -\newcommand{\sfilename}[1]{\index{\texttt{#1} file}\texttt{#1}} 4.22 - 4.23 -% Directory name, with index entry. 4.24 -\newcommand{\sdirname}[1]{\index{\texttt{#1} directory}\texttt{#1}} 4.25 - 4.26 -% Mercurial extension. 4.27 -\newcommand{\hgext}[1]{\index{\texttt{#1} extension}\texttt{#1}} 4.28 - 4.29 -% Command provided by a Mercurial extension. 4.30 -\newcommand{\hgxcmd}[2]{\index{\texttt{#2} command (\texttt{#1} 4.31 - extension)}\index{\texttt{#1} extension!\texttt{#2} command}``\texttt{hg #2}''} 4.32 - 4.33 -% Mercurial command. 4.34 -\newcommand{\hgcmd}[1]{\index{\texttt{#1} command}``\texttt{hg #1}''} 4.35 - 4.36 -% Mercurial command, with arguments. 4.37 -\newcommand{\hgcmdargs}[2]{\index{\texttt{#1} command}``\texttt{hg #1 #2}''} 4.38 - 4.39 -\newcommand{\tplkword}[1]{\index{\texttt{#1} template keyword}\index{template keywords!\texttt{#1}}\texttt{#1}} 4.40 - 4.41 -\newcommand{\tplkwfilt}[2]{\index{\texttt{#1} template keyword!\texttt{#2} 4.42 - filter}\index{template filters!\texttt{#2}}\index{\texttt{#2} 4.43 - template filter}\texttt{#2}} 4.44 - 4.45 -\newcommand{\tplfilter}[1]{\index{template 4.46 - filters!\texttt{#1}}\index{\texttt{#1} template 4.47 - filter}\texttt{#1}} 4.48 - 4.49 -% Shell/system command. 4.50 -\newcommand{\command}[1]{\index{\texttt{#1} system command}\texttt{#1}} 4.51 - 4.52 -% Shell/system command, with arguments. 4.53 -\newcommand{\cmdargs}[2]{\index{\texttt{#1} system command}``\texttt{#1 #2}''} 4.54 - 4.55 -% Mercurial command option. 4.56 -\newcommand{\hgopt}[2]{\index{\texttt{#1} command!\texttt{#2} option}\texttt{#2}} 4.57 - 4.58 -% Mercurial command option, provided by an extension command. 4.59 -\newcommand{\hgxopt}[3]{\index{\texttt{#2} command (\texttt{#1} extension)!\texttt{#3} option}\index{\texttt{#1} extension!\texttt{#2} command!\texttt{#3} option}\texttt{#3}} 4.60 - 4.61 -% Mercurial global option. 4.62 -\newcommand{\hggopt}[1]{\index{global options!\texttt{#1} option}\texttt{#1}} 4.63 - 4.64 -% Shell/system command option. 4.65 -\newcommand{\cmdopt}[2]{\index{\texttt{#1} command!\texttt{#2} option}\texttt{#2}} 4.66 - 4.67 -% Command option. 4.68 -\newcommand{\option}[1]{\texttt{#1}} 4.69 - 4.70 -% Software package. 4.71 -\newcommand{\package}[1]{\index{\texttt{#1} package}\texttt{#1}} 4.72 - 4.73 -% Section name from a hgrc file. 4.74 -\newcommand{\rcsection}[1]{\index{\texttt{hgrc} file!\texttt{#1} section}\texttt{[#1]}} 4.75 - 4.76 -% Named item in a hgrc file section. 4.77 -\newcommand{\rcitem}[2]{\index{\texttt{hgrc} file!\texttt{#1} 4.78 - section!\texttt{#2} entry}\texttt{#2}} 4.79 - 4.80 -% hgrc file. 4.81 -\newcommand{\hgrc}{\index{configuration file!\texttt{hgrc} 4.82 - (Linux/Unix)}\index{\texttt{hgrc} configuration file}\texttt{hgrc}} 4.83 - 4.84 -% Mercurial.ini file. 4.85 -\newcommand{\hgini}{\index{configuration file!\texttt{Mercurial.ini} 4.86 - (Windows)}\index{\texttt{Mercurial.ini} configuration file}\texttt{Mercurial.ini}} 4.87 - 4.88 -% Hook name. 4.89 -\newcommand{\hook}[1]{\index{\texttt{#1} hook}\index{hooks!\texttt{#1}}\texttt{#1}} 4.90 - 4.91 -% Environment variable. 4.92 -\newcommand{\envar}[1]{\index{\texttt{#1} environment 4.93 - variable}\index{environment variables!\texttt{#1}}\texttt{#1}} 4.94 - 4.95 -% Python module. 4.96 -\newcommand{\pymod}[1]{\index{\texttt{#1} module}\texttt{#1}} 4.97 - 4.98 -% Python class in a module. 4.99 -\newcommand{\pymodclass}[2]{\index{\texttt{#1} module!\texttt{#2} 4.100 - class}\texttt{#1.#2}} 4.101 - 4.102 -% Python function in a module. 4.103 -\newcommand{\pymodfunc}[2]{\index{\texttt{#1} module!\texttt{#2} 4.104 - function}\texttt{#1.#2}} 4.105 - 4.106 -% Note: blah blah. 4.107 -\newsavebox{\notebox} 4.108 -\newenvironment{note}% 4.109 - {\begin{lrbox}{\notebox}\begin{minipage}{0.7\textwidth}\textbf{Note:}\space}% 4.110 - {\end{minipage}\end{lrbox}\fbox{\usebox{\notebox}}} 4.111 -\newenvironment{caution}% 4.112 - {\begin{lrbox}{\notebox}\begin{minipage}{0.7\textwidth}\textbf{Caution:}\space}% 4.113 - {\end{minipage}\end{lrbox}\fbox{\usebox{\notebox}}} 4.114 - 4.115 -% Code sample, eating 4 characters of leading space. 4.116 -\DefineVerbatimEnvironment{codesample4}{Verbatim}{frame=single,gobble=4,numbers=left,commandchars=\\\{\}} 4.117 - 4.118 -% Code sample, eating 2 characters of leading space. 4.119 -\DefineVerbatimEnvironment{codesample2}{Verbatim}{frame=single,gobble=2,numbers=left,commandchars=\\\{\}} 4.120 - 4.121 -% Interaction from the examples directory. 4.122 -\newcommand{\interaction}[1]{\VerbatimInput[frame=single,numbers=left,commandchars=\\\{\}]{examples/#1.lxo}} 4.123 -% Example code from the examples directory. 4.124 -\newcommand{\excode}[1]{\VerbatimInput[frame=single,numbers=left,commandchars=\\\{\}]{../examples/#1}} 4.125 - 4.126 -% Graphics inclusion. 4.127 -\ifpdf 4.128 - \newcommand{\grafix}[1]{\includegraphics{#1}} 4.129 -\else 4.130 - \newcommand{\grafix}[1]{\includegraphics{#1.png}} 4.131 -\fi 4.132 - 4.133 -% Reference entry for a command. 4.134 -\newcommand{\cmdref}[2]{\section{\hgcmd{#1}---#2}\label{cmdref:#1}\index{\texttt{#1} command}} 4.135 - 4.136 -% Reference entry for a command option with long and short forms. 4.137 -\newcommand{\optref}[3]{\subsubsection{\hgopt{#1}{--#3}, also \hgopt{#1}{-#2}}} 4.138 - 4.139 -% Reference entry for a command option with only long form. 4.140 -\newcommand{\loptref}[2]{\subsubsection{\hgopt{#1}{--#2} option}} 4.141 - 4.142 -% command to generate a footnote to be used as a translator's note 4.143 -\newcommand{\ndt}[1]{\footnote{\textbf{N. del T.} #1}} 4.144 - 4.145 - 4.146 -%%% Local Variables: 4.147 -%%% mode: latex 4.148 -%%% TeX-master: "00book" 4.149 -%%% End:
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/fr/appA-svn.xml Sun Aug 16 04:58:01 2009 +0200 5.3 @@ -0,0 +1,540 @@ 5.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 5.5 + 5.6 +<appendix id="svn"> 5.7 + <?dbhtml filename="migrating-to-mercurial.html"?> 5.8 +<title>Migrating to Mercurial</title> 5.9 + 5.10 + <para id="x_6e1">A common way to test the waters with a new revision control 5.11 + tool is to experiment with switching an existing project, rather 5.12 + than starting a new project from scratch.</para> 5.13 + 5.14 + <para id="x_6e2">In this appendix, we discuss how to import a project's history 5.15 + into Mercurial, and what to look out for if you are used to a 5.16 + different revision control system.</para> 5.17 + 5.18 + <sect1> 5.19 + <title>Importing history from another system</title> 5.20 + 5.21 + <para id="x_6e3">Mercurial ships with an extension named 5.22 + <literal>convert</literal>, which can import project history 5.23 + from most popular revision control systems. At the time this 5.24 + book was written, it could import history from the following 5.25 + systems:</para> 5.26 + <itemizedlist> 5.27 + <listitem> 5.28 + <para id="x_6e4">Subversion</para> 5.29 + </listitem> 5.30 + <listitem> 5.31 + <para id="x_6e5">CVS</para> 5.32 + </listitem> 5.33 + <listitem> 5.34 + <para id="x_6e6">git</para> 5.35 + </listitem> 5.36 + <listitem> 5.37 + <para id="x_6e7">Darcs</para> 5.38 + </listitem> 5.39 + <listitem> 5.40 + <para id="x_6e8">Bazaar</para> 5.41 + </listitem> 5.42 + <listitem> 5.43 + <para id="x_6e9">Monotone</para> 5.44 + </listitem> 5.45 + <listitem> 5.46 + <para id="x_6ea">GNU Arch</para> 5.47 + </listitem> 5.48 + <listitem> 5.49 + <para id="x_6eb">Mercurial</para> 5.50 + </listitem> 5.51 + </itemizedlist> 5.52 + 5.53 + <para id="x_6ec">(To see why Mercurial itself is supported as a source, see 5.54 + <xref linkend="svn.filemap"/>.)</para> 5.55 + 5.56 + <para id="x_6ed">You can enable the extension in the usual way, by editing 5.57 + your <filename>~/.hgrc</filename> file.</para> 5.58 + 5.59 + <programlisting>[extensions] 5.60 +convert =</programlisting> 5.61 + 5.62 + <para id="x_6ee">This will make a <command>hg convert</command> command 5.63 + available. The command is easy to use. For instance, this 5.64 + command will import the Subversion history for the Nose unit 5.65 + testing framework into Mercurial.</para> 5.66 + 5.67 + <screen><prompt>$</prompt> <userinput>hg convert http://python-nose.googlecode.com/svn/trunk</userinput></screen> 5.68 + 5.69 + <para id="x_6ef">The <literal>convert</literal> extension operates 5.70 + incrementally. In other words, after you have run <command>hg 5.71 + convert</command> once, running it again will import any new 5.72 + revisions committed after the first run began. Incremental 5.73 + conversion will only work if you run <command>hg 5.74 + convert</command> in the same Mercurial repository that you 5.75 + originally used, because the <literal>convert</literal> 5.76 + extension saves some private metadata in a 5.77 + non-revision-controlled file named 5.78 + <filename>.hg/shamap</filename> inside the target 5.79 + repository.</para> 5.80 + 5.81 + <para id="x_707">When you want to start making changes using Mercurial, it's 5.82 + best to clone the tree in which you are doing your conversions, 5.83 + and leave the original tree for future incremental conversions. 5.84 + This is the safest way to let you pull and merge future commits 5.85 + from the source revision control system into your newly active 5.86 + Mercurial project.</para> 5.87 + 5.88 + <sect2> 5.89 + <title>Converting multiple branches</title> 5.90 + 5.91 + <para id="x_708">The <command>hg convert</command> command given above 5.92 + converts only the history of the <literal>trunk</literal> 5.93 + branch of the Subversion repository. If we instead use the 5.94 + URL <literal>http://python-nose.googlecode.com/svn</literal>, 5.95 + Mercurial will automatically detect the 5.96 + <literal>trunk</literal>, <literal>tags</literal> and 5.97 + <literal>branches</literal> layout that Subversion projects 5.98 + usually use, and it will import each as a separate Mercurial 5.99 + branch.</para> 5.100 + 5.101 + <para id="x_709">By default, each Subversion branch imported into Mercurial 5.102 + is given a branch name. After the conversion completes, you 5.103 + can get a list of the active branch names in the Mercurial 5.104 + repository using <command>hg branches -a</command>. If you 5.105 + would prefer to import the Subversion branches without names, 5.106 + pass the <option>--config 5.107 + convert.hg.usebranchnames=false</option> option to 5.108 + <command>hg convert</command>.</para> 5.109 + 5.110 + <para id="x_70a">Once you have converted your tree, if you want to follow 5.111 + the usual Mercurial practice of working in a tree that 5.112 + contains a single branch, you can clone that single branch 5.113 + using <command>hg clone -r mybranchname</command>.</para> 5.114 + </sect2> 5.115 + 5.116 + <sect2> 5.117 + <title>Mapping user names</title> 5.118 + 5.119 + <para id="x_6f0">Some revision control tools save only short usernames with 5.120 + commits, and these can be difficult to interpret. The norm 5.121 + with Mercurial is to save a committer's name and email 5.122 + address, which is much more useful for talking to them after 5.123 + the fact.</para> 5.124 + 5.125 + <para id="x_6f1">If you are converting a tree from a revision control 5.126 + system that uses short names, you can map those names to 5.127 + longer equivalents by passing a <option>--authors</option> 5.128 + option to <command>hg convert</command>. This option accepts 5.129 + a file name that should contain entries of the following 5.130 + form.</para> 5.131 + 5.132 + <programlisting>arist = Aristotle <aristotle@phil.example.gr> 5.133 +soc = Socrates <socrates@phil.example.gr></programlisting> 5.134 + 5.135 + <para id="x_6f2">Whenever <literal>convert</literal> encounters a commit 5.136 + with the username <literal>arist</literal> in the source 5.137 + repository, it will use the name <literal>Aristotle 5.138 + <aristotle@phil.example.gr></literal> in the converted 5.139 + Mercurial revision. If no match is found for a name, it is 5.140 + used verbatim.</para> 5.141 + </sect2> 5.142 + 5.143 + <sect2 id="svn.filemap"> 5.144 + <title>Tidying up the tree</title> 5.145 + 5.146 + <para id="x_6f3">Not all projects have pristine history. There may be a 5.147 + directory that should never have been checked in, a file that 5.148 + is too big, or a whole hierarchy that needs to be 5.149 + refactored.</para> 5.150 + 5.151 + <para id="x_6f4">The <literal>convert</literal> extension supports the idea 5.152 + of a <quote>file map</quote> that can reorganize the files and 5.153 + directories in a project as it imports the project's history. 5.154 + This is useful not only when importing history from other 5.155 + revision control systems, but also to prune or refactor a 5.156 + Mercurial tree.</para> 5.157 + 5.158 + <para id="x_6f5">To specify a file map, use the <option>--filemap</option> 5.159 + option and supply a file name. A file map contains lines of the 5.160 + following forms.</para> 5.161 + 5.162 + <programlisting># This is a comment. 5.163 +# Empty lines are ignored. 5.164 + 5.165 +include path/to/file 5.166 + 5.167 +exclude path/to/file 5.168 + 5.169 +rename from/some/path to/some/other/place 5.170 +</programlisting> 5.171 + 5.172 + <para id="x_6f6">The <literal>include</literal> directive causes a file, or 5.173 + all files under a directory, to be included in the destination 5.174 + repository. This also excludes all other files and dirs not 5.175 + explicitely included. The <literal>exclude</literal> 5.176 + directive causes files or directories to be omitted, and 5.177 + others not explicitly mentioned to be included.</para> 5.178 + 5.179 + <para id="x_6f7">To move a file or directory from one location to another, 5.180 + use the <literal>rename</literal> directive. If you need to 5.181 + move a file or directory from a subdirectory into the root of 5.182 + the repository, use <literal>.</literal> as the second 5.183 + argument to the <literal>rename</literal> directive.</para> 5.184 + </sect2> 5.185 + 5.186 + <sect2> 5.187 + <title>Improving Subversion conversion performance</title> 5.188 + 5.189 + <para id="x_70b">You will often need several attempts before you hit the 5.190 + perfect combination of user map, file map, and other 5.191 + conversion parameters. Converting a Subversion repository 5.192 + over an access protocol like <literal>ssh</literal> or 5.193 + <literal>http</literal> can proceed thousands of times more 5.194 + slowly than Mercurial is capable of actually operating, due to 5.195 + network delays. This can make tuning that perfect conversion 5.196 + recipe very painful.</para> 5.197 + 5.198 + <para id="x_70c">The <ulink 5.199 + url="http://svn.collab.net/repos/svn/trunk/notes/svnsync.txt"><command>svnsync</command></ulink> 5.200 + command can greatly speed up the conversion of a Subversion 5.201 + repository. It is a read-only mirroring program for 5.202 + Subversion repositories. The idea is that you create a local 5.203 + mirror of your Subversion tree, then convert the mirror into a 5.204 + Mercurial repository.</para> 5.205 + 5.206 + <para id="x_70d">Suppose we want to convert the Subversion repository for 5.207 + the popular Memcached project into a Mercurial tree. First, 5.208 + we create a local Subversion repository.</para> 5.209 + 5.210 + <screen><prompt>$</prompt> <userinput>svnadmin create memcached-mirror</userinput></screen> 5.211 + 5.212 + <para id="x_70e">Next, we set up a Subversion hook that 5.213 + <command>svnsync</command> needs.</para> 5.214 + 5.215 + <screen><prompt>$</prompt> <userinput>echo '#!/bin/sh' > memcached-mirror/hooks/pre-revprop-change</userinput> 5.216 +<prompt>$</prompt> <userinput>chmod +x memcached-mirror/hooks/pre-revprop-change</userinput></screen> 5.217 + 5.218 + <para id="x_70f">We then initialize <command>svnsync</command> in this 5.219 + repository.</para> 5.220 + 5.221 + <screen><prompt>$</prompt> <userinput>svnsync --init file://`pwd`/memcached-mirror \ 5.222 + http://code.sixapart.com/svn/memcached</userinput></screen> 5.223 + 5.224 + <para id="x_710">Our next step is to begin the <command>svnsync</command> 5.225 + mirroring process.</para> 5.226 + 5.227 + <screen><prompt>$</prompt> <userinput>svnsync sync file://`pwd`/memcached-mirror</userinput></screen> 5.228 + 5.229 + <para id="x_711">Finally, we import the history of our local Subversion 5.230 + mirror into Mercurial.</para> 5.231 + 5.232 + <screen><prompt>$</prompt> <userinput>hg convert memcached-mirror</userinput></screen> 5.233 + 5.234 + <para id="x_712">We can use this process incrementally if the Subversion 5.235 + repository is still in use. We run <command>svnsync</command> 5.236 + to pull new changes into our mirror, then <command>hg 5.237 + convert</command> to import them into our Mercurial 5.238 + tree.</para> 5.239 + 5.240 + <para id="x_713">There are two advantages to doing a two-stage import with 5.241 + <command>svnsync</command>. The first is that it uses more 5.242 + efficient Subversion network syncing code than <command>hg 5.243 + convert</command>, so it transfers less data over the 5.244 + network. The second is that the import from a local 5.245 + Subversion tree is so fast that you can tweak your conversion 5.246 + setup repeatedly without having to sit through a painfully 5.247 + slow network-based conversion process each time.</para> 5.248 + </sect2> 5.249 + </sect1> 5.250 + 5.251 + <sect1> 5.252 + <title>Migrating from Subversion</title> 5.253 + 5.254 + <para id="x_6f8">Subversion is currently the most popular open source 5.255 + revision control system. Although there are many differences 5.256 + between Mercurial and Subversion, making the transition from 5.257 + Subversion to Mercurial is not particularly difficult. The two 5.258 + have similar command sets and generally uniform 5.259 + interfaces.</para> 5.260 + 5.261 + <sect2> 5.262 + <title>Philosophical differences</title> 5.263 + 5.264 + <para id="x_6f9">The fundamental difference between Subversion and 5.265 + Mercurial is of course that Subversion is centralized, while 5.266 + Mercurial is distributed. Since Mercurial stores all of a 5.267 + project's history on your local drive, it only needs to 5.268 + perform a network access when you want to explicitly 5.269 + communicate with another repository. In contrast, Subversion 5.270 + stores very little information locally, and the client must 5.271 + thus contact its server for many common operations.</para> 5.272 + 5.273 + <para id="x_6fa">Subversion more or less gets away without a well-defined 5.274 + notion of a branch: which portion of a server's namespace 5.275 + qualifies as a branch is a matter of convention, with the 5.276 + software providing no enforcement. Mercurial treats a 5.277 + repository as the unit of branch management.</para> 5.278 + 5.279 + <sect3> 5.280 + <title>Scope of commands</title> 5.281 + 5.282 + <para id="x_6fb">Since Subversion doesn't know what parts of its 5.283 + namespace are really branches, it treats most commands as 5.284 + requests to operate at and below whatever directory you are 5.285 + currently visiting. For instance, if you run <command>svn 5.286 + log</command>, you'll get the history of whatever part of 5.287 + the tree you're looking at, not the tree as a whole.</para> 5.288 + 5.289 + <para id="x_6fc">Mercurial's commands behave differently, by defaulting 5.290 + to operating over an entire repository. Run <command>hg 5.291 + log</command> and it will tell you the history of the 5.292 + entire tree, no matter what part of the working directory 5.293 + you're visiting at the time. If you want the history of 5.294 + just a particular file or directory, simply supply it by 5.295 + name, e.g. <command>hg log src</command>.</para> 5.296 + 5.297 + <para id="x_6fd">From my own experience, this difference in default 5.298 + behaviors is probably the most likely to trip you up if you 5.299 + have to switch back and forth frequently between the two 5.300 + tools.</para> 5.301 + </sect3> 5.302 + 5.303 + <sect3> 5.304 + <title>Multi-user operation and safety</title> 5.305 + 5.306 + <para id="x_6fe">With Subversion, it is normal (though slightly frowned 5.307 + upon) for multiple people to collaborate in a single branch. 5.308 + If Alice and Bob are working together, and Alice commits 5.309 + some changes to their shared branch, Bob must update his 5.310 + client's view of the branch before he can commit. Since at 5.311 + this time he has no permanent record of the changes he has 5.312 + made, he can corrupt or lose his modifications during and 5.313 + after his update.</para> 5.314 + 5.315 + <para id="x_6ff">Mercurial encourages a commit-then-merge model instead. 5.316 + Bob commits his changes locally before pulling changes from, 5.317 + or pushing them to, the server that he shares with Alice. 5.318 + If Alice pushed her changes before Bob tries to push his, he 5.319 + will not be able to push his changes until he pulls hers, 5.320 + merges with them, and commits the result of the merge. If 5.321 + he makes a mistake during the merge, he still has the option 5.322 + of reverting to the commit that recorded his changes.</para> 5.323 + 5.324 + <para id="x_700">It is worth emphasizing that these are the common ways 5.325 + of working with these tools. Subversion supports a safer 5.326 + work-in-your-own-branch model, but it is cumbersome enough 5.327 + in practice to not be widely used. Mercurial can support 5.328 + the less safe mode of allowing changes to be pulled in and 5.329 + merged on top of uncommitted edits, but this is considered 5.330 + highly unusual.</para> 5.331 + </sect3> 5.332 + 5.333 + <sect3> 5.334 + <title>Published vs local changes</title> 5.335 + 5.336 + <para id="x_701">A Subversion <command>svn commit</command> command 5.337 + immediately publishes changes to a server, where they can be 5.338 + seen by everyone who has read access.</para> 5.339 + 5.340 + <para id="x_702">With Mercurial, commits are always local, and must be 5.341 + published via a <command>hg push</command> command 5.342 + afterwards.</para> 5.343 + 5.344 + <para id="x_703">Each approach has its advantages and disadvantages. The 5.345 + Subversion model means that changes are published, and hence 5.346 + reviewable and usable, immediately. On the other hand, this 5.347 + means that a user must have commit access to a repository in 5.348 + order to use the software in a normal way, and commit access 5.349 + is not lightly given out by most open source 5.350 + projects.</para> 5.351 + 5.352 + <para id="x_704">The Mercurial approach allows anyone who can clone a 5.353 + repository to commit changes without the need for someone 5.354 + else's permission, and they can then publish their changes 5.355 + and continue to participate however they see fit. The 5.356 + distinction between committing and pushing does open up the 5.357 + possibility of someone committing changes to their laptop 5.358 + and walking away for a few days having forgotten to push 5.359 + them, which in rare cases might leave collaborators 5.360 + temporarily stuck.</para> 5.361 + </sect3> 5.362 + </sect2> 5.363 + 5.364 + <sect2> 5.365 + <title>Quick reference</title> 5.366 + 5.367 + <table> 5.368 + <title>Subversion commands and Mercurial equivalents</title> 5.369 + <tgroup cols="3"> 5.370 + <thead> 5.371 + <row> 5.372 + <entry>Subversion</entry> 5.373 + <entry>Mercurial</entry> 5.374 + <entry>Notes</entry> 5.375 + </row> 5.376 + </thead> 5.377 + <tbody> 5.378 + <row> 5.379 + <entry><command>svn add</command></entry> 5.380 + <entry><command>hg add</command></entry> 5.381 + <entry></entry> 5.382 + </row> 5.383 + <row> 5.384 + <entry><command>svn blame</command></entry> 5.385 + <entry><command>hg annotate</command></entry> 5.386 + <entry></entry> 5.387 + </row> 5.388 + <row> 5.389 + <entry><command>svn cat</command></entry> 5.390 + <entry><command>hg cat</command></entry> 5.391 + <entry></entry> 5.392 + </row> 5.393 + <row> 5.394 + <entry><command>svn checkout</command></entry> 5.395 + <entry><command>hg clone</command></entry> 5.396 + <entry></entry> 5.397 + </row> 5.398 + <row> 5.399 + <entry><command>svn cleanup</command></entry> 5.400 + <entry>n/a</entry> 5.401 + <entry>No cleanup needed</entry> 5.402 + </row> 5.403 + <row> 5.404 + <entry><command>svn commit</command></entry> 5.405 + <entry><command>hg commit</command>; <command>hg 5.406 + push</command></entry> 5.407 + <entry><command>hg push</command> publishes after 5.408 + commit</entry> 5.409 + </row> 5.410 + <row> 5.411 + <entry><command>svn copy</command></entry> 5.412 + <entry><command>hg clone</command></entry> 5.413 + <entry>To create a new branch</entry> 5.414 + </row> 5.415 + <row> 5.416 + <entry><command>svn copy</command></entry> 5.417 + <entry><command>hg copy</command></entry> 5.418 + <entry>To copy files or directories</entry> 5.419 + </row> 5.420 + <row> 5.421 + <entry><command>svn delete</command> (<command>svn 5.422 + remove</command>)</entry> 5.423 + <entry><command>hg remove</command></entry> 5.424 + <entry></entry> 5.425 + </row> 5.426 + <row> 5.427 + <entry><command>svn diff</command></entry> 5.428 + <entry><command>hg diff</command></entry> 5.429 + <entry></entry> 5.430 + </row> 5.431 + <row> 5.432 + <entry><command>svn export</command></entry> 5.433 + <entry><command>hg archive</command></entry> 5.434 + <entry></entry> 5.435 + </row> 5.436 + <row> 5.437 + <entry><command>svn help</command></entry> 5.438 + <entry><command>hg help</command></entry> 5.439 + <entry></entry> 5.440 + </row> 5.441 + <row> 5.442 + <entry><command>svn import</command></entry> 5.443 + <entry><command>hg addremove</command>; <command>hg 5.444 + commit</command></entry> 5.445 + <entry></entry> 5.446 + </row> 5.447 + <row> 5.448 + <entry><command>svn info</command></entry> 5.449 + <entry><command>hg parents</command></entry> 5.450 + <entry>Shows what revision is checked out</entry> 5.451 + </row> 5.452 + <row> 5.453 + <entry><command>svn info</command></entry> 5.454 + <entry><command>hg showconfig 5.455 + paths.parent</command></entry> 5.456 + <entry>Shows what URL is checked out</entry> 5.457 + </row> 5.458 + <row> 5.459 + <entry><command>svn list</command></entry> 5.460 + <entry><command>hg manifest</command></entry> 5.461 + <entry></entry> 5.462 + </row> 5.463 + <row> 5.464 + <entry><command>svn log</command></entry> 5.465 + <entry><command>hg log</command></entry> 5.466 + <entry></entry> 5.467 + </row> 5.468 + <row> 5.469 + <entry><command>svn merge</command></entry> 5.470 + <entry><command>hg merge</command></entry> 5.471 + <entry></entry> 5.472 + </row> 5.473 + <row> 5.474 + <entry><command>svn mkdir</command></entry> 5.475 + <entry>n/a</entry> 5.476 + <entry>Mercurial does not track directories</entry> 5.477 + </row> 5.478 + <row> 5.479 + <entry><command>svn move</command> (<command>svn 5.480 + rename</command>)</entry> 5.481 + <entry><command>hg rename</command></entry> 5.482 + <entry></entry> 5.483 + </row> 5.484 + <row> 5.485 + <entry><command>svn resolved</command></entry> 5.486 + <entry><command>hg resolve -m</command></entry> 5.487 + <entry></entry> 5.488 + </row> 5.489 + <row> 5.490 + <entry><command>svn revert</command></entry> 5.491 + <entry><command>hg revert</command></entry> 5.492 + <entry></entry> 5.493 + </row> 5.494 + <row> 5.495 + <entry><command>svn status</command></entry> 5.496 + <entry><command>hg status</command></entry> 5.497 + <entry></entry> 5.498 + </row> 5.499 + <row> 5.500 + <entry><command>svn update</command></entry> 5.501 + <entry><command>hg pull -u</command></entry> 5.502 + <entry></entry> 5.503 + </row> 5.504 + </tbody> 5.505 + </tgroup> 5.506 + </table> 5.507 + </sect2> 5.508 + </sect1> 5.509 + 5.510 + <sect1> 5.511 + <title>Useful tips for newcomers</title> 5.512 + 5.513 + <para id="x_705">Under some revision control systems, printing a diff for a 5.514 + single committed revision can be painful. For instance, with 5.515 + Subversion, to see what changed in revision 104654, you must 5.516 + type <command>svn diff -r104653:104654</command>. Mercurial 5.517 + eliminates the need to type the revision ID twice in this common 5.518 + case. For a plain diff, <command>hg export 104654</command>. For 5.519 + a log message followed by a diff, <command>hg log -r104654 5.520 + -p</command>.</para> 5.521 + 5.522 + <para id="x_706">When you run <command>hg status</command> without any 5.523 + arguments, it prints the status of the entire tree, with paths 5.524 + relative to the root of the repository. This makes it tricky to 5.525 + copy a file name from the output of <command>hg status</command> 5.526 + into the command line. If you supply a file or directory name 5.527 + to <command>hg status</command>, it will print paths relative to 5.528 + your current location instead. So to get tree-wide status from 5.529 + <command>hg status</command>, with paths that are relative to 5.530 + your current directory and not the root of the repository, feed 5.531 + the output of <command>hg root</command> into <command>hg 5.532 + status</command>. You can easily do this as follows on a 5.533 + Unix-like system:</para> 5.534 + 5.535 + <screen><prompt>$</prompt> <userinput>hg status `hg root`</userinput></screen> 5.536 + </sect1> 5.537 +</appendix> 5.538 + 5.539 +<!-- 5.540 +local variables: 5.541 +sgml-parent-document: ("00book.xml" "book" "appendix") 5.542 +end: 5.543 +-->
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/fr/appB-mq-ref.xml Sun Aug 16 04:58:01 2009 +0200 6.3 @@ -0,0 +1,563 @@ 6.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 6.5 + 6.6 +<appendix id="chap:mqref"> 6.7 + <?dbhtml filename="mercurial-queues-reference.html"?> 6.8 + <title>Mercurial Queues reference</title> 6.9 + 6.10 + <sect1 id="sec:mqref:cmdref"> 6.11 + <title>MQ command reference</title> 6.12 + 6.13 + <para id="x_5e8">For an overview of the commands provided by MQ, use the 6.14 + command <command role="hg-cmd">hg help mq</command>.</para> 6.15 + 6.16 + <sect2> 6.17 + <title><command role="hg-ext-mq">qapplied</command>&emdash;print 6.18 + applied patches</title> 6.19 + 6.20 + <para id="x_5e9">The <command role="hg-ext-mq">qapplied</command> command 6.21 + prints the current stack of applied patches. Patches are 6.22 + printed in oldest-to-newest order, so the last patch in the 6.23 + list is the <quote>top</quote> patch.</para> 6.24 + 6.25 + </sect2> 6.26 + <sect2> 6.27 + <title><command role="hg-ext-mq">qcommit</command>&emdash;commit 6.28 + changes in the queue repository</title> 6.29 + 6.30 + <para id="x_5ea">The <command role="hg-ext-mq">qcommit</command> command 6.31 + commits any outstanding changes in the <filename 6.32 + role="special" class="directory">.hg/patches</filename> 6.33 + repository. This command only works if the <filename 6.34 + role="special" class="directory">.hg/patches</filename> 6.35 + directory is a repository, i.e. you created the directory 6.36 + using <command role="hg-cmd">hg qinit <option 6.37 + role="hg-ext-mq-cmd-qinit-opt">-c</option></command> or 6.38 + ran <command role="hg-cmd">hg init</command> in the directory 6.39 + after running <command 6.40 + role="hg-ext-mq">qinit</command>.</para> 6.41 + 6.42 + <para id="x_5eb">This command is shorthand for <command role="hg-cmd">hg 6.43 + commit --cwd .hg/patches</command>.</para> 6.44 + </sect2> 6.45 + <sect2> 6.46 + <title><command 6.47 + role="hg-ext-mq">qdelete</command>&emdash;delete a patch 6.48 + from the <filename role="special">series</filename> 6.49 + file</title> 6.50 + 6.51 + <para id="x_5ec">The <command role="hg-ext-mq">qdelete</command> command 6.52 + removes the entry for a patch from the <filename 6.53 + role="special">series</filename> file in the <filename 6.54 + role="special" class="directory">.hg/patches</filename> 6.55 + directory. It does not pop the patch if the patch is already 6.56 + applied. By default, it does not delete the patch file; use 6.57 + the <option role="hg-ext-mq-cmd-qdel-opt">-f</option> option 6.58 + to do that.</para> 6.59 + 6.60 + <para id="x_5ed">Options:</para> 6.61 + <itemizedlist> 6.62 + <listitem><para id="x_5ee"><option 6.63 + role="hg-ext-mq-cmd-qdel-opt">-f</option>: Delete the 6.64 + patch file.</para> 6.65 + </listitem></itemizedlist> 6.66 + 6.67 + </sect2> 6.68 + <sect2> 6.69 + <title><command role="hg-ext-mq">qdiff</command>&emdash;print a 6.70 + diff of the topmost applied patch</title> 6.71 + 6.72 + <para id="x_5ef">The <command role="hg-ext-mq">qdiff</command> command 6.73 + prints a diff of the topmost applied patch. It is equivalent 6.74 + to <command role="hg-cmd">hg diff -r-2:-1</command>.</para> 6.75 + 6.76 + </sect2> 6.77 + <sect2> 6.78 + <title><command role="hg-ext-mq">qfold</command>&emdash;move 6.79 + applied patches into repository history</title> 6.80 + 6.81 + <para id="x_72d">The <command>hg qfinish</command> command converts the 6.82 + specified applied patches into permanent changes by moving 6.83 + them out of MQ's control so that they will be treated as 6.84 + normal repository history.</para> 6.85 + </sect2> 6.86 + 6.87 + <sect2> 6.88 + <title><command role="hg-ext-mq">qfold</command>&emdash;merge 6.89 + (<quote>fold</quote>) several patches into one</title> 6.90 + 6.91 + <para id="x_5f0">The <command role="hg-ext-mq">qfold</command> command 6.92 + merges multiple patches into the topmost applied patch, so 6.93 + that the topmost applied patch makes the union of all of the 6.94 + changes in the patches in question.</para> 6.95 + 6.96 + <para id="x_5f1">The patches to fold must not be applied; <command 6.97 + role="hg-ext-mq">qfold</command> will exit with an error if 6.98 + any is. The order in which patches are folded is significant; 6.99 + <command role="hg-cmd">hg qfold a b</command> means 6.100 + <quote>apply the current topmost patch, followed by 6.101 + <literal>a</literal>, followed by 6.102 + <literal>b</literal></quote>.</para> 6.103 + 6.104 + <para id="x_5f2">The comments from the folded patches are appended to the 6.105 + comments of the destination patch, with each block of comments 6.106 + separated by three asterisk 6.107 + (<quote><literal>*</literal></quote>) characters. Use the 6.108 + <option role="hg-ext-mq-cmd-qfold-opt">-e</option> option to 6.109 + edit the commit message for the combined patch/changeset after 6.110 + the folding has completed.</para> 6.111 + 6.112 + <para id="x_5f3">Options:</para> 6.113 + <itemizedlist> 6.114 + <listitem><para id="x_5f4"><option 6.115 + role="hg-ext-mq-cmd-qfold-opt">-e</option>: Edit the 6.116 + commit message and patch description for the newly folded 6.117 + patch.</para> 6.118 + </listitem> 6.119 + <listitem><para id="x_5f5"><option 6.120 + role="hg-ext-mq-cmd-qfold-opt">-l</option>: Use the 6.121 + contents of the given file as the new commit message and 6.122 + patch description for the folded patch.</para> 6.123 + </listitem> 6.124 + <listitem><para id="x_5f6"><option 6.125 + role="hg-ext-mq-cmd-qfold-opt">-m</option>: Use the 6.126 + given text as the new commit message and patch description 6.127 + for the folded patch.</para> 6.128 + </listitem></itemizedlist> 6.129 + 6.130 + </sect2> 6.131 + <sect2> 6.132 + <title><command 6.133 + role="hg-ext-mq">qheader</command>&emdash;display the 6.134 + header/description of a patch</title> 6.135 + 6.136 + <para id="x_5f7">The <command role="hg-ext-mq">qheader</command> command 6.137 + prints the header, or description, of a patch. By default, it 6.138 + prints the header of the topmost applied patch. Given an 6.139 + argument, it prints the header of the named patch.</para> 6.140 + 6.141 + </sect2> 6.142 + <sect2> 6.143 + <title><command role="hg-ext-mq">qimport</command>&emdash;import 6.144 + a third-party patch into the queue</title> 6.145 + 6.146 + <para id="x_5f8">The <command role="hg-ext-mq">qimport</command> command 6.147 + adds an entry for an external patch to the <filename 6.148 + role="special">series</filename> file, and copies the patch 6.149 + into the <filename role="special" 6.150 + class="directory">.hg/patches</filename> directory. It adds 6.151 + the entry immediately after the topmost applied patch, but 6.152 + does not push the patch.</para> 6.153 + 6.154 + <para id="x_5f9">If the <filename role="special" 6.155 + class="directory">.hg/patches</filename> directory is a 6.156 + repository, <command role="hg-ext-mq">qimport</command> 6.157 + automatically does an <command role="hg-cmd">hg add</command> 6.158 + of the imported patch.</para> 6.159 + 6.160 + </sect2> 6.161 + <sect2> 6.162 + <title><command role="hg-ext-mq">qinit</command>&emdash;prepare 6.163 + a repository to work with MQ</title> 6.164 + 6.165 + <para id="x_5fa">The <command role="hg-ext-mq">qinit</command> command 6.166 + prepares a repository to work with MQ. It creates a directory 6.167 + called <filename role="special" 6.168 + class="directory">.hg/patches</filename>.</para> 6.169 + 6.170 + <para id="x_5fb">Options:</para> 6.171 + <itemizedlist> 6.172 + <listitem><para id="x_5fc"><option 6.173 + role="hg-ext-mq-cmd-qinit-opt">-c</option>: Create 6.174 + <filename role="special" 6.175 + class="directory">.hg/patches</filename> as a repository 6.176 + in its own right. Also creates a <filename 6.177 + role="special">.hgignore</filename> file that will 6.178 + ignore the <filename role="special">status</filename> 6.179 + file.</para> 6.180 + </listitem></itemizedlist> 6.181 + 6.182 + <para id="x_5fd">When the <filename role="special" 6.183 + class="directory">.hg/patches</filename> directory is a 6.184 + repository, the <command role="hg-ext-mq">qimport</command> 6.185 + and <command role="hg-ext-mq">qnew</command> commands 6.186 + automatically <command role="hg-cmd">hg add</command> new 6.187 + patches.</para> 6.188 + 6.189 + </sect2> 6.190 + <sect2> 6.191 + <title><command role="hg-ext-mq">qnew</command>&emdash;create a 6.192 + new patch</title> 6.193 + 6.194 + <para id="x_5fe">The <command role="hg-ext-mq">qnew</command> command 6.195 + creates a new patch. It takes one mandatory argument, the 6.196 + name to use for the patch file. The newly created patch is 6.197 + created empty by default. It is added to the <filename 6.198 + role="special">series</filename> file after the current 6.199 + topmost applied patch, and is immediately pushed on top of 6.200 + that patch.</para> 6.201 + 6.202 + <para id="x_5ff">If <command role="hg-ext-mq">qnew</command> finds modified 6.203 + files in the working directory, it will refuse to create a new 6.204 + patch unless the <option 6.205 + role="hg-ext-mq-cmd-qnew-opt">-f</option> option is used 6.206 + (see below). This behavior allows you to <command 6.207 + role="hg-ext-mq">qrefresh</command> your topmost applied 6.208 + patch before you apply a new patch on top of it.</para> 6.209 + 6.210 + <para id="x_600">Options:</para> 6.211 + <itemizedlist> 6.212 + <listitem><para id="x_601"><option 6.213 + role="hg-ext-mq-cmd-qnew-opt">-f</option>: Create a new 6.214 + patch if the contents of the working directory are 6.215 + modified. Any outstanding modifications are added to the 6.216 + newly created patch, so after this command completes, the 6.217 + working directory will no longer be modified.</para> 6.218 + </listitem> 6.219 + <listitem><para id="x_602"><option 6.220 + role="hg-ext-mq-cmd-qnew-opt">-m</option>: Use the given 6.221 + text as the commit message. This text will be stored at 6.222 + the beginning of the patch file, before the patch 6.223 + data.</para> 6.224 + </listitem></itemizedlist> 6.225 + 6.226 + </sect2> 6.227 + <sect2> 6.228 + <title><command role="hg-ext-mq">qnext</command>&emdash;print 6.229 + the name of the next patch</title> 6.230 + 6.231 + <para id="x_603">The <command role="hg-ext-mq">qnext</command> command 6.232 + prints the name name of the next patch in the <filename 6.233 + role="special">series</filename> file after the topmost 6.234 + applied patch. This patch will become the topmost applied 6.235 + patch if you run <command 6.236 + role="hg-ext-mq">qpush</command>.</para> 6.237 + 6.238 + </sect2> 6.239 + <sect2> 6.240 + <title><command role="hg-ext-mq">qpop</command>&emdash;pop 6.241 + patches off the stack</title> 6.242 + 6.243 + <para id="x_604">The <command role="hg-ext-mq">qpop</command> command 6.244 + removes applied patches from the top of the stack of applied 6.245 + patches. By default, it removes only one patch.</para> 6.246 + 6.247 + <para id="x_605">This command removes the changesets that represent the 6.248 + popped patches from the repository, and updates the working 6.249 + directory to undo the effects of the patches.</para> 6.250 + 6.251 + <para id="x_606">This command takes an optional argument, which it uses as 6.252 + the name or index of the patch to pop to. If given a name, it 6.253 + will pop patches until the named patch is the topmost applied 6.254 + patch. If given a number, <command 6.255 + role="hg-ext-mq">qpop</command> treats the number as an 6.256 + index into the entries in the series file, counting from zero 6.257 + (empty lines and lines containing only comments do not count). 6.258 + It pops patches until the patch identified by the given index 6.259 + is the topmost applied patch.</para> 6.260 + 6.261 + <para id="x_607">The <command role="hg-ext-mq">qpop</command> command does 6.262 + not read or write patches or the <filename 6.263 + role="special">series</filename> file. It is thus safe to 6.264 + <command role="hg-ext-mq">qpop</command> a patch that you have 6.265 + removed from the <filename role="special">series</filename> 6.266 + file, or a patch that you have renamed or deleted entirely. 6.267 + In the latter two cases, use the name of the patch as it was 6.268 + when you applied it.</para> 6.269 + 6.270 + <para id="x_608">By default, the <command role="hg-ext-mq">qpop</command> 6.271 + command will not pop any patches if the working directory has 6.272 + been modified. You can override this behavior using the 6.273 + <option role="hg-ext-mq-cmd-qpop-opt">-f</option> option, 6.274 + which reverts all modifications in the working 6.275 + directory.</para> 6.276 + 6.277 + <para id="x_609">Options:</para> 6.278 + <itemizedlist> 6.279 + <listitem><para id="x_60a"><option 6.280 + role="hg-ext-mq-cmd-qpop-opt">-a</option>: Pop all 6.281 + applied patches. This returns the repository to its state 6.282 + before you applied any patches.</para> 6.283 + </listitem> 6.284 + <listitem><para id="x_60b"><option 6.285 + role="hg-ext-mq-cmd-qpop-opt">-f</option>: Forcibly 6.286 + revert any modifications to the working directory when 6.287 + popping.</para> 6.288 + </listitem> 6.289 + <listitem><para id="x_60c"><option 6.290 + role="hg-ext-mq-cmd-qpop-opt">-n</option>: Pop a patch 6.291 + from the named queue.</para> 6.292 + </listitem></itemizedlist> 6.293 + 6.294 + <para id="x_60d">The <command role="hg-ext-mq">qpop</command> command 6.295 + removes one line from the end of the <filename 6.296 + role="special">status</filename> file for each patch that it 6.297 + pops.</para> 6.298 + 6.299 + </sect2> 6.300 + <sect2> 6.301 + <title><command role="hg-ext-mq">qprev</command>&emdash;print 6.302 + the name of the previous patch</title> 6.303 + 6.304 + <para id="x_60e">The <command role="hg-ext-mq">qprev</command> command 6.305 + prints the name of the patch in the <filename 6.306 + role="special">series</filename> file that comes before the 6.307 + topmost applied patch. This will become the topmost applied 6.308 + patch if you run <command 6.309 + role="hg-ext-mq">qpop</command>.</para> 6.310 + 6.311 + </sect2> 6.312 + <sect2 id="sec:mqref:cmd:qpush"> 6.313 + <title><command role="hg-ext-mq">qpush</command>&emdash;push 6.314 + patches onto the stack</title> 6.315 + 6.316 + <para id="x_60f">The <command role="hg-ext-mq">qpush</command> command adds 6.317 + patches onto the applied stack. By default, it adds only one 6.318 + patch.</para> 6.319 + 6.320 + <para id="x_610">This command creates a new changeset to represent each 6.321 + applied patch, and updates the working directory to apply the 6.322 + effects of the patches.</para> 6.323 + 6.324 + <para id="x_611">The default data used when creating a changeset are as 6.325 + follows:</para> 6.326 + <itemizedlist> 6.327 + <listitem><para id="x_612">The commit date and time zone are the current 6.328 + date and time zone. Because these data are used to 6.329 + compute the identity of a changeset, this means that if 6.330 + you <command role="hg-ext-mq">qpop</command> a patch and 6.331 + <command role="hg-ext-mq">qpush</command> it again, the 6.332 + changeset that you push will have a different identity 6.333 + than the changeset you popped.</para> 6.334 + </listitem> 6.335 + <listitem><para id="x_613">The author is the same as the default used by 6.336 + the <command role="hg-cmd">hg commit</command> 6.337 + command.</para> 6.338 + </listitem> 6.339 + <listitem><para id="x_614">The commit message is any text from the patch 6.340 + file that comes before the first diff header. If there is 6.341 + no such text, a default commit message is used that 6.342 + identifies the name of the patch.</para> 6.343 + </listitem></itemizedlist> 6.344 + <para id="x_615">If a patch contains a Mercurial patch header, 6.345 + the information in the patch header overrides these 6.346 + defaults.</para> 6.347 + 6.348 + <para id="x_616">Options:</para> 6.349 + <itemizedlist> 6.350 + <listitem><para id="x_617"><option 6.351 + role="hg-ext-mq-cmd-qpush-opt">-a</option>: Push all 6.352 + unapplied patches from the <filename 6.353 + role="special">series</filename> file until there are 6.354 + none left to push.</para> 6.355 + </listitem> 6.356 + <listitem><para id="x_618"><option 6.357 + role="hg-ext-mq-cmd-qpush-opt">-l</option>: Add the name 6.358 + of the patch to the end of the commit message.</para> 6.359 + </listitem> 6.360 + <listitem><para id="x_619"><option 6.361 + role="hg-ext-mq-cmd-qpush-opt">-m</option>: If a patch 6.362 + fails to apply cleanly, use the entry for the patch in 6.363 + another saved queue to compute the parameters for a 6.364 + three-way merge, and perform a three-way merge using the 6.365 + normal Mercurial merge machinery. Use the resolution of 6.366 + the merge as the new patch content.</para> 6.367 + </listitem> 6.368 + <listitem><para id="x_61a"><option 6.369 + role="hg-ext-mq-cmd-qpush-opt">-n</option>: Use the 6.370 + named queue if merging while pushing.</para> 6.371 + </listitem></itemizedlist> 6.372 + 6.373 + <para id="x_61b">The <command role="hg-ext-mq">qpush</command> command 6.374 + reads, but does not modify, the <filename 6.375 + role="special">series</filename> file. It appends one line 6.376 + to the <command role="hg-cmd">hg status</command> file for 6.377 + each patch that it pushes.</para> 6.378 + 6.379 + </sect2> 6.380 + <sect2> 6.381 + <title><command 6.382 + role="hg-ext-mq">qrefresh</command>&emdash;update the 6.383 + topmost applied patch</title> 6.384 + 6.385 + <para id="x_61c">The <command role="hg-ext-mq">qrefresh</command> command 6.386 + updates the topmost applied patch. It modifies the patch, 6.387 + removes the old changeset that represented the patch, and 6.388 + creates a new changeset to represent the modified 6.389 + patch.</para> 6.390 + 6.391 + <para id="x_61d">The <command role="hg-ext-mq">qrefresh</command> command 6.392 + looks for the following modifications:</para> 6.393 + <itemizedlist> 6.394 + <listitem><para id="x_61e">Changes to the commit message, i.e. the text 6.395 + before the first diff header in the patch file, are 6.396 + reflected in the new changeset that represents the 6.397 + patch.</para> 6.398 + </listitem> 6.399 + <listitem><para id="x_61f">Modifications to tracked files in the working 6.400 + directory are added to the patch.</para> 6.401 + </listitem> 6.402 + <listitem><para id="x_620">Changes to the files tracked using <command 6.403 + role="hg-cmd">hg add</command>, <command 6.404 + role="hg-cmd">hg copy</command>, <command 6.405 + role="hg-cmd">hg remove</command>, or <command 6.406 + role="hg-cmd">hg rename</command>. Added files and copy 6.407 + and rename destinations are added to the patch, while 6.408 + removed files and rename sources are removed.</para> 6.409 + </listitem></itemizedlist> 6.410 + 6.411 + <para id="x_621">Even if <command role="hg-ext-mq">qrefresh</command> 6.412 + detects no changes, it still recreates the changeset that 6.413 + represents the patch. This causes the identity of the 6.414 + changeset to differ from the previous changeset that 6.415 + identified the patch.</para> 6.416 + 6.417 + <para id="x_622">Options:</para> 6.418 + <itemizedlist> 6.419 + <listitem><para id="x_623"><option 6.420 + role="hg-ext-mq-cmd-qrefresh-opt">-e</option>: Modify 6.421 + the commit and patch description, using the preferred text 6.422 + editor.</para> 6.423 + </listitem> 6.424 + <listitem><para id="x_624"><option 6.425 + role="hg-ext-mq-cmd-qrefresh-opt">-m</option>: Modify 6.426 + the commit message and patch description, using the given 6.427 + text.</para> 6.428 + </listitem> 6.429 + <listitem><para id="x_625"><option 6.430 + role="hg-ext-mq-cmd-qrefresh-opt">-l</option>: Modify 6.431 + the commit message and patch description, using text from 6.432 + the given file.</para> 6.433 + </listitem></itemizedlist> 6.434 + 6.435 + </sect2> 6.436 + <sect2> 6.437 + <title><command role="hg-ext-mq">qrename</command>&emdash;rename 6.438 + a patch</title> 6.439 + 6.440 + <para id="x_626">The <command role="hg-ext-mq">qrename</command> command 6.441 + renames a patch, and changes the entry for the patch in the 6.442 + <filename role="special">series</filename> file.</para> 6.443 + 6.444 + <para id="x_627">With a single argument, <command 6.445 + role="hg-ext-mq">qrename</command> renames the topmost 6.446 + applied patch. With two arguments, it renames its first 6.447 + argument to its second.</para> 6.448 + 6.449 + </sect2> 6.450 + <sect2> 6.451 + <title><command role="hg-ext-mq">qseries</command>&emdash;print 6.452 + the entire patch series</title> 6.453 + 6.454 + <para id="x_62a">The <command role="hg-ext-mq">qseries</command> command 6.455 + prints the entire patch series from the <filename 6.456 + role="special">series</filename> file. It prints only patch 6.457 + names, not empty lines or comments. It prints in order from 6.458 + first to be applied to last.</para> 6.459 + 6.460 + </sect2> 6.461 + <sect2> 6.462 + <title><command role="hg-ext-mq">qtop</command>&emdash;print the 6.463 + name of the current patch</title> 6.464 + 6.465 + <para id="x_62b">The <command role="hg-ext-mq">qtop</command> prints the 6.466 + name of the topmost currently applied patch.</para> 6.467 + 6.468 + </sect2> 6.469 + <sect2> 6.470 + <title><command 6.471 + role="hg-ext-mq">qunapplied</command>&emdash;print patches 6.472 + not yet applied</title> 6.473 + 6.474 + <para id="x_62c">The <command role="hg-ext-mq">qunapplied</command> command 6.475 + prints the names of patches from the <filename 6.476 + role="special">series</filename> file that are not yet 6.477 + applied. It prints them in order from the next patch that 6.478 + will be pushed to the last.</para> 6.479 + 6.480 + </sect2> 6.481 + <sect2> 6.482 + <title><command role="hg-cmd">hg strip</command>&emdash;remove a 6.483 + revision and descendants</title> 6.484 + 6.485 + <para id="x_62d">The <command role="hg-cmd">hg strip</command> command 6.486 + removes a revision, and all of its descendants, from the 6.487 + repository. It undoes the effects of the removed revisions 6.488 + from the repository, and updates the working directory to the 6.489 + first parent of the removed revision.</para> 6.490 + 6.491 + <para id="x_62e">The <command role="hg-cmd">hg strip</command> command 6.492 + saves a backup of the removed changesets in a bundle, so that 6.493 + they can be reapplied if removed in error.</para> 6.494 + 6.495 + <para id="x_62f">Options:</para> 6.496 + <itemizedlist> 6.497 + <listitem><para id="x_630"><option role="hg-opt-strip">-b</option>: Save 6.498 + unrelated changesets that are intermixed with the stripped 6.499 + changesets in the backup bundle.</para> 6.500 + </listitem> 6.501 + <listitem><para id="x_631"><option role="hg-opt-strip">-f</option>: If a 6.502 + branch has multiple heads, remove all heads.</para> 6.503 + </listitem> 6.504 + <listitem><para id="x_632"><option role="hg-opt-strip">-n</option>: Do 6.505 + not save a backup bundle.</para> 6.506 + </listitem></itemizedlist> 6.507 + 6.508 + </sect2> 6.509 + </sect1> 6.510 + <sect1> 6.511 + <title>MQ file reference</title> 6.512 + 6.513 + <sect2> 6.514 + <title>The <filename role="special">series</filename> 6.515 + file</title> 6.516 + 6.517 + <para id="x_633">The <filename role="special">series</filename> file 6.518 + contains a list of the names of all patches that MQ can apply. 6.519 + It is represented as a list of names, with one name saved per 6.520 + line. Leading and trailing white space in each line are 6.521 + ignored.</para> 6.522 + 6.523 + <para id="x_634">Lines may contain comments. A comment begins with the 6.524 + <quote><literal>#</literal></quote> character, and extends to 6.525 + the end of the line. Empty lines, and lines that contain only 6.526 + comments, are ignored.</para> 6.527 + 6.528 + <para id="x_635">You will often need to edit the <filename 6.529 + role="special">series</filename> file by hand, hence the 6.530 + support for comments and empty lines noted above. For 6.531 + example, you can comment out a patch temporarily, and <command 6.532 + role="hg-ext-mq">qpush</command> will skip over that patch 6.533 + when applying patches. You can also change the order in which 6.534 + patches are applied by reordering their entries in the 6.535 + <filename role="special">series</filename> file.</para> 6.536 + 6.537 + <para id="x_636">Placing the <filename role="special">series</filename> 6.538 + file under revision control is also supported; it is a good 6.539 + idea to place all of the patches that it refers to under 6.540 + revision control, as well. If you create a patch directory 6.541 + using the <option role="hg-ext-mq-cmd-qinit-opt">-c</option> 6.542 + option to <command role="hg-ext-mq">qinit</command>, this will 6.543 + be done for you automatically.</para> 6.544 + 6.545 + </sect2> 6.546 + <sect2> 6.547 + <title>The <filename role="special">status</filename> 6.548 + file</title> 6.549 + 6.550 + <para id="x_637">The <filename role="special">status</filename> file 6.551 + contains the names and changeset hashes of all patches that MQ 6.552 + currently has applied. Unlike the <filename 6.553 + role="special">series</filename> file, this file is not 6.554 + intended for editing. You should not place this file under 6.555 + revision control, or modify it in any way. It is used by MQ 6.556 + strictly for internal book-keeping.</para> 6.557 + 6.558 + </sect2> 6.559 + </sect1> 6.560 +</appendix> 6.561 + 6.562 +<!-- 6.563 +local variables: 6.564 +sgml-parent-document: ("00book.xml" "book" "appendix") 6.565 +end: 6.566 +-->
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/fr/appC-srcinstall.xml Sun Aug 16 04:58:01 2009 +0200 7.3 @@ -0,0 +1,66 @@ 7.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 7.5 + 7.6 +<appendix id="chap:srcinstall"> 7.7 + <?dbhtml filename="installing-mercurial-from-source.html"?> 7.8 + <title>Installing Mercurial from source</title> 7.9 + 7.10 + <sect1 id="sec:srcinstall:unixlike"> 7.11 + <title>On a Unix-like system</title> 7.12 + 7.13 + <para id="x_5e0">If you are using a Unix-like system that has a sufficiently 7.14 + recent version of Python (2.3 or newer) available, it is easy to 7.15 + install Mercurial from source.</para> 7.16 + <orderedlist> 7.17 + <listitem><para id="x_5e1">Download a recent source tarball from <ulink 7.18 + url="http://www.selenic.com/mercurial/download">http://www.selenic.com/mercurial/download</ulink>.</para> 7.19 + </listitem> 7.20 + <listitem><para id="x_5e2">Unpack the tarball:</para> 7.21 + <programlisting>gzip -dc mercurial-MYVERSION.tar.gz | tar xf -</programlisting> 7.22 + </listitem> 7.23 + <listitem><para id="x_5e3">Go into the source directory and run the 7.24 + installer script. This will build Mercurial and install it 7.25 + in your home directory.</para> 7.26 + <programlisting>cd mercurial-MYVERSION 7.27 +python setup.py install --force --home=$HOME</programlisting> 7.28 + </listitem> 7.29 + </orderedlist> 7.30 + <para id="x_5e4">Once the install finishes, Mercurial will be in the 7.31 + <literal>bin</literal> subdirectory of your home directory. 7.32 + Don't forget to make sure that this directory is present in your 7.33 + shell's search path.</para> 7.34 + 7.35 + <para id="x_5e5">You will probably need to set the <envar>PYTHONPATH</envar> 7.36 + environment variable so that the Mercurial executable can find 7.37 + the rest of the Mercurial packages. For example, on my laptop, 7.38 + I have set it to <literal>/home/bos/lib/python</literal>. The 7.39 + exact path that you will need to use depends on how Python was 7.40 + built for your system, but should be easy to figure out. If 7.41 + you're uncertain, look through the output of the installer 7.42 + script above, and see where the contents of the 7.43 + <literal>mercurial</literal> directory were installed to.</para> 7.44 + 7.45 + </sect1> 7.46 + <sect1> 7.47 + <title>On Windows</title> 7.48 + 7.49 + <para id="x_5e6">Building and installing Mercurial on Windows requires a 7.50 + variety of tools, a fair amount of technical knowledge, and 7.51 + considerable patience. I very much <emphasis>do not 7.52 + recommend</emphasis> this route if you are a <quote>casual 7.53 + user</quote>. Unless you intend to hack on Mercurial, I 7.54 + strongly suggest that you use a binary package instead.</para> 7.55 + 7.56 + <para id="x_5e7">If you are intent on building Mercurial from source on 7.57 + Windows, follow the <quote>hard way</quote> directions on the 7.58 + Mercurial wiki at <ulink 7.59 + url="http://www.selenic.com/mercurial/wiki/index.cgi/WindowsInstall">http://www.selenic.com/mercurial/wiki/index.cgi/WindowsInstall</ulink>, 7.60 + and expect the process to involve a lot of fiddly work.</para> 7.61 + 7.62 + </sect1> 7.63 +</appendix> 7.64 + 7.65 +<!-- 7.66 +local variables: 7.67 +sgml-parent-document: ("00book.xml" "book" "appendix") 7.68 +end: 7.69 +-->
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/fr/appD-license.xml Sun Aug 16 04:58:01 2009 +0200 8.3 @@ -0,0 +1,185 @@ 8.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 8.5 + 8.6 +<chapter> 8.7 +<title>Open Publication License</title> 8.8 +<para>\label{cha:opl}</para> 8.9 + 8.10 +<para>Version 1.0, 8 June 1999</para> 8.11 + 8.12 +<sect1> 8.13 +<title>Requirements on both unmodified and modified versions</title> 8.14 + 8.15 +<para>The Open Publication works may be reproduced and distributed in whole 8.16 +or in part, in any medium physical or electronic, provided that the 8.17 +terms of this license are adhered to, and that this license or an 8.18 +incorporation of it by reference (with any options elected by the 8.19 +author(s) and/or publisher) is displayed in the reproduction.</para> 8.20 + 8.21 +<para>Proper form for an incorporation by reference is as follows:</para> 8.22 + 8.23 +<blockquote> 8.24 +<para> Copyright (c) <emphasis>year</emphasis> by <emphasis>author's name or designee</emphasis>. This 8.25 + material may be distributed only subject to the terms and conditions 8.26 + set forth in the Open Publication License, v<emphasis>x.y</emphasis> or later (the 8.27 + latest version is presently available at 8.28 + <ulink url="http://www.opencontent.org/openpub/">http://www.opencontent.org/openpub/</ulink>).</para> 8.29 +</blockquote> 8.30 + 8.31 +<para>The reference must be immediately followed with any options elected by 8.32 +the author(s) and/or publisher of the document (see 8.33 +section <xref linkend="sec:opl:options"/>).</para> 8.34 + 8.35 +<para>Commercial redistribution of Open Publication-licensed material is 8.36 +permitted.</para> 8.37 + 8.38 +<para>Any publication in standard (paper) book form shall require the 8.39 +citation of the original publisher and author. The publisher and 8.40 +author's names shall appear on all outer surfaces of the book. On all 8.41 +outer surfaces of the book the original publisher's name shall be as 8.42 +large as the title of the work and cited as possessive with respect to 8.43 +the title.</para> 8.44 + 8.45 +</sect1> 8.46 +<sect1> 8.47 +<title>Copyright</title> 8.48 + 8.49 +<para>The copyright to each Open Publication is owned by its author(s) or 8.50 +designee. 8.51 +</para> 8.52 + 8.53 +</sect1> 8.54 +<sect1> 8.55 +<title>Scope of license</title> 8.56 + 8.57 +<para>The following license terms apply to all Open Publication works, 8.58 +unless otherwise explicitly stated in the document. 8.59 +</para> 8.60 + 8.61 +<para>Mere aggregation of Open Publication works or a portion of an Open 8.62 +Publication work with other works or programs on the same media shall 8.63 +not cause this license to apply to those other works. The aggregate 8.64 +work shall contain a notice specifying the inclusion of the Open 8.65 +Publication material and appropriate copyright notice. 8.66 +</para> 8.67 + 8.68 +<para><emphasis role="bold">Severability</emphasis>. If any part of this license is found to be 8.69 +unenforceable in any jurisdiction, the remaining portions of the 8.70 +license remain in force. 8.71 +</para> 8.72 + 8.73 +<para><emphasis role="bold">No warranty</emphasis>. Open Publication works are licensed and provided 8.74 +<quote>as is</quote> without warranty of any kind, express or implied, including, 8.75 +but not limited to, the implied warranties of merchantability and 8.76 +fitness for a particular purpose or a warranty of non-infringement. 8.77 +</para> 8.78 + 8.79 +</sect1> 8.80 +<sect1> 8.81 +<title>Requirements on modified works</title> 8.82 + 8.83 +<para>All modified versions of documents covered by this license, including 8.84 +translations, anthologies, compilations and partial documents, must 8.85 +meet the following requirements: 8.86 +</para> 8.87 + 8.88 +<orderedlist> 8.89 +<listitem><para>The modified version must be labeled as such. 8.90 +</para> 8.91 +</listitem> 8.92 +<listitem><para>The person making the modifications must be identified and the 8.93 + modifications dated. 8.94 +</para> 8.95 +</listitem> 8.96 +<listitem><para>Acknowledgement of the original author and publisher if 8.97 + applicable must be retained according to normal academic citation 8.98 + practices. 8.99 +</para> 8.100 +</listitem> 8.101 +<listitem><para>The location of the original unmodified document must be 8.102 + identified. 8.103 +</para> 8.104 +</listitem> 8.105 +<listitem><para>The original author's (or authors') name(s) may not be used to 8.106 + assert or imply endorsement of the resulting document without the 8.107 + original author's (or authors') permission. 8.108 +</para> 8.109 +</listitem></orderedlist> 8.110 + 8.111 +</sect1> 8.112 +<sect1> 8.113 +<title>Good-practice recommendations</title> 8.114 + 8.115 +<para>In addition to the requirements of this license, it is requested from 8.116 +and strongly recommended of redistributors that: 8.117 +</para> 8.118 + 8.119 +<orderedlist> 8.120 +<listitem><para>If you are distributing Open Publication works on hardcopy or 8.121 + CD-ROM, you provide email notification to the authors of your intent 8.122 + to redistribute at least thirty days before your manuscript or media 8.123 + freeze, to give the authors time to provide updated documents. This 8.124 + notification should describe modifications, if any, made to the 8.125 + document. 8.126 +</para> 8.127 +</listitem> 8.128 +<listitem><para>All substantive modifications (including deletions) be either 8.129 + clearly marked up in the document or else described in an attachment 8.130 + to the document. 8.131 +</para> 8.132 +</listitem> 8.133 +<listitem><para>Finally, while it is not mandatory under this license, it is 8.134 + considered good form to offer a free copy of any hardcopy and CD-ROM 8.135 + expression of an Open Publication-licensed work to its author(s). 8.136 +</para> 8.137 +</listitem></orderedlist> 8.138 + 8.139 +</sect1> 8.140 +<sect1> 8.141 +<title>License options</title> 8.142 +<para>\label{sec:opl:options} 8.143 +</para> 8.144 + 8.145 +<para>The author(s) and/or publisher of an Open Publication-licensed 8.146 +document may elect certain options by appending language to the 8.147 +reference to or copy of the license. These options are considered part 8.148 +of the license instance and must be included with the license (or its 8.149 +incorporation by reference) in derived works. 8.150 +</para> 8.151 + 8.152 +<orderedlist> 8.153 +<listitem><para>To prohibit distribution of substantively modified versions 8.154 + without the explicit permission of the author(s). <quote>Substantive 8.155 + modification</quote> is defined as a change to the semantic content of the 8.156 + document, and excludes mere changes in format or typographical 8.157 + corrections. 8.158 +</para> 8.159 +</listitem> 8.160 +<listitem><para> To accomplish this, add the phrase <quote>Distribution of substantively 8.161 + modified versions of this document is prohibited without the 8.162 + explicit permission of the copyright holder.</quote> to the license 8.163 + reference or copy. 8.164 +</para> 8.165 +</listitem> 8.166 +</para> 8.167 +</listitem> 8.168 +<listitem><para>To prohibit any publication of this work or derivative works in 8.169 + whole or in part in standard (paper) book form for commercial 8.170 + purposes is prohibited unless prior permission is obtained from the 8.171 + copyright holder. 8.172 +</para> 8.173 +</listitem> 8.174 +<listitem><para> To accomplish this, add the phrase <quote>Distribution of the work or 8.175 + derivative of the work in any standard (paper) book form is 8.176 + prohibited unless prior permission is obtained from the copyright 8.177 + holder.</quote> to the license reference or copy. 8.178 +</para> 8.179 +</listitem></orderedlist> 8.180 + 8.181 +</sect1> 8.182 +</chapter> 8.183 + 8.184 +<!-- 8.185 +local variables: 8.186 +sgml-parent-document: ("00book.xml" "book" "chapter") 8.187 +end: 8.188 +--> 8.189 \ No newline at end of file
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/fr/autoid.py Sun Aug 16 04:58:01 2009 +0200 9.3 @@ -0,0 +1,47 @@ 9.4 +#!/usr/bin/env python 9.5 +# 9.6 +# Add unique ID attributes to para tags. This script should only be 9.7 +# run by one person, since otherwise it introduces the possibility of 9.8 +# chaotic conflicts among tags. 9.9 + 9.10 +import glob, os, re, sys 9.11 + 9.12 +tagged = re.compile('<para[^>]* id="x_([0-9a-f]+)"[^>]*>', re.M) 9.13 +untagged = re.compile('<para>') 9.14 + 9.15 +names = glob.glob('ch*.xml') + glob.glob('app*.xml') 9.16 + 9.17 +# First pass: find the highest-numbered paragraph ID. 9.18 + 9.19 +biggest_id = 0 9.20 +seen = set() 9.21 +errs = 0 9.22 + 9.23 +for name in names: 9.24 + for m in tagged.finditer(open(name).read()): 9.25 + i = int(m.group(1),16) 9.26 + if i in seen: 9.27 + print >> sys.stderr, '%s: duplication of ID %s' % (name, i) 9.28 + errs += 1 9.29 + seen.add(i) 9.30 + if i > biggest_id: 9.31 + biggest_id = i 9.32 + 9.33 +def retag(s): 9.34 + global biggest_id 9.35 + biggest_id += 1 9.36 + return '<para id="x_%x">' % biggest_id 9.37 + 9.38 +# Second pass: add IDs to paragraphs that currently lack them. 9.39 + 9.40 +for name in names: 9.41 + f = open(name).read() 9.42 + f1 = untagged.sub(retag, f) 9.43 + if f1 != f: 9.44 + tmpname = name + '.tmp' 9.45 + fp = open(tmpname, 'w') 9.46 + fp.write(f1) 9.47 + fp.close() 9.48 + os.rename(tmpname, name) 9.49 + 9.50 +sys.exit(errs)
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/fr/book-shortcuts.xml Sun Aug 16 04:58:01 2009 +0200 10.3 @@ -0,0 +1,3 @@ 10.4 +<!-- Please keep the contents of this file sorted. --> 10.5 + 10.6 +<!ENTITY emdash "—">
11.1 --- a/fr/bookhtml.cfg Sun Aug 16 03:41:39 2009 +0200 11.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 11.3 @@ -1,18 +0,0 @@ 11.4 -% -*- latex -*- 11.5 - 11.6 -\Preamble{xhtml} 11.7 - 11.8 -% Tex4ht's default definition of lists is complete crap. 11.9 -% Unfortunately, it can't distinguish between "ul" and "dl" lists. 11.10 - 11.11 -\ConfigureList{itemize}% 11.12 - {\EndP\HCode{<ul>}\let\endItem=\empty} 11.13 - {\ifvmode \IgnorePar\fi 11.14 - \EndP\HCode{</li></ul>}\ShowPar} 11.15 - {\endItem \def\endItem{\EndP\Tg</span>}\HCode{<li><span class="dt">}} 11.16 - {\HCode{</span><span class="dd">}} 11.17 -\def\textbullet{} 11.18 - 11.19 -\begin{document} 11.20 - 11.21 -\EndPreamble
12.1 --- a/fr/branch.tex Sun Aug 16 03:41:39 2009 +0200 12.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 12.3 @@ -1,392 +0,0 @@ 12.4 -\chapter{Managing releases and branchy development} 12.5 -\label{chap:branch} 12.6 - 12.7 -Mercurial provides several mechanisms for you to manage a project that 12.8 -is making progress on multiple fronts at once. To understand these 12.9 -mechanisms, let's first take a brief look at a fairly normal software 12.10 -project structure. 12.11 - 12.12 -Many software projects issue periodic ``major'' releases that contain 12.13 -substantial new features. In parallel, they may issue ``minor'' 12.14 -releases. These are usually identical to the major releases off which 12.15 -they're based, but with a few bugs fixed. 12.16 - 12.17 -In this chapter, we'll start by talking about how to keep records of 12.18 -project milestones such as releases. We'll then continue on to talk 12.19 -about the flow of work between different phases of a project, and how 12.20 -Mercurial can help you to isolate and manage this work. 12.21 - 12.22 -\section{Giving a persistent name to a revision} 12.23 - 12.24 -Once you decide that you'd like to call a particular revision a 12.25 -``release'', it's a good idea to record the identity of that revision. 12.26 -This will let you reproduce that release at a later date, for whatever 12.27 -purpose you might need at the time (reproducing a bug, porting to a 12.28 -new platform, etc). 12.29 -\interaction{tag.init} 12.30 - 12.31 -Mercurial lets you give a permanent name to any revision using the 12.32 -\hgcmd{tag} command. Not surprisingly, these names are called 12.33 -``tags''. 12.34 -\interaction{tag.tag} 12.35 - 12.36 -A tag is nothing more than a ``symbolic name'' for a revision. Tags 12.37 -exist purely for your convenience, so that you have a handy permanent 12.38 -way to refer to a revision; Mercurial doesn't interpret the tag names 12.39 -you use in any way. Neither does Mercurial place any restrictions on 12.40 -the name of a tag, beyond a few that are necessary to ensure that a 12.41 -tag can be parsed unambiguously. A tag name cannot contain any of the 12.42 -following characters: 12.43 -\begin{itemize} 12.44 -\item Colon (ASCII 58, ``\texttt{:}'') 12.45 -\item Carriage return (ASCII 13, ``\Verb+\r+'') 12.46 -\item Newline (ASCII 10, ``\Verb+\n+'') 12.47 -\end{itemize} 12.48 - 12.49 -You can use the \hgcmd{tags} command to display the tags present in 12.50 -your repository. In the output, each tagged revision is identified 12.51 -first by its name, then by revision number, and finally by the unique 12.52 -hash of the revision. 12.53 -\interaction{tag.tags} 12.54 -Notice that \texttt{tip} is listed in the output of \hgcmd{tags}. The 12.55 -\texttt{tip} tag is a special ``floating'' tag, which always 12.56 -identifies the newest revision in the repository. 12.57 - 12.58 -In the output of the \hgcmd{tags} command, tags are listed in reverse 12.59 -order, by revision number. This usually means that recent tags are 12.60 -listed before older tags. It also means that \texttt{tip} is always 12.61 -going to be the first tag listed in the output of \hgcmd{tags}. 12.62 - 12.63 -When you run \hgcmd{log}, if it displays a revision that has tags 12.64 -associated with it, it will print those tags. 12.65 -\interaction{tag.log} 12.66 - 12.67 -Any time you need to provide a revision~ID to a Mercurial command, the 12.68 -command will accept a tag name in its place. Internally, Mercurial 12.69 -will translate your tag name into the corresponding revision~ID, then 12.70 -use that. 12.71 -\interaction{tag.log.v1.0} 12.72 - 12.73 -There's no limit on the number of tags you can have in a repository, 12.74 -or on the number of tags that a single revision can have. As a 12.75 -practical matter, it's not a great idea to have ``too many'' (a number 12.76 -which will vary from project to project), simply because tags are 12.77 -supposed to help you to find revisions. If you have lots of tags, the 12.78 -ease of using them to identify revisions diminishes rapidly. 12.79 - 12.80 -For example, if your project has milestones as frequent as every few 12.81 -days, it's perfectly reasonable to tag each one of those. But if you 12.82 -have a continuous build system that makes sure every revision can be 12.83 -built cleanly, you'd be introducing a lot of noise if you were to tag 12.84 -every clean build. Instead, you could tag failed builds (on the 12.85 -assumption that they're rare!), or simply not use tags to track 12.86 -buildability. 12.87 - 12.88 -If you want to remove a tag that you no longer want, use 12.89 -\hgcmdargs{tag}{--remove}. 12.90 -\interaction{tag.remove} 12.91 -You can also modify a tag at any time, so that it identifies a 12.92 -different revision, by simply issuing a new \hgcmd{tag} command. 12.93 -You'll have to use the \hgopt{tag}{-f} option to tell Mercurial that 12.94 -you \emph{really} want to update the tag. 12.95 -\interaction{tag.replace} 12.96 -There will still be a permanent record of the previous identity of the 12.97 -tag, but Mercurial will no longer use it. There's thus no penalty to 12.98 -tagging the wrong revision; all you have to do is turn around and tag 12.99 -the correct revision once you discover your error. 12.100 - 12.101 -Mercurial stores tags in a normal revision-controlled file in your 12.102 -repository. If you've created any tags, you'll find them in a file 12.103 -named \sfilename{.hgtags}. When you run the \hgcmd{tag} command, 12.104 -Mercurial modifies this file, then automatically commits the change to 12.105 -it. This means that every time you run \hgcmd{tag}, you'll see a 12.106 -corresponding changeset in the output of \hgcmd{log}. 12.107 -\interaction{tag.tip} 12.108 - 12.109 -\subsection{Handling tag conflicts during a merge} 12.110 - 12.111 -You won't often need to care about the \sfilename{.hgtags} file, but 12.112 -it sometimes makes its presence known during a merge. The format of 12.113 -the file is simple: it consists of a series of lines. Each line 12.114 -starts with a changeset hash, followed by a space, followed by the 12.115 -name of a tag. 12.116 - 12.117 -If you're resolving a conflict in the \sfilename{.hgtags} file during 12.118 -a merge, there's one twist to modifying the \sfilename{.hgtags} file: 12.119 -when Mercurial is parsing the tags in a repository, it \emph{never} 12.120 -reads the working copy of the \sfilename{.hgtags} file. Instead, it 12.121 -reads the \emph{most recently committed} revision of the file. 12.122 - 12.123 -An unfortunate consequence of this design is that you can't actually 12.124 -verify that your merged \sfilename{.hgtags} file is correct until 12.125 -\emph{after} you've committed a change. So if you find yourself 12.126 -resolving a conflict on \sfilename{.hgtags} during a merge, be sure to 12.127 -run \hgcmd{tags} after you commit. If it finds an error in the 12.128 -\sfilename{.hgtags} file, it will report the location of the error, 12.129 -which you can then fix and commit. You should then run \hgcmd{tags} 12.130 -again, just to be sure that your fix is correct. 12.131 - 12.132 -\subsection{Tags and cloning} 12.133 - 12.134 -You may have noticed that the \hgcmd{clone} command has a 12.135 -\hgopt{clone}{-r} option that lets you clone an exact copy of the 12.136 -repository as of a particular changeset. The new clone will not 12.137 -contain any project history that comes after the revision you 12.138 -specified. This has an interaction with tags that can surprise the 12.139 -unwary. 12.140 - 12.141 -Recall that a tag is stored as a revision to the \sfilename{.hgtags} 12.142 -file, so that when you create a tag, the changeset in which it's 12.143 -recorded necessarily refers to an older changeset. When you run 12.144 -\hgcmdargs{clone}{-r foo} to clone a repository as of tag 12.145 -\texttt{foo}, the new clone \emph{will not contain the history that 12.146 - created the tag} that you used to clone the repository. The result 12.147 -is that you'll get exactly the right subset of the project's history 12.148 -in the new repository, but \emph{not} the tag you might have expected. 12.149 - 12.150 -\subsection{When permanent tags are too much} 12.151 - 12.152 -Since Mercurial's tags are revision controlled and carried around with 12.153 -a project's history, everyone you work with will see the tags you 12.154 -create. But giving names to revisions has uses beyond simply noting 12.155 -that revision \texttt{4237e45506ee} is really \texttt{v2.0.2}. If 12.156 -you're trying to track down a subtle bug, you might want a tag to 12.157 -remind you of something like ``Anne saw the symptoms with this 12.158 -revision''. 12.159 - 12.160 -For cases like this, what you might want to use are \emph{local} tags. 12.161 -You can create a local tag with the \hgopt{tag}{-l} option to the 12.162 -\hgcmd{tag} command. This will store the tag in a file called 12.163 -\sfilename{.hg/localtags}. Unlike \sfilename{.hgtags}, 12.164 -\sfilename{.hg/localtags} is not revision controlled. Any tags you 12.165 -create using \hgopt{tag}{-l} remain strictly local to the repository 12.166 -you're currently working in. 12.167 - 12.168 -\section{The flow of changes---big picture vs. little} 12.169 - 12.170 -To return to the outline I sketched at the beginning of a chapter, 12.171 -let's think about a project that has multiple concurrent pieces of 12.172 -work under development at once. 12.173 - 12.174 -There might be a push for a new ``main'' release; a new minor bugfix 12.175 -release to the last main release; and an unexpected ``hot fix'' to an 12.176 -old release that is now in maintenance mode. 12.177 - 12.178 -The usual way people refer to these different concurrent directions of 12.179 -development is as ``branches''. However, we've already seen numerous 12.180 -times that Mercurial treats \emph{all of history} as a series of 12.181 -branches and merges. Really, what we have here is two ideas that are 12.182 -peripherally related, but which happen to share a name. 12.183 -\begin{itemize} 12.184 -\item ``Big picture'' branches represent the sweep of a project's 12.185 - evolution; people give them names, and talk about them in 12.186 - conversation. 12.187 -\item ``Little picture'' branches are artefacts of the day-to-day 12.188 - activity of developing and merging changes. They expose the 12.189 - narrative of how the code was developed. 12.190 -\end{itemize} 12.191 - 12.192 -\section{Managing big-picture branches in repositories} 12.193 - 12.194 -The easiest way to isolate a ``big picture'' branch in Mercurial is in 12.195 -a dedicated repository. If you have an existing shared 12.196 -repository---let's call it \texttt{myproject}---that reaches a ``1.0'' 12.197 -milestone, you can start to prepare for future maintenance releases on 12.198 -top of version~1.0 by tagging the revision from which you prepared 12.199 -the~1.0 release. 12.200 -\interaction{branch-repo.tag} 12.201 -You can then clone a new shared \texttt{myproject-1.0.1} repository as 12.202 -of that tag. 12.203 -\interaction{branch-repo.clone} 12.204 - 12.205 -Afterwards, if someone needs to work on a bug fix that ought to go 12.206 -into an upcoming~1.0.1 minor release, they clone the 12.207 -\texttt{myproject-1.0.1} repository, make their changes, and push them 12.208 -back. 12.209 -\interaction{branch-repo.bugfix} 12.210 -Meanwhile, development for the next major release can continue, 12.211 -isolated and unabated, in the \texttt{myproject} repository. 12.212 -\interaction{branch-repo.new} 12.213 - 12.214 -\section{Don't repeat yourself: merging across branches} 12.215 - 12.216 -In many cases, if you have a bug to fix on a maintenance branch, the 12.217 -chances are good that the bug exists on your project's main branch 12.218 -(and possibly other maintenance branches, too). It's a rare developer 12.219 -who wants to fix the same bug multiple times, so let's look at a few 12.220 -ways that Mercurial can help you to manage these bugfixes without 12.221 -duplicating your work. 12.222 - 12.223 -In the simplest instance, all you need to do is pull changes from your 12.224 -maintenance branch into your local clone of the target branch. 12.225 -\interaction{branch-repo.pull} 12.226 -You'll then need to merge the heads of the two branches, and push back 12.227 -to the main branch. 12.228 -\interaction{branch-repo.merge} 12.229 - 12.230 -\section{Naming branches within one repository} 12.231 - 12.232 -In most instances, isolating branches in repositories is the right 12.233 -approach. Its simplicity makes it easy to understand; and so it's 12.234 -hard to make mistakes. There's a one-to-one relationship between 12.235 -branches you're working in and directories on your system. This lets 12.236 -you use normal (non-Mercurial-aware) tools to work on files within a 12.237 -branch/repository. 12.238 - 12.239 -If you're more in the ``power user'' category (\emph{and} your 12.240 -collaborators are too), there is an alternative way of handling 12.241 -branches that you can consider. I've already mentioned the 12.242 -human-level distinction between ``small picture'' and ``big picture'' 12.243 -branches. While Mercurial works with multiple ``small picture'' 12.244 -branches in a repository all the time (for example after you pull 12.245 -changes in, but before you merge them), it can \emph{also} work with 12.246 -multiple ``big picture'' branches. 12.247 - 12.248 -The key to working this way is that Mercurial lets you assign a 12.249 -persistent \emph{name} to a branch. There always exists a branch 12.250 -named \texttt{default}. Even before you start naming branches 12.251 -yourself, you can find traces of the \texttt{default} branch if you 12.252 -look for them. 12.253 - 12.254 -As an example, when you run the \hgcmd{commit} command, and it pops up 12.255 -your editor so that you can enter a commit message, look for a line 12.256 -that contains the text ``\texttt{HG: branch default}'' at the bottom. 12.257 -This is telling you that your commit will occur on the branch named 12.258 -\texttt{default}. 12.259 - 12.260 -To start working with named branches, use the \hgcmd{branches} 12.261 -command. This command lists the named branches already present in 12.262 -your repository, telling you which changeset is the tip of each. 12.263 -\interaction{branch-named.branches} 12.264 -Since you haven't created any named branches yet, the only one that 12.265 -exists is \texttt{default}. 12.266 - 12.267 -To find out what the ``current'' branch is, run the \hgcmd{branch} 12.268 -command, giving it no arguments. This tells you what branch the 12.269 -parent of the current changeset is on. 12.270 -\interaction{branch-named.branch} 12.271 - 12.272 -To create a new branch, run the \hgcmd{branch} command again. This 12.273 -time, give it one argument: the name of the branch you want to create. 12.274 -\interaction{branch-named.create} 12.275 - 12.276 -After you've created a branch, you might wonder what effect the 12.277 -\hgcmd{branch} command has had. What do the \hgcmd{status} and 12.278 -\hgcmd{tip} commands report? 12.279 -\interaction{branch-named.status} 12.280 -Nothing has changed in the working directory, and there's been no new 12.281 -history created. As this suggests, running the \hgcmd{branch} command 12.282 -has no permanent effect; it only tells Mercurial what branch name to 12.283 -use the \emph{next} time you commit a changeset. 12.284 - 12.285 -When you commit a change, Mercurial records the name of the branch on 12.286 -which you committed. Once you've switched from the \texttt{default} 12.287 -branch to another and committed, you'll see the name of the new branch 12.288 -show up in the output of \hgcmd{log}, \hgcmd{tip}, and other commands 12.289 -that display the same kind of output. 12.290 -\interaction{branch-named.commit} 12.291 -The \hgcmd{log}-like commands will print the branch name of every 12.292 -changeset that's not on the \texttt{default} branch. As a result, if 12.293 -you never use named branches, you'll never see this information. 12.294 - 12.295 -Once you've named a branch and committed a change with that name, 12.296 -every subsequent commit that descends from that change will inherit 12.297 -the same branch name. You can change the name of a branch at any 12.298 -time, using the \hgcmd{branch} command. 12.299 -\interaction{branch-named.rebranch} 12.300 -In practice, this is something you won't do very often, as branch 12.301 -names tend to have fairly long lifetimes. (This isn't a rule, just an 12.302 -observation.) 12.303 - 12.304 -\section{Dealing with multiple named branches in a repository} 12.305 - 12.306 -If you have more than one named branch in a repository, Mercurial will 12.307 -remember the branch that your working directory on when you start a 12.308 -command like \hgcmd{update} or \hgcmdargs{pull}{-u}. It will update 12.309 -the working directory to the tip of this branch, no matter what the 12.310 -``repo-wide'' tip is. To update to a revision that's on a different 12.311 -named branch, you may need to use the \hgopt{update}{-C} option to 12.312 -\hgcmd{update}. 12.313 - 12.314 -This behaviour is a little subtle, so let's see it in action. First, 12.315 -let's remind ourselves what branch we're currently on, and what 12.316 -branches are in our repository. 12.317 -\interaction{branch-named.parents} 12.318 -We're on the \texttt{bar} branch, but there also exists an older 12.319 -\hgcmd{foo} branch. 12.320 - 12.321 -We can \hgcmd{update} back and forth between the tips of the 12.322 -\texttt{foo} and \texttt{bar} branches without needing to use the 12.323 -\hgopt{update}{-C} option, because this only involves going backwards 12.324 -and forwards linearly through our change history. 12.325 -\interaction{branch-named.update-switchy} 12.326 - 12.327 -If we go back to the \texttt{foo} branch and then run \hgcmd{update}, 12.328 -it will keep us on \texttt{foo}, not move us to the tip of 12.329 -\texttt{bar}. 12.330 -\interaction{branch-named.update-nothing} 12.331 - 12.332 -Committing a new change on the \texttt{foo} branch introduces a new 12.333 -head. 12.334 -\interaction{branch-named.foo-commit} 12.335 - 12.336 -\section{Branch names and merging} 12.337 - 12.338 -As you've probably noticed, merges in Mercurial are not symmetrical. 12.339 -Let's say our repository has two heads, 17 and 23. If I 12.340 -\hgcmd{update} to 17 and then \hgcmd{merge} with 23, Mercurial records 12.341 -17 as the first parent of the merge, and 23 as the second. Whereas if 12.342 -I \hgcmd{update} to 23 and then \hgcmd{merge} with 17, it records 23 12.343 -as the first parent, and 17 as the second. 12.344 - 12.345 -This affects Mercurial's choice of branch name when you merge. After 12.346 -a merge, Mercurial will retain the branch name of the first parent 12.347 -when you commit the result of the merge. If your first parent's 12.348 -branch name is \texttt{foo}, and you merge with \texttt{bar}, the 12.349 -branch name will still be \texttt{foo} after you merge. 12.350 - 12.351 -It's not unusual for a repository to contain multiple heads, each with 12.352 -the same branch name. Let's say I'm working on the \texttt{foo} 12.353 -branch, and so are you. We commit different changes; I pull your 12.354 -changes; I now have two heads, each claiming to be on the \texttt{foo} 12.355 -branch. The result of a merge will be a single head on the 12.356 -\texttt{foo} branch, as you might hope. 12.357 - 12.358 -But if I'm working on the \texttt{bar} branch, and I merge work from 12.359 -the \texttt{foo} branch, the result will remain on the \texttt{bar} 12.360 -branch. 12.361 -\interaction{branch-named.merge} 12.362 - 12.363 -To give a more concrete example, if I'm working on the 12.364 -\texttt{bleeding-edge} branch, and I want to bring in the latest fixes 12.365 -from the \texttt{stable} branch, Mercurial will choose the ``right'' 12.366 -(\texttt{bleeding-edge}) branch name when I pull and merge from 12.367 -\texttt{stable}. 12.368 - 12.369 -\section{Branch naming is generally useful} 12.370 - 12.371 -You shouldn't think of named branches as applicable only to situations 12.372 -where you have multiple long-lived branches cohabiting in a single 12.373 -repository. They're very useful even in the one-branch-per-repository 12.374 -case. 12.375 - 12.376 -In the simplest case, giving a name to each branch gives you a 12.377 -permanent record of which branch a changeset originated on. This 12.378 -gives you more context when you're trying to follow the history of a 12.379 -long-lived branchy project. 12.380 - 12.381 -If you're working with shared repositories, you can set up a 12.382 -\hook{pretxnchangegroup} hook on each that will block incoming changes 12.383 -that have the ``wrong'' branch name. This provides a simple, but 12.384 -effective, defence against people accidentally pushing changes from a 12.385 -``bleeding edge'' branch to a ``stable'' branch. Such a hook might 12.386 -look like this inside the shared repo's \hgrc. 12.387 -\begin{codesample2} 12.388 - [hooks] 12.389 - pretxnchangegroup.branch = hg heads --template '{branches} ' | grep mybranch 12.390 -\end{codesample2} 12.391 - 12.392 -%%% Local Variables: 12.393 -%%% mode: latex 12.394 -%%% TeX-master: "00book" 12.395 -%%% End:
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 13.2 +++ b/fr/ch00-preface.xml Sun Aug 16 04:58:01 2009 +0200 13.3 @@ -0,0 +1,78 @@ 13.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 13.5 + 13.6 +<para>\chapter*{Préface} 13.7 +\addcontentsline{toc}{chapter}{Préface} 13.8 +\label{chap:preface}</para> 13.9 + 13.10 +<para>La gestion de source distribuée est encore un territoire peu exploré 13.11 +et qui, par conséquent, a grandi très rapidement grâce à la seule 13.12 +volonté de ses explorateurs.</para> 13.13 + 13.14 +<para>Je rédige un livre sur ce sujet car je crois que c'est un sujet 13.15 +important qui mérite bien un guide du <quote>terrain</quote>. J'ai choisi d'écrire 13.16 +ce livre sur Mercurial car c'est l'outil le plus simple pour découvrir 13.17 +ce nouveau monde et qu'en outre, il répond très bien au besoin de 13.18 +réels environnements, là où d'autres outils de gestion de source n'y 13.19 +parviennent pas.</para> 13.20 + 13.21 +<sect1> 13.22 +<title>Cet ouvrage est un travail en cours</title> 13.23 + 13.24 +<para>Je publie ce livre tout en continuant à l'écrire, dans l'espoir qu'il 13.25 +vous sera utile. J'espère aussi que les lecteurs pourront ainsi y contribuer 13.26 +si ils le souhaitent.</para> 13.27 + 13.28 +</sect1> 13.29 +<sect1> 13.30 +<title>À propros des exemples de ce livre</title> 13.31 + 13.32 +<para>Ce livre a une approche particulière des exemples d'exécution. Ils sont 13.33 +toujours <quote>dynamiques</quote>&emdash;chacun est le résultat d'un script shell qui 13.34 +exécute les commandes Mercurial que vous voyez. Chaque fois qu'une 13.35 +image du livre est construite à partir des sources, tous les scripts d'exemple 13.36 +sont exécutés automatiquement, et les résultats comparés à ceux attendus.</para> 13.37 + 13.38 +<para>Cette approche a l'avantage de garantir que les exemples sont toujours 13.39 +justes ; ils montrent <emphasis>exactement</emphasis> le comportement de la version de 13.40 +Mercurial spécifiée dans la couverture de ce livre. Si je mets à jour cette 13.41 +version, et que les commandes changent, la génération du livre échouera.</para> 13.42 + 13.43 +<para>Il y a un petit désavantage à cette approche, les dates et les 13.44 +durées que vous verrez dans ces exemples ont tendances à être 13.45 +<quote>réduits</quote> de manière très différente d'une exécution manuelle. Un être humain 13.46 +ne peut exécuter qu'une commande toutes les secondes, alors que mes scripts 13.47 +automatisés en exécutent plusieurs en une seule seconde.</para> 13.48 + 13.49 +<para>Ainsi, en une seule seconde, plusieurs <quote>commits</quote> peuvent avoir lieu 13.50 +au sein d'un exemple. Vous le constatez, entre autres, dans les 13.51 +exemples sur <literal role="hg-ext">bisect</literal>, dans la section <xref linkend="sec:undo:bisect"/>.</para> 13.52 + 13.53 +<para>En conséquence, quand vous lisez les exemples, n'accordez pas trop 13.54 +d'importance aux dates et aux durées d'exécution des commandes. Mais 13.55 +<emphasis>soyez sûr</emphasis> que le comportement que vous voyez est cohérent et 13.56 +reproductible. 13.57 +</para> 13.58 + 13.59 +</sect1> 13.60 +<sect1> 13.61 +<title>Colophon&emdash;Cet ouvrage est libre</title> 13.62 + 13.63 +<para>Ce livre est publié sous la licence <quote>Open Publication License</quote> 13.64 +\footnote{Pour plus de renseignements : 13.65 +<ulink url="http://opencontent.org/openpub/">http://opencontent.org/openpub/</ulink>{Open Publication License} }, 13.66 +et est construit uniquement à l'aide de logiciels libres. Il est mis 13.67 +en forme avec \LaTex{}; et les illustrations sont réalisées avec 13.68 +<ulink url="http://www.inkscape.org/">Inkscape</ulink>. 13.69 +</para> 13.70 + 13.71 +<para>L'ensemble des fichiers sources de cet ouvrage est publié dans un 13.72 +dépot mercurial <ulink url="http://hg.serpentine.com/mercurial/book">http://hg.serpentine.com/mercurial/book</ulink>. 13.73 +</para> 13.74 + 13.75 +</sect1> 13.76 + 13.77 +<!-- 13.78 +local variables: 13.79 +sgml-parent-document: ("00book.xml" "book" "chapter") 13.80 +end: 13.81 +--> 13.82 \ No newline at end of file
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 14.2 +++ b/fr/ch01-intro.xml Sun Aug 16 04:58:01 2009 +0200 14.3 @@ -0,0 +1,744 @@ 14.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 14.5 + 14.6 +<chapter> 14.7 +<title>Introduction</title> 14.8 +<para>\label{chap:intro}</para> 14.9 + 14.10 +<sect1> 14.11 +<title>À propos de la gestion source</title> 14.12 + 14.13 +<para>La gestion de sources est un processus permettant de gérer différentes 14.14 +versions de la même information. Dans sa forme la plus simple, c'est 14.15 +ce que tout le monde fait manuellement : quand vous modifiez 14.16 +un fichier, vous le sauvegardez sous un nouveau nom contenant un numéro, 14.17 +à chaque fois plus grand que celui de la version précédente.</para> 14.18 + 14.19 +<para>Ce genre de gestion de version manuelle est cependant facilement sujette 14.20 +à des erreurs, ainsi, depuis longtemps, des logiciels existent pour 14.21 +résoudre cette problématique. Les premiers outils de gestion de sources 14.22 +étaient destinés à aider un seul utilisateur, à automatiser la gestion 14.23 +des versions d'un seul fichier. Dans les dernières décades, cette cible 14.24 +s'est largement agrandie, ils gèrent désormais de multiples fichiers, et 14.25 +aident un grand nombre de personnes à travailler ensemble. Les outils les 14.26 +plus modernes n'ont aucune difficulté à gérer plusieurs milliers de 14.27 +personnes travaillant ensemble sur des projets regroupant plusieurs 14.28 +centaines de milliers de fichiers.</para> 14.29 + 14.30 +<sect2> 14.31 +<title>Pourquoi utiliser un gestionnaire de source ?</title> 14.32 + 14.33 +<para>Il y a de nombreuses raisons pour que vous ou votre équipe souhaitiez 14.34 +utiliser un outil automatisant la gestion de version pour votre projet.</para> 14.35 +<itemizedlist> 14.36 +<listitem><para>L'outil se chargera de suivre l'évolution de votre projet, sans 14.37 +que vous n'ayez à le faire. Pour chaque modification, vous aurez à votre 14.38 +disposition un journal indiquant <emphasis>qui</emphasis> a fait quoi, <emphasis>pourquoi</emphasis> 14.39 +ils l'ont fait, <emphasis>quand</emphasis> ils l'ont fait, et <emphasis>ce</emphasis> qu'ils ont 14.40 +modifiés.</para> 14.41 +</listitem> 14.42 +<listitem><para>Quand vous travaillez avec d'autres personnes, les logiciels de 14.43 +gestion de source facilitent le travail collaboratif. Par exemple, quand 14.44 +plusieurs personnes font, plus ou moins simultanément, des modifications 14.45 +incompatibles, le logiciel vous aidera à identifier et à résoudre les conflits.</para> 14.46 +</listitem> 14.47 +<listitem><para>L'outil vous aidera à réparer vos erreurs. Si vous effectuez un changement 14.48 +qui se révèle être une erreur, vous pourrez revenir à une version 14.49 +antérieure d'un fichier ou même d'un ensemble de fichiers. En fait, un outil de 14.50 +gestion de source <emphasis>vraiment</emphasis> efficace vous permettra d'identifier à quel 14.51 +moment le problème est apparu (voir la section <xref linkend="sec:undo:bisect"/> pour plus 14.52 +de détails).</para> 14.53 +</listitem> 14.54 +<listitem><para>L'outil vous permettra aussi de travailler sur plusieurs versions différentes 14.55 +de votre projet et à gérer l'écart entre chacune.</para> 14.56 +</listitem></itemizedlist> 14.57 +<para>La plupart de ces raisons ont autant d'importances &emdash;du moins en théorie&emdash; que 14.58 +vous travailliez sur un projet pour vous, ou avec une centaine d'autres 14.59 +personnes. 14.60 +</para> 14.61 + 14.62 +<para>Une question fondamentale à propos des outils de gestion de source, qu'il s'agisse 14.63 +du projet d'une personne ou d'une grande équipe, est quels sont ses 14.64 +<emphasis>avantages</emphasis> par rapport à ses <emphasis>coûts</emphasis>. Un outil qui est difficile à 14.65 +utiliser ou à comprendre exigera un lourd effort d'adaptation. 14.66 +</para> 14.67 + 14.68 +<para>Un projet de cinq milles personnes s'effondrera très certainement de lui même 14.69 +sans aucun processus et outil de gestion de source. Dans ce cas, le coût 14.70 +d'utilisation d'un logiciel de gestion de source est dérisoire puisque 14.71 +<emphasis>sans</emphasis>, l'échec est presque garanti. 14.72 +</para> 14.73 + 14.74 +<para>D'un autre coté, un <quote>rapide hack</quote> d'une personne peut sembler un contexte 14.75 +bien pauvre pour utiliser un outil de gestion de source, car, bien évidement 14.76 +le coût d'utilisation dépasse le coût total du projet. N'est ce pas ? 14.77 +</para> 14.78 + 14.79 +<para>Mercurial supporte ces <emphasis>deux</emphasis> échelles de travail. Vous pouvez apprendre 14.80 +les bases en quelques minutes seulement, et, grâce à sa performance, vous pouvez 14.81 +l'utiliser avec facilité sur le plus petit des projets. Cette simplicité 14.82 +signifie que vous n'avez pas de concept obscurs ou de séquence de commandes 14.83 +défiant l'imagination, sans aucune corrélation avec \emph{ce que vous êtes 14.84 +vraiment en train de faire}. En même temps, ces mêmes performances et sa 14.85 +nature <quote>peer-to-peer</quote> vous permettent d'augmenter, sans difficulté, son 14.86 +utilisation à de très grands projets. 14.87 +</para> 14.88 + 14.89 +<para>Aucun outil de gestion de source ne peut sauver un projet mal mené, mais un 14.90 +bon outil peut rendre beaucoup plus fluide votre travail. 14.91 +</para> 14.92 + 14.93 +</sect2> 14.94 +<sect2> 14.95 +<title>Les multiples noms de la gestion de source</title> 14.96 + 14.97 +<para>La gestion de source\footnote{NdT: J'ai utilisé systématiquement le terme 14.98 +<quote>gestion de source</quote> à travers tout l'ouvrage. Ce n'est pas forcement la 14.99 +meilleure traduction, et ceci peut rendre la lecture un peu lourde, mais je 14.100 +pense que le document y gagne en clarté et en précision.} est un domaine 14.101 +divers, tellement qu'il n'existe pas une seul nom ou acronyme pour le désigner. 14.102 +Voilà quelqu'uns des noms ou 14.103 +acronymes que vous rencontrerez le plus souvent\footnote{NdT: J'ai conservé la 14.104 +liste des noms en anglais pour des raisons de commodité (ils sont plus 14.105 +<quote>googelable</quote>). En outre, j'ai opté pour conserver l'ensemble des opérations de 14.106 +Mercurial (\textit{commit},\textit{push}, \textit{pull},...) en anglais, là 14.107 +aussi pour faciliter la lecture d'autres documents en anglais, ainsi que 14.108 +l'utilisation de Mercurial}. 14.109 +</para> 14.110 + 14.111 +<para>: 14.112 +</para> 14.113 +<itemizedlist> 14.114 +<listitem><para>\textit{Revision control (RCS)} ; 14.115 +</para> 14.116 +</listitem> 14.117 +<listitem><para>Software configuration management (SCM), ou \textit{configuration management} ; 14.118 +</para> 14.119 +</listitem> 14.120 +<listitem><para>\textit{Source code management} ; 14.121 +</para> 14.122 +</listitem> 14.123 +<listitem><para>\textit{Source code control}, ou \textit{source control} ; 14.124 +</para> 14.125 +</listitem> 14.126 +<listitem><para>\textit{Version control (VCS)}. 14.127 +</para> 14.128 +</listitem></itemizedlist> 14.129 + 14.130 +<para>Certaines personnes prétendent que ces termes ont en fait des sens 14.131 +différents mais en pratique ils se recouvrent tellement qu'il n'y a pas 14.132 +réellement de manière pertinente de les distinguer. 14.133 +</para> 14.134 + 14.135 +</sect2> 14.136 +</sect1> 14.137 +<sect1> 14.138 +<title>Une courte histoire de la gestion de source</title> 14.139 + 14.140 +<para>Le plus célèbre des anciens outils de gestion de source est \textit{SCCS 14.141 +(Source Code Control System)}, que Marc Rochkind conçu dans les laboratoires de 14.142 +recherche de Bell (\textit{Bell Labs}), dans le début des années 70. 14.143 +\textit{SCCS} ne fonctionnait que sur des fichiers individuels, et obligeait chaque 14.144 +personne travaillant sur le projet d'avoir un accès à un répertoire de 14.145 +travail commun, sur le même système. Seulement une seule personne pouvait 14.146 +modifier un fichier au même moment, ce fonctionnement était assuré par 14.147 +l'utilisation de verrou (<quote>lock</quote>). Il était courant que des personnes 14.148 +verrouillent des fichiers, et plus tard, oublient de le déverrouiller; 14.149 +empêchant n'importe qui d'autre de travailler sur ces fichiers sans l'aide de 14.150 +l'administrateur... 14.151 +</para> 14.152 + 14.153 +<para>Walter Tichy a développé une alternative libre à \textit{SCCS} au début des 14.154 +années 80, qu'il nomma \textit{RSC (Revison Control System)}. Comme 14.155 +\textit{SCCS}, \textit{RCS} demandait aux développeurs de travailler sur le même 14.156 +répertoire partagé, et de verrouiller les 14.157 +fichiers pour se prémunir de tout conflit issu de modifications concurrentes. 14.158 +</para> 14.159 + 14.160 +<para>Un peu plus tard dans les années 1980, Dick Grune utilisa \textit{RCS} comme 14.161 +une brique de base pour un ensemble de scripts \textit{shell} qu'il intitula 14.162 +cmt, avant de la renommer en \textit{CVS (Concurrent Versions System)}. La 14.163 +grande innovation de CVS était que les développeurs pouvaient travailler 14.164 +simultanément et indépendamment dans leur propre espace de travail. Ces espaces 14.165 +de travail privés assuraient que les développeurs ne se marchent pas 14.166 +mutuellement sur les pieds, comme c'était souvent le cas avec RCS et SCCS. 14.167 +Chaque développeur disposait donc de sa copie de tous les fichiers du projet, 14.168 +et ils pouvaient donc librement les modifier. Ils devaient néanmoins effectuer 14.169 +la <quote>fusion</quote> (\textit{<quote>merge</quote>}) de leurs fichiers, avant d'effectuer le 14.170 +<quote>commit</quote> de leur modifications sur le dépôt central. 14.171 +</para> 14.172 + 14.173 +<para>Brian Berliner reprit les scripts de Grune's et les réécrit en C, qu'il publia 14.174 +en 1989. Depuis, ce code a été modifié jusqu'à devenir la version moderne de 14.175 +CVS. CVS a acquis ainsi la capacité de fonctionner en réseau, transformant son 14.176 +architecture en client/serveur. L'architecture de CVS est centralisée, seul le 14.177 +serveur a une copie de l'historique du projet. L'espace de travail client ne 14.178 +contient qu'une copie de la dernière version du projet, et quelques métadonnées 14.179 +pour indiquer où le serveur se trouve. CVS a été un grand succès, aujourd'hui 14.180 +il est probablement l'outil de gestion de contrôle le plus utilisé au monde. 14.181 +</para> 14.182 + 14.183 +<para>Au début des années 1990, Sun Microsystmes développa un premier outil de 14.184 +gestion de source distribué, nommé TeamWare. Un espace de travail TeamWare 14.185 +contient une copie complète de l'historique du projet. TeamWare n'a pas de 14.186 +notion de dépôt central. (CVS utilisait RCS pour le stockage de l'historique, 14.187 +TeamWare utilisait SCCS). 14.188 +</para> 14.189 + 14.190 +<para>Alors que les années 1990 avançaient, les utilisateurs ont pris conscience d'un 14.191 +certain nombre de problèmes avec CVS. Il enregistrait simultanément des 14.192 +modifications sur différents fichiers individuellement, au lieu de les 14.193 +regrouper dans une seule opération cohérente et atomique. Il ne gère pas bien 14.194 +sa hiérarchie de fichier, il est donc assez aisé de créer le chaos en renommant 14.195 +les fichiers et les répertoires. Pire encore, son code source est difficile à 14.196 +lire et à maintenir, ce qui agrandit largement le <quote>niveau de souffrance</quote> 14.197 +associé à la réparation de ces problèmes d'architecture de manière prohibitive. 14.198 +</para> 14.199 + 14.200 +<para>En 2001, Jim Blandy et Karl Fogel, deux développeurs qui avaient travaillé sur 14.201 +CVS, initièrent un projet pour le remplacer par un outil qui aurait une 14.202 +meilleure architecture et un code plus propre. Le résultat, Subversion, ne 14.203 +quitte pas le modèle centralisé et client/server de CVS, mais ajoute les 14.204 +opérations de <quote>commit</quote> atomique sur de multiples fichiers, une meilleure 14.205 +gestion des espaces de noms, et d'autres fonctionnalités qui en font un 14.206 +meilleur outil que CVS. Depuis sa première publication, il est rapidement 14.207 +devenu très populaire. 14.208 +</para> 14.209 + 14.210 +<para>Plus ou moins simultanément, Graydon Hoare a commencé sur l'ambitieux 14.211 +système de gestion distribué Monotone. Bien que Monotone corrige plusieurs 14.212 +défauts de CVS's tout en offrant une architecture <quote>peer-to-peer</quote>, il va aussi 14.213 +plus loin que la plupart des outils de révision de manière assez innovante. Il 14.214 +utilise des <quote>hash</quote> cryptographiques comme identifiants, et il a une notion 14.215 +complète de <quote>confiance</quote> du code issu des différentes sources. 14.216 +</para> 14.217 + 14.218 +<para>Mercurial est né en 2005. Bien que très influencé par Monotone, Mercurial se 14.219 +concentre sur la facilité d'utilisation, les performances et la capacité à 14.220 +monter en charge pour de très gros projets. 14.221 +</para> 14.222 + 14.223 +</sect1> 14.224 +<sect1> 14.225 +<title>Tendances de la gestion de source</title> 14.226 + 14.227 +<para>Il y a eu une tendance évidente dans le développement et l'utilisation d'outils 14.228 +de gestion de source depuis les quatre dernières décades, au fur et à mesure 14.229 +que les utilisateurs se sont habitués à leur outils et se sont sentis contraints 14.230 +par leurs limitations. 14.231 +</para> 14.232 + 14.233 +<para>La première génération commença simplement par gérer un fichier unique sur un 14.234 +ordinateur individuel. Cependant, même si ces outils présentaient une grande 14.235 +avancée par rapport à la gestion manuelle des versions, leur modèle de 14.236 +verrouillage et leur utilisation limitée à un seul ordinateur rendaient leur 14.237 +utilisation possible uniquement dans une très petite équipe. 14.238 +</para> 14.239 + 14.240 +<para>La seconde génération a assoupli ces contraintes en adoptant une architecture 14.241 +réseau et centralisée, permettant de gérer plusieurs projets entiers en même 14.242 +temps. Alors que les projets grandirent en taille, ils rencontrèrent de nouveaux 14.243 +problèmes. Avec les clients discutant régulièrement avec le serveurs, la montée 14.244 +en charge devint un réel problème sur les gros projets. Une connexion réseau 14.245 +peu fiable pouvait complètement empêcher les utilisateurs distants de dialoguer 14.246 +avec le serveur. Alors que les projets \textit{Open Source} commencèrent à 14.247 +mettre en place des accès en lecture seule disponible anonymement, les 14.248 +utilisateurs sans les privilèges de <quote>commit</quote> réalisèrent qu'ils ne pouvaient 14.249 +pas utiliser les outils pour collaborer naturellement avec le projet, comme ils 14.250 +ne pouvaient pas non plus enregistrer leurs modifications. 14.251 +</para> 14.252 + 14.253 +<para>La génération actuelle des outils de gestion de source est <quote>peer-to-peer</quote> par 14.254 +nature. Tout ces systèmes ont abandonné la dépendance à un serveur central, et 14.255 +ont permis à leur utilisateur de distribuer les données de leur gestion de 14.256 +source à qui en a besoin. La collaboration à travers Internet a transformé la 14.257 +contrainte technologique en une simple question de choix et de consencus. Les 14.258 +outils modernes peuvent maintenant fonctionner en mode déconnecté sans limite et 14.259 +de manière autonome, la connexion au réseau n'étant nécessaire que pour 14.260 +synchroniser les modifications avec les autres dépôts. 14.261 +</para> 14.262 + 14.263 +</sect1> 14.264 +<sect1> 14.265 +<title>Quelques avantages des gestionnaires de source distribués</title> 14.266 + 14.267 +<para>Même si les gestionnaire de source distribués sont depuis plusieurs années 14.268 +assez robustes et aussi utilisables que leurs prédécesseurs, les utilisateurs 14.269 +d'autres outils n'y ont pas encore été sensibilisés. Les gestionnaires 14.270 +de source distribués se distinguent particulièrement de leurs équivalents 14.271 +centralisés de nombreuses manières. 14.272 +</para> 14.273 + 14.274 +<para>Pour un développeur individuel, ils restent beaucoup plus rapides que les 14.275 +outils centralisés. Cela pour une raison simple : un outil centralisé doit 14.276 +toujours dialoguer à travers le réseau pour la plupart des opérations, car 14.277 +presque toutes les métadonnées sont stockées sur la seule copie du serveur 14.278 +central. Un outil distribué stocke toute ses métadonnées localement. À tâche 14.279 +égale, effectuer un échange avec le réseau ajoute un délai aux outils 14.280 +centralisés. Ne sous-estimez pas la valeur d'un outil rapide : vous allez 14.281 +passer beaucoup de temps à interagir avec un logiciel de gestion de source. 14.282 +</para> 14.283 + 14.284 +<para>Les outils distribués sont complètement indépendants des aléas de votre serveur, 14.285 +d'autant plus qu'ils répliquent les métadonnées à beaucoup d'endroits. Si 14.286 +votre serveur central prend feu, vous avez intérêt à ce que les médias de 14.287 +sauvegardes soient fiables, et que votre dernier <quote>backup</quote> soit récent et 14.288 +fonctionne sans problème. Avec un outil distribué, vous avez autant de 14.289 +<quote>backup</quote> que de contributeurs. 14.290 +</para> 14.291 + 14.292 +<para>En outre, la fiabilité de votre réseau affectera beaucoup moins les 14.293 +outils distribués. Vous ne pouvez même pas utiliser un outil centralisé 14.294 +sans connexion réseau, à l'exception de quelques commandes, très limitées. 14.295 +Avec un outil distribué, si votre connexion réseau tombe pendant que vous 14.296 +travaillez, vous pouvez ne même pas vous en rendre compte. La seule chose 14.297 +que vous ne serez pas capable de faire sera de communiquer avec des dépôts 14.298 +distants, opération somme toute assez rare en comparaison aux opérations 14.299 +locales. Si vous avez une équipe de collaborateurs très dispersée ceci peut 14.300 +être significatif. 14.301 +</para> 14.302 + 14.303 +<sect2> 14.304 +<title>Avantages pour les projets \textit{Open Source}</title> 14.305 + 14.306 +<para>Si vous prenez goût à un projet \textit{Open Source} et que vous 14.307 +décidez de commencer à toucher à son code, et que le projet utilise 14.308 +un gestionnaire de source distribué, vous êtes immédiatement un "pair" 14.309 +avec les personnes formant le <quote>cœur</quote> du projet. Si ils publient 14.310 +leurs dépôts, vous pouvez immédiatement copier leurs historiques de 14.311 +projet, faire des modifications, enregistrer votre travail en utilisant 14.312 +les même outils qu'eux. Par comparaison, avec un outil centralisé, vous 14.313 +devez utiliser un logiciel en mode <quote>lecture seule</quote> à moins que 14.314 +quelqu'un ne vous donne les privilèges de <quote>commit</quote> sur le serveur 14.315 +central. Avant ça, vous ne serez pas capable d'enregistrer vos 14.316 +modifications, et vos propres modifications risqueront de se 14.317 +corrompre chaque fois que vous essayerez de mettre à jour à votre 14.318 +espace de travail avec le serveur central. 14.319 +</para> 14.320 + 14.321 +<sect3> 14.322 +<title>Le non-problème du \textit{fork}</title> 14.323 + 14.324 +<para>Il a été souvent suggéré que les gestionnaires de source distribués 14.325 +posent un risque pour les projets \textit{Open Source} car ils 14.326 +facilitent grandement la création de <quote>fork</quote>\footnote{NdT:Création 14.327 +d'une 14.328 +<ulink url="version alternative du logiciel">version alternative du logiciel</ulink>{http://fr.wikipedia.org/wiki/Fork#Embranchement_d.27un_projet_informatique}.} 14.329 +Un <quote>fork</quote> apparait quand il y des divergences d'opinion ou d'attitude 14.330 +au sein d'un groupe de développeurs qui aboutissent à la décision de ne 14.331 +plus travailler ensemble. Chaque parti s'empare d'une copie plus ou moins 14.332 +complète du code source du projet et continue dans sa propre direction. 14.333 +</para> 14.334 + 14.335 +<para>Parfois ces différents partis décident de se réconcilier. Avec un 14.336 +serveur central, l'aspect <emphasis>technique</emphasis> de cette réconciliation 14.337 +est un processus douloureux, et essentiellement manuel. Vous devez 14.338 +décider quelle modification est <quote>la gagnante</quote>, et replacer, par un 14.339 +moyen ou un autre, les modifications de l'autre équipe dans l'arborescence 14.340 +du projet. Ceci implique généralement la perte d'une partie de l'historique 14.341 +d'un des partis, ou même des deux. 14.342 +</para> 14.343 + 14.344 +<para>Ce que les outils distribués permettent à ce sujet est probablement 14.345 +la <emphasis>meilleure</emphasis> façon de développer un projet. Chaque modification 14.346 +que vous effectuez est potentiellement un <quote>fork</quote>. La grande force de 14.347 +cette approche est que les gestionnaires de source distribués doivent être 14.348 +vraiment très efficaces pour <emphasis>fusionner</emphasis>\footnote{NdT:j'ai choisi de 14.349 +traduire ici \textit{merging} par <quote>fusionner</quote> pour des raisons de clarté} 14.350 +des <quote>forks</quote>, car les <quote>forks</quote>, dans ce contexte, arrivent tout le 14.351 +temps. 14.352 +</para> 14.353 + 14.354 +<para>Si chaque altération que n'importe qui effectue, à tout moment, est vue 14.355 +comme un <quote>fork</quote> à fusionner, alors ce que le monde de l'\textit{Open 14.356 +Source} voit comme un <quote>fork</quote> devient <emphasis>uniquement</emphasis> une problématique 14.357 +sociale. En fait, les outils de gestions de source distribués <emphasis>réduisent</emphasis> 14.358 +les chances de <quote>fork</quote>: 14.359 +</para> 14.360 +<itemizedlist> 14.361 +<listitem><para>Ils éliminent la distinction sociale qu'imposent les outils centralisés 14.362 + entre les membres du projets (ceux qui ont accès au <quote>commit</quote>) et ceux de 14.363 + l'extérieur (ce qui ne l'ont pas). \item Ils rendent plus facile la 14.364 + réconciliation après un <quote>fork</quote> social, car 14.365 + tout ce qu'elle implique est une simple fusion. 14.366 +</para> 14.367 +</listitem></itemizedlist> 14.368 + 14.369 +<para>Certaines personnes font de la résistance envers les gestionnaires de source 14.370 +distribués parce qu'ils veulent garder un contrôle ferme sur leur projet, et 14.371 +ils pensent que les outils centralisés leur fournissent ce contrôle. Néanmoins, 14.372 +si c'est votre cas, sachez que si vous publiez votre dépôt CVS ou Subversion 14.373 +de manière publique, il existe une quantité d'outils disponibles pour récupérer 14.374 +entièrement votre projet et son historique (quoique lentement) et le récréer 14.375 +ailleurs, sans votre contrôle. En fait, votre contrôle sur votre projet est 14.376 +illusoire, vous ne faites qu'interdire à vos collaborateurs de travailler 14.377 +de manière fluide, en disposant d'un miroir ou d'un <quote>fork</quote> de votre 14.378 +historique. 14.379 +%%%TODO: Fussy, those last sentences are not really well translated: 14.380 +%%%no problem for me (wilk) 14.381 +%However, if you're of this belief, and you publish your CVS or Subversion 14.382 +%repositories publically, there are plenty of tools available that can pull 14.383 +%out your entire project's history (albeit slowly) and recreate it somewhere 14.384 +%that you don't control. So while your control in this case is illusory, you are 14.385 +%forgoing the ability to fluidly collaborate with whatever people feel 14.386 +%compelled to mirror and fork your history. 14.387 +</para> 14.388 + 14.389 +</sect3> 14.390 +</sect2> 14.391 +<sect2> 14.392 +<title>Avantages pour les projets commerciaux</title> 14.393 + 14.394 +<para>Beaucoup de projets commerciaux sont réalisés par des équipes éparpillées 14.395 +à travers le globe. Les contributeurs qui sont loin du serveur central 14.396 +devront subir des commandes lentes et même parfois peu fiables. Les 14.397 +solutions propriétaires de gestion de source tentent de palier ce problème 14.398 +avec des réplications de sites distants qui sont à la fois coûteuses à mettre 14.399 +en place et lourdes à administrer. Un système distribué ne souffre pas 14.400 +de ce genre de problèmes. En outre, il est très aisé de mettre en place 14.401 +plusieurs serveurs de références, disons un par site, de manière à ce qu'il 14.402 +n'y ait pas de communication redondante entre les dépôts, sur une connexion 14.403 +longue distance souvent onéreuse. 14.404 +</para> 14.405 + 14.406 +<para>Les systèmes de gestion de source supportent généralement assez mal la 14.407 +montée en charge. Ce n'est pas rare pour un gestionnaire de source centralisé 14.408 +pourtant onéreux de s'effondrer sous la charge combinée d'une douzaine 14.409 +d'utilisateurs concurrents seulement. Une fois encore, la réponse à cette problématique 14.410 +est généralement encore la mise en place d'un ensemble complexe de serveurs 14.411 +synchronisés par un mécanisme de réplication. Dans le cas d'un gestionnaire 14.412 +de source distribué, la charge du serveur central &emdash; si vous avez un&emdash; est 14.413 +plusieurs fois inférieure (car toutes les données sont déjà répliquées ailleurs), 14.414 +un simple serveur, pas très cher, peut gérer les besoins d'une plus grande 14.415 +équipe, et la réplication pour balancer la charge devient le 14.416 +travail d'un simple script. 14.417 +</para> 14.418 + 14.419 +<para>Si vous avez des employés sur le terrain, en train de chercher à résoudre un souci sur 14.420 +le site d'un client, ils bénéficieront aussi d'un gestionnaire de source 14.421 +distribué. Cet outil leur permettra de générer des versions personnalisées, 14.422 +d'essayer différentes solutions, en les isolant aisément les unes des autres, 14.423 +et de rechercher efficacement à travers l'historique des sources, la cause 14.424 +des bugs ou des régressions, tout ceci sans avoir besoin de la moindre 14.425 +connexion au réseau de votre compagnie. 14.426 +</para> 14.427 + 14.428 +</sect2> 14.429 +</sect1> 14.430 +<sect1> 14.431 +<title>Pourquoi choisir Mercurial?</title> 14.432 + 14.433 +<para>Mercurial a plusieurs caractéristiques qui en font un choix particulièrement 14.434 +pertinent pour la gestion de source: 14.435 +</para> 14.436 +<itemizedlist> 14.437 +<listitem><para> \item Il est facile à apprendre et à utiliser ; 14.438 + \item Il est léger et performant ; 14.439 + \item Il monte facilement en charge ; 14.440 + \item Il est facile à personnaliser ; 14.441 +</para> 14.442 +</listitem></itemizedlist> 14.443 + 14.444 +<para>Si vous êtes déjà familier d'un outil de gestion de source, vous serez 14.445 +capable de l'utiliser en moins de 5 minutes. Sinon, ça ne sera pas beaucoup 14.446 +plus long\footnote{NdT: Pour appuyer le propos de l'auteur, je signale que 14.447 +j'utilise Mercurial comme outil d'initiation à la gestion de contrôle dans 14.448 +des travaux pratiques à l'ESME Sudria (<ulink url="http://www.esme.fr">http://www.esme.fr</ulink>) et que les 14.449 +élèves le prennent en main sans difficulté majeure malgré l'approche distribuée.}. 14.450 +Les commandes utilisées par Mercurial, comme ses fonctionnalités, sont 14.451 +généralement uniformes et cohérentes, et vous pouvez donc ainsi garder en tête 14.452 +simplement quelques règles générales, plutôt qu'un lot complexe d'exceptions. 14.453 +</para> 14.454 + 14.455 +<para>Sur un petit projet, vous pouvez commencer à travailler avec Mercurial en 14.456 +quelques instants. Ajouter des modifications ou des branches, transférer 14.457 +ces modifications (localement ou via le réseau), et les opérations 14.458 +d'historique ou de statut sont aussi très rapides. Mercurial reste hors de 14.459 +votre chemin grâce à sa simplicité d'utilisation et sa rapidité d'exécution. 14.460 +</para> 14.461 + 14.462 +<para>L'utilité de Mercurial ne se limite pas à de petits projets: il est 14.463 +aussi utilisé par des projets ayant des centaines ou même des milliers 14.464 +de contributeurs, avec plusieurs dizaines de milliers de fichiers, et des 14.465 +centaines de méga de code source. 14.466 +</para> 14.467 + 14.468 +<para>Voici une liste non exhaustive des projets complexes ou critiques utilisant 14.469 +Mercurial : 14.470 +%TODO 14.471 +% For both spanish and english version, add the following examples: 14.472 +</para> 14.473 +<itemizedlist> 14.474 +<listitem><para> \item <ulink url="Firefox">Firefox</ulink>{https://developer.mozilla.org/en/Mozilla_Source_Code_(Mercurial)} ; 14.475 + \item <ulink url="OpenSolaris">OpenSolaris</ulink>{http://opensolaris.org/os/community/tools/scm/hg_help/} ; 14.476 + \item <ulink url="OpenJDK">OpenJDK</ulink>{http://hg.openjdk.java.net/} (utilisant en outre l'extension 14.477 + <quote>forest</quote> pour gérer ses sous modules); 14.478 +</para> 14.479 +</listitem></itemizedlist> 14.480 + 14.481 +<para>Si les fonctionnalités cœur de Mercurial ne sont pas suffisantes pour vous, 14.482 +il est très aisé d'en construire d'autres. Mercurial est adapté à l'utilisation 14.483 +de scripts, et son implémentation interne en Python, propre et claire, 14.484 +rend encore plus facile l'ajout de fonctionnalités sous forme d'extensions. Il 14.485 +en existe déjà un certain nombre de très populaires et très utiles, 14.486 +dont le périmètre va de la recherche de bugs à l'amélioration des performances. 14.487 +</para> 14.488 + 14.489 +</sect1> 14.490 +<sect1> 14.491 +<title>Mercurial comparé aux autres outils</title> 14.492 + 14.493 +<para>Avant que vous n'alliez plus loin, comprenez bien que cette section 14.494 +reflète mes propres expériences, et elle est donc (j'ose le dire) 14.495 +peu objective. Néanmoins, j'ai utilisé les outils de gestion de source 14.496 +listés ci dessous, dans la plupart des cas, pendant plusieurs années. 14.497 +%% TODO: Fussy translation. 14.498 +</para> 14.499 + 14.500 +<sect2> 14.501 +<title>Subversion</title> 14.502 + 14.503 +<para>Subversion est un des outils de gestion de source les plus populaire, il fût 14.504 +développé pour remplacer CVS. Il a une architecture client/server centralisée. 14.505 +</para> 14.506 + 14.507 +<para>Subversion et Mercurial ont des noms de commandes très similaires pour 14.508 +les mêmes opérations, ainsi si vous êtes familier avec l'un, c'est facile 14.509 +d'apprendre l'autre. Ces deux outils sont portables sur les systèmes 14.510 +d'exploitation les plus populaires\footnote{NdT:Mercurial fonctionne sans problème 14.511 +sur OpenVMS à l'ESME Sudria <ulink url="http://www.esme.fr">http://www.esme.fr</ulink>, compte tenu que Subversion a été 14.512 +développé en C, je ne suis pas sûr que son portage aurait été aussi aisé.}. 14.513 +%TODO: Backport this statement in english and spanish 14.514 +</para> 14.515 + 14.516 +<para>Avant la version 1.5, Subversion n'offrait aucune forme de support pour les fusions. Lors 14.517 +de l'écriture de ce livre, ses capacités de fusion étaient nouvelles, et réputées pour être 14.518 +\href{http://svnbook.red-bean.com/nightly/en/svn.branchmerge.advanced.html#svn.branchmerge.advanced.finalword}{complexes 14.519 +et bugguées}. 14.520 +</para> 14.521 + 14.522 +<para>Mercurial dispose d'un avantage substantiel en terme de performance par rapport à 14.523 +Subversion sur la plupart des opérations que j'ai pu tester. J'ai mesuré 14.524 +une différence de performance allant de deux à six fois plus rapide avec 14.525 +le système de stockage de fichier local de Subversion 1.4.3 14.526 +(<emphasis>ra_local</emphasis>), qui est la méthode d'accès la plus rapide disponible. Dans 14.527 +un déploiement plus réaliste, impliquant un stockage réseau, Subversion 14.528 +serait encore plus désavantagé. Parce que la plupart des commandes Subversion 14.529 +doivent communiquer avec le serveur et que Subversion n'a pas de mécanisme 14.530 +de réplication, la capacité du serveur et la bande passante sont devenues des 14.531 +goulots d'étranglement pour les projets de taille moyenne ou grande. 14.532 +</para> 14.533 + 14.534 +<para>En outre, Subversion implique une surcharge substantielle dans le stockage local 14.535 +de certaines données, pour éviter des transactions avec le serveur, pour 14.536 +certaines opérations communes, telles que la recherche des fichiers modifiés 14.537 +(<literal>status</literal>) et l'affichage des modifications par rapport à la révision 14.538 +courante (<literal>diff</literal>). En conséquence, un répertoire de travail Subversion 14.539 +a souvent la même taille, ou est plus grand, qu'un dépôt Mercurial et son 14.540 +espace de travail, et ceci bien que le dépôt Mercurial contienne l'intégralité 14.541 +de l'historique. 14.542 +</para> 14.543 + 14.544 +<para>Subversion est largement supporté par les outils tierces. Mercurial est 14.545 +actuellement encore en retrait de ce point de vue. L'écart se réduit, néanmoins, 14.546 +et en effet certains des outils graphiques sont maintenant supérieurs à leurs 14.547 +équivalents Subversion. Comme Mercurial, Subversion dispose d'un excellent 14.548 +manuel utilisateur. 14.549 +</para> 14.550 + 14.551 +<para>Parce que Subversion ne stocke pas l'historique chez ses clients, il est 14.552 +parfaitement adapté à la gestion de projets qui doivent suivre un ensemble 14.553 +de larges fichiers binaires et opaques. Si vous suivez une cinquantaine de 14.554 +versions d'un fichier incompressible de 10MB, l'occupation disque coté client 14.555 +d'un projet sous Subversion restera à peu près constante. A l'inverse, 14.556 +l'occupation disque du même projet sous n'importe lequel des gestionnaires 14.557 +de source distribués grandira rapidement, proportionnellement aux nombres 14.558 +de versions, car les différences entre chaque révisions seront très grandes. 14.559 +</para> 14.560 + 14.561 +<para>En outre, c'est souvent difficile ou, généralement, impossible de fusionner 14.562 +des différences dans un fichier binaire. La capacité de Subversion de 14.563 +verrouiller des fichiers, pour permettre à l'utilisateur d'être le seul 14.564 +à le mettre à jour (<quote>commit</quote>) temporairement, est un avantage significatif 14.565 +dans un projet doté de beaucoup de fichiers binaires. 14.566 +</para> 14.567 + 14.568 +<para>Mercurial peut importer l'historique depuis un dépôt Subversion. Il peut 14.569 +aussi exporter l'ensemble des révisions d'un projet vers un dépôt Subversion. 14.570 +Ceci rend très facile de <quote>prendre la température</quote> et d'utiliser Mercurial et Subversion 14.571 +en parallèle, avant de décider de migrer vers Mercurial. La conversion de 14.572 +l'historique est incrémentale, donc vous pouvez effectuer une conversion 14.573 +initiale, puis de petites additions par la suite pour ajouter les nouvelles 14.574 +modifications. 14.575 +</para> 14.576 + 14.577 +</sect2> 14.578 +<sect2> 14.579 +<title>Git</title> 14.580 + 14.581 +<para>Git est un outil de gestion de source distribué qui fût développé pour gérer 14.582 +le code source de noyau de Linux. Comme Mercurial, sa conception initiale a 14.583 +été inspirée par Monotone. 14.584 +</para> 14.585 + 14.586 +<para>Git dispose d'un ensemble conséquent de commandes, avec plus de 139 commandes 14.587 +individuelles pour la version 1.5.0. Il a aussi la réputation d'être difficile 14.588 +à apprendre. Comparé à Git, le point fort de Mercurial est clairement sa 14.589 +simplicité. 14.590 +</para> 14.591 + 14.592 +<para>En terme de performance, Git est extrêmement rapide. Dans la plupart des 14.593 +cas, il est plus rapide que Mercurial, tout du moins sur Linux, alors que 14.594 +Mercurial peut être plus performant sur d'autres opérations. Néanmoins, sur 14.595 +Windows, les performances et le niveau de support général fourni par Git, 14.596 +au moment de l'écriture de cet ouvrage, est bien derrière celui de Mercurial. 14.597 +</para> 14.598 + 14.599 +<para>Alors que le dépôt Mercurial ne demande aucune maintenance, un dépôt Git 14.600 +exige d'exécuter manuellement et régulièrement la commande <quote>repacks</quote> sur 14.601 +ces métadonnées. Sans ceci, les performances de git se dégradent et la 14.602 +consommation de l'espace disque augmente rapidement. Un serveur qui contient 14.603 +plusieurs dépôts Git qui ne sont pas régulièrement et fréquemment <quote>repacked</quote> 14.604 +deviendra un vrai problème lors des <quote>backups</quote> du disque, et il y eu des 14.605 +cas, où un <quote>backup</quote> journalier pouvait durer plus de 24 heures. Un dépôt 14.606 +fraichement <quote>repacked</quote> sera légèrement plus petit qu'un dépôt Mercurial, 14.607 +mais un dépôt non <quote>repacked</quote> est beaucoup plus grand. 14.608 +</para> 14.609 + 14.610 +<para>Le cœur de Git est écrit en C. La plupart des commandes Git sont implémentées 14.611 +sous forme de scripts Shell ou Perl, et la qualité de ces scripts varie 14.612 +grandement. J'ai plusieurs fois constaté que certains de ces scripts étaient 14.613 +chargés en mémoire aveuglément et que la présence d'erreurs pouvait s'avérer 14.614 +fatal. 14.615 +</para> 14.616 + 14.617 +<para>Mercurial peut importer l'historique d'un dépôt Git. 14.618 +</para> 14.619 + 14.620 +</sect2> 14.621 +<sect2> 14.622 +<title>CVS</title> 14.623 + 14.624 +<para>CVS est probablement l'outil de gestion de source le plus utilisé aujourd'hui 14.625 +dans le monde. À cause de son manque de clarté interne, il n'est plus 14.626 +maintenu depuis plusieurs années. 14.627 +</para> 14.628 + 14.629 +<para>Il a une architecture client/serveur centralisée. Il ne regroupe pas les 14.630 +modifications de fichiers dans une opération de <quote>commit</quote> atomique, ce 14.631 +qui permet à ses utilisateurs de <quote>casser le \textit{build}</quote> assez 14.632 +facilement : une personne peut effectuer une opération de <quote>commit</quote> 14.633 +sans problème puis être bloquée par besoin de fusion, avec comme conséquence 14.634 +néfaste, que les autres utilisateurs ne récupèreront qu'une partie de ses 14.635 +modifications. Ce problème affecte aussi la manière de travailler avec 14.636 +l'historique du projet. Si vous voulez voir toutes les modifications d'une 14.637 +personne du projet, vous devrez injecter manuellement les descriptions et les 14.638 +\textit{timestamps} des modifications de chacun des fichiers impliqués (si 14.639 +vous savez au moins quels sont ces fichiers). 14.640 +</para> 14.641 + 14.642 +<para>CVS a une notion étrange des \textit{tags} et des branches que je n'essayerai 14.643 +même pas de décrire ici. Il ne supporte pas bien les opérations de renommage d'un 14.644 +fichier ou d'un répertoire, ce qui facilite la corruption de son dépôt. Il n'a 14.645 +presque pas pour ainsi dire de contrôle de cohérence interne, il est donc 14.646 +pratiquement impossible de dire si un dépôt est corrompu ni à quel point. Je 14.647 +ne recommanderai pas CVS pour un projet existant ou nouveau. 14.648 +</para> 14.649 + 14.650 +<para>Mercurial peut importer l'historique d'un projet CVS. Néanmoins, il y a 14.651 +quelques principes à respecter; ce qui est vrai aussi pour les autres 14.652 +outils d'import de projet CVS. À cause de l'absence de <quote>commit</quote> atomique 14.653 +et gestion de version de l'arborescence, il n'est pas possible de reconstruire 14.654 +de manière précise l'ensemble de l'historique. Un travail de <quote>devinette</quote> 14.655 +est donc nécessaire, et les fichiers renommés ne sont pas détectés. Parce 14.656 +qu'une bonne part de l'administration d'un dépôt CVS est effectuée manuellement, 14.657 +et est donc, sujette à erreur, il est courant que les imports CVS rencontrent 14.658 +de nombreux problèmes avec les dépôt corrompus (des \textit{timestamps} 14.659 +de révision complètement buggés et des fichiers verrouillés depuis des années 14.660 +sont deux des problèmes les moins intéressants dont je me souvienne). 14.661 +</para> 14.662 + 14.663 +<para>Mercurial peut importer l'historique depuis un dépôt CVS. 14.664 +</para> 14.665 + 14.666 +</sect2> 14.667 +<sect2> 14.668 +<title>Outils propriétaires</title> 14.669 + 14.670 +<para>Perforce a une architecture client/serveur centralisée, sans aucun 14.671 +mécanisme de mise en cache de données coté client. Contrairement à la plupart 14.672 +des outils modernes de gestion de source, Perforce exige de ses 14.673 +utilisateurs d'exécuter une commande pour informer le serveur 14.674 +central de tout fichier qu'ils souhaitent modifier. 14.675 +</para> 14.676 + 14.677 +<para>Les performances de Perforce sont plutôt bonnes pour des petites 14.678 +équipes, mais elles s'effondrent rapidement lorsque le nombre 14.679 +d'utilisateurs augmente au delà de la douzaine. Des installations 14.680 +de Perforce assez larges nécessitent le déploiement de proxies pour 14.681 +supporter la montée en charge associée. 14.682 +</para> 14.683 + 14.684 +</sect2> 14.685 +<sect2> 14.686 +<title>Choisir un outil de gestion de source</title> 14.687 + 14.688 +<para>A l'exception de CVS, tous les outils listés ci-dessus ont des 14.689 +forces qui leur sont propres et qui correspondent à certaines 14.690 +formes de projet. Il n'y a pas un seul meilleur outil de gestion 14.691 +de source qui correspondrait le mieux à toutes les situations. 14.692 +</para> 14.693 + 14.694 +<para>Par exemple, Subversion est un très bon choix lorsqu'on travaille 14.695 +avec beaucoup de fichiers binaires, qui évoluent régulièrement, grâce 14.696 +à sa nature centralisée et sa capacité à verrouiller des fichiers. 14.697 +</para> 14.698 + 14.699 +<para>Personnellement, je préfère Mercurial pour sa simplicité, ses 14.700 +performances et sa bonne capacité de fusion, et il m'a très bien rendu service 14.701 +de plusieurs années maintenant. 14.702 +</para> 14.703 + 14.704 +</sect2> 14.705 +</sect1> 14.706 +<sect1> 14.707 +<title>Migrer depuis un outil à Mercurial</title> 14.708 + 14.709 +<para>Mercurial est livré avec une extension nommée <literal role="hg-ext">convert</literal>, qui 14.710 +peut de manière incrémentale importer des révisions depuis différents 14.711 +autres outils de gestion de source. Par <quote>incrémental</quote>, j'entends que 14.712 +vous pouvez convertir l'historique entier du projet en une seule fois, 14.713 +puis relancer l'outil d'import plus tard pour obtenir les modifications 14.714 +effectuées depuis votre import initial. 14.715 +</para> 14.716 + 14.717 +<para>Les outils de gestion de source supportés par <literal role="hg-ext">convert</literal> sont : 14.718 +</para> 14.719 +<itemizedlist> 14.720 +<listitem><para> \item Subversion 14.721 + \item CVS 14.722 + \item Git 14.723 + \item Darcs 14.724 +</para> 14.725 +</listitem></itemizedlist> 14.726 + 14.727 +<para>En outre, <literal role="hg-ext">convert</literal> peut exporter les modifications depuis Mercurial 14.728 +vers Subversion. Ceci rend possible d'essayer Subversion en parallèle 14.729 +avant de choisir une solution définitive, sans aucun risque de perte de 14.730 +données. 14.731 +</para> 14.732 + 14.733 +<para>La commande <command role="hg-ext-conver">convert</command> est très simple à utiliser. Simplement, 14.734 +indiquez le chemin ou l'URL du dépôt de source, en lui indiquant éventuellement 14.735 +le nom du chemin de destination, et la conversion se met en route. Après cet 14.736 +import initial, il suffit de relancer la commande encore une fois pour 14.737 +importer les modifications effectuées depuis. 14.738 +</para> 14.739 + 14.740 +</sect1> 14.741 +</chapter> 14.742 + 14.743 +<!-- 14.744 +local variables: 14.745 +sgml-parent-document: ("00book.xml" "book" "chapter") 14.746 +end: 14.747 +--> 14.748 \ No newline at end of file
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 15.2 +++ b/fr/ch02-tour-basic.xml Sun Aug 16 04:58:01 2009 +0200 15.3 @@ -0,0 +1,889 @@ 15.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 15.5 + 15.6 +<chapter> 15.7 +<title>Un rapide tour de Mercurial</title> 15.8 +<para>\label{chap:tour-basic}</para> 15.9 + 15.10 +<sect1> 15.11 +<title>Installer Mercurial sur votre système</title> 15.12 +<para>\label{sec:tour:install}</para> 15.13 + 15.14 +<para>Des paquetages binaires de Mercurial sont disponibles pour la plupart 15.15 +des systèmes d'exploitation, ce qui rend facile l'utilisation immédiate 15.16 +de Mercurial sur votre ordinateur.</para> 15.17 + 15.18 +<sect2> 15.19 +<title>Linux</title> 15.20 + 15.21 +<para>Parce que chaque distribution de Linux a ses propres outils de gestion 15.22 +de paquets, politiques et rythmes de développements, il est difficile de 15.23 +donner un ensemble d'instructions uniques pour installer les binaires de 15.24 +Mercurial. La version de Mercurial avec laquelle vous vous retrouverez 15.25 +dépendra grandement de l'activité de la personne en charge du paquetage 15.26 +pour la distribution.</para> 15.27 + 15.28 +<para>Pour rester simple, je me concentrerai sur l'installation de Mercurial 15.29 +en ligne de commande, sous les distributions les plus courantes. La 15.30 +plupart des distributions fournissent des gestionnaires graphiques de 15.31 +paquetage qui vous permettront d'installer Mercurial en quelques clicks. 15.32 +Le paquetage devrait se nommer \textit{mercurial}.</para> 15.33 + 15.34 +<itemizedlist> 15.35 +<listitem><para>Debian:</para> 15.36 +</listitem><programlisting> 15.37 +<listitem><para> apt-get install mercurial</para> 15.38 +</listitem></programlisting></para> 15.39 +</listitem> 15.40 +<listitem><para>Fedora Core: 15.41 +</para> 15.42 +</listitem><programlisting> 15.43 +<listitem><para> yum install mercurial 15.44 +</para> 15.45 +</listitem></programlisting> 15.46 + 15.47 +</para> 15.48 +</listitem> 15.49 +<listitem><para>Gentoo: 15.50 +</para> 15.51 +</listitem><programlisting> 15.52 +<listitem><para> emerge mercurial 15.53 +</para> 15.54 +</listitem></programlisting> 15.55 + 15.56 +</para> 15.57 +</listitem> 15.58 +<listitem><para>OpenSUSE: 15.59 +</para> 15.60 +</listitem><programlisting> 15.61 +<listitem><para> yum install mercurial 15.62 +</para> 15.63 +</listitem></programlisting> 15.64 + 15.65 +</para> 15.66 +</listitem> 15.67 +<listitem><para>Ubuntu: Le paquetage de Mercurial d'Ubuntu est construit sur celui de Debian. 15.68 + Pour l'installer, exécutez simplement les commandes suivantes: 15.69 +</para> 15.70 +</listitem><programlisting> 15.71 +<listitem><para> apt-get install mercurial 15.72 +</para> 15.73 +</listitem></programlisting> 15.74 +<listitem><para> Les paquetages Ubuntu pour Mercurial ont tendance à être un peu en retard 15.75 + par rapport au paquetage Debian (au moment de l'écriture de ce livre, il 15.76 + faut compter à peu près un retard de 7 mois), ce qui signifie que parfois 15.77 + sur Ubuntu, vous risquez de rencontrer des problèmes qui ont été corrigés 15.78 + depuis longtemps dans les paquetages Debian. 15.79 +</para> 15.80 +</listitem></itemizedlist> 15.81 + 15.82 +</sect2> 15.83 +<sect2> 15.84 +<title>Solaris</title> 15.85 + 15.86 +<para>SunFreeWare, à <ulink url="http://www.saufreeware.com">http://www.saufreeware.com</ulink>, est une bonne source 15.87 +pour trouver un vaste nombre de paquets précompilés pour 32 ou 64 bits 15.88 +Intel et les architecture Sparc, dont les versions courantes de Mercurial. 15.89 +</para> 15.90 + 15.91 +</sect2> 15.92 +<sect2> 15.93 +<title>Mac OS X</title> 15.94 + 15.95 +<para>Lee Cantey publie un installateur de Mercurial pour Mac OS X sur le site 15.96 +<ulink url="http://mercurial.berkwood.com">http://mercurial.berkwood.com</ulink>. Ce paquetage fonctionne sur les 15.97 +architectures Intel- et PowerPC. Avant de vous en servir, vous devez 15.98 +installer une version Universelle MacPython <citation>web:macpython</citation>. C'est 15.99 +assez facile à faire : suivez simplement les instructions sur le site 15.100 +de Lee. 15.101 +</para> 15.102 + 15.103 +<para>Il est aussi possible d'installer Mercurial en utilisant Fink ou MacPorts, 15.104 +deux outils de gestion de paquetage libres pour Mac OS X. Si vous avez 15.105 +Fink, utilisez <command>sudo fink install mercurial-py25</command>. Si vous avez 15.106 +MacPorts, <command>sudo port install mercurial</command>. 15.107 +</para> 15.108 + 15.109 +</sect2> 15.110 +<sect2> 15.111 +<title>Windows</title> 15.112 + 15.113 +<para>Lee Cantey publie aussi un installateur de Mercurial pour Windows sur le site 15.114 +<ulink url="http://mercurial.berkwood.com">http://mercurial.berkwood.com</ulink>. Ce paquetage n'a aucune dépendance 15.115 +externe, il fonctionne <quote>tout court</quote>. 15.116 +</para> 15.117 + 15.118 +<note> 15.119 +<para> La version de Windows de Mercurial ne convertie pas automatiquement 15.120 + les retours chariot Windows et Unix. Si vous désirez partager votre 15.121 + travail avec des utilisateurs Unix, vous devez faire un peu de configuration 15.122 + supplémentaire. XXX En dire plus. 15.123 +</para> 15.124 +</note> 15.125 + 15.126 +</sect2> 15.127 +</sect1> 15.128 +<sect1> 15.129 +<title>Commencer à utiliser Mercurial</title> 15.130 + 15.131 +<para>Pour commencer, nous utiliserons la commande <command role="hg-cmd">hg version</command> pour vérifier 15.132 +si Mercurial est installé proprement. Les informations affichées sur la 15.133 +version ne sont pas réellement importantes en soit, c'est surtout de savoir 15.134 +si elles s'affichent qui nous intéresse. 15.135 +<!-- &interaction.tour.version; --> 15.136 +</para> 15.137 + 15.138 +<sect2> 15.139 +<title>L'aide intégrée</title> 15.140 + 15.141 +<para>Mercurial fournit un système d'aide intégré, ce qui est inestimable quand 15.142 +vous vous retrouvez coincé à essayer de vous rappeler comment lancer telle 15.143 +ou telle commande. 15.144 +Si c'est le cas, exécutez simplement <command role="hg-cmd">hg help</command>; il vous aidera à imprimer 15.145 +une brève liste de commandes, avec une description de ce qu'elles font. Si vous 15.146 +demandez de l'aide sur une commande spécifique (voir ci-dessous), il affichera 15.147 +des informations plus détaillées. 15.148 +<!-- &interaction.tour.help; --> 15.149 +Pour un niveau d'informations encore plus détaillées (ce dont vous aurez rarement 15.150 +besoin), exécuter <command role="hg-cmd">hg help <option role="hg-opt-global">-v</option></command>. L'option <option role="hg-opt-global">-v</option> est 15.151 +l'abréviation de <option role="hg-opt-global">--verbose</option>, et indique à Mercurial d'afficher plus 15.152 +d'informations que d'habitude. 15.153 +</para> 15.154 + 15.155 +</sect2> 15.156 +</sect1> 15.157 +<sect1> 15.158 +<title>Travailler avec un dépôt</title> 15.159 + 15.160 +<para>Avec Mercurial, tout se déroule au sein du <emphasis>dépôt</emphasis>\footnote{NdT: Dépôt est 15.161 +la traduction que j'ai retenue pour tout l'ouvrage du terme anglais \textit{repository}}. 15.162 +Le dépôt d'un projet contient tous les fichiers qui <quote>appartiennent</quote> au projet. 15.163 +</para> 15.164 + 15.165 +<para>Il n'y a rien de particulièrement magique au sujet de ce dépôt, c'est 15.166 +simplement une arborescence sur votre système de fichiers que Mercurial 15.167 +traite de manière spéciale. Vous pouvez renommer ou effacer ce répertoire 15.168 +à n'importe quel moment, en utilisant la ligne de commande ou votre 15.169 +explorateur de fichiers. 15.170 +</para> 15.171 + 15.172 +<sect2> 15.173 +<title>Faire une copie locale de votre dépôt</title> 15.174 + 15.175 +<para><emphasis>Copier</emphasis> un dépôt est juste un peu spécial. Bien que vous 15.176 +puissiez utiliser une commande habituelle de copie pour copier 15.177 +votre dépôt, il vaut mieux utiliser une commande fournie par 15.178 +Mercurial. Cette commande est appelée <command role="hg-cmd">hg clone</command>, car elle 15.179 +crée une copie identique à un dépôt existant. 15.180 +<!-- &interaction.tour.clone; --> 15.181 +Si votre opération de clonage réussit, vous devriez maintenant 15.182 +avoir un répertoire local appelé <filename class="directory">hello</filename>. Ce répertoire 15.183 +contiendra quelques fichiers. 15.184 +<!-- &interaction.tour.ls; --> 15.185 +Ces fichiers ont le même contenu et historique dans votre dépôt 15.186 +qu'ils ont dans le dépôt que vous avez cloné. 15.187 +</para> 15.188 + 15.189 +<para>Chaque dépôt Mercurial est complet, autonome et indépendant. Il 15.190 +contient sa propre copie privée des fichiers du projet et de leur 15.191 +historique. Le clone d'un dépôt se souvient de la localisation du 15.192 +dépôt à partir duquel il a été clôné, mais il ne communique pas avec 15.193 +ce dernier, ou un autre, à moins que vous ne lui demandiez. 15.194 +</para> 15.195 + 15.196 +<para>Ce que tout ceci signifie pour le moment est que nous sommes libres 15.197 +d'expérimenter avec ce dépôt, confiants dans le fait qu'il s'agit d'un 15.198 +<quote>bac à sable</quote> qui n'affectera personne d'autre. 15.199 +</para> 15.200 + 15.201 +</sect2> 15.202 +<sect2> 15.203 +<title>Quel est le contenu d'un dépôt ?</title> 15.204 + 15.205 +<para>Prêtons plus attention un instant au contenu d'un dépôt. Nous voyons 15.206 +qu'il contient un répertoire nommé <filename class="directory">.hg</filename>. C'est ici que Mercurial 15.207 +conserve toutes ses métadonnées. 15.208 +<!-- &interaction.tour.ls-a; --> 15.209 +</para> 15.210 + 15.211 +<para>Le contenu du répertoire <filename class="directory">.hg</filename> et ses sous répertoires sont les 15.212 +seuls propres à Mercurial. Tous les autres fichiers et répertoires dans 15.213 +le dépôt sont à vous, et vous pouvez en faire ce que vous voulez. 15.214 +</para> 15.215 + 15.216 +<para>Pour introduire un peu de terminologie, le répertoire <filename class="directory">.hg</filename> est 15.217 +un <quote>vrai</quote> dépôt, et tous les fichiers et les répertoires qui coexistent 15.218 +avec lui, sont désignés sous le nom <emphasis>espace de travail</emphasis>\footnote{NdT: 15.219 +\textit{working directory}}. Une manière facile de se rappeler cette 15.220 +distinction est de retenir que le <emphasis>dépôt</emphasis> contient l'<emphasis>historique</emphasis> 15.221 +de votre projet, alors que l'<emphasis>espace de travail</emphasis> contient une \emph{copie 15.222 +ponctuelle}\footnote{NdT: Ce terme est une traduction du terme anglais 15.223 +\textit{snapshot}. Il est traduit ici pour faciliter la lecture, mais ne sera 15.224 +plus traduit par la suite.} de votre projet à un certain point de son 15.225 +historique. 15.226 +</para> 15.227 + 15.228 +</sect2> 15.229 +</sect1> 15.230 +<sect1> 15.231 +<title>Une ballade dans l'historique</title> 15.232 + 15.233 +<para>Une des premières choses que vous aurez envie de faire avec un nouveau 15.234 +dépôt, sera de comprendre son historique. La commande <command role="hg-cmd">hg log</command> vous 15.235 +donne une vue de l'historique. 15.236 +<!-- &interaction.tour.log; --> 15.237 +Par défaut, cette commande affiche à l'écran un bref paragraphe pour chaque 15.238 +révision enregistrée pour ce projet. Dans la terminologie de Mercurial, nous 15.239 +appelons chacun de ces évènements enregistrés un <emphasis>changeset</emphasis>, parce 15.240 +qu'il contient un ensemble de modifications sur plusieurs fichiers. 15.241 +</para> 15.242 + 15.243 +<para>La commande <command role="hg-cmd">hg log</command> affiche ainsi ces informations: 15.244 +</para> 15.245 +<itemizedlist> 15.246 +<listitem><para><literal>changeset</literal>: Ce champ contient un nombre, séparé par deux points 15.247 + (:), d'une chaine hexadécimale. Il s'agit en fait d'<emphasis>identifiants</emphasis> 15.248 + d'un \textit{changeset}. Il y a deux identifiants car le numéro de 15.249 + la révision est plus court et plus à facile à saisir qu'une séquence 15.250 + hexadécimale. 15.251 +</para> 15.252 +</listitem> 15.253 +<listitem><para><literal>user</literal>: L'identité de la personne qui a créée ce %%% laisser le terme anglais car il sera affiché 15.254 + \textit{changeset}. C'est un champ libre de forme, mais la plupart du 15.255 + temps il contient le nom et l'email de la personne. 15.256 +</para> 15.257 +</listitem> 15.258 +<listitem><para><literal>date</literal>: La date et l'heure à laquelle le \textit{changeset} 15.259 + a été créé, ainsi que le \textit{fuseau horaire} dans laquelle il a été créé. %%%TODO: Translate 'timezone' properly : FUSEAU 15.260 + (La date et l'heure sont locales à ce \textit{fuseau}, elles indiquent 15.261 + donc quelle date et heure il était pour la personne qui a créé ce %%%TODO: je suppose (quelle "heure") OUI 15.262 + \textit{changeset}.) 15.263 +</para> 15.264 +</listitem> 15.265 +<listitem><para><literal>résumé</literal>: La première du message que le créateur a associé à 15.266 + son \textit{changeset} pour le décrire. 15.267 +</para> 15.268 +</listitem></itemizedlist> 15.269 + 15.270 +<para>Par défaut, la commande <command role="hg-cmd">hg log</command> n'affiche qu'un résumé, il manque 15.271 +beaucoup de détails. 15.272 +</para> 15.273 + 15.274 +<para>La figure <xref linkend="fig:tour-basic:history"/> fournit une représentation graphique 15.275 +de l'historique du dépôt <filename class="directory">hello</filename>, pour rendre plus facile de voir 15.276 +dans quelle direction l'historique se <quote>déroule</quote>\footnote{NdT: \textit{flowing in}.}. 15.277 +Nous reviendrons régulièrement sur cette représentation dans ce chapitre et 15.278 +ceux qui suivent. 15.279 +</para> 15.280 + 15.281 +<informalfigure> 15.282 + 15.283 +<para> <mediaobject><imageobject><imagedata fileref="tour-history"/></imageobject><textobject><phrase>XXX add text</phrase></textobject></mediaobject> 15.284 + <caption><para>Représentation graphique du dépôt <filename class="directory">hello</para></caption> </filename> 15.285 + \label{fig:tour-basic:history} 15.286 +</para> 15.287 +</informalfigure> 15.288 + 15.289 +<sect2> 15.290 +<title>Changesets, révisions, et discuter avec les autres</title> 15.291 +<para>%%% je propose "colaboration" 15.292 +</para> 15.293 + 15.294 +<para>Comme l'anglais est réputé pour être un langage maladroit, et que l'informatique 15.295 +est la source de bien des erreurs de terminologies (pourquoi utiliser un 15.296 +seul terme quand quatre feront l'affaire ?), la gestion de version a une 15.297 +variété de mots et de phrases qui veulent dire la même chose. Si vous 15.298 +discutez d'historique de Mercurial avec d'autres personnes, 15.299 +%%%TODO: ça ne veut rien dire: il faut supprimer une des personnes : soit "quelqu'un", 15.300 +% soit "à d'autres personnes" 15.301 +vous constaterez que souvent le mot <quote>\textit{changeset}</quote> est contracté simplement 15.302 +en <quote>change</quote> ou (à l'écrit) <quote>cset</quote>, et même parfois un 15.303 +\textit{changeset} simplement <quote>révision</quote>, abrégé en <quote>rev</quote>. 15.304 +</para> 15.305 + 15.306 +<para>Bien que le <emphasis>mot</emphasis> que vous utilisez pour désigner le concept de 15.307 +\textit{changeset} importe peu, l'<emphasis>identifiant</emphasis> que vous utilisez 15.308 +pour désigner un <emphasis>changeset</emphasis> \textit{spécifique} a une grande 15.309 +importance. Rappelez vous que le champ \textit{changeset} affiché par la 15.310 +commande <command role="hg-cmd">hg log</command> identifie un \textit{changeset} à la fois avec 15.311 +un numéro de révision et une séquence hexadécimale. 15.312 +</para> 15.313 + 15.314 +<itemizedlist> 15.315 +<listitem><para>Le numéro de révision est <emphasis>seulement valable dans ce dépôt</emphasis>, 15.316 +</para> 15.317 +</listitem> 15.318 +<listitem><para>alors que la séquence hexadécimale est un \emph{identifiant 15.319 + permanent, et invariant } qui pourra toujours être associé au 15.320 + \textit{changeset} exact de <emphasis>chaque</emphasis> copie de votre dépôt. 15.321 +</para> 15.322 +</listitem></itemizedlist> 15.323 + 15.324 +<para>La distinction est importante. Si vous envoyez un email à quelqu'un en 15.325 +parlant de la <quote>révision 33</quote>, il est très probable que sa révision 33 15.326 +<emphasis>ne sera pas la même</emphasis> que la votre. La raison de ceci est que le 15.327 +numéro de révision dépend de l'ordre dans lequel les modifications sont 15.328 +arrivées dans le dépôt, et il n'y a aucune garantie que les mêmes changements 15.329 +soient arrivés dans le même ordre dans différents dépôts. Trois modifications 15.330 +$a,b,c$ peuvent aisément apparaitre dans un dépôt comme $0,1,2$, et dans 15.331 +un autre comme $1,0,2$. 15.332 +</para> 15.333 + 15.334 +<para>Mercurial utilise les numéros de révision uniquement comme des raccourcis 15.335 +pratiques. Si vous devez discuter d'un \textit{changeset} avec quelqu'un, 15.336 +ou identifer un \textit{changeset} pour une quelquonque %%%TODO: our : "pour" ou "ou" 15.337 +raison (par exemple, un rapport de \textit{bug}), utilisez la séquence 15.338 +hexadécimale. 15.339 +</para> 15.340 + 15.341 +</sect2> 15.342 +<sect2> 15.343 +<title>Afficher une révision spécifique</title> 15.344 + 15.345 +<para>Pour réduire la sortie de <command role="hg-cmd">hg log</command> à une seule révision, utilisez 15.346 +l'option <option role="hg-opt-log">-r</option> (ou <option role="hg-opt-log">--rev</option>). Vous pouvez utiliser 15.347 +le numéro de révision ou la séquence hexadécimale comme identifiant, et 15.348 +demander autant de révisions que vous le souhaitez. 15.349 +<!-- &interaction.tour.log-r; --> 15.350 +</para> 15.351 + 15.352 +<para>Si vous voulez voir l'historique de plusieurs révisions sans avoir à 15.353 +les énumérer, vous pouvez utiliser la <emphasis>\textit{range notation</emphasis>} 15.354 +\footnote{NdT: Il n'est pas aisé de traduire ce terme, donc je le %%%TODO : intervalle de numérotation ? 15.355 +laisse en anglais} qui vous permet d'exprimer l'idée <quote>je veux toutes 15.356 +les révisions entre $a$ et $b$, inclus</quote>. 15.357 +<!-- &interaction.tour.log.range; --> 15.358 +Mercurial respecte aussi l'ordre dans lequel vous spécifiez les 15.359 +révisions, ainsi <command role="hg-cmd">hg log -r 2:4</command> affichera $2,3,4$ alors que 15.360 +<command role="hg-cmd">hg log -r 4:2</command> affichera $4,3,2$. 15.361 +</para> 15.362 + 15.363 +</sect2> 15.364 +<sect2> 15.365 +<title>Informations détaillées</title> 15.366 + 15.367 + 15.368 +<para>Le résumé affiché par <command role="hg-cmd">hg log</command> est suffisant si vous savez déjà ce %%%TODO: je pense que le premier "si" est de trop : exact 15.369 +que vous cherchez. En revanche, vous aurez probablement besoin de voir une description 15.370 +complète du changement, ou une liste des fichiers modifiés si vous 15.371 +cherchez à déterminer qu'un \textit{changeset} est bien celui que vous%%%TODO: les propositions sont mal construites : après un "si...." il faut une proposition sans "si... donc ici : "si ... recherchez", ben quoi ? 15.372 +recherchez. L'option \hgopt{-v} de la commande <command role="hg-cmd">hg log</command> (ou 15.373 +\hgopt{--verbose}) vous donne ces informations supplémentaires. 15.374 +<!-- &interaction.tour.log-v; --> 15.375 +</para> 15.376 + 15.377 +<para>Si vous voulez voir à la fois la description et le contenu d'une 15.378 +modification, ajouter l'option <option role="hg-opt-log">-p</option> (ou <option role="hg-opt-log">--patch</option>). 15.379 +Ceci affiche le contenu d'une modification comme un <emphasis>diff unifié</emphasis> 15.380 +\footnote{NdT: \textit{unified diff}} (si vous n'avez jamais vu de diff 15.381 +unifié avant, consultez la section <xref linkend="sec:mq:patch"/> pour un rapide 15.382 +survol). 15.383 +</para> 15.384 + 15.385 +<para><!-- &interaction.tour.log-vp; --> 15.386 +</para> 15.387 + 15.388 +</sect2> 15.389 +</sect1> 15.390 +<sect1> 15.391 +<title>Tout sur les options de commandes</title> 15.392 + 15.393 + 15.394 +<para>Avant d'aller plus loin sur le fonctionnement des commandes de Mercurial, 15.395 +étudions un moment comment elles fonctionnent de manière générale. Vous 15.396 +trouverez ça probablement utile pour la suite de notre parcours. 15.397 +</para> 15.398 + 15.399 +<para>Mercurial utilise une approche directe et cohérente pour interpréter %%%TODO: une manière d'approche ? 15.400 +les options que vous passez aux commandes. Il suit une convention commune 15.401 +à la plupart des systèmes Unix et Linux modernes. 15.402 +</para> 15.403 + 15.404 +<itemizedlist> 15.405 +<listitem><para>Chaque option a un nom complet. Par exemple, comme nous l'avons déjà 15.406 + vu, la commande <command role="hg-cmd">hg log</command> accepte l'option <option role="hg-opt-log">--rev</option>.%%%TODO: commande ou command e\hgcmd...? 15.407 +</para> 15.408 +</listitem> 15.409 +<listitem><para>La plupart des options disposent de noms abrégés. Aussi, au lieu d'utiliser 15.410 + <option role="hg-opt-log">--rev</option>, vous pouvez utiliser <option role="hg-opt-log">-r</option>. (Les options qui 15.411 + n'ont pas de noms abrégés sont généralement rarement utilisées, pour cette raison). 15.412 +</para> 15.413 +</listitem> 15.414 +<listitem><para>Les noms complets commencent par deux tirets (i.e. <option role="hg-opt-log">--rev</option>), 15.415 + alors que les options courtes commencent avec un seul (i.e. <option role="hg-opt-log">-r</option>). 15.416 +</para> 15.417 +</listitem> 15.418 +<listitem><para>Les noms des options sont cohérents entre les commandes. Par exemple, 15.419 + chaque commande qui accepte un \textit{changeset ID} ou un numéro de révision 15.420 + accepte aussi <option role="hg-opt-log">-r</option> et <option role="hg-opt-log">--rev</option> comme arguments. 15.421 + %TODO: Small mistake here, shouldn't have log here... shouldn't it ? 15.422 +</para> 15.423 +</listitem></itemizedlist> 15.424 + 15.425 +<para>Dans les exemples de ce livre, j'utilise les noms abrégés plutôt que les noms 15.426 +complets. Ceci est une préférence personnelle, pas une recommandation. 15.427 +</para> 15.428 + 15.429 +<para>La plupart des commandes qui affichent une quelconque sortie à l'écran, 15.430 +afficheront davantage avec l'option <option role="hg-opt-global">-v</option> (ou <option role="hg-opt-global">--verbose</option>), et 15.431 +moins avec l'option <option role="hg-opt-global">-q</option> (ou <option role="hg-opt-global">--quiet</option>). 15.432 +</para> 15.433 + 15.434 +</sect1> 15.435 +<sect1> 15.436 +<title>Faire et vérifier des modifications</title> 15.437 + 15.438 +<para>Maintenant que nous avons une bonne idée des commandes pour consulter 15.439 +l'historique de Mercurial, regardons comment faire des modifications et 15.440 +les examiner. 15.441 +</para> 15.442 + 15.443 + 15.444 +<para>La première chose que nous allons faire c'est isoler notre expérience dans 15.445 +un dépôt à part. Nous allons utiliser la commande <command role="hg-cmd">hg clone</command>, mais nous 15.446 +n'avons pas besoin de faire une copie de dépôt distant. Comme nous avons 15.447 +déjà une copie locale, nous pouvons juste faire un clone de celle-ci à la 15.448 +place. C'est beaucoup plus rapide que de faire une copie à travers le 15.449 +réseau, et un dépôt cloné localement prend également moins d'espace disque. 15.450 +</para> 15.451 + 15.452 +<para><!-- &interaction.tour.reclone; --> 15.453 +</para> 15.454 + 15.455 +<para>On notera au passage qu'il est souvent considéré comme une bonne pratique 15.456 +de conserver une copie <quote>immaculée</quote> du dépôt distant, à partir de laquelle 15.457 +vous pourrez faire des copies locales temporaires pour créer des <quote>bacs à 15.458 +sable</quote> pour chaque tâche sur laquelle vous souhaitez travailler. Ceci vous 15.459 +permet de travailler sur plusieurs choses en parallèle, chacune isolée les 15.460 +unes des autres en attendant que ces tâches soient finies et que vous soyez 15.461 +prêt à les réintégrer. Parce que les copies locales sont peu coûteuses, il 15.462 +est très rapide de créer ou détruire des dépôts dès que vous en avez besoin. 15.463 +</para> 15.464 + 15.465 +<para>%% Note: la dernière phrase n'est pas une traduction littérale, mais je 15.466 +%% pense qu'elle exprime plus clairement en français ce que veut dire son 15.467 +%% équivalent anglais. : OUI 15.468 +</para> 15.469 + 15.470 +<para>Dans notre dépôt <filename class="directory">my-hello</filename>, nous avons un fichier <filename>hello.c</filename> 15.471 +qui contient le classique programme <quote>hello, world</quote>. Nous allons utiliser 15.472 +l'ancienne et vénérable commande <command>sed</command> pour l'éditer afin qu'il 15.473 +affiche une seconde ligne à l'écran. (J'utilise <command>sed</command> seulement parce 15.474 +qu'il est ainsi facile d'écrire des exemples sous forme de script. Comme 15.475 +vous n'avez pas ces contraintes, vous n'utiliserez probablement pas <command>sed</command> 15.476 +mais plutôt votre éditeur de texte favori). 15.477 +</para> 15.478 + 15.479 +<para><!-- &interaction.tour.sed; --> 15.480 +</para> 15.481 + 15.482 +<para>La commande <command role="hg-cmd">hg status</command> de Mercurial nous dira de quels fichiers Mercurial 15.483 +s'occupe au sein de ce dépôt. 15.484 +<!-- &interaction.tour.status; --> 15.485 +La commande <command role="hg-cmd">hg status</command> n'affiche rien sur la sortie pour quelques fichiers 15.486 +mais une ligne commence par <quote><literal>M</literal></quote> for <filename>hello.c</filename>. À moins que 15.487 +vous ne lui indiquiez de le faire, <command role="hg-cmd">hg status</command> n'affichera aucune sortie 15.488 +pour les fichiers qui n'ont pas été modifiés. 15.489 +</para> 15.490 + 15.491 +<para>Le caractère <quote><literal>M</literal></quote> indique que Mercurial a remarqué que nous avions 15.492 +modifié le fichier <filename>hello.c</filename>. Nous n'avons pas besoin d'<emphasis>informer</emphasis> 15.493 +Mercurial que nous allons modifier un fichier avant de le faire, ou que nous 15.494 +venons de le modifier, il est capable de s'en rendre compte tout seul. 15.495 +</para> 15.496 + 15.497 +<para>C'est pratique de savoir que nous avons modifié <filename>hello.c</filename>, mais il 15.498 +serait encore plus pratique de savoir ce que nous avons modifié exactement. Pour 15.499 +cela, nous avons la commande <command role="hg-cmd">hg diff</command>. 15.500 +</para> 15.501 + 15.502 +<para><!-- &interaction.tour.diff; --> 15.503 +</para> 15.504 + 15.505 +</sect1> 15.506 +<sect1> 15.507 +<title>Enregister les modifications dans un nouveau \textit{changeset}</title> 15.508 + 15.509 +<para>Nous pouvons modifier des fichiers, compiler et tester nos modifications, 15.510 +et utiliser les commandes <command role="hg-cmd">hg status</command> et <command role="hg-cmd">hg diff</command> pour voir les 15.511 +modifications effectuées, jusqu'au moment où nous serons assez satisfaits 15.512 +pour décider d'enregistrer notre travail dans un \textit{changeset}. 15.513 +</para> 15.514 + 15.515 +<para>La commande <command role="hg-cmd">hg commit</command> vous laisse créer un nouveau \textit{changeset}, 15.516 +nous désignerons généralement cette opération par <quote>faire un commit</quote> ou 15.517 +<quote>commiter</quote>\footnote{NdT: De mon expérience, la plupart des francophones 15.518 +utilisent régulièrement, à l'oral, cette expression, mais bien évidement 15.519 +il ne s'agit pas d'un terme de terminologie correcte, ni même français.} 15.520 +</para> 15.521 + 15.522 +<sect2> 15.523 +<title>Définir le nom d'utilisateur</title> 15.524 + 15.525 +<para>Quand vous exécutez la commande <command role="hg-cmd">hg commit</command> pour la première fois, elle 15.526 +n'est pas garantie de réussir. Mercurial enregistre votre nom et votre 15.527 +adresse avec chaque modification que vous effectuez, de manière à ce que 15.528 +vous soyez capable (ou d'autres le soient) de savoir qui a fait quelle 15.529 +modification. Mercurial essaye automatiquement de découvrir un nom 15.530 +d'utilisateur qui ait un minimum de sens pour effectuer l'opération 15.531 +de \textit{commit} avec. Il va essayer chacune des méthodes suivantes, 15.532 +dans l'ordre: 15.533 +</para> 15.534 +<orderedlist> 15.535 +<listitem><para>Si vous spécifiez l'option <option role="hg-opt-commit">-u</option> avec la commande 15.536 + <command role="hg-cmd">hg commit</command>, suivi d'un nom d'utilisateur, ceci aura toujours la 15.537 + priorité sur les autres méthodes ci dessous. 15.538 +</para> 15.539 +</listitem> 15.540 +<listitem><para>Si vous avez défini une variable d'environnement <envar>HGUSER</envar>, 15.541 + c'est cette valeur qui est alors utilisée. 15.542 +</para> 15.543 +</listitem> 15.544 +<listitem><para>Si vous créez un fichier nommé <filename role="special">.hgrc</filename> dans votre 15.545 + répertoire \textit{home}, avec une entrée <envar role="rc-item-ui">username</envar>, 15.546 + c'est la valeur associée qui sera utilisée. Pour voir à quoi 15.547 + ressemble le contenu de ce fichier regardez la 15.548 + section <xref linkend="sec:tour-basic:username"/> ci-dessous. 15.549 +</para> 15.550 +</listitem> 15.551 +<listitem><para>Si vous avez défini une variable d'environnement <envar>EMAIL</envar> 15.552 + celle ci sera utilisée ensuite. 15.553 +</para> 15.554 +</listitem> 15.555 +<listitem><para>Enfin, Mercurial interrogera votre système pour trouver votre 15.556 + nom d'utilisateur local ainsi que le nom de la machine hôte, et il 15.557 + fabriquera un nom d'utilisateur à partir de ces données. Comme il arrive 15.558 + souvent que ce genre de noms soit totalement inutile, il vous 15.559 + préviendra en affichant un message d'avertissement. 15.560 +</para> 15.561 +</listitem></orderedlist> 15.562 + 15.563 +<para>Si tous ces mécanismes échouent, Mercurial n'exécutera pas la commande, 15.564 +affichant un message d'erreur. Dans ce cas, il ne vous laissera pas 15.565 +effectuer de \textit{commit} tant que vous n'aurez pas défini un nom 15.566 +d'utilisateur. 15.567 +</para> 15.568 + 15.569 +<para>Vous devriez penser à utiliser la variable d'environement <envar>HGUSER</envar> 15.570 +et l'option <option role="hg-opt-commit">-u</option> comme moyen pour \emph{changer le nom 15.571 +d'utilisateur} par défaut. Pour une utilisation normale, la manière la plus 15.572 +simple et robuste d'opérer est de créer un fichier <filename role="special">.hgrc</filename>, 15.573 +voir ci-dessous pour les détails à ce sujet. 15.574 +</para> 15.575 + 15.576 +<sect3> 15.577 +<title>Créer un fichier de configuration pour Mercurial</title> 15.578 +<para>\label{sec:tour-basic:username} 15.579 +</para> 15.580 + 15.581 +<para>Pour définir un nom d'utilisateur, utilisez votre éditeur de texte favori 15.582 +pour créer un fichier <filename role="special">.hgrc</filename> dans votre répertoire \textit{home}. 15.583 +Mercurial va utiliser ce fichier pour retrouver votre configuration personnelle. 15.584 +Le contenu initial devrait ressembler à ceci: 15.585 +</para> 15.586 +<programlisting> 15.587 +<para> # This is a Mercurial configuration file. 15.588 + [ui] 15.589 + username = Firstname Lastname <email.address@domain.net> 15.590 +</para> 15.591 +</programlisting> 15.592 +<para>La ligne avec <literal>[ui]</literal> commence une <emphasis>section</emphasis> du fichier de 15.593 +configuration, ainsi la ligne <quote><literal>username = ...</literal></quote> signifie <quote> 15.594 +définir la valeur de l'élément <literal>username</literal> dans la section 15.595 +<literal>ui</literal></quote>. Une section continue jusqu'à ce qu'une nouvelle 15.596 +commence, ou que la fin du fichier soit atteinte. Mercurial ignore 15.597 +les lignes vides et traite tout texte situé à la suite d'un 15.598 +<quote><literal>#</literal></quote> jusqu'à la fin de la ligne comme un commentaire. 15.599 +</para> 15.600 + 15.601 +</sect3> 15.602 +<sect3> 15.603 +<title>Choisir un nom d'utilisateur</title> 15.604 + 15.605 +<para>Vous pouvez utiliser n'importe quelle valeur pour votre <literal>username</literal>, 15.606 +car cette information est destinée à d'autres personnes et non à être 15.607 +interprétée par Mercurial. La convention que la plupart des personnes 15.608 +<<<<<<< local 15.609 +suivent est d'utiliser leurs noms suivies de leurs adresses emails, 15.610 +comme montrée ci-dessus: 15.611 +</para> 15.612 + 15.613 +<note> 15.614 +<para> Le mécanisme interne du serveur \textit{web} intégré à Mercurial, 15.615 + masque les adresses emails, pour rendre plus difficile leurs 15.616 + récupérations par les outils utilisés par les \textit{spammmers}. 15.617 + Ceci réduit la probabilité que de recevoir encore plus de 15.618 + \textit{spam} si vous vous publiez un dépôt sur internet. 15.619 +</para> 15.620 +</note> 15.621 + 15.622 +</sect3> 15.623 +</sect2> 15.624 +<sect2> 15.625 +<title>Rédiger un message de \textit{commit}</title> 15.626 + 15.627 +<para>Lorsqu'on effectue une opération de \textit{commit}, Mercurial 15.628 +lance automatiquement un éditeur de texte pour permettre de saisir 15.629 +un message qui décrira les modifications effectuées dans ce 15.630 +\textit{changeset}. Ce message est nommé le \emph{message de 15.631 +\textit{commit}}. Ce sera un enregistrement pour tout lecteur 15.632 +expliquant le pourquoi et le comment de vos modifications, et il sera 15.633 +affiché par la commande <command role="hg-cmd">hg log</command>. 15.634 +<!-- &interaction.tour.commit; --> 15.635 +</para> 15.636 + 15.637 +<para>L'éditeur que la commande <command role="hg-cmd">hg commit</command> déclenche ne contiendra 15.638 +qu'une ligne vide suivi d'un certain nombre de lignes commençant 15.639 +par <quote><literal>HG:</literal></quote>. 15.640 +</para> 15.641 +<programlisting> 15.642 +<para> <emphasis>empty line</emphasis> 15.643 + HG: changed hello.c 15.644 +</para> 15.645 +</programlisting> 15.646 +<para>Mercurial ignore les lignes qui commencent avec <quote><literal>HG:</literal></quote>, il 15.647 +ne les utilise que pour nous indiquer quels fichiers modifiés il se 15.648 +prépare à \textit{commiter}. Modifier ou effacer ces lignes n'a 15.649 +aucune conséquence sur l'opération de \textit{commit}. 15.650 +</para> 15.651 + 15.652 +</sect2> 15.653 +<sect2> 15.654 +<title>Rédiger un message \textit{approprié}</title> 15.655 + 15.656 +<para>Comme <command role="hg-cmd">hg log</command> n'affiche que la première ligne du message de 15.657 +\textit{commit} par défaut, il est souvent considéré comme une bonne 15.658 +pratique de rédiger des messages de \textit{commit} qui tiennent 15.659 +sur une seule ligne. Voilà un exemple concret de message de 15.660 +\textit{commit} qui <emphasis>ne suit pas</emphasis> cette directive, et qui a donc 15.661 +un résumé peu lisible. 15.662 +</para> 15.663 + 15.664 +<programlisting> 15.665 +<para> changeset: 73:584af0e231be 15.666 + user: Censored Person <censored.person@example.org> 15.667 + date: Tue Sep 26 21:37:07 2006 -0700 15.668 + summary: include buildmeister/commondefs. Add an exports and install 15.669 +</para> 15.670 +</programlisting> 15.671 + 15.672 +<para>A ce sujet, il faut noter qu'il n'existe pas de règle absolue dans ce 15.673 +domaine. Mercurial lui-même n'interprète pas les contenus des messages 15.674 +de \textit{commit}, ainsi votre projet est libre de concevoir différentes 15.675 +politiques de mise en page des messages. 15.676 +</para> 15.677 + 15.678 +<para>Ma préférence personnelle va au message court, mais informatif, qui offre 15.679 +des précisions supplémentaires par rapport à ce que pourrait m'apprendre une commande 15.680 +<command role="hg-cmd">hg log --patch</command>. 15.681 +</para> 15.682 + 15.683 +</sect2> 15.684 +<sect2> 15.685 +<title>Annuler un \textit{commit}</title> 15.686 + 15.687 +<para>Si, en rédigeant le message, vous décidez que finalement vous ne 15.688 +voulez pas effectuer ce \textit{commit}, il suffit de quitter simplement 15.689 +l'éditeur sans sauver. Ceci n'aura aucune conséquence sur le dépôt ou 15.690 +les fichiers de l'espace de travail. 15.691 +</para> 15.692 + 15.693 +<para>Si vous exécuter la commande <command role="hg-cmd">hg commit</command> sans aucun argument, elle 15.694 +enregistre toutes les modifications que vous avez faites, comme le montre 15.695 +les commandes <command role="hg-cmd">hg status</command> et <command role="hg-cmd">hg diff</command>. 15.696 +</para> 15.697 + 15.698 +</sect2> 15.699 +<sect2> 15.700 +<title>Admirer votre travail</title> 15.701 + 15.702 +<para>Une fois que votre \textit{commit} est terminé, vous pouvez utiliser 15.703 +la commande <command role="hg-cmd">hg tip</command> pour afficher le \textit{changeset} que nous 15.704 +venons de créer. Cette commande produit une sortie à l'écran qui est 15.705 +identique à celle du <command role="hg-cmd">hg log</command>, mais qui n'affiche que la dernière 15.706 +révision du dépôt. 15.707 +<!-- &interaction.tour.tip; --> 15.708 +On fait couramment référence à la dernière révision du dépôt comme 15.709 +étant la révision \textit{tip}, ou plus simplement le \textit{tip}. 15.710 +</para> 15.711 + 15.712 +</sect2> 15.713 +</sect1> 15.714 +<sect1> 15.715 +<title>Partager ses modifications</title> 15.716 + 15.717 +<para>Nous avons mentionné plus haut que les dépôts de Mercurial 15.718 +sont autosuffisants. Ce qui signifie que le \textit{changeset} 15.719 +que vous venez de créer existe seulement dans votre répertoire 15.720 +<filename class="directory">my-hello</filename>. Étudions comment propager cette modification 15.721 +dans d'autres dépôts. 15.722 +</para> 15.723 + 15.724 +<sect2> 15.725 +<title>Récupérer les modifications d'autres dépôts</title> 15.726 +<para>\label{sec:tour:pull} 15.727 +</para> 15.728 + 15.729 +<para>Pour commencer, construisons un clone de notre dépôt <filename class="directory">hello</filename> 15.730 +qui ne contiendra pas le changement que nous venons d'effectuer. Nous 15.731 +l'appellerons notre dépôt temporaire <filename class="directory">hello-pull</filename>. 15.732 +</para> 15.733 + 15.734 +<para><!-- &interaction.tour.clone-pull; --> 15.735 +</para> 15.736 + 15.737 +<para>Nous allons utiliser la commande <command role="hg-cmd">hg pull</command> pour apporter les 15.738 +modifications depuis <filename class="directory">my-hello</filename> dans <filename class="directory">hello-pull</filename>. 15.739 +Néanmoins, récupérer aveuglement des modifications depuis un dépôt 15.740 +a quelque chose d'un peu effrayant. Mercurial propose donc une 15.741 +commande <command role="hg-cmd">hg incoming</command> qui permet de savoir quelles modifications 15.742 +la commande <command role="hg-cmd">hg pull</command> <emphasis>pourrait</emphasis> entraîner dans notre dépôt, 15.743 +et ceci sans effectuer réellement de modification dessus. 15.744 +<!-- &interaction.tour.incoming; --> 15.745 +(Bien évidement, quelqu'un pourrait ajouter des modifications 15.746 +supplémentaires sur le dépôt que nous étudions avec <command role="hg-cmd">hg incoming</command>, 15.747 +avant que nous ayons effectué notre <command role="hg-cmd">hg pull</command>, avec comme 15.748 +triste conséquence que nous aurons récupéré des modifications que 15.749 +nous n'attendions pas.) 15.750 +</para> 15.751 + 15.752 +<para>Apporter les modifications rapatriées dans un dépôt se résume donc 15.753 +à exécuter la commande <command role="hg-cmd">hg pull</command>, et préciser depuis quel dépôt 15.754 +effectuer le <command role="hg-cmd">hg pull</command>. 15.755 +<!-- &interaction.tour.pull; --> 15.756 +</para> 15.757 + 15.758 +<para>Comme vous le voyez avec une sortie avant et après de la commande 15.759 +<command role="hg-cmd">hg tip</command>, nous avons réussi à récupérer aisément les modifications 15.760 +dans notre dépôt. Il reste néanmoins quelque chose à faire avant de 15.761 +placer ces modifications dans l'espace de travail. 15.762 +</para> 15.763 + 15.764 +</sect2> 15.765 +<sect2> 15.766 +<title>Mise à jour de l'espace de travail</title> 15.767 + 15.768 +<para>Nous avons jusqu'à maintenant grossièrement définie la relation 15.769 +entre un dépôt et un espace de travail. La commande <command role="hg-cmd">hg pull</command> que 15.770 +nous avons exécutée dans la section <xref linkend="sec:tour:pull"/> a apporté 15.771 +des modifications, que nous avons vérifiées, dans notre dépôt, mais 15.772 +il n'y a aucune trace de ces modifications dans notre espace de travail. 15.773 +En effet, <command role="hg-cmd">hg pull</command> ne touche pas (par défaut) à l'espace de 15.774 +travail. C'est la commande <command role="hg-cmd">hg update</command> qui s'en charge. 15.775 +<!-- &interaction.tour.update; --> 15.776 +</para> 15.777 + 15.778 +<para>Il peut sembler un peu étrange que la commande <command role="hg-cmd">hg pull</command> ne mette 15.779 +pas à jour l'espace de travail automatiquement. Il y a en fait une 15.780 +très bonne raison à cela : vous pouvez utilisez la commande 15.781 +</para> 15.782 + 15.783 +<para><command role="hg-cmd">hg update</command> pour mettre à jour votre espace de travail à l'état 15.784 +dans lequel il était à <emphasis>n'importe quelle révision</emphasis> de l'historique 15.785 +du dépôt. Si vous aviez un espace de travail contenant une ancienne 15.786 +révision&emdash;pour chercher l'origine d'un \textit{bug}, par exemple&emdash;et 15.787 +que vous effectuiez un <command role="hg-cmd">hg pull</command> qui mettrait à jour automatiquement 15.788 +votre espace de travail, vous ne seriez probablement pas très satisfait. 15.789 +</para> 15.790 + 15.791 +<para>Néanmoins, comme les opérations de \textit{pull} sont très souvent 15.792 +suivies d'un \textit{update}, Mercurial vous permet de combiner les 15.793 +deux aisément en passant l'option <option role="hg-opt-pull">-u</option> à la commande 15.794 +<command role="hg-cmd">hg pull</command> 15.795 +</para> 15.796 +<programlisting> 15.797 +<para> hg pull -u 15.798 +</para> 15.799 +</programlisting> 15.800 + 15.801 +<para>Si vous étudiez de nouveau la sortie de la commande <command role="hg-cmd">hg pull</command> dans 15.802 +la section <xref linkend="sec:tour:pull"/> quand nous l'avons exécutée sans l'option 15.803 +<option role="hg-opt-pull">-u</option>, vous pouvez constater qu'elle a affiché un rappel assez 15.804 +utile : vous devez encore effectuer une opération pour mettre à jour 15.805 +votre espace de travail: 15.806 +</para> 15.807 + 15.808 +<programlisting> 15.809 +<para> (run 'hg update' to get a working copy) 15.810 +</para> 15.811 +</programlisting> 15.812 + 15.813 +<para>Pour découvrir sur quelle révision de l'espace de travail on est, utilisez 15.814 +la commande <command role="hg-cmd">hg parents</command>. 15.815 +<!-- &interaction.tour.parents; --> 15.816 +Si vous regardez de nouveau le dessin <xref linkend="fig:tour-basic:history"/>, vous 15.817 +<<<<<<< local 15.818 +verrez les flèches reliant entre eux les \textit{changeset}. Le nœud 15.819 +d'où la flèche <emphasis>part</emphasis> est dans chaque cas un parent, 15.820 +et le nœud où la flèche <emphasis>arrive</emphasis> est un enfant. 15.821 +</para> 15.822 + 15.823 +<para>L'espace de travail a un parent de la même manière, c'est ce \textit{changeset} 15.824 +que l'espace de travail contient à ce moment. 15.825 +%%%TODO : difficile à comprendre : l'espace de travail a un parent, de la même manière, c'est ce changeset que l'espace... 15.826 +</para> 15.827 + 15.828 +<para>Pour mettre à jour l'espace de travail d'une révision particulière, 15.829 +indiquez un numéro de révision ou un \textit{changeset ID} à la commande 15.830 +<command role="hg-cmd">hg update</command>. 15.831 +<!-- &interaction.tour.older; --> 15.832 +Si vous ne précisez pas de manière explicite de numéro de révision 15.833 +la commande <command role="hg-cmd">hg update</command> mettra à jour votre espace de travail avec 15.834 +le contenu de la révsion \textit{tip}, comme montré dans l'exemple 15.835 +ci dessus lors du second appel à <command role="hg-cmd">hg update</command>. 15.836 +</para> 15.837 + 15.838 +</sect2> 15.839 +<sect2> 15.840 +<title>Transférer les modifications à un autre dépôt</title> 15.841 + 15.842 +<para>Mercurial vous laisse transférer les modifications à un autre 15.843 +dépôt, depuis votre dépôt actuel. Comme dans l'exemple du 15.844 +<command role="hg-cmd">hg pull</command> ci-dessus, nous allons créer un dépôt temporaire 15.845 +vers lequel transférer\footnote{NdT: Les francophones disent souvent 15.846 +<quote>pousser</quote> tout simplement} nos modifications. 15.847 +<!-- &interaction.tour.clone-push; --> 15.848 +La commande <command role="hg-cmd">hg outgoing</command> nous indique quels changements nous 15.849 +allons transférer vers l'autre serveur ? 15.850 +<!-- &interaction.tour.outgoing; --> 15.851 +Et la commande <command role="hg-cmd">hg push</command> effectue réellement le transfert. 15.852 +<!-- &interaction.tour.push; --> 15.853 +Comme avec <command role="hg-cmd">hg pull</command>, la commande <command role="hg-cmd">hg push</command> ne met pas à jour 15.854 +le répertoire de travail du dépôt dans lequel il transfère les 15.855 +modifications. (À l'inverse de <command role="hg-cmd">hg pull</command>, <command role="hg-cmd">hg push</command> ne fournit 15.856 +pas d'option <literal>-u</literal> pour forcer la mise à jour de l'espace 15.857 +de travail cible). 15.858 +</para> 15.859 + 15.860 +<para>Qu'est ce qui se passe lorsque vous essayez de récupérer ou de transférer 15.861 +vos modifications et que le dépôt cible a déjà reçu ces modifications ? 15.862 +Rien de bien excitant. 15.863 +<!-- &interaction.tour.push.nothing; --> 15.864 +</para> 15.865 + 15.866 +</sect2> 15.867 +<sect2> 15.868 +<title>Partager ses modifications à travers le réseau</title> 15.869 + 15.870 +<para>Les commandes que nous avons étudiées dans les sections précédentes 15.871 +ne sont pas limitées aux dépôt locaux. Chacune fonctionne de la même 15.872 +manière à travers une connexion réseau, il suffit de lui passer une 15.873 +URL à la place d'un chemin de fichier local. 15.874 +</para> 15.875 + 15.876 +<para><!-- &interaction.tour.outgoing.net; --> 15.877 +Dans cet exemple, nous allons voir quels changements nous pourrions 15.878 +transférer vers le dépôt distant, mais le dépôt est, de manière tout 15.879 +à fait compréhensible, pas configuré pour accepter des modifications 15.880 +d'utilisateurs anonymes. 15.881 +<!-- &interaction.tour.push.net; --> 15.882 +</para> 15.883 + 15.884 +</sect2> 15.885 +</sect1> 15.886 +</chapter> 15.887 + 15.888 +<!-- 15.889 +local variables: 15.890 +sgml-parent-document: ("00book.xml" "book" "chapter") 15.891 +end: 15.892 +--> 15.893 \ No newline at end of file
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 16.2 +++ b/fr/ch03-tour-merge.xml Sun Aug 16 04:58:01 2009 +0200 16.3 @@ -0,0 +1,384 @@ 16.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 16.5 + 16.6 +<chapter> 16.7 +<title>Un rapide tour de Mercurial: fusionner les travaux</title> 16.8 +<para>\label{chap:tour-merge}</para> 16.9 + 16.10 +<para>Nous avons maintenant étudié comment cloner un dépôt, effectuer 16.11 +des changements dedans, et récupérer ou transférer depuis un 16.12 +autre dépôt. La prochaine étape est donc de <emphasis>fusionner</emphasis> les 16.13 +modifications de différents dépôts.</para> 16.14 + 16.15 +<sect1> 16.16 +<title>Fusionner différents travaux</title> 16.17 +<para> %%% for 'Merging streams of work' ? 16.18 +La fusion\footnote{NdT: Je garde fusion mais le jargon professionnel 16.19 +emploiera généralement le terme \textit{merge}.} est un aspect 16.20 +fondamental lorsqu'on travaille avec un gestionnaire de source 16.21 +distribué.</para> 16.22 +<itemizedlist> 16.23 +<listitem><para>Alice et Bob ont chacun une copie personnelle du dépôt d'un 16.24 + projet sur lequel ils collaborent. Alice corrige un \textit{bug} 16.25 + dans son dépôt, et Bob ajoute une nouvelle fonctionnalité dans le 16.26 + sien. Ils veulent un dépôt partagé avec à la fois le correctif du 16.27 + \textit{bug} et la nouvelle fonctionnalité.</para> 16.28 +</listitem> 16.29 +<listitem><para>Je travaille régulièrement sur plusieurs tâches différentes sur 16.30 + un seul projet en même temps, chacun isolé dans son propre dépôt. 16.31 + Travailler ainsi signifie que je dois régulièrement fusionner une 16.32 + partie de mon code avec celui des autres.</para> 16.33 +</listitem></itemizedlist> 16.34 + 16.35 +<para>Parce que la fusion est une opération si commune à réaliser, 16.36 +Mercurial la rend facile. Étudions ensemble le déroulement des opérations. 16.37 +Nous commencerons encore par faire un clone d'un autre dépôt (vous voyez 16.38 +que l'on fait ça tout le temps ?) puis nous ferons quelques modifications 16.39 +dessus. 16.40 +<!-- &interaction.tour.merge.clone; --> 16.41 +Nous devrions avoir maintenant deux copies de <filename>hello.c</filename> avec 16.42 +des contenus différents. Les historiques de ces deux dépôts ont aussi 16.43 +divergés, comme illustré dans la figure <xref linkend="fig:tour-merge:sep-repos"/>.</para> 16.44 + 16.45 +<para><!-- &interaction.tour.merge.cat; --></para> 16.46 + 16.47 +<informalfigure> 16.48 + 16.49 +<para> <mediaobject><imageobject><imagedata fileref="tour-merge-sep-repos"/></imageobject><textobject><phrase>XXX add text</phrase></textobject></mediaobject> 16.50 + <caption><para>Historiques récent divergents des dépôts \dirname{my-hello</para></caption> 16.51 + et <filename class="directory">my-new-hello</filename>} 16.52 + \label{fig:tour-merge:sep-repos}</para> 16.53 +</informalfigure> 16.54 + 16.55 +<para>Nous savons déjà que récupérer les modifications depuis notre dépôt 16.56 +<filename class="directory">my-hello</filename> n'aura aucun effet sur l'espace de travail. 16.57 +</para> 16.58 + 16.59 +<para><!-- &interaction.tour.merge.pull; --> 16.60 +</para> 16.61 + 16.62 +<para>Néanmoins, la commande <command role="hg-cmd">hg pull</command> nous indique quelque chose au 16.63 +sujet des <quote>heads</quote>. 16.64 +</para> 16.65 + 16.66 +<sect2> 16.67 +<title>\textit{Head changesets}</title> 16.68 + 16.69 +<para>Une \textit{head}\footnote{NdT: Je garde \textit{head} que j'accorde 16.70 +au féminin comme la coutume orale l'a imposé.} est un \textit{changeset} 16.71 +sans descendants, ou enfants, comme on les désigne parfois. La révision 16.72 +\textit{tip} est une \textit{head}, car la dernière révision dans un dépôt 16.73 +n'a aucun enfant, mais il est important de noter qu'un dépôt peut contenir 16.74 +plus d'une \textit{head}. 16.75 +</para> 16.76 + 16.77 +<informalfigure> 16.78 + 16.79 +<para> <mediaobject><imageobject><imagedata fileref="tour-merge-pull"/></imageobject><textobject><phrase>XXX add text</phrase></textobject></mediaobject> 16.80 + \caption{Contenu d'un dépôt après avoir transféré le contenu du dépôt 16.81 + <filename class="directory">my-hello</filename> dans le dépôt <filename class="directory">my-new-hello</filename>} 16.82 + \label{fig:tour-merge:pull} 16.83 +</para> 16.84 +</informalfigure> 16.85 + 16.86 +<para>Dans la figure <xref linkend="fig:tour-merge:pull"/>, vous pouvez constater l'effet 16.87 +d'un \textit{pull} depuis le dépôt <filename class="directory">my-hello</filename> dans le dépôt 16.88 +<filename class="directory">my-new-hello</filename>. L'historique qui était déjà présent dans le dépôt 16.89 +<filename class="directory">my-new-hello</filename> reste intact, mais une nouvelle révision a été 16.90 +ajoutée. En vous reportant à la figure <xref linkend="fig:tour-merge:sep-repos"/>, 16.91 +vous pouvez voir que le \textit{<emphasis>changeset ID</emphasis>} reste le même dans 16.92 +le nouveau dépôt, mais que le <emphasis>numéro de révision</emphasis> reste le même. 16.93 +(Ceci est un parfait exemple de pourquoi il n'est fiable d'utiliser les 16.94 +numéros de révision lorsque l'on discute d'un \textit{changeset}.) Vous 16.95 +pouvez voir les \texit{heads} présentes dans le dépôt en utilisant la 16.96 +commande <command role="hg-cmd">hg heads</command>. 16.97 +<!-- &interaction.tour.merge.heads; --> 16.98 +</para> 16.99 + 16.100 +</sect2> 16.101 +<sect2> 16.102 +<title>Effectuer la fusion</title> 16.103 + 16.104 +<para>Que se passe-t-il quand vous essayez d'utiliser la commande <command role="hg-cmd">hg update</command> 16.105 +pour mettre à jour votre espace de travail au nouveau \textit{tip}. 16.106 +<!-- &interaction.tour.merge.update; --> 16.107 +Mercurial nous prévient que la commande <command role="hg-cmd">hg update</command> n'effectuera pas 16.108 +la fusion, il ne veut pas mettre à jour l'espace de travail quand il 16.109 +estime que nous pourrions avoir besoin d'une fusion, à moins de lui 16.110 +forcer la main. À la place, il faut utiliser la commande <command role="hg-cmd">hg merge</command> 16.111 +pour fusionner les deux \textit{heads}. 16.112 +<!-- &interaction.tour.merge.merge; --> 16.113 +</para> 16.114 + 16.115 +<informalfigure> 16.116 + 16.117 +<para> <mediaobject><imageobject><imagedata fileref="tour-merge-merge"/></imageobject><textobject><phrase>XXX add text</phrase></textobject></mediaobject> 16.118 + \caption{Espace de travail et dépôt lors d'une fusion, et dans le 16.119 + \textit{commit} qui suit.} 16.120 + \label{fig:tour-merge:merge} 16.121 +</para> 16.122 +</informalfigure> 16.123 + 16.124 +<para>Ceci met à jour l'espace de travail de manière à ce qu'il contienne 16.125 +les modifications des <emphasis>deux</emphasis> \textit{heads}, ce qui apparaît dans 16.126 +les sorties de la commande <command role="hg-cmd">hg parents</command> et le contenu de 16.127 +<filename>hello.c</filename>. 16.128 +<!-- &interaction.tour.merge.parents; --> 16.129 +</para> 16.130 + 16.131 +</sect2> 16.132 +<sect2> 16.133 +<title>Effectuer le \textit{commit} du résultat de la fusion</title> 16.134 + 16.135 +<para>Dès l'instant où vous avez effectué une fusion, <command role="hg-cmd">hg parents</command> vous 16.136 +affichera deux parents, avant que vous n'exécutiez la commande 16.137 +<command role="hg-cmd">hg commit</command> sur le résultat de la fusion. 16.138 +<!-- &interaction.tour.merge.commit; --> 16.139 +Nous avons maintenant un nouveau \textit{tip}, remarquer qu'il contient 16.140 +<emphasis>à la fois</emphasis> nos anciennes \textit{heads} et leurs parents. Ce sont 16.141 +les mêmes révisions que nous avions affichées avec la commande 16.142 +<command role="hg-cmd">hg parents</command>. 16.143 +</para> 16.144 + 16.145 +<para><!-- &interaction.tour.merge.tip; --> 16.146 +Dans la figure <xref linkend="fig:tour-merge:merge"/>, vous pouvez voir une représentation 16.147 +de ce qui se passe dans l'espace de travail pendant la fusion, et comment ceci 16.148 +affecte le dépôt lors du \textit{commit}. Pendant la fusion, l'espace de travail, 16.149 +qui a deux \texit{changesets} comme parents, voit ces derniers devenir le parent 16.150 +%%% TODO: le parent ou "les parents" : plus logique mais si il reste seulement 16.151 +%%% un changeset, alors c'est effectivement un parent (le changeset est hermaphrodite) 16.152 +d'un nouveau \textit{changeset}. 16.153 +</para> 16.154 + 16.155 +</sect2> 16.156 +</sect1> 16.157 +<sect1> 16.158 +<title>Fusionner les modifications en conflit</title> 16.159 + 16.160 +<para>La plupart des fusions sont assez simple à réaliser, mais parfois 16.161 +vous vous retrouverez à fusionner des fichiers où la modification touche 16.162 +la même portion de code, au sein d'un même fichier. À moins que ces 16.163 +modification ne soient identiques, ceci aboutira à un <emphasis>conflit</emphasis>, 16.164 +et vous devrez décider comment réconcilier les différentes modifications 16.165 +dans un tout cohérent. 16.166 +</para> 16.167 + 16.168 +<informalfigure> 16.169 + 16.170 +<para> <mediaobject><imageobject><imagedata fileref="tour-merge-conflict"/></imageobject><textobject><phrase>XXX add text</phrase></textobject></mediaobject> 16.171 + <caption><para>Modifications conflictuelles dans un document</para></caption> 16.172 + \label{fig:tour-merge:conflict} 16.173 +</para> 16.174 +</informalfigure> 16.175 + 16.176 +<para>La figure <xref linkend="fig:tour-merge:conflict"/> illustre un cas de modifications 16.177 +conflictuelles dans un document. Nous avons commencé avec une version simple 16.178 +de ce fichier, puis nous avons ajouté des modifications, pendant que 16.179 +quelqu'un d'autre modifiait le même texte. Notre tâche dans la résolution 16.180 +du conflit est de décider à quoi le fichier devrait ressembler. 16.181 +</para> 16.182 + 16.183 +<para>Mercurial n'a pas de mécanisme interne pour gérer les conflits. 16.184 +À la place, il exécute un programme externe appelé <command>hgmerge</command>. 16.185 +Il s'agit d'un script shell qui est embarqué par Mercurial, vous 16.186 +pouvez le modifier si vous le voulez. Ce qu'il fait par défaut est 16.187 +d'essayer de trouver un des différents outils de fusion qui seront 16.188 +probablement installés sur le système. Il commence par les outils 16.189 +totalement automatiques, et si ils échouent (parce que la résolution 16.190 +du conflit nécessite une intervention humaine) ou si ils sont absents, 16.191 +le script tente d'exécuter certains outils graphiques de fusion. 16.192 +</para> 16.193 + 16.194 +<para>Il est aussi possible de demander à Mercurial d'exécuter un autre 16.195 +programme ou un autre script au lieu de la commande <command>hgmerge</command>, 16.196 +en définissant la variable d'environnement <envar>HGMERGE</envar> avec le nom 16.197 +du programme de votre choix. 16.198 +</para> 16.199 + 16.200 +<sect2> 16.201 +<title>Utiliser un outil graphique de fusion</title> 16.202 + 16.203 +<para>Mon outil de fusion préféré est <command>kdiff3</command>, que j'utilise ici 16.204 +pour illustrer les fonctionnalités classiques des outils graphiques 16.205 +de fusion. Vous pouvez voir une capture d'écran de l'utilisation de 16.206 +<command>kdiff3</command> dans la figure <xref linkend="fig:tour-merge:kdiff3"/>. Cet outil 16.207 +effectue une <emphasis>fusion \textit{three-way</emphasis>}, car il y a trois différentes 16.208 +versions du fichier qui nous intéresse. Le fichier découpe la partie 16.209 +supérieure de la fenêtre en trois panneaux: 16.210 +</para> 16.211 + 16.212 +<itemizedlist> 16.213 +<listitem><para>A gauche on la version de <emphasis>base</emphasis> du fichier, soit la plus 16.214 + récente version des deux versions qu'on souhaite fusionner. 16.215 +</para> 16.216 +</listitem> 16.217 +<listitem><para>Au centre, il y a <quote>notre</quote> version du fichier, avec le contenu 16.218 + que nous avons modifié. 16.219 +</para> 16.220 +</listitem> 16.221 +<listitem><para>Sur la droite, on trouve <quote>leur</quote> version du fichier, celui qui 16.222 + contient le \textit{changeset} que nous souhaitons intégré. 16.223 +</para> 16.224 +</listitem></itemizedlist> 16.225 + 16.226 +<para>Dans le panneau en dessous, on trouve le <emphasis>résultat</emphasis> actuel de notre 16.227 +fusion. Notre tâche consiste donc à remplacement tous les textes en rouges, 16.228 +qui indiquent des conflits non résolus, avec une fusion manuelle et pertinente 16.229 +de <quote>notre</quote> version et de la <quote>leur</quote>. 16.230 +</para> 16.231 + 16.232 +<para>Tous les quatre panneaux sont <emphasis>accrochés ensemble</emphasis>, si nous déroulons 16.233 +les ascenseurs verticalement ou horizontalement dans chacun d'entre eux, les 16.234 +autres sont mis à jour avec la section correspondante dans leurs fichiers 16.235 +respectifs. 16.236 +</para> 16.237 + 16.238 +<informalfigure> 16.239 + 16.240 +<para> <mediaobject><imageobject><imagedata fileref="kdiff3"/></imageobject><textobject><phrase>XXX add text</phrase></textobject></mediaobject> 16.241 + <caption><para>Utilisation de \command{kdiff3</para></caption> pour fusionner différentes versions 16.242 + d'un fichier.} 16.243 + \label{fig:tour-merge:kdiff3} 16.244 +</para> 16.245 +</informalfigure> 16.246 + 16.247 +<para>Pour chaque portion de fichier posant problème, nous pouvons choisir 16.248 +de résoudre le conflit en utilisant une combinaison 16.249 +de texte depuis la version de base, la notre, ou la leur. Nous pouvons 16.250 +aussi éditer manuellement les fichiers à tout moment, si c'est 16.251 +nécessaire. 16.252 +</para> 16.253 + 16.254 +<para>Il y a <emphasis>beaucoup</emphasis> d'outils de fusion disponibles, bien trop pour 16.255 +en parler de tous ici. Leurs disponibilités varient selon les plate formes 16.256 +ainsi que leurs avantages et inconvénients. La plupart sont optimisé pour 16.257 +la fusion de fichier contenant un texte plat, certains sont spécialisé 16.258 +dans un format de fichier précis (généralement XML). 16.259 +</para> 16.260 + 16.261 +</sect2> 16.262 +<sect2> 16.263 +<title>Un exemple concret</title> 16.264 + 16.265 +<para>Dans cet exemple, nous allons reproduire la modification de l'historique 16.266 +du fichier de la figure <xref linkend="fig:tour-merge:conflict"/> ci dessus. Commençons 16.267 +par créer un dépôt avec une version de base de notre document. 16.268 +</para> 16.269 + 16.270 +<para><!-- &interaction.tour-merge-conflict.wife; --> 16.271 +Créons un clone de ce dépôt et faisons une modification dans le fichier. 16.272 +<!-- &interaction.tour-merge-conflict.cousin; --> 16.273 +Et un autre clone, pour simuler que quelqu'un d'autre effectue une 16.274 +modification sur le fichier. (Ceci pour suggérer qu'il n'est pas rare 16.275 +de devoir effectuer des \textit{merge} avec vos propres travaux quand 16.276 +vous isolez les tâches dans des dépôts distincts. En effet, vous 16.277 +aurez alors à trouver et résoudre certains conflits). 16.278 +<!-- &interaction.tour-merge-conflict.son; --> 16.279 +Maintenant que ces deux versions différentes du même fichier sont 16.280 +créées, nous allons configurer l'environnement de manière appropriée pour 16.281 +exécuter notre \textit{merge}. 16.282 +<!-- &interaction.tour-merge-conflict.pull; --> 16.283 +</para> 16.284 + 16.285 +<para>Dans cette exemple, je n'utiliserais pas la commande Mercurial 16.286 +habituelle <command>hgmerge</command> pour effectuer le \textit{merge}, 16.287 +car il me faudrait abandonner ce joli petit exemple automatisé 16.288 +pour utiliser un outil graphique. À la place, je vais définir 16.289 +la variable d'environnement <envar>HGMERGE</envar> pour indiquer à 16.290 +Mercurial d'utiliser la commande non-interactive <command>merge</command>. 16.291 +Cette dernière est embarquée par de nombreux systèmes <quote>à la Unix</quote>. 16.292 +Si vous exécutez cet exemple depuis votre ordinateur, ne vous 16.293 +occupez pas de définir <envar>HGMERGE</envar>. 16.294 +<!-- &interaction.tour-merge-conflict.merge; --> 16.295 +Parce que <command>merge</command> ne peut pas résoudre les modifications 16.296 +conflictuelles, il laisse des <emphasis>marqueurs de différences</emphasis> 16.297 +\footnote{NdT: Oui, je traduis \textit{merge markers} par un sens 16.298 +inverse en Français, mais je pense vraiment que c'est plus clair 16.299 +comme ça...} à l'intérieur du fichier qui a des conflits, indiquant 16.300 +clairement quelles lignes sont en conflits, et si elles viennent de 16.301 +notre fichier ou du fichier externe. 16.302 +</para> 16.303 + 16.304 +<para>Mercurial peut distinguer, à la manière dont la commande <command>merge</command> 16.305 +se termine, qu'elle n'a pas été capable d'effectuer le \textit{merge}, 16.306 +alors il nous indique que nous devons effectuer de nouveau cette 16.307 +opération. Ceci peut être très utile si, par exemple, nous exécutons un 16.308 +outil graphique de fusion et que nous le quittons sans nous rendre compte 16.309 +qu'il reste des conflits ou simplement par erreur. 16.310 +</para> 16.311 + 16.312 +<para>Si le \textit{merge} automatique ou manuel échoue, il n'y a rien pour 16.313 +nous empêcher de <quote>corriger le tir</quote> en modifiant nous même les fichiers, 16.314 +et enfin effectuer le \textit{commit} du fichier: 16.315 +<!-- &interaction.tour-merge-conflict.commit; --> 16.316 +</para> 16.317 + 16.318 +</sect2> 16.319 +</sect1> 16.320 +<sect1> 16.321 +<title>Simplification de la séquence pull-merge-commit</title> 16.322 +<para>\label{sec:tour-merge:fetch} 16.323 +</para> 16.324 + 16.325 +<para>La procédure pour effectuer la fusion indiquée ci-dessus est simple, 16.326 +mais requiert le lancement de trois commandes à la suite. 16.327 +</para> 16.328 +<programlisting> 16.329 +<para> hg pull 16.330 + hg merge 16.331 + hg commit -m 'Merged remote changes' 16.332 +</para> 16.333 +</programlisting> 16.334 + 16.335 +<para>Lors du \textit{commit} final, vous devez également saisir un message, 16.336 +qui aura vraisemblablement assez peu d'intérêt. 16.337 +</para> 16.338 + 16.339 +<para>Il serait assez sympathique de pouvoir réduire le nombre d'opérations 16.340 +nécessaire, si possible. De fait Mercurial est fourni avec une 16.341 +extension appelé <literal role="hg-ext">fetch</literal> qui fait justement cela. 16.342 +</para> 16.343 + 16.344 +<para>Mercurial fourni un mécanisme d'extension flexible qui permet à chacun 16.345 +d'étendre ces fonctionnalités, tout en conservant le cœur de Mercurial 16.346 +léger et facile à utiliser. Certains extensions ajoutent de nouvelles 16.347 +commandes que vous pouvez utiliser en ligne de commande, alors que 16.348 +d'autres travaillent <quote>en coulisse,</quote> par exemple en ajoutant des 16.349 +possibilités au serveur. 16.350 +</para> 16.351 + 16.352 +<para>L'extension <literal role="hg-ext">fetch</literal> ajoute une nouvelle commande nommée, sans 16.353 +surprise, <command role="hg-cmd">hg fetch</command>. Cette extension résulte en une combinaison 16.354 +de <command role="hg-cmd">hg pull</command>, <command role="hg-cmd">hg update</command> and <command role="hg-cmd">hg merge</command>. Elle commence par 16.355 +récupérer les modifications d'un autre dépôt dans le dépôt courant. 16.356 +Si elle trouve que les modifications ajoutent une nouvelle \textit{head}, 16.357 +elle effectue un \textit{merge}, et ensuite \texit{commit} le résultat 16.358 +du \textit{merge} avec un message généré automatiquement. Si aucune 16.359 +\textit{head} n'ont été ajouté, elle met à jour le répertoire de travail 16.360 +au niveau du nouveau \textit{changeset} \textit{tip}. 16.361 +</para> 16.362 + 16.363 + 16.364 +<para>Activer l'extension <literal role="hg-ext">fetch</literal> est facile. Modifiez votre <filename role="special">.hgrc</filename>, 16.365 +et soit allez à la section <literal role="rc-extensions">extensions</literal> soit créer une 16.366 +section <literal role="rc-extensions">extensions</literal>. Ensuite ajoutez une ligne qui consiste 16.367 +simplement en <quote>\Verb+fetch =</quote>. 16.368 +</para> 16.369 + 16.370 +<programlisting> 16.371 +<para> [extensions] 16.372 + fetch = 16.373 +</para> 16.374 +</programlisting> 16.375 +<para>(Normalement, sur la partie droite de <quote><literal>=</literal></quote> devrait apparaître 16.376 +le chemin de l'extension, mais étant donné que l'extension <literal role="hg-ext">fetch</literal> 16.377 +fait partie de la distribution standard, Mercurial sait où la trouver.) 16.378 +</para> 16.379 + 16.380 +</sect1> 16.381 +</chapter> 16.382 + 16.383 +<!-- 16.384 +local variables: 16.385 +sgml-parent-document: ("00book.xml" "book" "chapter") 16.386 +end: 16.387 +--> 16.388 \ No newline at end of file
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 17.2 +++ b/fr/ch04-concepts.xml Sun Aug 16 04:58:01 2009 +0200 17.3 @@ -0,0 +1,710 @@ 17.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 17.5 + 17.6 +<chapter> 17.7 +<title>Behind the scenes</title> 17.8 +<para>\label{chap:concepts}</para> 17.9 + 17.10 +<para>Unlike many revision control systems, the concepts upon which 17.11 +Mercurial is built are simple enough that it's easy to understand how 17.12 +the software really works. Knowing this certainly isn't necessary, 17.13 +but I find it useful to have a <quote>mental model</quote> of what's going on.</para> 17.14 + 17.15 +<para>This understanding gives me confidence that Mercurial has been 17.16 +carefully designed to be both <emphasis>safe</emphasis> and <emphasis>efficient</emphasis>. And 17.17 +just as importantly, if it's easy for me to retain a good idea of what 17.18 +the software is doing when I perform a revision control task, I'm less 17.19 +likely to be surprised by its behaviour.</para> 17.20 + 17.21 +<para>In this chapter, we'll initially cover the core concepts behind 17.22 +Mercurial's design, then continue to discuss some of the interesting 17.23 +details of its implementation.</para> 17.24 + 17.25 +<sect1> 17.26 +<title>Mercurial's historical record</title> 17.27 + 17.28 +<sect2> 17.29 +<title>Tracking the history of a single file</title> 17.30 + 17.31 +<para>When Mercurial tracks modifications to a file, it stores the history 17.32 +of that file in a metadata object called a <emphasis>filelog</emphasis>. Each entry 17.33 +in the filelog contains enough information to reconstruct one revision 17.34 +of the file that is being tracked. Filelogs are stored as files in 17.35 +the <filename role="special" class="directory">.hg/store/data</filename> directory. A filelog contains two kinds 17.36 +of information: revision data, and an index to help Mercurial to find 17.37 +a revision efficiently.</para> 17.38 + 17.39 +<para>A file that is large, or has a lot of history, has its filelog stored 17.40 +in separate data (<quote><literal>.d</literal></quote> suffix) and index (<quote><literal>.i</literal></quote> 17.41 +suffix) files. For small files without much history, the revision 17.42 +data and index are combined in a single <quote><literal>.i</literal></quote> file. The 17.43 +correspondence between a file in the working directory and the filelog 17.44 +that tracks its history in the repository is illustrated in 17.45 +figure <xref linkend="fig:concepts:filelog"/>.</para> 17.46 + 17.47 +<informalfigure> 17.48 + 17.49 +<para> <mediaobject><imageobject><imagedata fileref="filelog"/></imageobject><textobject><phrase>XXX add text</phrase></textobject></mediaobject> 17.50 + \caption{Relationships between files in working directory and 17.51 + filelogs in repository} 17.52 + \label{fig:concepts:filelog}</para> 17.53 +</informalfigure> 17.54 + 17.55 +</sect2> 17.56 +<sect2> 17.57 +<title>Managing tracked files</title> 17.58 + 17.59 +<para>Mercurial uses a structure called a <emphasis>manifest</emphasis> to collect 17.60 +together information about the files that it tracks. Each entry in 17.61 +the manifest contains information about the files present in a single 17.62 +changeset. An entry records which files are present in the changeset, 17.63 +the revision of each file, and a few other pieces of file metadata.</para> 17.64 + 17.65 +</sect2> 17.66 +<sect2> 17.67 +<title>Recording changeset information</title> 17.68 + 17.69 +<para>The <emphasis>changelog</emphasis> contains information about each changeset. Each 17.70 +revision records who committed a change, the changeset comment, other 17.71 +pieces of changeset-related information, and the revision of the 17.72 +manifest to use. 17.73 +</para> 17.74 + 17.75 +</sect2> 17.76 +<sect2> 17.77 +<title>Relationships between revisions</title> 17.78 + 17.79 +<para>Within a changelog, a manifest, or a filelog, each revision stores a 17.80 +pointer to its immediate parent (or to its two parents, if it's a 17.81 +merge revision). As I mentioned above, there are also relationships 17.82 +between revisions <emphasis>across</emphasis> these structures, and they are 17.83 +hierarchical in nature. 17.84 +</para> 17.85 + 17.86 +<para>For every changeset in a repository, there is exactly one revision 17.87 +stored in the changelog. Each revision of the changelog contains a 17.88 +pointer to a single revision of the manifest. A revision of the 17.89 +manifest stores a pointer to a single revision of each filelog tracked 17.90 +when that changeset was created. These relationships are illustrated 17.91 +in figure <xref linkend="fig:concepts:metadata"/>. 17.92 +</para> 17.93 + 17.94 +<informalfigure> 17.95 + 17.96 +<para> <mediaobject><imageobject><imagedata fileref="metadata"/></imageobject><textobject><phrase>XXX add text</phrase></textobject></mediaobject> 17.97 + <caption><para>Metadata relationships</para></caption> 17.98 + \label{fig:concepts:metadata} 17.99 +</para> 17.100 +</informalfigure> 17.101 + 17.102 +<para>As the illustration shows, there is <emphasis>not</emphasis> a <quote>one to one</quote> 17.103 +relationship between revisions in the changelog, manifest, or filelog. 17.104 +If the manifest hasn't changed between two changesets, the changelog 17.105 +entries for those changesets will point to the same revision of the 17.106 +manifest. If a file that Mercurial tracks hasn't changed between two 17.107 +changesets, the entry for that file in the two revisions of the 17.108 +manifest will point to the same revision of its filelog. 17.109 +</para> 17.110 + 17.111 +</sect2> 17.112 +</sect1> 17.113 +<sect1> 17.114 +<title>Safe, efficient storage</title> 17.115 + 17.116 +<para>The underpinnings of changelogs, manifests, and filelogs are provided 17.117 +by a single structure called the <emphasis>revlog</emphasis>. 17.118 +</para> 17.119 + 17.120 +<sect2> 17.121 +<title>Efficient storage</title> 17.122 + 17.123 +<para>The revlog provides efficient storage of revisions using a 17.124 +<emphasis>delta</emphasis> mechanism. Instead of storing a complete copy of a file 17.125 +for each revision, it stores the changes needed to transform an older 17.126 +revision into the new revision. For many kinds of file data, these 17.127 +deltas are typically a fraction of a percent of the size of a full 17.128 +copy of a file. 17.129 +</para> 17.130 + 17.131 +<para>Some obsolete revision control systems can only work with deltas of 17.132 +text files. They must either store binary files as complete snapshots 17.133 +or encoded into a text representation, both of which are wasteful 17.134 +approaches. Mercurial can efficiently handle deltas of files with 17.135 +arbitrary binary contents; it doesn't need to treat text as special. 17.136 +</para> 17.137 + 17.138 +</sect2> 17.139 +<sect2> 17.140 +<title>Safe operation</title> 17.141 +<para>\label{sec:concepts:txn} 17.142 +</para> 17.143 + 17.144 +<para>Mercurial only ever <emphasis>appends</emphasis> data to the end of a revlog file. 17.145 +It never modifies a section of a file after it has written it. This 17.146 +is both more robust and efficient than schemes that need to modify or 17.147 +rewrite data. 17.148 +</para> 17.149 + 17.150 +<para>In addition, Mercurial treats every write as part of a 17.151 +<emphasis>transaction</emphasis> that can span a number of files. A transaction is 17.152 +<emphasis>atomic</emphasis>: either the entire transaction succeeds and its effects 17.153 +are all visible to readers in one go, or the whole thing is undone. 17.154 +This guarantee of atomicity means that if you're running two copies of 17.155 +Mercurial, where one is reading data and one is writing it, the reader 17.156 +will never see a partially written result that might confuse it. 17.157 +</para> 17.158 + 17.159 +<para>The fact that Mercurial only appends to files makes it easier to 17.160 +provide this transactional guarantee. The easier it is to do stuff 17.161 +like this, the more confident you should be that it's done correctly. 17.162 +</para> 17.163 + 17.164 +</sect2> 17.165 +<sect2> 17.166 +<title>Fast retrieval</title> 17.167 + 17.168 +<para>Mercurial cleverly avoids a pitfall common to all earlier 17.169 +revision control systems: the problem of <emphasis>inefficient retrieval</emphasis>. 17.170 +Most revision control systems store the contents of a revision as an 17.171 +incremental series of modifications against a <quote>snapshot</quote>. To 17.172 +reconstruct a specific revision, you must first read the snapshot, and 17.173 +then every one of the revisions between the snapshot and your target 17.174 +revision. The more history that a file accumulates, the more 17.175 +revisions you must read, hence the longer it takes to reconstruct a 17.176 +particular revision. 17.177 +</para> 17.178 + 17.179 +<informalfigure> 17.180 + 17.181 +<para> <mediaobject><imageobject><imagedata fileref="snapshot"/></imageobject><textobject><phrase>XXX add text</phrase></textobject></mediaobject> 17.182 + <caption><para>Snapshot of a revlog, with incremental deltas</para></caption> 17.183 + \label{fig:concepts:snapshot} 17.184 +</para> 17.185 +</informalfigure> 17.186 + 17.187 +<para>The innovation that Mercurial applies to this problem is simple but 17.188 +effective. Once the cumulative amount of delta information stored 17.189 +since the last snapshot exceeds a fixed threshold, it stores a new 17.190 +snapshot (compressed, of course), instead of another delta. This 17.191 +makes it possible to reconstruct <emphasis>any</emphasis> revision of a file 17.192 +quickly. This approach works so well that it has since been copied by 17.193 +several other revision control systems. 17.194 +</para> 17.195 + 17.196 +<para>Figure <xref linkend="fig:concepts:snapshot"/> illustrates the idea. In an entry 17.197 +in a revlog's index file, Mercurial stores the range of entries from 17.198 +the data file that it must read to reconstruct a particular revision. 17.199 +</para> 17.200 + 17.201 +<sect3> 17.202 +<title>Aside: the influence of video compression</title> 17.203 + 17.204 +<para>If you're familiar with video compression or have ever watched a TV 17.205 +feed through a digital cable or satellite service, you may know that 17.206 +most video compression schemes store each frame of video as a delta 17.207 +against its predecessor frame. In addition, these schemes use 17.208 +<quote>lossy</quote> compression techniques to increase the compression ratio, so 17.209 +visual errors accumulate over the course of a number of inter-frame 17.210 +deltas. 17.211 +</para> 17.212 + 17.213 +<para>Because it's possible for a video stream to <quote>drop out</quote> occasionally 17.214 +due to signal glitches, and to limit the accumulation of artefacts 17.215 +introduced by the lossy compression process, video encoders 17.216 +periodically insert a complete frame (called a <quote>key frame</quote>) into the 17.217 +video stream; the next delta is generated against that frame. This 17.218 +means that if the video signal gets interrupted, it will resume once 17.219 +the next key frame is received. Also, the accumulation of encoding 17.220 +errors restarts anew with each key frame. 17.221 +</para> 17.222 + 17.223 +</sect3> 17.224 +</sect2> 17.225 +<sect2> 17.226 +<title>Identification and strong integrity</title> 17.227 + 17.228 +<para>Along with delta or snapshot information, a revlog entry contains a 17.229 +cryptographic hash of the data that it represents. This makes it 17.230 +difficult to forge the contents of a revision, and easy to detect 17.231 +accidental corruption. 17.232 +</para> 17.233 + 17.234 +<para>Hashes provide more than a mere check against corruption; they are 17.235 +used as the identifiers for revisions. The changeset identification 17.236 +hashes that you see as an end user are from revisions of the 17.237 +changelog. Although filelogs and the manifest also use hashes, 17.238 +Mercurial only uses these behind the scenes. 17.239 +</para> 17.240 + 17.241 +<para>Mercurial verifies that hashes are correct when it retrieves file 17.242 +revisions and when it pulls changes from another repository. If it 17.243 +encounters an integrity problem, it will complain and stop whatever 17.244 +it's doing. 17.245 +</para> 17.246 + 17.247 +<para>In addition to the effect it has on retrieval efficiency, Mercurial's 17.248 +use of periodic snapshots makes it more robust against partial data 17.249 +corruption. If a revlog becomes partly corrupted due to a hardware 17.250 +error or system bug, it's often possible to reconstruct some or most 17.251 +revisions from the uncorrupted sections of the revlog, both before and 17.252 +after the corrupted section. This would not be possible with a 17.253 +delta-only storage model. 17.254 +</para> 17.255 + 17.256 +<para>\section{Revision history, branching, 17.257 + and merging} 17.258 +</para> 17.259 + 17.260 +<para>Every entry in a Mercurial revlog knows the identity of its immediate 17.261 +ancestor revision, usually referred to as its <emphasis>parent</emphasis>. In fact, 17.262 +a revision contains room for not one parent, but two. Mercurial uses 17.263 +a special hash, called the <quote>null ID</quote>, to represent the idea <quote>there 17.264 +is no parent here</quote>. This hash is simply a string of zeroes. 17.265 +</para> 17.266 + 17.267 +<para>In figure <xref linkend="fig:concepts:revlog"/>, you can see an example of the 17.268 +conceptual structure of a revlog. Filelogs, manifests, and changelogs 17.269 +all have this same structure; they differ only in the kind of data 17.270 +stored in each delta or snapshot. 17.271 +</para> 17.272 + 17.273 +<para>The first revision in a revlog (at the bottom of the image) has the 17.274 +null ID in both of its parent slots. For a <quote>normal</quote> revision, its 17.275 +first parent slot contains the ID of its parent revision, and its 17.276 +second contains the null ID, indicating that the revision has only one 17.277 +real parent. Any two revisions that have the same parent ID are 17.278 +branches. A revision that represents a merge between branches has two 17.279 +normal revision IDs in its parent slots. 17.280 +</para> 17.281 + 17.282 +<informalfigure> 17.283 + 17.284 +<para> <mediaobject><imageobject><imagedata fileref="revlog"/></imageobject><textobject><phrase>XXX add text</phrase></textobject></mediaobject> 17.285 + \caption{} 17.286 + \label{fig:concepts:revlog} 17.287 +</para> 17.288 +</informalfigure> 17.289 + 17.290 +</sect2> 17.291 +</sect1> 17.292 +<sect1> 17.293 +<title>The working directory</title> 17.294 + 17.295 +<para>In the working directory, Mercurial stores a snapshot of the files 17.296 +from the repository as of a particular changeset. 17.297 +</para> 17.298 + 17.299 +<para>The working directory <quote>knows</quote> which changeset it contains. When you 17.300 +update the working directory to contain a particular changeset, 17.301 +Mercurial looks up the appropriate revision of the manifest to find 17.302 +out which files it was tracking at the time that changeset was 17.303 +committed, and which revision of each file was then current. It then 17.304 +recreates a copy of each of those files, with the same contents it had 17.305 +when the changeset was committed. 17.306 +</para> 17.307 + 17.308 +<para>The <emphasis>dirstate</emphasis> contains Mercurial's knowledge of the working 17.309 +directory. This details which changeset the working directory is 17.310 +updated to, and all of the files that Mercurial is tracking in the 17.311 +working directory. 17.312 +</para> 17.313 + 17.314 +<para>Just as a revision of a revlog has room for two parents, so that it 17.315 +can represent either a normal revision (with one parent) or a merge of 17.316 +two earlier revisions, the dirstate has slots for two parents. When 17.317 +you use the <command role="hg-cmd">hg update</command> command, the changeset that you update to 17.318 +is stored in the <quote>first parent</quote> slot, and the null ID in the second. 17.319 +When you <command role="hg-cmd">hg merge</command> with another changeset, the first parent 17.320 +remains unchanged, and the second parent is filled in with the 17.321 +changeset you're merging with. The <command role="hg-cmd">hg parents</command> command tells you 17.322 +what the parents of the dirstate are. 17.323 +</para> 17.324 + 17.325 +<sect2> 17.326 +<title>What happens when you commit</title> 17.327 + 17.328 +<para>The dirstate stores parent information for more than just book-keeping 17.329 +purposes. Mercurial uses the parents of the dirstate as \emph{the 17.330 + parents of a new changeset} when you perform a commit. 17.331 +</para> 17.332 + 17.333 +<informalfigure> 17.334 + 17.335 +<para> <mediaobject><imageobject><imagedata fileref="wdir"/></imageobject><textobject><phrase>XXX add text</phrase></textobject></mediaobject> 17.336 + <caption><para>The working directory can have two parents</para></caption> 17.337 + \label{fig:concepts:wdir} 17.338 +</para> 17.339 +</informalfigure> 17.340 + 17.341 +<para>Figure <xref linkend="fig:concepts:wdir"/> shows the normal state of the working 17.342 +directory, where it has a single changeset as parent. That changeset 17.343 +is the <emphasis>tip</emphasis>, the newest changeset in the repository that has no 17.344 +children. 17.345 +</para> 17.346 + 17.347 +<informalfigure> 17.348 + 17.349 +<para> <mediaobject><imageobject><imagedata fileref="wdir-after-commit"/></imageobject><textobject><phrase>XXX add text</phrase></textobject></mediaobject> 17.350 + <caption><para>The working directory gains new parents after a commit</para></caption> 17.351 + \label{fig:concepts:wdir-after-commit} 17.352 +</para> 17.353 +</informalfigure> 17.354 + 17.355 +<para>It's useful to think of the working directory as <quote>the changeset I'm 17.356 +about to commit</quote>. Any files that you tell Mercurial that you've 17.357 +added, removed, renamed, or copied will be reflected in that 17.358 +changeset, as will modifications to any files that Mercurial is 17.359 +already tracking; the new changeset will have the parents of the 17.360 +working directory as its parents. 17.361 +</para> 17.362 + 17.363 +<para>After a commit, Mercurial will update the parents of the working 17.364 +directory, so that the first parent is the ID of the new changeset, 17.365 +and the second is the null ID. This is shown in 17.366 +figure <xref linkend="fig:concepts:wdir-after-commit"/>. Mercurial doesn't touch 17.367 +any of the files in the working directory when you commit; it just 17.368 +modifies the dirstate to note its new parents. 17.369 +</para> 17.370 + 17.371 +</sect2> 17.372 +<sect2> 17.373 +<title>Creating a new head</title> 17.374 + 17.375 +<para>It's perfectly normal to update the working directory to a changeset 17.376 +other than the current tip. For example, you might want to know what 17.377 +your project looked like last Tuesday, or you could be looking through 17.378 +changesets to see which one introduced a bug. In cases like this, the 17.379 +natural thing to do is update the working directory to the changeset 17.380 +you're interested in, and then examine the files in the working 17.381 +directory directly to see their contents as they were when you 17.382 +committed that changeset. The effect of this is shown in 17.383 +figure <xref linkend="fig:concepts:wdir-pre-branch"/>. 17.384 +</para> 17.385 + 17.386 +<informalfigure> 17.387 + 17.388 +<para> <mediaobject><imageobject><imagedata fileref="wdir-pre-branch"/></imageobject><textobject><phrase>XXX add text</phrase></textobject></mediaobject> 17.389 + <caption><para>The working directory, updated to an older changeset</para></caption> 17.390 + \label{fig:concepts:wdir-pre-branch} 17.391 +</para> 17.392 +</informalfigure> 17.393 + 17.394 +<para>Having updated the working directory to an older changeset, what 17.395 +happens if you make some changes, and then commit? Mercurial behaves 17.396 +in the same way as I outlined above. The parents of the working 17.397 +directory become the parents of the new changeset. This new changeset 17.398 +has no children, so it becomes the new tip. And the repository now 17.399 +contains two changesets that have no children; we call these 17.400 +<emphasis>heads</emphasis>. You can see the structure that this creates in 17.401 +figure <xref linkend="fig:concepts:wdir-branch"/>. 17.402 +</para> 17.403 + 17.404 +<informalfigure> 17.405 + 17.406 +<para> <mediaobject><imageobject><imagedata fileref="wdir-branch"/></imageobject><textobject><phrase>XXX add text</phrase></textobject></mediaobject> 17.407 + <caption><para>After a commit made while synced to an older changeset</para></caption> 17.408 + \label{fig:concepts:wdir-branch} 17.409 +</para> 17.410 +</informalfigure> 17.411 + 17.412 +<note> 17.413 +<para> If you're new to Mercurial, you should keep in mind a common 17.414 + <quote>error</quote>, which is to use the <command role="hg-cmd">hg pull</command> command without any 17.415 + options. By default, the <command role="hg-cmd">hg pull</command> command <emphasis>does not</emphasis> 17.416 + update the working directory, so you'll bring new changesets into 17.417 + your repository, but the working directory will stay synced at the 17.418 + same changeset as before the pull. If you make some changes and 17.419 + commit afterwards, you'll thus create a new head, because your 17.420 + working directory isn't synced to whatever the current tip is. 17.421 +</para> 17.422 + 17.423 +<para> I put the word <quote>error</quote> in quotes because all that you need to do 17.424 + to rectify this situation is <command role="hg-cmd">hg merge</command>, then <command role="hg-cmd">hg commit</command>. In 17.425 + other words, this almost never has negative consequences; it just 17.426 + surprises people. I'll discuss other ways to avoid this behaviour, 17.427 + and why Mercurial behaves in this initially surprising way, later 17.428 + on. 17.429 +</para> 17.430 +</note> 17.431 + 17.432 +</sect2> 17.433 +<sect2> 17.434 +<title>Merging heads</title> 17.435 + 17.436 +<para>When you run the <command role="hg-cmd">hg merge</command> command, Mercurial leaves the first 17.437 +parent of the working directory unchanged, and sets the second parent 17.438 +to the changeset you're merging with, as shown in 17.439 +figure <xref linkend="fig:concepts:wdir-merge"/>. 17.440 +</para> 17.441 + 17.442 +<informalfigure> 17.443 + 17.444 +<para> <mediaobject><imageobject><imagedata fileref="wdir-merge"/></imageobject><textobject><phrase>XXX add text</phrase></textobject></mediaobject> 17.445 + <caption><para>Merging two heads</para></caption> 17.446 + \label{fig:concepts:wdir-merge} 17.447 +</para> 17.448 +</informalfigure> 17.449 + 17.450 +<para>Mercurial also has to modify the working directory, to merge the files 17.451 +managed in the two changesets. Simplified a little, the merging 17.452 +process goes like this, for every file in the manifests of both 17.453 +changesets. 17.454 +</para> 17.455 +<itemizedlist> 17.456 +<listitem><para>If neither changeset has modified a file, do nothing with that 17.457 + file. 17.458 +</para> 17.459 +</listitem> 17.460 +<listitem><para>If one changeset has modified a file, and the other hasn't, 17.461 + create the modified copy of the file in the working directory. 17.462 +</para> 17.463 +</listitem> 17.464 +<listitem><para>If one changeset has removed a file, and the other hasn't (or 17.465 + has also deleted it), delete the file from the working directory. 17.466 +</para> 17.467 +</listitem> 17.468 +<listitem><para>If one changeset has removed a file, but the other has modified 17.469 + the file, ask the user what to do: keep the modified file, or remove 17.470 + it? 17.471 +</para> 17.472 +</listitem> 17.473 +<listitem><para>If both changesets have modified a file, invoke an external 17.474 + merge program to choose the new contents for the merged file. This 17.475 + may require input from the user. 17.476 +</para> 17.477 +</listitem> 17.478 +<listitem><para>If one changeset has modified a file, and the other has renamed 17.479 + or copied the file, make sure that the changes follow the new name 17.480 + of the file. 17.481 +</para> 17.482 +</listitem></itemizedlist> 17.483 +<para>There are more details&emdash;merging has plenty of corner cases&emdash;but 17.484 +these are the most common choices that are involved in a merge. As 17.485 +you can see, most cases are completely automatic, and indeed most 17.486 +merges finish automatically, without requiring your input to resolve 17.487 +any conflicts. 17.488 +</para> 17.489 + 17.490 +<para>When you're thinking about what happens when you commit after a merge, 17.491 +once again the working directory is <quote>the changeset I'm about to 17.492 +commit</quote>. After the <command role="hg-cmd">hg merge</command> command completes, the working 17.493 +directory has two parents; these will become the parents of the new 17.494 +changeset. 17.495 +</para> 17.496 + 17.497 +<para>Mercurial lets you perform multiple merges, but you must commit the 17.498 +results of each individual merge as you go. This is necessary because 17.499 +Mercurial only tracks two parents for both revisions and the working 17.500 +directory. While it would be technically possible to merge multiple 17.501 +changesets at once, the prospect of user confusion and making a 17.502 +terrible mess of a merge immediately becomes overwhelming. 17.503 +</para> 17.504 + 17.505 +</sect2> 17.506 +</sect1> 17.507 +<sect1> 17.508 +<title>Other interesting design features</title> 17.509 + 17.510 +<para>In the sections above, I've tried to highlight some of the most 17.511 +important aspects of Mercurial's design, to illustrate that it pays 17.512 +careful attention to reliability and performance. However, the 17.513 +attention to detail doesn't stop there. There are a number of other 17.514 +aspects of Mercurial's construction that I personally find 17.515 +interesting. I'll detail a few of them here, separate from the <quote>big 17.516 +ticket</quote> items above, so that if you're interested, you can gain a 17.517 +better idea of the amount of thinking that goes into a well-designed 17.518 +system. 17.519 +</para> 17.520 + 17.521 +<sect2> 17.522 +<title>Clever compression</title> 17.523 + 17.524 +<para>When appropriate, Mercurial will store both snapshots and deltas in 17.525 +compressed form. It does this by always <emphasis>trying to</emphasis> compress a 17.526 +snapshot or delta, but only storing the compressed version if it's 17.527 +smaller than the uncompressed version. 17.528 +</para> 17.529 + 17.530 +<para>This means that Mercurial does <quote>the right thing</quote> when storing a file 17.531 +whose native form is compressed, such as a <literal>zip</literal> archive or a 17.532 +JPEG image. When these types of files are compressed a second time, 17.533 +the resulting file is usually bigger than the once-compressed form, 17.534 +and so Mercurial will store the plain <literal>zip</literal> or JPEG. 17.535 +</para> 17.536 + 17.537 +<para>Deltas between revisions of a compressed file are usually larger than 17.538 +snapshots of the file, and Mercurial again does <quote>the right thing</quote> in 17.539 +these cases. It finds that such a delta exceeds the threshold at 17.540 +which it should store a complete snapshot of the file, so it stores 17.541 +the snapshot, again saving space compared to a naive delta-only 17.542 +approach. 17.543 +</para> 17.544 + 17.545 +<sect3> 17.546 +<title>Network recompression</title> 17.547 + 17.548 +<para>When storing revisions on disk, Mercurial uses the <quote>deflate</quote> 17.549 +compression algorithm (the same one used by the popular <literal>zip</literal> 17.550 +archive format), which balances good speed with a respectable 17.551 +compression ratio. However, when transmitting revision data over a 17.552 +network connection, Mercurial uncompresses the compressed revision 17.553 +data. 17.554 +</para> 17.555 + 17.556 +<para>If the connection is over HTTP, Mercurial recompresses the entire 17.557 +stream of data using a compression algorithm that gives a better 17.558 +compression ratio (the Burrows-Wheeler algorithm from the widely used 17.559 +<literal>bzip2</literal> compression package). This combination of algorithm 17.560 +and compression of the entire stream (instead of a revision at a time) 17.561 +substantially reduces the number of bytes to be transferred, yielding 17.562 +better network performance over almost all kinds of network. 17.563 +</para> 17.564 + 17.565 +<para>(If the connection is over <command>ssh</command>, Mercurial <emphasis>doesn't</emphasis> 17.566 +recompress the stream, because <command>ssh</command> can already do this 17.567 +itself.) 17.568 +</para> 17.569 + 17.570 +</sect3> 17.571 +</sect2> 17.572 +<sect2> 17.573 +<title>Read/write ordering and atomicity</title> 17.574 + 17.575 +<para>Appending to files isn't the whole story when it comes to guaranteeing 17.576 +that a reader won't see a partial write. If you recall 17.577 +figure <xref linkend="fig:concepts:metadata"/>, revisions in the changelog point to 17.578 +revisions in the manifest, and revisions in the manifest point to 17.579 +revisions in filelogs. This hierarchy is deliberate. 17.580 +</para> 17.581 + 17.582 +<para>A writer starts a transaction by writing filelog and manifest data, 17.583 +and doesn't write any changelog data until those are finished. A 17.584 +reader starts by reading changelog data, then manifest data, followed 17.585 +by filelog data. 17.586 +</para> 17.587 + 17.588 +<para>Since the writer has always finished writing filelog and manifest data 17.589 +before it writes to the changelog, a reader will never read a pointer 17.590 +to a partially written manifest revision from the changelog, and it will 17.591 +never read a pointer to a partially written filelog revision from the 17.592 +manifest. 17.593 +</para> 17.594 + 17.595 +</sect2> 17.596 +<sect2> 17.597 +<title>Concurrent access</title> 17.598 + 17.599 +<para>The read/write ordering and atomicity guarantees mean that Mercurial 17.600 +never needs to <emphasis>lock</emphasis> a repository when it's reading data, even 17.601 +if the repository is being written to while the read is occurring. 17.602 +This has a big effect on scalability; you can have an arbitrary number 17.603 +of Mercurial processes safely reading data from a repository safely 17.604 +all at once, no matter whether it's being written to or not. 17.605 +</para> 17.606 + 17.607 +<para>The lockless nature of reading means that if you're sharing a 17.608 +repository on a multi-user system, you don't need to grant other local 17.609 +users permission to <emphasis>write</emphasis> to your repository in order for them 17.610 +to be able to clone it or pull changes from it; they only need 17.611 +<emphasis>read</emphasis> permission. (This is <emphasis>not</emphasis> a common feature among 17.612 +revision control systems, so don't take it for granted! Most require 17.613 +readers to be able to lock a repository to access it safely, and this 17.614 +requires write permission on at least one directory, which of course 17.615 +makes for all kinds of nasty and annoying security and administrative 17.616 +problems.) 17.617 +</para> 17.618 + 17.619 +<para>Mercurial uses locks to ensure that only one process can write to a 17.620 +repository at a time (the locking mechanism is safe even over 17.621 +filesystems that are notoriously hostile to locking, such as NFS). If 17.622 +a repository is locked, a writer will wait for a while to retry if the 17.623 +repository becomes unlocked, but if the repository remains locked for 17.624 +too long, the process attempting to write will time out after a while. 17.625 +This means that your daily automated scripts won't get stuck forever 17.626 +and pile up if a system crashes unnoticed, for example. (Yes, the 17.627 +timeout is configurable, from zero to infinity.) 17.628 +</para> 17.629 + 17.630 +<sect3> 17.631 +<title>Safe dirstate access</title> 17.632 + 17.633 +<para>As with revision data, Mercurial doesn't take a lock to read the 17.634 +dirstate file; it does acquire a lock to write it. To avoid the 17.635 +possibility of reading a partially written copy of the dirstate file, 17.636 +Mercurial writes to a file with a unique name in the same directory as 17.637 +the dirstate file, then renames the temporary file atomically to 17.638 +<filename>dirstate</filename>. The file named <filename>dirstate</filename> is thus 17.639 +guaranteed to be complete, not partially written. 17.640 +</para> 17.641 + 17.642 +</sect3> 17.643 +</sect2> 17.644 +<sect2> 17.645 +<title>Avoiding seeks</title> 17.646 + 17.647 +<para>Critical to Mercurial's performance is the avoidance of seeks of the 17.648 +disk head, since any seek is far more expensive than even a 17.649 +comparatively large read operation. 17.650 +</para> 17.651 + 17.652 +<para>This is why, for example, the dirstate is stored in a single file. If 17.653 +there were a dirstate file per directory that Mercurial tracked, the 17.654 +disk would seek once per directory. Instead, Mercurial reads the 17.655 +entire single dirstate file in one step. 17.656 +</para> 17.657 + 17.658 +<para>Mercurial also uses a <quote>copy on write</quote> scheme when cloning a 17.659 +repository on local storage. Instead of copying every revlog file 17.660 +from the old repository into the new repository, it makes a <quote>hard 17.661 +link</quote>, which is a shorthand way to say <quote>these two names point to the 17.662 +same file</quote>. When Mercurial is about to write to one of a revlog's 17.663 +files, it checks to see if the number of names pointing at the file is 17.664 +greater than one. If it is, more than one repository is using the 17.665 +file, so Mercurial makes a new copy of the file that is private to 17.666 +this repository. 17.667 +</para> 17.668 + 17.669 +<para>A few revision control developers have pointed out that this idea of 17.670 +making a complete private copy of a file is not very efficient in its 17.671 +use of storage. While this is true, storage is cheap, and this method 17.672 +gives the highest performance while deferring most book-keeping to the 17.673 +operating system. An alternative scheme would most likely reduce 17.674 +performance and increase the complexity of the software, each of which 17.675 +is much more important to the <quote>feel</quote> of day-to-day use. 17.676 +</para> 17.677 + 17.678 +</sect2> 17.679 +<sect2> 17.680 +<title>Other contents of the dirstate</title> 17.681 + 17.682 +<para>Because Mercurial doesn't force you to tell it when you're modifying a 17.683 +file, it uses the dirstate to store some extra information so it can 17.684 +determine efficiently whether you have modified a file. For each file 17.685 +in the working directory, it stores the time that it last modified the 17.686 +file itself, and the size of the file at that time. 17.687 +</para> 17.688 + 17.689 +<para>When you explicitly <command role="hg-cmd">hg add</command>, <command role="hg-cmd">hg remove</command>, <command role="hg-cmd">hg rename</command> or 17.690 +<command role="hg-cmd">hg copy</command> files, Mercurial updates the dirstate so that it knows 17.691 +what to do with those files when you commit. 17.692 +</para> 17.693 + 17.694 +<para>When Mercurial is checking the states of files in the working 17.695 +directory, it first checks a file's modification time. If that has 17.696 +not changed, the file must not have been modified. If the file's size 17.697 +has changed, the file must have been modified. If the modification 17.698 +time has changed, but the size has not, only then does Mercurial need 17.699 +to read the actual contents of the file to see if they've changed. 17.700 +Storing these few extra pieces of information dramatically reduces the 17.701 +amount of data that Mercurial needs to read, which yields large 17.702 +performance improvements compared to other revision control systems. 17.703 +</para> 17.704 + 17.705 +</sect2> 17.706 +</sect1> 17.707 +</chapter> 17.708 + 17.709 +<!-- 17.710 +local variables: 17.711 +sgml-parent-document: ("00book.xml" "book" "chapter") 17.712 +end: 17.713 +--> 17.714 \ No newline at end of file
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 18.2 +++ b/fr/ch05-daily.xml Sun Aug 16 04:58:01 2009 +0200 18.3 @@ -0,0 +1,474 @@ 18.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 18.5 + 18.6 +<chapter> 18.7 +<title>Mercurial in daily use</title> 18.8 +<para>\label{chap:daily}</para> 18.9 + 18.10 +<sect1> 18.11 +<title>Telling Mercurial which files to track</title> 18.12 + 18.13 +<para>Mercurial does not work with files in your repository unless you tell 18.14 +it to manage them. The <command role="hg-cmd">hg status</command> command will tell you which 18.15 +files Mercurial doesn't know about; it uses a <quote><literal>?</literal></quote> to 18.16 +display such files.</para> 18.17 + 18.18 +<para>To tell Mercurial to track a file, use the <command role="hg-cmd">hg add</command> command. Once 18.19 +you have added a file, the entry in the output of <command role="hg-cmd">hg status</command> for 18.20 +that file changes from <quote><literal>?</literal></quote> to <quote><literal>A</literal></quote>. 18.21 +<!-- &interaction.daily.files.add; --></para> 18.22 + 18.23 +<para>After you run a <command role="hg-cmd">hg commit</command>, the files that you added before the 18.24 +commit will no longer be listed in the output of <command role="hg-cmd">hg status</command>. The 18.25 +reason for this is that <command role="hg-cmd">hg status</command> only tells you about 18.26 +<quote>interesting</quote> files&emdash;those that you have modified or told Mercurial 18.27 +to do something with&emdash;by default. If you have a repository that 18.28 +contains thousands of files, you will rarely want to know about files 18.29 +that Mercurial is tracking, but that have not changed. (You can still 18.30 +get this information; we'll return to this later.)</para> 18.31 + 18.32 +<para>Once you add a file, Mercurial doesn't do anything with it 18.33 +immediately. Instead, it will take a snapshot of the file's state the 18.34 +next time you perform a commit. It will then continue to track the 18.35 +changes you make to the file every time you commit, until you remove 18.36 +the file.</para> 18.37 + 18.38 +<sect2> 18.39 +<title>Explicit versus implicit file naming</title> 18.40 + 18.41 +<para>A useful behaviour that Mercurial has is that if you pass the name of 18.42 +a directory to a command, every Mercurial command will treat this as 18.43 +<quote>I want to operate on every file in this directory and its 18.44 +subdirectories</quote>. 18.45 +<!-- &interaction.daily.files.add-dir; --> 18.46 +Notice in this example that Mercurial printed the names of the files 18.47 +it added, whereas it didn't do so when we added the file named 18.48 +<filename>a</filename> in the earlier example.</para> 18.49 + 18.50 +<para>What's going on is that in the former case, we explicitly named the 18.51 +file to add on the command line, so the assumption that Mercurial 18.52 +makes in such cases is that you know what you were doing, and it 18.53 +doesn't print any output.</para> 18.54 + 18.55 +<para>However, when we <emphasis>imply</emphasis> the names of files by giving the name of 18.56 +a directory, Mercurial takes the extra step of printing the name of 18.57 +each file that it does something with. This makes it more clear what 18.58 +is happening, and reduces the likelihood of a silent and nasty 18.59 +surprise. This behaviour is common to most Mercurial commands.</para> 18.60 + 18.61 +</sect2> 18.62 +<sect2> 18.63 +<title>Aside: Mercurial tracks files, not directories</title> 18.64 + 18.65 +<para>Mercurial does not track directory information. Instead, it tracks 18.66 +the path to a file. Before creating a file, it first creates any 18.67 +missing directory components of the path. After it deletes a file, it 18.68 +then deletes any empty directories that were in the deleted file's 18.69 +path. This sounds like a trivial distinction, but it has one minor 18.70 +practical consequence: it is not possible to represent a completely 18.71 +empty directory in Mercurial. 18.72 +</para> 18.73 + 18.74 +<para>Empty directories are rarely useful, and there are unintrusive 18.75 +workarounds that you can use to achieve an appropriate effect. The 18.76 +developers of Mercurial thus felt that the complexity that would be 18.77 +required to manage empty directories was not worth the limited benefit 18.78 +this feature would bring. 18.79 +</para> 18.80 + 18.81 +<para>If you need an empty directory in your repository, there are a few 18.82 +ways to achieve this. One is to create a directory, then <command role="hg-cmd">hg add</command> a 18.83 +<quote>hidden</quote> file to that directory. On Unix-like systems, any file 18.84 +name that begins with a period (<quote><literal>.</literal></quote>) is treated as hidden 18.85 +by most commands and GUI tools. This approach is illustrated in 18.86 +figure <xref linkend="ex:daily:hidden"/>. 18.87 +</para> 18.88 + 18.89 +<informalfigure> 18.90 +<para> <!-- &interaction.daily.files.hidden; --> 18.91 + <caption><para>Simulating an empty directory using a hidden file</para></caption> 18.92 + \label{ex:daily:hidden} 18.93 +</para> 18.94 +</informalfigure> 18.95 + 18.96 +<para>Another way to tackle a need for an empty directory is to simply 18.97 +create one in your automated build scripts before they will need it. 18.98 +</para> 18.99 + 18.100 +</sect2> 18.101 +</sect1> 18.102 +<sect1> 18.103 +<title>How to stop tracking a file</title> 18.104 + 18.105 +<para>Once you decide that a file no longer belongs in your repository, use 18.106 +the <command role="hg-cmd">hg remove</command> command; this deletes the file, and tells Mercurial 18.107 +to stop tracking it. A removed file is represented in the output of 18.108 +<command role="hg-cmd">hg status</command> with a <quote><literal>R</literal></quote>. 18.109 +<!-- &interaction.daily.files.remove; --> 18.110 +</para> 18.111 + 18.112 +<para>After you <command role="hg-cmd">hg remove</command> a file, Mercurial will no longer track 18.113 +changes to that file, even if you recreate a file with the same name 18.114 +in your working directory. If you do recreate a file with the same 18.115 +name and want Mercurial to track the new file, simply <command role="hg-cmd">hg add</command> it. 18.116 +Mercurial will know that the newly added file is not related to the 18.117 +old file of the same name. 18.118 +</para> 18.119 + 18.120 +<sect2> 18.121 +<title>Removing a file does not affect its history</title> 18.122 + 18.123 +<para>It is important to understand that removing a file has only two 18.124 +effects. 18.125 +</para> 18.126 +<itemizedlist> 18.127 +<listitem><para>It removes the current version of the file from the working 18.128 + directory. 18.129 +</para> 18.130 +</listitem> 18.131 +<listitem><para>It stops Mercurial from tracking changes to the file, from the 18.132 + time of the next commit. 18.133 +</para> 18.134 +</listitem></itemizedlist> 18.135 +<para>Removing a file <emphasis>does not</emphasis> in any way alter the <emphasis>history</emphasis> of 18.136 +the file. 18.137 +</para> 18.138 + 18.139 +<para>If you update the working directory to a changeset in which a file 18.140 +that you have removed was still tracked, it will reappear in the 18.141 +working directory, with the contents it had when you committed that 18.142 +changeset. If you then update the working directory to a later 18.143 +changeset, in which the file had been removed, Mercurial will once 18.144 +again remove the file from the working directory. 18.145 +</para> 18.146 + 18.147 +</sect2> 18.148 +<sect2> 18.149 +<title>Missing files</title> 18.150 + 18.151 +<para>Mercurial considers a file that you have deleted, but not used 18.152 +<command role="hg-cmd">hg remove</command> to delete, to be <emphasis>missing</emphasis>. A missing file is 18.153 +represented with <quote><literal>!</literal></quote> in the output of <command role="hg-cmd">hg status</command>. 18.154 +Mercurial commands will not generally do anything with missing files. 18.155 +<!-- &interaction.daily.files.missing; --> 18.156 +</para> 18.157 + 18.158 +<para>If your repository contains a file that <command role="hg-cmd">hg status</command> reports as 18.159 +missing, and you want the file to stay gone, you can run 18.160 +<command role="hg-cmd">hg remove <option role="hg-opt-remove">--after</option></command> at any time later on, to 18.161 +tell Mercurial that you really did mean to remove the file. 18.162 +<!-- &interaction.daily.files.remove-after; --> 18.163 +</para> 18.164 + 18.165 +<para>On the other hand, if you deleted the missing file by accident, use 18.166 +<command role="hg-cmd">hg revert <emphasis>filename</emphasis></command> to recover the file. It will 18.167 +reappear, in unmodified form. 18.168 +<!-- &interaction.daily.files.recover-missing; --> 18.169 +</para> 18.170 + 18.171 +<para>\subsection{Aside: why tell Mercurial explicitly to 18.172 + remove a file?} 18.173 +</para> 18.174 + 18.175 +<para>You might wonder why Mercurial requires you to explicitly tell it that 18.176 +you are deleting a file. Early during the development of Mercurial, 18.177 +it let you delete a file however you pleased; Mercurial would notice 18.178 +the absence of the file automatically when you next ran a 18.179 +<command role="hg-cmd">hg commit</command>, and stop tracking the file. In practice, this made it 18.180 +too easy to accidentally remove a file without noticing. 18.181 +</para> 18.182 + 18.183 +<para>\subsection{Useful shorthand&emdash;adding and removing files 18.184 + in one step} 18.185 +</para> 18.186 + 18.187 +<para>Mercurial offers a combination command, <command role="hg-cmd">hg addremove</command>, that adds 18.188 +untracked files and marks missing files as removed. 18.189 +<!-- &interaction.daily.files.addremove; --> 18.190 +The <command role="hg-cmd">hg commit</command> command also provides a <option role="hg-opt-commit">-A</option> option 18.191 +that performs this same add-and-remove, immediately followed by a 18.192 +commit. 18.193 +<!-- &interaction.daily.files.commit-addremove; --> 18.194 +</para> 18.195 + 18.196 +</sect2> 18.197 +</sect1> 18.198 +<sect1> 18.199 +<title>Copying files</title> 18.200 + 18.201 +<para>Mercurial provides a <command role="hg-cmd">hg copy</command> command that lets you make a new 18.202 +copy of a file. When you copy a file using this command, Mercurial 18.203 +makes a record of the fact that the new file is a copy of the original 18.204 +file. It treats these copied files specially when you merge your work 18.205 +with someone else's. 18.206 +</para> 18.207 + 18.208 +<sect2> 18.209 +<title>The results of copying during a merge</title> 18.210 + 18.211 +<para>What happens during a merge is that changes <quote>follow</quote> a copy. To 18.212 +best illustrate what this means, let's create an example. We'll start 18.213 +with the usual tiny repository that contains a single file. 18.214 +<!-- &interaction.daily.copy.init; --> 18.215 +We need to do some work in parallel, so that we'll have something to 18.216 +merge. So let's clone our repository. 18.217 +<!-- &interaction.daily.copy.clone; --> 18.218 +Back in our initial repository, let's use the <command role="hg-cmd">hg copy</command> command to 18.219 +make a copy of the first file we created. 18.220 +<!-- &interaction.daily.copy.copy; --> 18.221 +</para> 18.222 + 18.223 +<para>If we look at the output of the <command role="hg-cmd">hg status</command> command afterwards, the 18.224 +copied file looks just like a normal added file. 18.225 +<!-- &interaction.daily.copy.status; --> 18.226 +But if we pass the <option role="hg-opt-status">-C</option> option to <command role="hg-cmd">hg status</command>, it 18.227 +prints another line of output: this is the file that our newly-added 18.228 +file was copied <emphasis>from</emphasis>. 18.229 +<!-- &interaction.daily.copy.status-copy; --> 18.230 +</para> 18.231 + 18.232 +<para>Now, back in the repository we cloned, let's make a change in 18.233 +parallel. We'll add a line of content to the original file that we 18.234 +created. 18.235 +<!-- &interaction.daily.copy.other; --> 18.236 +Now we have a modified <filename>file</filename> in this repository. When we 18.237 +pull the changes from the first repository, and merge the two heads, 18.238 +Mercurial will propagate the changes that we made locally to 18.239 +<filename>file</filename> into its copy, <filename>new-file</filename>. 18.240 +<!-- &interaction.daily.copy.merge; --> 18.241 +</para> 18.242 + 18.243 +</sect2> 18.244 +<sect2> 18.245 +<title>Why should changes follow copies?</title> 18.246 +<para>\label{sec:daily:why-copy} 18.247 +</para> 18.248 + 18.249 +<para>This behaviour, of changes to a file propagating out to copies of the 18.250 +file, might seem esoteric, but in most cases it's highly desirable. 18.251 +</para> 18.252 + 18.253 +<para>First of all, remember that this propagation <emphasis>only</emphasis> happens when 18.254 +you merge. So if you <command role="hg-cmd">hg copy</command> a file, and subsequently modify the 18.255 +original file during the normal course of your work, nothing will 18.256 +happen. 18.257 +</para> 18.258 + 18.259 +<para>The second thing to know is that modifications will only propagate 18.260 +across a copy as long as the repository that you're pulling changes 18.261 +from <emphasis>doesn't know</emphasis> about the copy. 18.262 +</para> 18.263 + 18.264 +<para>The reason that Mercurial does this is as follows. Let's say I make 18.265 +an important bug fix in a source file, and commit my changes. 18.266 +Meanwhile, you've decided to <command role="hg-cmd">hg copy</command> the file in your repository, 18.267 +without knowing about the bug or having seen the fix, and you have 18.268 +started hacking on your copy of the file. 18.269 +</para> 18.270 + 18.271 +<para>If you pulled and merged my changes, and Mercurial <emphasis>didn't</emphasis> 18.272 +propagate changes across copies, your source file would now contain 18.273 +the bug, and unless you remembered to propagate the bug fix by hand, 18.274 +the bug would <emphasis>remain</emphasis> in your copy of the file. 18.275 +</para> 18.276 + 18.277 +<para>By automatically propagating the change that fixed the bug from the 18.278 +original file to the copy, Mercurial prevents this class of problem. 18.279 +To my knowledge, Mercurial is the <emphasis>only</emphasis> revision control system 18.280 +that propagates changes across copies like this. 18.281 +</para> 18.282 + 18.283 +<para>Once your change history has a record that the copy and subsequent 18.284 +merge occurred, there's usually no further need to propagate changes 18.285 +from the original file to the copied file, and that's why Mercurial 18.286 +only propagates changes across copies until this point, and no 18.287 +further. 18.288 +</para> 18.289 + 18.290 +</sect2> 18.291 +<sect2> 18.292 +<title>How to make changes <emphasis>not</emphasis> follow a copy</title> 18.293 + 18.294 +<para>If, for some reason, you decide that this business of automatically 18.295 +propagating changes across copies is not for you, simply use your 18.296 +system's normal file copy command (on Unix-like systems, that's 18.297 +<command>cp</command>) to make a copy of a file, then <command role="hg-cmd">hg add</command> the new copy 18.298 +by hand. Before you do so, though, please do reread 18.299 +section <xref linkend="sec:daily:why-copy"/>, and make an informed decision that 18.300 +this behaviour is not appropriate to your specific case. 18.301 +</para> 18.302 + 18.303 +</sect2> 18.304 +<sect2> 18.305 +<title>Behaviour of the <command role="hg-cmd">hg copy</command> command</title> 18.306 + 18.307 +<para>When you use the <command role="hg-cmd">hg copy</command> command, Mercurial makes a copy of each 18.308 +source file as it currently stands in the working directory. This 18.309 +means that if you make some modifications to a file, then <command role="hg-cmd">hg copy</command> 18.310 +it without first having committed those changes, the new copy will 18.311 +also contain the modifications you have made up until that point. (I 18.312 +find this behaviour a little counterintuitive, which is why I mention 18.313 +it here.) 18.314 +</para> 18.315 + 18.316 +<para>The <command role="hg-cmd">hg copy</command> command acts similarly to the Unix <command>cp</command> 18.317 +command (you can use the <command role="hg-cmd">hg cp</command> alias if you prefer). The last 18.318 +argument is the <emphasis>destination</emphasis>, and all prior arguments are 18.319 +<emphasis>sources</emphasis>. If you pass it a single file as the source, and the 18.320 +destination does not exist, it creates a new file with that name. 18.321 +<!-- &interaction.daily.copy.simple; --> 18.322 +If the destination is a directory, Mercurial copies its sources into 18.323 +that directory. 18.324 +<!-- &interaction.daily.copy.dir-dest; --> 18.325 +Copying a directory is recursive, and preserves the directory 18.326 +structure of the source. 18.327 +<!-- &interaction.daily.copy.dir-src; --> 18.328 +If the source and destination are both directories, the source tree is 18.329 +recreated in the destination directory. 18.330 +<!-- &interaction.daily.copy.dir-src-dest; --> 18.331 +</para> 18.332 + 18.333 +<para>As with the <command role="hg-cmd">hg rename</command> command, if you copy a file manually and 18.334 +then want Mercurial to know that you've copied the file, simply use 18.335 +the <option role="hg-opt-copy">--after</option> option to <command role="hg-cmd">hg copy</command>. 18.336 +<!-- &interaction.daily.copy.after; --> 18.337 +</para> 18.338 + 18.339 +</sect2> 18.340 +</sect1> 18.341 +<sect1> 18.342 +<title>Renaming files</title> 18.343 + 18.344 +<para>It's rather more common to need to rename a file than to make a copy 18.345 +of it. The reason I discussed the <command role="hg-cmd">hg copy</command> command before talking 18.346 +about renaming files is that Mercurial treats a rename in essentially 18.347 +the same way as a copy. Therefore, knowing what Mercurial does when 18.348 +you copy a file tells you what to expect when you rename a file. 18.349 +</para> 18.350 + 18.351 +<para>When you use the <command role="hg-cmd">hg rename</command> command, Mercurial makes a copy of 18.352 +each source file, then deletes it and marks the file as removed. 18.353 +<!-- &interaction.daily.rename.rename; --> 18.354 +The <command role="hg-cmd">hg status</command> command shows the newly copied file as added, and 18.355 +the copied-from file as removed. 18.356 +<!-- &interaction.daily.rename.status; --> 18.357 +As with the results of a <command role="hg-cmd">hg copy</command>, we must use the 18.358 +<option role="hg-opt-status">-C</option> option to <command role="hg-cmd">hg status</command> to see that the added file 18.359 +is really being tracked by Mercurial as a copy of the original, now 18.360 +removed, file. 18.361 +<!-- &interaction.daily.rename.status-copy; --> 18.362 +</para> 18.363 + 18.364 +<para>As with <command role="hg-cmd">hg remove</command> and <command role="hg-cmd">hg copy</command>, you can tell Mercurial about 18.365 +a rename after the fact using the <option role="hg-opt-rename">--after</option> option. In 18.366 +most other respects, the behaviour of the <command role="hg-cmd">hg rename</command> command, and 18.367 +the options it accepts, are similar to the <command role="hg-cmd">hg copy</command> command. 18.368 +</para> 18.369 + 18.370 +<sect2> 18.371 +<title>Renaming files and merging changes</title> 18.372 + 18.373 +<para>Since Mercurial's rename is implemented as copy-and-remove, the same 18.374 +propagation of changes happens when you merge after a rename as after 18.375 +a copy. 18.376 +</para> 18.377 + 18.378 +<para>If I modify a file, and you rename it to a new name, and then we merge 18.379 +our respective changes, my modifications to the file under its 18.380 +original name will be propagated into the file under its new name. 18.381 +(This is something you might expect to <quote>simply work,</quote> but not all 18.382 +revision control systems actually do this.) 18.383 +</para> 18.384 + 18.385 +<para>Whereas having changes follow a copy is a feature where you can 18.386 +perhaps nod and say <quote>yes, that might be useful,</quote> it should be clear 18.387 +that having them follow a rename is definitely important. Without 18.388 +this facility, it would simply be too easy for changes to become 18.389 +orphaned when files are renamed. 18.390 +</para> 18.391 + 18.392 +</sect2> 18.393 +<sect2> 18.394 +<title>Divergent renames and merging</title> 18.395 + 18.396 +<para>The case of diverging names occurs when two developers start with a 18.397 +file&emdash;let's call it <filename>foo</filename>&emdash;in their respective 18.398 +repositories. 18.399 +</para> 18.400 + 18.401 +<para><!-- &interaction.rename.divergent.clone; --> 18.402 +Anne renames the file to <filename>bar</filename>. 18.403 +<!-- &interaction.rename.divergent.rename.anne; --> 18.404 +Meanwhile, Bob renames it to <filename>quux</filename>. 18.405 +<!-- &interaction.rename.divergent.rename.bob; --> 18.406 +</para> 18.407 + 18.408 +<para>I like to think of this as a conflict because each developer has 18.409 +expressed different intentions about what the file ought to be named. 18.410 +</para> 18.411 + 18.412 +<para>What do you think should happen when they merge their work? 18.413 +Mercurial's actual behaviour is that it always preserves <emphasis>both</emphasis> 18.414 +names when it merges changesets that contain divergent renames. 18.415 +<!-- &interaction.rename.divergent.merge; --> 18.416 +</para> 18.417 + 18.418 +<para>Notice that Mercurial does warn about the divergent renames, but it 18.419 +leaves it up to you to do something about the divergence after the merge. 18.420 +</para> 18.421 + 18.422 +</sect2> 18.423 +<sect2> 18.424 +<title>Convergent renames and merging</title> 18.425 + 18.426 +<para>Another kind of rename conflict occurs when two people choose to 18.427 +rename different <emphasis>source</emphasis> files to the same <emphasis>destination</emphasis>. 18.428 +In this case, Mercurial runs its normal merge machinery, and lets you 18.429 +guide it to a suitable resolution. 18.430 +</para> 18.431 + 18.432 +</sect2> 18.433 +<sect2> 18.434 +<title>Other name-related corner cases</title> 18.435 + 18.436 +<para>Mercurial has a longstanding bug in which it fails to handle a merge 18.437 +where one side has a file with a given name, while another has a 18.438 +directory with the same name. This is documented as <ulink role="hg-bug" url="http://www.selenic.com/mercurial/bts/issue29">issue 29</ulink>. 18.439 +<!-- &interaction.issue29.go; --> 18.440 +</para> 18.441 + 18.442 +</sect2> 18.443 +</sect1> 18.444 +<sect1> 18.445 +<title>Recovering from mistakes</title> 18.446 + 18.447 +<para>Mercurial has some useful commands that will help you to recover from 18.448 +some common mistakes. 18.449 +</para> 18.450 + 18.451 +<para>The <command role="hg-cmd">hg revert</command> command lets you undo changes that you have made to 18.452 +your working directory. For example, if you <command role="hg-cmd">hg add</command> a file by 18.453 +accident, just run <command role="hg-cmd">hg revert</command> with the name of the file you added, 18.454 +and while the file won't be touched in any way, it won't be tracked 18.455 +for adding by Mercurial any longer, either. You can also use 18.456 +<command role="hg-cmd">hg revert</command> to get rid of erroneous changes to a file. 18.457 +</para> 18.458 + 18.459 +<para>It's useful to remember that the <command role="hg-cmd">hg revert</command> command is useful for 18.460 +changes that you have not yet committed. Once you've committed a 18.461 +change, if you decide it was a mistake, you can still do something 18.462 +about it, though your options may be more limited. 18.463 +</para> 18.464 + 18.465 +<para>For more information about the <command role="hg-cmd">hg revert</command> command, and details 18.466 +about how to deal with changes you have already committed, see 18.467 +chapter <xref linkend="chap:undo"/>. 18.468 +</para> 18.469 + 18.470 +</sect1> 18.471 +</chapter> 18.472 + 18.473 +<!-- 18.474 +local variables: 18.475 +sgml-parent-document: ("00book.xml" "book" "chapter") 18.476 +end: 18.477 +--> 18.478 \ No newline at end of file
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 19.2 +++ b/fr/ch06-collab.xml Sun Aug 16 04:58:01 2009 +0200 19.3 @@ -0,0 +1,1405 @@ 19.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 19.5 + 19.6 +<chapter> 19.7 +<title>Collaborating with other people</title> 19.8 +<para>\label{cha:collab}</para> 19.9 + 19.10 +<para>As a completely decentralised tool, Mercurial doesn't impose any 19.11 +policy on how people ought to work with each other. However, if 19.12 +you're new to distributed revision control, it helps to have some 19.13 +tools and examples in mind when you're thinking about possible 19.14 +workflow models.</para> 19.15 + 19.16 +<sect1> 19.17 +<title>Mercurial's web interface</title> 19.18 + 19.19 +<para>Mercurial has a powerful web interface that provides several 19.20 +useful capabilities.</para> 19.21 + 19.22 +<para>For interactive use, the web interface lets you browse a single 19.23 +repository or a collection of repositories. You can view the history 19.24 +of a repository, examine each change (comments and diffs), and view 19.25 +the contents of each directory and file.</para> 19.26 + 19.27 +<para>Also for human consumption, the web interface provides an RSS feed of 19.28 +the changes in a repository. This lets you <quote>subscribe</quote> to a 19.29 +repository using your favourite feed reader, and be automatically 19.30 +notified of activity in that repository as soon as it happens. I find 19.31 +this capability much more convenient than the model of subscribing to 19.32 +a mailing list to which notifications are sent, as it requires no 19.33 +additional configuration on the part of whoever is serving the 19.34 +repository.</para> 19.35 + 19.36 +<para>The web interface also lets remote users clone a repository, pull 19.37 +changes from it, and (when the server is configured to permit it) push 19.38 +changes back to it. Mercurial's HTTP tunneling protocol aggressively 19.39 +compresses data, so that it works efficiently even over low-bandwidth 19.40 +network connections.</para> 19.41 + 19.42 +<para>The easiest way to get started with the web interface is to use your 19.43 +web browser to visit an existing repository, such as the master 19.44 +Mercurial repository at 19.45 +<ulink url="http://www.selenic.com/repo/hg?style=gitweb">http://www.selenic.com/repo/hg?style=gitweb</ulink>.</para> 19.46 + 19.47 +<para>If you're interested in providing a web interface to your own 19.48 +repositories, Mercurial provides two ways to do this. The first is 19.49 +using the <command role="hg-cmd">hg serve</command> command, which is best suited to short-term 19.50 +<quote>lightweight</quote> serving. See section <xref linkend="sec:collab:serve"/> below for 19.51 +details of how to use this command. If you have a long-lived 19.52 +repository that you'd like to make permanently available, Mercurial 19.53 +has built-in support for the CGI (Common Gateway Interface) standard, 19.54 +which all common web servers support. See 19.55 +section <xref linkend="sec:collab:cgi"/> for details of CGI configuration.</para> 19.56 + 19.57 +</sect1> 19.58 +<sect1> 19.59 +<title>Collaboration models</title> 19.60 + 19.61 +<para>With a suitably flexible tool, making decisions about workflow is much 19.62 +more of a social engineering challenge than a technical one. 19.63 +Mercurial imposes few limitations on how you can structure the flow of 19.64 +work in a project, so it's up to you and your group to set up and live 19.65 +with a model that matches your own particular needs. 19.66 +</para> 19.67 + 19.68 +<sect2> 19.69 +<title>Factors to keep in mind</title> 19.70 + 19.71 +<para>The most important aspect of any model that you must keep in mind is 19.72 +how well it matches the needs and capabilities of the people who will 19.73 +be using it. This might seem self-evident; even so, you still can't 19.74 +afford to forget it for a moment. 19.75 +</para> 19.76 + 19.77 +<para>I once put together a workflow model that seemed to make perfect sense 19.78 +to me, but that caused a considerable amount of consternation and 19.79 +strife within my development team. In spite of my attempts to explain 19.80 +why we needed a complex set of branches, and how changes ought to flow 19.81 +between them, a few team members revolted. Even though they were 19.82 +smart people, they didn't want to pay attention to the constraints we 19.83 +were operating under, or face the consequences of those constraints in 19.84 +the details of the model that I was advocating. 19.85 +</para> 19.86 + 19.87 +<para>Don't sweep foreseeable social or technical problems under the rug. 19.88 +Whatever scheme you put into effect, you should plan for mistakes and 19.89 +problem scenarios. Consider adding automated machinery to prevent, or 19.90 +quickly recover from, trouble that you can anticipate. As an example, 19.91 +if you intend to have a branch with not-for-release changes in it, 19.92 +you'd do well to think early about the possibility that someone might 19.93 +accidentally merge those changes into a release branch. You could 19.94 +avoid this particular problem by writing a hook that prevents changes 19.95 +from being merged from an inappropriate branch. 19.96 +</para> 19.97 + 19.98 +</sect2> 19.99 +<sect2> 19.100 +<title>Informal anarchy</title> 19.101 + 19.102 +<para>I wouldn't suggest an <quote>anything goes</quote> approach as something 19.103 +sustainable, but it's a model that's easy to grasp, and it works 19.104 +perfectly well in a few unusual situations. 19.105 +</para> 19.106 + 19.107 +<para>As one example, many projects have a loose-knit group of collaborators 19.108 +who rarely physically meet each other. Some groups like to overcome 19.109 +the isolation of working at a distance by organising occasional 19.110 +<quote>sprints</quote>. In a sprint, a number of people get together in a single 19.111 +location (a company's conference room, a hotel meeting room, that kind 19.112 +of place) and spend several days more or less locked in there, hacking 19.113 +intensely on a handful of projects. 19.114 +</para> 19.115 + 19.116 +<para>A sprint is the perfect place to use the <command role="hg-cmd">hg serve</command> command, since 19.117 +<command role="hg-cmd">hg serve</command> does not requires any fancy server infrastructure. You 19.118 +can get started with <command role="hg-cmd">hg serve</command> in moments, by reading 19.119 +section <xref linkend="sec:collab:serve"/> below. Then simply tell the person 19.120 +next to you that you're running a server, send the URL to them in an 19.121 +instant message, and you immediately have a quick-turnaround way to 19.122 +work together. They can type your URL into their web browser and 19.123 +quickly review your changes; or they can pull a bugfix from you and 19.124 +verify it; or they can clone a branch containing a new feature and try 19.125 +it out. 19.126 +</para> 19.127 + 19.128 +<para>The charm, and the problem, with doing things in an ad hoc fashion 19.129 +like this is that only people who know about your changes, and where 19.130 +they are, can see them. Such an informal approach simply doesn't 19.131 +scale beyond a handful people, because each individual needs to know 19.132 +about $n$ different repositories to pull from. 19.133 +</para> 19.134 + 19.135 +</sect2> 19.136 +<sect2> 19.137 +<title>A single central repository</title> 19.138 + 19.139 +<para>For smaller projects migrating from a centralised revision control 19.140 +tool, perhaps the easiest way to get started is to have changes flow 19.141 +through a single shared central repository. This is also the 19.142 +most common <quote>building block</quote> for more ambitious workflow schemes. 19.143 +</para> 19.144 + 19.145 +<para>Contributors start by cloning a copy of this repository. They can 19.146 +pull changes from it whenever they need to, and some (perhaps all) 19.147 +developers have permission to push a change back when they're ready 19.148 +for other people to see it. 19.149 +</para> 19.150 + 19.151 +<para>Under this model, it can still often make sense for people to pull 19.152 +changes directly from each other, without going through the central 19.153 +repository. Consider a case in which I have a tentative bug fix, but 19.154 +I am worried that if I were to publish it to the central repository, 19.155 +it might subsequently break everyone else's trees as they pull it. To 19.156 +reduce the potential for damage, I can ask you to clone my repository 19.157 +into a temporary repository of your own and test it. This lets us put 19.158 +off publishing the potentially unsafe change until it has had a little 19.159 +testing. 19.160 +</para> 19.161 + 19.162 +<para>In this kind of scenario, people usually use the <command>ssh</command> 19.163 +protocol to securely push changes to the central repository, as 19.164 +documented in section <xref linkend="sec:collab:ssh"/>. It's also usual to 19.165 +publish a read-only copy of the repository over HTTP using CGI, as in 19.166 +section <xref linkend="sec:collab:cgi"/>. Publishing over HTTP satisfies the 19.167 +needs of people who don't have push access, and those who want to use 19.168 +web browsers to browse the repository's history. 19.169 +</para> 19.170 + 19.171 +</sect2> 19.172 +<sect2> 19.173 +<title>Working with multiple branches</title> 19.174 + 19.175 +<para>Projects of any significant size naturally tend to make progress on 19.176 +several fronts simultaneously. In the case of software, it's common 19.177 +for a project to go through periodic official releases. A release 19.178 +might then go into <quote>maintenance mode</quote> for a while after its first 19.179 +publication; maintenance releases tend to contain only bug fixes, not 19.180 +new features. In parallel with these maintenance releases, one or 19.181 +more future releases may be under development. People normally use 19.182 +the word <quote>branch</quote> to refer to one of these many slightly different 19.183 +directions in which development is proceeding. 19.184 +</para> 19.185 + 19.186 +<para>Mercurial is particularly well suited to managing a number of 19.187 +simultaneous, but not identical, branches. Each <quote>development 19.188 +direction</quote> can live in its own central repository, and you can merge 19.189 +changes from one to another as the need arises. Because repositories 19.190 +are independent of each other, unstable changes in a development 19.191 +branch will never affect a stable branch unless someone explicitly 19.192 +merges those changes in. 19.193 +</para> 19.194 + 19.195 +<para>Here's an example of how this can work in practice. Let's say you 19.196 +have one <quote>main branch</quote> on a central server. 19.197 +<!-- &interaction.branching.init; --> 19.198 +People clone it, make changes locally, test them, and push them back. 19.199 +</para> 19.200 + 19.201 +<para>Once the main branch reaches a release milestone, you can use the 19.202 +<command role="hg-cmd">hg tag</command> command to give a permanent name to the milestone 19.203 +revision. 19.204 +<!-- &interaction.branching.tag; --> 19.205 +Let's say some ongoing development occurs on the main branch. 19.206 +<!-- &interaction.branching.main; --> 19.207 +Using the tag that was recorded at the milestone, people who clone 19.208 +that repository at any time in the future can use <command role="hg-cmd">hg update</command> to 19.209 +get a copy of the working directory exactly as it was when that tagged 19.210 +revision was committed. 19.211 +<!-- &interaction.branching.update; --> 19.212 +</para> 19.213 + 19.214 +<para>In addition, immediately after the main branch is tagged, someone can 19.215 +then clone the main branch on the server to a new <quote>stable</quote> branch, 19.216 +also on the server. 19.217 +<!-- &interaction.branching.clone; --> 19.218 +</para> 19.219 + 19.220 +<para>Someone who needs to make a change to the stable branch can then clone 19.221 +<emphasis>that</emphasis> repository, make their changes, commit, and push their 19.222 +changes back there. 19.223 +<!-- &interaction.branching.stable; --> 19.224 +Because Mercurial repositories are independent, and Mercurial doesn't 19.225 +move changes around automatically, the stable and main branches are 19.226 +<emphasis>isolated</emphasis> from each other. The changes that you made on the 19.227 +main branch don't <quote>leak</quote> to the stable branch, and vice versa. 19.228 +</para> 19.229 + 19.230 +<para>You'll often want all of your bugfixes on the stable branch to show up 19.231 +on the main branch, too. Rather than rewrite a bugfix on the main 19.232 +branch, you can simply pull and merge changes from the stable to the 19.233 +main branch, and Mercurial will bring those bugfixes in for you. 19.234 +<!-- &interaction.branching.merge; --> 19.235 +The main branch will still contain changes that are not on the stable 19.236 +branch, but it will also contain all of the bugfixes from the stable 19.237 +branch. The stable branch remains unaffected by these changes. 19.238 +</para> 19.239 + 19.240 +</sect2> 19.241 +<sect2> 19.242 +<title>Feature branches</title> 19.243 + 19.244 +<para>For larger projects, an effective way to manage change is to break up 19.245 +a team into smaller groups. Each group has a shared branch of its 19.246 +own, cloned from a single <quote>master</quote> branch used by the entire 19.247 +project. People working on an individual branch are typically quite 19.248 +isolated from developments on other branches. 19.249 +</para> 19.250 + 19.251 +<informalfigure> 19.252 + 19.253 +<para> <mediaobject><imageobject><imagedata fileref="feature-branches"/></imageobject><textobject><phrase>XXX add text</phrase></textobject></mediaobject> 19.254 + <caption><para>Feature branches</para></caption> 19.255 + \label{fig:collab:feature-branches} 19.256 +</para> 19.257 +</informalfigure> 19.258 + 19.259 +<para>When a particular feature is deemed to be in suitable shape, someone 19.260 +on that feature team pulls and merges from the master branch into the 19.261 +feature branch, then pushes back up to the master branch. 19.262 +</para> 19.263 + 19.264 +</sect2> 19.265 +<sect2> 19.266 +<title>The release train</title> 19.267 + 19.268 +<para>Some projects are organised on a <quote>train</quote> basis: a release is 19.269 +scheduled to happen every few months, and whatever features are ready 19.270 +when the <quote>train</quote> is ready to leave are allowed in. 19.271 +</para> 19.272 + 19.273 +<para>This model resembles working with feature branches. The difference is 19.274 +that when a feature branch misses a train, someone on the feature team 19.275 +pulls and merges the changes that went out on that train release into 19.276 +the feature branch, and the team continues its work on top of that 19.277 +release so that their feature can make the next release. 19.278 +</para> 19.279 + 19.280 +</sect2> 19.281 +<sect2> 19.282 +<title>The Linux kernel model</title> 19.283 + 19.284 +<para>The development of the Linux kernel has a shallow hierarchical 19.285 +structure, surrounded by a cloud of apparent chaos. Because most 19.286 +Linux developers use <command>git</command>, a distributed revision control 19.287 +tool with capabilities similar to Mercurial, it's useful to describe 19.288 +the way work flows in that environment; if you like the ideas, the 19.289 +approach translates well across tools. 19.290 +</para> 19.291 + 19.292 +<para>At the center of the community sits Linus Torvalds, the creator of 19.293 +Linux. He publishes a single source repository that is considered the 19.294 +<quote>authoritative</quote> current tree by the entire developer community. 19.295 +Anyone can clone Linus's tree, but he is very choosy about whose trees 19.296 +he pulls from. 19.297 +</para> 19.298 + 19.299 +<para>Linus has a number of <quote>trusted lieutenants</quote>. As a general rule, he 19.300 +pulls whatever changes they publish, in most cases without even 19.301 +reviewing those changes. Some of those lieutenants are generally 19.302 +agreed to be <quote>maintainers</quote>, responsible for specific subsystems 19.303 +within the kernel. If a random kernel hacker wants to make a change 19.304 +to a subsystem that they want to end up in Linus's tree, they must 19.305 +find out who the subsystem's maintainer is, and ask that maintainer to 19.306 +take their change. If the maintainer reviews their changes and agrees 19.307 +to take them, they'll pass them along to Linus in due course. 19.308 +</para> 19.309 + 19.310 +<para>Individual lieutenants have their own approaches to reviewing, 19.311 +accepting, and publishing changes; and for deciding when to feed them 19.312 +to Linus. In addition, there are several well known branches that 19.313 +people use for different purposes. For example, a few people maintain 19.314 +<quote>stable</quote> repositories of older versions of the kernel, to which they 19.315 +apply critical fixes as needed. Some maintainers publish multiple 19.316 +trees: one for experimental changes; one for changes that they are 19.317 +about to feed upstream; and so on. Others just publish a single 19.318 +tree. 19.319 +</para> 19.320 + 19.321 +<para>This model has two notable features. The first is that it's <quote>pull 19.322 +only</quote>. You have to ask, convince, or beg another developer to take a 19.323 +change from you, because there are almost no trees to which more than 19.324 +one person can push, and there's no way to push changes into a tree 19.325 +that someone else controls. 19.326 +</para> 19.327 + 19.328 +<para>The second is that it's based on reputation and acclaim. If you're an 19.329 +unknown, Linus will probably ignore changes from you without even 19.330 +responding. But a subsystem maintainer will probably review them, and 19.331 +will likely take them if they pass their criteria for suitability. 19.332 +The more <quote>good</quote> changes you contribute to a maintainer, the more 19.333 +likely they are to trust your judgment and accept your changes. If 19.334 +you're well-known and maintain a long-lived branch for something Linus 19.335 +hasn't yet accepted, people with similar interests may pull your 19.336 +changes regularly to keep up with your work. 19.337 +</para> 19.338 + 19.339 +<para>Reputation and acclaim don't necessarily cross subsystem or <quote>people</quote> 19.340 +boundaries. If you're a respected but specialised storage hacker, and 19.341 +you try to fix a networking bug, that change will receive a level of 19.342 +scrutiny from a network maintainer comparable to a change from a 19.343 +complete stranger. 19.344 +</para> 19.345 + 19.346 +<para>To people who come from more orderly project backgrounds, the 19.347 +comparatively chaotic Linux kernel development process often seems 19.348 +completely insane. It's subject to the whims of individuals; people 19.349 +make sweeping changes whenever they deem it appropriate; and the pace 19.350 +of development is astounding. And yet Linux is a highly successful, 19.351 +well-regarded piece of software. 19.352 +</para> 19.353 + 19.354 +</sect2> 19.355 +<sect2> 19.356 +<title>Pull-only versus shared-push collaboration</title> 19.357 + 19.358 +<para>A perpetual source of heat in the open source community is whether a 19.359 +development model in which people only ever pull changes from others 19.360 +is <quote>better than</quote> one in which multiple people can push changes to a 19.361 +shared repository. 19.362 +</para> 19.363 + 19.364 +<para>Typically, the backers of the shared-push model use tools that 19.365 +actively enforce this approach. If you're using a centralised 19.366 +revision control tool such as Subversion, there's no way to make a 19.367 +choice over which model you'll use: the tool gives you shared-push, 19.368 +and if you want to do anything else, you'll have to roll your own 19.369 +approach on top (such as applying a patch by hand). 19.370 +</para> 19.371 + 19.372 +<para>A good distributed revision control tool, such as Mercurial, will 19.373 +support both models. You and your collaborators can then structure 19.374 +how you work together based on your own needs and preferences, not on 19.375 +what contortions your tools force you into. 19.376 +</para> 19.377 + 19.378 +</sect2> 19.379 +<sect2> 19.380 +<title>Where collaboration meets branch management</title> 19.381 + 19.382 +<para>Once you and your team set up some shared repositories and start 19.383 +propagating changes back and forth between local and shared repos, you 19.384 +begin to face a related, but slightly different challenge: that of 19.385 +managing the multiple directions in which your team may be moving at 19.386 +once. Even though this subject is intimately related to how your team 19.387 +collaborates, it's dense enough to merit treatment of its own, in 19.388 +chapter <xref linkend="chap:branch"/>. 19.389 +</para> 19.390 + 19.391 +</sect2> 19.392 +</sect1> 19.393 +<sect1> 19.394 +<title>The technical side of sharing</title> 19.395 + 19.396 +<para>The remainder of this chapter is devoted to the question of serving 19.397 +data to your collaborators. 19.398 +</para> 19.399 + 19.400 +</sect1> 19.401 +<sect1> 19.402 +<title>Informal sharing with <command role="hg-cmd">hg serve</command></title> 19.403 +<para>\label{sec:collab:serve} 19.404 +</para> 19.405 + 19.406 +<para>Mercurial's <command role="hg-cmd">hg serve</command> command is wonderfully suited to small, 19.407 +tight-knit, and fast-paced group environments. It also provides a 19.408 +great way to get a feel for using Mercurial commands over a network. 19.409 +</para> 19.410 + 19.411 +<para>Run <command role="hg-cmd">hg serve</command> inside a repository, and in under a second it will 19.412 +bring up a specialised HTTP server; this will accept connections from 19.413 +any client, and serve up data for that repository until you terminate 19.414 +it. Anyone who knows the URL of the server you just started, and can 19.415 +talk to your computer over the network, can then use a web browser or 19.416 +Mercurial to read data from that repository. A URL for a 19.417 +<command role="hg-cmd">hg serve</command> instance running on a laptop is likely to look something 19.418 +like <literal>http://my-laptop.local:8000/</literal>. 19.419 +</para> 19.420 + 19.421 +<para>The <command role="hg-cmd">hg serve</command> command is <emphasis>not</emphasis> a general-purpose web server. 19.422 +It can do only two things: 19.423 +</para> 19.424 +<itemizedlist> 19.425 +<listitem><para>Allow people to browse the history of the repository it's 19.426 + serving, from their normal web browsers. 19.427 +</para> 19.428 +</listitem> 19.429 +<listitem><para>Speak Mercurial's wire protocol, so that people can 19.430 + <command role="hg-cmd">hg clone</command> or <command role="hg-cmd">hg pull</command> changes from that repository. 19.431 +</para> 19.432 +</listitem></itemizedlist> 19.433 +<para>In particular, <command role="hg-cmd">hg serve</command> won't allow remote users to <emphasis>modify</emphasis> 19.434 +your repository. It's intended for read-only use. 19.435 +</para> 19.436 + 19.437 +<para>If you're getting started with Mercurial, there's nothing to prevent 19.438 +you from using <command role="hg-cmd">hg serve</command> to serve up a repository on your own 19.439 +computer, then use commands like <command role="hg-cmd">hg clone</command>, <command role="hg-cmd">hg incoming</command>, and 19.440 +so on to talk to that server as if the repository was hosted remotely. 19.441 +This can help you to quickly get acquainted with using commands on 19.442 +network-hosted repositories. 19.443 +</para> 19.444 + 19.445 +<sect2> 19.446 +<title>A few things to keep in mind</title> 19.447 + 19.448 +<para>Because it provides unauthenticated read access to all clients, you 19.449 +should only use <command role="hg-cmd">hg serve</command> in an environment where you either don't 19.450 +care, or have complete control over, who can access your network and 19.451 +pull data from your repository. 19.452 +</para> 19.453 + 19.454 +<para>The <command role="hg-cmd">hg serve</command> command knows nothing about any firewall software 19.455 +you might have installed on your system or network. It cannot detect 19.456 +or control your firewall software. If other people are unable to talk 19.457 +to a running <command role="hg-cmd">hg serve</command> instance, the second thing you should do 19.458 +(<emphasis>after</emphasis> you make sure that they're using the correct URL) is 19.459 +check your firewall configuration. 19.460 +</para> 19.461 + 19.462 +<para>By default, <command role="hg-cmd">hg serve</command> listens for incoming connections on 19.463 +port 8000. If another process is already listening on the port you 19.464 +want to use, you can specify a different port to listen on using the 19.465 +<option role="hg-opt-serve">-p</option> option. 19.466 +</para> 19.467 + 19.468 +<para>Normally, when <command role="hg-cmd">hg serve</command> starts, it prints no output, which can be 19.469 +a bit unnerving. If you'd like to confirm that it is indeed running 19.470 +correctly, and find out what URL you should send to your 19.471 +collaborators, start it with the <option role="hg-opt-global">-v</option> option. 19.472 +</para> 19.473 + 19.474 +</sect2> 19.475 +</sect1> 19.476 +<sect1> 19.477 +<title>Using the Secure Shell (ssh) protocol</title> 19.478 +<para>\label{sec:collab:ssh} 19.479 +</para> 19.480 + 19.481 +<para>You can pull and push changes securely over a network connection using 19.482 +the Secure Shell (<literal>ssh</literal>) protocol. To use this successfully, 19.483 +you may have to do a little bit of configuration on the client or 19.484 +server sides. 19.485 +</para> 19.486 + 19.487 +<para>If you're not familiar with ssh, it's a network protocol that lets you 19.488 +securely communicate with another computer. To use it with Mercurial, 19.489 +you'll be setting up one or more user accounts on a server so that 19.490 +remote users can log in and execute commands. 19.491 +</para> 19.492 + 19.493 +<para>(If you <emphasis>are</emphasis> familiar with ssh, you'll probably find some of the 19.494 +material that follows to be elementary in nature.) 19.495 +</para> 19.496 + 19.497 +<sect2> 19.498 +<title>How to read and write ssh URLs</title> 19.499 + 19.500 +<para>An ssh URL tends to look like this: 19.501 +</para> 19.502 +<programlisting> 19.503 +<para> ssh://bos@hg.serpentine.com:22/hg/hgbook 19.504 +</para> 19.505 +</programlisting> 19.506 +<orderedlist> 19.507 +<listitem><para>The <quote><literal>ssh://</literal></quote> part tells Mercurial to use the ssh 19.508 + protocol. 19.509 +</para> 19.510 +</listitem> 19.511 +<listitem><para>The <quote><literal>bos@</literal></quote> component indicates what username to log 19.512 + into the server as. You can leave this out if the remote username 19.513 + is the same as your local username. 19.514 +</para> 19.515 +</listitem> 19.516 +<listitem><para>The <quote><literal>hg.serpentine.com</literal></quote> gives the hostname of the 19.517 + server to log into. 19.518 +</para> 19.519 +</listitem> 19.520 +<listitem><para>The <quote>:22</quote> identifies the port number to connect to the server 19.521 + on. The default port is 22, so you only need to specify this part 19.522 + if you're <emphasis>not</emphasis> using port 22. 19.523 +</para> 19.524 +</listitem> 19.525 +<listitem><para>The remainder of the URL is the local path to the repository on 19.526 + the server. 19.527 +</para> 19.528 +</listitem></orderedlist> 19.529 + 19.530 +<para>There's plenty of scope for confusion with the path component of ssh 19.531 +URLs, as there is no standard way for tools to interpret it. Some 19.532 +programs behave differently than others when dealing with these paths. 19.533 +This isn't an ideal situation, but it's unlikely to change. Please 19.534 +read the following paragraphs carefully. 19.535 +</para> 19.536 + 19.537 +<para>Mercurial treats the path to a repository on the server as relative to 19.538 +the remote user's home directory. For example, if user <literal>foo</literal> 19.539 +on the server has a home directory of <filename class="directory">/home/foo</filename>, then an ssh 19.540 +URL that contains a path component of <filename class="directory">bar</filename> 19.541 +<emphasis>really</emphasis> refers to the directory <filename class="directory">/home/foo/bar</filename>. 19.542 +</para> 19.543 + 19.544 +<para>If you want to specify a path relative to another user's home 19.545 +directory, you can use a path that starts with a tilde character 19.546 +followed by the user's name (let's call them <literal>otheruser</literal>), like 19.547 +this. 19.548 +</para> 19.549 +<programlisting> 19.550 +<para> ssh://server/ otheruser/hg/repo 19.551 +</para> 19.552 +</programlisting> 19.553 + 19.554 +<para>And if you really want to specify an <emphasis>absolute</emphasis> path on the 19.555 +server, begin the path component with two slashes, as in this example. 19.556 +</para> 19.557 +<programlisting> 19.558 +<para> ssh://server//absolute/path 19.559 +</para> 19.560 +</programlisting> 19.561 + 19.562 +</sect2> 19.563 +<sect2> 19.564 +<title>Finding an ssh client for your system</title> 19.565 + 19.566 +<para>Almost every Unix-like system comes with OpenSSH preinstalled. If 19.567 +you're using such a system, run <literal>which ssh</literal> to find out if 19.568 +the <command>ssh</command> command is installed (it's usually in 19.569 +<filename class="directory">/usr/bin</filename>). In the unlikely event that it isn't present, 19.570 +take a look at your system documentation to figure out how to install 19.571 +it. 19.572 +</para> 19.573 + 19.574 +<para>On Windows, you'll first need to download a suitable ssh 19.575 +client. There are two alternatives. 19.576 +</para> 19.577 +<itemizedlist> 19.578 +<listitem><para>Simon Tatham's excellent PuTTY package <citation>web:putty</citation> provides 19.579 + a complete suite of ssh client commands. 19.580 +</para> 19.581 +</listitem> 19.582 +<listitem><para>If you have a high tolerance for pain, you can use the Cygwin 19.583 + port of OpenSSH. 19.584 +</para> 19.585 +</listitem></itemizedlist> 19.586 +<para>In either case, you'll need to edit your \hgini\ file to tell 19.587 +Mercurial where to find the actual client command. For example, if 19.588 +you're using PuTTY, you'll need to use the <command>plink</command> command as 19.589 +a command-line ssh client. 19.590 +</para> 19.591 +<programlisting> 19.592 +<para> [ui] 19.593 + ssh = C:/path/to/plink.exe -ssh -i "C:/path/to/my/private/key" 19.594 +</para> 19.595 +</programlisting> 19.596 + 19.597 +<note> 19.598 +<para> The path to <command>plink</command> shouldn't contain any whitespace 19.599 + characters, or Mercurial may not be able to run it correctly (so 19.600 + putting it in <filename class="directory">C:\\Program Files</filename> is probably not a good 19.601 + idea). 19.602 +</para> 19.603 +</note> 19.604 + 19.605 +</sect2> 19.606 +<sect2> 19.607 +<title>Generating a key pair</title> 19.608 + 19.609 +<para>To avoid the need to repetitively type a password every time you need 19.610 +to use your ssh client, I recommend generating a key pair. On a 19.611 +Unix-like system, the <command>ssh-keygen</command> command will do the trick. 19.612 +On Windows, if you're using PuTTY, the <command>puttygen</command> command is 19.613 +what you'll need. 19.614 +</para> 19.615 + 19.616 +<para>When you generate a key pair, it's usually <emphasis>highly</emphasis> advisable to 19.617 +protect it with a passphrase. (The only time that you might not want 19.618 +to do this is when you're using the ssh protocol for automated tasks 19.619 +on a secure network.) 19.620 +</para> 19.621 + 19.622 +<para>Simply generating a key pair isn't enough, however. You'll need to 19.623 +add the public key to the set of authorised keys for whatever user 19.624 +you're logging in remotely as. For servers using OpenSSH (the vast 19.625 +majority), this will mean adding the public key to a list in a file 19.626 +called <filename role="special">authorized_keys</filename> in their <filename role="special" class="directory">.ssh</filename> 19.627 +directory. 19.628 +</para> 19.629 + 19.630 +<para>On a Unix-like system, your public key will have a <filename>.pub</filename> 19.631 +extension. If you're using <command>puttygen</command> on Windows, you can 19.632 +save the public key to a file of your choosing, or paste it from the 19.633 +window it's displayed in straight into the 19.634 +<filename role="special">authorized_keys</filename> file. 19.635 +</para> 19.636 + 19.637 +</sect2> 19.638 +<sect2> 19.639 +<title>Using an authentication agent</title> 19.640 + 19.641 +<para>An authentication agent is a daemon that stores passphrases in memory 19.642 +(so it will forget passphrases if you log out and log back in again). 19.643 +An ssh client will notice if it's running, and query it for a 19.644 +passphrase. If there's no authentication agent running, or the agent 19.645 +doesn't store the necessary passphrase, you'll have to type your 19.646 +passphrase every time Mercurial tries to communicate with a server on 19.647 +your behalf (e.g. whenever you pull or push changes). 19.648 +</para> 19.649 + 19.650 +<para>The downside of storing passphrases in an agent is that it's possible 19.651 +for a well-prepared attacker to recover the plain text of your 19.652 +passphrases, in some cases even if your system has been power-cycled. 19.653 +You should make your own judgment as to whether this is an acceptable 19.654 +risk. It certainly saves a lot of repeated typing. 19.655 +</para> 19.656 + 19.657 +<para>On Unix-like systems, the agent is called <command>ssh-agent</command>, and 19.658 +it's often run automatically for you when you log in. You'll need to 19.659 +use the <command>ssh-add</command> command to add passphrases to the agent's 19.660 +store. On Windows, if you're using PuTTY, the <command>pageant</command> 19.661 +command acts as the agent. It adds an icon to your system tray that 19.662 +will let you manage stored passphrases. 19.663 +</para> 19.664 + 19.665 +</sect2> 19.666 +<sect2> 19.667 +<title>Configuring the server side properly</title> 19.668 + 19.669 +<para>Because ssh can be fiddly to set up if you're new to it, there's a 19.670 +variety of things that can go wrong. Add Mercurial on top, and 19.671 +there's plenty more scope for head-scratching. Most of these 19.672 +potential problems occur on the server side, not the client side. The 19.673 +good news is that once you've gotten a configuration working, it will 19.674 +usually continue to work indefinitely. 19.675 +</para> 19.676 + 19.677 +<para>Before you try using Mercurial to talk to an ssh server, it's best to 19.678 +make sure that you can use the normal <command>ssh</command> or <command>putty</command> 19.679 +command to talk to the server first. If you run into problems with 19.680 +using these commands directly, Mercurial surely won't work. Worse, it 19.681 +will obscure the underlying problem. Any time you want to debug 19.682 +ssh-related Mercurial problems, you should drop back to making sure 19.683 +that plain ssh client commands work first, <emphasis>before</emphasis> you worry 19.684 +about whether there's a problem with Mercurial. 19.685 +</para> 19.686 + 19.687 +<para>The first thing to be sure of on the server side is that you can 19.688 +actually log in from another machine at all. If you can't use 19.689 +<command>ssh</command> or <command>putty</command> to log in, the error message you get 19.690 +may give you a few hints as to what's wrong. The most common problems 19.691 +are as follows. 19.692 +</para> 19.693 +<itemizedlist> 19.694 +<listitem><para>If you get a <quote>connection refused</quote> error, either there isn't an 19.695 + SSH daemon running on the server at all, or it's inaccessible due to 19.696 + firewall configuration. 19.697 +</para> 19.698 +</listitem> 19.699 +<listitem><para>If you get a <quote>no route to host</quote> error, you either have an 19.700 + incorrect address for the server or a seriously locked down firewall 19.701 + that won't admit its existence at all. 19.702 +</para> 19.703 +</listitem> 19.704 +<listitem><para>If you get a <quote>permission denied</quote> error, you may have mistyped 19.705 + the username on the server, or you could have mistyped your key's 19.706 + passphrase or the remote user's password. 19.707 +</para> 19.708 +</listitem></itemizedlist> 19.709 +<para>In summary, if you're having trouble talking to the server's ssh 19.710 +daemon, first make sure that one is running at all. On many systems 19.711 +it will be installed, but disabled, by default. Once you're done with 19.712 +this step, you should then check that the server's firewall is 19.713 +configured to allow incoming connections on the port the ssh daemon is 19.714 +listening on (usually 22). Don't worry about more exotic 19.715 +possibilities for misconfiguration until you've checked these two 19.716 +first. 19.717 +</para> 19.718 + 19.719 +<para>If you're using an authentication agent on the client side to store 19.720 +passphrases for your keys, you ought to be able to log into the server 19.721 +without being prompted for a passphrase or a password. If you're 19.722 +prompted for a passphrase, there are a few possible culprits. 19.723 +</para> 19.724 +<itemizedlist> 19.725 +<listitem><para>You might have forgotten to use <command>ssh-add</command> or 19.726 + <command>pageant</command> to store the passphrase. 19.727 +</para> 19.728 +</listitem> 19.729 +<listitem><para>You might have stored the passphrase for the wrong key. 19.730 +</para> 19.731 +</listitem></itemizedlist> 19.732 +<para>If you're being prompted for the remote user's password, there are 19.733 +another few possible problems to check. 19.734 +</para> 19.735 +<itemizedlist> 19.736 +<listitem><para>Either the user's home directory or their <filename role="special" class="directory">.ssh</filename> 19.737 + directory might have excessively liberal permissions. As a result, 19.738 + the ssh daemon will not trust or read their 19.739 + <filename role="special">authorized_keys</filename> file. For example, a group-writable 19.740 + home or <filename role="special" class="directory">.ssh</filename> directory will often cause this symptom. 19.741 +</para> 19.742 +</listitem> 19.743 +<listitem><para>The user's <filename role="special">authorized_keys</filename> file may have a problem. 19.744 + If anyone other than the user owns or can write to that file, the 19.745 + ssh daemon will not trust or read it. 19.746 +</para> 19.747 +</listitem></itemizedlist> 19.748 + 19.749 +<para>In the ideal world, you should be able to run the following command 19.750 +successfully, and it should print exactly one line of output, the 19.751 +current date and time. 19.752 +</para> 19.753 +<programlisting> 19.754 +<para> ssh myserver date 19.755 +</para> 19.756 +</programlisting> 19.757 + 19.758 +<para>If, on your server, you have login scripts that print banners or other 19.759 +junk even when running non-interactive commands like this, you should 19.760 +fix them before you continue, so that they only print output if 19.761 +they're run interactively. Otherwise these banners will at least 19.762 +clutter up Mercurial's output. Worse, they could potentially cause 19.763 +problems with running Mercurial commands remotely. Mercurial makes 19.764 +tries to detect and ignore banners in non-interactive <command>ssh</command> 19.765 +sessions, but it is not foolproof. (If you're editing your login 19.766 +scripts on your server, the usual way to see if a login script is 19.767 +running in an interactive shell is to check the return code from the 19.768 +command <literal>tty -s</literal>.) 19.769 +</para> 19.770 + 19.771 +<para>Once you've verified that plain old ssh is working with your server, 19.772 +the next step is to ensure that Mercurial runs on the server. The 19.773 +following command should run successfully: 19.774 +</para> 19.775 +<programlisting> 19.776 +<para> ssh myserver hg version 19.777 +</para> 19.778 +</programlisting> 19.779 +<para>If you see an error message instead of normal <command role="hg-cmd">hg version</command> output, 19.780 +this is usually because you haven't installed Mercurial to 19.781 +<filename class="directory">/usr/bin</filename>. Don't worry if this is the case; you don't need 19.782 +to do that. But you should check for a few possible problems. 19.783 +</para> 19.784 +<itemizedlist> 19.785 +<listitem><para>Is Mercurial really installed on the server at all? I know this 19.786 + sounds trivial, but it's worth checking! 19.787 +</para> 19.788 +</listitem> 19.789 +<listitem><para>Maybe your shell's search path (usually set via the <envar>PATH</envar> 19.790 + environment variable) is simply misconfigured. 19.791 +</para> 19.792 +</listitem> 19.793 +<listitem><para>Perhaps your <envar>PATH</envar> environment variable is only being set 19.794 + to point to the location of the <command>hg</command> executable if the login 19.795 + session is interactive. This can happen if you're setting the path 19.796 + in the wrong shell login script. See your shell's documentation for 19.797 + details. 19.798 +</para> 19.799 +</listitem> 19.800 +<listitem><para>The <envar>PYTHONPATH</envar> environment variable may need to contain 19.801 + the path to the Mercurial Python modules. It might not be set at 19.802 + all; it could be incorrect; or it may be set only if the login is 19.803 + interactive. 19.804 +</para> 19.805 +</listitem></itemizedlist> 19.806 + 19.807 +<para>If you can run <command role="hg-cmd">hg version</command> over an ssh connection, well done! 19.808 +You've got the server and client sorted out. You should now be able 19.809 +to use Mercurial to access repositories hosted by that username on 19.810 +that server. If you run into problems with Mercurial and ssh at this 19.811 +point, try using the <option role="hg-opt-global">--debug</option> option to get a clearer picture 19.812 +of what's going on. 19.813 +</para> 19.814 + 19.815 +</sect2> 19.816 +<sect2> 19.817 +<title>Using compression with ssh</title> 19.818 + 19.819 +<para>Mercurial does not compress data when it uses the ssh protocol, 19.820 +because the ssh protocol can transparently compress data. However, 19.821 +the default behaviour of ssh clients is <emphasis>not</emphasis> to request 19.822 +compression. 19.823 +</para> 19.824 + 19.825 +<para>Over any network other than a fast LAN (even a wireless network), 19.826 +using compression is likely to significantly speed up Mercurial's 19.827 +network operations. For example, over a WAN, someone measured 19.828 +compression as reducing the amount of time required to clone a 19.829 +particularly large repository from 51 minutes to 17 minutes. 19.830 +</para> 19.831 + 19.832 +<para>Both <command>ssh</command> and <command>plink</command> accept a <option role="cmd-opt-ssh">-C</option> 19.833 +option which turns on compression. You can easily edit your <filename role="special"> /.hgrc</filename>\ to 19.834 +enable compression for all of Mercurial's uses of the ssh protocol. 19.835 +</para> 19.836 +<programlisting> 19.837 +<para> [ui] 19.838 + ssh = ssh -C 19.839 +</para> 19.840 +</programlisting> 19.841 + 19.842 +<para>If you use <command>ssh</command>, you can configure it to always use 19.843 +compression when talking to your server. To do this, edit your 19.844 +<filename role="special">.ssh/config</filename> file (which may not yet exist), as follows. 19.845 +</para> 19.846 +<programlisting> 19.847 +<para> Host hg 19.848 + Compression yes 19.849 + HostName hg.example.com 19.850 +</para> 19.851 +</programlisting> 19.852 +<para>This defines an alias, <literal>hg</literal>. When you use it on the 19.853 +<command>ssh</command> command line or in a Mercurial <literal>ssh</literal>-protocol 19.854 +URL, it will cause <command>ssh</command> to connect to <literal>hg.example.com</literal> 19.855 +and use compression. This gives you both a shorter name to type and 19.856 +compression, each of which is a good thing in its own right. 19.857 +</para> 19.858 + 19.859 +</sect2> 19.860 +</sect1> 19.861 +<sect1> 19.862 +<title>Serving over HTTP using CGI</title> 19.863 +<para>\label{sec:collab:cgi} 19.864 +</para> 19.865 + 19.866 +<para>Depending on how ambitious you are, configuring Mercurial's CGI 19.867 +interface can take anything from a few moments to several hours. 19.868 +</para> 19.869 + 19.870 +<para>We'll begin with the simplest of examples, and work our way towards a 19.871 +more complex configuration. Even for the most basic case, you're 19.872 +almost certainly going to need to read and modify your web server's 19.873 +configuration. 19.874 +</para> 19.875 + 19.876 +<note> 19.877 +<para> Configuring a web server is a complex, fiddly, and highly 19.878 + system-dependent activity. I can't possibly give you instructions 19.879 + that will cover anything like all of the cases you will encounter. 19.880 + Please use your discretion and judgment in following the sections 19.881 + below. Be prepared to make plenty of mistakes, and to spend a lot 19.882 + of time reading your server's error logs. 19.883 +</para> 19.884 +</note> 19.885 + 19.886 +<sect2> 19.887 +<title>Web server configuration checklist</title> 19.888 + 19.889 +<para>Before you continue, do take a few moments to check a few aspects of 19.890 +your system's setup. 19.891 +</para> 19.892 + 19.893 +<orderedlist> 19.894 +<listitem><para>Do you have a web server installed at all? Mac OS X ships with 19.895 + Apache, but many other systems may not have a web server installed. 19.896 +</para> 19.897 +</listitem> 19.898 +<listitem><para>If you have a web server installed, is it actually running? On 19.899 + most systems, even if one is present, it will be disabled by 19.900 + default. 19.901 +</para> 19.902 +</listitem> 19.903 +<listitem><para>Is your server configured to allow you to run CGI programs in 19.904 + the directory where you plan to do so? Most servers default to 19.905 + explicitly disabling the ability to run CGI programs. 19.906 +</para> 19.907 +</listitem></orderedlist> 19.908 + 19.909 +<para>If you don't have a web server installed, and don't have substantial 19.910 +experience configuring Apache, you should consider using the 19.911 +<literal>lighttpd</literal> web server instead of Apache. Apache has a 19.912 +well-deserved reputation for baroque and confusing configuration. 19.913 +While <literal>lighttpd</literal> is less capable in some ways than Apache, most 19.914 +of these capabilities are not relevant to serving Mercurial 19.915 +repositories. And <literal>lighttpd</literal> is undeniably <emphasis>much</emphasis> easier 19.916 +to get started with than Apache. 19.917 +</para> 19.918 + 19.919 +</sect2> 19.920 +<sect2> 19.921 +<title>Basic CGI configuration</title> 19.922 + 19.923 +<para>On Unix-like systems, it's common for users to have a subdirectory 19.924 +named something like <filename class="directory">public_html</filename> in their home directory, 19.925 +from which they can serve up web pages. A file named <filename>foo</filename> 19.926 +in this directory will be accessible at a URL of the form 19.927 +<literal>http://www.example.com/\ {</literal>username/foo}. 19.928 +</para> 19.929 + 19.930 +<para>To get started, find the <filename role="special">hgweb.cgi</filename> script that should be 19.931 +present in your Mercurial installation. If you can't quickly find a 19.932 +local copy on your system, simply download one from the master 19.933 +Mercurial repository at 19.934 +<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>. 19.935 +</para> 19.936 + 19.937 +<para>You'll need to copy this script into your <filename class="directory">public_html</filename> 19.938 +directory, and ensure that it's executable. 19.939 +</para> 19.940 +<programlisting> 19.941 +<para> cp .../hgweb.cgi /public_html 19.942 + chmod 755 /public_html/hgweb.cgi 19.943 +</para> 19.944 +</programlisting> 19.945 +<para>The <literal>755</literal> argument to <command>chmod</command> is a little more general 19.946 +than just making the script executable: it ensures that the script is 19.947 +executable by anyone, and that <quote>group</quote> and <quote>other</quote> write 19.948 +permissions are <emphasis>not</emphasis> set. If you were to leave those write 19.949 +permissions enabled, Apache's <literal>suexec</literal> subsystem would likely 19.950 +refuse to execute the script. In fact, <literal>suexec</literal> also insists 19.951 +that the <emphasis>directory</emphasis> in which the script resides must not be 19.952 +writable by others. 19.953 +</para> 19.954 +<programlisting> 19.955 +<para> chmod 755 /public_html 19.956 +</para> 19.957 +</programlisting> 19.958 + 19.959 +<sect3> 19.960 +<title>What could <emphasis>possibly</emphasis> go wrong?</title> 19.961 +<para>\label{sec:collab:wtf} 19.962 +</para> 19.963 + 19.964 +<para>Once you've copied the CGI script into place, go into a web browser, 19.965 +and try to open the URL <ulink url="http://myhostname/ myuser/hgweb.cgi">http://myhostname/ myuser/hgweb.cgi</ulink>, 19.966 +<emphasis>but</emphasis> brace yourself for instant failure. There's a high 19.967 +probability that trying to visit this URL will fail, and there are 19.968 +many possible reasons for this. In fact, you're likely to stumble 19.969 +over almost every one of the possible errors below, so please read 19.970 +carefully. The following are all of the problems I ran into on a 19.971 +system running Fedora 7, with a fresh installation of Apache, and a 19.972 +user account that I created specially to perform this exercise. 19.973 +</para> 19.974 + 19.975 +<para>Your web server may have per-user directories disabled. If you're 19.976 +using Apache, search your config file for a <literal>UserDir</literal> 19.977 +directive. If there's none present, per-user directories will be 19.978 +disabled. If one exists, but its value is <literal>disabled</literal>, then 19.979 +per-user directories will be disabled. Otherwise, the string after 19.980 +<literal>UserDir</literal> gives the name of the subdirectory that Apache will 19.981 +look in under your home directory, for example <filename class="directory">public_html</filename>. 19.982 +</para> 19.983 + 19.984 +<para>Your file access permissions may be too restrictive. The web server 19.985 +must be able to traverse your home directory and directories under 19.986 +your <filename class="directory">public_html</filename> directory, and read files under the latter 19.987 +too. Here's a quick recipe to help you to make your permissions more 19.988 +appropriate. 19.989 +</para> 19.990 +<programlisting> 19.991 +<para> chmod 755 19.992 + find /public_html -type d -print0 | xargs -0r chmod 755 19.993 + find /public_html -type f -print0 | xargs -0r chmod 644 19.994 +</para> 19.995 +</programlisting> 19.996 + 19.997 +<para>The other possibility with permissions is that you might get a 19.998 +completely empty window when you try to load the script. In this 19.999 +case, it's likely that your access permissions are \emph{too 19.1000 + permissive}. Apache's <literal>suexec</literal> subsystem won't execute a 19.1001 +script that's group- or world-writable, for example. 19.1002 +</para> 19.1003 + 19.1004 +<para>Your web server may be configured to disallow execution of CGI 19.1005 +programs in your per-user web directory. Here's Apache's 19.1006 +default per-user configuration from my Fedora system. 19.1007 +</para> 19.1008 +<programlisting> 19.1009 +<para> <Directory /home/*/public_html> 19.1010 + AllowOverride FileInfo AuthConfig Limit 19.1011 + Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec 19.1012 + <Limit GET POST OPTIONS> 19.1013 + Order allow,deny 19.1014 + Allow from all 19.1015 + </Limit> 19.1016 + <LimitExcept GET POST OPTIONS> 19.1017 + Order deny,allow 19.1018 + Deny from all 19.1019 + </LimitExcept> 19.1020 + </Directory> 19.1021 +</para> 19.1022 +</programlisting> 19.1023 +<para>If you find a similar-looking <literal>Directory</literal> group in your Apache 19.1024 +configuration, the directive to look at inside it is <literal>Options</literal>. 19.1025 +Add <literal>ExecCGI</literal> to the end of this list if it's missing, and 19.1026 +restart the web server. 19.1027 +</para> 19.1028 + 19.1029 +<para>If you find that Apache serves you the text of the CGI script instead 19.1030 +of executing it, you may need to either uncomment (if already present) 19.1031 +or add a directive like this. 19.1032 +</para> 19.1033 +<programlisting> 19.1034 +<para> AddHandler cgi-script .cgi 19.1035 +</para> 19.1036 +</programlisting> 19.1037 + 19.1038 +<para>The next possibility is that you might be served with a colourful 19.1039 +Python backtrace claiming that it can't import a 19.1040 +<literal>mercurial</literal>-related module. This is actually progress! The 19.1041 +server is now capable of executing your CGI script. This error is 19.1042 +only likely to occur if you're running a private installation of 19.1043 +Mercurial, instead of a system-wide version. Remember that the web 19.1044 +server runs the CGI program without any of the environment variables 19.1045 +that you take for granted in an interactive session. If this error 19.1046 +happens to you, edit your copy of <filename role="special">hgweb.cgi</filename> and follow the 19.1047 +directions inside it to correctly set your <envar>PYTHONPATH</envar> 19.1048 +environment variable. 19.1049 +</para> 19.1050 + 19.1051 +<para>Finally, you are <emphasis>certain</emphasis> to by served with another colourful 19.1052 +Python backtrace: this one will complain that it can't find 19.1053 +<filename class="directory">/path/to/repository</filename>. Edit your <filename role="special">hgweb.cgi</filename> script 19.1054 +and replace the <filename class="directory">/path/to/repository</filename> string with the complete 19.1055 +path to the repository you want to serve up. 19.1056 +</para> 19.1057 + 19.1058 +<para>At this point, when you try to reload the page, you should be 19.1059 +presented with a nice HTML view of your repository's history. Whew! 19.1060 +</para> 19.1061 + 19.1062 +</sect3> 19.1063 +<sect3> 19.1064 +<title>Configuring lighttpd</title> 19.1065 + 19.1066 +<para>To be exhaustive in my experiments, I tried configuring the 19.1067 +increasingly popular <literal>lighttpd</literal> web server to serve the same 19.1068 +repository as I described with Apache above. I had already overcome 19.1069 +all of the problems I outlined with Apache, many of which are not 19.1070 +server-specific. As a result, I was fairly sure that my file and 19.1071 +directory permissions were good, and that my <filename role="special">hgweb.cgi</filename> 19.1072 +script was properly edited. 19.1073 +</para> 19.1074 + 19.1075 +<para>Once I had Apache running, getting <literal>lighttpd</literal> to serve the 19.1076 +repository was a snap (in other words, even if you're trying to use 19.1077 +<literal>lighttpd</literal>, you should read the Apache section). I first had 19.1078 +to edit the <literal>mod_access</literal> section of its config file to enable 19.1079 +<literal>mod_cgi</literal> and <literal>mod_userdir</literal>, both of which were 19.1080 +disabled by default on my system. I then added a few lines to the end 19.1081 +of the config file, to configure these modules. 19.1082 +</para> 19.1083 +<programlisting> 19.1084 +<para> userdir.path = "public_html" 19.1085 + cgi.assign = ( ".cgi" => "" ) 19.1086 +</para> 19.1087 +</programlisting> 19.1088 +<para>With this done, <literal>lighttpd</literal> ran immediately for me. If I had 19.1089 +configured <literal>lighttpd</literal> before Apache, I'd almost certainly have 19.1090 +run into many of the same system-level configuration problems as I did 19.1091 +with Apache. However, I found <literal>lighttpd</literal> to be noticeably 19.1092 +easier to configure than Apache, even though I've used Apache for over 19.1093 +a decade, and this was my first exposure to <literal>lighttpd</literal>. 19.1094 +</para> 19.1095 + 19.1096 +</sect3> 19.1097 +</sect2> 19.1098 +<sect2> 19.1099 +<title>Sharing multiple repositories with one CGI script</title> 19.1100 + 19.1101 +<para>The <filename role="special">hgweb.cgi</filename> script only lets you publish a single 19.1102 +repository, which is an annoying restriction. If you want to publish 19.1103 +more than one without wracking yourself with multiple copies of the 19.1104 +same script, each with different names, a better choice is to use the 19.1105 +<filename role="special">hgwebdir.cgi</filename> script. 19.1106 +</para> 19.1107 + 19.1108 +<para>The procedure to configure <filename role="special">hgwebdir.cgi</filename> is only a little 19.1109 +more involved than for <filename role="special">hgweb.cgi</filename>. First, you must obtain 19.1110 +a copy of the script. If you don't have one handy, you can download a 19.1111 +copy from the master Mercurial repository at 19.1112 +<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>. 19.1113 +</para> 19.1114 + 19.1115 +<para>You'll need to copy this script into your <filename class="directory">public_html</filename> 19.1116 +directory, and ensure that it's executable. 19.1117 +</para> 19.1118 +<programlisting> 19.1119 +<para> cp .../hgwebdir.cgi /public_html 19.1120 + chmod 755 /public_html /public_html/hgwebdir.cgi 19.1121 +</para> 19.1122 +</programlisting> 19.1123 +<para>With basic configuration out of the way, try to visit 19.1124 +<ulink url="http://myhostname/ myuser/hgwebdir.cgi">http://myhostname/ myuser/hgwebdir.cgi</ulink> in your browser. It 19.1125 +should display an empty list of repositories. If you get a blank 19.1126 +window or error message, try walking through the list of potential 19.1127 +problems in section <xref linkend="sec:collab:wtf"/>. 19.1128 +</para> 19.1129 + 19.1130 +<para>The <filename role="special">hgwebdir.cgi</filename> script relies on an external 19.1131 +configuration file. By default, it searches for a file named 19.1132 +<filename role="special">hgweb.config</filename> in the same directory as itself. You'll need 19.1133 +to create this file, and make it world-readable. The format of the 19.1134 +file is similar to a Windows <quote>ini</quote> file, as understood by Python's 19.1135 +<literal>ConfigParser</literal> <citation>web:configparser</citation> module. 19.1136 +</para> 19.1137 + 19.1138 +<para>The easiest way to configure <filename role="special">hgwebdir.cgi</filename> is with a 19.1139 +section named <literal>collections</literal>. This will automatically publish 19.1140 +<emphasis>every</emphasis> repository under the directories you name. The section 19.1141 +should look like this: 19.1142 +</para> 19.1143 +<programlisting> 19.1144 +<para> [collections] 19.1145 + /my/root = /my/root 19.1146 +</para> 19.1147 +</programlisting> 19.1148 +<para>Mercurial interprets this by looking at the directory name on the 19.1149 +<emphasis>right</emphasis> hand side of the <quote><literal>=</literal></quote> sign; finding 19.1150 +repositories in that directory hierarchy; and using the text on the 19.1151 +<emphasis>left</emphasis> to strip off matching text from the names it will actually 19.1152 +list in the web interface. The remaining component of a path after 19.1153 +this stripping has occurred is called a <quote>virtual path</quote>. 19.1154 +</para> 19.1155 + 19.1156 +<para>Given the example above, if we have a repository whose local path is 19.1157 +<filename class="directory">/my/root/this/repo</filename>, the CGI script will strip the leading 19.1158 +<filename class="directory">/my/root</filename> from the name, and publish the repository with a 19.1159 +virtual path of <filename class="directory">this/repo</filename>. If the base URL for our CGI 19.1160 +script is <ulink url="http://myhostname/ myuser/hgwebdir.cgi">http://myhostname/ myuser/hgwebdir.cgi</ulink>, the complete 19.1161 +URL for that repository will be 19.1162 +<ulink url="http://myhostname/ myuser/hgwebdir.cgi/this/repo">http://myhostname/ myuser/hgwebdir.cgi/this/repo</ulink>. 19.1163 +</para> 19.1164 + 19.1165 +<para>If we replace <filename class="directory">/my/root</filename> on the left hand side of this example 19.1166 +with <filename class="directory">/my</filename>, then <filename role="special">hgwebdir.cgi</filename> will only strip off 19.1167 +<filename class="directory">/my</filename> from the repository name, and will give us a virtual 19.1168 +path of <filename class="directory">root/this/repo</filename> instead of <filename class="directory">this/repo</filename>. 19.1169 +</para> 19.1170 + 19.1171 +<para>The <filename role="special">hgwebdir.cgi</filename> script will recursively search each 19.1172 +directory listed in the <literal>collections</literal> section of its 19.1173 +configuration file, but it will <literal>not</literal> recurse into the 19.1174 +repositories it finds. 19.1175 +</para> 19.1176 + 19.1177 +<para>The <literal>collections</literal> mechanism makes it easy to publish many 19.1178 +repositories in a <quote>fire and forget</quote> manner. You only need to set up 19.1179 +the CGI script and configuration file one time. Afterwards, you can 19.1180 +publish or unpublish a repository at any time by simply moving it 19.1181 +into, or out of, the directory hierarchy in which you've configured 19.1182 +<filename role="special">hgwebdir.cgi</filename> to look. 19.1183 +</para> 19.1184 + 19.1185 +<sect3> 19.1186 +<title>Explicitly specifying which repositories to publish</title> 19.1187 + 19.1188 +<para>In addition to the <literal>collections</literal> mechanism, the 19.1189 +<filename role="special">hgwebdir.cgi</filename> script allows you to publish a specific list 19.1190 +of repositories. To do so, create a <literal>paths</literal> section, with 19.1191 +contents of the following form. 19.1192 +</para> 19.1193 +<programlisting> 19.1194 +<para> [paths] 19.1195 + repo1 = /my/path/to/some/repo 19.1196 + repo2 = /some/path/to/another 19.1197 +</para> 19.1198 +</programlisting> 19.1199 +<para>In this case, the virtual path (the component that will appear in a 19.1200 +URL) is on the left hand side of each definition, while the path to 19.1201 +the repository is on the right. Notice that there does not need to be 19.1202 +any relationship between the virtual path you choose and the location 19.1203 +of a repository in your filesystem. 19.1204 +</para> 19.1205 + 19.1206 +<para>If you wish, you can use both the <literal>collections</literal> and 19.1207 +<literal>paths</literal> mechanisms simultaneously in a single configuration 19.1208 +file. 19.1209 +</para> 19.1210 + 19.1211 +<note> 19.1212 +<para> If multiple repositories have the same virtual path, 19.1213 + <filename role="special">hgwebdir.cgi</filename> will not report an error. Instead, it will 19.1214 + behave unpredictably. 19.1215 +</para> 19.1216 +</note> 19.1217 + 19.1218 +</sect3> 19.1219 +</sect2> 19.1220 +<sect2> 19.1221 +<title>Downloading source archives</title> 19.1222 + 19.1223 +<para>Mercurial's web interface lets users download an archive of any 19.1224 +revision. This archive will contain a snapshot of the working 19.1225 +directory as of that revision, but it will not contain a copy of the 19.1226 +repository data. 19.1227 +</para> 19.1228 + 19.1229 +<para>By default, this feature is not enabled. To enable it, you'll need to 19.1230 +add an <envar role="rc-item-web">allow_archive</envar> item to the <literal role="rc-web">web</literal> 19.1231 +section of your <filename role="special"> /.hgrc</filename>. 19.1232 +</para> 19.1233 + 19.1234 +</sect2> 19.1235 +<sect2> 19.1236 +<title>Web configuration options</title> 19.1237 + 19.1238 +<para>Mercurial's web interfaces (the <command role="hg-cmd">hg serve</command> command, and the 19.1239 +<filename role="special">hgweb.cgi</filename> and <filename role="special">hgwebdir.cgi</filename> scripts) have a 19.1240 +number of configuration options that you can set. These belong in a 19.1241 +section named <literal role="rc-web">web</literal>. 19.1242 +</para> 19.1243 +<itemizedlist> 19.1244 +<listitem><para><envar role="rc-item-web">allow_archive</envar>: Determines which (if any) archive 19.1245 + download mechanisms Mercurial supports. If you enable this 19.1246 + feature, users of the web interface will be able to download an 19.1247 + archive of whatever revision of a repository they are viewing. 19.1248 + To enable the archive feature, this item must take the form of a 19.1249 + sequence of words drawn from the list below. 19.1250 +</para> 19.1251 +</listitem><itemizedlist> 19.1252 +<listitem><para> \item <literal>bz2</literal>: A <command>tar</command> archive, compressed using 19.1253 + <literal>bzip2</literal> compression. This has the best compression ratio, 19.1254 + but uses the most CPU time on the server. 19.1255 + \item <literal>gz</literal>: A <command>tar</command> archive, compressed using 19.1256 + <literal>gzip</literal> compression. 19.1257 + \item <literal>zip</literal>: A <command>zip</command> archive, compressed using LZW 19.1258 + compression. This format has the worst compression ratio, but is 19.1259 + widely used in the Windows world. 19.1260 +</para> 19.1261 +</listitem></itemizedlist> 19.1262 +<para> If you provide an empty list, or don't have an 19.1263 + <envar role="rc-item-web">allow_archive</envar> entry at all, this feature will be 19.1264 + disabled. Here is an example of how to enable all three supported 19.1265 + formats. 19.1266 +</para> 19.1267 +<programlisting> 19.1268 +<para> [web] 19.1269 + allow_archive = bz2 gz zip 19.1270 +</para> 19.1271 +</programlisting> 19.1272 +<listitem><para><envar role="rc-item-web">allowpull</envar>: Boolean. Determines whether the web 19.1273 + interface allows remote users to <command role="hg-cmd">hg pull</command> and <command role="hg-cmd">hg clone</command> this 19.1274 + repository over HTTP. If set to <literal>no</literal> or <literal>false</literal>, only 19.1275 + the <quote>human-oriented</quote> portion of the web interface is available. 19.1276 +</para> 19.1277 +</listitem> 19.1278 +<listitem><para><envar role="rc-item-web">contact</envar>: String. A free-form (but preferably 19.1279 + brief) string identifying the person or group in charge of the 19.1280 + repository. This often contains the name and email address of a 19.1281 + person or mailing list. It often makes sense to place this entry in 19.1282 + a repository's own <filename role="special">.hg/hgrc</filename> file, but it can make sense 19.1283 + to use in a global <filename role="special"> /.hgrc</filename>\ if every repository has a single 19.1284 + maintainer. 19.1285 +</para> 19.1286 +</listitem> 19.1287 +<listitem><para><envar role="rc-item-web">maxchanges</envar>: Integer. The default maximum number 19.1288 + of changesets to display in a single page of output. 19.1289 +</para> 19.1290 +</listitem> 19.1291 +<listitem><para><envar role="rc-item-web">maxfiles</envar>: Integer. The default maximum number 19.1292 + of modified files to display in a single page of output. 19.1293 +</para> 19.1294 +</listitem> 19.1295 +<listitem><para><envar role="rc-item-web">stripes</envar>: Integer. If the web interface displays 19.1296 + alternating <quote>stripes</quote> to make it easier to visually align rows 19.1297 + when you are looking at a table, this number controls the number of 19.1298 + rows in each stripe. 19.1299 +</para> 19.1300 +</listitem> 19.1301 +<listitem><para><envar role="rc-item-web">style</envar>: Controls the template Mercurial uses to 19.1302 + display the web interface. Mercurial ships with two web templates, 19.1303 + named <literal>default</literal> and <literal>gitweb</literal> (the latter is much more 19.1304 + visually attractive). You can also specify a custom template of 19.1305 + your own; see chapter <xref linkend="chap:template"/> for details. Here, you 19.1306 + can see how to enable the <literal>gitweb</literal> style. 19.1307 +</para> 19.1308 +</listitem><programlisting> 19.1309 +<listitem><para> [web] 19.1310 + style = gitweb 19.1311 +</para> 19.1312 +</listitem></programlisting> 19.1313 +</para> 19.1314 +</listitem> 19.1315 +<listitem><para><envar role="rc-item-web">templates</envar>: Path. The directory in which to search 19.1316 + for template files. By default, Mercurial searches in the directory 19.1317 + in which it was installed. 19.1318 +</para> 19.1319 +</listitem></itemizedlist> 19.1320 +<para>If you are using <filename role="special">hgwebdir.cgi</filename>, you can place a few 19.1321 +configuration items in a <literal role="rc-web">web</literal> section of the 19.1322 +<filename role="special">hgweb.config</filename> file instead of a <filename role="special"> /.hgrc</filename>\ file, for 19.1323 +convenience. These items are <envar role="rc-item-web">motd</envar> and 19.1324 +<envar role="rc-item-web">style</envar>. 19.1325 +</para> 19.1326 + 19.1327 +<sect3> 19.1328 +<title>Options specific to an individual repository</title> 19.1329 + 19.1330 +<para>A few <literal role="rc-web">web</literal> configuration items ought to be placed in a 19.1331 +repository's local <filename role="special">.hg/hgrc</filename>, rather than a user's or 19.1332 +global <filename role="special"> /.hgrc</filename>. 19.1333 +</para> 19.1334 +<itemizedlist> 19.1335 +<listitem><para><envar role="rc-item-web">description</envar>: String. A free-form (but preferably 19.1336 + brief) string that describes the contents or purpose of the 19.1337 + repository. 19.1338 +</para> 19.1339 +</listitem> 19.1340 +<listitem><para><envar role="rc-item-web">name</envar>: String. The name to use for the repository 19.1341 + in the web interface. This overrides the default name, which is the 19.1342 + last component of the repository's path. 19.1343 +</para> 19.1344 +</listitem></itemizedlist> 19.1345 + 19.1346 +</sect3> 19.1347 +<sect3> 19.1348 +<title>Options specific to the <command role="hg-cmd">hg serve</command> command</title> 19.1349 + 19.1350 +<para>Some of the items in the <literal role="rc-web">web</literal> section of a <filename role="special"> /.hgrc</filename>\ file are 19.1351 +only for use with the <command role="hg-cmd">hg serve</command> command. 19.1352 +</para> 19.1353 +<itemizedlist> 19.1354 +<listitem><para><envar role="rc-item-web">accesslog</envar>: Path. The name of a file into which to 19.1355 + write an access log. By default, the <command role="hg-cmd">hg serve</command> command writes 19.1356 + this information to standard output, not to a file. Log entries are 19.1357 + written in the standard <quote>combined</quote> file format used by almost all 19.1358 + web servers. 19.1359 +</para> 19.1360 +</listitem> 19.1361 +<listitem><para><envar role="rc-item-web">address</envar>: String. The local address on which the 19.1362 + server should listen for incoming connections. By default, the 19.1363 + server listens on all addresses. 19.1364 +</para> 19.1365 +</listitem> 19.1366 +<listitem><para><envar role="rc-item-web">errorlog</envar>: Path. The name of a file into which to 19.1367 + write an error log. By default, the <command role="hg-cmd">hg serve</command> command writes this 19.1368 + information to standard error, not to a file. 19.1369 +</para> 19.1370 +</listitem> 19.1371 +<listitem><para><envar role="rc-item-web">ipv6</envar>: Boolean. Whether to use the IPv6 protocol. 19.1372 + By default, IPv6 is not used. 19.1373 +</para> 19.1374 +</listitem> 19.1375 +<listitem><para><envar role="rc-item-web">port</envar>: Integer. The TCP port number on which the 19.1376 + server should listen. The default port number used is 8000. 19.1377 +</para> 19.1378 +</listitem></itemizedlist> 19.1379 + 19.1380 +<para>\subsubsection{Choosing the right <filename role="special"> /.hgrc</filename>\ file to add <literal role="rc-web">web</literal> 19.1381 + items to} 19.1382 +</para> 19.1383 + 19.1384 +<para>It is important to remember that a web server like Apache or 19.1385 +<literal>lighttpd</literal> will run under a user ID that is different to yours. 19.1386 +CGI scripts run by your server, such as <filename role="special">hgweb.cgi</filename>, will 19.1387 +usually also run under that user ID. 19.1388 +</para> 19.1389 + 19.1390 +<para>If you add <literal role="rc-web">web</literal> items to your own personal <filename role="special"> /.hgrc</filename>\ file, CGI 19.1391 +scripts won't read that <filename role="special"> /.hgrc</filename>\ file. Those settings will thus only 19.1392 +affect the behaviour of the <command role="hg-cmd">hg serve</command> command when you run it. To 19.1393 +cause CGI scripts to see your settings, either create a <filename role="special"> /.hgrc</filename>\ file in 19.1394 +the home directory of the user ID that runs your web server, or add 19.1395 +those settings to a system-wide <filename role="special"> /.hgrc</filename>\ file. 19.1396 +</para> 19.1397 + 19.1398 + 19.1399 +</sect3> 19.1400 +</sect2> 19.1401 +</sect1> 19.1402 +</chapter> 19.1403 + 19.1404 +<!-- 19.1405 +local variables: 19.1406 +sgml-parent-document: ("00book.xml" "book" "chapter") 19.1407 +end: 19.1408 +--> 19.1409 \ No newline at end of file
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 20.2 +++ b/fr/ch07-filenames.xml Sun Aug 16 04:58:01 2009 +0200 20.3 @@ -0,0 +1,388 @@ 20.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 20.5 + 20.6 +<chapter> 20.7 +<title>File names and pattern matching</title> 20.8 +<para>\label{chap:names}</para> 20.9 + 20.10 +<para>Mercurial provides mechanisms that let you work with file names in a 20.11 +consistent and expressive way.</para> 20.12 + 20.13 +<sect1> 20.14 +<title>Simple file naming</title> 20.15 + 20.16 +<para>Mercurial uses a unified piece of machinery <quote>under the hood</quote> to 20.17 +handle file names. Every command behaves uniformly with respect to 20.18 +file names. The way in which commands work with file names is as 20.19 +follows.</para> 20.20 + 20.21 +<para>If you explicitly name real files on the command line, Mercurial works 20.22 +with exactly those files, as you would expect. 20.23 +<!-- &interaction.filenames.files; --></para> 20.24 + 20.25 +<para>When you provide a directory name, Mercurial will interpret this as 20.26 +<quote>operate on every file in this directory and its subdirectories</quote>. 20.27 +Mercurial traverses the files and subdirectories in a directory in 20.28 +alphabetical order. When it encounters a subdirectory, it will 20.29 +traverse that subdirectory before continuing with the current 20.30 +directory. 20.31 +<!-- &interaction.filenames.dirs; --></para> 20.32 + 20.33 +</sect1> 20.34 +<sect1> 20.35 +<title>Running commands without any file names</title> 20.36 + 20.37 +<para>Mercurial's commands that work with file names have useful default 20.38 +behaviours when you invoke them without providing any file names or 20.39 +patterns. What kind of behaviour you should expect depends on what 20.40 +the command does. Here are a few rules of thumb you can use to 20.41 +predict what a command is likely to do if you don't give it any names 20.42 +to work with.</para> 20.43 +<itemizedlist> 20.44 +<listitem><para>Most commands will operate on the entire working directory. 20.45 + This is what the <command role="hg-cmd">hg add</command> command does, for example.</para> 20.46 +</listitem> 20.47 +<listitem><para>If the command has effects that are difficult or impossible to 20.48 + reverse, it will force you to explicitly provide at least one name 20.49 + or pattern (see below). This protects you from accidentally 20.50 + deleting files by running <command role="hg-cmd">hg remove</command> with no arguments, for 20.51 + example.</para> 20.52 +</listitem></itemizedlist> 20.53 + 20.54 +<para>It's easy to work around these default behaviours if they don't suit 20.55 +you. If a command normally operates on the whole working directory, 20.56 +you can invoke it on just the current directory and its subdirectories 20.57 +by giving it the name <quote><filename class="directory">.</filename></quote>. 20.58 +<!-- &interaction.filenames.wdir-subdir; --> 20.59 +</para> 20.60 + 20.61 +<para>Along the same lines, some commands normally print file names relative 20.62 +to the root of the repository, even if you're invoking them from a 20.63 +subdirectory. Such a command will print file names relative to your 20.64 +subdirectory if you give it explicit names. Here, we're going to run 20.65 +<command role="hg-cmd">hg status</command> from a subdirectory, and get it to operate on the 20.66 +entire working directory while printing file names relative to our 20.67 +subdirectory, by passing it the output of the <command role="hg-cmd">hg root</command> command. 20.68 +<!-- &interaction.filenames.wdir-relname; --> 20.69 +</para> 20.70 + 20.71 +</sect1> 20.72 +<sect1> 20.73 +<title>Telling you what's going on</title> 20.74 + 20.75 +<para>The <command role="hg-cmd">hg add</command> example in the preceding section illustrates something 20.76 +else that's helpful about Mercurial commands. If a command operates 20.77 +on a file that you didn't name explicitly on the command line, it will 20.78 +usually print the name of the file, so that you will not be surprised 20.79 +what's going on. 20.80 +</para> 20.81 + 20.82 +<para>The principle here is of <emphasis>least surprise</emphasis>. If you've exactly 20.83 +named a file on the command line, there's no point in repeating it 20.84 +back at you. If Mercurial is acting on a file <emphasis>implicitly</emphasis>, 20.85 +because you provided no names, or a directory, or a pattern (see 20.86 +below), it's safest to tell you what it's doing. 20.87 +</para> 20.88 + 20.89 +<para>For commands that behave this way, you can silence them using the 20.90 +<option role="hg-opt-global">-q</option> option. You can also get them to print the name of every 20.91 +file, even those you've named explicitly, using the <option role="hg-opt-global">-v</option> 20.92 +option. 20.93 +</para> 20.94 + 20.95 +</sect1> 20.96 +<sect1> 20.97 +<title>Using patterns to identify files</title> 20.98 + 20.99 +<para>In addition to working with file and directory names, Mercurial lets 20.100 +you use <emphasis>patterns</emphasis> to identify files. Mercurial's pattern 20.101 +handling is expressive. 20.102 +</para> 20.103 + 20.104 +<para>On Unix-like systems (Linux, MacOS, etc.), the job of matching file 20.105 +names to patterns normally falls to the shell. On these systems, you 20.106 +must explicitly tell Mercurial that a name is a pattern. On Windows, 20.107 +the shell does not expand patterns, so Mercurial will automatically 20.108 +identify names that are patterns, and expand them for you. 20.109 +</para> 20.110 + 20.111 +<para>To provide a pattern in place of a regular name on the command line, 20.112 +the mechanism is simple: 20.113 +</para> 20.114 +<programlisting> 20.115 +<para> syntax:patternbody 20.116 +</para> 20.117 +</programlisting> 20.118 +<para>That is, a pattern is identified by a short text string that says what 20.119 +kind of pattern this is, followed by a colon, followed by the actual 20.120 +pattern. 20.121 +</para> 20.122 + 20.123 +<para>Mercurial supports two kinds of pattern syntax. The most frequently 20.124 +used is called <literal>glob</literal>; this is the same kind of pattern 20.125 +matching used by the Unix shell, and should be familiar to Windows 20.126 +command prompt users, too. 20.127 +</para> 20.128 + 20.129 +<para>When Mercurial does automatic pattern matching on Windows, it uses 20.130 +<literal>glob</literal> syntax. You can thus omit the <quote><literal>glob:</literal></quote> prefix 20.131 +on Windows, but it's safe to use it, too. 20.132 +</para> 20.133 + 20.134 +<para>The <literal>re</literal> syntax is more powerful; it lets you specify patterns 20.135 +using regular expressions, also known as regexps. 20.136 +</para> 20.137 + 20.138 +<para>By the way, in the examples that follow, notice that I'm careful to 20.139 +wrap all of my patterns in quote characters, so that they won't get 20.140 +expanded by the shell before Mercurial sees them. 20.141 +</para> 20.142 + 20.143 +<sect2> 20.144 +<title>Shell-style <literal>glob</literal> patterns</title> 20.145 + 20.146 +<para>This is an overview of the kinds of patterns you can use when you're 20.147 +matching on glob patterns. 20.148 +</para> 20.149 + 20.150 +<para>The <quote><literal>*</literal></quote> character matches any string, within a single 20.151 +directory. 20.152 +<!-- &interaction.filenames.glob.star; --> 20.153 +</para> 20.154 + 20.155 +<para>The <quote><literal>**</literal></quote> pattern matches any string, and crosses directory 20.156 +boundaries. It's not a standard Unix glob token, but it's accepted by 20.157 +several popular Unix shells, and is very useful. 20.158 +<!-- &interaction.filenames.glob.starstar; --> 20.159 +</para> 20.160 + 20.161 +<para>The <quote><literal>?</literal></quote> pattern matches any single character. 20.162 +<!-- &interaction.filenames.glob.question; --> 20.163 +</para> 20.164 + 20.165 +<para>The <quote><literal>[</literal></quote> character begins a <emphasis>character class</emphasis>. This 20.166 +matches any single character within the class. The class ends with a 20.167 +<quote><literal>]</literal></quote> character. A class may contain multiple <emphasis>range</emphasis>s 20.168 +of the form <quote><literal>a-f</literal></quote>, which is shorthand for 20.169 +<quote><literal>abcdef</literal></quote>. 20.170 +<!-- &interaction.filenames.glob.range; --> 20.171 +If the first character after the <quote><literal>[</literal></quote> in a character class 20.172 +is a <quote><literal>!</literal></quote>, it <emphasis>negates</emphasis> the class, making it match any 20.173 +single character not in the class. 20.174 +</para> 20.175 + 20.176 +<para>A <quote><literal>{</literal></quote> begins a group of subpatterns, where the whole group 20.177 +matches if any subpattern in the group matches. The <quote><literal>,</literal></quote> 20.178 +character separates subpatterns, and <quote>\texttt{}}</quote> ends the group. 20.179 +<!-- &interaction.filenames.glob.group; --> 20.180 +</para> 20.181 + 20.182 +<sect3> 20.183 +<title>Watch out!</title> 20.184 + 20.185 +<para>Don't forget that if you want to match a pattern in any directory, you 20.186 +should not be using the <quote><literal>*</literal></quote> match-any token, as this will 20.187 +only match within one directory. Instead, use the <quote><literal>**</literal></quote> 20.188 +token. This small example illustrates the difference between the two. 20.189 +<!-- &interaction.filenames.glob.star-starstar; --> 20.190 +</para> 20.191 + 20.192 +</sect3> 20.193 +</sect2> 20.194 +<sect2> 20.195 +<title>Regular expression matching with <literal>re</literal> patterns</title> 20.196 + 20.197 +<para>Mercurial accepts the same regular expression syntax as the Python 20.198 +programming language (it uses Python's regexp engine internally). 20.199 +This is based on the Perl language's regexp syntax, which is the most 20.200 +popular dialect in use (it's also used in Java, for example). 20.201 +</para> 20.202 + 20.203 +<para>I won't discuss Mercurial's regexp dialect in any detail here, as 20.204 +regexps are not often used. Perl-style regexps are in any case 20.205 +already exhaustively documented on a multitude of web sites, and in 20.206 +many books. Instead, I will focus here on a few things you should 20.207 +know if you find yourself needing to use regexps with Mercurial. 20.208 +</para> 20.209 + 20.210 +<para>A regexp is matched against an entire file name, relative to the root 20.211 +of the repository. In other words, even if you're already in 20.212 +subbdirectory <filename class="directory">foo</filename>, if you want to match files under this 20.213 +directory, your pattern must start with <quote><literal>foo/</literal></quote>. 20.214 +</para> 20.215 + 20.216 +<para>One thing to note, if you're familiar with Perl-style regexps, is that 20.217 +Mercurial's are <emphasis>rooted</emphasis>. That is, a regexp starts matching 20.218 +against the beginning of a string; it doesn't look for a match 20.219 +anywhere within the string. To match anywhere in a string, start 20.220 +your pattern with <quote><literal>.*</literal></quote>. 20.221 +</para> 20.222 + 20.223 +</sect2> 20.224 +</sect1> 20.225 +<sect1> 20.226 +<title>Filtering files</title> 20.227 + 20.228 +<para>Not only does Mercurial give you a variety of ways to specify files; 20.229 +it lets you further winnow those files using <emphasis>filters</emphasis>. Commands 20.230 +that work with file names accept two filtering options. 20.231 +</para> 20.232 +<itemizedlist> 20.233 +<listitem><para><option role="hg-opt-global">-I</option>, or <option role="hg-opt-global">--include</option>, lets you specify a pattern 20.234 + that file names must match in order to be processed. 20.235 +</para> 20.236 +</listitem> 20.237 +<listitem><para><option role="hg-opt-global">-X</option>, or <option role="hg-opt-global">--exclude</option>, gives you a way to 20.238 + <emphasis>avoid</emphasis> processing files, if they match this pattern. 20.239 +</para> 20.240 +</listitem></itemizedlist> 20.241 +<para>You can provide multiple <option role="hg-opt-global">-I</option> and <option role="hg-opt-global">-X</option> options on the 20.242 +command line, and intermix them as you please. Mercurial interprets 20.243 +the patterns you provide using glob syntax by default (but you can use 20.244 +regexps if you need to). 20.245 +</para> 20.246 + 20.247 +<para>You can read a <option role="hg-opt-global">-I</option> filter as <quote>process only the files that 20.248 +match this filter</quote>. 20.249 +<!-- &interaction.filenames.filter.include; --> 20.250 +The <option role="hg-opt-global">-X</option> filter is best read as <quote>process only the files that 20.251 +don't match this pattern</quote>. 20.252 +<!-- &interaction.filenames.filter.exclude; --> 20.253 +</para> 20.254 + 20.255 +</sect1> 20.256 +<sect1> 20.257 +<title>Ignoring unwanted files and directories</title> 20.258 + 20.259 +<para>XXX. 20.260 +</para> 20.261 + 20.262 +</sect1> 20.263 +<sect1> 20.264 +<title>Case sensitivity</title> 20.265 +<para>\label{sec:names:case} 20.266 +</para> 20.267 + 20.268 +<para>If you're working in a mixed development environment that contains 20.269 +both Linux (or other Unix) systems and Macs or Windows systems, you 20.270 +should keep in the back of your mind the knowledge that they treat the 20.271 +case (<quote>N</quote> versus <quote>n</quote>) of file names in incompatible ways. This is 20.272 +not very likely to affect you, and it's easy to deal with if it does, 20.273 +but it could surprise you if you don't know about it. 20.274 +</para> 20.275 + 20.276 +<para>Operating systems and filesystems differ in the way they handle the 20.277 +<emphasis>case</emphasis> of characters in file and directory names. There are 20.278 +three common ways to handle case in names. 20.279 +</para> 20.280 +<itemizedlist> 20.281 +<listitem><para>Completely case insensitive. Uppercase and lowercase versions 20.282 + of a letter are treated as identical, both when creating a file and 20.283 + during subsequent accesses. This is common on older DOS-based 20.284 + systems. 20.285 +</para> 20.286 +</listitem> 20.287 +<listitem><para>Case preserving, but insensitive. When a file or directory is 20.288 + created, the case of its name is stored, and can be retrieved and 20.289 + displayed by the operating system. When an existing file is being 20.290 + looked up, its case is ignored. This is the standard arrangement on 20.291 + Windows and MacOS. The names <filename>foo</filename> and <filename>FoO</filename> 20.292 + identify the same file. This treatment of uppercase and lowercase 20.293 + letters as interchangeable is also referred to as \emph{case 20.294 + folding}. 20.295 +</para> 20.296 +</listitem> 20.297 +<listitem><para>Case sensitive. The case of a name is significant at all times. 20.298 + The names <filename>foo</filename> and {FoO} identify different files. This 20.299 + is the way Linux and Unix systems normally work. 20.300 +</para> 20.301 +</listitem></itemizedlist> 20.302 + 20.303 +<para>On Unix-like systems, it is possible to have any or all of the above 20.304 +ways of handling case in action at once. For example, if you use a 20.305 +USB thumb drive formatted with a FAT32 filesystem on a Linux system, 20.306 +Linux will handle names on that filesystem in a case preserving, but 20.307 +insensitive, way. 20.308 +</para> 20.309 + 20.310 +<sect2> 20.311 +<title>Safe, portable repository storage</title> 20.312 + 20.313 +<para>Mercurial's repository storage mechanism is <emphasis>case safe</emphasis>. It 20.314 +translates file names so that they can be safely stored on both case 20.315 +sensitive and case insensitive filesystems. This means that you can 20.316 +use normal file copying tools to transfer a Mercurial repository onto, 20.317 +for example, a USB thumb drive, and safely move that drive and 20.318 +repository back and forth between a Mac, a PC running Windows, and a 20.319 +Linux box. 20.320 +</para> 20.321 + 20.322 +</sect2> 20.323 +<sect2> 20.324 +<title>Detecting case conflicts</title> 20.325 + 20.326 +<para>When operating in the working directory, Mercurial honours the naming 20.327 +policy of the filesystem where the working directory is located. If 20.328 +the filesystem is case preserving, but insensitive, Mercurial will 20.329 +treat names that differ only in case as the same. 20.330 +</para> 20.331 + 20.332 +<para>An important aspect of this approach is that it is possible to commit 20.333 +a changeset on a case sensitive (typically Linux or Unix) filesystem 20.334 +that will cause trouble for users on case insensitive (usually Windows 20.335 +and MacOS) users. If a Linux user commits changes to two files, one 20.336 +named <filename>myfile.c</filename> and the other named <filename>MyFile.C</filename>, 20.337 +they will be stored correctly in the repository. And in the working 20.338 +directories of other Linux users, they will be correctly represented 20.339 +as separate files. 20.340 +</para> 20.341 + 20.342 +<para>If a Windows or Mac user pulls this change, they will not initially 20.343 +have a problem, because Mercurial's repository storage mechanism is 20.344 +case safe. However, once they try to <command role="hg-cmd">hg update</command> the working 20.345 +directory to that changeset, or <command role="hg-cmd">hg merge</command> with that changeset, 20.346 +Mercurial will spot the conflict between the two file names that the 20.347 +filesystem would treat as the same, and forbid the update or merge 20.348 +from occurring. 20.349 +</para> 20.350 + 20.351 +</sect2> 20.352 +<sect2> 20.353 +<title>Fixing a case conflict</title> 20.354 + 20.355 +<para>If you are using Windows or a Mac in a mixed environment where some of 20.356 +your collaborators are using Linux or Unix, and Mercurial reports a 20.357 +case folding conflict when you try to <command role="hg-cmd">hg update</command> or <command role="hg-cmd">hg merge</command>, 20.358 +the procedure to fix the problem is simple. 20.359 +</para> 20.360 + 20.361 +<para>Just find a nearby Linux or Unix box, clone the problem repository 20.362 +onto it, and use Mercurial's <command role="hg-cmd">hg rename</command> command to change the 20.363 +names of any offending files or directories so that they will no 20.364 +longer cause case folding conflicts. Commit this change, <command role="hg-cmd">hg pull</command> 20.365 +or <command role="hg-cmd">hg push</command> it across to your Windows or MacOS system, and 20.366 +<command role="hg-cmd">hg update</command> to the revision with the non-conflicting names. 20.367 +</para> 20.368 + 20.369 +<para>The changeset with case-conflicting names will remain in your 20.370 +project's history, and you still won't be able to <command role="hg-cmd">hg update</command> your 20.371 +working directory to that changeset on a Windows or MacOS system, but 20.372 +you can continue development unimpeded. 20.373 +</para> 20.374 + 20.375 +<note> 20.376 +<para> Prior to version 0.9.3, Mercurial did not use a case safe repository 20.377 + storage mechanism, and did not detect case folding conflicts. If 20.378 + you are using an older version of Mercurial on Windows or MacOS, I 20.379 + strongly recommend that you upgrade. 20.380 +</para> 20.381 +</note> 20.382 + 20.383 +</sect2> 20.384 +</sect1> 20.385 +</chapter> 20.386 + 20.387 +<!-- 20.388 +local variables: 20.389 +sgml-parent-document: ("00book.xml" "book" "chapter") 20.390 +end: 20.391 +--> 20.392 \ No newline at end of file
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 21.2 +++ b/fr/ch08-branch.xml Sun Aug 16 04:58:01 2009 +0200 21.3 @@ -0,0 +1,473 @@ 21.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 21.5 + 21.6 +<chapter> 21.7 +<title>Managing releases and branchy development</title> 21.8 +<para>\label{chap:branch}</para> 21.9 + 21.10 +<para>Mercurial provides several mechanisms for you to manage a project that 21.11 +is making progress on multiple fronts at once. To understand these 21.12 +mechanisms, let's first take a brief look at a fairly normal software 21.13 +project structure.</para> 21.14 + 21.15 +<para>Many software projects issue periodic <quote>major</quote> releases that contain 21.16 +substantial new features. In parallel, they may issue <quote>minor</quote> 21.17 +releases. These are usually identical to the major releases off which 21.18 +they're based, but with a few bugs fixed.</para> 21.19 + 21.20 +<para>In this chapter, we'll start by talking about how to keep records of 21.21 +project milestones such as releases. We'll then continue on to talk 21.22 +about the flow of work between different phases of a project, and how 21.23 +Mercurial can help you to isolate and manage this work.</para> 21.24 + 21.25 +<sect1> 21.26 +<title>Giving a persistent name to a revision</title> 21.27 + 21.28 +<para>Once you decide that you'd like to call a particular revision a 21.29 +<quote>release</quote>, it's a good idea to record the identity of that revision. 21.30 +This will let you reproduce that release at a later date, for whatever 21.31 +purpose you might need at the time (reproducing a bug, porting to a 21.32 +new platform, etc). 21.33 +<!-- &interaction.tag.init; --></para> 21.34 + 21.35 +<para>Mercurial lets you give a permanent name to any revision using the 21.36 +<command role="hg-cmd">hg tag</command> command. Not surprisingly, these names are called 21.37 +<quote>tags</quote>. 21.38 +<!-- &interaction.tag.tag; --></para> 21.39 + 21.40 +<para>A tag is nothing more than a <quote>symbolic name</quote> for a revision. Tags 21.41 +exist purely for your convenience, so that you have a handy permanent 21.42 +way to refer to a revision; Mercurial doesn't interpret the tag names 21.43 +you use in any way. Neither does Mercurial place any restrictions on 21.44 +the name of a tag, beyond a few that are necessary to ensure that a 21.45 +tag can be parsed unambiguously. A tag name cannot contain any of the 21.46 +following characters:</para> 21.47 +<itemizedlist> 21.48 +<listitem><para>Colon (ASCII 58, <quote><literal>:</literal></quote>)</para> 21.49 +</listitem> 21.50 +<listitem><para>Carriage return (ASCII 13, <quote><literal>\r</literal></quote>) 21.51 +</para> 21.52 +</listitem> 21.53 +<listitem><para>Newline (ASCII 10, <quote><literal>\n</literal></quote>) 21.54 +</para> 21.55 +</listitem></itemizedlist> 21.56 + 21.57 +<para>You can use the <command role="hg-cmd">hg tags</command> command to display the tags present in 21.58 +your repository. In the output, each tagged revision is identified 21.59 +first by its name, then by revision number, and finally by the unique 21.60 +hash of the revision. 21.61 +<!-- &interaction.tag.tags; --> 21.62 +Notice that <literal>tip</literal> is listed in the output of <command role="hg-cmd">hg tags</command>. The 21.63 +<literal>tip</literal> tag is a special <quote>floating</quote> tag, which always 21.64 +identifies the newest revision in the repository. 21.65 +</para> 21.66 + 21.67 +<para>In the output of the <command role="hg-cmd">hg tags</command> command, tags are listed in reverse 21.68 +order, by revision number. This usually means that recent tags are 21.69 +listed before older tags. It also means that <literal>tip</literal> is always 21.70 +going to be the first tag listed in the output of <command role="hg-cmd">hg tags</command>. 21.71 +</para> 21.72 + 21.73 +<para>When you run <command role="hg-cmd">hg log</command>, if it displays a revision that has tags 21.74 +associated with it, it will print those tags. 21.75 +<!-- &interaction.tag.log; --> 21.76 +</para> 21.77 + 21.78 +<para>Any time you need to provide a revision ID to a Mercurial command, the 21.79 +command will accept a tag name in its place. Internally, Mercurial 21.80 +will translate your tag name into the corresponding revision ID, then 21.81 +use that. 21.82 +<!-- &interaction.tag.log.v1.0; --> 21.83 +</para> 21.84 + 21.85 +<para>There's no limit on the number of tags you can have in a repository, 21.86 +or on the number of tags that a single revision can have. As a 21.87 +practical matter, it's not a great idea to have <quote>too many</quote> (a number 21.88 +which will vary from project to project), simply because tags are 21.89 +supposed to help you to find revisions. If you have lots of tags, the 21.90 +ease of using them to identify revisions diminishes rapidly. 21.91 +</para> 21.92 + 21.93 +<para>For example, if your project has milestones as frequent as every few 21.94 +days, it's perfectly reasonable to tag each one of those. But if you 21.95 +have a continuous build system that makes sure every revision can be 21.96 +built cleanly, you'd be introducing a lot of noise if you were to tag 21.97 +every clean build. Instead, you could tag failed builds (on the 21.98 +assumption that they're rare!), or simply not use tags to track 21.99 +buildability. 21.100 +</para> 21.101 + 21.102 +<para>If you want to remove a tag that you no longer want, use 21.103 +<command role="hg-cmd">hg tag --remove</command>. 21.104 +<!-- &interaction.tag.remove; --> 21.105 +You can also modify a tag at any time, so that it identifies a 21.106 +different revision, by simply issuing a new <command role="hg-cmd">hg tag</command> command. 21.107 +You'll have to use the <option role="hg-opt-tag">-f</option> option to tell Mercurial that 21.108 +you <emphasis>really</emphasis> want to update the tag. 21.109 +<!-- &interaction.tag.replace; --> 21.110 +There will still be a permanent record of the previous identity of the 21.111 +tag, but Mercurial will no longer use it. There's thus no penalty to 21.112 +tagging the wrong revision; all you have to do is turn around and tag 21.113 +the correct revision once you discover your error. 21.114 +</para> 21.115 + 21.116 +<para>Mercurial stores tags in a normal revision-controlled file in your 21.117 +repository. If you've created any tags, you'll find them in a file 21.118 +named <filename role="special">.hgtags</filename>. When you run the <command role="hg-cmd">hg tag</command> command, 21.119 +Mercurial modifies this file, then automatically commits the change to 21.120 +it. This means that every time you run <command role="hg-cmd">hg tag</command>, you'll see a 21.121 +corresponding changeset in the output of <command role="hg-cmd">hg log</command>. 21.122 +<!-- &interaction.tag.tip; --> 21.123 +</para> 21.124 + 21.125 +<sect2> 21.126 +<title>Handling tag conflicts during a merge</title> 21.127 + 21.128 +<para>You won't often need to care about the <filename role="special">.hgtags</filename> file, but 21.129 +it sometimes makes its presence known during a merge. The format of 21.130 +the file is simple: it consists of a series of lines. Each line 21.131 +starts with a changeset hash, followed by a space, followed by the 21.132 +name of a tag. 21.133 +</para> 21.134 + 21.135 +<para>If you're resolving a conflict in the <filename role="special">.hgtags</filename> file during 21.136 +a merge, there's one twist to modifying the <filename role="special">.hgtags</filename> file: 21.137 +when Mercurial is parsing the tags in a repository, it <emphasis>never</emphasis> 21.138 +reads the working copy of the <filename role="special">.hgtags</filename> file. Instead, it 21.139 +reads the <emphasis>most recently committed</emphasis> revision of the file. 21.140 +</para> 21.141 + 21.142 +<para>An unfortunate consequence of this design is that you can't actually 21.143 +verify that your merged <filename role="special">.hgtags</filename> file is correct until 21.144 +<emphasis>after</emphasis> you've committed a change. So if you find yourself 21.145 +resolving a conflict on <filename role="special">.hgtags</filename> during a merge, be sure to 21.146 +run <command role="hg-cmd">hg tags</command> after you commit. If it finds an error in the 21.147 +<filename role="special">.hgtags</filename> file, it will report the location of the error, 21.148 +which you can then fix and commit. You should then run <command role="hg-cmd">hg tags</command> 21.149 +again, just to be sure that your fix is correct. 21.150 +</para> 21.151 + 21.152 +</sect2> 21.153 +<sect2> 21.154 +<title>Tags and cloning</title> 21.155 + 21.156 +<para>You may have noticed that the <command role="hg-cmd">hg clone</command> command has a 21.157 +<option role="hg-opt-clone">-r</option> option that lets you clone an exact copy of the 21.158 +repository as of a particular changeset. The new clone will not 21.159 +contain any project history that comes after the revision you 21.160 +specified. This has an interaction with tags that can surprise the 21.161 +unwary. 21.162 +</para> 21.163 + 21.164 +<para>Recall that a tag is stored as a revision to the <filename role="special">.hgtags</filename> 21.165 +file, so that when you create a tag, the changeset in which it's 21.166 +recorded necessarily refers to an older changeset. When you run 21.167 +<command role="hg-cmd">hg clone -r foo</command> to clone a repository as of tag 21.168 +<literal>foo</literal>, the new clone \emph{will not contain the history that 21.169 + created the tag} that you used to clone the repository. The result 21.170 +is that you'll get exactly the right subset of the project's history 21.171 +in the new repository, but <emphasis>not</emphasis> the tag you might have expected. 21.172 +</para> 21.173 + 21.174 +</sect2> 21.175 +<sect2> 21.176 +<title>When permanent tags are too much</title> 21.177 + 21.178 +<para>Since Mercurial's tags are revision controlled and carried around with 21.179 +a project's history, everyone you work with will see the tags you 21.180 +create. But giving names to revisions has uses beyond simply noting 21.181 +that revision <literal>4237e45506ee</literal> is really <literal>v2.0.2</literal>. If 21.182 +you're trying to track down a subtle bug, you might want a tag to 21.183 +remind you of something like <quote>Anne saw the symptoms with this 21.184 +revision</quote>. 21.185 +</para> 21.186 + 21.187 +<para>For cases like this, what you might want to use are <emphasis>local</emphasis> tags. 21.188 +You can create a local tag with the <option role="hg-opt-tag">-l</option> option to the 21.189 +<command role="hg-cmd">hg tag</command> command. This will store the tag in a file called 21.190 +<filename role="special">.hg/localtags</filename>. Unlike <filename role="special">.hgtags</filename>, 21.191 +<filename role="special">.hg/localtags</filename> is not revision controlled. Any tags you 21.192 +create using <option role="hg-opt-tag">-l</option> remain strictly local to the repository 21.193 +you're currently working in. 21.194 +</para> 21.195 + 21.196 +</sect2> 21.197 +</sect1> 21.198 +<sect1> 21.199 +<title>The flow of changes&emdash;big picture vs. little</title> 21.200 + 21.201 +<para>To return to the outline I sketched at the beginning of a chapter, 21.202 +let's think about a project that has multiple concurrent pieces of 21.203 +work under development at once. 21.204 +</para> 21.205 + 21.206 +<para>There might be a push for a new <quote>main</quote> release; a new minor bugfix 21.207 +release to the last main release; and an unexpected <quote>hot fix</quote> to an 21.208 +old release that is now in maintenance mode. 21.209 +</para> 21.210 + 21.211 +<para>The usual way people refer to these different concurrent directions of 21.212 +development is as <quote>branches</quote>. However, we've already seen numerous 21.213 +times that Mercurial treats <emphasis>all of history</emphasis> as a series of 21.214 +branches and merges. Really, what we have here is two ideas that are 21.215 +peripherally related, but which happen to share a name. 21.216 +</para> 21.217 +<itemizedlist> 21.218 +<listitem><para><quote>Big picture</quote> branches represent the sweep of a project's 21.219 + evolution; people give them names, and talk about them in 21.220 + conversation. 21.221 +</para> 21.222 +</listitem> 21.223 +<listitem><para><quote>Little picture</quote> branches are artefacts of the day-to-day 21.224 + activity of developing and merging changes. They expose the 21.225 + narrative of how the code was developed. 21.226 +</para> 21.227 +</listitem></itemizedlist> 21.228 + 21.229 +</sect1> 21.230 +<sect1> 21.231 +<title>Managing big-picture branches in repositories</title> 21.232 + 21.233 +<para>The easiest way to isolate a <quote>big picture</quote> branch in Mercurial is in 21.234 +a dedicated repository. If you have an existing shared 21.235 +repository&emdash;let's call it <literal>myproject</literal>&emdash;that reaches a <quote>1.0</quote> 21.236 +milestone, you can start to prepare for future maintenance releases on 21.237 +top of version 1.0 by tagging the revision from which you prepared 21.238 +the 1.0 release. 21.239 +<!-- &interaction.branch-repo.tag; --> 21.240 +You can then clone a new shared <literal>myproject-1.0.1</literal> repository as 21.241 +of that tag. 21.242 +<!-- &interaction.branch-repo.clone; --> 21.243 +</para> 21.244 + 21.245 +<para>Afterwards, if someone needs to work on a bug fix that ought to go 21.246 +into an upcoming 1.0.1 minor release, they clone the 21.247 +<literal>myproject-1.0.1</literal> repository, make their changes, and push them 21.248 +back. 21.249 +<!-- &interaction.branch-repo.bugfix; --> 21.250 +Meanwhile, development for the next major release can continue, 21.251 +isolated and unabated, in the <literal>myproject</literal> repository. 21.252 +<!-- &interaction.branch-repo.new; --> 21.253 +</para> 21.254 + 21.255 +</sect1> 21.256 +<sect1> 21.257 +<title>Don't repeat yourself: merging across branches</title> 21.258 + 21.259 +<para>In many cases, if you have a bug to fix on a maintenance branch, the 21.260 +chances are good that the bug exists on your project's main branch 21.261 +(and possibly other maintenance branches, too). It's a rare developer 21.262 +who wants to fix the same bug multiple times, so let's look at a few 21.263 +ways that Mercurial can help you to manage these bugfixes without 21.264 +duplicating your work. 21.265 +</para> 21.266 + 21.267 +<para>In the simplest instance, all you need to do is pull changes from your 21.268 +maintenance branch into your local clone of the target branch. 21.269 +<!-- &interaction.branch-repo.pull; --> 21.270 +You'll then need to merge the heads of the two branches, and push back 21.271 +to the main branch. 21.272 +<!-- &interaction.branch-repo.merge; --> 21.273 +</para> 21.274 + 21.275 +</sect1> 21.276 +<sect1> 21.277 +<title>Naming branches within one repository</title> 21.278 + 21.279 +<para>In most instances, isolating branches in repositories is the right 21.280 +approach. Its simplicity makes it easy to understand; and so it's 21.281 +hard to make mistakes. There's a one-to-one relationship between 21.282 +branches you're working in and directories on your system. This lets 21.283 +you use normal (non-Mercurial-aware) tools to work on files within a 21.284 +branch/repository. 21.285 +</para> 21.286 + 21.287 +<para>If you're more in the <quote>power user</quote> category (<emphasis>and</emphasis> your 21.288 +collaborators are too), there is an alternative way of handling 21.289 +branches that you can consider. I've already mentioned the 21.290 +human-level distinction between <quote>small picture</quote> and <quote>big picture</quote> 21.291 +branches. While Mercurial works with multiple <quote>small picture</quote> 21.292 +branches in a repository all the time (for example after you pull 21.293 +changes in, but before you merge them), it can <emphasis>also</emphasis> work with 21.294 +multiple <quote>big picture</quote> branches. 21.295 +</para> 21.296 + 21.297 +<para>The key to working this way is that Mercurial lets you assign a 21.298 +persistent <emphasis>name</emphasis> to a branch. There always exists a branch 21.299 +named <literal>default</literal>. Even before you start naming branches 21.300 +yourself, you can find traces of the <literal>default</literal> branch if you 21.301 +look for them. 21.302 +</para> 21.303 + 21.304 +<para>As an example, when you run the <command role="hg-cmd">hg commit</command> command, and it pops up 21.305 +your editor so that you can enter a commit message, look for a line 21.306 +that contains the text <quote><literal>HG: branch default</literal></quote> at the bottom. 21.307 +This is telling you that your commit will occur on the branch named 21.308 +<literal>default</literal>. 21.309 +</para> 21.310 + 21.311 +<para>To start working with named branches, use the <command role="hg-cmd">hg branches</command> 21.312 +command. This command lists the named branches already present in 21.313 +your repository, telling you which changeset is the tip of each. 21.314 +<!-- &interaction.branch-named.branches; --> 21.315 +Since you haven't created any named branches yet, the only one that 21.316 +exists is <literal>default</literal>. 21.317 +</para> 21.318 + 21.319 +<para>To find out what the <quote>current</quote> branch is, run the <command role="hg-cmd">hg branch</command> 21.320 +command, giving it no arguments. This tells you what branch the 21.321 +parent of the current changeset is on. 21.322 +<!-- &interaction.branch-named.branch; --> 21.323 +</para> 21.324 + 21.325 +<para>To create a new branch, run the <command role="hg-cmd">hg branch</command> command again. This 21.326 +time, give it one argument: the name of the branch you want to create. 21.327 +<!-- &interaction.branch-named.create; --> 21.328 +</para> 21.329 + 21.330 +<para>After you've created a branch, you might wonder what effect the 21.331 +<command role="hg-cmd">hg branch</command> command has had. What do the <command role="hg-cmd">hg status</command> and 21.332 +<command role="hg-cmd">hg tip</command> commands report? 21.333 +<!-- &interaction.branch-named.status; --> 21.334 +Nothing has changed in the working directory, and there's been no new 21.335 +history created. As this suggests, running the <command role="hg-cmd">hg branch</command> command 21.336 +has no permanent effect; it only tells Mercurial what branch name to 21.337 +use the <emphasis>next</emphasis> time you commit a changeset. 21.338 +</para> 21.339 + 21.340 +<para>When you commit a change, Mercurial records the name of the branch on 21.341 +which you committed. Once you've switched from the <literal>default</literal> 21.342 +branch to another and committed, you'll see the name of the new branch 21.343 +show up in the output of <command role="hg-cmd">hg log</command>, <command role="hg-cmd">hg tip</command>, and other commands 21.344 +that display the same kind of output. 21.345 +<!-- &interaction.branch-named.commit; --> 21.346 +The <command role="hg-cmd">hg log</command>-like commands will print the branch name of every 21.347 +changeset that's not on the <literal>default</literal> branch. As a result, if 21.348 +you never use named branches, you'll never see this information. 21.349 +</para> 21.350 + 21.351 +<para>Once you've named a branch and committed a change with that name, 21.352 +every subsequent commit that descends from that change will inherit 21.353 +the same branch name. You can change the name of a branch at any 21.354 +time, using the <command role="hg-cmd">hg branch</command> command. 21.355 +<!-- &interaction.branch-named.rebranch; --> 21.356 +In practice, this is something you won't do very often, as branch 21.357 +names tend to have fairly long lifetimes. (This isn't a rule, just an 21.358 +observation.) 21.359 +</para> 21.360 + 21.361 +</sect1> 21.362 +<sect1> 21.363 +<title>Dealing with multiple named branches in a repository</title> 21.364 + 21.365 +<para>If you have more than one named branch in a repository, Mercurial will 21.366 +remember the branch that your working directory on when you start a 21.367 +command like <command role="hg-cmd">hg update</command> or <command role="hg-cmd">hg pull -u</command>. It will update 21.368 +the working directory to the tip of this branch, no matter what the 21.369 +<quote>repo-wide</quote> tip is. To update to a revision that's on a different 21.370 +named branch, you may need to use the <option role="hg-opt-update">-C</option> option to 21.371 +<command role="hg-cmd">hg update</command>. 21.372 +</para> 21.373 + 21.374 +<para>This behaviour is a little subtle, so let's see it in action. First, 21.375 +let's remind ourselves what branch we're currently on, and what 21.376 +branches are in our repository. 21.377 +<!-- &interaction.branch-named.parents; --> 21.378 +We're on the <literal>bar</literal> branch, but there also exists an older 21.379 +<command role="hg-cmd">hg foo</command> branch. 21.380 +</para> 21.381 + 21.382 +<para>We can <command role="hg-cmd">hg update</command> back and forth between the tips of the 21.383 +<literal>foo</literal> and <literal>bar</literal> branches without needing to use the 21.384 +<option role="hg-opt-update">-C</option> option, because this only involves going backwards 21.385 +and forwards linearly through our change history. 21.386 +<!-- &interaction.branch-named.update-switchy; --> 21.387 +</para> 21.388 + 21.389 +<para>If we go back to the <literal>foo</literal> branch and then run <command role="hg-cmd">hg update</command>, 21.390 +it will keep us on <literal>foo</literal>, not move us to the tip of 21.391 +<literal>bar</literal>. 21.392 +<!-- &interaction.branch-named.update-nothing; --> 21.393 +</para> 21.394 + 21.395 +<para>Committing a new change on the <literal>foo</literal> branch introduces a new 21.396 +head. 21.397 +<!-- &interaction.branch-named.foo-commit; --> 21.398 +</para> 21.399 + 21.400 +</sect1> 21.401 +<sect1> 21.402 +<title>Branch names and merging</title> 21.403 + 21.404 +<para>As you've probably noticed, merges in Mercurial are not symmetrical. 21.405 +Let's say our repository has two heads, 17 and 23. If I 21.406 +<command role="hg-cmd">hg update</command> to 17 and then <command role="hg-cmd">hg merge</command> with 23, Mercurial records 21.407 +17 as the first parent of the merge, and 23 as the second. Whereas if 21.408 +I <command role="hg-cmd">hg update</command> to 23 and then <command role="hg-cmd">hg merge</command> with 17, it records 23 21.409 +as the first parent, and 17 as the second. 21.410 +</para> 21.411 + 21.412 +<para>This affects Mercurial's choice of branch name when you merge. After 21.413 +a merge, Mercurial will retain the branch name of the first parent 21.414 +when you commit the result of the merge. If your first parent's 21.415 +branch name is <literal>foo</literal>, and you merge with <literal>bar</literal>, the 21.416 +branch name will still be <literal>foo</literal> after you merge. 21.417 +</para> 21.418 + 21.419 +<para>It's not unusual for a repository to contain multiple heads, each with 21.420 +the same branch name. Let's say I'm working on the <literal>foo</literal> 21.421 +branch, and so are you. We commit different changes; I pull your 21.422 +changes; I now have two heads, each claiming to be on the <literal>foo</literal> 21.423 +branch. The result of a merge will be a single head on the 21.424 +<literal>foo</literal> branch, as you might hope. 21.425 +</para> 21.426 + 21.427 +<para>But if I'm working on the <literal>bar</literal> branch, and I merge work from 21.428 +the <literal>foo</literal> branch, the result will remain on the <literal>bar</literal> 21.429 +branch. 21.430 +<!-- &interaction.branch-named.merge; --> 21.431 +</para> 21.432 + 21.433 +<para>To give a more concrete example, if I'm working on the 21.434 +<literal>bleeding-edge</literal> branch, and I want to bring in the latest fixes 21.435 +from the <literal>stable</literal> branch, Mercurial will choose the <quote>right</quote> 21.436 +(<literal>bleeding-edge</literal>) branch name when I pull and merge from 21.437 +<literal>stable</literal>. 21.438 +</para> 21.439 + 21.440 +</sect1> 21.441 +<sect1> 21.442 +<title>Branch naming is generally useful</title> 21.443 + 21.444 +<para>You shouldn't think of named branches as applicable only to situations 21.445 +where you have multiple long-lived branches cohabiting in a single 21.446 +repository. They're very useful even in the one-branch-per-repository 21.447 +case. 21.448 +</para> 21.449 + 21.450 +<para>In the simplest case, giving a name to each branch gives you a 21.451 +permanent record of which branch a changeset originated on. This 21.452 +gives you more context when you're trying to follow the history of a 21.453 +long-lived branchy project. 21.454 +</para> 21.455 + 21.456 +<para>If you're working with shared repositories, you can set up a 21.457 +<literal role="hook">pretxnchangegroup</literal> hook on each that will block incoming changes 21.458 +that have the <quote>wrong</quote> branch name. This provides a simple, but 21.459 +effective, defence against people accidentally pushing changes from a 21.460 +<quote>bleeding edge</quote> branch to a <quote>stable</quote> branch. Such a hook might 21.461 +look like this inside the shared repo's <filename role="special"> /.hgrc</filename>. 21.462 +</para> 21.463 +<programlisting> 21.464 +<para> [hooks] 21.465 + pretxnchangegroup.branch = hg heads --template '{branches} ' | grep mybranch 21.466 +</para> 21.467 +</programlisting> 21.468 + 21.469 +</sect1> 21.470 +</chapter> 21.471 + 21.472 +<!-- 21.473 +local variables: 21.474 +sgml-parent-document: ("00book.xml" "book" "chapter") 21.475 +end: 21.476 +--> 21.477 \ No newline at end of file
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 22.2 +++ b/fr/ch09-undo.xml Sun Aug 16 04:58:01 2009 +0200 22.3 @@ -0,0 +1,963 @@ 22.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 22.5 + 22.6 +<chapter> 22.7 +<title>Finding and fixing your mistakes</title> 22.8 +<para>\label{chap:undo}</para> 22.9 + 22.10 +<para>To err might be human, but to really handle the consequences well 22.11 +takes a top-notch revision control system. In this chapter, we'll 22.12 +discuss some of the techniques you can use when you find that a 22.13 +problem has crept into your project. Mercurial has some highly 22.14 +capable features that will help you to isolate the sources of 22.15 +problems, and to handle them appropriately.</para> 22.16 + 22.17 +<sect1> 22.18 +<title>Erasing local history</title> 22.19 + 22.20 +<sect2> 22.21 +<title>The accidental commit</title> 22.22 + 22.23 +<para>I have the occasional but persistent problem of typing rather more 22.24 +quickly than I can think, which sometimes results in me committing a 22.25 +changeset that is either incomplete or plain wrong. In my case, the 22.26 +usual kind of incomplete changeset is one in which I've created a new 22.27 +source file, but forgotten to <command role="hg-cmd">hg add</command> it. A <quote>plain wrong</quote> 22.28 +changeset is not as common, but no less annoying.</para> 22.29 + 22.30 +</sect2> 22.31 +<sect2> 22.32 +<title>Rolling back a transaction</title> 22.33 +<para>\label{sec:undo:rollback}</para> 22.34 + 22.35 +<para>In section <xref linkend="sec:concepts:txn"/>, I mentioned that Mercurial treats 22.36 +each modification of a repository as a <emphasis>transaction</emphasis>. Every time 22.37 +you commit a changeset or pull changes from another repository, 22.38 +Mercurial remembers what you did. You can undo, or <emphasis>roll back</emphasis>, 22.39 +exactly one of these actions using the <command role="hg-cmd">hg rollback</command> command. (See 22.40 +section <xref linkend="sec:undo:rollback-after-push"/> for an important caveat 22.41 +about the use of this command.)</para> 22.42 + 22.43 +<para>Here's a mistake that I often find myself making: committing a change 22.44 +in which I've created a new file, but forgotten to <command role="hg-cmd">hg add</command> it. 22.45 +<!-- &interaction.rollback.commit; --> 22.46 +Looking at the output of <command role="hg-cmd">hg status</command> after the commit immediately 22.47 +confirms the error. 22.48 +<!-- &interaction.rollback.status; --> 22.49 +The commit captured the changes to the file <filename>a</filename>, but not the 22.50 +new file <filename>b</filename>. If I were to push this changeset to a 22.51 +repository that I shared with a colleague, the chances are high that 22.52 +something in <filename>a</filename> would refer to <filename>b</filename>, which would not 22.53 +be present in their repository when they pulled my changes. I would 22.54 +thus become the object of some indignation.</para> 22.55 + 22.56 +<para>However, luck is with me&emdash;I've caught my error before I pushed the 22.57 +changeset. I use the <command role="hg-cmd">hg rollback</command> command, and Mercurial makes 22.58 +that last changeset vanish. 22.59 +<!-- &interaction.rollback.rollback; --> 22.60 +Notice that the changeset is no longer present in the repository's 22.61 +history, and the working directory once again thinks that the file 22.62 +<filename>a</filename> is modified. The commit and rollback have left the 22.63 +working directory exactly as it was prior to the commit; the changeset 22.64 +has been completely erased. I can now safely <command role="hg-cmd">hg add</command> the file 22.65 +<filename>b</filename>, and rerun my commit. 22.66 +<!-- &interaction.rollback.add; --></para> 22.67 + 22.68 +</sect2> 22.69 +<sect2> 22.70 +<title>The erroneous pull</title> 22.71 + 22.72 +<para>It's common practice with Mercurial to maintain separate development 22.73 +branches of a project in different repositories. Your development 22.74 +team might have one shared repository for your project's <quote>0.9</quote> 22.75 +release, and another, containing different changes, for the <quote>1.0</quote> 22.76 +release.</para> 22.77 + 22.78 +<para>Given this, you can imagine that the consequences could be messy if 22.79 +you had a local <quote>0.9</quote> repository, and accidentally pulled changes 22.80 +from the shared <quote>1.0</quote> repository into it. At worst, you could be 22.81 +paying insufficient attention, and push those changes into the shared 22.82 +<quote>0.9</quote> tree, confusing your entire team (but don't worry, we'll 22.83 +return to this horror scenario later). However, it's more likely that 22.84 +you'll notice immediately, because Mercurial will display the URL it's 22.85 +pulling from, or you will see it pull a suspiciously large number of 22.86 +changes into the repository. 22.87 +</para> 22.88 + 22.89 +<para>The <command role="hg-cmd">hg rollback</command> command will work nicely to expunge all of the 22.90 +changesets that you just pulled. Mercurial groups all changes from 22.91 +one <command role="hg-cmd">hg pull</command> into a single transaction, so one <command role="hg-cmd">hg rollback</command> is 22.92 +all you need to undo this mistake. 22.93 +</para> 22.94 + 22.95 +</sect2> 22.96 +<sect2> 22.97 +<title>Rolling back is useless once you've pushed</title> 22.98 +<para>\label{sec:undo:rollback-after-push} 22.99 +</para> 22.100 + 22.101 +<para>The value of the <command role="hg-cmd">hg rollback</command> command drops to zero once you've 22.102 +pushed your changes to another repository. Rolling back a change 22.103 +makes it disappear entirely, but <emphasis>only</emphasis> in the repository in 22.104 +which you perform the <command role="hg-cmd">hg rollback</command>. Because a rollback eliminates 22.105 +history, there's no way for the disappearance of a change to propagate 22.106 +between repositories. 22.107 +</para> 22.108 + 22.109 +<para>If you've pushed a change to another repository&emdash;particularly if it's 22.110 +a shared repository&emdash;it has essentially <quote>escaped into the wild,</quote> 22.111 +and you'll have to recover from your mistake in a different way. What 22.112 +will happen if you push a changeset somewhere, then roll it back, then 22.113 +pull from the repository you pushed to, is that the changeset will 22.114 +reappear in your repository. 22.115 +</para> 22.116 + 22.117 +<para>(If you absolutely know for sure that the change you want to roll back 22.118 +is the most recent change in the repository that you pushed to, 22.119 +<emphasis>and</emphasis> you know that nobody else could have pulled it from that 22.120 +repository, you can roll back the changeset there, too, but you really 22.121 +should really not rely on this working reliably. If you do this, 22.122 +sooner or later a change really will make it into a repository that 22.123 +you don't directly control (or have forgotten about), and come back to 22.124 +bite you.) 22.125 +</para> 22.126 + 22.127 +</sect2> 22.128 +<sect2> 22.129 +<title>You can only roll back once</title> 22.130 + 22.131 +<para>Mercurial stores exactly one transaction in its transaction log; that 22.132 +transaction is the most recent one that occurred in the repository. 22.133 +This means that you can only roll back one transaction. If you expect 22.134 +to be able to roll back one transaction, then its predecessor, this is 22.135 +not the behaviour you will get. 22.136 +<!-- &interaction.rollback.twice; --> 22.137 +Once you've rolled back one transaction in a repository, you can't 22.138 +roll back again in that repository until you perform another commit or 22.139 +pull. 22.140 +</para> 22.141 + 22.142 +</sect2> 22.143 +</sect1> 22.144 +<sect1> 22.145 +<title>Reverting the mistaken change</title> 22.146 + 22.147 +<para>If you make a modification to a file, and decide that you really 22.148 +didn't want to change the file at all, and you haven't yet committed 22.149 +your changes, the <command role="hg-cmd">hg revert</command> command is the one you'll need. It 22.150 +looks at the changeset that's the parent of the working directory, and 22.151 +restores the contents of the file to their state as of that changeset. 22.152 +(That's a long-winded way of saying that, in the normal case, it 22.153 +undoes your modifications.) 22.154 +</para> 22.155 + 22.156 +<para>Let's illustrate how the <command role="hg-cmd">hg revert</command> command works with yet another 22.157 +small example. We'll begin by modifying a file that Mercurial is 22.158 +already tracking. 22.159 +<!-- &interaction.daily.revert.modify; --> 22.160 +If we don't want that change, we can simply <command role="hg-cmd">hg revert</command> the file. 22.161 +<!-- &interaction.daily.revert.unmodify; --> 22.162 +The <command role="hg-cmd">hg revert</command> command provides us with an extra degree of safety 22.163 +by saving our modified file with a <filename>.orig</filename> extension. 22.164 +<!-- &interaction.daily.revert.status; --> 22.165 +</para> 22.166 + 22.167 +<para>Here is a summary of the cases that the <command role="hg-cmd">hg revert</command> command can 22.168 +deal with. We will describe each of these in more detail in the 22.169 +section that follows. 22.170 +</para> 22.171 +<itemizedlist> 22.172 +<listitem><para>If you modify a file, it will restore the file to its unmodified 22.173 + state. 22.174 +</para> 22.175 +</listitem> 22.176 +<listitem><para>If you <command role="hg-cmd">hg add</command> a file, it will undo the <quote>added</quote> state of 22.177 + the file, but leave the file itself untouched. 22.178 +</para> 22.179 +</listitem> 22.180 +<listitem><para>If you delete a file without telling Mercurial, it will restore 22.181 + the file to its unmodified contents. 22.182 +</para> 22.183 +</listitem> 22.184 +<listitem><para>If you use the <command role="hg-cmd">hg remove</command> command to remove a file, it will 22.185 + undo the <quote>removed</quote> state of the file, and restore the file to its 22.186 + unmodified contents. 22.187 +</para> 22.188 +</listitem></itemizedlist> 22.189 + 22.190 +<sect2> 22.191 +<title>File management errors</title> 22.192 +<para>\label{sec:undo:mgmt} 22.193 +</para> 22.194 + 22.195 +<para>The <command role="hg-cmd">hg revert</command> command is useful for more than just modified 22.196 +files. It lets you reverse the results of all of Mercurial's file 22.197 +management commands&emdash;<command role="hg-cmd">hg add</command>, <command role="hg-cmd">hg remove</command>, and so on. 22.198 +</para> 22.199 + 22.200 +<para>If you <command role="hg-cmd">hg add</command> a file, then decide that in fact you don't want 22.201 +Mercurial to track it, use <command role="hg-cmd">hg revert</command> to undo the add. Don't 22.202 +worry; Mercurial will not modify the file in any way. It will just 22.203 +<quote>unmark</quote> the file. 22.204 +<!-- &interaction.daily.revert.add; --> 22.205 +</para> 22.206 + 22.207 +<para>Similarly, if you ask Mercurial to <command role="hg-cmd">hg remove</command> a file, you can use 22.208 +<command role="hg-cmd">hg revert</command> to restore it to the contents it had as of the parent 22.209 +of the working directory. 22.210 +<!-- &interaction.daily.revert.remove; --> 22.211 +This works just as well for a file that you deleted by hand, without 22.212 +telling Mercurial (recall that in Mercurial terminology, this kind of 22.213 +file is called <quote>missing</quote>). 22.214 +<!-- &interaction.daily.revert.missing; --> 22.215 +</para> 22.216 + 22.217 +<para>If you revert a <command role="hg-cmd">hg copy</command>, the copied-to file remains in your 22.218 +working directory afterwards, untracked. Since a copy doesn't affect 22.219 +the copied-from file in any way, Mercurial doesn't do anything with 22.220 +the copied-from file. 22.221 +<!-- &interaction.daily.revert.copy; --> 22.222 +</para> 22.223 + 22.224 +<sect3> 22.225 +<title>A slightly special case: reverting a rename</title> 22.226 + 22.227 +<para>If you <command role="hg-cmd">hg rename</command> a file, there is one small detail that 22.228 +you should remember. When you <command role="hg-cmd">hg revert</command> a rename, it's not 22.229 +enough to provide the name of the renamed-to file, as you can see 22.230 +here. 22.231 +<!-- &interaction.daily.revert.rename; --> 22.232 +As you can see from the output of <command role="hg-cmd">hg status</command>, the renamed-to file 22.233 +is no longer identified as added, but the renamed-<emphasis>from</emphasis> file is 22.234 +still removed! This is counter-intuitive (at least to me), but at 22.235 +least it's easy to deal with. 22.236 +<!-- &interaction.daily.revert.rename-orig; --> 22.237 +So remember, to revert a <command role="hg-cmd">hg rename</command>, you must provide <emphasis>both</emphasis> 22.238 +the source and destination names. 22.239 +</para> 22.240 + 22.241 +<para>% TODO: the output doesn't look like it will be removed! 22.242 +</para> 22.243 + 22.244 +<para>(By the way, if you rename a file, then modify the renamed-to file, 22.245 +then revert both components of the rename, when Mercurial restores the 22.246 +file that was removed as part of the rename, it will be unmodified. 22.247 +If you need the modifications in the renamed-to file to show up in the 22.248 +renamed-from file, don't forget to copy them over.) 22.249 +</para> 22.250 + 22.251 +<para>These fiddly aspects of reverting a rename arguably constitute a small 22.252 +bug in Mercurial. 22.253 +</para> 22.254 + 22.255 +</sect3> 22.256 +</sect2> 22.257 +</sect1> 22.258 +<sect1> 22.259 +<title>Dealing with committed changes</title> 22.260 + 22.261 +<para>Consider a case where you have committed a change $a$, and another 22.262 +change $b$ on top of it; you then realise that change $a$ was 22.263 +incorrect. Mercurial lets you <quote>back out</quote> an entire changeset 22.264 +automatically, and building blocks that let you reverse part of a 22.265 +changeset by hand. 22.266 +</para> 22.267 + 22.268 +<para>Before you read this section, here's something to keep in mind: the 22.269 +<command role="hg-cmd">hg backout</command> command undoes changes by <emphasis>adding</emphasis> history, not 22.270 +by modifying or erasing it. It's the right tool to use if you're 22.271 +fixing bugs, but not if you're trying to undo some change that has 22.272 +catastrophic consequences. To deal with those, see 22.273 +section <xref linkend="sec:undo:aaaiiieee"/>. 22.274 +</para> 22.275 + 22.276 +<sect2> 22.277 +<title>Backing out a changeset</title> 22.278 + 22.279 +<para>The <command role="hg-cmd">hg backout</command> command lets you <quote>undo</quote> the effects of an entire 22.280 +changeset in an automated fashion. Because Mercurial's history is 22.281 +immutable, this command <emphasis>does not</emphasis> get rid of the changeset you 22.282 +want to undo. Instead, it creates a new changeset that 22.283 +<emphasis>reverses</emphasis> the effect of the to-be-undone changeset. 22.284 +</para> 22.285 + 22.286 +<para>The operation of the <command role="hg-cmd">hg backout</command> command is a little intricate, so 22.287 +let's illustrate it with some examples. First, we'll create a 22.288 +repository with some simple changes. 22.289 +<!-- &interaction.backout.init; --> 22.290 +</para> 22.291 + 22.292 +<para>The <command role="hg-cmd">hg backout</command> command takes a single changeset ID as its 22.293 +argument; this is the changeset to back out. Normally, 22.294 +<command role="hg-cmd">hg backout</command> will drop you into a text editor to write a commit 22.295 +message, so you can record why you're backing the change out. In this 22.296 +example, we provide a commit message on the command line using the 22.297 +<option role="hg-opt-backout">-m</option> option. 22.298 +</para> 22.299 + 22.300 +</sect2> 22.301 +<sect2> 22.302 +<title>Backing out the tip changeset</title> 22.303 + 22.304 +<para>We're going to start by backing out the last changeset we committed. 22.305 +<!-- &interaction.backout.simple; --> 22.306 +You can see that the second line from <filename>myfile</filename> is no longer 22.307 +present. Taking a look at the output of <command role="hg-cmd">hg log</command> gives us an idea 22.308 +of what the <command role="hg-cmd">hg backout</command> command has done. 22.309 +<!-- &interaction.backout.simple.log; --> 22.310 +Notice that the new changeset that <command role="hg-cmd">hg backout</command> has created is a 22.311 +child of the changeset we backed out. It's easier to see this in 22.312 +figure <xref linkend="fig:undo:backout"/>, which presents a graphical view of the 22.313 +change history. As you can see, the history is nice and linear. 22.314 +</para> 22.315 + 22.316 +<informalfigure> 22.317 + 22.318 +<para> <mediaobject><imageobject><imagedata fileref="undo-simple"/></imageobject><textobject><phrase>XXX add text</phrase></textobject></mediaobject> 22.319 + <caption><para>Backing out a change using the <command role="hg-cmd">hg backout</command> command</para></caption> 22.320 + \label{fig:undo:backout} 22.321 +</para> 22.322 +</informalfigure> 22.323 + 22.324 +</sect2> 22.325 +<sect2> 22.326 +<title>Backing out a non-tip change</title> 22.327 + 22.328 +<para>If you want to back out a change other than the last one you 22.329 +committed, pass the <option role="hg-opt-backout">--merge</option> option to the 22.330 +<command role="hg-cmd">hg backout</command> command. 22.331 +<!-- &interaction.backout.non-tip.clone; --> 22.332 +This makes backing out any changeset a <quote>one-shot</quote> operation that's 22.333 +usually simple and fast. 22.334 +<!-- &interaction.backout.non-tip.backout; --> 22.335 +</para> 22.336 + 22.337 +<para>If you take a look at the contents of <filename>myfile</filename> after the 22.338 +backout finishes, you'll see that the first and third changes are 22.339 +present, but not the second. 22.340 +<!-- &interaction.backout.non-tip.cat; --> 22.341 +</para> 22.342 + 22.343 +<para>As the graphical history in figure <xref linkend="fig:undo:backout-non-tip"/> 22.344 +illustrates, Mercurial actually commits <emphasis>two</emphasis> changes in this 22.345 +kind of situation (the box-shaped nodes are the ones that Mercurial 22.346 +commits automatically). Before Mercurial begins the backout process, 22.347 +it first remembers what the current parent of the working directory 22.348 +is. It then backs out the target changeset, and commits that as a 22.349 +changeset. Finally, it merges back to the previous parent of the 22.350 +working directory, and commits the result of the merge. 22.351 +</para> 22.352 + 22.353 +<para>% TODO: to me it looks like mercurial doesn't commit the second merge automatically! 22.354 +</para> 22.355 + 22.356 +<informalfigure> 22.357 + 22.358 +<para> <mediaobject><imageobject><imagedata fileref="undo-non-tip"/></imageobject><textobject><phrase>XXX add text</phrase></textobject></mediaobject> 22.359 + <caption><para>Automated backout of a non-tip change using the <command role="hg-cmd">hg backout</command> command</para></caption> 22.360 + \label{fig:undo:backout-non-tip} 22.361 +</para> 22.362 +</informalfigure> 22.363 + 22.364 +<para>The result is that you end up <quote>back where you were</quote>, only with some 22.365 +extra history that undoes the effect of the changeset you wanted to 22.366 +back out. 22.367 +</para> 22.368 + 22.369 +<sect3> 22.370 +<title>Always use the <option role="hg-opt-backout">--merge</option> option</title> 22.371 + 22.372 +<para>In fact, since the <option role="hg-opt-backout">--merge</option> option will do the <quote>right 22.373 +thing</quote> whether or not the changeset you're backing out is the tip 22.374 +(i.e. it won't try to merge if it's backing out the tip, since there's 22.375 +no need), you should <emphasis>always</emphasis> use this option when you run the 22.376 +<command role="hg-cmd">hg backout</command> command. 22.377 +</para> 22.378 + 22.379 +</sect3> 22.380 +</sect2> 22.381 +<sect2> 22.382 +<title>Gaining more control of the backout process</title> 22.383 + 22.384 +<para>While I've recommended that you always use the 22.385 +<option role="hg-opt-backout">--merge</option> option when backing out a change, the 22.386 +<command role="hg-cmd">hg backout</command> command lets you decide how to merge a backout 22.387 +changeset. Taking control of the backout process by hand is something 22.388 +you will rarely need to do, but it can be useful to understand what 22.389 +the <command role="hg-cmd">hg backout</command> command is doing for you automatically. To 22.390 +illustrate this, let's clone our first repository, but omit the 22.391 +backout change that it contains. 22.392 +</para> 22.393 + 22.394 +<para><!-- &interaction.backout.manual.clone; --> 22.395 +As with our earlier example, We'll commit a third changeset, then back 22.396 +out its parent, and see what happens. 22.397 +<!-- &interaction.backout.manual.backout; --> 22.398 +Our new changeset is again a descendant of the changeset we backout 22.399 +out; it's thus a new head, <emphasis>not</emphasis> a descendant of the changeset 22.400 +that was the tip. The <command role="hg-cmd">hg backout</command> command was quite explicit in 22.401 +telling us this. 22.402 +<!-- &interaction.backout.manual.log; --> 22.403 +</para> 22.404 + 22.405 +<para>Again, it's easier to see what has happened by looking at a graph of 22.406 +the revision history, in figure <xref linkend="fig:undo:backout-manual"/>. This 22.407 +makes it clear that when we use <command role="hg-cmd">hg backout</command> to back out a change 22.408 +other than the tip, Mercurial adds a new head to the repository (the 22.409 +change it committed is box-shaped). 22.410 +</para> 22.411 + 22.412 +<informalfigure> 22.413 + 22.414 +<para> <mediaobject><imageobject><imagedata fileref="undo-manual"/></imageobject><textobject><phrase>XXX add text</phrase></textobject></mediaobject> 22.415 + <caption><para>Backing out a change using the <command role="hg-cmd">hg backout</command> command</para></caption> 22.416 + \label{fig:undo:backout-manual} 22.417 +</para> 22.418 +</informalfigure> 22.419 + 22.420 +<para>After the <command role="hg-cmd">hg backout</command> command has completed, it leaves the new 22.421 +<quote>backout</quote> changeset as the parent of the working directory. 22.422 +<!-- &interaction.backout.manual.parents; --> 22.423 +Now we have two isolated sets of changes. 22.424 +<!-- &interaction.backout.manual.heads; --> 22.425 +</para> 22.426 + 22.427 +<para>Let's think about what we expect to see as the contents of 22.428 +<filename>myfile</filename> now. The first change should be present, because 22.429 +we've never backed it out. The second change should be missing, as 22.430 +that's the change we backed out. Since the history graph shows the 22.431 +third change as a separate head, we <emphasis>don't</emphasis> expect to see the 22.432 +third change present in <filename>myfile</filename>. 22.433 +<!-- &interaction.backout.manual.cat; --> 22.434 +To get the third change back into the file, we just do a normal merge 22.435 +of our two heads. 22.436 +<!-- &interaction.backout.manual.merge; --> 22.437 +Afterwards, the graphical history of our repository looks like 22.438 +figure <xref linkend="fig:undo:backout-manual-merge"/>. 22.439 +</para> 22.440 + 22.441 +<informalfigure> 22.442 + 22.443 +<para> <mediaobject><imageobject><imagedata fileref="undo-manual-merge"/></imageobject><textobject><phrase>XXX add text</phrase></textobject></mediaobject> 22.444 + <caption><para>Manually merging a backout change</para></caption> 22.445 + \label{fig:undo:backout-manual-merge} 22.446 +</para> 22.447 +</informalfigure> 22.448 + 22.449 +</sect2> 22.450 +<sect2> 22.451 +<title>Why <command role="hg-cmd">hg backout</command> works as it does</title> 22.452 + 22.453 +<para>Here's a brief description of how the <command role="hg-cmd">hg backout</command> command works. 22.454 +</para> 22.455 +<orderedlist> 22.456 +<listitem><para>It ensures that the working directory is <quote>clean</quote>, i.e. that 22.457 + the output of <command role="hg-cmd">hg status</command> would be empty. 22.458 +</para> 22.459 +</listitem> 22.460 +<listitem><para>It remembers the current parent of the working directory. Let's 22.461 + call this changeset <literal>orig</literal> 22.462 +</para> 22.463 +</listitem> 22.464 +<listitem><para>It does the equivalent of a <command role="hg-cmd">hg update</command> to sync the working 22.465 + directory to the changeset you want to back out. Let's call this 22.466 + changeset <literal>backout</literal> 22.467 +</para> 22.468 +</listitem> 22.469 +<listitem><para>It finds the parent of that changeset. Let's call that 22.470 + changeset <literal>parent</literal>. 22.471 +</para> 22.472 +</listitem> 22.473 +<listitem><para>For each file that the <literal>backout</literal> changeset affected, it 22.474 + does the equivalent of a <command role="hg-cmd">hg revert -r parent</command> on that file, 22.475 + to restore it to the contents it had before that changeset was 22.476 + committed. 22.477 +</para> 22.478 +</listitem> 22.479 +<listitem><para>It commits the result as a new changeset. This changeset has 22.480 + <literal>backout</literal> as its parent. 22.481 +</para> 22.482 +</listitem> 22.483 +<listitem><para>If you specify <option role="hg-opt-backout">--merge</option> on the command line, it 22.484 + merges with <literal>orig</literal>, and commits the result of the merge. 22.485 +</para> 22.486 +</listitem></orderedlist> 22.487 + 22.488 +<para>An alternative way to implement the <command role="hg-cmd">hg backout</command> command would be 22.489 +to <command role="hg-cmd">hg export</command> the to-be-backed-out changeset as a diff, then use 22.490 +the <option role="cmd-opt-patch">--reverse</option> option to the <command>patch</command> command to 22.491 +reverse the effect of the change without fiddling with the working 22.492 +directory. This sounds much simpler, but it would not work nearly as 22.493 +well. 22.494 +</para> 22.495 + 22.496 +<para>The reason that <command role="hg-cmd">hg backout</command> does an update, a commit, a merge, and 22.497 +another commit is to give the merge machinery the best chance to do a 22.498 +good job when dealing with all the changes <emphasis>between</emphasis> the change 22.499 +you're backing out and the current tip. 22.500 +</para> 22.501 + 22.502 +<para>If you're backing out a changeset that's 100 revisions back in your 22.503 +project's history, the chances that the <command>patch</command> command will 22.504 +be able to apply a reverse diff cleanly are not good, because 22.505 +intervening changes are likely to have <quote>broken the context</quote> that 22.506 +<command>patch</command> uses to determine whether it can apply a patch (if 22.507 +this sounds like gibberish, see <xref linkend="sec:mq:patch"/> for a 22.508 +discussion of the <command>patch</command> command). Also, Mercurial's merge 22.509 +machinery will handle files and directories being renamed, permission 22.510 +changes, and modifications to binary files, none of which 22.511 +<command>patch</command> can deal with. 22.512 +</para> 22.513 + 22.514 +</sect2> 22.515 +</sect1> 22.516 +<sect1> 22.517 +<title>Changes that should never have been</title> 22.518 +<para>\label{sec:undo:aaaiiieee} 22.519 +</para> 22.520 + 22.521 +<para>Most of the time, the <command role="hg-cmd">hg backout</command> command is exactly what you need 22.522 +if you want to undo the effects of a change. It leaves a permanent 22.523 +record of exactly what you did, both when committing the original 22.524 +changeset and when you cleaned up after it. 22.525 +</para> 22.526 + 22.527 +<para>On rare occasions, though, you may find that you've committed a change 22.528 +that really should not be present in the repository at all. For 22.529 +example, it would be very unusual, and usually considered a mistake, 22.530 +to commit a software project's object files as well as its source 22.531 +files. Object files have almost no intrinsic value, and they're 22.532 +<emphasis>big</emphasis>, so they increase the size of the repository and the amount 22.533 +of time it takes to clone or pull changes. 22.534 +</para> 22.535 + 22.536 +<para>Before I discuss the options that you have if you commit a <quote>brown 22.537 +paper bag</quote> change (the kind that's so bad that you want to pull a 22.538 +brown paper bag over your head), let me first discuss some approaches 22.539 +that probably won't work. 22.540 +</para> 22.541 + 22.542 +<para>Since Mercurial treats history as accumulative&emdash;every change builds 22.543 +on top of all changes that preceded it&emdash;you generally can't just make 22.544 +disastrous changes disappear. The one exception is when you've just 22.545 +committed a change, and it hasn't been pushed or pulled into another 22.546 +repository. That's when you can safely use the <command role="hg-cmd">hg rollback</command> 22.547 +command, as I detailed in section <xref linkend="sec:undo:rollback"/>. 22.548 +</para> 22.549 + 22.550 +<para>After you've pushed a bad change to another repository, you 22.551 +<emphasis>could</emphasis> still use <command role="hg-cmd">hg rollback</command> to make your local copy of the 22.552 +change disappear, but it won't have the consequences you want. The 22.553 +change will still be present in the remote repository, so it will 22.554 +reappear in your local repository the next time you pull. 22.555 +</para> 22.556 + 22.557 +<para>If a situation like this arises, and you know which repositories your 22.558 +bad change has propagated into, you can <emphasis>try</emphasis> to get rid of the 22.559 +changeefrom <emphasis>every</emphasis> one of those repositories. This is, of 22.560 +course, not a satisfactory solution: if you miss even a single 22.561 +repository while you're expunging, the change is still <quote>in the 22.562 +wild</quote>, and could propagate further. 22.563 +</para> 22.564 + 22.565 +<para>If you've committed one or more changes <emphasis>after</emphasis> the change that 22.566 +you'd like to see disappear, your options are further reduced. 22.567 +Mercurial doesn't provide a way to <quote>punch a hole</quote> in history, 22.568 +leaving changesets intact. 22.569 +</para> 22.570 + 22.571 +<para>XXX This needs filling out. The <literal>hg-replay</literal> script in the 22.572 +<literal>examples</literal> directory works, but doesn't handle merge 22.573 +changesets. Kind of an important omission. 22.574 +</para> 22.575 + 22.576 +<sect2> 22.577 +<title>Protect yourself from <quote>escaped</quote> changes</title> 22.578 + 22.579 +<para>If you've committed some changes to your local repository and they've 22.580 +been pushed or pulled somewhere else, this isn't necessarily a 22.581 +disaster. You can protect yourself ahead of time against some classes 22.582 +of bad changeset. This is particularly easy if your team usually 22.583 +pulls changes from a central repository. 22.584 +</para> 22.585 + 22.586 +<para>By configuring some hooks on that repository to validate incoming 22.587 +changesets (see chapter <xref linkend="chap:hook"/>), you can automatically 22.588 +prevent some kinds of bad changeset from being pushed to the central 22.589 +repository at all. With such a configuration in place, some kinds of 22.590 +bad changeset will naturally tend to <quote>die out</quote> because they can't 22.591 +propagate into the central repository. Better yet, this happens 22.592 +without any need for explicit intervention. 22.593 +</para> 22.594 + 22.595 +<para>For instance, an incoming change hook that verifies that a changeset 22.596 +will actually compile can prevent people from inadvertantly <quote>breaking 22.597 +the build</quote>. 22.598 +</para> 22.599 + 22.600 +</sect2> 22.601 +</sect1> 22.602 +<sect1> 22.603 +<title>Finding the source of a bug</title> 22.604 +<para>\label{sec:undo:bisect} 22.605 +</para> 22.606 + 22.607 +<para>While it's all very well to be able to back out a changeset that 22.608 +introduced a bug, this requires that you know which changeset to back 22.609 +out. Mercurial provides an invaluable command, called 22.610 +<command role="hg-cmd">hg bisect</command>, that helps you to automate this process and accomplish 22.611 +it very efficiently. 22.612 +</para> 22.613 + 22.614 +<para>The idea behind the <command role="hg-cmd">hg bisect</command> command is that a changeset has 22.615 +introduced some change of behaviour that you can identify with a 22.616 +simple binary test. You don't know which piece of code introduced the 22.617 +change, but you know how to test for the presence of the bug. The 22.618 +<command role="hg-cmd">hg bisect</command> command uses your test to direct its search for the 22.619 +changeset that introduced the code that caused the bug. 22.620 +</para> 22.621 + 22.622 +<para>Here are a few scenarios to help you understand how you might apply 22.623 +this command. 22.624 +</para> 22.625 +<itemizedlist> 22.626 +<listitem><para>The most recent version of your software has a bug that you 22.627 + remember wasn't present a few weeks ago, but you don't know when it 22.628 + was introduced. Here, your binary test checks for the presence of 22.629 + that bug. 22.630 +</para> 22.631 +</listitem> 22.632 +<listitem><para>You fixed a bug in a rush, and now it's time to close the entry 22.633 + in your team's bug database. The bug database requires a changeset 22.634 + ID when you close an entry, but you don't remember which changeset 22.635 + you fixed the bug in. Once again, your binary test checks for the 22.636 + presence of the bug. 22.637 +</para> 22.638 +</listitem> 22.639 +<listitem><para>Your software works correctly, but runs 15% slower than the 22.640 + last time you measured it. You want to know which changeset 22.641 + introduced the performance regression. In this case, your binary 22.642 + test measures the performance of your software, to see whether it's 22.643 + <quote>fast</quote> or <quote>slow</quote>. 22.644 +</para> 22.645 +</listitem> 22.646 +<listitem><para>The sizes of the components of your project that you ship 22.647 + exploded recently, and you suspect that something changed in the way 22.648 + you build your project. 22.649 +</para> 22.650 +</listitem></itemizedlist> 22.651 + 22.652 +<para>From these examples, it should be clear that the <command role="hg-cmd">hg bisect</command> 22.653 +command is not useful only for finding the sources of bugs. You can 22.654 +use it to find any <quote>emergent property</quote> of a repository (anything 22.655 +that you can't find from a simple text search of the files in the 22.656 +tree) for which you can write a binary test. 22.657 +</para> 22.658 + 22.659 +<para>We'll introduce a little bit of terminology here, just to make it 22.660 +clear which parts of the search process are your responsibility, and 22.661 +which are Mercurial's. A <emphasis>test</emphasis> is something that <emphasis>you</emphasis> run 22.662 +when <command role="hg-cmd">hg bisect</command> chooses a changeset. A <emphasis>probe</emphasis> is what 22.663 +<command role="hg-cmd">hg bisect</command> runs to tell whether a revision is good. Finally, 22.664 +we'll use the word <quote>bisect</quote>, as both a noun and a verb, to stand in 22.665 +for the phrase <quote>search using the <command role="hg-cmd">hg bisect</command> command. 22.666 +</para> 22.667 + 22.668 +<para>One simple way to automate the searching process would be simply to 22.669 +probe every changeset. However, this scales poorly. If it took ten 22.670 +minutes to test a single changeset, and you had 10,000 changesets in 22.671 +your repository, the exhaustive approach would take on average 35 22.672 +<emphasis>days</emphasis> to find the changeset that introduced a bug. Even if you 22.673 +knew that the bug was introduced by one of the last 500 changesets, 22.674 +and limited your search to those, you'd still be looking at over 40 22.675 +hours to find the changeset that introduced your bug. 22.676 +</para> 22.677 + 22.678 +<para>What the <command role="hg-cmd">hg bisect</command> command does is use its knowledge of the 22.679 +<quote>shape</quote> of your project's revision history to perform a search in 22.680 +time proportional to the <emphasis>logarithm</emphasis> of the number of changesets 22.681 +to check (the kind of search it performs is called a dichotomic 22.682 +search). With this approach, searching through 10,000 changesets will 22.683 +take less than three hours, even at ten minutes per test (the search 22.684 +will require about 14 tests). Limit your search to the last hundred 22.685 +changesets, and it will take only about an hour (roughly seven tests). 22.686 +</para> 22.687 + 22.688 +<para>The <command role="hg-cmd">hg bisect</command> command is aware of the <quote>branchy</quote> nature of a 22.689 +Mercurial project's revision history, so it has no problems dealing 22.690 +with branches, merges, or multiple heads in a repository. It can 22.691 +prune entire branches of history with a single probe, which is how it 22.692 +operates so efficiently. 22.693 +</para> 22.694 + 22.695 +<sect2> 22.696 +<title>Using the <command role="hg-cmd">hg bisect</command> command</title> 22.697 + 22.698 +<para>Here's an example of <command role="hg-cmd">hg bisect</command> in action. 22.699 +</para> 22.700 + 22.701 +<note> 22.702 +<para> In versions 0.9.5 and earlier of Mercurial, <command role="hg-cmd">hg bisect</command> was not a 22.703 + core command: it was distributed with Mercurial as an extension. 22.704 + This section describes the built-in command, not the old extension. 22.705 +</para> 22.706 +</note> 22.707 + 22.708 +<para>Now let's create a repository, so that we can try out the 22.709 +<command role="hg-cmd">hg bisect</command> command in isolation. 22.710 +<!-- &interaction.bisect.init; --> 22.711 +We'll simulate a project that has a bug in it in a simple-minded way: 22.712 +create trivial changes in a loop, and nominate one specific change 22.713 +that will have the <quote>bug</quote>. This loop creates 35 changesets, each 22.714 +adding a single file to the repository. We'll represent our <quote>bug</quote> 22.715 +with a file that contains the text <quote>i have a gub</quote>. 22.716 +<!-- &interaction.bisect.commits; --> 22.717 +</para> 22.718 + 22.719 +<para>The next thing that we'd like to do is figure out how to use the 22.720 +<command role="hg-cmd">hg bisect</command> command. We can use Mercurial's normal built-in help 22.721 +mechanism for this. 22.722 +<!-- &interaction.bisect.help; --> 22.723 +</para> 22.724 + 22.725 +<para>The <command role="hg-cmd">hg bisect</command> command works in steps. Each step proceeds as follows. 22.726 +</para> 22.727 +<orderedlist> 22.728 +<listitem><para>You run your binary test. 22.729 +</para> 22.730 +</listitem><itemizedlist> 22.731 +<listitem><para> \item If the test succeeded, you tell <command role="hg-cmd">hg bisect</command> by running the 22.732 + <command role="hg-cmd">hg bisect good</command> command. 22.733 + \item If it failed, run the <command role="hg-cmd">hg bisect --bad</command> command. 22.734 +</para> 22.735 +</listitem></itemizedlist> 22.736 +<listitem><para>The command uses your information to decide which changeset to 22.737 + test next. 22.738 +</para> 22.739 +</listitem> 22.740 +<listitem><para>It updates the working directory to that changeset, and the 22.741 + process begins again. 22.742 +</para> 22.743 +</listitem></orderedlist> 22.744 +<para>The process ends when <command role="hg-cmd">hg bisect</command> identifies a unique changeset 22.745 +that marks the point where your test transitioned from <quote>succeeding</quote> 22.746 +to <quote>failing</quote>. 22.747 +</para> 22.748 + 22.749 +<para>To start the search, we must run the <command role="hg-cmd">hg bisect --reset</command> command. 22.750 +<!-- &interaction.bisect.search.init; --> 22.751 +</para> 22.752 + 22.753 +<para>In our case, the binary test we use is simple: we check to see if any 22.754 +file in the repository contains the string <quote>i have a gub</quote>. If it 22.755 +does, this changeset contains the change that <quote>caused the bug</quote>. By 22.756 +convention, a changeset that has the property we're searching for is 22.757 +<quote>bad</quote>, while one that doesn't is <quote>good</quote>. 22.758 +</para> 22.759 + 22.760 +<para>Most of the time, the revision to which the working directory is 22.761 +synced (usually the tip) already exhibits the problem introduced by 22.762 +the buggy change, so we'll mark it as <quote>bad</quote>. 22.763 +<!-- &interaction.bisect.search.bad-init; --> 22.764 +</para> 22.765 + 22.766 +<para>Our next task is to nominate a changeset that we know <emphasis>doesn't</emphasis> 22.767 +have the bug; the <command role="hg-cmd">hg bisect</command> command will <quote>bracket</quote> its search 22.768 +between the first pair of good and bad changesets. In our case, we 22.769 +know that revision 10 didn't have the bug. (I'll have more words 22.770 +about choosing the first <quote>good</quote> changeset later.) 22.771 +<!-- &interaction.bisect.search.good-init; --> 22.772 +</para> 22.773 + 22.774 +<para>Notice that this command printed some output. 22.775 +</para> 22.776 +<itemizedlist> 22.777 +<listitem><para>It told us how many changesets it must consider before it can 22.778 + identify the one that introduced the bug, and how many tests that 22.779 + will require. 22.780 +</para> 22.781 +</listitem> 22.782 +<listitem><para>It updated the working directory to the next changeset to test, 22.783 + and told us which changeset it's testing. 22.784 +</para> 22.785 +</listitem></itemizedlist> 22.786 + 22.787 +<para>We now run our test in the working directory. We use the 22.788 +<command>grep</command> command to see if our <quote>bad</quote> file is present in the 22.789 +working directory. If it is, this revision is bad; if not, this 22.790 +revision is good. 22.791 +<!-- &interaction.bisect.search.step1; --> 22.792 +</para> 22.793 + 22.794 +<para>This test looks like a perfect candidate for automation, so let's turn 22.795 +it into a shell function. 22.796 +<!-- &interaction.bisect.search.mytest; --> 22.797 +We can now run an entire test step with a single command, 22.798 +<literal>mytest</literal>. 22.799 +<!-- &interaction.bisect.search.step2; --> 22.800 +A few more invocations of our canned test step command, and we're 22.801 +done. 22.802 +<!-- &interaction.bisect.search.rest; --> 22.803 +</para> 22.804 + 22.805 +<para>Even though we had 40 changesets to search through, the <command role="hg-cmd">hg bisect</command> 22.806 +command let us find the changeset that introduced our <quote>bug</quote> with 22.807 +only five tests. Because the number of tests that the <command role="hg-cmd">hg bisect</command> 22.808 +command performs grows logarithmically with the number of changesets to 22.809 +search, the advantage that it has over the <quote>brute force</quote> search 22.810 +approach increases with every changeset you add. 22.811 +</para> 22.812 + 22.813 +</sect2> 22.814 +<sect2> 22.815 +<title>Cleaning up after your search</title> 22.816 + 22.817 +<para>When you're finished using the <command role="hg-cmd">hg bisect</command> command in a 22.818 +repository, you can use the <command role="hg-cmd">hg bisect reset</command> command to drop 22.819 +the information it was using to drive your search. The command 22.820 +doesn't use much space, so it doesn't matter if you forget to run this 22.821 +command. However, <command role="hg-cmd">hg bisect</command> won't let you start a new search in 22.822 +that repository until you do a <command role="hg-cmd">hg bisect reset</command>. 22.823 +<!-- &interaction.bisect.search.reset; --> 22.824 +</para> 22.825 + 22.826 +</sect2> 22.827 +</sect1> 22.828 +<sect1> 22.829 +<title>Tips for finding bugs effectively</title> 22.830 + 22.831 +<sect2> 22.832 +<title>Give consistent input</title> 22.833 + 22.834 +<para>The <command role="hg-cmd">hg bisect</command> command requires that you correctly report the 22.835 +result of every test you perform. If you tell it that a test failed 22.836 +when it really succeeded, it <emphasis>might</emphasis> be able to detect the 22.837 +inconsistency. If it can identify an inconsistency in your reports, 22.838 +it will tell you that a particular changeset is both good and bad. 22.839 +However, it can't do this perfectly; it's about as likely to report 22.840 +the wrong changeset as the source of the bug. 22.841 +</para> 22.842 + 22.843 +</sect2> 22.844 +<sect2> 22.845 +<title>Automate as much as possible</title> 22.846 + 22.847 +<para>When I started using the <command role="hg-cmd">hg bisect</command> command, I tried a few times 22.848 +to run my tests by hand, on the command line. This is an approach 22.849 +that I, at least, am not suited to. After a few tries, I found that I 22.850 +was making enough mistakes that I was having to restart my searches 22.851 +several times before finally getting correct results. 22.852 +</para> 22.853 + 22.854 +<para>My initial problems with driving the <command role="hg-cmd">hg bisect</command> command by hand 22.855 +occurred even with simple searches on small repositories; if the 22.856 +problem you're looking for is more subtle, or the number of tests that 22.857 +<command role="hg-cmd">hg bisect</command> must perform increases, the likelihood of operator 22.858 +error ruining the search is much higher. Once I started automating my 22.859 +tests, I had much better results. 22.860 +</para> 22.861 + 22.862 +<para>The key to automated testing is twofold: 22.863 +</para> 22.864 +<itemizedlist> 22.865 +<listitem><para>always test for the same symptom, and 22.866 +</para> 22.867 +</listitem> 22.868 +<listitem><para>always feed consistent input to the <command role="hg-cmd">hg bisect</command> command. 22.869 +</para> 22.870 +</listitem></itemizedlist> 22.871 +<para>In my tutorial example above, the <command>grep</command> command tests for the 22.872 +symptom, and the <literal>if</literal> statement takes the result of this check 22.873 +and ensures that we always feed the same input to the <command role="hg-cmd">hg bisect</command> 22.874 +command. The <literal>mytest</literal> function marries these together in a 22.875 +reproducible way, so that every test is uniform and consistent. 22.876 +</para> 22.877 + 22.878 +</sect2> 22.879 +<sect2> 22.880 +<title>Check your results</title> 22.881 + 22.882 +<para>Because the output of a <command role="hg-cmd">hg bisect</command> search is only as good as the 22.883 +input you give it, don't take the changeset it reports as the 22.884 +absolute truth. A simple way to cross-check its report is to manually 22.885 +run your test at each of the following changesets: 22.886 +</para> 22.887 +<itemizedlist> 22.888 +<listitem><para>The changeset that it reports as the first bad revision. Your 22.889 + test should still report this as bad. 22.890 +</para> 22.891 +</listitem> 22.892 +<listitem><para>The parent of that changeset (either parent, if it's a merge). 22.893 + Your test should report this changeset as good. 22.894 +</para> 22.895 +</listitem> 22.896 +<listitem><para>A child of that changeset. Your test should report this 22.897 + changeset as bad. 22.898 +</para> 22.899 +</listitem></itemizedlist> 22.900 + 22.901 +</sect2> 22.902 +<sect2> 22.903 +<title>Beware interference between bugs</title> 22.904 + 22.905 +<para>It's possible that your search for one bug could be disrupted by the 22.906 +presence of another. For example, let's say your software crashes at 22.907 +revision 100, and worked correctly at revision 50. Unknown to you, 22.908 +someone else introduced a different crashing bug at revision 60, and 22.909 +fixed it at revision 80. This could distort your results in one of 22.910 +several ways. 22.911 +</para> 22.912 + 22.913 +<para>It is possible that this other bug completely <quote>masks</quote> yours, which 22.914 +is to say that it occurs before your bug has a chance to manifest 22.915 +itself. If you can't avoid that other bug (for example, it prevents 22.916 +your project from building), and so can't tell whether your bug is 22.917 +present in a particular changeset, the <command role="hg-cmd">hg bisect</command> command cannot 22.918 +help you directly. Instead, you can mark a changeset as untested by 22.919 +running <command role="hg-cmd">hg bisect --skip</command>. 22.920 +</para> 22.921 + 22.922 +<para>A different problem could arise if your test for a bug's presence is 22.923 +not specific enough. If you check for <quote>my program crashes</quote>, then 22.924 +both your crashing bug and an unrelated crashing bug that masks it 22.925 +will look like the same thing, and mislead <command role="hg-cmd">hg bisect</command>. 22.926 +</para> 22.927 + 22.928 +<para>Another useful situation in which to use <command role="hg-cmd">hg bisect --skip</command> is 22.929 +if you can't test a revision because your project was in a broken and 22.930 +hence untestable state at that revision, perhaps because someone 22.931 +checked in a change that prevented the project from building. 22.932 +</para> 22.933 + 22.934 +</sect2> 22.935 +<sect2> 22.936 +<title>Bracket your search lazily</title> 22.937 + 22.938 +<para>Choosing the first <quote>good</quote> and <quote>bad</quote> changesets that will mark the 22.939 +end points of your search is often easy, but it bears a little 22.940 +discussion nevertheless. From the perspective of <command role="hg-cmd">hg bisect</command>, the 22.941 +<quote>newest</quote> changeset is conventionally <quote>bad</quote>, and the older 22.942 +changeset is <quote>good</quote>. 22.943 +</para> 22.944 + 22.945 +<para>If you're having trouble remembering when a suitable <quote>good</quote> change 22.946 +was, so that you can tell <command role="hg-cmd">hg bisect</command>, you could do worse than 22.947 +testing changesets at random. Just remember to eliminate contenders 22.948 +that can't possibly exhibit the bug (perhaps because the feature with 22.949 +the bug isn't present yet) and those where another problem masks the 22.950 +bug (as I discussed above). 22.951 +</para> 22.952 + 22.953 +<para>Even if you end up <quote>early</quote> by thousands of changesets or months of 22.954 +history, you will only add a handful of tests to the total number that 22.955 +<command role="hg-cmd">hg bisect</command> must perform, thanks to its logarithmic behaviour. 22.956 +</para> 22.957 + 22.958 +</sect2> 22.959 +</sect1> 22.960 +</chapter> 22.961 + 22.962 +<!-- 22.963 +local variables: 22.964 +sgml-parent-document: ("00book.xml" "book" "chapter") 22.965 +end: 22.966 +--> 22.967 \ No newline at end of file
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 23.2 +++ b/fr/ch10-hook.xml Sun Aug 16 04:58:01 2009 +0200 23.3 @@ -0,0 +1,1883 @@ 23.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 23.5 + 23.6 +<chapter> 23.7 +<title>Handling repository events with hooks</title> 23.8 +<para>\label{chap:hook}</para> 23.9 + 23.10 +<para>Mercurial offers a powerful mechanism to let you perform automated 23.11 +actions in response to events that occur in a repository. In some 23.12 +cases, you can even control Mercurial's response to those events.</para> 23.13 + 23.14 +<para>The name Mercurial uses for one of these actions is a <emphasis>hook</emphasis>. 23.15 +Hooks are called <quote>triggers</quote> in some revision control systems, but 23.16 +the two names refer to the same idea.</para> 23.17 + 23.18 +<sect1> 23.19 +<title>An overview of hooks in Mercurial</title> 23.20 + 23.21 +<para>Here is a brief list of the hooks that Mercurial supports. We will 23.22 +revisit each of these hooks in more detail later, in 23.23 +section <xref linkend="sec:hook:ref"/>.</para> 23.24 + 23.25 +<itemizedlist> 23.26 +<listitem><para><literal role="hook">changegroup</literal>: This is run after a group of 23.27 + changesets has been brought into the repository from elsewhere.</para> 23.28 +</listitem> 23.29 +<listitem><para><literal role="hook">commit</literal>: This is run after a new changeset has been 23.30 + created in the local repository.</para> 23.31 +</listitem> 23.32 +<listitem><para><literal role="hook">incoming</literal>: This is run once for each new changeset 23.33 + that is brought into the repository from elsewhere. Notice the 23.34 + difference from <literal role="hook">changegroup</literal>, which is run once per 23.35 + <emphasis>group</emphasis> of changesets brought in.</para> 23.36 +</listitem> 23.37 +<listitem><para><literal role="hook">outgoing</literal>: This is run after a group of changesets 23.38 + has been transmitted from this repository.</para> 23.39 +</listitem> 23.40 +<listitem><para><literal role="hook">prechangegroup</literal>: This is run before starting to 23.41 + bring a group of changesets into the repository. 23.42 +</para> 23.43 +</listitem> 23.44 +<listitem><para><literal role="hook">precommit</literal>: Controlling. This is run before starting 23.45 + a commit. 23.46 +</para> 23.47 +</listitem> 23.48 +<listitem><para><literal role="hook">preoutgoing</literal>: Controlling. This is run before 23.49 + starting to transmit a group of changesets from this repository. 23.50 +</para> 23.51 +</listitem> 23.52 +<listitem><para><literal role="hook">pretag</literal>: Controlling. This is run before creating a tag. 23.53 +</para> 23.54 +</listitem> 23.55 +<listitem><para><literal role="hook">pretxnchangegroup</literal>: Controlling. This is run after a 23.56 + group of changesets has been brought into the local repository from 23.57 + another, but before the transaction completes that will make the 23.58 + changes permanent in the repository. 23.59 +</para> 23.60 +</listitem> 23.61 +<listitem><para><literal role="hook">pretxncommit</literal>: Controlling. This is run after a new 23.62 + changeset has been created in the local repository, but before the 23.63 + transaction completes that will make it permanent. 23.64 +</para> 23.65 +</listitem> 23.66 +<listitem><para><literal role="hook">preupdate</literal>: Controlling. This is run before starting 23.67 + an update or merge of the working directory. 23.68 +</para> 23.69 +</listitem> 23.70 +<listitem><para><literal role="hook">tag</literal>: This is run after a tag is created. 23.71 +</para> 23.72 +</listitem> 23.73 +<listitem><para><literal role="hook">update</literal>: This is run after an update or merge of the 23.74 + working directory has finished. 23.75 +</para> 23.76 +</listitem></itemizedlist> 23.77 +<para>Each of the hooks whose description begins with the word 23.78 +<quote>Controlling</quote> has the ability to determine whether an activity can 23.79 +proceed. If the hook succeeds, the activity may proceed; if it fails, 23.80 +the activity is either not permitted or undone, depending on the hook. 23.81 +</para> 23.82 + 23.83 +</sect1> 23.84 +<sect1> 23.85 +<title>Hooks and security</title> 23.86 + 23.87 +<sect2> 23.88 +<title>Hooks are run with your privileges</title> 23.89 + 23.90 +<para>When you run a Mercurial command in a repository, and the command 23.91 +causes a hook to run, that hook runs on <emphasis>your</emphasis> system, under 23.92 +<emphasis>your</emphasis> user account, with <emphasis>your</emphasis> privilege level. Since 23.93 +hooks are arbitrary pieces of executable code, you should treat them 23.94 +with an appropriate level of suspicion. Do not install a hook unless 23.95 +you are confident that you know who created it and what it does. 23.96 +</para> 23.97 + 23.98 +<para>In some cases, you may be exposed to hooks that you did not install 23.99 +yourself. If you work with Mercurial on an unfamiliar system, 23.100 +Mercurial will run hooks defined in that system's global <filename role="special"> /.hgrc</filename>\ file. 23.101 +</para> 23.102 + 23.103 +<para>If you are working with a repository owned by another user, Mercurial 23.104 +can run hooks defined in that user's repository, but it will still run 23.105 +them as <quote>you</quote>. For example, if you <command role="hg-cmd">hg pull</command> from that 23.106 +repository, and its <filename role="special">.hg/hgrc</filename> defines a local 23.107 +<literal role="hook">outgoing</literal> hook, that hook will run under your user account, even 23.108 +though you don't own that repository. 23.109 +</para> 23.110 + 23.111 +<note> 23.112 +<para> This only applies if you are pulling from a repository on a local or 23.113 + network filesystem. If you're pulling over http or ssh, any 23.114 + <literal role="hook">outgoing</literal> hook will run under whatever account is executing 23.115 + the server process, on the server. 23.116 +</para> 23.117 +</note> 23.118 + 23.119 +<para>XXX To see what hooks are defined in a repository, use the 23.120 +<command role="hg-cmd">hg config hooks</command> command. If you are working in one 23.121 +repository, but talking to another that you do not own (e.g. using 23.122 +<command role="hg-cmd">hg pull</command> or <command role="hg-cmd">hg incoming</command>), remember that it is the other 23.123 +repository's hooks you should be checking, not your own. 23.124 +</para> 23.125 + 23.126 +</sect2> 23.127 +<sect2> 23.128 +<title>Hooks do not propagate</title> 23.129 + 23.130 +<para>In Mercurial, hooks are not revision controlled, and do not propagate 23.131 +when you clone, or pull from, a repository. The reason for this is 23.132 +simple: a hook is a completely arbitrary piece of executable code. It 23.133 +runs under your user identity, with your privilege level, on your 23.134 +machine. 23.135 +</para> 23.136 + 23.137 +<para>It would be extremely reckless for any distributed revision control 23.138 +system to implement revision-controlled hooks, as this would offer an 23.139 +easily exploitable way to subvert the accounts of users of the 23.140 +revision control system. 23.141 +</para> 23.142 + 23.143 +<para>Since Mercurial does not propagate hooks, if you are collaborating 23.144 +with other people on a common project, you should not assume that they 23.145 +are using the same Mercurial hooks as you are, or that theirs are 23.146 +correctly configured. You should document the hooks you expect people 23.147 +to use. 23.148 +</para> 23.149 + 23.150 +<para>In a corporate intranet, this is somewhat easier to control, as you 23.151 +can for example provide a <quote>standard</quote> installation of Mercurial on an 23.152 +NFS filesystem, and use a site-wide <filename role="special"> /.hgrc</filename>\ file to define hooks that 23.153 +all users will see. However, this too has its limits; see below. 23.154 +</para> 23.155 + 23.156 +</sect2> 23.157 +<sect2> 23.158 +<title>Hooks can be overridden</title> 23.159 + 23.160 +<para>Mercurial allows you to override a hook definition by redefining the 23.161 +hook. You can disable it by setting its value to the empty string, or 23.162 +change its behaviour as you wish. 23.163 +</para> 23.164 + 23.165 +<para>If you deploy a system- or site-wide <filename role="special"> /.hgrc</filename>\ file that defines some 23.166 +hooks, you should thus understand that your users can disable or 23.167 +override those hooks. 23.168 +</para> 23.169 + 23.170 +</sect2> 23.171 +<sect2> 23.172 +<title>Ensuring that critical hooks are run</title> 23.173 + 23.174 +<para>Sometimes you may want to enforce a policy that you do not want others 23.175 +to be able to work around. For example, you may have a requirement 23.176 +that every changeset must pass a rigorous set of tests. Defining this 23.177 +requirement via a hook in a site-wide <filename role="special"> /.hgrc</filename>\ won't work for remote 23.178 +users on laptops, and of course local users can subvert it at will by 23.179 +overriding the hook. 23.180 +</para> 23.181 + 23.182 +<para>Instead, you can set up your policies for use of Mercurial so that 23.183 +people are expected to propagate changes through a well-known 23.184 +<quote>canonical</quote> server that you have locked down and configured 23.185 +appropriately. 23.186 +</para> 23.187 + 23.188 +<para>One way to do this is via a combination of social engineering and 23.189 +technology. Set up a restricted-access account; users can push 23.190 +changes over the network to repositories managed by this account, but 23.191 +they cannot log into the account and run normal shell commands. In 23.192 +this scenario, a user can commit a changeset that contains any old 23.193 +garbage they want. 23.194 +</para> 23.195 + 23.196 +<para>When someone pushes a changeset to the server that everyone pulls 23.197 +from, the server will test the changeset before it accepts it as 23.198 +permanent, and reject it if it fails to pass the test suite. If 23.199 +people only pull changes from this filtering server, it will serve to 23.200 +ensure that all changes that people pull have been automatically 23.201 +vetted. 23.202 +</para> 23.203 + 23.204 +</sect2> 23.205 +</sect1> 23.206 +<sect1> 23.207 +<title>Care with <literal>pretxn</literal> hooks in a shared-access repository</title> 23.208 + 23.209 +<para>If you want to use hooks to do some automated work in a repository 23.210 +that a number of people have shared access to, you need to be careful 23.211 +in how you do this. 23.212 +</para> 23.213 + 23.214 +<para>Mercurial only locks a repository when it is writing to the 23.215 +repository, and only the parts of Mercurial that write to the 23.216 +repository pay attention to locks. Write locks are necessary to 23.217 +prevent multiple simultaneous writers from scribbling on each other's 23.218 +work, corrupting the repository. 23.219 +</para> 23.220 + 23.221 +<para>Because Mercurial is careful with the order in which it reads and 23.222 +writes data, it does not need to acquire a lock when it wants to read 23.223 +data from the repository. The parts of Mercurial that read from the 23.224 +repository never pay attention to locks. This lockless reading scheme 23.225 +greatly increases performance and concurrency. 23.226 +</para> 23.227 + 23.228 +<para>With great performance comes a trade-off, though, one which has the 23.229 +potential to cause you trouble unless you're aware of it. To describe 23.230 +this requires a little detail about how Mercurial adds changesets to a 23.231 +repository and reads those changes. 23.232 +</para> 23.233 + 23.234 +<para>When Mercurial <emphasis>writes</emphasis> metadata, it writes it straight into the 23.235 +destination file. It writes file data first, then manifest data 23.236 +(which contains pointers to the new file data), then changelog data 23.237 +(which contains pointers to the new manifest data). Before the first 23.238 +write to each file, it stores a record of where the end of the file 23.239 +was in its transaction log. If the transaction must be rolled back, 23.240 +Mercurial simply truncates each file back to the size it was before the 23.241 +transaction began. 23.242 +</para> 23.243 + 23.244 +<para>When Mercurial <emphasis>reads</emphasis> metadata, it reads the changelog first, 23.245 +then everything else. Since a reader will only access parts of the 23.246 +manifest or file metadata that it can see in the changelog, it can 23.247 +never see partially written data. 23.248 +</para> 23.249 + 23.250 +<para>Some controlling hooks (<literal role="hook">pretxncommit</literal> and 23.251 +<literal role="hook">pretxnchangegroup</literal>) run when a transaction is almost complete. 23.252 +All of the metadata has been written, but Mercurial can still roll the 23.253 +transaction back and cause the newly-written data to disappear. 23.254 +</para> 23.255 + 23.256 +<para>If one of these hooks runs for long, it opens a window of time during 23.257 +which a reader can see the metadata for changesets that are not yet 23.258 +permanent, and should not be thought of as <quote>really there</quote>. The 23.259 +longer the hook runs, the longer that window is open. 23.260 +</para> 23.261 + 23.262 +<sect2> 23.263 +<title>The problem illustrated</title> 23.264 + 23.265 +<para>In principle, a good use for the <literal role="hook">pretxnchangegroup</literal> hook would 23.266 +be to automatically build and test incoming changes before they are 23.267 +accepted into a central repository. This could let you guarantee that 23.268 +nobody can push changes to this repository that <quote>break the build</quote>. 23.269 +But if a client can pull changes while they're being tested, the 23.270 +usefulness of the test is zero; an unsuspecting someone can pull 23.271 +untested changes, potentially breaking their build. 23.272 +</para> 23.273 + 23.274 +<para>The safest technological answer to this challenge is to set up such a 23.275 +<quote>gatekeeper</quote> repository as <emphasis>unidirectional</emphasis>. Let it take 23.276 +changes pushed in from the outside, but do not allow anyone to pull 23.277 +changes from it (use the <literal role="hook">preoutgoing</literal> hook to lock it down). 23.278 +Configure a <literal role="hook">changegroup</literal> hook so that if a build or test 23.279 +succeeds, the hook will push the new changes out to another repository 23.280 +that people <emphasis>can</emphasis> pull from. 23.281 +</para> 23.282 + 23.283 +<para>In practice, putting a centralised bottleneck like this in place is 23.284 +not often a good idea, and transaction visibility has nothing to do 23.285 +with the problem. As the size of a project&emdash;and the time it takes to 23.286 +build and test&emdash;grows, you rapidly run into a wall with this <quote>try 23.287 +before you buy</quote> approach, where you have more changesets to test than 23.288 +time in which to deal with them. The inevitable result is frustration 23.289 +on the part of all involved. 23.290 +</para> 23.291 + 23.292 +<para>An approach that scales better is to get people to build and test 23.293 +before they push, then run automated builds and tests centrally 23.294 +<emphasis>after</emphasis> a push, to be sure all is well. The advantage of this 23.295 +approach is that it does not impose a limit on the rate at which the 23.296 +repository can accept changes. 23.297 +</para> 23.298 + 23.299 +</sect2> 23.300 +</sect1> 23.301 +<sect1> 23.302 +<title>A short tutorial on using hooks</title> 23.303 +<para>\label{sec:hook:simple} 23.304 +</para> 23.305 + 23.306 +<para>It is easy to write a Mercurial hook. Let's start with a hook that 23.307 +runs when you finish a <command role="hg-cmd">hg commit</command>, and simply prints the hash of 23.308 +the changeset you just created. The hook is called <literal role="hook">commit</literal>. 23.309 +</para> 23.310 + 23.311 +<informalfigure> 23.312 +<para> <!-- &interaction.hook.simple.init; --> 23.313 + <caption><para>A simple hook that runs when a changeset is committed</para></caption> 23.314 + \label{ex:hook:init} 23.315 +</para> 23.316 +</informalfigure> 23.317 + 23.318 +<para>All hooks follow the pattern in example <xref linkend="ex:hook:init"/>. You add 23.319 +an entry to the <literal role="rc-hooks">hooks</literal> section of your <filename role="special"> /.hgrc</filename>. On the left 23.320 +is the name of the event to trigger on; on the right is the action to 23.321 +take. As you can see, you can run an arbitrary shell command in a 23.322 +hook. Mercurial passes extra information to the hook using 23.323 +environment variables (look for <envar>HG_NODE</envar> in the example). 23.324 +</para> 23.325 + 23.326 +<sect2> 23.327 +<title>Performing multiple actions per event</title> 23.328 + 23.329 +<para>Quite often, you will want to define more than one hook for a 23.330 +particular kind of event, as shown in example <xref linkend="ex:hook:ext"/>. 23.331 +Mercurial lets you do this by adding an <emphasis>extension</emphasis> to the end of 23.332 +a hook's name. You extend a hook's name by giving the name of the 23.333 +hook, followed by a full stop (the <quote><literal>.</literal></quote> character), followed 23.334 +by some more text of your choosing. For example, Mercurial will run 23.335 +both <literal>commit.foo</literal> and <literal>commit.bar</literal> when the 23.336 +<literal>commit</literal> event occurs. 23.337 +</para> 23.338 + 23.339 +<informalfigure> 23.340 +<para> <!-- &interaction.hook.simple.ext; --> 23.341 + <caption><para>Defining a second <literal role="hook">commit</para></caption> hook</literal> 23.342 + \label{ex:hook:ext} 23.343 +</para> 23.344 +</informalfigure> 23.345 + 23.346 +<para>To give a well-defined order of execution when there are multiple 23.347 +hooks defined for an event, Mercurial sorts hooks by extension, and 23.348 +executes the hook commands in this sorted order. In the above 23.349 +example, it will execute <literal>commit.bar</literal> before 23.350 +<literal>commit.foo</literal>, and <literal>commit</literal> before both. 23.351 +</para> 23.352 + 23.353 +<para>It is a good idea to use a somewhat descriptive extension when you 23.354 +define a new hook. This will help you to remember what the hook was 23.355 +for. If the hook fails, you'll get an error message that contains the 23.356 +hook name and extension, so using a descriptive extension could give 23.357 +you an immediate hint as to why the hook failed (see 23.358 +section <xref linkend="sec:hook:perm"/> for an example). 23.359 +</para> 23.360 + 23.361 +</sect2> 23.362 +<sect2> 23.363 +<title>Controlling whether an activity can proceed</title> 23.364 +<para>\label{sec:hook:perm} 23.365 +</para> 23.366 + 23.367 +<para>In our earlier examples, we used the <literal role="hook">commit</literal> hook, which is 23.368 +run after a commit has completed. This is one of several Mercurial 23.369 +hooks that run after an activity finishes. Such hooks have no way of 23.370 +influencing the activity itself. 23.371 +</para> 23.372 + 23.373 +<para>Mercurial defines a number of events that occur before an activity 23.374 +starts; or after it starts, but before it finishes. Hooks that 23.375 +trigger on these events have the added ability to choose whether the 23.376 +activity can continue, or will abort. 23.377 +</para> 23.378 + 23.379 +<para>The <literal role="hook">pretxncommit</literal> hook runs after a commit has all but 23.380 +completed. In other words, the metadata representing the changeset 23.381 +has been written out to disk, but the transaction has not yet been 23.382 +allowed to complete. The <literal role="hook">pretxncommit</literal> hook has the ability to 23.383 +decide whether the transaction can complete, or must be rolled back. 23.384 +</para> 23.385 + 23.386 +<para>If the <literal role="hook">pretxncommit</literal> hook exits with a status code of zero, the 23.387 +transaction is allowed to complete; the commit finishes; and the 23.388 +<literal role="hook">commit</literal> hook is run. If the <literal role="hook">pretxncommit</literal> hook exits with 23.389 +a non-zero status code, the transaction is rolled back; the metadata 23.390 +representing the changeset is erased; and the <literal role="hook">commit</literal> hook is 23.391 +not run. 23.392 +</para> 23.393 + 23.394 +<informalfigure> 23.395 +<para> <!-- &interaction.hook.simple.pretxncommit; --> 23.396 + <caption><para>Using the <literal role="hook">pretxncommit</para></caption> hook to control commits</literal> 23.397 + \label{ex:hook:pretxncommit} 23.398 +</para> 23.399 +</informalfigure> 23.400 + 23.401 +<para>The hook in example <xref linkend="ex:hook:pretxncommit"/> checks that a commit 23.402 +comment contains a bug ID. If it does, the commit can complete. If 23.403 +not, the commit is rolled back. 23.404 +</para> 23.405 + 23.406 +</sect2> 23.407 +</sect1> 23.408 +<sect1> 23.409 +<title>Writing your own hooks</title> 23.410 + 23.411 +<para>When you are writing a hook, you might find it useful to run Mercurial 23.412 +either with the <option role="hg-opt-global">-v</option> option, or the <envar role="rc-item-ui">verbose</envar> config 23.413 +item set to <quote>true</quote>. When you do so, Mercurial will print a message 23.414 +before it calls each hook. 23.415 +</para> 23.416 + 23.417 +<sect2> 23.418 +<title>Choosing how your hook should run</title> 23.419 +<para>\label{sec:hook:lang} 23.420 +</para> 23.421 + 23.422 +<para>You can write a hook either as a normal program&emdash;typically a shell 23.423 +script&emdash;or as a Python function that is executed within the Mercurial 23.424 +process. 23.425 +</para> 23.426 + 23.427 +<para>Writing a hook as an external program has the advantage that it 23.428 +requires no knowledge of Mercurial's internals. You can call normal 23.429 +Mercurial commands to get any added information you need. The 23.430 +trade-off is that external hooks are slower than in-process hooks. 23.431 +</para> 23.432 + 23.433 +<para>An in-process Python hook has complete access to the Mercurial API, 23.434 +and does not <quote>shell out</quote> to another process, so it is inherently 23.435 +faster than an external hook. It is also easier to obtain much of the 23.436 +information that a hook requires by using the Mercurial API than by 23.437 +running Mercurial commands. 23.438 +</para> 23.439 + 23.440 +<para>If you are comfortable with Python, or require high performance, 23.441 +writing your hooks in Python may be a good choice. However, when you 23.442 +have a straightforward hook to write and you don't need to care about 23.443 +performance (probably the majority of hooks), a shell script is 23.444 +perfectly fine. 23.445 +</para> 23.446 + 23.447 +</sect2> 23.448 +<sect2> 23.449 +<title>Hook parameters</title> 23.450 +<para>\label{sec:hook:param} 23.451 +</para> 23.452 + 23.453 +<para>Mercurial calls each hook with a set of well-defined parameters. In 23.454 +Python, a parameter is passed as a keyword argument to your hook 23.455 +function. For an external program, a parameter is passed as an 23.456 +environment variable. 23.457 +</para> 23.458 + 23.459 +<para>Whether your hook is written in Python or as a shell script, the 23.460 +hook-specific parameter names and values will be the same. A boolean 23.461 +parameter will be represented as a boolean value in Python, but as the 23.462 +number 1 (for <quote>true</quote>) or 0 (for <quote>false</quote>) as an environment 23.463 +variable for an external hook. If a hook parameter is named 23.464 +<literal>foo</literal>, the keyword argument for a Python hook will also be 23.465 +named <literal>foo</literal>, while the environment variable for an external 23.466 +hook will be named <literal>HG_FOO</literal>. 23.467 +</para> 23.468 + 23.469 +</sect2> 23.470 +<sect2> 23.471 +<title>Hook return values and activity control</title> 23.472 + 23.473 +<para>A hook that executes successfully must exit with a status of zero if 23.474 +external, or return boolean <quote>false</quote> if in-process. Failure is 23.475 +indicated with a non-zero exit status from an external hook, or an 23.476 +in-process hook returning boolean <quote>true</quote>. If an in-process hook 23.477 +raises an exception, the hook is considered to have failed. 23.478 +</para> 23.479 + 23.480 +<para>For a hook that controls whether an activity can proceed, zero/false 23.481 +means <quote>allow</quote>, while non-zero/true/exception means <quote>deny</quote>. 23.482 +</para> 23.483 + 23.484 +</sect2> 23.485 +<sect2> 23.486 +<title>Writing an external hook</title> 23.487 + 23.488 +<para>When you define an external hook in your <filename role="special"> /.hgrc</filename>\ and the hook is run, 23.489 +its value is passed to your shell, which interprets it. This means 23.490 +that you can use normal shell constructs in the body of the hook. 23.491 +</para> 23.492 + 23.493 +<para>An executable hook is always run with its current directory set to a 23.494 +repository's root directory. 23.495 +</para> 23.496 + 23.497 +<para>Each hook parameter is passed in as an environment variable; the name 23.498 +is upper-cased, and prefixed with the string <quote><literal>HG_</literal></quote>. 23.499 +</para> 23.500 + 23.501 +<para>With the exception of hook parameters, Mercurial does not set or 23.502 +modify any environment variables when running a hook. This is useful 23.503 +to remember if you are writing a site-wide hook that may be run by a 23.504 +number of different users with differing environment variables set. 23.505 +In multi-user situations, you should not rely on environment variables 23.506 +being set to the values you have in your environment when testing the 23.507 +hook. 23.508 +</para> 23.509 + 23.510 +</sect2> 23.511 +<sect2> 23.512 +<title>Telling Mercurial to use an in-process hook</title> 23.513 + 23.514 +<para>The <filename role="special"> /.hgrc</filename>\ syntax for defining an in-process hook is slightly 23.515 +different than for an executable hook. The value of the hook must 23.516 +start with the text <quote><literal>python:</literal></quote>, and continue with the 23.517 +fully-qualified name of a callable object to use as the hook's value. 23.518 +</para> 23.519 + 23.520 +<para>The module in which a hook lives is automatically imported when a hook 23.521 +is run. So long as you have the module name and <envar>PYTHONPATH</envar> 23.522 +right, it should <quote>just work</quote>. 23.523 +</para> 23.524 + 23.525 +<para>The following <filename role="special"> /.hgrc</filename>\ example snippet illustrates the syntax and 23.526 +meaning of the notions we just described. 23.527 +</para> 23.528 +<programlisting> 23.529 +<para> [hooks] 23.530 + commit.example = python:mymodule.submodule.myhook 23.531 +</para> 23.532 +</programlisting> 23.533 +<para>When Mercurial runs the <literal>commit.example</literal> hook, it imports 23.534 +<literal>mymodule.submodule</literal>, looks for the callable object named 23.535 +<literal>myhook</literal>, and calls it. 23.536 +</para> 23.537 + 23.538 +</sect2> 23.539 +<sect2> 23.540 +<title>Writing an in-process hook</title> 23.541 + 23.542 +<para>The simplest in-process hook does nothing, but illustrates the basic 23.543 +shape of the hook API: 23.544 +</para> 23.545 +<programlisting> 23.546 +<para> def myhook(ui, repo, **kwargs): 23.547 + pass 23.548 +</para> 23.549 +</programlisting> 23.550 +<para>The first argument to a Python hook is always a 23.551 +<literal role="py-mod-mercurial.ui">ui</literal> object. The second is a repository object; 23.552 +at the moment, it is always an instance of 23.553 +<literal role="py-mod-mercurial.localrepo">localrepository</literal>. Following these two 23.554 +arguments are other keyword arguments. Which ones are passed in 23.555 +depends on the hook being called, but a hook can ignore arguments it 23.556 +doesn't care about by dropping them into a keyword argument dict, as 23.557 +with <literal>**kwargs</literal> above. 23.558 +</para> 23.559 + 23.560 +</sect2> 23.561 +</sect1> 23.562 +<sect1> 23.563 +<title>Some hook examples</title> 23.564 + 23.565 +<sect2> 23.566 +<title>Writing meaningful commit messages</title> 23.567 + 23.568 +<para>It's hard to imagine a useful commit message being very short. The 23.569 +simple <literal role="hook">pretxncommit</literal> hook of figure <xref linkend="ex:hook:msglen.go"/> 23.570 +will prevent you from committing a changeset with a message that is 23.571 +less than ten bytes long. 23.572 +</para> 23.573 + 23.574 +<informalfigure> 23.575 +<para> <!-- &interaction.hook.msglen.go; --> 23.576 + <caption><para>A hook that forbids overly short commit messages</para></caption> 23.577 + \label{ex:hook:msglen.go} 23.578 +</para> 23.579 +</informalfigure> 23.580 + 23.581 +</sect2> 23.582 +<sect2> 23.583 +<title>Checking for trailing whitespace</title> 23.584 + 23.585 +<para>An interesting use of a commit-related hook is to help you to write 23.586 +cleaner code. A simple example of <quote>cleaner code</quote> is the dictum that 23.587 +a change should not add any new lines of text that contain <quote>trailing 23.588 +whitespace</quote>. Trailing whitespace is a series of space and tab 23.589 +characters at the end of a line of text. In most cases, trailing 23.590 +whitespace is unnecessary, invisible noise, but it is occasionally 23.591 +problematic, and people often prefer to get rid of it. 23.592 +</para> 23.593 + 23.594 +<para>You can use either the <literal role="hook">precommit</literal> or <literal role="hook">pretxncommit</literal> hook to 23.595 +tell whether you have a trailing whitespace problem. If you use the 23.596 +<literal role="hook">precommit</literal> hook, the hook will not know which files you are 23.597 +committing, so it will have to check every modified file in the 23.598 +repository for trailing white space. If you want to commit a change 23.599 +to just the file <filename>foo</filename>, but the file <filename>bar</filename> contains 23.600 +trailing whitespace, doing a check in the <literal role="hook">precommit</literal> hook will 23.601 +prevent you from committing <filename>foo</filename> due to the problem with 23.602 +<filename>bar</filename>. This doesn't seem right. 23.603 +</para> 23.604 + 23.605 +<para>Should you choose the <literal role="hook">pretxncommit</literal> hook, the check won't occur 23.606 +until just before the transaction for the commit completes. This will 23.607 +allow you to check for problems only the exact files that are being 23.608 +committed. However, if you entered the commit message interactively 23.609 +and the hook fails, the transaction will roll back; you'll have to 23.610 +re-enter the commit message after you fix the trailing whitespace and 23.611 +run <command role="hg-cmd">hg commit</command> again. 23.612 +</para> 23.613 + 23.614 +<informalfigure> 23.615 +<para> <!-- &interaction.hook.ws.simple; --> 23.616 + <caption><para>A simple hook that checks for trailing whitespace</para></caption> 23.617 + \label{ex:hook:ws.simple} 23.618 +</para> 23.619 +</informalfigure> 23.620 + 23.621 +<para>Figure <xref linkend="ex:hook:ws.simple"/> introduces a simple <literal role="hook">pretxncommit</literal> 23.622 +hook that checks for trailing whitespace. This hook is short, but not 23.623 +very helpful. It exits with an error status if a change adds a line 23.624 +with trailing whitespace to any file, but does not print any 23.625 +information that might help us to identify the offending file or 23.626 +line. It also has the nice property of not paying attention to 23.627 +unmodified lines; only lines that introduce new trailing whitespace 23.628 +cause problems. 23.629 +</para> 23.630 + 23.631 +<informalfigure> 23.632 +<para> <!-- &interaction.hook.ws.better; --> 23.633 + <caption><para>A better trailing whitespace hook</para></caption> 23.634 + \label{ex:hook:ws.better} 23.635 +</para> 23.636 +</informalfigure> 23.637 + 23.638 +<para>The example of figure <xref linkend="ex:hook:ws.better"/> is much more complex, 23.639 +but also more useful. It parses a unified diff to see if any lines 23.640 +add trailing whitespace, and prints the name of the file and the line 23.641 +number of each such occurrence. Even better, if the change adds 23.642 +trailing whitespace, this hook saves the commit comment and prints the 23.643 +name of the save file before exiting and telling Mercurial to roll the 23.644 +transaction back, so you can use 23.645 +<command role="hg-cmd">hg commit <option role="hg-opt-commit">-l</option> <emphasis>filename</emphasis></command> to reuse the 23.646 +saved commit message once you've corrected the problem. 23.647 +</para> 23.648 + 23.649 +<para>As a final aside, note in figure <xref linkend="ex:hook:ws.better"/> the use of 23.650 +<command>perl</command>'s in-place editing feature to get rid of trailing 23.651 +whitespace from a file. This is concise and useful enough that I will 23.652 +reproduce it here. 23.653 +</para> 23.654 +<programlisting> 23.655 +<para> perl -pi -e 's,\textbackslash{}s+$,,' filename 23.656 +</para> 23.657 +</programlisting> 23.658 + 23.659 +</sect2> 23.660 +</sect1> 23.661 +<sect1> 23.662 +<title>Bundled hooks</title> 23.663 + 23.664 +<para>Mercurial ships with several bundled hooks. You can find them in the 23.665 +<filename class="directory">hgext</filename> directory of a Mercurial source tree. If you are 23.666 +using a Mercurial binary package, the hooks will be located in the 23.667 +<filename class="directory">hgext</filename> directory of wherever your package installer put 23.668 +Mercurial. 23.669 +</para> 23.670 + 23.671 +<sect2> 23.672 +<title><literal role="hg-ext">acl</literal>&emdash;access control for parts of a repository</title> 23.673 + 23.674 +<para>The <literal role="hg-ext">acl</literal> extension lets you control which remote users are 23.675 +allowed to push changesets to a networked server. You can protect any 23.676 +portion of a repository (including the entire repo), so that a 23.677 +specific remote user can push changes that do not affect the protected 23.678 +portion. 23.679 +</para> 23.680 + 23.681 +<para>This extension implements access control based on the identity of the 23.682 +user performing a push, <emphasis>not</emphasis> on who committed the changesets 23.683 +they're pushing. It makes sense to use this hook only if you have a 23.684 +locked-down server environment that authenticates remote users, and 23.685 +you want to be sure that only specific users are allowed to push 23.686 +changes to that server. 23.687 +</para> 23.688 + 23.689 +<sect3> 23.690 +<title>Configuring the <literal role="hook">acl</literal> hook</title> 23.691 + 23.692 +<para>In order to manage incoming changesets, the <literal role="hg-ext">acl</literal> hook must be 23.693 +used as a <literal role="hook">pretxnchangegroup</literal> hook. This lets it see which files 23.694 +are modified by each incoming changeset, and roll back a group of 23.695 +changesets if they modify <quote>forbidden</quote> files. Example: 23.696 +</para> 23.697 +<programlisting> 23.698 +<para> [hooks] 23.699 + pretxnchangegroup.acl = python:hgext.acl.hook 23.700 +</para> 23.701 +</programlisting> 23.702 + 23.703 +<para>The <literal role="hg-ext">acl</literal> extension is configured using three sections. 23.704 +</para> 23.705 + 23.706 +<para>The <literal role="rc-acl">acl</literal> section has only one entry, <envar role="rc-item-acl">sources</envar>, 23.707 +which lists the sources of incoming changesets that the hook should 23.708 +pay attention to. You don't normally need to configure this section. 23.709 +</para> 23.710 +<itemizedlist> 23.711 +<listitem><para><envar role="rc-item-acl">serve</envar>: Control incoming changesets that are arriving 23.712 + from a remote repository over http or ssh. This is the default 23.713 + value of <envar role="rc-item-acl">sources</envar>, and usually the only setting you'll 23.714 + need for this configuration item. 23.715 +</para> 23.716 +</listitem> 23.717 +<listitem><para><envar role="rc-item-acl">pull</envar>: Control incoming changesets that are 23.718 + arriving via a pull from a local repository. 23.719 +</para> 23.720 +</listitem> 23.721 +<listitem><para><envar role="rc-item-acl">push</envar>: Control incoming changesets that are 23.722 + arriving via a push from a local repository. 23.723 +</para> 23.724 +</listitem> 23.725 +<listitem><para><envar role="rc-item-acl">bundle</envar>: Control incoming changesets that are 23.726 + arriving from another repository via a bundle. 23.727 +</para> 23.728 +</listitem></itemizedlist> 23.729 + 23.730 +<para>The <literal role="rc-acl.allow">acl.allow</literal> section controls the users that are allowed to 23.731 +add changesets to the repository. If this section is not present, all 23.732 +users that are not explicitly denied are allowed. If this section is 23.733 +present, all users that are not explicitly allowed are denied (so an 23.734 +empty section means that all users are denied). 23.735 +</para> 23.736 + 23.737 +<para>The <literal role="rc-acl.deny">acl.deny</literal> section determines which users are denied 23.738 +from adding changesets to the repository. If this section is not 23.739 +present or is empty, no users are denied. 23.740 +</para> 23.741 + 23.742 +<para>The syntaxes for the <literal role="rc-acl.allow">acl.allow</literal> and <literal role="rc-acl.deny">acl.deny</literal> 23.743 +sections are identical. On the left of each entry is a glob pattern 23.744 +that matches files or directories, relative to the root of the 23.745 +repository; on the right, a user name. 23.746 +</para> 23.747 + 23.748 +<para>In the following example, the user <literal>docwriter</literal> can only push 23.749 +changes to the <filename class="directory">docs</filename> subtree of the repository, while 23.750 +<literal>intern</literal> can push changes to any file or directory except 23.751 +<filename class="directory">source/sensitive</filename>. 23.752 +</para> 23.753 +<programlisting> 23.754 +<para> [acl.allow] 23.755 + docs/** = docwriter 23.756 +</para> 23.757 + 23.758 +<para> [acl.deny] 23.759 + source/sensitive/** = intern 23.760 +</para> 23.761 +</programlisting> 23.762 + 23.763 +</sect3> 23.764 +<sect3> 23.765 +<title>Testing and troubleshooting</title> 23.766 + 23.767 +<para>If you want to test the <literal role="hg-ext">acl</literal> hook, run it with Mercurial's 23.768 +debugging output enabled. Since you'll probably be running it on a 23.769 +server where it's not convenient (or sometimes possible) to pass in 23.770 +the <option role="hg-opt-global">--debug</option> option, don't forget that you can enable 23.771 +debugging output in your <filename role="special"> /.hgrc</filename>: 23.772 +</para> 23.773 +<programlisting> 23.774 +<para> [ui] 23.775 + debug = true 23.776 +</para> 23.777 +</programlisting> 23.778 +<para>With this enabled, the <literal role="hg-ext">acl</literal> hook will print enough information 23.779 +to let you figure out why it is allowing or forbidding pushes from 23.780 +specific users. 23.781 +</para> 23.782 + 23.783 +</sect3> 23.784 +</sect2> 23.785 +<sect2> 23.786 +<title><literal role="hg-ext">bugzilla</literal>&emdash;integration with Bugzilla</title> 23.787 + 23.788 +<para>The <literal role="hg-ext">bugzilla</literal> extension adds a comment to a Bugzilla bug 23.789 +whenever it finds a reference to that bug ID in a commit comment. You 23.790 +can install this hook on a shared server, so that any time a remote 23.791 +user pushes changes to this server, the hook gets run. 23.792 +</para> 23.793 + 23.794 +<para>It adds a comment to the bug that looks like this (you can configure 23.795 +the contents of the comment&emdash;see below): 23.796 +</para> 23.797 +<programlisting> 23.798 +<para> Changeset aad8b264143a, made by Joe User <joe.user@domain.com> in 23.799 + the frobnitz repository, refers to this bug. 23.800 +</para> 23.801 + 23.802 +<para> For complete details, see 23.803 + http://hg.domain.com/frobnitz?cmd=changeset;node=aad8b264143a 23.804 +</para> 23.805 + 23.806 +<para> Changeset description: 23.807 + Fix bug 10483 by guarding against some NULL pointers 23.808 +</para> 23.809 +</programlisting> 23.810 +<para>The value of this hook is that it automates the process of updating a 23.811 +bug any time a changeset refers to it. If you configure the hook 23.812 +properly, it makes it easy for people to browse straight from a 23.813 +Bugzilla bug to a changeset that refers to that bug. 23.814 +</para> 23.815 + 23.816 +<para>You can use the code in this hook as a starting point for some more 23.817 +exotic Bugzilla integration recipes. Here are a few possibilities: 23.818 +</para> 23.819 +<itemizedlist> 23.820 +<listitem><para>Require that every changeset pushed to the server have a valid 23.821 + bug ID in its commit comment. In this case, you'd want to configure 23.822 + the hook as a <literal role="hook">pretxncommit</literal> hook. This would allow the hook 23.823 + to reject changes that didn't contain bug IDs. 23.824 +</para> 23.825 +</listitem> 23.826 +<listitem><para>Allow incoming changesets to automatically modify the 23.827 + <emphasis>state</emphasis> of a bug, as well as simply adding a comment. For 23.828 + example, the hook could recognise the string <quote>fixed bug 31337</quote> as 23.829 + indicating that it should update the state of bug 31337 to 23.830 + <quote>requires testing</quote>. 23.831 +</para> 23.832 +</listitem></itemizedlist> 23.833 + 23.834 +<sect3> 23.835 +<title>Configuring the <literal role="hook">bugzilla</literal> hook</title> 23.836 +<para>\label{sec:hook:bugzilla:config} 23.837 +</para> 23.838 + 23.839 +<para>You should configure this hook in your server's <filename role="special"> /.hgrc</filename>\ as an 23.840 +<literal role="hook">incoming</literal> hook, for example as follows: 23.841 +</para> 23.842 +<programlisting> 23.843 +<para> [hooks] 23.844 + incoming.bugzilla = python:hgext.bugzilla.hook 23.845 +</para> 23.846 +</programlisting> 23.847 + 23.848 +<para>Because of the specialised nature of this hook, and because Bugzilla 23.849 +was not written with this kind of integration in mind, configuring 23.850 +this hook is a somewhat involved process. 23.851 +</para> 23.852 + 23.853 +<para>Before you begin, you must install the MySQL bindings for Python on 23.854 +the host(s) where you'll be running the hook. If this is not 23.855 +available as a binary package for your system, you can download it 23.856 +from <citation>web:mysql-python</citation>. 23.857 +</para> 23.858 + 23.859 +<para>Configuration information for this hook lives in the 23.860 +<literal role="rc-bugzilla">bugzilla</literal> section of your <filename role="special"> /.hgrc</filename>. 23.861 +</para> 23.862 +<itemizedlist> 23.863 +<listitem><para><envar role="rc-item-bugzilla">version</envar>: The version of Bugzilla installed on 23.864 + the server. The database schema that Bugzilla uses changes 23.865 + occasionally, so this hook has to know exactly which schema to use. 23.866 + At the moment, the only version supported is <literal>2.16</literal>. 23.867 +</para> 23.868 +</listitem> 23.869 +<listitem><para><envar role="rc-item-bugzilla">host</envar>: The hostname of the MySQL server that 23.870 + stores your Bugzilla data. The database must be configured to allow 23.871 + connections from whatever host you are running the <literal role="hook">bugzilla</literal> 23.872 + hook on. 23.873 +</para> 23.874 +</listitem> 23.875 +<listitem><para><envar role="rc-item-bugzilla">user</envar>: The username with which to connect to 23.876 + the MySQL server. The database must be configured to allow this 23.877 + user to connect from whatever host you are running the 23.878 + <literal role="hook">bugzilla</literal> hook on. This user must be able to access and 23.879 + modify Bugzilla tables. The default value of this item is 23.880 + <literal>bugs</literal>, which is the standard name of the Bugzilla user in a 23.881 + MySQL database. 23.882 +</para> 23.883 +</listitem> 23.884 +<listitem><para><envar role="rc-item-bugzilla">password</envar>: The MySQL password for the user you 23.885 + configured above. This is stored as plain text, so you should make 23.886 + sure that unauthorised users cannot read the <filename role="special"> /.hgrc</filename>\ file where you 23.887 + store this information. 23.888 +</para> 23.889 +</listitem> 23.890 +<listitem><para><envar role="rc-item-bugzilla">db</envar>: The name of the Bugzilla database on the 23.891 + MySQL server. The default value of this item is <literal>bugs</literal>, 23.892 + which is the standard name of the MySQL database where Bugzilla 23.893 + stores its data. 23.894 +</para> 23.895 +</listitem> 23.896 +<listitem><para><envar role="rc-item-bugzilla">notify</envar>: If you want Bugzilla to send out a 23.897 + notification email to subscribers after this hook has added a 23.898 + comment to a bug, you will need this hook to run a command whenever 23.899 + it updates the database. The command to run depends on where you 23.900 + have installed Bugzilla, but it will typically look something like 23.901 + this, if you have Bugzilla installed in 23.902 + <filename class="directory">/var/www/html/bugzilla</filename>: 23.903 +</para> 23.904 +</listitem><programlisting> 23.905 +<listitem><para> cd /var/www/html/bugzilla && ./processmail %s nobody@nowhere.com 23.906 +</para> 23.907 +</listitem></programlisting> 23.908 +<listitem><para> The Bugzilla <literal>processmail</literal> program expects to be given a 23.909 + bug ID (the hook replaces <quote><literal>%s</literal></quote> with the bug ID) and an 23.910 + email address. It also expects to be able to write to some files in 23.911 + the directory that it runs in. If Bugzilla and this hook are not 23.912 + installed on the same machine, you will need to find a way to run 23.913 + <literal>processmail</literal> on the server where Bugzilla is installed. 23.914 +</para> 23.915 +</listitem></itemizedlist> 23.916 + 23.917 +</sect3> 23.918 +<sect3> 23.919 +<title>Mapping committer names to Bugzilla user names</title> 23.920 + 23.921 +<para>By default, the <literal role="hg-ext">bugzilla</literal> hook tries to use the email address 23.922 +of a changeset's committer as the Bugzilla user name with which to 23.923 +update a bug. If this does not suit your needs, you can map committer 23.924 +email addresses to Bugzilla user names using a <literal role="rc-usermap">usermap</literal> 23.925 +section. 23.926 +</para> 23.927 + 23.928 +<para>Each item in the <literal role="rc-usermap">usermap</literal> section contains an email address 23.929 +on the left, and a Bugzilla user name on the right. 23.930 +</para> 23.931 +<programlisting> 23.932 +<para> [usermap] 23.933 + jane.user@example.com = jane 23.934 +</para> 23.935 +</programlisting> 23.936 +<para>You can either keep the <literal role="rc-usermap">usermap</literal> data in a normal <filename role="special"> /.hgrc</filename>, or 23.937 +tell the <literal role="hg-ext">bugzilla</literal> hook to read the information from an 23.938 +external <filename>usermap</filename> file. In the latter case, you can store 23.939 +<filename>usermap</filename> data by itself in (for example) a user-modifiable 23.940 +repository. This makes it possible to let your users maintain their 23.941 +own <envar role="rc-item-bugzilla">usermap</envar> entries. The main <filename role="special"> /.hgrc</filename>\ file might 23.942 +look like this: 23.943 +</para> 23.944 +<programlisting> 23.945 +<para> # regular hgrc file refers to external usermap file 23.946 + [bugzilla] 23.947 + usermap = /home/hg/repos/userdata/bugzilla-usermap.conf 23.948 +</para> 23.949 +</programlisting> 23.950 +<para>While the <filename>usermap</filename> file that it refers to might look like 23.951 +this: 23.952 +</para> 23.953 +<programlisting> 23.954 +<para> # bugzilla-usermap.conf - inside a hg repository 23.955 + [usermap] 23.956 + stephanie@example.com = steph 23.957 +</para> 23.958 +</programlisting> 23.959 + 23.960 +</sect3> 23.961 +<sect3> 23.962 +<title>Configuring the text that gets added to a bug</title> 23.963 + 23.964 +<para>You can configure the text that this hook adds as a comment; you 23.965 +specify it in the form of a Mercurial template. Several <filename role="special"> /.hgrc</filename>\ 23.966 +entries (still in the <literal role="rc-bugzilla">bugzilla</literal> section) control this 23.967 +behaviour. 23.968 +</para> 23.969 +<itemizedlist> 23.970 +<listitem><para><literal>strip</literal>: The number of leading path elements to strip 23.971 + from a repository's path name to construct a partial path for a URL. 23.972 + For example, if the repositories on your server live under 23.973 + <filename class="directory">/home/hg/repos</filename>, and you have a repository whose path is 23.974 + <filename class="directory">/home/hg/repos/app/tests</filename>, then setting <literal>strip</literal> to 23.975 + <literal>4</literal> will give a partial path of <filename class="directory">app/tests</filename>. The 23.976 + hook will make this partial path available when expanding a 23.977 + template, as <literal>webroot</literal>. 23.978 +</para> 23.979 +</listitem> 23.980 +<listitem><para><literal>template</literal>: The text of the template to use. In addition 23.981 + to the usual changeset-related variables, this template can use 23.982 + <literal>hgweb</literal> (the value of the <literal>hgweb</literal> configuration item 23.983 + above) and <literal>webroot</literal> (the path constructed using 23.984 + <literal>strip</literal> above). 23.985 +</para> 23.986 +</listitem></itemizedlist> 23.987 + 23.988 +<para>In addition, you can add a <envar role="rc-item-web">baseurl</envar> item to the 23.989 +<literal role="rc-web">web</literal> section of your <filename role="special"> /.hgrc</filename>. The <literal role="hg-ext">bugzilla</literal> hook will 23.990 +make this available when expanding a template, as the base string to 23.991 +use when constructing a URL that will let users browse from a Bugzilla 23.992 +comment to view a changeset. Example: 23.993 +</para> 23.994 +<programlisting> 23.995 +<para> [web] 23.996 + baseurl = http://hg.domain.com/ 23.997 +</para> 23.998 +</programlisting> 23.999 + 23.1000 +<para>Here is an example set of <literal role="hg-ext">bugzilla</literal> hook config information. 23.1001 +</para> 23.1002 +<programlisting> 23.1003 +<para> [bugzilla] 23.1004 + host = bugzilla.example.com 23.1005 + password = mypassword 23.1006 + version = 2.16 23.1007 + # server-side repos live in /home/hg/repos, so strip 4 leading 23.1008 + # separators 23.1009 + strip = 4 23.1010 + hgweb = http://hg.example.com/ 23.1011 + usermap = /home/hg/repos/notify/bugzilla.conf 23.1012 + template = Changeset {node|short}, made by {author} in the {webroot} 23.1013 + repo, refers to this bug.\\nFor complete details, see 23.1014 + {hgweb}{webroot}?cmd=changeset;node={node|short}\\nChangeset 23.1015 + description:\\n\\t{desc|tabindent} 23.1016 +</para> 23.1017 +</programlisting> 23.1018 + 23.1019 +</sect3> 23.1020 +<sect3> 23.1021 +<title>Testing and troubleshooting</title> 23.1022 + 23.1023 +<para>The most common problems with configuring the <literal role="hg-ext">bugzilla</literal> hook 23.1024 +relate to running Bugzilla's <filename>processmail</filename> script and mapping 23.1025 +committer names to user names. 23.1026 +</para> 23.1027 + 23.1028 +<para>Recall from section <xref linkend="sec:hook:bugzilla:config"/> above that the user 23.1029 +that runs the Mercurial process on the server is also the one that 23.1030 +will run the <filename>processmail</filename> script. The 23.1031 +<filename>processmail</filename> script sometimes causes Bugzilla to write to 23.1032 +files in its configuration directory, and Bugzilla's configuration 23.1033 +files are usually owned by the user that your web server runs under. 23.1034 +</para> 23.1035 + 23.1036 +<para>You can cause <filename>processmail</filename> to be run with the suitable 23.1037 +user's identity using the <command>sudo</command> command. Here is an example 23.1038 +entry for a <filename>sudoers</filename> file. 23.1039 +</para> 23.1040 +<programlisting> 23.1041 +<para> hg_user = (httpd_user) NOPASSWD: /var/www/html/bugzilla/processmail-wrapper %s 23.1042 +</para> 23.1043 +</programlisting> 23.1044 +<para>This allows the <literal>hg_user</literal> user to run a 23.1045 +<filename>processmail-wrapper</filename> program under the identity of 23.1046 +<literal>httpd_user</literal>. 23.1047 +</para> 23.1048 + 23.1049 +<para>This indirection through a wrapper script is necessary, because 23.1050 +<filename>processmail</filename> expects to be run with its current directory 23.1051 +set to wherever you installed Bugzilla; you can't specify that kind of 23.1052 +constraint in a <filename>sudoers</filename> file. The contents of the wrapper 23.1053 +script are simple: 23.1054 +</para> 23.1055 +<programlisting> 23.1056 +<para> #!/bin/sh 23.1057 + cd `dirname $0` && ./processmail "$1" nobody@example.com 23.1058 +</para> 23.1059 +</programlisting> 23.1060 +<para>It doesn't seem to matter what email address you pass to 23.1061 +<filename>processmail</filename>. 23.1062 +</para> 23.1063 + 23.1064 +<para>If your <literal role="rc-usermap">usermap</literal> is not set up correctly, users will see an 23.1065 +error message from the <literal role="hg-ext">bugzilla</literal> hook when they push changes 23.1066 +to the server. The error message will look like this: 23.1067 +</para> 23.1068 +<programlisting> 23.1069 +<para> cannot find bugzilla user id for john.q.public@example.com 23.1070 +</para> 23.1071 +</programlisting> 23.1072 +<para>What this means is that the committer's address, 23.1073 +<literal>john.q.public@example.com</literal>, is not a valid Bugzilla user name, 23.1074 +nor does it have an entry in your <literal role="rc-usermap">usermap</literal> that maps it to 23.1075 +a valid Bugzilla user name. 23.1076 +</para> 23.1077 + 23.1078 +</sect3> 23.1079 +</sect2> 23.1080 +<sect2> 23.1081 +<title><literal role="hg-ext">notify</literal>&emdash;send email notifications</title> 23.1082 + 23.1083 +<para>Although Mercurial's built-in web server provides RSS feeds of changes 23.1084 +in every repository, many people prefer to receive change 23.1085 +notifications via email. The <literal role="hg-ext">notify</literal> hook lets you send out 23.1086 +notifications to a set of email addresses whenever changesets arrive 23.1087 +that those subscribers are interested in. 23.1088 +</para> 23.1089 + 23.1090 +<para>As with the <literal role="hg-ext">bugzilla</literal> hook, the <literal role="hg-ext">notify</literal> hook is 23.1091 +template-driven, so you can customise the contents of the notification 23.1092 +messages that it sends. 23.1093 +</para> 23.1094 + 23.1095 +<para>By default, the <literal role="hg-ext">notify</literal> hook includes a diff of every changeset 23.1096 +that it sends out; you can limit the size of the diff, or turn this 23.1097 +feature off entirely. It is useful for letting subscribers review 23.1098 +changes immediately, rather than clicking to follow a URL. 23.1099 +</para> 23.1100 + 23.1101 +<sect3> 23.1102 +<title>Configuring the <literal role="hg-ext">notify</literal> hook</title> 23.1103 + 23.1104 +<para>You can set up the <literal role="hg-ext">notify</literal> hook to send one email message per 23.1105 +incoming changeset, or one per incoming group of changesets (all those 23.1106 +that arrived in a single pull or push). 23.1107 +</para> 23.1108 +<programlisting> 23.1109 +<para> [hooks] 23.1110 + # send one email per group of changes 23.1111 + changegroup.notify = python:hgext.notify.hook 23.1112 + # send one email per change 23.1113 + incoming.notify = python:hgext.notify.hook 23.1114 +</para> 23.1115 +</programlisting> 23.1116 + 23.1117 +<para>Configuration information for this hook lives in the 23.1118 +<literal role="rc-notify">notify</literal> section of a <filename role="special"> /.hgrc</filename>\ file. 23.1119 +</para> 23.1120 +<itemizedlist> 23.1121 +<listitem><para><envar role="rc-item-notify">test</envar>: By default, this hook does not send out 23.1122 + email at all; instead, it prints the message that it <emphasis>would</emphasis> 23.1123 + send. Set this item to <literal>false</literal> to allow email to be sent. 23.1124 + The reason that sending of email is turned off by default is that it 23.1125 + takes several tries to configure this extension exactly as you would 23.1126 + like, and it would be bad form to spam subscribers with a number of 23.1127 + <quote>broken</quote> notifications while you debug your configuration. 23.1128 +</para> 23.1129 +</listitem> 23.1130 +<listitem><para><envar role="rc-item-notify">config</envar>: The path to a configuration file that 23.1131 + contains subscription information. This is kept separate from the 23.1132 + main <filename role="special"> /.hgrc</filename>\ so that you can maintain it in a repository of its own. 23.1133 + People can then clone that repository, update their subscriptions, 23.1134 + and push the changes back to your server. 23.1135 +</para> 23.1136 +</listitem> 23.1137 +<listitem><para><envar role="rc-item-notify">strip</envar>: The number of leading path separator 23.1138 + characters to strip from a repository's path, when deciding whether 23.1139 + a repository has subscribers. For example, if the repositories on 23.1140 + your server live in <filename class="directory">/home/hg/repos</filename>, and <literal role="hg-ext">notify</literal> is 23.1141 + considering a repository named <filename class="directory">/home/hg/repos/shared/test</filename>, 23.1142 + setting <envar role="rc-item-notify">strip</envar> to <literal>4</literal> will cause 23.1143 + <literal role="hg-ext">notify</literal> to trim the path it considers down to 23.1144 + <filename class="directory">shared/test</filename>, and it will match subscribers against that. 23.1145 +</para> 23.1146 +</listitem> 23.1147 +<listitem><para><envar role="rc-item-notify">template</envar>: The template text to use when sending 23.1148 + messages. This specifies both the contents of the message header 23.1149 + and its body. 23.1150 +</para> 23.1151 +</listitem> 23.1152 +<listitem><para><envar role="rc-item-notify">maxdiff</envar>: The maximum number of lines of diff 23.1153 + data to append to the end of a message. If a diff is longer than 23.1154 + this, it is truncated. By default, this is set to 300. Set this to 23.1155 + <literal>0</literal> to omit diffs from notification emails. 23.1156 +</para> 23.1157 +</listitem> 23.1158 +<listitem><para><envar role="rc-item-notify">sources</envar>: A list of sources of changesets to 23.1159 + consider. This lets you limit <literal role="hg-ext">notify</literal> to only sending out 23.1160 + email about changes that remote users pushed into this repository 23.1161 + via a server, for example. See section <xref linkend="sec:hook:sources"/> for 23.1162 + the sources you can specify here. 23.1163 +</para> 23.1164 +</listitem></itemizedlist> 23.1165 + 23.1166 +<para>If you set the <envar role="rc-item-web">baseurl</envar> item in the <literal role="rc-web">web</literal> 23.1167 +section, you can use it in a template; it will be available as 23.1168 +<literal>webroot</literal>. 23.1169 +</para> 23.1170 + 23.1171 +<para>Here is an example set of <literal role="hg-ext">notify</literal> configuration information. 23.1172 +</para> 23.1173 +<programlisting> 23.1174 +<para> [notify] 23.1175 + # really send email 23.1176 + test = false 23.1177 + # subscriber data lives in the notify repo 23.1178 + config = /home/hg/repos/notify/notify.conf 23.1179 + # repos live in /home/hg/repos on server, so strip 4 "/" chars 23.1180 + strip = 4 23.1181 + template = X-Hg-Repo: {webroot} 23.1182 + Subject: {webroot}: {desc|firstline|strip} 23.1183 + From: {author} 23.1184 +</para> 23.1185 + 23.1186 +<para> changeset {node|short} in {root} 23.1187 + details: {baseurl}{webroot}?cmd=changeset;node={node|short} 23.1188 + description: 23.1189 + {desc|tabindent|strip} 23.1190 +</para> 23.1191 + 23.1192 +<para> [web] 23.1193 + baseurl = http://hg.example.com/ 23.1194 +</para> 23.1195 +</programlisting> 23.1196 + 23.1197 +<para>This will produce a message that looks like the following: 23.1198 +</para> 23.1199 +<programlisting> 23.1200 +<para> X-Hg-Repo: tests/slave 23.1201 + Subject: tests/slave: Handle error case when slave has no buffers 23.1202 + Date: Wed, 2 Aug 2006 15:25:46 -0700 (PDT) 23.1203 +</para> 23.1204 + 23.1205 +<para> changeset 3cba9bfe74b5 in /home/hg/repos/tests/slave 23.1206 + details: http://hg.example.com/tests/slave?cmd=changeset;node=3cba9bfe74b5 23.1207 + description: 23.1208 + Handle error case when slave has no buffers 23.1209 + diffs (54 lines): 23.1210 +</para> 23.1211 + 23.1212 +<para> diff -r 9d95df7cf2ad -r 3cba9bfe74b5 include/tests.h 23.1213 + &emdash; a/include/tests.h Wed Aug 02 15:19:52 2006 -0700 23.1214 + +++ b/include/tests.h Wed Aug 02 15:25:26 2006 -0700 23.1215 + @@ -212,6 +212,15 @@ static __inline__ void test_headers(void *h) 23.1216 + [...snip...] 23.1217 +</para> 23.1218 +</programlisting> 23.1219 + 23.1220 +</sect3> 23.1221 +<sect3> 23.1222 +<title>Testing and troubleshooting</title> 23.1223 + 23.1224 +<para>Do not forget that by default, the <literal role="hg-ext">notify</literal> extension \emph{will 23.1225 + not send any mail} until you explicitly configure it to do so, by 23.1226 +setting <envar role="rc-item-notify">test</envar> to <literal>false</literal>. Until you do that, 23.1227 +it simply prints the message it <emphasis>would</emphasis> send. 23.1228 +</para> 23.1229 + 23.1230 +</sect3> 23.1231 +</sect2> 23.1232 +</sect1> 23.1233 +<sect1> 23.1234 +<title>Information for writers of hooks</title> 23.1235 +<para>\label{sec:hook:ref} 23.1236 +</para> 23.1237 + 23.1238 +<sect2> 23.1239 +<title>In-process hook execution</title> 23.1240 + 23.1241 +<para>An in-process hook is called with arguments of the following form: 23.1242 +</para> 23.1243 +<programlisting> 23.1244 +<para> def myhook(ui, repo, **kwargs): 23.1245 + pass 23.1246 +</para> 23.1247 +</programlisting> 23.1248 +<para>The <literal>ui</literal> parameter is a <literal role="py-mod-mercurial.ui">ui</literal> object. 23.1249 +The <literal>repo</literal> parameter is a 23.1250 +<literal role="py-mod-mercurial.localrepo">localrepository</literal> object. The 23.1251 +names and values of the <literal>**kwargs</literal> parameters depend on the 23.1252 +hook being invoked, with the following common features: 23.1253 +</para> 23.1254 +<itemizedlist> 23.1255 +<listitem><para>If a parameter is named <literal>node</literal> or 23.1256 + <literal>parent<emphasis>N</emphasis></literal>, it will contain a hexadecimal changeset ID. 23.1257 + The empty string is used to represent <quote>null changeset ID</quote> instead 23.1258 + of a string of zeroes. 23.1259 +</para> 23.1260 +</listitem> 23.1261 +<listitem><para>If a parameter is named <literal>url</literal>, it will contain the URL of 23.1262 + a remote repository, if that can be determined. 23.1263 +</para> 23.1264 +</listitem> 23.1265 +<listitem><para>Boolean-valued parameters are represented as Python 23.1266 + <literal>bool</literal> objects. 23.1267 +</para> 23.1268 +</listitem></itemizedlist> 23.1269 + 23.1270 +<para>An in-process hook is called without a change to the process's working 23.1271 +directory (unlike external hooks, which are run in the root of the 23.1272 +repository). It must not change the process's working directory, or 23.1273 +it will cause any calls it makes into the Mercurial API to fail. 23.1274 +</para> 23.1275 + 23.1276 +<para>If a hook returns a boolean <quote>false</quote> value, it is considered to have 23.1277 +succeeded. If it returns a boolean <quote>true</quote> value or raises an 23.1278 +exception, it is considered to have failed. A useful way to think of 23.1279 +the calling convention is <quote>tell me if you fail</quote>. 23.1280 +</para> 23.1281 + 23.1282 +<para>Note that changeset IDs are passed into Python hooks as hexadecimal 23.1283 +strings, not the binary hashes that Mercurial's APIs normally use. To 23.1284 +convert a hash from hex to binary, use the 23.1285 +\pymodfunc{mercurial.node}{bin} function. 23.1286 +</para> 23.1287 + 23.1288 +</sect2> 23.1289 +<sect2> 23.1290 +<title>External hook execution</title> 23.1291 + 23.1292 +<para>An external hook is passed to the shell of the user running Mercurial. 23.1293 +Features of that shell, such as variable substitution and command 23.1294 +redirection, are available. The hook is run in the root directory of 23.1295 +the repository (unlike in-process hooks, which are run in the same 23.1296 +directory that Mercurial was run in). 23.1297 +</para> 23.1298 + 23.1299 +<para>Hook parameters are passed to the hook as environment variables. Each 23.1300 +environment variable's name is converted in upper case and prefixed 23.1301 +with the string <quote><literal>HG_</literal></quote>. For example, if the name of a 23.1302 +parameter is <quote><literal>node</literal></quote>, the name of the environment variable 23.1303 +representing that parameter will be <quote><literal>HG_NODE</literal></quote>. 23.1304 +</para> 23.1305 + 23.1306 +<para>A boolean parameter is represented as the string <quote><literal>1</literal></quote> for 23.1307 +<quote>true</quote>, <quote><literal>0</literal></quote> for <quote>false</quote>. If an environment variable is 23.1308 +named <envar>HG_NODE</envar>, <envar>HG_PARENT1</envar> or <envar>HG_PARENT2</envar>, it 23.1309 +contains a changeset ID represented as a hexadecimal string. The 23.1310 +empty string is used to represent <quote>null changeset ID</quote> instead of a 23.1311 +string of zeroes. If an environment variable is named 23.1312 +<envar>HG_URL</envar>, it will contain the URL of a remote repository, if 23.1313 +that can be determined. 23.1314 +</para> 23.1315 + 23.1316 +<para>If a hook exits with a status of zero, it is considered to have 23.1317 +succeeded. If it exits with a non-zero status, it is considered to 23.1318 +have failed. 23.1319 +</para> 23.1320 + 23.1321 +</sect2> 23.1322 +<sect2> 23.1323 +<title>Finding out where changesets come from</title> 23.1324 + 23.1325 +<para>A hook that involves the transfer of changesets between a local 23.1326 +repository and another may be able to find out information about the 23.1327 +<quote>far side</quote>. Mercurial knows <emphasis>how</emphasis> changes are being 23.1328 +transferred, and in many cases <emphasis>where</emphasis> they are being transferred 23.1329 +to or from. 23.1330 +</para> 23.1331 + 23.1332 +<sect3> 23.1333 +<title>Sources of changesets</title> 23.1334 +<para>\label{sec:hook:sources} 23.1335 +</para> 23.1336 + 23.1337 +<para>Mercurial will tell a hook what means are, or were, used to transfer 23.1338 +changesets between repositories. This is provided by Mercurial in a 23.1339 +Python parameter named <literal>source</literal>, or an environment variable named 23.1340 +<envar>HG_SOURCE</envar>. 23.1341 +</para> 23.1342 + 23.1343 +<itemizedlist> 23.1344 +<listitem><para><literal>serve</literal>: Changesets are transferred to or from a remote 23.1345 + repository over http or ssh. 23.1346 +</para> 23.1347 +</listitem> 23.1348 +<listitem><para><literal>pull</literal>: Changesets are being transferred via a pull from 23.1349 + one repository into another. 23.1350 +</para> 23.1351 +</listitem> 23.1352 +<listitem><para><literal>push</literal>: Changesets are being transferred via a push from 23.1353 + one repository into another. 23.1354 +</para> 23.1355 +</listitem> 23.1356 +<listitem><para><literal>bundle</literal>: Changesets are being transferred to or from a 23.1357 + bundle. 23.1358 +</para> 23.1359 +</listitem></itemizedlist> 23.1360 + 23.1361 +</sect3> 23.1362 +<sect3> 23.1363 +<title>Where changes are going&emdash;remote repository URLs</title> 23.1364 +<para>\label{sec:hook:url} 23.1365 +</para> 23.1366 + 23.1367 +<para>When possible, Mercurial will tell a hook the location of the <quote>far 23.1368 +side</quote> of an activity that transfers changeset data between 23.1369 +repositories. This is provided by Mercurial in a Python parameter 23.1370 +named <literal>url</literal>, or an environment variable named <envar>HG_URL</envar>. 23.1371 +</para> 23.1372 + 23.1373 +<para>This information is not always known. If a hook is invoked in a 23.1374 +repository that is being served via http or ssh, Mercurial cannot tell 23.1375 +where the remote repository is, but it may know where the client is 23.1376 +connecting from. In such cases, the URL will take one of the 23.1377 +following forms: 23.1378 +</para> 23.1379 +<itemizedlist> 23.1380 +<listitem><para><literal>remote:ssh:<emphasis>ip-address</emphasis></literal>&emdash;remote ssh client, at 23.1381 + the given IP address. 23.1382 +</para> 23.1383 +</listitem> 23.1384 +<listitem><para><literal>remote:http:<emphasis>ip-address</emphasis></literal>&emdash;remote http client, at 23.1385 + the given IP address. If the client is using SSL, this will be of 23.1386 + the form <literal>remote:https:<emphasis>ip-address</emphasis></literal>. 23.1387 +</para> 23.1388 +</listitem> 23.1389 +<listitem><para>Empty&emdash;no information could be discovered about the remote 23.1390 + client. 23.1391 +</para> 23.1392 +</listitem></itemizedlist> 23.1393 + 23.1394 +</sect3> 23.1395 +</sect2> 23.1396 +</sect1> 23.1397 +<sect1> 23.1398 +<title>Hook reference</title> 23.1399 + 23.1400 +<sect2> 23.1401 +<title><literal role="hook">changegroup</literal>&emdash;after remote changesets added</title> 23.1402 +<para>\label{sec:hook:changegroup} 23.1403 +</para> 23.1404 + 23.1405 +<para>This hook is run after a group of pre-existing changesets has been 23.1406 +added to the repository, for example via a <command role="hg-cmd">hg pull</command> or 23.1407 +<command role="hg-cmd">hg unbundle</command>. This hook is run once per operation that added one 23.1408 +or more changesets. This is in contrast to the <literal role="hook">incoming</literal> hook, 23.1409 +which is run once per changeset, regardless of whether the changesets 23.1410 +arrive in a group. 23.1411 +</para> 23.1412 + 23.1413 +<para>Some possible uses for this hook include kicking off an automated 23.1414 +build or test of the added changesets, updating a bug database, or 23.1415 +notifying subscribers that a repository contains new changes. 23.1416 +</para> 23.1417 + 23.1418 +<para>Parameters to this hook: 23.1419 +</para> 23.1420 +<itemizedlist> 23.1421 +<listitem><para><literal>node</literal>: A changeset ID. The changeset ID of the first 23.1422 + changeset in the group that was added. All changesets between this 23.1423 + and \index{tags!<literal>tip</literal>}<literal>tip</literal>, inclusive, were added by 23.1424 + a single <command role="hg-cmd">hg pull</command>, <command role="hg-cmd">hg push</command> or <command role="hg-cmd">hg unbundle</command>. 23.1425 +</para> 23.1426 +</listitem> 23.1427 +<listitem><para><literal>source</literal>: A string. The source of these changes. See 23.1428 + section <xref linkend="sec:hook:sources"/> for details. 23.1429 +</para> 23.1430 +</listitem> 23.1431 +<listitem><para><literal>url</literal>: A URL. The location of the remote repository, if 23.1432 + known. See section <xref linkend="sec:hook:url"/> for more information. 23.1433 +</para> 23.1434 +</listitem></itemizedlist> 23.1435 + 23.1436 +<para>See also: <literal role="hook">incoming</literal> (section <xref linkend="sec:hook:incoming"/>), 23.1437 +<literal role="hook">prechangegroup</literal> (section <xref linkend="sec:hook:prechangegroup"/>), 23.1438 +<literal role="hook">pretxnchangegroup</literal> (section <xref linkend="sec:hook:pretxnchangegroup"/>) 23.1439 +</para> 23.1440 + 23.1441 +</sect2> 23.1442 +<sect2> 23.1443 +<title><literal role="hook">commit</literal>&emdash;after a new changeset is created</title> 23.1444 +<para>\label{sec:hook:commit} 23.1445 +</para> 23.1446 + 23.1447 +<para>This hook is run after a new changeset has been created. 23.1448 +</para> 23.1449 + 23.1450 +<para>Parameters to this hook: 23.1451 +</para> 23.1452 +<itemizedlist> 23.1453 +<listitem><para><literal>node</literal>: A changeset ID. The changeset ID of the newly 23.1454 + committed changeset. 23.1455 +</para> 23.1456 +</listitem> 23.1457 +<listitem><para><literal>parent1</literal>: A changeset ID. The changeset ID of the first 23.1458 + parent of the newly committed changeset. 23.1459 +</para> 23.1460 +</listitem> 23.1461 +<listitem><para><literal>parent2</literal>: A changeset ID. The changeset ID of the second 23.1462 + parent of the newly committed changeset. 23.1463 +</para> 23.1464 +</listitem></itemizedlist> 23.1465 + 23.1466 +<para>See also: <literal role="hook">precommit</literal> (section <xref linkend="sec:hook:precommit"/>), 23.1467 +<literal role="hook">pretxncommit</literal> (section <xref linkend="sec:hook:pretxncommit"/>) 23.1468 +</para> 23.1469 + 23.1470 +</sect2> 23.1471 +<sect2> 23.1472 +<title><literal role="hook">incoming</literal>&emdash;after one remote changeset is added</title> 23.1473 +<para>\label{sec:hook:incoming} 23.1474 +</para> 23.1475 + 23.1476 +<para>This hook is run after a pre-existing changeset has been added to the 23.1477 +repository, for example via a <command role="hg-cmd">hg push</command>. If a group of changesets 23.1478 +was added in a single operation, this hook is called once for each 23.1479 +added changeset. 23.1480 +</para> 23.1481 + 23.1482 +<para>You can use this hook for the same purposes as the <literal role="hook">changegroup</literal> 23.1483 +hook (section <xref linkend="sec:hook:changegroup"/>); it's simply more convenient 23.1484 +sometimes to run a hook once per group of changesets, while other 23.1485 +times it's handier once per changeset. 23.1486 +</para> 23.1487 + 23.1488 +<para>Parameters to this hook: 23.1489 +</para> 23.1490 +<itemizedlist> 23.1491 +<listitem><para><literal>node</literal>: A changeset ID. The ID of the newly added 23.1492 + changeset. 23.1493 +</para> 23.1494 +</listitem> 23.1495 +<listitem><para><literal>source</literal>: A string. The source of these changes. See 23.1496 + section <xref linkend="sec:hook:sources"/> for details. 23.1497 +</para> 23.1498 +</listitem> 23.1499 +<listitem><para><literal>url</literal>: A URL. The location of the remote repository, if 23.1500 + known. See section <xref linkend="sec:hook:url"/> for more information. 23.1501 +</para> 23.1502 +</listitem></itemizedlist> 23.1503 + 23.1504 +<para>See also: <literal role="hook">changegroup</literal> (section <xref linkend="sec:hook:changegroup"/>) <literal role="hook">prechangegroup</literal> (section <xref linkend="sec:hook:prechangegroup"/>), <literal role="hook">pretxnchangegroup</literal> (section <xref linkend="sec:hook:pretxnchangegroup"/>) 23.1505 +</para> 23.1506 + 23.1507 +</sect2> 23.1508 +<sect2> 23.1509 +<title><literal role="hook">outgoing</literal>&emdash;after changesets are propagated</title> 23.1510 +<para>\label{sec:hook:outgoing} 23.1511 +</para> 23.1512 + 23.1513 +<para>This hook is run after a group of changesets has been propagated out 23.1514 +of this repository, for example by a <command role="hg-cmd">hg push</command> or <command role="hg-cmd">hg bundle</command> 23.1515 +command. 23.1516 +</para> 23.1517 + 23.1518 +<para>One possible use for this hook is to notify administrators that 23.1519 +changes have been pulled. 23.1520 +</para> 23.1521 + 23.1522 +<para>Parameters to this hook: 23.1523 +</para> 23.1524 +<itemizedlist> 23.1525 +<listitem><para><literal>node</literal>: A changeset ID. The changeset ID of the first 23.1526 + changeset of the group that was sent. 23.1527 +</para> 23.1528 +</listitem> 23.1529 +<listitem><para><literal>source</literal>: A string. The source of the of the operation 23.1530 + (see section <xref linkend="sec:hook:sources"/>). If a remote client pulled 23.1531 + changes from this repository, <literal>source</literal> will be 23.1532 + <literal>serve</literal>. If the client that obtained changes from this 23.1533 + repository was local, <literal>source</literal> will be <literal>bundle</literal>, 23.1534 + <literal>pull</literal>, or <literal>push</literal>, depending on the operation the 23.1535 + client performed. 23.1536 +</para> 23.1537 +</listitem> 23.1538 +<listitem><para><literal>url</literal>: A URL. The location of the remote repository, if 23.1539 + known. See section <xref linkend="sec:hook:url"/> for more information. 23.1540 +</para> 23.1541 +</listitem></itemizedlist> 23.1542 + 23.1543 +<para>See also: <literal role="hook">preoutgoing</literal> (section <xref linkend="sec:hook:preoutgoing"/>) 23.1544 +</para> 23.1545 + 23.1546 +</sect2> 23.1547 +<sect2> 23.1548 +<title><literal role="hook">prechangegroup</literal>&emdash;before starting to add remote changesets</title> 23.1549 +<para>\label{sec:hook:prechangegroup} 23.1550 +</para> 23.1551 + 23.1552 +<para>This controlling hook is run before Mercurial begins to add a group of 23.1553 +changesets from another repository. 23.1554 +</para> 23.1555 + 23.1556 +<para>This hook does not have any information about the changesets to be 23.1557 +added, because it is run before transmission of those changesets is 23.1558 +allowed to begin. If this hook fails, the changesets will not be 23.1559 +transmitted. 23.1560 +</para> 23.1561 + 23.1562 +<para>One use for this hook is to prevent external changes from being added 23.1563 +to a repository. For example, you could use this to <quote>freeze</quote> a 23.1564 +server-hosted branch temporarily or permanently so that users cannot 23.1565 +push to it, while still allowing a local administrator to modify the 23.1566 +repository. 23.1567 +</para> 23.1568 + 23.1569 +<para>Parameters to this hook: 23.1570 +</para> 23.1571 +<itemizedlist> 23.1572 +<listitem><para><literal>source</literal>: A string. The source of these changes. See 23.1573 + section <xref linkend="sec:hook:sources"/> for details. 23.1574 +</para> 23.1575 +</listitem> 23.1576 +<listitem><para><literal>url</literal>: A URL. The location of the remote repository, if 23.1577 + known. See section <xref linkend="sec:hook:url"/> for more information. 23.1578 +</para> 23.1579 +</listitem></itemizedlist> 23.1580 + 23.1581 +<para>See also: <literal role="hook">changegroup</literal> (section <xref linkend="sec:hook:changegroup"/>), 23.1582 +<literal role="hook">incoming</literal> (section <xref linkend="sec:hook:incoming"/>), , 23.1583 +<literal role="hook">pretxnchangegroup</literal> (section <xref linkend="sec:hook:pretxnchangegroup"/>) 23.1584 +</para> 23.1585 + 23.1586 +</sect2> 23.1587 +<sect2> 23.1588 +<title><literal role="hook">precommit</literal>&emdash;before starting to commit a changeset</title> 23.1589 +<para>\label{sec:hook:precommit} 23.1590 +</para> 23.1591 + 23.1592 +<para>This hook is run before Mercurial begins to commit a new changeset. 23.1593 +It is run before Mercurial has any of the metadata for the commit, 23.1594 +such as the files to be committed, the commit message, or the commit 23.1595 +date. 23.1596 +</para> 23.1597 + 23.1598 +<para>One use for this hook is to disable the ability to commit new 23.1599 +changesets, while still allowing incoming changesets. Another is to 23.1600 +run a build or test, and only allow the commit to begin if the build 23.1601 +or test succeeds. 23.1602 +</para> 23.1603 + 23.1604 +<para>Parameters to this hook: 23.1605 +</para> 23.1606 +<itemizedlist> 23.1607 +<listitem><para><literal>parent1</literal>: A changeset ID. The changeset ID of the first 23.1608 + parent of the working directory. 23.1609 +</para> 23.1610 +</listitem> 23.1611 +<listitem><para><literal>parent2</literal>: A changeset ID. The changeset ID of the second 23.1612 + parent of the working directory. 23.1613 +</para> 23.1614 +</listitem></itemizedlist> 23.1615 +<para>If the commit proceeds, the parents of the working directory will 23.1616 +become the parents of the new changeset. 23.1617 +</para> 23.1618 + 23.1619 +<para>See also: <literal role="hook">commit</literal> (section <xref linkend="sec:hook:commit"/>), 23.1620 +<literal role="hook">pretxncommit</literal> (section <xref linkend="sec:hook:pretxncommit"/>) 23.1621 +</para> 23.1622 + 23.1623 +</sect2> 23.1624 +<sect2> 23.1625 +<title><literal role="hook">preoutgoing</literal>&emdash;before starting to propagate changesets</title> 23.1626 +<para>\label{sec:hook:preoutgoing} 23.1627 +</para> 23.1628 + 23.1629 +<para>This hook is invoked before Mercurial knows the identities of the 23.1630 +changesets to be transmitted. 23.1631 +</para> 23.1632 + 23.1633 +<para>One use for this hook is to prevent changes from being transmitted to 23.1634 +another repository. 23.1635 +</para> 23.1636 + 23.1637 +<para>Parameters to this hook: 23.1638 +</para> 23.1639 +<itemizedlist> 23.1640 +<listitem><para><literal>source</literal>: A string. The source of the operation that is 23.1641 + attempting to obtain changes from this repository (see 23.1642 + section <xref linkend="sec:hook:sources"/>). See the documentation for the 23.1643 + <literal>source</literal> parameter to the <literal role="hook">outgoing</literal> hook, in 23.1644 + section <xref linkend="sec:hook:outgoing"/>, for possible values of this 23.1645 + parameter. 23.1646 +</para> 23.1647 +</listitem> 23.1648 +<listitem><para><literal>url</literal>: A URL. The location of the remote repository, if 23.1649 + known. See section <xref linkend="sec:hook:url"/> for more information. 23.1650 +</para> 23.1651 +</listitem></itemizedlist> 23.1652 + 23.1653 +<para>See also: <literal role="hook">outgoing</literal> (section <xref linkend="sec:hook:outgoing"/>) 23.1654 +</para> 23.1655 + 23.1656 +</sect2> 23.1657 +<sect2> 23.1658 +<title><literal role="hook">pretag</literal>&emdash;before tagging a changeset</title> 23.1659 +<para>\label{sec:hook:pretag} 23.1660 +</para> 23.1661 + 23.1662 +<para>This controlling hook is run before a tag is created. If the hook 23.1663 +succeeds, creation of the tag proceeds. If the hook fails, the tag is 23.1664 +not created. 23.1665 +</para> 23.1666 + 23.1667 +<para>Parameters to this hook: 23.1668 +</para> 23.1669 +<itemizedlist> 23.1670 +<listitem><para><literal>local</literal>: A boolean. Whether the tag is local to this 23.1671 + repository instance (i.e. stored in <filename role="special">.hg/localtags</filename>) or 23.1672 + managed by Mercurial (stored in <filename role="special">.hgtags</filename>). 23.1673 +</para> 23.1674 +</listitem> 23.1675 +<listitem><para><literal>node</literal>: A changeset ID. The ID of the changeset to be tagged. 23.1676 +</para> 23.1677 +</listitem> 23.1678 +<listitem><para><literal>tag</literal>: A string. The name of the tag to be created. 23.1679 +</para> 23.1680 +</listitem></itemizedlist> 23.1681 + 23.1682 +<para>If the tag to be created is revision-controlled, the <literal role="hook">precommit</literal> 23.1683 +and <literal role="hook">pretxncommit</literal> hooks (sections <xref linkend="sec:hook:commit"/> 23.1684 +and <xref linkend="sec:hook:pretxncommit"/>) will also be run. 23.1685 +</para> 23.1686 + 23.1687 +<para>See also: <literal role="hook">tag</literal> (section <xref linkend="sec:hook:tag"/>) 23.1688 +</para> 23.1689 + 23.1690 +<para>\subsection{<literal role="hook">pretxnchangegroup</literal>&emdash;before completing addition of 23.1691 + remote changesets} 23.1692 +\label{sec:hook:pretxnchangegroup} 23.1693 +</para> 23.1694 + 23.1695 +<para>This controlling hook is run before a transaction&emdash;that manages the 23.1696 +addition of a group of new changesets from outside the 23.1697 +repository&emdash;completes. If the hook succeeds, the transaction 23.1698 +completes, and all of the changesets become permanent within this 23.1699 +repository. If the hook fails, the transaction is rolled back, and 23.1700 +the data for the changesets is erased. 23.1701 +</para> 23.1702 + 23.1703 +<para>This hook can access the metadata associated with the almost-added 23.1704 +changesets, but it should not do anything permanent with this data. 23.1705 +It must also not modify the working directory. 23.1706 +</para> 23.1707 + 23.1708 +<para>While this hook is running, if other Mercurial processes access this 23.1709 +repository, they will be able to see the almost-added changesets as if 23.1710 +they are permanent. This may lead to race conditions if you do not 23.1711 +take steps to avoid them. 23.1712 +</para> 23.1713 + 23.1714 +<para>This hook can be used to automatically vet a group of changesets. If 23.1715 +the hook fails, all of the changesets are <quote>rejected</quote> when the 23.1716 +transaction rolls back. 23.1717 +</para> 23.1718 + 23.1719 +<para>Parameters to this hook: 23.1720 +</para> 23.1721 +<itemizedlist> 23.1722 +<listitem><para><literal>node</literal>: A changeset ID. The changeset ID of the first 23.1723 + changeset in the group that was added. All changesets between this 23.1724 + and \index{tags!<literal>tip</literal>}<literal>tip</literal>, inclusive, were added by 23.1725 + a single <command role="hg-cmd">hg pull</command>, <command role="hg-cmd">hg push</command> or <command role="hg-cmd">hg unbundle</command>. 23.1726 +</para> 23.1727 +</listitem> 23.1728 +<listitem><para><literal>source</literal>: A string. The source of these changes. See 23.1729 + section <xref linkend="sec:hook:sources"/> for details. 23.1730 +</para> 23.1731 +</listitem> 23.1732 +<listitem><para><literal>url</literal>: A URL. The location of the remote repository, if 23.1733 + known. See section <xref linkend="sec:hook:url"/> for more information. 23.1734 +</para> 23.1735 +</listitem></itemizedlist> 23.1736 + 23.1737 +<para>See also: <literal role="hook">changegroup</literal> (section <xref linkend="sec:hook:changegroup"/>), 23.1738 +<literal role="hook">incoming</literal> (section <xref linkend="sec:hook:incoming"/>), 23.1739 +<literal role="hook">prechangegroup</literal> (section <xref linkend="sec:hook:prechangegroup"/>) 23.1740 +</para> 23.1741 + 23.1742 +</sect2> 23.1743 +<sect2> 23.1744 +<title><literal role="hook">pretxncommit</literal>&emdash;before completing commit of new changeset</title> 23.1745 +<para>\label{sec:hook:pretxncommit} 23.1746 +</para> 23.1747 + 23.1748 +<para>This controlling hook is run before a transaction&emdash;that manages a new 23.1749 +commit&emdash;completes. If the hook succeeds, the transaction completes 23.1750 +and the changeset becomes permanent within this repository. If the 23.1751 +hook fails, the transaction is rolled back, and the commit data is 23.1752 +erased. 23.1753 +</para> 23.1754 + 23.1755 +<para>This hook can access the metadata associated with the almost-new 23.1756 +changeset, but it should not do anything permanent with this data. It 23.1757 +must also not modify the working directory. 23.1758 +</para> 23.1759 + 23.1760 +<para>While this hook is running, if other Mercurial processes access this 23.1761 +repository, they will be able to see the almost-new changeset as if it 23.1762 +is permanent. This may lead to race conditions if you do not take 23.1763 +steps to avoid them. 23.1764 +</para> 23.1765 + 23.1766 +<para>Parameters to this hook: 23.1767 +</para> 23.1768 +<itemizedlist> 23.1769 +<listitem><para><literal>node</literal>: A changeset ID. The changeset ID of the newly 23.1770 + committed changeset. 23.1771 +</para> 23.1772 +</listitem> 23.1773 +<listitem><para><literal>parent1</literal>: A changeset ID. The changeset ID of the first 23.1774 + parent of the newly committed changeset. 23.1775 +</para> 23.1776 +</listitem> 23.1777 +<listitem><para><literal>parent2</literal>: A changeset ID. The changeset ID of the second 23.1778 + parent of the newly committed changeset. 23.1779 +</para> 23.1780 +</listitem></itemizedlist> 23.1781 + 23.1782 +<para>See also: <literal role="hook">precommit</literal> (section <xref linkend="sec:hook:precommit"/>) 23.1783 +</para> 23.1784 + 23.1785 +</sect2> 23.1786 +<sect2> 23.1787 +<title><literal role="hook">preupdate</literal>&emdash;before updating or merging working directory</title> 23.1788 +<para>\label{sec:hook:preupdate} 23.1789 +</para> 23.1790 + 23.1791 +<para>This controlling hook is run before an update or merge of the working 23.1792 +directory begins. It is run only if Mercurial's normal pre-update 23.1793 +checks determine that the update or merge can proceed. If the hook 23.1794 +succeeds, the update or merge may proceed; if it fails, the update or 23.1795 +merge does not start. 23.1796 +</para> 23.1797 + 23.1798 +<para>Parameters to this hook: 23.1799 +</para> 23.1800 +<itemizedlist> 23.1801 +<listitem><para><literal>parent1</literal>: A changeset ID. The ID of the parent that the 23.1802 + working directory is to be updated to. If the working directory is 23.1803 + being merged, it will not change this parent. 23.1804 +</para> 23.1805 +</listitem> 23.1806 +<listitem><para><literal>parent2</literal>: A changeset ID. Only set if the working 23.1807 + directory is being merged. The ID of the revision that the working 23.1808 + directory is being merged with. 23.1809 +</para> 23.1810 +</listitem></itemizedlist> 23.1811 + 23.1812 +<para>See also: <literal role="hook">update</literal> (section <xref linkend="sec:hook:update"/>) 23.1813 +</para> 23.1814 + 23.1815 +</sect2> 23.1816 +<sect2> 23.1817 +<title><literal role="hook">tag</literal>&emdash;after tagging a changeset</title> 23.1818 +<para>\label{sec:hook:tag} 23.1819 +</para> 23.1820 + 23.1821 +<para>This hook is run after a tag has been created. 23.1822 +</para> 23.1823 + 23.1824 +<para>Parameters to this hook: 23.1825 +</para> 23.1826 +<itemizedlist> 23.1827 +<listitem><para><literal>local</literal>: A boolean. Whether the new tag is local to this 23.1828 + repository instance (i.e. stored in <filename role="special">.hg/localtags</filename>) or 23.1829 + managed by Mercurial (stored in <filename role="special">.hgtags</filename>). 23.1830 +</para> 23.1831 +</listitem> 23.1832 +<listitem><para><literal>node</literal>: A changeset ID. The ID of the changeset that was 23.1833 + tagged. 23.1834 +</para> 23.1835 +</listitem> 23.1836 +<listitem><para><literal>tag</literal>: A string. The name of the tag that was created. 23.1837 +</para> 23.1838 +</listitem></itemizedlist> 23.1839 + 23.1840 +<para>If the created tag is revision-controlled, the <literal role="hook">commit</literal> hook 23.1841 +(section <xref linkend="sec:hook:commit"/>) is run before this hook. 23.1842 +</para> 23.1843 + 23.1844 +<para>See also: <literal role="hook">pretag</literal> (section <xref linkend="sec:hook:pretag"/>) 23.1845 +</para> 23.1846 + 23.1847 +</sect2> 23.1848 +<sect2> 23.1849 +<title><literal role="hook">update</literal>&emdash;after updating or merging working directory</title> 23.1850 +<para>\label{sec:hook:update} 23.1851 +</para> 23.1852 + 23.1853 +<para>This hook is run after an update or merge of the working directory 23.1854 +completes. Since a merge can fail (if the external <command>hgmerge</command> 23.1855 +command fails to resolve conflicts in a file), this hook communicates 23.1856 +whether the update or merge completed cleanly. 23.1857 +</para> 23.1858 + 23.1859 +<itemizedlist> 23.1860 +<listitem><para><literal>error</literal>: A boolean. Indicates whether the update or 23.1861 + merge completed successfully. 23.1862 +</para> 23.1863 +</listitem> 23.1864 +<listitem><para><literal>parent1</literal>: A changeset ID. The ID of the parent that the 23.1865 + working directory was updated to. If the working directory was 23.1866 + merged, it will not have changed this parent. 23.1867 +</para> 23.1868 +</listitem> 23.1869 +<listitem><para><literal>parent2</literal>: A changeset ID. Only set if the working 23.1870 + directory was merged. The ID of the revision that the working 23.1871 + directory was merged with. 23.1872 +</para> 23.1873 +</listitem></itemizedlist> 23.1874 + 23.1875 +<para>See also: <literal role="hook">preupdate</literal> (section <xref linkend="sec:hook:preupdate"/>) 23.1876 +</para> 23.1877 + 23.1878 +</sect2> 23.1879 +</sect1> 23.1880 +</chapter> 23.1881 + 23.1882 +<!-- 23.1883 +local variables: 23.1884 +sgml-parent-document: ("00book.xml" "book" "chapter") 23.1885 +end: 23.1886 +--> 23.1887 \ No newline at end of file
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 24.2 +++ b/fr/ch11-template.xml Sun Aug 16 04:58:01 2009 +0200 24.3 @@ -0,0 +1,689 @@ 24.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 24.5 + 24.6 +<chapter> 24.7 +<title>Customising the output of Mercurial</title> 24.8 +<para>\label{chap:template}</para> 24.9 + 24.10 +<para>Mercurial provides a powerful mechanism to let you control how it 24.11 +displays information. The mechanism is based on templates. You can 24.12 +use templates to generate specific output for a single command, or to 24.13 +customise the entire appearance of the built-in web interface.</para> 24.14 + 24.15 +<sect1> 24.16 +<title>Using precanned output styles</title> 24.17 +<para>\label{sec:style}</para> 24.18 + 24.19 +<para>Packaged with Mercurial are some output styles that you can use 24.20 +immediately. A style is simply a precanned template that someone 24.21 +wrote and installed somewhere that Mercurial can find.</para> 24.22 + 24.23 +<para>Before we take a look at Mercurial's bundled styles, let's review its 24.24 +normal output.</para> 24.25 + 24.26 +<para><!-- &interaction.template.simple.normal; --></para> 24.27 + 24.28 +<para>This is somewhat informative, but it takes up a lot of space&emdash;five 24.29 +lines of output per changeset. The <literal>compact</literal> style reduces 24.30 +this to three lines, presented in a sparse manner.</para> 24.31 + 24.32 +<para><!-- &interaction.template.simple.compact; --></para> 24.33 + 24.34 +<para>The <literal>changelog</literal> style hints at the expressive power of 24.35 +Mercurial's templating engine. This style attempts to follow the GNU 24.36 +Project's changelog guidelines<citation>web:changelog</citation>. 24.37 +</para> 24.38 + 24.39 +<para><!-- &interaction.template.simple.changelog; --> 24.40 +</para> 24.41 + 24.42 +<para>You will not be shocked to learn that Mercurial's default output style 24.43 +is named <literal>default</literal>. 24.44 +</para> 24.45 + 24.46 +<sect2> 24.47 +<title>Setting a default style</title> 24.48 + 24.49 +<para>You can modify the output style that Mercurial will use for every 24.50 +command by editing your <filename role="special"> /.hgrc</filename>\ file, naming the style you would 24.51 +prefer to use. 24.52 +</para> 24.53 + 24.54 +<programlisting> 24.55 +<para> [ui] 24.56 + style = compact 24.57 +</para> 24.58 +</programlisting> 24.59 + 24.60 +<para>If you write a style of your own, you can use it by either providing 24.61 +the path to your style file, or copying your style file into a 24.62 +location where Mercurial can find it (typically the <literal>templates</literal> 24.63 +subdirectory of your Mercurial install directory). 24.64 +</para> 24.65 + 24.66 +</sect2> 24.67 +</sect1> 24.68 +<sect1> 24.69 +<title>Commands that support styles and templates</title> 24.70 + 24.71 +<para>All of Mercurial's <quote><literal>log</literal>-like</quote> commands let you use styles 24.72 +and templates: <command role="hg-cmd">hg incoming</command>, <command role="hg-cmd">hg log</command>, <command role="hg-cmd">hg outgoing</command>, and 24.73 +<command role="hg-cmd">hg tip</command>. 24.74 +</para> 24.75 + 24.76 +<para>As I write this manual, these are so far the only commands that 24.77 +support styles and templates. Since these are the most important 24.78 +commands that need customisable output, there has been little pressure 24.79 +from the Mercurial user community to add style and template support to 24.80 +other commands. 24.81 +</para> 24.82 + 24.83 +</sect1> 24.84 +<sect1> 24.85 +<title>The basics of templating</title> 24.86 + 24.87 +<para>At its simplest, a Mercurial template is a piece of text. Some of the 24.88 +text never changes, while other parts are <emphasis>expanded</emphasis>, or replaced 24.89 +with new text, when necessary. 24.90 +</para> 24.91 + 24.92 +<para>Before we continue, let's look again at a simple example of 24.93 +Mercurial's normal output. 24.94 +</para> 24.95 + 24.96 +<para><!-- &interaction.template.simple.normal; --> 24.97 +</para> 24.98 + 24.99 +<para>Now, let's run the same command, but using a template to change its 24.100 +output. 24.101 +</para> 24.102 + 24.103 +<para><!-- &interaction.template.simple.simplest; --> 24.104 +</para> 24.105 + 24.106 +<para>The example above illustrates the simplest possible template; it's 24.107 +just a piece of static text, printed once for each changeset. The 24.108 +<option role="hg-opt-log">--template</option> option to the <command role="hg-cmd">hg log</command> command tells 24.109 +Mercurial to use the given text as the template when printing each 24.110 +changeset. 24.111 +</para> 24.112 + 24.113 +<para>Notice that the template string above ends with the text 24.114 +<quote><literal>\n</literal></quote>. This is an <emphasis>escape sequence</emphasis>, telling Mercurial 24.115 +to print a newline at the end of each template item. If you omit this 24.116 +newline, Mercurial will run each piece of output together. See 24.117 +section <xref linkend="sec:template:escape"/> for more details of escape sequences. 24.118 +</para> 24.119 + 24.120 +<para>A template that prints a fixed string of text all the time isn't very 24.121 +useful; let's try something a bit more complex. 24.122 +</para> 24.123 + 24.124 +<para><!-- &interaction.template.simple.simplesub; --> 24.125 +</para> 24.126 + 24.127 +<para>As you can see, the string <quote><literal>{desc}</literal></quote> in the template has been 24.128 +replaced in the output with the description of each changeset. Every 24.129 +time Mercurial finds text enclosed in curly braces (<quote><literal>{</literal></quote> 24.130 +and <quote>\texttt{}}</quote>), it will try to replace the braces and text with 24.131 +the expansion of whatever is inside. To print a literal curly brace, 24.132 +you must escape it, as described in section <xref linkend="sec:template:escape"/>. 24.133 +</para> 24.134 + 24.135 +</sect1> 24.136 +<sect1> 24.137 +<title>Common template keywords</title> 24.138 +<para>\label{sec:template:keyword} 24.139 +</para> 24.140 + 24.141 +<para>You can start writing simple templates immediately using the keywords 24.142 +below. 24.143 +</para> 24.144 + 24.145 +<itemizedlist> 24.146 +<listitem><para><literal role="template-keyword">author</literal>: String. The unmodified author of the changeset. 24.147 +</para> 24.148 +</listitem> 24.149 +<listitem><para><literal role="template-keyword">branches</literal>: String. The name of the branch on which 24.150 + the changeset was committed. Will be empty if the branch name was 24.151 + <literal>default</literal>. 24.152 +</para> 24.153 +</listitem> 24.154 +<listitem><para><literal role="template-keyword">date</literal>: Date information. The date when the changeset 24.155 + was committed. This is <emphasis>not</emphasis> human-readable; you must pass it 24.156 + through a filter that will render it appropriately. See 24.157 + section <xref linkend="sec:template:filter"/> for more information on filters. 24.158 + The date is expressed as a pair of numbers. The first number is a 24.159 + Unix UTC timestamp (seconds since January 1, 1970); the second is 24.160 + the offset of the committer's timezone from UTC, in seconds. 24.161 +</para> 24.162 +</listitem> 24.163 +<listitem><para><literal role="template-keyword">desc</literal>: String. The text of the changeset description. 24.164 +</para> 24.165 +</listitem> 24.166 +<listitem><para><literal role="template-keyword">files</literal>: List of strings. All files modified, added, or 24.167 + removed by this changeset. 24.168 +</para> 24.169 +</listitem> 24.170 +<listitem><para><literal role="template-keyword">file_adds</literal>: List of strings. Files added by this 24.171 + changeset. 24.172 +</para> 24.173 +</listitem> 24.174 +<listitem><para><literal role="template-keyword">file_dels</literal>: List of strings. Files removed by this 24.175 + changeset. 24.176 +</para> 24.177 +</listitem> 24.178 +<listitem><para><literal role="template-keyword">node</literal>: String. The changeset identification hash, as a 24.179 + 40-character hexadecimal string. 24.180 +</para> 24.181 +</listitem> 24.182 +<listitem><para><literal role="template-keyword">parents</literal>: List of strings. The parents of the 24.183 + changeset. 24.184 +</para> 24.185 +</listitem> 24.186 +<listitem><para><literal role="template-keyword">rev</literal>: Integer. The repository-local changeset revision 24.187 + number. 24.188 +</para> 24.189 +</listitem> 24.190 +<listitem><para><literal role="template-keyword">tags</literal>: List of strings. Any tags associated with the 24.191 + changeset. 24.192 +</para> 24.193 +</listitem></itemizedlist> 24.194 + 24.195 +<para>A few simple experiments will show us what to expect when we use these 24.196 +keywords; you can see the results in 24.197 +figure <xref linkend="fig:template:keywords"/>. 24.198 +</para> 24.199 + 24.200 +<informalfigure> 24.201 +<para> <!-- &interaction.template.simple.keywords; --> 24.202 + <caption><para>Template keywords in use</para></caption> 24.203 + \label{fig:template:keywords} 24.204 +</para> 24.205 +</informalfigure> 24.206 + 24.207 +<para>As we noted above, the date keyword does not produce human-readable 24.208 +output, so we must treat it specially. This involves using a 24.209 +<emphasis>filter</emphasis>, about which more in section <xref linkend="sec:template:filter"/>. 24.210 +</para> 24.211 + 24.212 +<para><!-- &interaction.template.simple.datekeyword; --> 24.213 +</para> 24.214 + 24.215 +</sect1> 24.216 +<sect1> 24.217 +<title>Escape sequences</title> 24.218 +<para>\label{sec:template:escape} 24.219 +</para> 24.220 + 24.221 +<para>Mercurial's templating engine recognises the most commonly used escape 24.222 +sequences in strings. When it sees a backslash (<quote><literal>\</literal></quote>) 24.223 +character, it looks at the following character and substitutes the two 24.224 +characters with a single replacement, as described below. 24.225 +</para> 24.226 + 24.227 +<itemizedlist> 24.228 +<listitem><para><literal>\textbackslash\textbackslash</literal>: Backslash, <quote><literal>\</literal></quote>, 24.229 + ASCII 134. 24.230 +</para> 24.231 +</listitem> 24.232 +<listitem><para><literal>\textbackslash n</literal>: Newline, ASCII 12. 24.233 +</para> 24.234 +</listitem> 24.235 +<listitem><para><literal>\textbackslash r</literal>: Carriage return, ASCII 15. 24.236 +</para> 24.237 +</listitem> 24.238 +<listitem><para><literal>\textbackslash t</literal>: Tab, ASCII 11. 24.239 +</para> 24.240 +</listitem> 24.241 +<listitem><para><literal>\textbackslash v</literal>: Vertical tab, ASCII 13. 24.242 +</para> 24.243 +</listitem> 24.244 +<listitem><para><literal>\textbackslash {</literal>: Open curly brace, <quote><literal>{</literal></quote>, ASCII 173. 24.245 +</para> 24.246 +</listitem> 24.247 +<listitem><para><literal>\textbackslash }</literal>: Close curly brace, <quote><literal>}</literal></quote>, ASCII 175. 24.248 +</para> 24.249 +</listitem></itemizedlist> 24.250 + 24.251 +<para>As indicated above, if you want the expansion of a template to contain 24.252 +a literal <quote><literal>\</literal></quote>, <quote><literal>{</literal></quote>, or <quote><literal>{</literal></quote> character, you 24.253 +must escape it. 24.254 +</para> 24.255 + 24.256 +</sect1> 24.257 +<sect1> 24.258 +<title>Filtering keywords to change their results</title> 24.259 +<para>\label{sec:template:filter} 24.260 +</para> 24.261 + 24.262 +<para>Some of the results of template expansion are not immediately easy to 24.263 +use. Mercurial lets you specify an optional chain of <emphasis>filters</emphasis> 24.264 +to modify the result of expanding a keyword. You have already seen a 24.265 +common filter, <literal role="template-kw-filt-date">isodate</literal>, in action above, to make a 24.266 +date readable. 24.267 +</para> 24.268 + 24.269 +<para>Below is a list of the most commonly used filters that Mercurial 24.270 +supports. While some filters can be applied to any text, others can 24.271 +only be used in specific circumstances. The name of each filter is 24.272 +followed first by an indication of where it can be used, then a 24.273 +description of its effect. 24.274 +</para> 24.275 + 24.276 +<itemizedlist> 24.277 +<listitem><para><literal role="template-filter">addbreaks</literal>: Any text. Add an XHTML <quote><literal><br/></literal></quote> 24.278 + tag before the end of every line except the last. For example, 24.279 + <quote><literal>foo\nbar</literal></quote> becomes <quote><literal>foo<br/>\nbar</literal></quote>. 24.280 +</para> 24.281 +</listitem> 24.282 +<listitem><para><literal role="template-kw-filt-date">age</literal>: <literal role="template-keyword">date</literal> keyword. Render the 24.283 + age of the date, relative to the current time. Yields a string like 24.284 + <quote><literal>10 minutes</literal></quote>. 24.285 +</para> 24.286 +</listitem> 24.287 +<listitem><para><literal role="template-filter">basename</literal>: Any text, but most useful for the 24.288 + <literal role="template-keyword">files</literal> keyword and its relatives. Treat the text as a 24.289 + path, and return the basename. For example, <quote><literal>foo/bar/baz</literal></quote> 24.290 + becomes <quote><literal>baz</literal></quote>. 24.291 +</para> 24.292 +</listitem> 24.293 +<listitem><para><literal role="template-kw-filt-date">date</literal>: <literal role="template-keyword">date</literal> keyword. Render a date 24.294 + in a similar format to the Unix <literal role="template-keyword">date</literal> command, but with 24.295 + timezone included. Yields a string like 24.296 + <quote><literal>Mon Sep 04 15:13:13 2006 -0700</literal></quote>. 24.297 +</para> 24.298 +</listitem> 24.299 +<listitem><para><literal role="template-kw-filt-author">domain</literal>: Any text, but most useful for the 24.300 + <literal role="template-keyword">author</literal> keyword. Finds the first string that looks like 24.301 + an email address, and extract just the domain component. For 24.302 + example, <quote><literal>Bryan O'Sullivan <bos@serpentine.com></literal></quote> becomes 24.303 + <quote><literal>serpentine.com</literal></quote>. 24.304 +</para> 24.305 +</listitem> 24.306 +<listitem><para><literal role="template-kw-filt-author">email</literal>: Any text, but most useful for the 24.307 + <literal role="template-keyword">author</literal> keyword. Extract the first string that looks like 24.308 + an email address. For example, 24.309 + <quote><literal>Bryan O'Sullivan <bos@serpentine.com></literal></quote> becomes 24.310 + <quote><literal>bos@serpentine.com</literal></quote>. 24.311 +</para> 24.312 +</listitem> 24.313 +<listitem><para><literal role="template-filter">escape</literal>: Any text. Replace the special XML/XHTML 24.314 + characters <quote><literal>&</literal></quote>, <quote><literal><</literal></quote> and <quote><literal>></literal></quote> with 24.315 + XML entities. 24.316 +</para> 24.317 +</listitem> 24.318 +<listitem><para><literal role="template-filter">fill68</literal>: Any text. Wrap the text to fit in 68 24.319 + columns. This is useful before you pass text through the 24.320 + <literal role="template-filter">tabindent</literal> filter, and still want it to fit in an 24.321 + 80-column fixed-font window. 24.322 +</para> 24.323 +</listitem> 24.324 +<listitem><para><literal role="template-filter">fill76</literal>: Any text. Wrap the text to fit in 76 24.325 + columns. 24.326 +</para> 24.327 +</listitem> 24.328 +<listitem><para><literal role="template-filter">firstline</literal>: Any text. Yield the first line of text, 24.329 + without any trailing newlines. 24.330 +</para> 24.331 +</listitem> 24.332 +<listitem><para><literal role="template-kw-filt-date">hgdate</literal>: <literal role="template-keyword">date</literal> keyword. Render the 24.333 + date as a pair of readable numbers. Yields a string like 24.334 + <quote><literal>1157407993 25200</literal></quote>. 24.335 +</para> 24.336 +</listitem> 24.337 +<listitem><para><literal role="template-kw-filt-date">isodate</literal>: <literal role="template-keyword">date</literal> keyword. Render the 24.338 + date as a text string in ISO 8601 format. Yields a string like 24.339 + <quote><literal>2006-09-04 15:13:13 -0700</literal></quote>. 24.340 +</para> 24.341 +</listitem> 24.342 +<listitem><para><literal role="template-filter">obfuscate</literal>: Any text, but most useful for the 24.343 + <literal role="template-keyword">author</literal> keyword. Yield the input text rendered as a 24.344 + sequence of XML entities. This helps to defeat some particularly 24.345 + stupid screen-scraping email harvesting spambots. 24.346 +</para> 24.347 +</listitem> 24.348 +<listitem><para><literal role="template-kw-filt-author">person</literal>: Any text, but most useful for the 24.349 + <literal role="template-keyword">author</literal> keyword. Yield the text before an email address. 24.350 + For example, <quote><literal>Bryan O'Sullivan <bos@serpentine.com></literal></quote> 24.351 + becomes <quote><literal>Bryan O'Sullivan</literal></quote>. 24.352 +</para> 24.353 +</listitem> 24.354 +<listitem><para><literal role="template-kw-filt-date">rfc822date</literal>: <literal role="template-keyword">date</literal> keyword. Render a 24.355 + date using the same format used in email headers. Yields a string 24.356 + like <quote><literal>Mon, 04 Sep 2006 15:13:13 -0700</literal></quote>. 24.357 +</para> 24.358 +</listitem> 24.359 +<listitem><para><literal role="template-kw-filt-node">short</literal>: Changeset hash. Yield the short form 24.360 + of a changeset hash, i.e. a 12-character hexadecimal string. 24.361 +</para> 24.362 +</listitem> 24.363 +<listitem><para><literal role="template-kw-filt-date">shortdate</literal>: <literal role="template-keyword">date</literal> keyword. Render 24.364 + the year, month, and day of the date. Yields a string like 24.365 + <quote><literal>2006-09-04</literal></quote>. 24.366 +</para> 24.367 +</listitem> 24.368 +<listitem><para><literal role="template-filter">strip</literal>: Any text. Strip all leading and trailing 24.369 + whitespace from the string. 24.370 +</para> 24.371 +</listitem> 24.372 +<listitem><para><literal role="template-filter">tabindent</literal>: Any text. Yield the text, with every line 24.373 + except the first starting with a tab character. 24.374 +</para> 24.375 +</listitem> 24.376 +<listitem><para><literal role="template-filter">urlescape</literal>: Any text. Escape all characters that are 24.377 + considered <quote>special</quote> by URL parsers. For example, <literal>foo bar</literal> 24.378 + becomes <literal>foo%20bar</literal>. 24.379 +</para> 24.380 +</listitem> 24.381 +<listitem><para><literal role="template-kw-filt-author">user</literal>: Any text, but most useful for the 24.382 + <literal role="template-keyword">author</literal> keyword. Return the <quote>user</quote> portion of an email 24.383 + address. For example, 24.384 + <quote><literal>Bryan O'Sullivan <bos@serpentine.com></literal></quote> becomes 24.385 + <quote><literal>bos</literal></quote>. 24.386 +</para> 24.387 +</listitem></itemizedlist> 24.388 + 24.389 +<informalfigure> 24.390 +<para> <!-- &interaction.template.simple.manyfilters; --> 24.391 + <caption><para>Template filters in action</para></caption> 24.392 + \label{fig:template:filters} 24.393 +</para> 24.394 +</informalfigure> 24.395 + 24.396 +<note> 24.397 +<para> If you try to apply a filter to a piece of data that it cannot 24.398 + process, Mercurial will fail and print a Python exception. For 24.399 + example, trying to run the output of the <literal role="template-keyword">desc</literal> keyword 24.400 + into the <literal role="template-kw-filt-date">isodate</literal> filter is not a good idea. 24.401 +</para> 24.402 +</note> 24.403 + 24.404 +<sect2> 24.405 +<title>Combining filters</title> 24.406 + 24.407 +<para>It is easy to combine filters to yield output in the form you would 24.408 +like. The following chain of filters tidies up a description, then 24.409 +makes sure that it fits cleanly into 68 columns, then indents it by a 24.410 +further 8 characters (at least on Unix-like systems, where a tab is 24.411 +conventionally 8 characters wide). 24.412 +</para> 24.413 + 24.414 +<para><!-- &interaction.template.simple.combine; --> 24.415 +</para> 24.416 + 24.417 +<para>Note the use of <quote><literal>\t</literal></quote> (a tab character) in the template to 24.418 +force the first line to be indented; this is necessary since 24.419 +<literal role="template-keyword">tabindent</literal> indents all lines <emphasis>except</emphasis> the first. 24.420 +</para> 24.421 + 24.422 +<para>Keep in mind that the order of filters in a chain is significant. The 24.423 +first filter is applied to the result of the keyword; the second to 24.424 +the result of the first filter; and so on. For example, using 24.425 +<literal>fill68|tabindent</literal> gives very different results from 24.426 +<literal>tabindent|fill68</literal>. 24.427 +</para> 24.428 + 24.429 + 24.430 +</sect2> 24.431 +</sect1> 24.432 +<sect1> 24.433 +<title>From templates to styles</title> 24.434 + 24.435 +<para>A command line template provides a quick and simple way to format some 24.436 +output. Templates can become verbose, though, and it's useful to be 24.437 +able to give a template a name. A style file is a template with a 24.438 +name, stored in a file. 24.439 +</para> 24.440 + 24.441 +<para>More than that, using a style file unlocks the power of Mercurial's 24.442 +templating engine in ways that are not possible using the command line 24.443 +<option role="hg-opt-log">--template</option> option. 24.444 +</para> 24.445 + 24.446 +<sect2> 24.447 +<title>The simplest of style files</title> 24.448 + 24.449 +<para>Our simple style file contains just one line: 24.450 +</para> 24.451 + 24.452 +<para><!-- &interaction.template.simple.rev; --> 24.453 +</para> 24.454 + 24.455 +<para>This tells Mercurial, <quote>if you're printing a changeset, use the text 24.456 +on the right as the template</quote>. 24.457 +</para> 24.458 + 24.459 +</sect2> 24.460 +<sect2> 24.461 +<title>Style file syntax</title> 24.462 + 24.463 +<para>The syntax rules for a style file are simple. 24.464 +</para> 24.465 + 24.466 +<itemizedlist> 24.467 +<listitem><para>The file is processed one line at a time. 24.468 +</para> 24.469 +</listitem> 24.470 +</para> 24.471 +</listitem> 24.472 +<listitem><para>Leading and trailing white space are ignored. 24.473 +</para> 24.474 +</listitem> 24.475 +</para> 24.476 +</listitem> 24.477 +<listitem><para>Empty lines are skipped. 24.478 +</para> 24.479 +</listitem> 24.480 +</para> 24.481 +</listitem> 24.482 +<listitem><para>If a line starts with either of the characters <quote><literal>#</literal></quote> or 24.483 + <quote><literal>;</literal></quote>, the entire line is treated as a comment, and skipped 24.484 + as if empty. 24.485 +</para> 24.486 +</listitem> 24.487 +</para> 24.488 +</listitem> 24.489 +<listitem><para>A line starts with a keyword. This must start with an 24.490 + alphabetic character or underscore, and can subsequently contain any 24.491 + alphanumeric character or underscore. (In regexp notation, a 24.492 + keyword must match <literal>[A-Za-z_][A-Za-z0-9_]*</literal>.) 24.493 +</para> 24.494 +</listitem> 24.495 +</para> 24.496 +</listitem> 24.497 +<listitem><para>The next element must be an <quote><literal>=</literal></quote> character, which can 24.498 + be preceded or followed by an arbitrary amount of white space. 24.499 +</para> 24.500 +</listitem> 24.501 +</para> 24.502 +</listitem> 24.503 +<listitem><para>If the rest of the line starts and ends with matching quote 24.504 + characters (either single or double quote), it is treated as a 24.505 + template body. 24.506 +</para> 24.507 +</listitem> 24.508 +</para> 24.509 +</listitem> 24.510 +<listitem><para>If the rest of the line <emphasis>does not</emphasis> start with a quote 24.511 + character, it is treated as the name of a file; the contents of this 24.512 + file will be read and used as a template body. 24.513 +</para> 24.514 +</listitem></itemizedlist> 24.515 + 24.516 +</sect2> 24.517 +</sect1> 24.518 +<sect1> 24.519 +<title>Style files by example</title> 24.520 + 24.521 +<para>To illustrate how to write a style file, we will construct a few by 24.522 +example. Rather than provide a complete style file and walk through 24.523 +it, we'll mirror the usual process of developing a style file by 24.524 +starting with something very simple, and walking through a series of 24.525 +successively more complete examples. 24.526 +</para> 24.527 + 24.528 +<sect2> 24.529 +<title>Identifying mistakes in style files</title> 24.530 + 24.531 +<para>If Mercurial encounters a problem in a style file you are working on, 24.532 +it prints a terse error message that, once you figure out what it 24.533 +means, is actually quite useful. 24.534 +</para> 24.535 + 24.536 +<para><!-- &interaction.template.svnstyle.syntax.input; --> 24.537 +</para> 24.538 + 24.539 +<para>Notice that <filename>broken.style</filename> attempts to define a 24.540 +<literal>changeset</literal> keyword, but forgets to give any content for it. 24.541 +When instructed to use this style file, Mercurial promptly complains. 24.542 +</para> 24.543 + 24.544 +<para><!-- &interaction.template.svnstyle.syntax.error; --> 24.545 +</para> 24.546 + 24.547 +<para>This error message looks intimidating, but it is not too hard to 24.548 +follow. 24.549 +</para> 24.550 + 24.551 +<itemizedlist> 24.552 +<listitem><para>The first component is simply Mercurial's way of saying <quote>I am 24.553 + giving up</quote>. 24.554 +</para> 24.555 +</listitem><programlisting> 24.556 +<listitem><para> <emphasis role="bold">abort:</emphasis> broken.style:1: parse error 24.557 +</para> 24.558 +</listitem></programlisting> 24.559 + 24.560 +</para> 24.561 +</listitem> 24.562 +<listitem><para>Next comes the name of the style file that contains the error. 24.563 +</para> 24.564 +</listitem><programlisting> 24.565 +<listitem><para> abort: <emphasis role="bold">broken.style</emphasis>:1: parse error 24.566 +</para> 24.567 +</listitem></programlisting> 24.568 + 24.569 +</para> 24.570 +</listitem> 24.571 +<listitem><para>Following the file name is the line number where the error was 24.572 + encountered. 24.573 +</para> 24.574 +</listitem><programlisting> 24.575 +<listitem><para> abort: broken.style:<emphasis role="bold">1</emphasis>: parse error 24.576 +</para> 24.577 +</listitem></programlisting> 24.578 + 24.579 +</para> 24.580 +</listitem> 24.581 +<listitem><para>Finally, a description of what went wrong. 24.582 +</para> 24.583 +</listitem><programlisting> 24.584 +<listitem><para> abort: broken.style:1: <emphasis role="bold">parse error</emphasis> 24.585 +</para> 24.586 +</listitem></programlisting> 24.587 +<listitem><para> The description of the problem is not always clear (as in this 24.588 + case), but even when it is cryptic, it is almost always trivial to 24.589 + visually inspect the offending line in the style file and see what 24.590 + is wrong. 24.591 +</para> 24.592 +</listitem></itemizedlist> 24.593 + 24.594 +</sect2> 24.595 +<sect2> 24.596 +<title>Uniquely identifying a repository</title> 24.597 + 24.598 +<para>If you would like to be able to identify a Mercurial repository 24.599 +<quote>fairly uniquely</quote> using a short string as an identifier, you can 24.600 +use the first revision in the repository. 24.601 +<!-- &interaction.template.svnstyle.id; --> 24.602 +This is not guaranteed to be unique, but it is nevertheless useful in 24.603 +many cases. 24.604 +</para> 24.605 +<itemizedlist> 24.606 +<listitem><para>It will not work in a completely empty repository, because such 24.607 + a repository does not have a revision zero. 24.608 +</para> 24.609 +</listitem> 24.610 +<listitem><para>Neither will it work in the (extremely rare) case where a 24.611 + repository is a merge of two or more formerly independent 24.612 + repositories, and you still have those repositories around. 24.613 +</para> 24.614 +</listitem></itemizedlist> 24.615 +<para>Here are some uses to which you could put this identifier: 24.616 +</para> 24.617 +<itemizedlist> 24.618 +<listitem><para>As a key into a table for a database that manages repositories 24.619 + on a server. 24.620 +</para> 24.621 +</listitem> 24.622 +<listitem><para>As half of a {<emphasis>repository ID</emphasis>, <emphasis>revision ID</emphasis>} tuple. 24.623 + Save this information away when you run an automated build or other 24.624 + activity, so that you can <quote>replay</quote> the build later if necessary. 24.625 +</para> 24.626 +</listitem></itemizedlist> 24.627 + 24.628 +</sect2> 24.629 +<sect2> 24.630 +<title>Mimicking Subversion's output</title> 24.631 + 24.632 +<para>Let's try to emulate the default output format used by another 24.633 +revision control tool, Subversion. 24.634 +<!-- &interaction.template.svnstyle.short; --> 24.635 +</para> 24.636 + 24.637 +<para>Since Subversion's output style is fairly simple, it is easy to 24.638 +copy-and-paste a hunk of its output into a file, and replace the text 24.639 +produced above by Subversion with the template values we'd like to see 24.640 +expanded. 24.641 +<!-- &interaction.template.svnstyle.template; --> 24.642 +</para> 24.643 + 24.644 +<para>There are a few small ways in which this template deviates from the 24.645 +output produced by Subversion. 24.646 +</para> 24.647 +<itemizedlist> 24.648 +<listitem><para>Subversion prints a <quote>readable</quote> date (the <quote>\texttt{Wed, 27 Sep 24.649 + 2006}</quote> in the example output above) in parentheses. Mercurial's 24.650 + templating engine does not provide a way to display a date in this 24.651 + format without also printing the time and time zone. 24.652 +</para> 24.653 +</listitem> 24.654 +<listitem><para>We emulate Subversion's printing of <quote>separator</quote> lines full of 24.655 + <quote><literal>-</literal></quote> characters by ending the template with such a line. 24.656 + We use the templating engine's <literal role="template-keyword">header</literal> keyword to print a 24.657 + separator line as the first line of output (see below), thus 24.658 + achieving similar output to Subversion. 24.659 +</para> 24.660 +</listitem> 24.661 +<listitem><para>Subversion's output includes a count in the header of the number 24.662 + of lines in the commit message. We cannot replicate this in 24.663 + Mercurial; the templating engine does not currently provide a filter 24.664 + that counts the number of lines the template generates. 24.665 +</para> 24.666 +</listitem></itemizedlist> 24.667 +<para>It took me no more than a minute or two of work to replace literal 24.668 +text from an example of Subversion's output with some keywords and 24.669 +filters to give the template above. The style file simply refers to 24.670 +the template. 24.671 +<!-- &interaction.template.svnstyle.style; --> 24.672 +</para> 24.673 + 24.674 +<para>We could have included the text of the template file directly in the 24.675 +style file by enclosing it in quotes and replacing the newlines with 24.676 +<quote><literal>\n</literal></quote> sequences, but it would have made the style file too 24.677 +difficult to read. Readability is a good guide when you're trying to 24.678 +decide whether some text belongs in a style file, or in a template 24.679 +file that the style file points to. If the style file will look too 24.680 +big or cluttered if you insert a literal piece of text, drop it into a 24.681 +template instead. 24.682 +</para> 24.683 + 24.684 +</sect2> 24.685 +</sect1> 24.686 +</chapter> 24.687 + 24.688 +<!-- 24.689 +local variables: 24.690 +sgml-parent-document: ("00book.xml" "book" "chapter") 24.691 +end: 24.692 +--> 24.693 \ No newline at end of file
25.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 25.2 +++ b/fr/ch12-mq.xml Sun Aug 16 04:58:01 2009 +0200 25.3 @@ -0,0 +1,1309 @@ 25.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 25.5 + 25.6 +<chapter> 25.7 +<title>Managing change with Mercurial Queues</title> 25.8 +<para>\label{chap:mq}</para> 25.9 + 25.10 +<sect1> 25.11 +<title>The patch management problem</title> 25.12 +<para>\label{sec:mq:patch-mgmt}</para> 25.13 + 25.14 +<para>Here is a common scenario: you need to install a software package from 25.15 +source, but you find a bug that you must fix in the source before you 25.16 +can start using the package. You make your changes, forget about the 25.17 +package for a while, and a few months later you need to upgrade to a 25.18 +newer version of the package. If the newer version of the package 25.19 +still has the bug, you must extract your fix from the older source 25.20 +tree and apply it against the newer version. This is a tedious task, 25.21 +and it's easy to make mistakes.</para> 25.22 + 25.23 +<para>This is a simple case of the <quote>patch management</quote> problem. You have 25.24 +an <quote>upstream</quote> source tree that you can't change; you need to make 25.25 +some local changes on top of the upstream tree; and you'd like to be 25.26 +able to keep those changes separate, so that you can apply them to 25.27 +newer versions of the upstream source.</para> 25.28 + 25.29 +<para>The patch management problem arises in many situations. Probably the 25.30 +most visible is that a user of an open source software project will 25.31 +contribute a bug fix or new feature to the project's maintainers in the 25.32 +form of a patch.</para> 25.33 + 25.34 +<para>Distributors of operating systems that include open source software 25.35 +often need to make changes to the packages they distribute so that 25.36 +they will build properly in their environments.</para> 25.37 + 25.38 +<para>When you have few changes to maintain, it is easy to manage a single 25.39 +patch using the standard <command>diff</command> and <command>patch</command> programs 25.40 +(see section <xref linkend="sec:mq:patch"/> for a discussion of these tools). 25.41 +Once the number of changes grows, it starts to make sense to maintain 25.42 +patches as discrete <quote>chunks of work,</quote> so that for example a single 25.43 +patch will contain only one bug fix (the patch might modify several 25.44 +files, but it's doing <quote>only one thing</quote>), and you may have a number 25.45 +of such patches for different bugs you need fixed and local changes 25.46 +you require. In this situation, if you submit a bug fix patch to the 25.47 +upstream maintainers of a package and they include your fix in a 25.48 +subsequent release, you can simply drop that single patch when you're 25.49 +updating to the newer release.</para> 25.50 + 25.51 +<para>Maintaining a single patch against an upstream tree is a little 25.52 +tedious and error-prone, but not difficult. However, the complexity 25.53 +of the problem grows rapidly as the number of patches you have to 25.54 +maintain increases. With more than a tiny number of patches in hand, 25.55 +understanding which ones you have applied and maintaining them moves 25.56 +from messy to overwhelming.</para> 25.57 + 25.58 +<para>Fortunately, Mercurial includes a powerful extension, Mercurial Queues 25.59 +(or simply <quote>MQ</quote>), that massively simplifies the patch management 25.60 +problem. 25.61 +</para> 25.62 + 25.63 +</sect1> 25.64 +<sect1> 25.65 +<title>The prehistory of Mercurial Queues</title> 25.66 +<para>\label{sec:mq:history} 25.67 +</para> 25.68 + 25.69 +<para>During the late 1990s, several Linux kernel developers started to 25.70 +maintain <quote>patch series</quote> that modified the behaviour of the Linux 25.71 +kernel. Some of these series were focused on stability, some on 25.72 +feature coverage, and others were more speculative. 25.73 +</para> 25.74 + 25.75 +<para>The sizes of these patch series grew rapidly. In 2002, Andrew Morton 25.76 +published some shell scripts he had been using to automate the task of 25.77 +managing his patch queues. Andrew was successfully using these 25.78 +scripts to manage hundreds (sometimes thousands) of patches on top of 25.79 +the Linux kernel. 25.80 +</para> 25.81 + 25.82 +<sect2> 25.83 +<title>A patchwork quilt</title> 25.84 +<para>\label{sec:mq:quilt} 25.85 +</para> 25.86 + 25.87 +<para>In early 2003, Andreas Gruenbacher and Martin Quinson borrowed the 25.88 +approach of Andrew's scripts and published a tool called <quote>patchwork 25.89 +quilt</quote> <citation>web:quilt</citation>, or simply <quote>quilt</quote> 25.90 +(see <citation>gruenbacher:2005</citation> for a paper describing it). Because 25.91 +quilt substantially automated patch management, it rapidly gained a 25.92 +large following among open source software developers. 25.93 +</para> 25.94 + 25.95 +<para>Quilt manages a <emphasis>stack of patches</emphasis> on top of a directory tree. 25.96 +To begin, you tell quilt to manage a directory tree, and tell it which 25.97 +files you want to manage; it stores away the names and contents of 25.98 +those files. To fix a bug, you create a new patch (using a single 25.99 +command), edit the files you need to fix, then <quote>refresh</quote> the patch. 25.100 +</para> 25.101 + 25.102 +<para>The refresh step causes quilt to scan the directory tree; it updates 25.103 +the patch with all of the changes you have made. You can create 25.104 +another patch on top of the first, which will track the changes 25.105 +required to modify the tree from <quote>tree with one patch applied</quote> to 25.106 +<quote>tree with two patches applied</quote>. 25.107 +</para> 25.108 + 25.109 +<para>You can <emphasis>change</emphasis> which patches are applied to the tree. If you 25.110 +<quote>pop</quote> a patch, the changes made by that patch will vanish from the 25.111 +directory tree. Quilt remembers which patches you have popped, 25.112 +though, so you can <quote>push</quote> a popped patch again, and the directory 25.113 +tree will be restored to contain the modifications in the patch. Most 25.114 +importantly, you can run the <quote>refresh</quote> command at any time, and the 25.115 +topmost applied patch will be updated. This means that you can, at 25.116 +any time, change both which patches are applied and what 25.117 +modifications those patches make. 25.118 +</para> 25.119 + 25.120 +<para>Quilt knows nothing about revision control tools, so it works equally 25.121 +well on top of an unpacked tarball or a Subversion working copy. 25.122 +</para> 25.123 + 25.124 +</sect2> 25.125 +<sect2> 25.126 +<title>From patchwork quilt to Mercurial Queues</title> 25.127 +<para>\label{sec:mq:quilt-mq} 25.128 +</para> 25.129 + 25.130 +<para>In mid-2005, Chris Mason took the features of quilt and wrote an 25.131 +extension that he called Mercurial Queues, which added quilt-like 25.132 +behaviour to Mercurial. 25.133 +</para> 25.134 + 25.135 +<para>The key difference between quilt and MQ is that quilt knows nothing 25.136 +about revision control systems, while MQ is <emphasis>integrated</emphasis> into 25.137 +Mercurial. Each patch that you push is represented as a Mercurial 25.138 +changeset. Pop a patch, and the changeset goes away. 25.139 +</para> 25.140 + 25.141 +<para>Because quilt does not care about revision control tools, it is still 25.142 +a tremendously useful piece of software to know about for situations 25.143 +where you cannot use Mercurial and MQ. 25.144 +</para> 25.145 + 25.146 +</sect2> 25.147 +</sect1> 25.148 +<sect1> 25.149 +<title>The huge advantage of MQ</title> 25.150 + 25.151 +<para>I cannot overstate the value that MQ offers through the unification of 25.152 +patches and revision control. 25.153 +</para> 25.154 + 25.155 +<para>A major reason that patches have persisted in the free software and 25.156 +open source world&emdash;in spite of the availability of increasingly 25.157 +capable revision control tools over the years&emdash;is the <emphasis>agility</emphasis> 25.158 +they offer. 25.159 +</para> 25.160 + 25.161 +<para>Traditional revision control tools make a permanent, irreversible 25.162 +record of everything that you do. While this has great value, it's 25.163 +also somewhat stifling. If you want to perform a wild-eyed 25.164 +experiment, you have to be careful in how you go about it, or you risk 25.165 +leaving unneeded&emdash;or worse, misleading or destabilising&emdash;traces of 25.166 +your missteps and errors in the permanent revision record. 25.167 +</para> 25.168 + 25.169 +<para>By contrast, MQ's marriage of distributed revision control with 25.170 +patches makes it much easier to isolate your work. Your patches live 25.171 +on top of normal revision history, and you can make them disappear or 25.172 +reappear at will. If you don't like a patch, you can drop it. If a 25.173 +patch isn't quite as you want it to be, simply fix it&emdash;as many times 25.174 +as you need to, until you have refined it into the form you desire. 25.175 +</para> 25.176 + 25.177 +<para>As an example, the integration of patches with revision control makes 25.178 +understanding patches and debugging their effects&emdash;and their 25.179 +interplay with the code they're based on&emdash;<emphasis>enormously</emphasis> easier. 25.180 +Since every applied patch has an associated changeset, you can use 25.181 +<command role="hg-cmd">hg log <emphasis>filename</emphasis></command> to see which changesets and patches 25.182 +affected a file. You can use the <literal role="hg-ext">bisect</literal> command to 25.183 +binary-search through all changesets and applied patches to see where 25.184 +a bug got introduced or fixed. You can use the <command role="hg-cmd">hg annotate</command> 25.185 +command to see which changeset or patch modified a particular line of 25.186 +a source file. And so on. 25.187 +</para> 25.188 + 25.189 +</sect1> 25.190 +<sect1> 25.191 +<title>Understanding patches</title> 25.192 +<para>\label{sec:mq:patch} 25.193 +</para> 25.194 + 25.195 +<para>Because MQ doesn't hide its patch-oriented nature, it is helpful to 25.196 +understand what patches are, and a little about the tools that work 25.197 +with them. 25.198 +</para> 25.199 + 25.200 +<para>The traditional Unix <command>diff</command> command compares two files, and 25.201 +prints a list of differences between them. The <command>patch</command> command 25.202 +understands these differences as <emphasis>modifications</emphasis> to make to a 25.203 +file. Take a look at figure <xref linkend="ex:mq:diff"/> for a simple example of 25.204 +these commands in action. 25.205 +</para> 25.206 + 25.207 +<informalfigure> 25.208 +<para> <!-- &interaction.mq.dodiff.diff; --> 25.209 + <caption><para>Simple uses of the <command>diff</para></caption> and \command{patch</command> commands} 25.210 + \label{ex:mq:diff} 25.211 +</para> 25.212 +</informalfigure> 25.213 + 25.214 +<para>The type of file that <command>diff</command> generates (and <command>patch</command> 25.215 +takes as input) is called a <quote>patch</quote> or a <quote>diff</quote>; there is no 25.216 +difference between a patch and a diff. (We'll use the term <quote>patch</quote>, 25.217 +since it's more commonly used.) 25.218 +</para> 25.219 + 25.220 +<para>A patch file can start with arbitrary text; the <command>patch</command> 25.221 +command ignores this text, but MQ uses it as the commit message when 25.222 +creating changesets. To find the beginning of the patch content, 25.223 +<command>patch</command> searches for the first line that starts with the 25.224 +string <quote><literal>diff -</literal></quote>. 25.225 +</para> 25.226 + 25.227 +<para>MQ works with <emphasis>unified</emphasis> diffs (<command>patch</command> can accept several 25.228 +other diff formats, but MQ doesn't). A unified diff contains two 25.229 +kinds of header. The <emphasis>file header</emphasis> describes the file being 25.230 +modified; it contains the name of the file to modify. When 25.231 +<command>patch</command> sees a new file header, it looks for a file with that 25.232 +name to start modifying. 25.233 +</para> 25.234 + 25.235 +<para>After the file header comes a series of <emphasis>hunks</emphasis>. Each hunk 25.236 +starts with a header; this identifies the range of line numbers within 25.237 +the file that the hunk should modify. Following the header, a hunk 25.238 +starts and ends with a few (usually three) lines of text from the 25.239 +unmodified file; these are called the <emphasis>context</emphasis> for the hunk. If 25.240 +there's only a small amount of context between successive hunks, 25.241 +<command>diff</command> doesn't print a new hunk header; it just runs the hunks 25.242 +together, with a few lines of context between modifications. 25.243 +</para> 25.244 + 25.245 +<para>Each line of context begins with a space character. Within the hunk, 25.246 +a line that begins with <quote><literal>-</literal></quote> means <quote>remove this line,</quote> 25.247 +while a line that begins with <quote><literal>+</literal></quote> means <quote>insert this 25.248 +line.</quote> For example, a line that is modified is represented by one 25.249 +deletion and one insertion. 25.250 +</para> 25.251 + 25.252 +<para>We will return to some of the more subtle aspects of patches later (in 25.253 +section <xref linkend="sec:mq:adv-patch"/>), but you should have enough information 25.254 +now to use MQ. 25.255 +</para> 25.256 + 25.257 +</sect1> 25.258 +<sect1> 25.259 +<title>Getting started with Mercurial Queues</title> 25.260 +<para>\label{sec:mq:start} 25.261 +</para> 25.262 + 25.263 +<para>Because MQ is implemented as an extension, you must explicitly enable 25.264 +before you can use it. (You don't need to download anything; MQ ships 25.265 +with the standard Mercurial distribution.) To enable MQ, edit your 25.266 +<filename role="home">~/.hgrc</filename> file, and add the lines in figure <xref linkend="ex:mq:config"/>. 25.267 +</para> 25.268 + 25.269 +<informalfigure> 25.270 +<programlisting> 25.271 +<para> [extensions] 25.272 + hgext.mq = 25.273 +</para> 25.274 +</programlisting> 25.275 +<para> \label{ex:mq:config} 25.276 + <caption><para>Contents to add to <filename role="home">~/.hgrc</para></caption> to enable the MQ extension</filename> 25.277 +</para> 25.278 +</informalfigure> 25.279 + 25.280 +<para>Once the extension is enabled, it will make a number of new commands 25.281 +available. To verify that the extension is working, you can use 25.282 +<command role="hg-cmd">hg help</command> to see if the <command role="hg-ext-mq">qinit</command> command is now available; see 25.283 +the example in figure <xref linkend="ex:mq:enabled"/>. 25.284 +</para> 25.285 + 25.286 +<informalfigure> 25.287 +<para> <!-- &interaction.mq.qinit-help.help; --> 25.288 + <caption><para>How to verify that MQ is enabled</para></caption> 25.289 + \label{ex:mq:enabled} 25.290 +</para> 25.291 +</informalfigure> 25.292 + 25.293 +<para>You can use MQ with <emphasis>any</emphasis> Mercurial repository, and its commands 25.294 +only operate within that repository. To get started, simply prepare 25.295 +the repository using the <command role="hg-ext-mq">qinit</command> command (see 25.296 +figure <xref linkend="ex:mq:qinit"/>). This command creates an empty directory 25.297 +called <filename role="special" class="directory">.hg/patches</filename>, where MQ will keep its metadata. As 25.298 +with many Mercurial commands, the <command role="hg-ext-mq">qinit</command> command prints nothing 25.299 +if it succeeds. 25.300 +</para> 25.301 + 25.302 +<informalfigure> 25.303 +<para> <!-- &interaction.mq.tutorial.qinit; --> 25.304 + <caption><para>Preparing a repository for use with MQ</para></caption> 25.305 + \label{ex:mq:qinit} 25.306 +</para> 25.307 +</informalfigure> 25.308 + 25.309 +<informalfigure> 25.310 +<para> <!-- &interaction.mq.tutorial.qnew; --> 25.311 + <caption><para>Creating a new patch</para></caption> 25.312 + \label{ex:mq:qnew} 25.313 +</para> 25.314 +</informalfigure> 25.315 + 25.316 +<sect2> 25.317 +<title>Creating a new patch</title> 25.318 + 25.319 +<para>To begin work on a new patch, use the <command role="hg-ext-mq">qnew</command> command. This 25.320 +command takes one argument, the name of the patch to create. MQ will 25.321 +use this as the name of an actual file in the <filename role="special" class="directory">.hg/patches</filename> 25.322 +directory, as you can see in figure <xref linkend="ex:mq:qnew"/>. 25.323 +</para> 25.324 + 25.325 +<para>Also newly present in the <filename role="special" class="directory">.hg/patches</filename> directory are two 25.326 +other files, <filename role="special">series</filename> and <filename role="special">status</filename>. The 25.327 +<filename role="special">series</filename> file lists all of the patches that MQ knows about 25.328 +for this repository, with one patch per line. Mercurial uses the 25.329 +<filename role="special">status</filename> file for internal book-keeping; it tracks all of the 25.330 +patches that MQ has <emphasis>applied</emphasis> in this repository. 25.331 +</para> 25.332 + 25.333 +<note> 25.334 +<para> You may sometimes want to edit the <filename role="special">series</filename> file by hand; 25.335 + for example, to change the sequence in which some patches are 25.336 + applied. However, manually editing the <filename role="special">status</filename> file is 25.337 + almost always a bad idea, as it's easy to corrupt MQ's idea of what 25.338 + is happening. 25.339 +</para> 25.340 +</note> 25.341 + 25.342 +<para>Once you have created your new patch, you can edit files in the 25.343 +working directory as you usually would. All of the normal Mercurial 25.344 +commands, such as <command role="hg-cmd">hg diff</command> and <command role="hg-cmd">hg annotate</command>, work exactly as 25.345 +they did before. 25.346 +</para> 25.347 + 25.348 +</sect2> 25.349 +<sect2> 25.350 +<title>Refreshing a patch</title> 25.351 + 25.352 +<para>When you reach a point where you want to save your work, use the 25.353 +<command role="hg-ext-mq">qrefresh</command> command (figure <xref linkend="ex:mq:qnew"/>) to update the patch 25.354 +you are working on. This command folds the changes you have made in 25.355 +the working directory into your patch, and updates its corresponding 25.356 +changeset to contain those changes. 25.357 +</para> 25.358 + 25.359 +<informalfigure> 25.360 +<para> <!-- &interaction.mq.tutorial.qrefresh; --> 25.361 + <caption><para>Refreshing a patch</para></caption> 25.362 + \label{ex:mq:qrefresh} 25.363 +</para> 25.364 +</informalfigure> 25.365 + 25.366 +<para>You can run <command role="hg-ext-mq">qrefresh</command> as often as you like, so it's a good way 25.367 +to <quote>checkpoint</quote> your work. Refresh your patch at an opportune 25.368 +time; try an experiment; and if the experiment doesn't work out, 25.369 +<command role="hg-cmd">hg revert</command> your modifications back to the last time you refreshed. 25.370 +</para> 25.371 + 25.372 +<informalfigure> 25.373 +<para> <!-- &interaction.mq.tutorial.qrefresh2; --> 25.374 + <caption><para>Refresh a patch many times to accumulate changes</para></caption> 25.375 + \label{ex:mq:qrefresh2} 25.376 +</para> 25.377 +</informalfigure> 25.378 + 25.379 +</sect2> 25.380 +<sect2> 25.381 +<title>Stacking and tracking patches</title> 25.382 + 25.383 +<para>Once you have finished working on a patch, or need to work on another, 25.384 +you can use the <command role="hg-ext-mq">qnew</command> command again to create a new patch. 25.385 +Mercurial will apply this patch on top of your existing patch. See 25.386 +figure <xref linkend="ex:mq:qnew2"/> for an example. Notice that the patch 25.387 +contains the changes in our prior patch as part of its context (you 25.388 +can see this more clearly in the output of <command role="hg-cmd">hg annotate</command>). 25.389 +</para> 25.390 + 25.391 +<informalfigure> 25.392 +<para> <!-- &interaction.mq.tutorial.qnew2; --> 25.393 + <caption><para>Stacking a second patch on top of the first</para></caption> 25.394 + \label{ex:mq:qnew2} 25.395 +</para> 25.396 +</informalfigure> 25.397 + 25.398 +<para>So far, with the exception of <command role="hg-ext-mq">qnew</command> and <command role="hg-ext-mq">qrefresh</command>, we've 25.399 +been careful to only use regular Mercurial commands. However, MQ 25.400 +provides many commands that are easier to use when you are thinking 25.401 +about patches, as illustrated in figure <xref linkend="ex:mq:qseries"/>: 25.402 +</para> 25.403 + 25.404 +<itemizedlist> 25.405 +<listitem><para>The <command role="hg-ext-mq">qseries</command> command lists every patch that MQ knows 25.406 + about in this repository, from oldest to newest (most recently 25.407 + <emphasis>created</emphasis>). 25.408 +</para> 25.409 +</listitem> 25.410 +<listitem><para>The <command role="hg-ext-mq">qapplied</command> command lists every patch that MQ has 25.411 + <emphasis>applied</emphasis> in this repository, again from oldest to newest (most 25.412 + recently applied). 25.413 +</para> 25.414 +</listitem></itemizedlist> 25.415 + 25.416 +<informalfigure> 25.417 +<para> <!-- &interaction.mq.tutorial.qseries; --> 25.418 + \caption{Understanding the patch stack with <command role="hg-ext-mq">qseries</command> and 25.419 + <command role="hg-ext-mq">qapplied</command>} 25.420 + \label{ex:mq:qseries} 25.421 +</para> 25.422 +</informalfigure> 25.423 + 25.424 +</sect2> 25.425 +<sect2> 25.426 +<title>Manipulating the patch stack</title> 25.427 + 25.428 +<para>The previous discussion implied that there must be a difference 25.429 +between <quote>known</quote> and <quote>applied</quote> patches, and there is. MQ can 25.430 +manage a patch without it being applied in the repository. 25.431 +</para> 25.432 + 25.433 +<para>An <emphasis>applied</emphasis> patch has a corresponding changeset in the 25.434 +repository, and the effects of the patch and changeset are visible in 25.435 +the working directory. You can undo the application of a patch using 25.436 +the <command role="hg-ext-mq">qpop</command> command. MQ still <emphasis>knows about</emphasis>, or manages, a 25.437 +popped patch, but the patch no longer has a corresponding changeset in 25.438 +the repository, and the working directory does not contain the changes 25.439 +made by the patch. Figure <xref linkend="fig:mq:stack"/> illustrates the 25.440 +difference between applied and tracked patches. 25.441 +</para> 25.442 + 25.443 +<informalfigure> 25.444 + 25.445 +<para> <mediaobject><imageobject><imagedata fileref="mq-stack"/></imageobject><textobject><phrase>XXX add text</phrase></textobject></mediaobject> 25.446 + <caption><para>Applied and unapplied patches in the MQ patch stack</para></caption> 25.447 + \label{fig:mq:stack} 25.448 +</para> 25.449 +</informalfigure> 25.450 + 25.451 +<para>You can reapply an unapplied, or popped, patch using the <command role="hg-ext-mq">qpush</command> 25.452 +command. This creates a new changeset to correspond to the patch, and 25.453 +the patch's changes once again become present in the working 25.454 +directory. See figure <xref linkend="ex:mq:qpop"/> for examples of <command role="hg-ext-mq">qpop</command> 25.455 +and <command role="hg-ext-mq">qpush</command> in action. Notice that once we have popped a patch 25.456 +or two patches, the output of <command role="hg-ext-mq">qseries</command> remains the same, while 25.457 +that of <command role="hg-ext-mq">qapplied</command> has changed. 25.458 +</para> 25.459 + 25.460 +<informalfigure> 25.461 +<para> <!-- &interaction.mq.tutorial.qpop; --> 25.462 + <caption><para>Modifying the stack of applied patches</para></caption> 25.463 + \label{ex:mq:qpop} 25.464 +</para> 25.465 +</informalfigure> 25.466 + 25.467 +</sect2> 25.468 +<sect2> 25.469 +<title>Pushing and popping many patches</title> 25.470 + 25.471 +<para>While <command role="hg-ext-mq">qpush</command> and <command role="hg-ext-mq">qpop</command> each operate on a single patch at 25.472 +a time by default, you can push and pop many patches in one go. The 25.473 +<option role="hg-ext-mq-cmd-qpush-opt">-a</option> option to <command role="hg-ext-mq">qpush</command> causes it to push all 25.474 +unapplied patches, while the <option role="hg-ext-mq-cmd-qpop-opt">-a</option> option to <command role="hg-ext-mq">qpop</command> 25.475 +causes it to pop all applied patches. (For some more ways to push and 25.476 +pop many patches, see section <xref linkend="sec:mq:perf"/> below.) 25.477 +</para> 25.478 + 25.479 +<informalfigure> 25.480 +<para> <!-- &interaction.mq.tutorial.qpush-a; --> 25.481 + <caption><para>Pushing all unapplied patches</para></caption> 25.482 + \label{ex:mq:qpush-a} 25.483 +</para> 25.484 +</informalfigure> 25.485 + 25.486 +</sect2> 25.487 +<sect2> 25.488 +<title>Safety checks, and overriding them</title> 25.489 + 25.490 +<para>Several MQ commands check the working directory before they do 25.491 +anything, and fail if they find any modifications. They do this to 25.492 +ensure that you won't lose any changes that you have made, but not yet 25.493 +incorporated into a patch. Figure <xref linkend="ex:mq:add"/> illustrates this; 25.494 +the <command role="hg-ext-mq">qnew</command> command will not create a new patch if there are 25.495 +outstanding changes, caused in this case by the <command role="hg-cmd">hg add</command> of 25.496 +<filename>file3</filename>. 25.497 +</para> 25.498 + 25.499 +<informalfigure> 25.500 +<para> <!-- &interaction.mq.tutorial.add; --> 25.501 + <caption><para>Forcibly creating a patch</para></caption> 25.502 + \label{ex:mq:add} 25.503 +</para> 25.504 +</informalfigure> 25.505 + 25.506 +<para>Commands that check the working directory all take an <quote>I know what 25.507 +I'm doing</quote> option, which is always named <option>-f</option>. The exact 25.508 +meaning of <option>-f</option> depends on the command. For example, 25.509 +<command role="hg-cmd">hg qnew <option role="hg-ext-mq-cmd-qnew-opt">-f</option></command> will incorporate any outstanding 25.510 +changes into the new patch it creates, but 25.511 +<command role="hg-cmd">hg qpop <option role="hg-ext-mq-cmd-qpop-opt">-f</option></command> will revert modifications to any 25.512 +files affected by the patch that it is popping. Be sure to read the 25.513 +documentation for a command's <option>-f</option> option before you use it! 25.514 +</para> 25.515 + 25.516 +</sect2> 25.517 +<sect2> 25.518 +<title>Working on several patches at once</title> 25.519 + 25.520 +<para>The <command role="hg-ext-mq">qrefresh</command> command always refreshes the <emphasis>topmost</emphasis> 25.521 +applied patch. This means that you can suspend work on one patch (by 25.522 +refreshing it), pop or push to make a different patch the top, and 25.523 +work on <emphasis>that</emphasis> patch for a while. 25.524 +</para> 25.525 + 25.526 +<para>Here's an example that illustrates how you can use this ability. 25.527 +Let's say you're developing a new feature as two patches. The first 25.528 +is a change to the core of your software, and the second&emdash;layered on 25.529 +top of the first&emdash;changes the user interface to use the code you just 25.530 +added to the core. If you notice a bug in the core while you're 25.531 +working on the UI patch, it's easy to fix the core. Simply 25.532 +<command role="hg-ext-mq">qrefresh</command> the UI patch to save your in-progress changes, and 25.533 +<command role="hg-ext-mq">qpop</command> down to the core patch. Fix the core bug, 25.534 +<command role="hg-ext-mq">qrefresh</command> the core patch, and <command role="hg-ext-mq">qpush</command> back to the UI 25.535 +patch to continue where you left off. 25.536 +</para> 25.537 + 25.538 +</sect2> 25.539 +</sect1> 25.540 +<sect1> 25.541 +<title>More about patches</title> 25.542 +<para>\label{sec:mq:adv-patch} 25.543 +</para> 25.544 + 25.545 +<para>MQ uses the GNU <command>patch</command> command to apply patches, so it's 25.546 +helpful to know a few more detailed aspects of how <command>patch</command> 25.547 +works, and about patches themselves. 25.548 +</para> 25.549 + 25.550 +<sect2> 25.551 +<title>The strip count</title> 25.552 + 25.553 +<para>If you look at the file headers in a patch, you will notice that the 25.554 +pathnames usually have an extra component on the front that isn't 25.555 +present in the actual path name. This is a holdover from the way that 25.556 +people used to generate patches (people still do this, but it's 25.557 +somewhat rare with modern revision control tools). 25.558 +</para> 25.559 + 25.560 +<para>Alice would unpack a tarball, edit her files, then decide that she 25.561 +wanted to create a patch. So she'd rename her working directory, 25.562 +unpack the tarball again (hence the need for the rename), and use the 25.563 +<option role="cmd-opt-diff">-r</option> and <option role="cmd-opt-diff">-N</option> options to <command>diff</command> to 25.564 +recursively generate a patch between the unmodified directory and the 25.565 +modified one. The result would be that the name of the unmodified 25.566 +directory would be at the front of the left-hand path in every file 25.567 +header, and the name of the modified directory would be at the front 25.568 +of the right-hand path. 25.569 +</para> 25.570 + 25.571 +<para>Since someone receiving a patch from the Alices of the net would be 25.572 +unlikely to have unmodified and modified directories with exactly the 25.573 +same names, the <command>patch</command> command has a <option role="cmd-opt-patch">-p</option> 25.574 +option that indicates the number of leading path name components to 25.575 +strip when trying to apply a patch. This number is called the 25.576 +<emphasis>strip count</emphasis>. 25.577 +</para> 25.578 + 25.579 +<para>An option of <quote><literal>-p1</literal></quote> means <quote>use a strip count of one</quote>. If 25.580 +<command>patch</command> sees a file name <filename>foo/bar/baz</filename> in a file 25.581 +header, it will strip <filename>foo</filename> and try to patch a file named 25.582 +<filename>bar/baz</filename>. (Strictly speaking, the strip count refers to the 25.583 +number of <emphasis>path separators</emphasis> (and the components that go with them 25.584 +) to strip. A strip count of one will turn <filename>foo/bar</filename> into 25.585 +<filename>bar</filename>, but <filename>/foo/bar</filename> (notice the extra leading 25.586 +slash) into <filename>foo/bar</filename>.) 25.587 +</para> 25.588 + 25.589 +<para>The <quote>standard</quote> strip count for patches is one; almost all patches 25.590 +contain one leading path name component that needs to be stripped. 25.591 +Mercurial's <command role="hg-cmd">hg diff</command> command generates path names in this form, 25.592 +and the <command role="hg-cmd">hg import</command> command and MQ expect patches to have a strip 25.593 +count of one. 25.594 +</para> 25.595 + 25.596 +<para>If you receive a patch from someone that you want to add to your patch 25.597 +queue, and the patch needs a strip count other than one, you cannot 25.598 +just <command role="hg-ext-mq">qimport</command> the patch, because <command role="hg-ext-mq">qimport</command> does not yet 25.599 +have a <literal>-p</literal> option (see <ulink role="hg-bug" url="http://www.selenic.com/mercurial/bts/issue311">issue 311</ulink>). Your best bet is to 25.600 +<command role="hg-ext-mq">qnew</command> a patch of your own, then use <command>patch -p<emphasis>N</emphasis></command> 25.601 +to apply their patch, followed by <command role="hg-cmd">hg addremove</command> to pick up any 25.602 +files added or removed by the patch, followed by <command role="hg-ext-mq">qrefresh</command>. 25.603 +This complexity may become unnecessary; see <ulink role="hg-bug" url="http://www.selenic.com/mercurial/bts/issue311">issue 311</ulink> for details. 25.604 +</sect2> 25.605 +<sect2> 25.606 +<title>Strategies for applying a patch</title> 25.607 +</para> 25.608 + 25.609 +<para>When <command>patch</command> applies a hunk, it tries a handful of 25.610 +successively less accurate strategies to try to make the hunk apply. 25.611 +This falling-back technique often makes it possible to take a patch 25.612 +that was generated against an old version of a file, and apply it 25.613 +against a newer version of that file. 25.614 +</para> 25.615 + 25.616 +<para>First, <command>patch</command> tries an exact match, where the line numbers, 25.617 +the context, and the text to be modified must apply exactly. If it 25.618 +cannot make an exact match, it tries to find an exact match for the 25.619 +context, without honouring the line numbering information. If this 25.620 +succeeds, it prints a line of output saying that the hunk was applied, 25.621 +but at some <emphasis>offset</emphasis> from the original line number. 25.622 +</para> 25.623 + 25.624 +<para>If a context-only match fails, <command>patch</command> removes the first and 25.625 +last lines of the context, and tries a <emphasis>reduced</emphasis> context-only 25.626 +match. If the hunk with reduced context succeeds, it prints a message 25.627 +saying that it applied the hunk with a <emphasis>fuzz factor</emphasis> (the number 25.628 +after the fuzz factor indicates how many lines of context 25.629 +<command>patch</command> had to trim before the patch applied). 25.630 +</para> 25.631 + 25.632 +<para>When neither of these techniques works, <command>patch</command> prints a 25.633 +message saying that the hunk in question was rejected. It saves 25.634 +rejected hunks (also simply called <quote>rejects</quote>) to a file with the 25.635 +same name, and an added <filename role="special">.rej</filename> extension. It also saves an 25.636 +unmodified copy of the file with a <filename role="special">.orig</filename> extension; the 25.637 +copy of the file without any extensions will contain any changes made 25.638 +by hunks that <emphasis>did</emphasis> apply cleanly. If you have a patch that 25.639 +modifies <filename>foo</filename> with six hunks, and one of them fails to 25.640 +apply, you will have: an unmodified <filename>foo.orig</filename>, a 25.641 +<filename>foo.rej</filename> containing one hunk, and <filename>foo</filename>, containing 25.642 +the changes made by the five successful hunks. 25.643 +</para> 25.644 + 25.645 +</sect2> 25.646 +<sect2> 25.647 +<title>Some quirks of patch representation</title> 25.648 + 25.649 +<para>There are a few useful things to know about how <command>patch</command> works 25.650 +with files. 25.651 +</para> 25.652 +<itemizedlist> 25.653 +<listitem><para>This should already be obvious, but <command>patch</command> cannot 25.654 + handle binary files. 25.655 +</para> 25.656 +</listitem> 25.657 +<listitem><para>Neither does it care about the executable bit; it creates new 25.658 + files as readable, but not executable. 25.659 +</para> 25.660 +</listitem> 25.661 +<listitem><para><command>patch</command> treats the removal of a file as a diff between 25.662 + the file to be removed and the empty file. So your idea of <quote>I 25.663 + deleted this file</quote> looks like <quote>every line of this file was 25.664 + deleted</quote> in a patch. 25.665 +</para> 25.666 +</listitem> 25.667 +<listitem><para>It treats the addition of a file as a diff between the empty 25.668 + file and the file to be added. So in a patch, your idea of <quote>I 25.669 + added this file</quote> looks like <quote>every line of this file was added</quote>. 25.670 +</para> 25.671 +</listitem> 25.672 +<listitem><para>It treats a renamed file as the removal of the old name, and the 25.673 + addition of the new name. This means that renamed files have a big 25.674 + footprint in patches. (Note also that Mercurial does not currently 25.675 + try to infer when files have been renamed or copied in a patch.) 25.676 +</para> 25.677 +</listitem> 25.678 +<listitem><para><command>patch</command> cannot represent empty files, so you cannot use 25.679 + a patch to represent the notion <quote>I added this empty file to the 25.680 + tree</quote>. 25.681 +</para> 25.682 +</listitem></itemizedlist> 25.683 +</sect2> 25.684 +<sect2> 25.685 +<title>Beware the fuzz</title> 25.686 + 25.687 +<para>While applying a hunk at an offset, or with a fuzz factor, will often 25.688 +be completely successful, these inexact techniques naturally leave 25.689 +open the possibility of corrupting the patched file. The most common 25.690 +cases typically involve applying a patch twice, or at an incorrect 25.691 +location in the file. If <command>patch</command> or <command role="hg-ext-mq">qpush</command> ever 25.692 +mentions an offset or fuzz factor, you should make sure that the 25.693 +modified files are correct afterwards. 25.694 +</para> 25.695 + 25.696 +<para>It's often a good idea to refresh a patch that has applied with an 25.697 +offset or fuzz factor; refreshing the patch generates new context 25.698 +information that will make it apply cleanly. I say <quote>often,</quote> not 25.699 +<quote>always,</quote> because sometimes refreshing a patch will make it fail to 25.700 +apply against a different revision of the underlying files. In some 25.701 +cases, such as when you're maintaining a patch that must sit on top of 25.702 +multiple versions of a source tree, it's acceptable to have a patch 25.703 +apply with some fuzz, provided you've verified the results of the 25.704 +patching process in such cases. 25.705 +</para> 25.706 + 25.707 +</sect2> 25.708 +<sect2> 25.709 +<title>Handling rejection</title> 25.710 + 25.711 +<para>If <command role="hg-ext-mq">qpush</command> fails to apply a patch, it will print an error 25.712 +message and exit. If it has left <filename role="special">.rej</filename> files behind, it is 25.713 +usually best to fix up the rejected hunks before you push more patches 25.714 +or do any further work. 25.715 +</para> 25.716 + 25.717 +<para>If your patch <emphasis>used to</emphasis> apply cleanly, and no longer does because 25.718 +you've changed the underlying code that your patches are based on, 25.719 +Mercurial Queues can help; see section <xref linkend="sec:mq:merge"/> for details. 25.720 +</para> 25.721 + 25.722 +<para>Unfortunately, there aren't any great techniques for dealing with 25.723 +rejected hunks. Most often, you'll need to view the <filename role="special">.rej</filename> 25.724 +file and edit the target file, applying the rejected hunks by hand. 25.725 +</para> 25.726 + 25.727 +<para>If you're feeling adventurous, Neil Brown, a Linux kernel hacker, 25.728 +wrote a tool called <command>wiggle</command> <citation>web:wiggle</citation>, which is more 25.729 +vigorous than <command>patch</command> in its attempts to make a patch apply. 25.730 +</para> 25.731 + 25.732 +<para>Another Linux kernel hacker, Chris Mason (the author of Mercurial 25.733 +Queues), wrote a similar tool called 25.734 +<command>mpatch</command> <citation>web:mpatch</citation>, which takes a simple approach to 25.735 +automating the application of hunks rejected by <command>patch</command>. The 25.736 +<command>mpatch</command> command can help with four common reasons that a hunk 25.737 +may be rejected: 25.738 +</para> 25.739 + 25.740 +<itemizedlist> 25.741 +<listitem><para>The context in the middle of a hunk has changed. 25.742 +</para> 25.743 +</listitem> 25.744 +<listitem><para>A hunk is missing some context at the beginning or end. 25.745 +</para> 25.746 +</listitem> 25.747 +<listitem><para>A large hunk might apply better&emdash;either entirely or in 25.748 + part&emdash;if it was broken up into smaller hunks. 25.749 +</para> 25.750 +</listitem> 25.751 +<listitem><para>A hunk removes lines with slightly different content than those 25.752 + currently present in the file. 25.753 +</para> 25.754 +</listitem></itemizedlist> 25.755 + 25.756 +<para>If you use <command>wiggle</command> or <command>mpatch</command>, you should be doubly 25.757 +careful to check your results when you're done. In fact, 25.758 +<command>mpatch</command> enforces this method of double-checking the tool's 25.759 +output, by automatically dropping you into a merge program when it has 25.760 +done its job, so that you can verify its work and finish off any 25.761 +remaining merges. 25.762 +</para> 25.763 + 25.764 +</sect2> 25.765 +</sect1> 25.766 +<sect1> 25.767 +<title>Getting the best performance out of MQ</title> 25.768 +<para>\label{sec:mq:perf} 25.769 +</para> 25.770 + 25.771 +<para>MQ is very efficient at handling a large number of patches. I ran 25.772 +some performance experiments in mid-2006 for a talk that I gave at the 25.773 +2006 EuroPython conference <citation>web:europython</citation>. I used as my data 25.774 +set the Linux 2.6.17-mm1 patch series, which consists of 1,738 25.775 +patches. I applied these on top of a Linux kernel repository 25.776 +containing all 27,472 revisions between Linux 2.6.12-rc2 and Linux 25.777 +2.6.17. 25.778 +</para> 25.779 + 25.780 +<para>On my old, slow laptop, I was able to 25.781 +<command role="hg-cmd">hg qpush <option role="hg-ext-mq-cmd-qpush-opt">-a</option></command> all 1,738 patches in 3.5 minutes, 25.782 +and <command role="hg-cmd">hg qpop <option role="hg-ext-mq-cmd-qpop-opt">-a</option></command> them all in 30 seconds. (On a 25.783 +newer laptop, the time to push all patches dropped to two minutes.) I 25.784 +could <command role="hg-ext-mq">qrefresh</command> one of the biggest patches (which made 22,779 25.785 +lines of changes to 287 files) in 6.6 seconds. 25.786 +</para> 25.787 + 25.788 +<para>Clearly, MQ is well suited to working in large trees, but there are a 25.789 +few tricks you can use to get the best performance of it. 25.790 +</para> 25.791 + 25.792 +<para>First of all, try to <quote>batch</quote> operations together. Every time you 25.793 +run <command role="hg-ext-mq">qpush</command> or <command role="hg-ext-mq">qpop</command>, these commands scan the working 25.794 +directory once to make sure you haven't made some changes and then 25.795 +forgotten to run <command role="hg-ext-mq">qrefresh</command>. On a small tree, the time that 25.796 +this scan takes is unnoticeable. However, on a medium-sized tree 25.797 +(containing tens of thousands of files), it can take a second or more. 25.798 +</para> 25.799 + 25.800 +<para>The <command role="hg-ext-mq">qpush</command> and <command role="hg-ext-mq">qpop</command> commands allow you to push and pop 25.801 +multiple patches at a time. You can identify the <quote>destination 25.802 +patch</quote> that you want to end up at. When you <command role="hg-ext-mq">qpush</command> with a 25.803 +destination specified, it will push patches until that patch is at the 25.804 +top of the applied stack. When you <command role="hg-ext-mq">qpop</command> to a destination, MQ 25.805 +will pop patches until the destination patch is at the top. 25.806 +</para> 25.807 + 25.808 +<para>You can identify a destination patch using either the name of the 25.809 +patch, or by number. If you use numeric addressing, patches are 25.810 +counted from zero; this means that the first patch is zero, the second 25.811 +is one, and so on. 25.812 +</para> 25.813 + 25.814 +</sect1> 25.815 +<sect1> 25.816 +<title>Updating your patches when the underlying code changes</title> 25.817 +<para>\label{sec:mq:merge} 25.818 +</para> 25.819 + 25.820 +<para>It's common to have a stack of patches on top of an underlying 25.821 +repository that you don't modify directly. If you're working on 25.822 +changes to third-party code, or on a feature that is taking longer to 25.823 +develop than the rate of change of the code beneath, you will often 25.824 +need to sync up with the underlying code, and fix up any hunks in your 25.825 +patches that no longer apply. This is called <emphasis>rebasing</emphasis> your 25.826 +patch series. 25.827 +</para> 25.828 + 25.829 +<para>The simplest way to do this is to <command role="hg-cmd">hg qpop <option role="hg-ext-mq-cmd-qpop-opt">-a</option></command> 25.830 +your patches, then <command role="hg-cmd">hg pull</command> changes into the underlying 25.831 +repository, and finally <command role="hg-cmd">hg qpush <option role="hg-ext-mq-cmd-qpop-opt">-a</option></command> your 25.832 +patches again. MQ will stop pushing any time it runs across a patch 25.833 +that fails to apply during conflicts, allowing you to fix your 25.834 +conflicts, <command role="hg-ext-mq">qrefresh</command> the affected patch, and continue pushing 25.835 +until you have fixed your entire stack. 25.836 +</para> 25.837 + 25.838 +<para>This approach is easy to use and works well if you don't expect 25.839 +changes to the underlying code to affect how well your patches apply. 25.840 +If your patch stack touches code that is modified frequently or 25.841 +invasively in the underlying repository, however, fixing up rejected 25.842 +hunks by hand quickly becomes tiresome. 25.843 +</para> 25.844 + 25.845 +<para>It's possible to partially automate the rebasing process. If your 25.846 +patches apply cleanly against some revision of the underlying repo, MQ 25.847 +can use this information to help you to resolve conflicts between your 25.848 +patches and a different revision. 25.849 +</para> 25.850 + 25.851 +<para>The process is a little involved. 25.852 +</para> 25.853 +<orderedlist> 25.854 +<listitem><para>To begin, <command role="hg-cmd">hg qpush -a</command> all of your patches on top of 25.855 + the revision where you know that they apply cleanly. 25.856 +</para> 25.857 +</listitem> 25.858 +<listitem><para>Save a backup copy of your patch directory using 25.859 + <command role="hg-cmd">hg qsave <option role="hg-ext-mq-cmd-qsave-opt">-e</option> <option role="hg-ext-mq-cmd-qsave-opt">-c</option></command>. This prints 25.860 + the name of the directory that it has saved the patches in. It will 25.861 + save the patches to a directory called 25.862 + <filename role="special" class="directory">.hg/patches.<emphasis>N</filename></emphasis>, where <literal><emphasis>N</emphasis></literal> is a small 25.863 + integer. It also commits a <quote>save changeset</quote> on top of your 25.864 + applied patches; this is for internal book-keeping, and records the 25.865 + states of the <filename role="special">series</filename> and <filename role="special">status</filename> files. 25.866 +</para> 25.867 +</listitem> 25.868 +<listitem><para>Use <command role="hg-cmd">hg pull</command> to bring new changes into the underlying 25.869 + repository. (Don't run <command role="hg-cmd">hg pull -u</command>; see below for why.) 25.870 +</para> 25.871 +</listitem> 25.872 +<listitem><para>Update to the new tip revision, using 25.873 + <command role="hg-cmd">hg update <option role="hg-opt-update">-C</option></command> to override the patches you 25.874 + have pushed. 25.875 +</para> 25.876 +</listitem> 25.877 +<listitem><para>Merge all patches using \hgcmdargs{qpush}{<option role="hg-ext-mq-cmd-qpush-opt">-m</option> 25.878 + <option role="hg-ext-mq-cmd-qpush-opt">-a</option>}. The <option role="hg-ext-mq-cmd-qpush-opt">-m</option> option to <command role="hg-ext-mq">qpush</command> 25.879 + tells MQ to perform a three-way merge if the patch fails to apply. 25.880 +</para> 25.881 +</listitem></orderedlist> 25.882 + 25.883 +<para>During the <command role="hg-cmd">hg qpush <option role="hg-ext-mq-cmd-qpush-opt">-m</option></command>, each patch in the 25.884 +<filename role="special">series</filename> file is applied normally. If a patch applies with 25.885 +fuzz or rejects, MQ looks at the queue you <command role="hg-ext-mq">qsave</command>d, and 25.886 +performs a three-way merge with the corresponding changeset. This 25.887 +merge uses Mercurial's normal merge machinery, so it may pop up a GUI 25.888 +merge tool to help you to resolve problems. 25.889 +</para> 25.890 + 25.891 +<para>When you finish resolving the effects of a patch, MQ refreshes your 25.892 +patch based on the result of the merge. 25.893 +</para> 25.894 + 25.895 +<para>At the end of this process, your repository will have one extra head 25.896 +from the old patch queue, and a copy of the old patch queue will be in 25.897 +<filename role="special" class="directory">.hg/patches.<emphasis>N</filename></emphasis>. You can remove the extra head using 25.898 +<command role="hg-cmd">hg qpop <option role="hg-ext-mq-cmd-qpop-opt">-a</option> <option role="hg-ext-mq-cmd-qpop-opt">-n</option> patches.<emphasis>N</emphasis></command> 25.899 +or <command role="hg-cmd">hg strip</command>. You can delete <filename role="special" class="directory">.hg/patches.<emphasis>N</filename></emphasis> once 25.900 +you are sure that you no longer need it as a backup. 25.901 +</para> 25.902 + 25.903 +</sect1> 25.904 +<sect1> 25.905 +<title>Identifying patches</title> 25.906 + 25.907 +<para>MQ commands that work with patches let you refer to a patch either by 25.908 +using its name or by a number. By name is obvious enough; pass the 25.909 +name <filename>foo.patch</filename> to <command role="hg-ext-mq">qpush</command>, for example, and it will 25.910 +push patches until <filename>foo.patch</filename> is applied. 25.911 +</para> 25.912 + 25.913 +<para>As a shortcut, you can refer to a patch using both a name and a 25.914 +numeric offset; <literal>foo.patch-2</literal> means <quote>two patches before 25.915 +<literal>foo.patch</literal></quote>, while <literal>bar.patch+4</literal> means <quote>four patches 25.916 +after <literal>bar.patch</literal></quote>. 25.917 +</para> 25.918 + 25.919 +<para>Referring to a patch by index isn't much different. The first patch 25.920 +printed in the output of <command role="hg-ext-mq">qseries</command> is patch zero (yes, it's one 25.921 +of those start-at-zero counting systems); the second is patch one; and 25.922 +so on. 25.923 +</para> 25.924 + 25.925 +<para>MQ also makes it easy to work with patches when you are using normal 25.926 +Mercurial commands. Every command that accepts a changeset ID will 25.927 +also accept the name of an applied patch. MQ augments the tags 25.928 +normally in the repository with an eponymous one for each applied 25.929 +patch. In addition, the special tags \index{tags!special tag 25.930 + names!<literal>qbase</literal>}<literal>qbase</literal> and \index{tags!special tag 25.931 + names!<literal>qtip</literal>}<literal>qtip</literal> identify the <quote>bottom-most</quote> and 25.932 +topmost applied patches, respectively. 25.933 +</para> 25.934 + 25.935 +<para>These additions to Mercurial's normal tagging capabilities make 25.936 +dealing with patches even more of a breeze. 25.937 +</para> 25.938 +<itemizedlist> 25.939 +<listitem><para>Want to patchbomb a mailing list with your latest series of 25.940 + changes? 25.941 +</para> 25.942 +</listitem><programlisting> 25.943 +<listitem><para> hg email qbase:qtip 25.944 +</para> 25.945 +</listitem></programlisting> 25.946 +<listitem><para> (Don't know what <quote>patchbombing</quote> is? See 25.947 + section <xref linkend="sec:hgext:patchbomb"/>.) 25.948 +</para> 25.949 +</listitem> 25.950 +<listitem><para>Need to see all of the patches since <literal>foo.patch</literal> that 25.951 + have touched files in a subdirectory of your tree? 25.952 +</para> 25.953 +</listitem><programlisting> 25.954 +<listitem><para> hg log -r foo.patch:qtip <emphasis>subdir</emphasis> 25.955 +</para> 25.956 +</listitem></programlisting> 25.957 +</itemizedlist> 25.958 + 25.959 +<para>Because MQ makes the names of patches available to the rest of 25.960 +Mercurial through its normal internal tag machinery, you don't need to 25.961 +type in the entire name of a patch when you want to identify it by 25.962 +name. 25.963 +</para> 25.964 + 25.965 +<informalfigure> 25.966 +<para> <!-- &interaction.mq.id.output; --> 25.967 + <caption><para>Using MQ's tag features to work with patches</para></caption> 25.968 + \label{ex:mq:id} 25.969 +</para> 25.970 +</informalfigure> 25.971 + 25.972 +<para>Another nice consequence of representing patch names as tags is that 25.973 +when you run the <command role="hg-cmd">hg log</command> command, it will display a patch's name 25.974 +as a tag, simply as part of its normal output. This makes it easy to 25.975 +visually distinguish applied patches from underlying <quote>normal</quote> 25.976 +revisions. Figure <xref linkend="ex:mq:id"/> shows a few normal Mercurial 25.977 +commands in use with applied patches. 25.978 +</para> 25.979 + 25.980 +</sect1> 25.981 +<sect1> 25.982 +<title>Useful things to know about</title> 25.983 + 25.984 +<para>There are a number of aspects of MQ usage that don't fit tidily into 25.985 +sections of their own, but that are good to know. Here they are, in 25.986 +one place. 25.987 +</para> 25.988 + 25.989 +<itemizedlist> 25.990 +<listitem><para>Normally, when you <command role="hg-ext-mq">qpop</command> a patch and <command role="hg-ext-mq">qpush</command> it 25.991 + again, the changeset that represents the patch after the pop/push 25.992 + will have a <emphasis>different identity</emphasis> than the changeset that 25.993 + represented the hash beforehand. See 25.994 + section <xref linkend="sec:mqref:cmd:qpush"/> for information as to why this is. 25.995 +</para> 25.996 +</listitem> 25.997 +<listitem><para>It's not a good idea to <command role="hg-cmd">hg merge</command> changes from another 25.998 + branch with a patch changeset, at least if you want to maintain the 25.999 + <quote>patchiness</quote> of that changeset and changesets below it on the 25.1000 + patch stack. If you try to do this, it will appear to succeed, but 25.1001 + MQ will become confused. 25.1002 +</para> 25.1003 +</listitem></itemizedlist> 25.1004 + 25.1005 +</sect1> 25.1006 +<sect1> 25.1007 +<title>Managing patches in a repository</title> 25.1008 +<para>\label{sec:mq:repo} 25.1009 +</para> 25.1010 + 25.1011 +<para>Because MQ's <filename role="special" class="directory">.hg/patches</filename> directory resides outside a 25.1012 +Mercurial repository's working directory, the <quote>underlying</quote> Mercurial 25.1013 +repository knows nothing about the management or presence of patches. 25.1014 +</para> 25.1015 + 25.1016 +<para>This presents the interesting possibility of managing the contents of 25.1017 +the patch directory as a Mercurial repository in its own right. This 25.1018 +can be a useful way to work. For example, you can work on a patch for 25.1019 +a while, <command role="hg-ext-mq">qrefresh</command> it, then <command role="hg-cmd">hg commit</command> the current state of 25.1020 +the patch. This lets you <quote>roll back</quote> to that version of the patch 25.1021 +later on. 25.1022 +</para> 25.1023 + 25.1024 +<para>You can then share different versions of the same patch stack among 25.1025 +multiple underlying repositories. I use this when I am developing a 25.1026 +Linux kernel feature. I have a pristine copy of my kernel sources for 25.1027 +each of several CPU architectures, and a cloned repository under each 25.1028 +that contains the patches I am working on. When I want to test a 25.1029 +change on a different architecture, I push my current patches to the 25.1030 +patch repository associated with that kernel tree, pop and push all of 25.1031 +my patches, and build and test that kernel. 25.1032 +</para> 25.1033 + 25.1034 +<para>Managing patches in a repository makes it possible for multiple 25.1035 +developers to work on the same patch series without colliding with 25.1036 +each other, all on top of an underlying source base that they may or 25.1037 +may not control. 25.1038 +</para> 25.1039 + 25.1040 +<sect2> 25.1041 +<title>MQ support for patch repositories</title> 25.1042 + 25.1043 +<para>MQ helps you to work with the <filename role="special" class="directory">.hg/patches</filename> directory as a 25.1044 +repository; when you prepare a repository for working with patches 25.1045 +using <command role="hg-ext-mq">qinit</command>, you can pass the <option role="hg-ext-mq-cmd-qinit-opt">-c</option> option to 25.1046 +create the <filename role="special" class="directory">.hg/patches</filename> directory as a Mercurial repository. 25.1047 +</para> 25.1048 + 25.1049 +<note> 25.1050 +<para> If you forget to use the <option role="hg-ext-mq-cmd-qinit-opt">-c</option> option, you can simply go 25.1051 + into the <filename role="special" class="directory">.hg/patches</filename> directory at any time and run 25.1052 + <command role="hg-cmd">hg init</command>. Don't forget to add an entry for the 25.1053 + <filename role="special">status</filename> file to the <filename role="special">.hgignore</filename> file, though 25.1054 +</para> 25.1055 + 25.1056 +<para> (<command role="hg-cmd">hg qinit <option role="hg-ext-mq-cmd-qinit-opt">-c</option></command> does this for you 25.1057 + automatically); you <emphasis>really</emphasis> don't want to manage the 25.1058 + <filename role="special">status</filename> file. 25.1059 +</para> 25.1060 +</note> 25.1061 + 25.1062 +<para>As a convenience, if MQ notices that the <filename class="directory">.hg/patches</filename> 25.1063 +directory is a repository, it will automatically <command role="hg-cmd">hg add</command> every 25.1064 +patch that you create and import. 25.1065 +</para> 25.1066 + 25.1067 +<para>MQ provides a shortcut command, <command role="hg-ext-mq">qcommit</command>, that runs 25.1068 +<command role="hg-cmd">hg commit</command> in the <filename role="special" class="directory">.hg/patches</filename> directory. This saves 25.1069 +some bothersome typing. 25.1070 +</para> 25.1071 + 25.1072 +<para>Finally, as a convenience to manage the patch directory, you can 25.1073 +define the alias <command>mq</command> on Unix systems. For example, on Linux 25.1074 +systems using the <command>bash</command> shell, you can include the following 25.1075 +snippet in your <filename role="home">~/.bashrc</filename>. 25.1076 +</para> 25.1077 + 25.1078 +<programlisting> 25.1079 +<para> alias mq=`hg -R $(hg root)/.hg/patches' 25.1080 +</para> 25.1081 +</programlisting> 25.1082 + 25.1083 +<para>You can then issue commands of the form <command>mq pull</command> from 25.1084 +the main repository. 25.1085 +</para> 25.1086 + 25.1087 +</sect2> 25.1088 +<sect2> 25.1089 +<title>A few things to watch out for</title> 25.1090 + 25.1091 +<para>MQ's support for working with a repository full of patches is limited 25.1092 +in a few small respects. 25.1093 +</para> 25.1094 + 25.1095 +<para>MQ cannot automatically detect changes that you make to the patch 25.1096 +directory. If you <command role="hg-cmd">hg pull</command>, manually edit, or <command role="hg-cmd">hg update</command> 25.1097 +changes to patches or the <filename role="special">series</filename> file, you will have to 25.1098 +<command role="hg-cmd">hg qpop <option role="hg-ext-mq-cmd-qpop-opt">-a</option></command> and then 25.1099 +<command role="hg-cmd">hg qpush <option role="hg-ext-mq-cmd-qpush-opt">-a</option></command> in the underlying repository to 25.1100 +see those changes show up there. If you forget to do this, you can 25.1101 +confuse MQ's idea of which patches are applied. 25.1102 +</para> 25.1103 + 25.1104 +</sect2> 25.1105 +</sect1> 25.1106 +<sect1> 25.1107 +<title>Third party tools for working with patches</title> 25.1108 +<para>\label{sec:mq:tools} 25.1109 +</para> 25.1110 + 25.1111 +<para>Once you've been working with patches for a while, you'll find 25.1112 +yourself hungry for tools that will help you to understand and 25.1113 +manipulate the patches you're dealing with. 25.1114 +</para> 25.1115 + 25.1116 +<para>The <command>diffstat</command> command <citation>web:diffstat</citation> generates a 25.1117 +histogram of the modifications made to each file in a patch. It 25.1118 +provides a good way to <quote>get a sense of</quote> a patch&emdash;which files it 25.1119 +affects, and how much change it introduces to each file and as a 25.1120 +whole. (I find that it's a good idea to use <command>diffstat</command>'s 25.1121 +<option role="cmd-opt-diffstat">-p</option> option as a matter of course, as otherwise it 25.1122 +will try to do clever things with prefixes of file names that 25.1123 +inevitably confuse at least me.) 25.1124 +</para> 25.1125 + 25.1126 +<informalfigure> 25.1127 +<para> <!-- &interaction.mq.tools.tools; --> 25.1128 + <caption><para>The <command>diffstat</para></caption>, \command{filterdiff</command>, and <command>lsdiff</command> commands} 25.1129 + \label{ex:mq:tools} 25.1130 +</para> 25.1131 +</informalfigure> 25.1132 + 25.1133 +<para>The <literal role="package">patchutils</literal> package <citation>web:patchutils</citation> is invaluable. 25.1134 +It provides a set of small utilities that follow the <quote>Unix 25.1135 +philosophy;</quote> each does one useful thing with a patch. The 25.1136 +<literal role="package">patchutils</literal> command I use most is <command>filterdiff</command>, which 25.1137 +extracts subsets from a patch file. For example, given a patch that 25.1138 +modifies hundreds of files across dozens of directories, a single 25.1139 +invocation of <command>filterdiff</command> can generate a smaller patch that 25.1140 +only touches files whose names match a particular glob pattern. See 25.1141 +section <xref linkend="mq-collab:tips:interdiff"/> for another example. 25.1142 +</para> 25.1143 + 25.1144 +</sect1> 25.1145 +<sect1> 25.1146 +<title>Good ways to work with patches</title> 25.1147 + 25.1148 +<para>Whether you are working on a patch series to submit to a free software 25.1149 +or open source project, or a series that you intend to treat as a 25.1150 +sequence of regular changesets when you're done, you can use some 25.1151 +simple techniques to keep your work well organised. 25.1152 +</para> 25.1153 + 25.1154 +<para>Give your patches descriptive names. A good name for a patch might be 25.1155 +<filename>rework-device-alloc.patch</filename>, because it will immediately give 25.1156 +you a hint what the purpose of the patch is. Long names shouldn't be 25.1157 +a problem; you won't be typing the names often, but you <emphasis>will</emphasis> be 25.1158 +running commands like <command role="hg-ext-mq">qapplied</command> and <command role="hg-ext-mq">qtop</command> over and over. 25.1159 +Good naming becomes especially important when you have a number of 25.1160 +patches to work with, or if you are juggling a number of different 25.1161 +tasks and your patches only get a fraction of your attention. 25.1162 +</para> 25.1163 + 25.1164 +<para>Be aware of what patch you're working on. Use the <command role="hg-ext-mq">qtop</command> 25.1165 +command and skim over the text of your patches frequently&emdash;for 25.1166 +example, using <command role="hg-cmd">hg tip <option role="hg-opt-tip">-p</option></command>)&emdash;to be sure of where 25.1167 +you stand. I have several times worked on and <command role="hg-ext-mq">qrefresh</command>ed a 25.1168 +patch other than the one I intended, and it's often tricky to migrate 25.1169 +changes into the right patch after making them in the wrong one. 25.1170 +</para> 25.1171 + 25.1172 +<para>For this reason, it is very much worth investing a little time to 25.1173 +learn how to use some of the third-party tools I described in 25.1174 +section <xref linkend="sec:mq:tools"/>, particularly <command>diffstat</command> and 25.1175 +<command>filterdiff</command>. The former will give you a quick idea of what 25.1176 +changes your patch is making, while the latter makes it easy to splice 25.1177 +hunks selectively out of one patch and into another. 25.1178 +</para> 25.1179 + 25.1180 +</sect1> 25.1181 +<sect1> 25.1182 +<title>MQ cookbook</title> 25.1183 + 25.1184 +<sect2> 25.1185 +<title>Manage <quote>trivial</quote> patches</title> 25.1186 + 25.1187 +<para>Because the overhead of dropping files into a new Mercurial repository 25.1188 +is so low, it makes a lot of sense to manage patches this way even if 25.1189 +you simply want to make a few changes to a source tarball that you 25.1190 +downloaded. 25.1191 +</para> 25.1192 + 25.1193 +<para>Begin by downloading and unpacking the source tarball, 25.1194 +and turning it into a Mercurial repository. 25.1195 +<!-- &interaction.mq.tarball.download; --> 25.1196 +</para> 25.1197 + 25.1198 +<para>Continue by creating a patch stack and making your changes. 25.1199 +<!-- &interaction.mq.tarball.qinit; --> 25.1200 +</para> 25.1201 + 25.1202 +<para>Let's say a few weeks or months pass, and your package author releases 25.1203 +a new version. First, bring their changes into the repository. 25.1204 +<!-- &interaction.mq.tarball.newsource; --> 25.1205 +The pipeline starting with <command role="hg-cmd">hg locate</command> above deletes all files in 25.1206 +the working directory, so that <command role="hg-cmd">hg commit</command>'s 25.1207 +<option role="hg-opt-commit">--addremove</option> option can actually tell which files have 25.1208 +really been removed in the newer version of the source. 25.1209 +</para> 25.1210 + 25.1211 +<para>Finally, you can apply your patches on top of the new tree. 25.1212 +<!-- &interaction.mq.tarball.repush; --> 25.1213 +</para> 25.1214 + 25.1215 +</sect2> 25.1216 +<sect2> 25.1217 +<title>Combining entire patches</title> 25.1218 +<para>\label{sec:mq:combine} 25.1219 +</para> 25.1220 + 25.1221 +<para>MQ provides a command, <command role="hg-ext-mq">qfold</command> that lets you combine entire 25.1222 +patches. This <quote>folds</quote> the patches you name, in the order you name 25.1223 +them, into the topmost applied patch, and concatenates their 25.1224 +descriptions onto the end of its description. The patches that you 25.1225 +fold must be unapplied before you fold them. 25.1226 +</para> 25.1227 + 25.1228 +<para>The order in which you fold patches matters. If your topmost applied 25.1229 +patch is <literal>foo</literal>, and you <command role="hg-ext-mq">qfold</command> <literal>bar</literal> and 25.1230 +<literal>quux</literal> into it, you will end up with a patch that has the same 25.1231 +effect as if you applied first <literal>foo</literal>, then <literal>bar</literal>, 25.1232 +followed by <literal>quux</literal>. 25.1233 +</para> 25.1234 + 25.1235 +</sect2> 25.1236 +<sect2> 25.1237 +<title>Merging part of one patch into another</title> 25.1238 + 25.1239 +<para>Merging <emphasis>part</emphasis> of one patch into another is more difficult than 25.1240 +combining entire patches. 25.1241 +</para> 25.1242 + 25.1243 +<para>If you want to move changes to entire files, you can use 25.1244 +<command>filterdiff</command>'s <option role="cmd-opt-filterdiff">-i</option> and 25.1245 +<option role="cmd-opt-filterdiff">-x</option> options to choose the modifications to snip 25.1246 +out of one patch, concatenating its output onto the end of the patch 25.1247 +you want to merge into. You usually won't need to modify the patch 25.1248 +you've merged the changes from. Instead, MQ will report some rejected 25.1249 +hunks when you <command role="hg-ext-mq">qpush</command> it (from the hunks you moved into the 25.1250 +other patch), and you can simply <command role="hg-ext-mq">qrefresh</command> the patch to drop 25.1251 +the duplicate hunks. 25.1252 +</para> 25.1253 + 25.1254 +<para>If you have a patch that has multiple hunks modifying a file, and you 25.1255 +only want to move a few of those hunks, the job becomes more messy, 25.1256 +but you can still partly automate it. Use <command>lsdiff -nvv</command> to 25.1257 +print some metadata about the patch. 25.1258 +<!-- &interaction.mq.tools.lsdiff; --> 25.1259 +</para> 25.1260 + 25.1261 +<para>This command prints three different kinds of number: 25.1262 +</para> 25.1263 +<itemizedlist> 25.1264 +<listitem><para>(in the first column) a <emphasis>file number</emphasis> to identify each file 25.1265 + modified in the patch; 25.1266 +</para> 25.1267 +</listitem> 25.1268 +<listitem><para>(on the next line, indented) the line number within a modified 25.1269 + file where a hunk starts; and 25.1270 +</para> 25.1271 +</listitem> 25.1272 +<listitem><para>(on the same line) a <emphasis>hunk number</emphasis> to identify that hunk. 25.1273 +</para> 25.1274 +</listitem></itemizedlist> 25.1275 + 25.1276 +<para>You'll have to use some visual inspection, and reading of the patch, 25.1277 +to identify the file and hunk numbers you'll want, but you can then 25.1278 +pass them to to <command>filterdiff</command>'s <option role="cmd-opt-filterdiff">--files</option> 25.1279 +and <option role="cmd-opt-filterdiff">--hunks</option> options, to select exactly the file 25.1280 +and hunk you want to extract. 25.1281 +</para> 25.1282 + 25.1283 +<para>Once you have this hunk, you can concatenate it onto the end of your 25.1284 +destination patch and continue with the remainder of 25.1285 +section <xref linkend="sec:mq:combine"/>. 25.1286 +</para> 25.1287 + 25.1288 +</sect2> 25.1289 +</sect1> 25.1290 +<sect1> 25.1291 +<title>Differences between quilt and MQ</title> 25.1292 + 25.1293 +<para>If you are already familiar with quilt, MQ provides a similar command 25.1294 +set. There are a few differences in the way that it works. 25.1295 +</para> 25.1296 + 25.1297 +<para>You will already have noticed that most quilt commands have MQ 25.1298 +counterparts that simply begin with a <quote><literal>q</literal></quote>. The exceptions 25.1299 +are quilt's <literal>add</literal> and <literal>remove</literal> commands, the 25.1300 +counterparts for which are the normal Mercurial <command role="hg-cmd">hg add</command> and 25.1301 +<command role="hg-cmd">hg remove</command> commands. There is no MQ equivalent of the quilt 25.1302 +<literal>edit</literal> command. 25.1303 +</para> 25.1304 + 25.1305 +</sect1> 25.1306 +</chapter> 25.1307 + 25.1308 +<!-- 25.1309 +local variables: 25.1310 +sgml-parent-document: ("00book.xml" "book" "chapter") 25.1311 +end: 25.1312 +--> 25.1313 \ No newline at end of file
26.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 26.2 +++ b/fr/ch13-mq-collab.xml Sun Aug 16 04:58:01 2009 +0200 26.3 @@ -0,0 +1,499 @@ 26.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 26.5 + 26.6 +<chapter> 26.7 +<title>Advanced uses of Mercurial Queues</title> 26.8 +<para>\label{chap:mq-collab}</para> 26.9 + 26.10 +<para>While it's easy to pick up straightforward uses of Mercurial Queues, 26.11 +use of a little discipline and some of MQ's less frequently used 26.12 +capabilities makes it possible to work in complicated development 26.13 +environments.</para> 26.14 + 26.15 +<para>In this chapter, I will use as an example a technique I have used to 26.16 +manage the development of an Infiniband device driver for the Linux 26.17 +kernel. The driver in question is large (at least as drivers go), 26.18 +with 25,000 lines of code spread across 35 source files. It is 26.19 +maintained by a small team of developers.</para> 26.20 + 26.21 +<para>While much of the material in this chapter is specific to Linux, the 26.22 +same principles apply to any code base for which you're not the 26.23 +primary owner, and upon which you need to do a lot of development.</para> 26.24 + 26.25 +<sect1> 26.26 +<title>The problem of many targets</title> 26.27 + 26.28 +<para>The Linux kernel changes rapidly, and has never been internally 26.29 +stable; developers frequently make drastic changes between releases. 26.30 +This means that a version of the driver that works well with a 26.31 +particular released version of the kernel will not even <emphasis>compile</emphasis> 26.32 +correctly against, typically, any other version.</para> 26.33 + 26.34 +<para>To maintain a driver, we have to keep a number of distinct versions of 26.35 +Linux in mind.</para> 26.36 +<itemizedlist> 26.37 +<listitem><para>One target is the main Linux kernel development tree. 26.38 + Maintenance of the code is in this case partly shared by other 26.39 + developers in the kernel community, who make <quote>drive-by</quote> 26.40 + modifications to the driver as they develop and refine kernel 26.41 + subsystems.</para> 26.42 +</listitem> 26.43 +<listitem><para>We also maintain a number of <quote>backports</quote> to older versions of 26.44 + the Linux kernel, to support the needs of customers who are running 26.45 + older Linux distributions that do not incorporate our drivers. (To 26.46 + <emphasis>backport</emphasis> a piece of code is to modify it to work in an older 26.47 + version of its target environment than the version it was developed 26.48 + for.)</para> 26.49 +</listitem> 26.50 +<listitem><para>Finally, we make software releases on a schedule that is 26.51 + necessarily not aligned with those used by Linux distributors and 26.52 + kernel developers, so that we can deliver new features to customers 26.53 + without forcing them to upgrade their entire kernels or 26.54 + distributions. 26.55 +</para> 26.56 +</listitem></itemizedlist> 26.57 + 26.58 +<sect2> 26.59 +<title>Tempting approaches that don't work well</title> 26.60 + 26.61 +<para>There are two <quote>standard</quote> ways to maintain a piece of software that 26.62 +has to target many different environments. 26.63 +</para> 26.64 + 26.65 +<para>The first is to maintain a number of branches, each intended for a 26.66 +single target. The trouble with this approach is that you must 26.67 +maintain iron discipline in the flow of changes between repositories. 26.68 +A new feature or bug fix must start life in a <quote>pristine</quote> repository, 26.69 +then percolate out to every backport repository. Backport changes are 26.70 +more limited in the branches they should propagate to; a backport 26.71 +change that is applied to a branch where it doesn't belong will 26.72 +probably stop the driver from compiling. 26.73 +</para> 26.74 + 26.75 +<para>The second is to maintain a single source tree filled with conditional 26.76 +statements that turn chunks of code on or off depending on the 26.77 +intended target. Because these <quote>ifdefs</quote> are not allowed in the 26.78 +Linux kernel tree, a manual or automatic process must be followed to 26.79 +strip them out and yield a clean tree. A code base maintained in this 26.80 +fashion rapidly becomes a rat's nest of conditional blocks that are 26.81 +difficult to understand and maintain. 26.82 +</para> 26.83 + 26.84 +<para>Neither of these approaches is well suited to a situation where you 26.85 +don't <quote>own</quote> the canonical copy of a source tree. In the case of a 26.86 +Linux driver that is distributed with the standard kernel, Linus's 26.87 +tree contains the copy of the code that will be treated by the world 26.88 +as canonical. The upstream version of <quote>my</quote> driver can be modified 26.89 +by people I don't know, without me even finding out about it until 26.90 +after the changes show up in Linus's tree. 26.91 +</para> 26.92 + 26.93 +<para>These approaches have the added weakness of making it difficult to 26.94 +generate well-formed patches to submit upstream. 26.95 +</para> 26.96 + 26.97 +<para>In principle, Mercurial Queues seems like a good candidate to manage a 26.98 +development scenario such as the above. While this is indeed the 26.99 +case, MQ contains a few added features that make the job more 26.100 +pleasant. 26.101 +</para> 26.102 + 26.103 +<para>\section{Conditionally applying patches with 26.104 + guards} 26.105 +</para> 26.106 + 26.107 +<para>Perhaps the best way to maintain sanity with so many targets is to be 26.108 +able to choose specific patches to apply for a given situation. MQ 26.109 +provides a feature called <quote>guards</quote> (which originates with quilt's 26.110 +<literal>guards</literal> command) that does just this. To start off, let's 26.111 +create a simple repository for experimenting in. 26.112 +<!-- &interaction.mq.guards.init; --> 26.113 +This gives us a tiny repository that contains two patches that don't 26.114 +have any dependencies on each other, because they touch different files. 26.115 +</para> 26.116 + 26.117 +<para>The idea behind conditional application is that you can <quote>tag</quote> a 26.118 +patch with a <emphasis>guard</emphasis>, which is simply a text string of your 26.119 +choosing, then tell MQ to select specific guards to use when applying 26.120 +patches. MQ will then either apply, or skip over, a guarded patch, 26.121 +depending on the guards that you have selected. 26.122 +</para> 26.123 + 26.124 +<para>A patch can have an arbitrary number of guards; 26.125 +each one is <emphasis>positive</emphasis> (<quote>apply this patch if this guard is 26.126 +selected</quote>) or <emphasis>negative</emphasis> (<quote>skip this patch if this guard is 26.127 +selected</quote>). A patch with no guards is always applied. 26.128 +</para> 26.129 + 26.130 +</sect2> 26.131 +</sect1> 26.132 +<sect1> 26.133 +<title>Controlling the guards on a patch</title> 26.134 + 26.135 +<para>The <command role="hg-ext-mq">qguard</command> command lets you determine which guards should 26.136 +apply to a patch, or display the guards that are already in effect. 26.137 +Without any arguments, it displays the guards on the current topmost 26.138 +patch. 26.139 +<!-- &interaction.mq.guards.qguard; --> 26.140 +To set a positive guard on a patch, prefix the name of the guard with 26.141 +a <quote><literal>+</literal></quote>. 26.142 +<!-- &interaction.mq.guards.qguard.pos; --> 26.143 +To set a negative guard on a patch, prefix the name of the guard with 26.144 +a <quote><literal>-</literal></quote>. 26.145 +<!-- &interaction.mq.guards.qguard.neg; --> 26.146 +</para> 26.147 + 26.148 +<note> 26.149 +<para> The <command role="hg-ext-mq">qguard</command> command <emphasis>sets</emphasis> the guards on a patch; it 26.150 + doesn't <emphasis>modify</emphasis> them. What this means is that if you run 26.151 + <command role="hg-cmd">hg qguard +a +b</command> on a patch, then <command role="hg-cmd">hg qguard +c</command> on 26.152 + the same patch, the <emphasis>only</emphasis> guard that will be set on it 26.153 + afterwards is <literal>+c</literal>. 26.154 +</para> 26.155 +</note> 26.156 + 26.157 +<para>Mercurial stores guards in the <filename role="special">series</filename> file; the form in 26.158 +which they are stored is easy both to understand and to edit by hand. 26.159 +(In other words, you don't have to use the <command role="hg-ext-mq">qguard</command> command if 26.160 +you don't want to; it's okay to simply edit the <filename role="special">series</filename> 26.161 +file.) 26.162 +<!-- &interaction.mq.guards.series; --> 26.163 +</para> 26.164 + 26.165 +</sect1> 26.166 +<sect1> 26.167 +<title>Selecting the guards to use</title> 26.168 + 26.169 +<para>The <command role="hg-ext-mq">qselect</command> command determines which guards are active at a 26.170 +given time. The effect of this is to determine which patches MQ will 26.171 +apply the next time you run <command role="hg-ext-mq">qpush</command>. It has no other effect; in 26.172 +particular, it doesn't do anything to patches that are already 26.173 +applied. 26.174 +</para> 26.175 + 26.176 +<para>With no arguments, the <command role="hg-ext-mq">qselect</command> command lists the guards 26.177 +currently in effect, one per line of output. Each argument is treated 26.178 +as the name of a guard to apply. 26.179 +<!-- &interaction.mq.guards.qselect.foo; --> 26.180 +In case you're interested, the currently selected guards are stored in 26.181 +the <filename role="special">guards</filename> file. 26.182 +<!-- &interaction.mq.guards.qselect.cat; --> 26.183 +We can see the effect the selected guards have when we run 26.184 +<command role="hg-ext-mq">qpush</command>. 26.185 +<!-- &interaction.mq.guards.qselect.qpush; --> 26.186 +</para> 26.187 + 26.188 +<para>A guard cannot start with a <quote><literal>+</literal></quote> or <quote><literal>-</literal></quote> 26.189 +character. The name of a guard must not contain white space, but most 26.190 +other characters are acceptable. If you try to use a guard with an 26.191 +invalid name, MQ will complain: 26.192 +<!-- &interaction.mq.guards.qselect.error; --> 26.193 +Changing the selected guards changes the patches that are applied. 26.194 +<!-- &interaction.mq.guards.qselect.quux; --> 26.195 +You can see in the example below that negative guards take precedence 26.196 +over positive guards. 26.197 +<!-- &interaction.mq.guards.qselect.foobar; --> 26.198 +</para> 26.199 + 26.200 +</sect1> 26.201 +<sect1> 26.202 +<title>MQ's rules for applying patches</title> 26.203 + 26.204 +<para>The rules that MQ uses when deciding whether to apply a patch 26.205 +are as follows. 26.206 +</para> 26.207 +<itemizedlist> 26.208 +<listitem><para>A patch that has no guards is always applied. 26.209 +</para> 26.210 +</listitem> 26.211 +<listitem><para>If the patch has any negative guard that matches any currently 26.212 + selected guard, the patch is skipped. 26.213 +</para> 26.214 +</listitem> 26.215 +<listitem><para>If the patch has any positive guard that matches any currently 26.216 + selected guard, the patch is applied. 26.217 +</para> 26.218 +</listitem> 26.219 +<listitem><para>If the patch has positive or negative guards, but none matches 26.220 + any currently selected guard, the patch is skipped. 26.221 +</para> 26.222 +</listitem></itemizedlist> 26.223 + 26.224 +</sect1> 26.225 +<sect1> 26.226 +<title>Trimming the work environment</title> 26.227 + 26.228 +<para>In working on the device driver I mentioned earlier, I don't apply the 26.229 +patches to a normal Linux kernel tree. Instead, I use a repository 26.230 +that contains only a snapshot of the source files and headers that are 26.231 +relevant to Infiniband development. This repository is 1% the size 26.232 +of a kernel repository, so it's easier to work with. 26.233 +</para> 26.234 + 26.235 +<para>I then choose a <quote>base</quote> version on top of which the patches are 26.236 +applied. This is a snapshot of the Linux kernel tree as of a revision 26.237 +of my choosing. When I take the snapshot, I record the changeset ID 26.238 +from the kernel repository in the commit message. Since the snapshot 26.239 +preserves the <quote>shape</quote> and content of the relevant parts of the 26.240 +kernel tree, I can apply my patches on top of either my tiny 26.241 +repository or a normal kernel tree. 26.242 +</para> 26.243 + 26.244 +<para>Normally, the base tree atop which the patches apply should be a 26.245 +snapshot of a very recent upstream tree. This best facilitates the 26.246 +development of patches that can easily be submitted upstream with few 26.247 +or no modifications. 26.248 +</para> 26.249 + 26.250 +</sect1> 26.251 +<sect1> 26.252 +<title>Dividing up the <filename role="special">series</filename> file</title> 26.253 + 26.254 +<para>I categorise the patches in the <filename role="special">series</filename> file into a number 26.255 +of logical groups. Each section of like patches begins with a block 26.256 +of comments that describes the purpose of the patches that follow. 26.257 +</para> 26.258 + 26.259 +<para>The sequence of patch groups that I maintain follows. The ordering of 26.260 +these groups is important; I'll describe why after I introduce the 26.261 +groups. 26.262 +</para> 26.263 +<itemizedlist> 26.264 +<listitem><para>The <quote>accepted</quote> group. Patches that the development team has 26.265 + submitted to the maintainer of the Infiniband subsystem, and which 26.266 + he has accepted, but which are not present in the snapshot that the 26.267 + tiny repository is based on. These are <quote>read only</quote> patches, 26.268 + present only to transform the tree into a similar state as it is in 26.269 + the upstream maintainer's repository. 26.270 +</para> 26.271 +</listitem> 26.272 +<listitem><para>The <quote>rework</quote> group. Patches that I have submitted, but that 26.273 + the upstream maintainer has requested modifications to before he 26.274 + will accept them. 26.275 +</para> 26.276 +</listitem> 26.277 +<listitem><para>The <quote>pending</quote> group. Patches that I have not yet submitted to 26.278 + the upstream maintainer, but which we have finished working on. 26.279 + These will be <quote>read only</quote> for a while. If the upstream maintainer 26.280 + accepts them upon submission, I'll move them to the end of the 26.281 + <quote>accepted</quote> group. If he requests that I modify any, I'll move 26.282 + them to the beginning of the <quote>rework</quote> group. 26.283 +</para> 26.284 +</listitem> 26.285 +<listitem><para>The <quote>in progress</quote> group. Patches that are actively being 26.286 + developed, and should not be submitted anywhere yet. 26.287 +</para> 26.288 +</listitem> 26.289 +<listitem><para>The <quote>backport</quote> group. Patches that adapt the source tree to 26.290 + older versions of the kernel tree. 26.291 +</para> 26.292 +</listitem> 26.293 +<listitem><para>The <quote>do not ship</quote> group. Patches that for some reason should 26.294 + never be submitted upstream. For example, one such patch might 26.295 + change embedded driver identification strings to make it easier to 26.296 + distinguish, in the field, between an out-of-tree version of the 26.297 + driver and a version shipped by a distribution vendor. 26.298 +</para> 26.299 +</listitem></itemizedlist> 26.300 + 26.301 +<para>Now to return to the reasons for ordering groups of patches in this 26.302 +way. We would like the lowest patches in the stack to be as stable as 26.303 +possible, so that we will not need to rework higher patches due to 26.304 +changes in context. Putting patches that will never be changed first 26.305 +in the <filename role="special">series</filename> file serves this purpose. 26.306 +</para> 26.307 + 26.308 +<para>We would also like the patches that we know we'll need to modify to be 26.309 +applied on top of a source tree that resembles the upstream tree as 26.310 +closely as possible. This is why we keep accepted patches around for 26.311 +a while. 26.312 +</para> 26.313 + 26.314 +<para>The <quote>backport</quote> and <quote>do not ship</quote> patches float at the end of the 26.315 +<filename role="special">series</filename> file. The backport patches must be applied on top 26.316 +of all other patches, and the <quote>do not ship</quote> patches might as well 26.317 +stay out of harm's way. 26.318 +</para> 26.319 + 26.320 +</sect1> 26.321 +<sect1> 26.322 +<title>Maintaining the patch series</title> 26.323 + 26.324 +<para>In my work, I use a number of guards to control which patches are to 26.325 +be applied. 26.326 +</para> 26.327 + 26.328 +<itemizedlist> 26.329 +<listitem><para><quote>Accepted</quote> patches are guarded with <literal>accepted</literal>. I 26.330 + enable this guard most of the time. When I'm applying the patches 26.331 + on top of a tree where the patches are already present, I can turn 26.332 + this patch off, and the patches that follow it will apply cleanly. 26.333 +</para> 26.334 +</listitem> 26.335 +<listitem><para>Patches that are <quote>finished</quote>, but not yet submitted, have no 26.336 + guards. If I'm applying the patch stack to a copy of the upstream 26.337 + tree, I don't need to enable any guards in order to get a reasonably 26.338 + safe source tree. 26.339 +</para> 26.340 +</listitem> 26.341 +<listitem><para>Those patches that need reworking before being resubmitted are 26.342 + guarded with <literal>rework</literal>. 26.343 +</para> 26.344 +</listitem> 26.345 +<listitem><para>For those patches that are still under development, I use 26.346 + <literal>devel</literal>. 26.347 +</para> 26.348 +</listitem> 26.349 +<listitem><para>A backport patch may have several guards, one for each version 26.350 + of the kernel to which it applies. For example, a patch that 26.351 + backports a piece of code to 2.6.9 will have a <literal>2.6.9</literal> guard. 26.352 +</para> 26.353 +</listitem></itemizedlist> 26.354 +<para>This variety of guards gives me considerable flexibility in 26.355 +determining what kind of source tree I want to end up with. For most 26.356 +situations, the selection of appropriate guards is automated during 26.357 +the build process, but I can manually tune the guards to use for less 26.358 +common circumstances. 26.359 +</para> 26.360 + 26.361 +<sect2> 26.362 +<title>The art of writing backport patches</title> 26.363 + 26.364 +<para>Using MQ, writing a backport patch is a simple process. All such a 26.365 +patch has to do is modify a piece of code that uses a kernel feature 26.366 +not present in the older version of the kernel, so that the driver 26.367 +continues to work correctly under that older version. 26.368 +</para> 26.369 + 26.370 +<para>A useful goal when writing a good backport patch is to make your code 26.371 +look as if it was written for the older version of the kernel you're 26.372 +targeting. The less obtrusive the patch, the easier it will be to 26.373 +understand and maintain. If you're writing a collection of backport 26.374 +patches to avoid the <quote>rat's nest</quote> effect of lots of 26.375 +<literal>#ifdef</literal>s (hunks of source code that are only used 26.376 +conditionally) in your code, don't introduce version-dependent 26.377 +<literal>#ifdef</literal>s into the patches. Instead, write several patches, 26.378 +each of which makes unconditional changes, and control their 26.379 +application using guards. 26.380 +</para> 26.381 + 26.382 +<para>There are two reasons to divide backport patches into a distinct 26.383 +group, away from the <quote>regular</quote> patches whose effects they modify. 26.384 +The first is that intermingling the two makes it more difficult to use 26.385 +a tool like the <literal role="hg-ext">patchbomb</literal> extension to automate the process of 26.386 +submitting the patches to an upstream maintainer. The second is that 26.387 +a backport patch could perturb the context in which a subsequent 26.388 +regular patch is applied, making it impossible to apply the regular 26.389 +patch cleanly <emphasis>without</emphasis> the earlier backport patch already being 26.390 +applied. 26.391 +</para> 26.392 + 26.393 +</sect2> 26.394 +</sect1> 26.395 +<sect1> 26.396 +<title>Useful tips for developing with MQ</title> 26.397 + 26.398 +<sect2> 26.399 +<title>Organising patches in directories</title> 26.400 + 26.401 +<para>If you're working on a substantial project with MQ, it's not difficult 26.402 +to accumulate a large number of patches. For example, I have one 26.403 +patch repository that contains over 250 patches. 26.404 +</para> 26.405 + 26.406 +<para>If you can group these patches into separate logical categories, you 26.407 +can if you like store them in different directories; MQ has no 26.408 +problems with patch names that contain path separators. 26.409 +</para> 26.410 + 26.411 +</sect2> 26.412 +<sect2> 26.413 +<title>Viewing the history of a patch</title> 26.414 +<para>\label{mq-collab:tips:interdiff} 26.415 +</para> 26.416 + 26.417 +<para>If you're developing a set of patches over a long time, it's a good 26.418 +idea to maintain them in a repository, as discussed in 26.419 +section <xref linkend="sec:mq:repo"/>. If you do so, you'll quickly discover that 26.420 +using the <command role="hg-cmd">hg diff</command> command to look at the history of changes to a 26.421 +patch is unworkable. This is in part because you're looking at the 26.422 +second derivative of the real code (a diff of a diff), but also 26.423 +because MQ adds noise to the process by modifying time stamps and 26.424 +directory names when it updates a patch. 26.425 +</para> 26.426 + 26.427 +<para>However, you can use the <literal role="hg-ext">extdiff</literal> extension, which is bundled 26.428 +with Mercurial, to turn a diff of two versions of a patch into 26.429 +something readable. To do this, you will need a third-party package 26.430 +called <literal role="package">patchutils</literal> <citation>web:patchutils</citation>. This provides a 26.431 +command named <command>interdiff</command>, which shows the differences between 26.432 +two diffs as a diff. Used on two versions of the same diff, it 26.433 +generates a diff that represents the diff from the first to the second 26.434 +version. 26.435 +</para> 26.436 + 26.437 +<para>You can enable the <literal role="hg-ext">extdiff</literal> extension in the usual way, by 26.438 +adding a line to the <literal role="rc-extensions">extensions</literal> section of your <filename role="special"> /.hgrc</filename>. 26.439 +</para> 26.440 +<programlisting> 26.441 +<para> [extensions] 26.442 + extdiff = 26.443 +</para> 26.444 +</programlisting> 26.445 +<para>The <command>interdiff</command> command expects to be passed the names of two 26.446 +files, but the <literal role="hg-ext">extdiff</literal> extension passes the program it runs a 26.447 +pair of directories, each of which can contain an arbitrary number of 26.448 +files. We thus need a small program that will run <command>interdiff</command> 26.449 +on each pair of files in these two directories. This program is 26.450 +available as <filename role="special">hg-interdiff</filename> in the <filename class="directory">examples</filename> 26.451 +directory of the source code repository that accompanies this book. 26.452 +<!-- &example.hg-interdiff; --> 26.453 +</para> 26.454 + 26.455 +<para>With the <filename role="special">hg-interdiff</filename> program in your shell's search path, 26.456 +you can run it as follows, from inside an MQ patch directory: 26.457 +</para> 26.458 +<programlisting> 26.459 +<para> hg extdiff -p hg-interdiff -r A:B my-change.patch 26.460 +</para> 26.461 +</programlisting> 26.462 +<para>Since you'll probably want to use this long-winded command a lot, you 26.463 +can get <literal role="hg-ext">hgext</literal> to make it available as a normal Mercurial 26.464 +command, again by editing your <filename role="special"> /.hgrc</filename>. 26.465 +</para> 26.466 +<programlisting> 26.467 +<para> [extdiff] 26.468 + cmd.interdiff = hg-interdiff 26.469 +</para> 26.470 +</programlisting> 26.471 +<para>This directs <literal role="hg-ext">hgext</literal> to make an <literal>interdiff</literal> command 26.472 +available, so you can now shorten the previous invocation of 26.473 +<command role="hg-ext-extdiff">extdiff</command> to something a little more wieldy. 26.474 +</para> 26.475 +<programlisting> 26.476 +<para> hg interdiff -r A:B my-change.patch 26.477 +</para> 26.478 +</programlisting> 26.479 + 26.480 +<note> 26.481 +<para> The <command>interdiff</command> command works well only if the underlying 26.482 + files against which versions of a patch are generated remain the 26.483 + same. If you create a patch, modify the underlying files, and then 26.484 + regenerate the patch, <command>interdiff</command> may not produce useful 26.485 + output. 26.486 +</para> 26.487 +</note> 26.488 + 26.489 +<para>The <literal role="hg-ext">extdiff</literal> extension is useful for more than merely improving 26.490 +the presentation of MQ patches. To read more about it, go to 26.491 +section <xref linkend="sec:hgext:extdiff"/>. 26.492 +</para> 26.493 + 26.494 +</sect2> 26.495 +</sect1> 26.496 +</chapter> 26.497 + 26.498 +<!-- 26.499 +local variables: 26.500 +sgml-parent-document: ("00book.xml" "book" "chapter") 26.501 +end: 26.502 +--> 26.503 \ No newline at end of file
27.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 27.2 +++ b/fr/ch14-hgext.xml Sun Aug 16 04:58:01 2009 +0200 27.3 @@ -0,0 +1,539 @@ 27.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 27.5 + 27.6 +<chapter> 27.7 +<title>Adding functionality with extensions</title> 27.8 +<para>\label{chap:hgext}</para> 27.9 + 27.10 +<para>While the core of Mercurial is quite complete from a functionality 27.11 +standpoint, it's deliberately shorn of fancy features. This approach 27.12 +of preserving simplicity keeps the software easy to deal with for both 27.13 +maintainers and users.</para> 27.14 + 27.15 +<para>However, Mercurial doesn't box you in with an inflexible command set: 27.16 +you can add features to it as <emphasis>extensions</emphasis> (sometimes known as 27.17 +<emphasis>plugins</emphasis>). We've already discussed a few of these extensions in 27.18 +earlier chapters.</para> 27.19 +<itemizedlist> 27.20 +<listitem><para>Section <xref linkend="sec:tour-merge:fetch"/> covers the <literal role="hg-ext">fetch</literal> 27.21 + extension; this combines pulling new changes and merging them with 27.22 + local changes into a single command, <command role="hg-ext-fetch">fetch</command>.</para> 27.23 +</listitem> 27.24 +<listitem><para>In chapter <xref linkend="chap:hook"/>, we covered several extensions that 27.25 + are useful for hook-related functionality: <literal role="hg-ext">acl</literal> adds access 27.26 + control lists; <literal role="hg-ext">bugzilla</literal> adds integration with the Bugzilla 27.27 + bug tracking system; and <literal role="hg-ext">notify</literal> sends notification emails on 27.28 + new changes.</para> 27.29 +</listitem> 27.30 +<listitem><para>The Mercurial Queues patch management extension is so invaluable 27.31 + that it merits two chapters and an appendix all to itself. 27.32 + Chapter <xref linkend="chap:mq"/> covers the basics; 27.33 + chapter <xref linkend="chap:mq-collab"/> discusses advanced topics; and 27.34 + appendix <xref linkend="chap:mqref"/> goes into detail on each command.</para> 27.35 +</listitem></itemizedlist> 27.36 + 27.37 +<para>In this chapter, we'll cover some of the other extensions that are 27.38 +available for Mercurial, and briefly touch on some of the machinery 27.39 +you'll need to know about if you want to write an extension of your 27.40 +own.</para> 27.41 +<itemizedlist> 27.42 +<listitem><para>In section <xref linkend="sec:hgext:inotify"/>, we'll discuss the 27.43 + possibility of <emphasis>huge</emphasis> performance improvements using the 27.44 + <literal role="hg-ext">inotify</literal> extension.</para> 27.45 +</listitem></itemizedlist> 27.46 + 27.47 +<sect1> 27.48 +<title>Improve performance with the <literal role="hg-ext">inotify</literal> extension</title> 27.49 +<para>\label{sec:hgext:inotify} 27.50 +</para> 27.51 + 27.52 +<para>Are you interested in having some of the most common Mercurial 27.53 +operations run as much as a hundred times faster? Read on! 27.54 +</para> 27.55 + 27.56 +<para>Mercurial has great performance under normal circumstances. For 27.57 +example, when you run the <command role="hg-cmd">hg status</command> command, Mercurial has to 27.58 +scan almost every directory and file in your repository so that it can 27.59 +display file status. Many other Mercurial commands need to do the 27.60 +same work behind the scenes; for example, the <command role="hg-cmd">hg diff</command> command 27.61 +uses the status machinery to avoid doing an expensive comparison 27.62 +operation on files that obviously haven't changed. 27.63 +</para> 27.64 + 27.65 +<para>Because obtaining file status is crucial to good performance, the 27.66 +authors of Mercurial have optimised this code to within an inch of its 27.67 +life. However, there's no avoiding the fact that when you run 27.68 +<command role="hg-cmd">hg status</command>, Mercurial is going to have to perform at least one 27.69 +expensive system call for each managed file to determine whether it's 27.70 +changed since the last time Mercurial checked. For a sufficiently 27.71 +large repository, this can take a long time. 27.72 +</para> 27.73 + 27.74 +<para>To put a number on the magnitude of this effect, I created a 27.75 +repository containing 150,000 managed files. I timed <command role="hg-cmd">hg status</command> 27.76 +as taking ten seconds to run, even when <emphasis>none</emphasis> of those files had 27.77 +been modified. 27.78 +</para> 27.79 + 27.80 +<para>Many modern operating systems contain a file notification facility. 27.81 +If a program signs up to an appropriate service, the operating system 27.82 +will notify it every time a file of interest is created, modified, or 27.83 +deleted. On Linux systems, the kernel component that does this is 27.84 +called <literal>inotify</literal>. 27.85 +</para> 27.86 + 27.87 +<para>Mercurial's <literal role="hg-ext">inotify</literal> extension talks to the kernel's 27.88 +<literal>inotify</literal> component to optimise <command role="hg-cmd">hg status</command> commands. The 27.89 +extension has two components. A daemon sits in the background and 27.90 +receives notifications from the <literal>inotify</literal> subsystem. It also 27.91 +listens for connections from a regular Mercurial command. The 27.92 +extension modifies Mercurial's behaviour so that instead of scanning 27.93 +the filesystem, it queries the daemon. Since the daemon has perfect 27.94 +information about the state of the repository, it can respond with a 27.95 +result instantaneously, avoiding the need to scan every directory and 27.96 +file in the repository. 27.97 +</para> 27.98 + 27.99 +<para>Recall the ten seconds that I measured plain Mercurial as taking to 27.100 +run <command role="hg-cmd">hg status</command> on a 150,000 file repository. With the 27.101 +<literal role="hg-ext">inotify</literal> extension enabled, the time dropped to 0.1 seconds, a 27.102 +factor of <emphasis>one hundred</emphasis> faster. 27.103 +</para> 27.104 + 27.105 +<para>Before we continue, please pay attention to some caveats. 27.106 +</para> 27.107 +<itemizedlist> 27.108 +<listitem><para>The <literal role="hg-ext">inotify</literal> extension is Linux-specific. Because it 27.109 + interfaces directly to the Linux kernel's <literal>inotify</literal> 27.110 + subsystem, it does not work on other operating systems. 27.111 +</para> 27.112 +</listitem> 27.113 +<listitem><para>It should work on any Linux distribution that was released after 27.114 + early 2005. Older distributions are likely to have a kernel that 27.115 + lacks <literal>inotify</literal>, or a version of <literal>glibc</literal> that does not 27.116 + have the necessary interfacing support. 27.117 +</para> 27.118 +</listitem> 27.119 +<listitem><para>Not all filesystems are suitable for use with the 27.120 + <literal role="hg-ext">inotify</literal> extension. Network filesystems such as NFS are a 27.121 + non-starter, for example, particularly if you're running Mercurial 27.122 + on several systems, all mounting the same network filesystem. The 27.123 + kernel's <literal>inotify</literal> system has no way of knowing about changes 27.124 + made on another system. Most local filesystems (e.g. ext3, XFS, 27.125 + ReiserFS) should work fine. 27.126 +</para> 27.127 +</listitem></itemizedlist> 27.128 + 27.129 +<para>The <literal role="hg-ext">inotify</literal> extension is not yet shipped with Mercurial as of 27.130 +May 2007, so it's a little more involved to set up than other 27.131 +extensions. But the performance improvement is worth it! 27.132 +</para> 27.133 + 27.134 +<para>The extension currently comes in two parts: a set of patches to the 27.135 +Mercurial source code, and a library of Python bindings to the 27.136 +<literal>inotify</literal> subsystem. 27.137 +</para> 27.138 +<note> 27.139 +<para> There are <emphasis>two</emphasis> Python <literal>inotify</literal> binding libraries. One 27.140 + of them is called <literal>pyinotify</literal>, and is packaged by some Linux 27.141 + distributions as <literal>python-inotify</literal>. This is <emphasis>not</emphasis> the 27.142 + one you'll need, as it is too buggy and inefficient to be practical. 27.143 +</para> 27.144 +</note> 27.145 +<para>To get going, it's best to already have a functioning copy of 27.146 +Mercurial installed. 27.147 +</para> 27.148 +<note> 27.149 +<para> If you follow the instructions below, you'll be <emphasis>replacing</emphasis> and 27.150 + overwriting any existing installation of Mercurial that you might 27.151 + already have, using the latest <quote>bleeding edge</quote> Mercurial code. 27.152 + Don't say you weren't warned! 27.153 +</para> 27.154 +</note> 27.155 +<orderedlist> 27.156 +<listitem><para>Clone the Python <literal>inotify</literal> binding repository. Build and 27.157 + install it. 27.158 +</para> 27.159 +</listitem><programlisting> 27.160 +<listitem><para> hg clone http://hg.kublai.com/python/inotify 27.161 + cd inotify 27.162 + python setup.py build --force 27.163 + sudo python setup.py install --skip-build 27.164 +</para> 27.165 +</listitem></programlisting> 27.166 +</para> 27.167 +</listitem> 27.168 +<listitem><para>Clone the <filename class="directory">crew</filename> Mercurial repository. Clone the 27.169 + <literal role="hg-ext">inotify</literal> patch repository so that Mercurial Queues will be 27.170 + able to apply patches to your cope of the <filename class="directory">crew</filename> repository. 27.171 +</para> 27.172 +</listitem><programlisting> 27.173 +<listitem><para> hg clone http://hg.intevation.org/mercurial/crew 27.174 + hg clone crew inotify 27.175 + hg clone http://hg.kublai.com/mercurial/patches/inotify inotify/.hg/patches 27.176 +</para> 27.177 +</listitem></programlisting> 27.178 +</para> 27.179 +</listitem> 27.180 +<listitem><para>Make sure that you have the Mercurial Queues extension, 27.181 + <literal role="hg-ext">mq</literal>, enabled. If you've never used MQ, read 27.182 + section <xref linkend="sec:mq:start"/> to get started quickly. 27.183 +</para> 27.184 +</listitem> 27.185 +<listitem><para>Go into the <filename class="directory">inotify</filename> repo, and apply all of the 27.186 + <literal role="hg-ext">inotify</literal> patches using the <option role="hg-ext-mq-cmd-qpush-opt">-a</option> option to 27.187 + the <command role="hg-ext-mq">qpush</command> command. 27.188 +</para> 27.189 +</listitem><programlisting> 27.190 +<listitem><para> cd inotify 27.191 + hg qpush -a 27.192 +</para> 27.193 +</listitem></programlisting> 27.194 +<listitem><para> If you get an error message from <command role="hg-ext-mq">qpush</command>, you should not 27.195 + continue. Instead, ask for help. 27.196 +</para> 27.197 +</listitem> 27.198 +<listitem><para>Build and install the patched version of Mercurial. 27.199 +</para> 27.200 +</listitem><programlisting> 27.201 +<listitem><para> python setup.py build --force 27.202 + sudo python setup.py install --skip-build 27.203 +</para> 27.204 +</listitem></programlisting> 27.205 +</orderedlist> 27.206 +<para>Once you've build a suitably patched version of Mercurial, all you 27.207 +need to do to enable the <literal role="hg-ext">inotify</literal> extension is add an entry to 27.208 +your <filename role="special"> /.hgrc</filename>. 27.209 +</para> 27.210 +<programlisting> 27.211 +<para> [extensions] 27.212 + inotify = 27.213 +</para> 27.214 +</programlisting> 27.215 +<para>When the <literal role="hg-ext">inotify</literal> extension is enabled, Mercurial will 27.216 +automatically and transparently start the status daemon the first time 27.217 +you run a command that needs status in a repository. It runs one 27.218 +status daemon per repository. 27.219 +</para> 27.220 + 27.221 +<para>The status daemon is started silently, and runs in the background. If 27.222 +you look at a list of running processes after you've enabled the 27.223 +<literal role="hg-ext">inotify</literal> extension and run a few commands in different 27.224 +repositories, you'll thus see a few <literal>hg</literal> processes sitting 27.225 +around, waiting for updates from the kernel and queries from 27.226 +Mercurial. 27.227 +</para> 27.228 + 27.229 +<para>The first time you run a Mercurial command in a repository when you 27.230 +have the <literal role="hg-ext">inotify</literal> extension enabled, it will run with about the 27.231 +same performance as a normal Mercurial command. This is because the 27.232 +status daemon needs to perform a normal status scan so that it has a 27.233 +baseline against which to apply later updates from the kernel. 27.234 +However, <emphasis>every</emphasis> subsequent command that does any kind of status 27.235 +check should be noticeably faster on repositories of even fairly 27.236 +modest size. Better yet, the bigger your repository is, the greater a 27.237 +performance advantage you'll see. The <literal role="hg-ext">inotify</literal> daemon makes 27.238 +status operations almost instantaneous on repositories of all sizes! 27.239 +</para> 27.240 + 27.241 +<para>If you like, you can manually start a status daemon using the 27.242 +<command role="hg-ext-inotify">inserve</command> command. This gives you slightly finer 27.243 +control over how the daemon ought to run. This command will of course 27.244 +only be available when the <literal role="hg-ext">inotify</literal> extension is enabled. 27.245 +</para> 27.246 + 27.247 +<para>When you're using the <literal role="hg-ext">inotify</literal> extension, you should notice 27.248 +<emphasis>no difference at all</emphasis> in Mercurial's behaviour, with the sole 27.249 +exception of status-related commands running a whole lot faster than 27.250 +they used to. You should specifically expect that commands will not 27.251 +print different output; neither should they give different results. 27.252 +If either of these situations occurs, please report a bug. 27.253 +</para> 27.254 + 27.255 +</sect1> 27.256 +<sect1> 27.257 +<title>Flexible diff support with the <literal role="hg-ext">extdiff</literal> extension</title> 27.258 +<para>\label{sec:hgext:extdiff} 27.259 +</para> 27.260 + 27.261 +<para>Mercurial's built-in <command role="hg-cmd">hg diff</command> command outputs plaintext unified 27.262 +diffs. 27.263 +<!-- &interaction.extdiff.diff; --> 27.264 +If you would like to use an external tool to display modifications, 27.265 +you'll want to use the <literal role="hg-ext">extdiff</literal> extension. This will let you 27.266 +use, for example, a graphical diff tool. 27.267 +</para> 27.268 + 27.269 +<para>The <literal role="hg-ext">extdiff</literal> extension is bundled with Mercurial, so it's easy 27.270 +to set up. In the <literal role="rc-extensions">extensions</literal> section of your <filename role="special"> /.hgrc</filename>, 27.271 +simply add a one-line entry to enable the extension. 27.272 +</para> 27.273 +<programlisting> 27.274 +<para> [extensions] 27.275 + extdiff = 27.276 +</para> 27.277 +</programlisting> 27.278 +<para>This introduces a command named <command role="hg-ext-extdiff">extdiff</command>, which by 27.279 +default uses your system's <command>diff</command> command to generate a 27.280 +unified diff in the same form as the built-in <command role="hg-cmd">hg diff</command> command. 27.281 +<!-- &interaction.extdiff.extdiff; --> 27.282 +The result won't be exactly the same as with the built-in <command role="hg-cmd">hg diff</command> 27.283 +variations, because the output of <command>diff</command> varies from one 27.284 +system to another, even when passed the same options. 27.285 +</para> 27.286 + 27.287 +<para>As the <quote><literal>making snapshot</literal></quote> lines of output above imply, the 27.288 +<command role="hg-ext-extdiff">extdiff</command> command works by creating two snapshots of 27.289 +your source tree. The first snapshot is of the source revision; the 27.290 +second, of the target revision or working directory. The 27.291 +<command role="hg-ext-extdiff">extdiff</command> command generates these snapshots in a 27.292 +temporary directory, passes the name of each directory to an external 27.293 +diff viewer, then deletes the temporary directory. For efficiency, it 27.294 +only snapshots the directories and files that have changed between the 27.295 +two revisions. 27.296 +</para> 27.297 + 27.298 +<para>Snapshot directory names have the same base name as your repository. 27.299 +If your repository path is <filename class="directory">/quux/bar/foo</filename>, then <filename class="directory">foo</filename> 27.300 +will be the name of each snapshot directory. Each snapshot directory 27.301 +name has its changeset ID appended, if appropriate. If a snapshot is 27.302 +of revision <literal>a631aca1083f</literal>, the directory will be named 27.303 +<filename class="directory">foo.a631aca1083f</filename>. A snapshot of the working directory won't 27.304 +have a changeset ID appended, so it would just be <filename class="directory">foo</filename> in 27.305 +this example. To see what this looks like in practice, look again at 27.306 +the <command role="hg-ext-extdiff">extdiff</command> example above. Notice that the diff has 27.307 +the snapshot directory names embedded in its header. 27.308 +</para> 27.309 + 27.310 +<para>The <command role="hg-ext-extdiff">extdiff</command> command accepts two important options. 27.311 +The <option role="hg-ext-extdiff-cmd-extdiff-opt">-p</option> option lets you choose a program to 27.312 +view differences with, instead of <command>diff</command>. With the 27.313 +<option role="hg-ext-extdiff-cmd-extdiff-opt">-o</option> option, you can change the options that 27.314 +<command role="hg-ext-extdiff">extdiff</command> passes to the program (by default, these 27.315 +options are <quote><literal>-Npru</literal></quote>, which only make sense if you're 27.316 +running <command>diff</command>). In other respects, the 27.317 +<command role="hg-ext-extdiff">extdiff</command> command acts similarly to the built-in 27.318 +<command role="hg-cmd">hg diff</command> command: you use the same option names, syntax, and 27.319 +arguments to specify the revisions you want, the files you want, and 27.320 +so on. 27.321 +</para> 27.322 + 27.323 +<para>As an example, here's how to run the normal system <command>diff</command> 27.324 +command, getting it to generate context diffs (using the 27.325 +<option role="cmd-opt-diff">-c</option> option) instead of unified diffs, and five lines of 27.326 +context instead of the default three (passing <literal>5</literal> as the 27.327 +argument to the <option role="cmd-opt-diff">-C</option> option). 27.328 +<!-- &interaction.extdiff.extdiff-ctx; --> 27.329 +</para> 27.330 + 27.331 +<para>Launching a visual diff tool is just as easy. Here's how to launch 27.332 +the <command>kdiff3</command> viewer. 27.333 +</para> 27.334 +<programlisting> 27.335 +<para> hg extdiff -p kdiff3 -o </quote> 27.336 +</para> 27.337 +</programlisting> 27.338 + 27.339 +<para>If your diff viewing command can't deal with directories, you can 27.340 +easily work around this with a little scripting. For an example of 27.341 +such scripting in action with the <literal role="hg-ext">mq</literal> extension and the 27.342 +<command>interdiff</command> command, see 27.343 +section <xref linkend="mq-collab:tips:interdiff"/>. 27.344 +</para> 27.345 + 27.346 +<sect2> 27.347 +<title>Defining command aliases</title> 27.348 + 27.349 +<para>It can be cumbersome to remember the options to both the 27.350 +<command role="hg-ext-extdiff">extdiff</command> command and the diff viewer you want to use, 27.351 +so the <literal role="hg-ext">extdiff</literal> extension lets you define <emphasis>new</emphasis> commands 27.352 +that will invoke your diff viewer with exactly the right options. 27.353 +</para> 27.354 + 27.355 +<para>All you need to do is edit your <filename role="special"> /.hgrc</filename>, and add a section named 27.356 +<literal role="rc-extdiff">extdiff</literal>. Inside this section, you can define multiple 27.357 +commands. Here's how to add a <literal>kdiff3</literal> command. Once you've 27.358 +defined this, you can type <quote><literal>hg kdiff3</literal></quote> and the 27.359 +<literal role="hg-ext">extdiff</literal> extension will run <command>kdiff3</command> for you. 27.360 +</para> 27.361 +<programlisting> 27.362 +<para> [extdiff] 27.363 + cmd.kdiff3 = 27.364 +</para> 27.365 +</programlisting> 27.366 +<para>If you leave the right hand side of the definition empty, as above, 27.367 +the <literal role="hg-ext">extdiff</literal> extension uses the name of the command you defined 27.368 +as the name of the external program to run. But these names don't 27.369 +have to be the same. Here, we define a command named <quote>\texttt{hg 27.370 + wibble}</quote>, which runs <command>kdiff3</command>. 27.371 +</para> 27.372 +<programlisting> 27.373 +<para> [extdiff] 27.374 + cmd.wibble = kdiff3 27.375 +</para> 27.376 +</programlisting> 27.377 + 27.378 +<para>You can also specify the default options that you want to invoke your 27.379 +diff viewing program with. The prefix to use is <quote><literal>opts.</literal></quote>, 27.380 +followed by the name of the command to which the options apply. This 27.381 +example defines a <quote><literal>hg vimdiff</literal></quote> command that runs the 27.382 +<command>vim</command> editor's <literal>DirDiff</literal> extension. 27.383 +</para> 27.384 +<programlisting> 27.385 +<para> [extdiff] 27.386 + cmd.vimdiff = vim 27.387 + opts.vimdiff = -f '+next' '+execute "DirDiff" argv(0) argv(1)' 27.388 +</para> 27.389 +</programlisting> 27.390 + 27.391 +</sect2> 27.392 +</sect1> 27.393 +<sect1> 27.394 +<title>Cherrypicking changes with the <literal role="hg-ext">transplant</literal> extension</title> 27.395 +<para>\label{sec:hgext:transplant} 27.396 +</para> 27.397 + 27.398 +<para>Need to have a long chat with Brendan about this. 27.399 +</para> 27.400 + 27.401 +</sect1> 27.402 +<sect1> 27.403 +<title>Send changes via email with the <literal role="hg-ext">patchbomb</literal> extension</title> 27.404 +<para>\label{sec:hgext:patchbomb} 27.405 +</para> 27.406 + 27.407 +<para>Many projects have a culture of <quote>change review</quote>, in which people 27.408 +send their modifications to a mailing list for others to read and 27.409 +comment on before they commit the final version to a shared 27.410 +repository. Some projects have people who act as gatekeepers; they 27.411 +apply changes from other people to a repository to which those others 27.412 +don't have access. 27.413 +</para> 27.414 + 27.415 +<para>Mercurial makes it easy to send changes over email for review or 27.416 +application, via its <literal role="hg-ext">patchbomb</literal> extension. The extension is so 27.417 +namd because changes are formatted as patches, and it's usual to send 27.418 +one changeset per email message. Sending a long series of changes by 27.419 +email is thus much like <quote>bombing</quote> the recipient's inbox, hence 27.420 +<quote>patchbomb</quote>. 27.421 +</para> 27.422 + 27.423 +<para>As usual, the basic configuration of the <literal role="hg-ext">patchbomb</literal> extension 27.424 +takes just one or two lines in your <filename role="special"> /.hgrc</filename>. 27.425 +</para> 27.426 +<programlisting> 27.427 +<para> [extensions] 27.428 + patchbomb = 27.429 +</para> 27.430 +</programlisting> 27.431 +<para>Once you've enabled the extension, you will have a new command 27.432 +available, named <command role="hg-ext-patchbomb">email</command>. 27.433 +</para> 27.434 + 27.435 +<para>The safest and best way to invoke the <command role="hg-ext-patchbomb">email</command> 27.436 +command is to <emphasis>always</emphasis> run it first with the 27.437 +<option role="hg-ext-patchbomb-cmd-email-opt">-n</option> option. This will show you what the 27.438 +command <emphasis>would</emphasis> send, without actually sending anything. Once 27.439 +you've had a quick glance over the changes and verified that you are 27.440 +sending the right ones, you can rerun the same command, with the 27.441 +<option role="hg-ext-patchbomb-cmd-email-opt">-n</option> option removed. 27.442 +</para> 27.443 + 27.444 +<para>The <command role="hg-ext-patchbomb">email</command> command accepts the same kind of 27.445 +revision syntax as every other Mercurial command. For example, this 27.446 +command will send every revision between 7 and <literal>tip</literal>, 27.447 +inclusive. 27.448 +</para> 27.449 +<programlisting> 27.450 +<para> hg email -n 7:tip 27.451 +</para> 27.452 +</programlisting> 27.453 +<para>You can also specify a <emphasis>repository</emphasis> to compare with. If you 27.454 +provide a repository but no revisions, the <command role="hg-ext-patchbomb">email</command> 27.455 +command will send all revisions in the local repository that are not 27.456 +present in the remote repository. If you additionally specify 27.457 +revisions or a branch name (the latter using the 27.458 +<option role="hg-ext-patchbomb-cmd-email-opt">-b</option> option), this will constrain the 27.459 +revisions sent. 27.460 +</para> 27.461 + 27.462 +<para>It's perfectly safe to run the <command role="hg-ext-patchbomb">email</command> command 27.463 +without the names of the people you want to send to: if you do this, 27.464 +it will just prompt you for those values interactively. (If you're 27.465 +using a Linux or Unix-like system, you should have enhanced 27.466 +<literal>readline</literal>-style editing capabilities when entering those 27.467 +headers, too, which is useful.) 27.468 +</para> 27.469 + 27.470 +<para>When you are sending just one revision, the <command role="hg-ext-patchbomb">email</command> 27.471 +command will by default use the first line of the changeset 27.472 +description as the subject of the single email message it sends. 27.473 +</para> 27.474 + 27.475 +<para>If you send multiple revisions, the <command role="hg-ext-patchbomb">email</command> command 27.476 +will usually send one message per changeset. It will preface the 27.477 +series with an introductory message, in which you should describe the 27.478 +purpose of the series of changes you're sending. 27.479 +</para> 27.480 + 27.481 +<sect2> 27.482 +<title>Changing the behaviour of patchbombs</title> 27.483 + 27.484 +<para>Not every project has exactly the same conventions for sending changes 27.485 +in email; the <literal role="hg-ext">patchbomb</literal> extension tries to accommodate a 27.486 +number of variations through command line options. 27.487 +</para> 27.488 +<itemizedlist> 27.489 +<listitem><para>You can write a subject for the introductory message on the 27.490 + command line using the <option role="hg-ext-patchbomb-cmd-email-opt">-s</option> option. This 27.491 + takes one argument, the text of the subject to use. 27.492 +</para> 27.493 +</listitem> 27.494 +<listitem><para>To change the email address from which the messages originate, 27.495 + use the <option role="hg-ext-patchbomb-cmd-email-opt">-f</option> option. This takes one 27.496 + argument, the email address to use. 27.497 +</para> 27.498 +</listitem> 27.499 +<listitem><para>The default behaviour is to send unified diffs (see 27.500 + section <xref linkend="sec:mq:patch"/> for a description of the format), one per 27.501 + message. You can send a binary bundle instead with the 27.502 + <option role="hg-ext-patchbomb-cmd-email-opt">-b</option> option. 27.503 +</para> 27.504 +</listitem> 27.505 +<listitem><para>Unified diffs are normally prefaced with a metadata header. You 27.506 + can omit this, and send unadorned diffs, with the 27.507 + <option role="hg-ext-patchbomb-cmd-email-opt">--plain</option> option. 27.508 +</para> 27.509 +</listitem> 27.510 +<listitem><para>Diffs are normally sent <quote>inline</quote>, in the same body part as the 27.511 + description of a patch. This makes it easiest for the largest 27.512 + number of readers to quote and respond to parts of a diff, as some 27.513 + mail clients will only quote the first MIME body part in a message. 27.514 + If you'd prefer to send the description and the diff in separate 27.515 + body parts, use the <option role="hg-ext-patchbomb-cmd-email-opt">-a</option> option. 27.516 +</para> 27.517 +</listitem> 27.518 +<listitem><para>Instead of sending mail messages, you can write them to an 27.519 + <literal>mbox</literal>-format mail folder using the 27.520 + <option role="hg-ext-patchbomb-cmd-email-opt">-m</option> option. That option takes one 27.521 + argument, the name of the file to write to. 27.522 +</para> 27.523 +</listitem> 27.524 +<listitem><para>If you would like to add a <command>diffstat</command>-format summary to 27.525 + each patch, and one to the introductory message, use the 27.526 + <option role="hg-ext-patchbomb-cmd-email-opt">-d</option> option. The <command>diffstat</command> 27.527 + command displays a table containing the name of each file patched, 27.528 + the number of lines affected, and a histogram showing how much each 27.529 + file is modified. This gives readers a qualitative glance at how 27.530 + complex a patch is. 27.531 +</para> 27.532 +</listitem></itemizedlist> 27.533 + 27.534 +</sect2> 27.535 +</sect1> 27.536 +</chapter> 27.537 + 27.538 +<!-- 27.539 +local variables: 27.540 +sgml-parent-document: ("00book.xml" "book" "chapter") 27.541 +end: 27.542 +--> 27.543 \ No newline at end of file
28.1 --- a/fr/cmdref.tex Sun Aug 16 03:41:39 2009 +0200 28.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 28.3 @@ -1,176 +0,0 @@ 28.4 -\chapter{Command reference} 28.5 -\label{cmdref} 28.6 - 28.7 -\cmdref{add}{add files at the next commit} 28.8 -\optref{add}{I}{include} 28.9 -\optref{add}{X}{exclude} 28.10 -\optref{add}{n}{dry-run} 28.11 - 28.12 -\cmdref{diff}{print changes in history or working directory} 28.13 - 28.14 -Show differences between revisions for the specified files or 28.15 -directories, using the unified diff format. For a description of the 28.16 -unified diff format, see section~\ref{sec:mq:patch}. 28.17 - 28.18 -By default, this command does not print diffs for files that Mercurial 28.19 -considers to contain binary data. To control this behaviour, see the 28.20 -\hgopt{diff}{-a} and \hgopt{diff}{--git} options. 28.21 - 28.22 -\subsection{Options} 28.23 - 28.24 -\loptref{diff}{nodates} 28.25 - 28.26 -Omit date and time information when printing diff headers. 28.27 - 28.28 -\optref{diff}{B}{ignore-blank-lines} 28.29 - 28.30 -Do not print changes that only insert or delete blank lines. A line 28.31 -that contains only whitespace is not considered blank. 28.32 - 28.33 -\optref{diff}{I}{include} 28.34 - 28.35 -Include files and directories whose names match the given patterns. 28.36 - 28.37 -\optref{diff}{X}{exclude} 28.38 - 28.39 -Exclude files and directories whose names match the given patterns. 28.40 - 28.41 -\optref{diff}{a}{text} 28.42 - 28.43 -If this option is not specified, \hgcmd{diff} will refuse to print 28.44 -diffs for files that it detects as binary. Specifying \hgopt{diff}{-a} 28.45 -forces \hgcmd{diff} to treat all files as text, and generate diffs for 28.46 -all of them. 28.47 - 28.48 -This option is useful for files that are ``mostly text'' but have a 28.49 -few embedded NUL characters. If you use it on files that contain a 28.50 -lot of binary data, its output will be incomprehensible. 28.51 - 28.52 -\optref{diff}{b}{ignore-space-change} 28.53 - 28.54 -Do not print a line if the only change to that line is in the amount 28.55 -of white space it contains. 28.56 - 28.57 -\optref{diff}{g}{git} 28.58 - 28.59 -Print \command{git}-compatible diffs. XXX reference a format 28.60 -description. 28.61 - 28.62 -\optref{diff}{p}{show-function} 28.63 - 28.64 -Display the name of the enclosing function in a hunk header, using a 28.65 -simple heuristic. This functionality is enabled by default, so the 28.66 -\hgopt{diff}{-p} option has no effect unless you change the value of 28.67 -the \rcitem{diff}{showfunc} config item, as in the following example. 28.68 -\interaction{cmdref.diff-p} 28.69 - 28.70 -\optref{diff}{r}{rev} 28.71 - 28.72 -Specify one or more revisions to compare. The \hgcmd{diff} command 28.73 -accepts up to two \hgopt{diff}{-r} options to specify the revisions to 28.74 -compare. 28.75 - 28.76 -\begin{enumerate} 28.77 -\setcounter{enumi}{0} 28.78 -\item Display the differences between the parent revision of the 28.79 - working directory and the working directory. 28.80 -\item Display the differences between the specified changeset and the 28.81 - working directory. 28.82 -\item Display the differences between the two specified changesets. 28.83 -\end{enumerate} 28.84 - 28.85 -You can specify two revisions using either two \hgopt{diff}{-r} 28.86 -options or revision range notation. For example, the two revision 28.87 -specifications below are equivalent. 28.88 -\begin{codesample2} 28.89 - hg diff -r 10 -r 20 28.90 - hg diff -r10:20 28.91 -\end{codesample2} 28.92 - 28.93 -When you provide two revisions, Mercurial treats the order of those 28.94 -revisions as significant. Thus, \hgcmdargs{diff}{-r10:20} will 28.95 -produce a diff that will transform files from their contents as of 28.96 -revision~10 to their contents as of revision~20, while 28.97 -\hgcmdargs{diff}{-r20:10} means the opposite: the diff that will 28.98 -transform files from their revision~20 contents to their revision~10 28.99 -contents. You cannot reverse the ordering in this way if you are 28.100 -diffing against the working directory. 28.101 - 28.102 -\optref{diff}{w}{ignore-all-space} 28.103 - 28.104 -\cmdref{version}{print version and copyright information} 28.105 - 28.106 -This command displays the version of Mercurial you are running, and 28.107 -its copyright license. There are four kinds of version string that 28.108 -you may see. 28.109 -\begin{itemize} 28.110 -\item The string ``\texttt{unknown}''. This version of Mercurial was 28.111 - not built in a Mercurial repository, and cannot determine its own 28.112 - version. 28.113 -\item A short numeric string, such as ``\texttt{1.1}''. This is a 28.114 - build of a revision of Mercurial that was identified by a specific 28.115 - tag in the repository where it was built. (This doesn't necessarily 28.116 - mean that you're running an official release; someone else could 28.117 - have added that tag to any revision in the repository where they 28.118 - built Mercurial.) 28.119 -\item A hexadecimal string, such as ``\texttt{875489e31abe}''. This 28.120 - is a build of the given revision of Mercurial. 28.121 -\item A hexadecimal string followed by a date, such as 28.122 - ``\texttt{875489e31abe+20070205}''. This is a build of the given 28.123 - revision of Mercurial, where the build repository contained some 28.124 - local changes that had not been committed. 28.125 -\end{itemize} 28.126 - 28.127 -\subsection{Tips and tricks} 28.128 - 28.129 -\subsubsection{Why do the results of \hgcmd{diff} and \hgcmd{status} 28.130 - differ?} 28.131 -\label{cmdref:diff-vs-status} 28.132 - 28.133 -When you run the \hgcmd{status} command, you'll see a list of files 28.134 -that Mercurial will record changes for the next time you perform a 28.135 -commit. If you run the \hgcmd{diff} command, you may notice that it 28.136 -prints diffs for only a \emph{subset} of the files that \hgcmd{status} 28.137 -listed. There are two possible reasons for this. 28.138 - 28.139 -The first is that \hgcmd{status} prints some kinds of modifications 28.140 -that \hgcmd{diff} doesn't normally display. The \hgcmd{diff} command 28.141 -normally outputs unified diffs, which don't have the ability to 28.142 -represent some changes that Mercurial can track. Most notably, 28.143 -traditional diffs can't represent a change in whether or not a file is 28.144 -executable, but Mercurial records this information. 28.145 - 28.146 -If you use the \hgopt{diff}{--git} option to \hgcmd{diff}, it will 28.147 -display \command{git}-compatible diffs that \emph{can} display this 28.148 -extra information. 28.149 - 28.150 -The second possible reason that \hgcmd{diff} might be printing diffs 28.151 -for a subset of the files displayed by \hgcmd{status} is that if you 28.152 -invoke it without any arguments, \hgcmd{diff} prints diffs against the 28.153 -first parent of the working directory. If you have run \hgcmd{merge} 28.154 -to merge two changesets, but you haven't yet committed the results of 28.155 -the merge, your working directory has two parents (use \hgcmd{parents} 28.156 -to see them). While \hgcmd{status} prints modifications relative to 28.157 -\emph{both} parents after an uncommitted merge, \hgcmd{diff} still 28.158 -operates relative only to the first parent. You can get it to print 28.159 -diffs relative to the second parent by specifying that parent with the 28.160 -\hgopt{diff}{-r} option. There is no way to print diffs relative to 28.161 -both parents. 28.162 - 28.163 -\subsubsection{Generating safe binary diffs} 28.164 - 28.165 -If you use the \hgopt{diff}{-a} option to force Mercurial to print 28.166 -diffs of files that are either ``mostly text'' or contain lots of 28.167 -binary data, those diffs cannot subsequently be applied by either 28.168 -Mercurial's \hgcmd{import} command or the system's \command{patch} 28.169 -command. 28.170 - 28.171 -If you want to generate a diff of a binary file that is safe to use as 28.172 -input for \hgcmd{import}, use the \hgcmd{diff}{--git} option when you 28.173 -generate the patch. The system \command{patch} command cannot handle 28.174 -binary patches at all. 28.175 - 28.176 -%%% Local Variables: 28.177 -%%% mode: latex 28.178 -%%% TeX-master: "00book" 28.179 -%%% End:
29.1 --- a/fr/collab.tex Sun Aug 16 03:41:39 2009 +0200 29.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 29.3 @@ -1,1118 +0,0 @@ 29.4 -\chapter{Collaborating with other people} 29.5 -\label{cha:collab} 29.6 - 29.7 -As a completely decentralised tool, Mercurial doesn't impose any 29.8 -policy on how people ought to work with each other. However, if 29.9 -you're new to distributed revision control, it helps to have some 29.10 -tools and examples in mind when you're thinking about possible 29.11 -workflow models. 29.12 - 29.13 -\section{Mercurial's web interface} 29.14 - 29.15 -Mercurial has a powerful web interface that provides several 29.16 -useful capabilities. 29.17 - 29.18 -For interactive use, the web interface lets you browse a single 29.19 -repository or a collection of repositories. You can view the history 29.20 -of a repository, examine each change (comments and diffs), and view 29.21 -the contents of each directory and file. 29.22 - 29.23 -Also for human consumption, the web interface provides an RSS feed of 29.24 -the changes in a repository. This lets you ``subscribe'' to a 29.25 -repository using your favourite feed reader, and be automatically 29.26 -notified of activity in that repository as soon as it happens. I find 29.27 -this capability much more convenient than the model of subscribing to 29.28 -a mailing list to which notifications are sent, as it requires no 29.29 -additional configuration on the part of whoever is serving the 29.30 -repository. 29.31 - 29.32 -The web interface also lets remote users clone a repository, pull 29.33 -changes from it, and (when the server is configured to permit it) push 29.34 -changes back to it. Mercurial's HTTP tunneling protocol aggressively 29.35 -compresses data, so that it works efficiently even over low-bandwidth 29.36 -network connections. 29.37 - 29.38 -The easiest way to get started with the web interface is to use your 29.39 -web browser to visit an existing repository, such as the master 29.40 -Mercurial repository at 29.41 -\url{http://www.selenic.com/repo/hg?style=gitweb}. 29.42 - 29.43 -If you're interested in providing a web interface to your own 29.44 -repositories, Mercurial provides two ways to do this. The first is 29.45 -using the \hgcmd{serve} command, which is best suited to short-term 29.46 -``lightweight'' serving. See section~\ref{sec:collab:serve} below for 29.47 -details of how to use this command. If you have a long-lived 29.48 -repository that you'd like to make permanently available, Mercurial 29.49 -has built-in support for the CGI (Common Gateway Interface) standard, 29.50 -which all common web servers support. See 29.51 -section~\ref{sec:collab:cgi} for details of CGI configuration. 29.52 - 29.53 -\section{Collaboration models} 29.54 - 29.55 -With a suitably flexible tool, making decisions about workflow is much 29.56 -more of a social engineering challenge than a technical one. 29.57 -Mercurial imposes few limitations on how you can structure the flow of 29.58 -work in a project, so it's up to you and your group to set up and live 29.59 -with a model that matches your own particular needs. 29.60 - 29.61 -\subsection{Factors to keep in mind} 29.62 - 29.63 -The most important aspect of any model that you must keep in mind is 29.64 -how well it matches the needs and capabilities of the people who will 29.65 -be using it. This might seem self-evident; even so, you still can't 29.66 -afford to forget it for a moment. 29.67 - 29.68 -I once put together a workflow model that seemed to make perfect sense 29.69 -to me, but that caused a considerable amount of consternation and 29.70 -strife within my development team. In spite of my attempts to explain 29.71 -why we needed a complex set of branches, and how changes ought to flow 29.72 -between them, a few team members revolted. Even though they were 29.73 -smart people, they didn't want to pay attention to the constraints we 29.74 -were operating under, or face the consequences of those constraints in 29.75 -the details of the model that I was advocating. 29.76 - 29.77 -Don't sweep foreseeable social or technical problems under the rug. 29.78 -Whatever scheme you put into effect, you should plan for mistakes and 29.79 -problem scenarios. Consider adding automated machinery to prevent, or 29.80 -quickly recover from, trouble that you can anticipate. As an example, 29.81 -if you intend to have a branch with not-for-release changes in it, 29.82 -you'd do well to think early about the possibility that someone might 29.83 -accidentally merge those changes into a release branch. You could 29.84 -avoid this particular problem by writing a hook that prevents changes 29.85 -from being merged from an inappropriate branch. 29.86 - 29.87 -\subsection{Informal anarchy} 29.88 - 29.89 -I wouldn't suggest an ``anything goes'' approach as something 29.90 -sustainable, but it's a model that's easy to grasp, and it works 29.91 -perfectly well in a few unusual situations. 29.92 - 29.93 -As one example, many projects have a loose-knit group of collaborators 29.94 -who rarely physically meet each other. Some groups like to overcome 29.95 -the isolation of working at a distance by organising occasional 29.96 -``sprints''. In a sprint, a number of people get together in a single 29.97 -location (a company's conference room, a hotel meeting room, that kind 29.98 -of place) and spend several days more or less locked in there, hacking 29.99 -intensely on a handful of projects. 29.100 - 29.101 -A sprint is the perfect place to use the \hgcmd{serve} command, since 29.102 -\hgcmd{serve} does not requires any fancy server infrastructure. You 29.103 -can get started with \hgcmd{serve} in moments, by reading 29.104 -section~\ref{sec:collab:serve} below. Then simply tell the person 29.105 -next to you that you're running a server, send the URL to them in an 29.106 -instant message, and you immediately have a quick-turnaround way to 29.107 -work together. They can type your URL into their web browser and 29.108 -quickly review your changes; or they can pull a bugfix from you and 29.109 -verify it; or they can clone a branch containing a new feature and try 29.110 -it out. 29.111 - 29.112 -The charm, and the problem, with doing things in an ad hoc fashion 29.113 -like this is that only people who know about your changes, and where 29.114 -they are, can see them. Such an informal approach simply doesn't 29.115 -scale beyond a handful people, because each individual needs to know 29.116 -about $n$ different repositories to pull from. 29.117 - 29.118 -\subsection{A single central repository} 29.119 - 29.120 -For smaller projects migrating from a centralised revision control 29.121 -tool, perhaps the easiest way to get started is to have changes flow 29.122 -through a single shared central repository. This is also the 29.123 -most common ``building block'' for more ambitious workflow schemes. 29.124 - 29.125 -Contributors start by cloning a copy of this repository. They can 29.126 -pull changes from it whenever they need to, and some (perhaps all) 29.127 -developers have permission to push a change back when they're ready 29.128 -for other people to see it. 29.129 - 29.130 -Under this model, it can still often make sense for people to pull 29.131 -changes directly from each other, without going through the central 29.132 -repository. Consider a case in which I have a tentative bug fix, but 29.133 -I am worried that if I were to publish it to the central repository, 29.134 -it might subsequently break everyone else's trees as they pull it. To 29.135 -reduce the potential for damage, I can ask you to clone my repository 29.136 -into a temporary repository of your own and test it. This lets us put 29.137 -off publishing the potentially unsafe change until it has had a little 29.138 -testing. 29.139 - 29.140 -In this kind of scenario, people usually use the \command{ssh} 29.141 -protocol to securely push changes to the central repository, as 29.142 -documented in section~\ref{sec:collab:ssh}. It's also usual to 29.143 -publish a read-only copy of the repository over HTTP using CGI, as in 29.144 -section~\ref{sec:collab:cgi}. Publishing over HTTP satisfies the 29.145 -needs of people who don't have push access, and those who want to use 29.146 -web browsers to browse the repository's history. 29.147 - 29.148 -\subsection{Working with multiple branches} 29.149 - 29.150 -Projects of any significant size naturally tend to make progress on 29.151 -several fronts simultaneously. In the case of software, it's common 29.152 -for a project to go through periodic official releases. A release 29.153 -might then go into ``maintenance mode'' for a while after its first 29.154 -publication; maintenance releases tend to contain only bug fixes, not 29.155 -new features. In parallel with these maintenance releases, one or 29.156 -more future releases may be under development. People normally use 29.157 -the word ``branch'' to refer to one of these many slightly different 29.158 -directions in which development is proceeding. 29.159 - 29.160 -Mercurial is particularly well suited to managing a number of 29.161 -simultaneous, but not identical, branches. Each ``development 29.162 -direction'' can live in its own central repository, and you can merge 29.163 -changes from one to another as the need arises. Because repositories 29.164 -are independent of each other, unstable changes in a development 29.165 -branch will never affect a stable branch unless someone explicitly 29.166 -merges those changes in. 29.167 - 29.168 -Here's an example of how this can work in practice. Let's say you 29.169 -have one ``main branch'' on a central server. 29.170 -\interaction{branching.init} 29.171 -People clone it, make changes locally, test them, and push them back. 29.172 - 29.173 -Once the main branch reaches a release milestone, you can use the 29.174 -\hgcmd{tag} command to give a permanent name to the milestone 29.175 -revision. 29.176 -\interaction{branching.tag} 29.177 -Let's say some ongoing development occurs on the main branch. 29.178 -\interaction{branching.main} 29.179 -Using the tag that was recorded at the milestone, people who clone 29.180 -that repository at any time in the future can use \hgcmd{update} to 29.181 -get a copy of the working directory exactly as it was when that tagged 29.182 -revision was committed. 29.183 -\interaction{branching.update} 29.184 - 29.185 -In addition, immediately after the main branch is tagged, someone can 29.186 -then clone the main branch on the server to a new ``stable'' branch, 29.187 -also on the server. 29.188 -\interaction{branching.clone} 29.189 - 29.190 -Someone who needs to make a change to the stable branch can then clone 29.191 -\emph{that} repository, make their changes, commit, and push their 29.192 -changes back there. 29.193 -\interaction{branching.stable} 29.194 -Because Mercurial repositories are independent, and Mercurial doesn't 29.195 -move changes around automatically, the stable and main branches are 29.196 -\emph{isolated} from each other. The changes that you made on the 29.197 -main branch don't ``leak'' to the stable branch, and vice versa. 29.198 - 29.199 -You'll often want all of your bugfixes on the stable branch to show up 29.200 -on the main branch, too. Rather than rewrite a bugfix on the main 29.201 -branch, you can simply pull and merge changes from the stable to the 29.202 -main branch, and Mercurial will bring those bugfixes in for you. 29.203 -\interaction{branching.merge} 29.204 -The main branch will still contain changes that are not on the stable 29.205 -branch, but it will also contain all of the bugfixes from the stable 29.206 -branch. The stable branch remains unaffected by these changes. 29.207 - 29.208 -\subsection{Feature branches} 29.209 - 29.210 -For larger projects, an effective way to manage change is to break up 29.211 -a team into smaller groups. Each group has a shared branch of its 29.212 -own, cloned from a single ``master'' branch used by the entire 29.213 -project. People working on an individual branch are typically quite 29.214 -isolated from developments on other branches. 29.215 - 29.216 -\begin{figure}[ht] 29.217 - \centering 29.218 - \grafix{feature-branches} 29.219 - \caption{Feature branches} 29.220 - \label{fig:collab:feature-branches} 29.221 -\end{figure} 29.222 - 29.223 -When a particular feature is deemed to be in suitable shape, someone 29.224 -on that feature team pulls and merges from the master branch into the 29.225 -feature branch, then pushes back up to the master branch. 29.226 - 29.227 -\subsection{The release train} 29.228 - 29.229 -Some projects are organised on a ``train'' basis: a release is 29.230 -scheduled to happen every few months, and whatever features are ready 29.231 -when the ``train'' is ready to leave are allowed in. 29.232 - 29.233 -This model resembles working with feature branches. The difference is 29.234 -that when a feature branch misses a train, someone on the feature team 29.235 -pulls and merges the changes that went out on that train release into 29.236 -the feature branch, and the team continues its work on top of that 29.237 -release so that their feature can make the next release. 29.238 - 29.239 -\subsection{The Linux kernel model} 29.240 - 29.241 -The development of the Linux kernel has a shallow hierarchical 29.242 -structure, surrounded by a cloud of apparent chaos. Because most 29.243 -Linux developers use \command{git}, a distributed revision control 29.244 -tool with capabilities similar to Mercurial, it's useful to describe 29.245 -the way work flows in that environment; if you like the ideas, the 29.246 -approach translates well across tools. 29.247 - 29.248 -At the center of the community sits Linus Torvalds, the creator of 29.249 -Linux. He publishes a single source repository that is considered the 29.250 -``authoritative'' current tree by the entire developer community. 29.251 -Anyone can clone Linus's tree, but he is very choosy about whose trees 29.252 -he pulls from. 29.253 - 29.254 -Linus has a number of ``trusted lieutenants''. As a general rule, he 29.255 -pulls whatever changes they publish, in most cases without even 29.256 -reviewing those changes. Some of those lieutenants are generally 29.257 -agreed to be ``maintainers'', responsible for specific subsystems 29.258 -within the kernel. If a random kernel hacker wants to make a change 29.259 -to a subsystem that they want to end up in Linus's tree, they must 29.260 -find out who the subsystem's maintainer is, and ask that maintainer to 29.261 -take their change. If the maintainer reviews their changes and agrees 29.262 -to take them, they'll pass them along to Linus in due course. 29.263 - 29.264 -Individual lieutenants have their own approaches to reviewing, 29.265 -accepting, and publishing changes; and for deciding when to feed them 29.266 -to Linus. In addition, there are several well known branches that 29.267 -people use for different purposes. For example, a few people maintain 29.268 -``stable'' repositories of older versions of the kernel, to which they 29.269 -apply critical fixes as needed. Some maintainers publish multiple 29.270 -trees: one for experimental changes; one for changes that they are 29.271 -about to feed upstream; and so on. Others just publish a single 29.272 -tree. 29.273 - 29.274 -This model has two notable features. The first is that it's ``pull 29.275 -only''. You have to ask, convince, or beg another developer to take a 29.276 -change from you, because there are almost no trees to which more than 29.277 -one person can push, and there's no way to push changes into a tree 29.278 -that someone else controls. 29.279 - 29.280 -The second is that it's based on reputation and acclaim. If you're an 29.281 -unknown, Linus will probably ignore changes from you without even 29.282 -responding. But a subsystem maintainer will probably review them, and 29.283 -will likely take them if they pass their criteria for suitability. 29.284 -The more ``good'' changes you contribute to a maintainer, the more 29.285 -likely they are to trust your judgment and accept your changes. If 29.286 -you're well-known and maintain a long-lived branch for something Linus 29.287 -hasn't yet accepted, people with similar interests may pull your 29.288 -changes regularly to keep up with your work. 29.289 - 29.290 -Reputation and acclaim don't necessarily cross subsystem or ``people'' 29.291 -boundaries. If you're a respected but specialised storage hacker, and 29.292 -you try to fix a networking bug, that change will receive a level of 29.293 -scrutiny from a network maintainer comparable to a change from a 29.294 -complete stranger. 29.295 - 29.296 -To people who come from more orderly project backgrounds, the 29.297 -comparatively chaotic Linux kernel development process often seems 29.298 -completely insane. It's subject to the whims of individuals; people 29.299 -make sweeping changes whenever they deem it appropriate; and the pace 29.300 -of development is astounding. And yet Linux is a highly successful, 29.301 -well-regarded piece of software. 29.302 - 29.303 -\subsection{Pull-only versus shared-push collaboration} 29.304 - 29.305 -A perpetual source of heat in the open source community is whether a 29.306 -development model in which people only ever pull changes from others 29.307 -is ``better than'' one in which multiple people can push changes to a 29.308 -shared repository. 29.309 - 29.310 -Typically, the backers of the shared-push model use tools that 29.311 -actively enforce this approach. If you're using a centralised 29.312 -revision control tool such as Subversion, there's no way to make a 29.313 -choice over which model you'll use: the tool gives you shared-push, 29.314 -and if you want to do anything else, you'll have to roll your own 29.315 -approach on top (such as applying a patch by hand). 29.316 - 29.317 -A good distributed revision control tool, such as Mercurial, will 29.318 -support both models. You and your collaborators can then structure 29.319 -how you work together based on your own needs and preferences, not on 29.320 -what contortions your tools force you into. 29.321 - 29.322 -\subsection{Where collaboration meets branch management} 29.323 - 29.324 -Once you and your team set up some shared repositories and start 29.325 -propagating changes back and forth between local and shared repos, you 29.326 -begin to face a related, but slightly different challenge: that of 29.327 -managing the multiple directions in which your team may be moving at 29.328 -once. Even though this subject is intimately related to how your team 29.329 -collaborates, it's dense enough to merit treatment of its own, in 29.330 -chapter~\ref{chap:branch}. 29.331 - 29.332 -\section{The technical side of sharing} 29.333 - 29.334 -The remainder of this chapter is devoted to the question of serving 29.335 -data to your collaborators. 29.336 - 29.337 -\section{Informal sharing with \hgcmd{serve}} 29.338 -\label{sec:collab:serve} 29.339 - 29.340 -Mercurial's \hgcmd{serve} command is wonderfully suited to small, 29.341 -tight-knit, and fast-paced group environments. It also provides a 29.342 -great way to get a feel for using Mercurial commands over a network. 29.343 - 29.344 -Run \hgcmd{serve} inside a repository, and in under a second it will 29.345 -bring up a specialised HTTP server; this will accept connections from 29.346 -any client, and serve up data for that repository until you terminate 29.347 -it. Anyone who knows the URL of the server you just started, and can 29.348 -talk to your computer over the network, can then use a web browser or 29.349 -Mercurial to read data from that repository. A URL for a 29.350 -\hgcmd{serve} instance running on a laptop is likely to look something 29.351 -like \Verb|http://my-laptop.local:8000/|. 29.352 - 29.353 -The \hgcmd{serve} command is \emph{not} a general-purpose web server. 29.354 -It can do only two things: 29.355 -\begin{itemize} 29.356 -\item Allow people to browse the history of the repository it's 29.357 - serving, from their normal web browsers. 29.358 -\item Speak Mercurial's wire protocol, so that people can 29.359 - \hgcmd{clone} or \hgcmd{pull} changes from that repository. 29.360 -\end{itemize} 29.361 -In particular, \hgcmd{serve} won't allow remote users to \emph{modify} 29.362 -your repository. It's intended for read-only use. 29.363 - 29.364 -If you're getting started with Mercurial, there's nothing to prevent 29.365 -you from using \hgcmd{serve} to serve up a repository on your own 29.366 -computer, then use commands like \hgcmd{clone}, \hgcmd{incoming}, and 29.367 -so on to talk to that server as if the repository was hosted remotely. 29.368 -This can help you to quickly get acquainted with using commands on 29.369 -network-hosted repositories. 29.370 - 29.371 -\subsection{A few things to keep in mind} 29.372 - 29.373 -Because it provides unauthenticated read access to all clients, you 29.374 -should only use \hgcmd{serve} in an environment where you either don't 29.375 -care, or have complete control over, who can access your network and 29.376 -pull data from your repository. 29.377 - 29.378 -The \hgcmd{serve} command knows nothing about any firewall software 29.379 -you might have installed on your system or network. It cannot detect 29.380 -or control your firewall software. If other people are unable to talk 29.381 -to a running \hgcmd{serve} instance, the second thing you should do 29.382 -(\emph{after} you make sure that they're using the correct URL) is 29.383 -check your firewall configuration. 29.384 - 29.385 -By default, \hgcmd{serve} listens for incoming connections on 29.386 -port~8000. If another process is already listening on the port you 29.387 -want to use, you can specify a different port to listen on using the 29.388 -\hgopt{serve}{-p} option. 29.389 - 29.390 -Normally, when \hgcmd{serve} starts, it prints no output, which can be 29.391 -a bit unnerving. If you'd like to confirm that it is indeed running 29.392 -correctly, and find out what URL you should send to your 29.393 -collaborators, start it with the \hggopt{-v} option. 29.394 - 29.395 -\section{Using the Secure Shell (ssh) protocol} 29.396 -\label{sec:collab:ssh} 29.397 - 29.398 -You can pull and push changes securely over a network connection using 29.399 -the Secure Shell (\texttt{ssh}) protocol. To use this successfully, 29.400 -you may have to do a little bit of configuration on the client or 29.401 -server sides. 29.402 - 29.403 -If you're not familiar with ssh, it's a network protocol that lets you 29.404 -securely communicate with another computer. To use it with Mercurial, 29.405 -you'll be setting up one or more user accounts on a server so that 29.406 -remote users can log in and execute commands. 29.407 - 29.408 -(If you \emph{are} familiar with ssh, you'll probably find some of the 29.409 -material that follows to be elementary in nature.) 29.410 - 29.411 -\subsection{How to read and write ssh URLs} 29.412 - 29.413 -An ssh URL tends to look like this: 29.414 -\begin{codesample2} 29.415 - ssh://bos@hg.serpentine.com:22/hg/hgbook 29.416 -\end{codesample2} 29.417 -\begin{enumerate} 29.418 -\item The ``\texttt{ssh://}'' part tells Mercurial to use the ssh 29.419 - protocol. 29.420 -\item The ``\texttt{bos@}'' component indicates what username to log 29.421 - into the server as. You can leave this out if the remote username 29.422 - is the same as your local username. 29.423 -\item The ``\texttt{hg.serpentine.com}'' gives the hostname of the 29.424 - server to log into. 29.425 -\item The ``:22'' identifies the port number to connect to the server 29.426 - on. The default port is~22, so you only need to specify this part 29.427 - if you're \emph{not} using port~22. 29.428 -\item The remainder of the URL is the local path to the repository on 29.429 - the server. 29.430 -\end{enumerate} 29.431 - 29.432 -There's plenty of scope for confusion with the path component of ssh 29.433 -URLs, as there is no standard way for tools to interpret it. Some 29.434 -programs behave differently than others when dealing with these paths. 29.435 -This isn't an ideal situation, but it's unlikely to change. Please 29.436 -read the following paragraphs carefully. 29.437 - 29.438 -Mercurial treats the path to a repository on the server as relative to 29.439 -the remote user's home directory. For example, if user \texttt{foo} 29.440 -on the server has a home directory of \dirname{/home/foo}, then an ssh 29.441 -URL that contains a path component of \dirname{bar} 29.442 -\emph{really} refers to the directory \dirname{/home/foo/bar}. 29.443 - 29.444 -If you want to specify a path relative to another user's home 29.445 -directory, you can use a path that starts with a tilde character 29.446 -followed by the user's name (let's call them \texttt{otheruser}), like 29.447 -this. 29.448 -\begin{codesample2} 29.449 - ssh://server/~otheruser/hg/repo 29.450 -\end{codesample2} 29.451 - 29.452 -And if you really want to specify an \emph{absolute} path on the 29.453 -server, begin the path component with two slashes, as in this example. 29.454 -\begin{codesample2} 29.455 - ssh://server//absolute/path 29.456 -\end{codesample2} 29.457 - 29.458 -\subsection{Finding an ssh client for your system} 29.459 - 29.460 -Almost every Unix-like system comes with OpenSSH preinstalled. If 29.461 -you're using such a system, run \Verb|which ssh| to find out if 29.462 -the \command{ssh} command is installed (it's usually in 29.463 -\dirname{/usr/bin}). In the unlikely event that it isn't present, 29.464 -take a look at your system documentation to figure out how to install 29.465 -it. 29.466 - 29.467 -On Windows, you'll first need to download a suitable ssh 29.468 -client. There are two alternatives. 29.469 -\begin{itemize} 29.470 -\item Simon Tatham's excellent PuTTY package~\cite{web:putty} provides 29.471 - a complete suite of ssh client commands. 29.472 -\item If you have a high tolerance for pain, you can use the Cygwin 29.473 - port of OpenSSH. 29.474 -\end{itemize} 29.475 -In either case, you'll need to edit your \hgini\ file to tell 29.476 -Mercurial where to find the actual client command. For example, if 29.477 -you're using PuTTY, you'll need to use the \command{plink} command as 29.478 -a command-line ssh client. 29.479 -\begin{codesample2} 29.480 - [ui] 29.481 - ssh = C:/path/to/plink.exe -ssh -i "C:/path/to/my/private/key" 29.482 -\end{codesample2} 29.483 - 29.484 -\begin{note} 29.485 - The path to \command{plink} shouldn't contain any whitespace 29.486 - characters, or Mercurial may not be able to run it correctly (so 29.487 - putting it in \dirname{C:\\Program Files} is probably not a good 29.488 - idea). 29.489 -\end{note} 29.490 - 29.491 -\subsection{Generating a key pair} 29.492 - 29.493 -To avoid the need to repetitively type a password every time you need 29.494 -to use your ssh client, I recommend generating a key pair. On a 29.495 -Unix-like system, the \command{ssh-keygen} command will do the trick. 29.496 -On Windows, if you're using PuTTY, the \command{puttygen} command is 29.497 -what you'll need. 29.498 - 29.499 -When you generate a key pair, it's usually \emph{highly} advisable to 29.500 -protect it with a passphrase. (The only time that you might not want 29.501 -to do this is when you're using the ssh protocol for automated tasks 29.502 -on a secure network.) 29.503 - 29.504 -Simply generating a key pair isn't enough, however. You'll need to 29.505 -add the public key to the set of authorised keys for whatever user 29.506 -you're logging in remotely as. For servers using OpenSSH (the vast 29.507 -majority), this will mean adding the public key to a list in a file 29.508 -called \sfilename{authorized\_keys} in their \sdirname{.ssh} 29.509 -directory. 29.510 - 29.511 -On a Unix-like system, your public key will have a \filename{.pub} 29.512 -extension. If you're using \command{puttygen} on Windows, you can 29.513 -save the public key to a file of your choosing, or paste it from the 29.514 -window it's displayed in straight into the 29.515 -\sfilename{authorized\_keys} file. 29.516 - 29.517 -\subsection{Using an authentication agent} 29.518 - 29.519 -An authentication agent is a daemon that stores passphrases in memory 29.520 -(so it will forget passphrases if you log out and log back in again). 29.521 -An ssh client will notice if it's running, and query it for a 29.522 -passphrase. If there's no authentication agent running, or the agent 29.523 -doesn't store the necessary passphrase, you'll have to type your 29.524 -passphrase every time Mercurial tries to communicate with a server on 29.525 -your behalf (e.g.~whenever you pull or push changes). 29.526 - 29.527 -The downside of storing passphrases in an agent is that it's possible 29.528 -for a well-prepared attacker to recover the plain text of your 29.529 -passphrases, in some cases even if your system has been power-cycled. 29.530 -You should make your own judgment as to whether this is an acceptable 29.531 -risk. It certainly saves a lot of repeated typing. 29.532 - 29.533 -On Unix-like systems, the agent is called \command{ssh-agent}, and 29.534 -it's often run automatically for you when you log in. You'll need to 29.535 -use the \command{ssh-add} command to add passphrases to the agent's 29.536 -store. On Windows, if you're using PuTTY, the \command{pageant} 29.537 -command acts as the agent. It adds an icon to your system tray that 29.538 -will let you manage stored passphrases. 29.539 - 29.540 -\subsection{Configuring the server side properly} 29.541 - 29.542 -Because ssh can be fiddly to set up if you're new to it, there's a 29.543 -variety of things that can go wrong. Add Mercurial on top, and 29.544 -there's plenty more scope for head-scratching. Most of these 29.545 -potential problems occur on the server side, not the client side. The 29.546 -good news is that once you've gotten a configuration working, it will 29.547 -usually continue to work indefinitely. 29.548 - 29.549 -Before you try using Mercurial to talk to an ssh server, it's best to 29.550 -make sure that you can use the normal \command{ssh} or \command{putty} 29.551 -command to talk to the server first. If you run into problems with 29.552 -using these commands directly, Mercurial surely won't work. Worse, it 29.553 -will obscure the underlying problem. Any time you want to debug 29.554 -ssh-related Mercurial problems, you should drop back to making sure 29.555 -that plain ssh client commands work first, \emph{before} you worry 29.556 -about whether there's a problem with Mercurial. 29.557 - 29.558 -The first thing to be sure of on the server side is that you can 29.559 -actually log in from another machine at all. If you can't use 29.560 -\command{ssh} or \command{putty} to log in, the error message you get 29.561 -may give you a few hints as to what's wrong. The most common problems 29.562 -are as follows. 29.563 -\begin{itemize} 29.564 -\item If you get a ``connection refused'' error, either there isn't an 29.565 - SSH daemon running on the server at all, or it's inaccessible due to 29.566 - firewall configuration. 29.567 -\item If you get a ``no route to host'' error, you either have an 29.568 - incorrect address for the server or a seriously locked down firewall 29.569 - that won't admit its existence at all. 29.570 -\item If you get a ``permission denied'' error, you may have mistyped 29.571 - the username on the server, or you could have mistyped your key's 29.572 - passphrase or the remote user's password. 29.573 -\end{itemize} 29.574 -In summary, if you're having trouble talking to the server's ssh 29.575 -daemon, first make sure that one is running at all. On many systems 29.576 -it will be installed, but disabled, by default. Once you're done with 29.577 -this step, you should then check that the server's firewall is 29.578 -configured to allow incoming connections on the port the ssh daemon is 29.579 -listening on (usually~22). Don't worry about more exotic 29.580 -possibilities for misconfiguration until you've checked these two 29.581 -first. 29.582 - 29.583 -If you're using an authentication agent on the client side to store 29.584 -passphrases for your keys, you ought to be able to log into the server 29.585 -without being prompted for a passphrase or a password. If you're 29.586 -prompted for a passphrase, there are a few possible culprits. 29.587 -\begin{itemize} 29.588 -\item You might have forgotten to use \command{ssh-add} or 29.589 - \command{pageant} to store the passphrase. 29.590 -\item You might have stored the passphrase for the wrong key. 29.591 -\end{itemize} 29.592 -If you're being prompted for the remote user's password, there are 29.593 -another few possible problems to check. 29.594 -\begin{itemize} 29.595 -\item Either the user's home directory or their \sdirname{.ssh} 29.596 - directory might have excessively liberal permissions. As a result, 29.597 - the ssh daemon will not trust or read their 29.598 - \sfilename{authorized\_keys} file. For example, a group-writable 29.599 - home or \sdirname{.ssh} directory will often cause this symptom. 29.600 -\item The user's \sfilename{authorized\_keys} file may have a problem. 29.601 - If anyone other than the user owns or can write to that file, the 29.602 - ssh daemon will not trust or read it. 29.603 -\end{itemize} 29.604 - 29.605 -In the ideal world, you should be able to run the following command 29.606 -successfully, and it should print exactly one line of output, the 29.607 -current date and time. 29.608 -\begin{codesample2} 29.609 - ssh myserver date 29.610 -\end{codesample2} 29.611 - 29.612 -If, on your server, you have login scripts that print banners or other 29.613 -junk even when running non-interactive commands like this, you should 29.614 -fix them before you continue, so that they only print output if 29.615 -they're run interactively. Otherwise these banners will at least 29.616 -clutter up Mercurial's output. Worse, they could potentially cause 29.617 -problems with running Mercurial commands remotely. Mercurial makes 29.618 -tries to detect and ignore banners in non-interactive \command{ssh} 29.619 -sessions, but it is not foolproof. (If you're editing your login 29.620 -scripts on your server, the usual way to see if a login script is 29.621 -running in an interactive shell is to check the return code from the 29.622 -command \Verb|tty -s|.) 29.623 - 29.624 -Once you've verified that plain old ssh is working with your server, 29.625 -the next step is to ensure that Mercurial runs on the server. The 29.626 -following command should run successfully: 29.627 -\begin{codesample2} 29.628 - ssh myserver hg version 29.629 -\end{codesample2} 29.630 -If you see an error message instead of normal \hgcmd{version} output, 29.631 -this is usually because you haven't installed Mercurial to 29.632 -\dirname{/usr/bin}. Don't worry if this is the case; you don't need 29.633 -to do that. But you should check for a few possible problems. 29.634 -\begin{itemize} 29.635 -\item Is Mercurial really installed on the server at all? I know this 29.636 - sounds trivial, but it's worth checking! 29.637 -\item Maybe your shell's search path (usually set via the \envar{PATH} 29.638 - environment variable) is simply misconfigured. 29.639 -\item Perhaps your \envar{PATH} environment variable is only being set 29.640 - to point to the location of the \command{hg} executable if the login 29.641 - session is interactive. This can happen if you're setting the path 29.642 - in the wrong shell login script. See your shell's documentation for 29.643 - details. 29.644 -\item The \envar{PYTHONPATH} environment variable may need to contain 29.645 - the path to the Mercurial Python modules. It might not be set at 29.646 - all; it could be incorrect; or it may be set only if the login is 29.647 - interactive. 29.648 -\end{itemize} 29.649 - 29.650 -If you can run \hgcmd{version} over an ssh connection, well done! 29.651 -You've got the server and client sorted out. You should now be able 29.652 -to use Mercurial to access repositories hosted by that username on 29.653 -that server. If you run into problems with Mercurial and ssh at this 29.654 -point, try using the \hggopt{--debug} option to get a clearer picture 29.655 -of what's going on. 29.656 - 29.657 -\subsection{Using compression with ssh} 29.658 - 29.659 -Mercurial does not compress data when it uses the ssh protocol, 29.660 -because the ssh protocol can transparently compress data. However, 29.661 -the default behaviour of ssh clients is \emph{not} to request 29.662 -compression. 29.663 - 29.664 -Over any network other than a fast LAN (even a wireless network), 29.665 -using compression is likely to significantly speed up Mercurial's 29.666 -network operations. For example, over a WAN, someone measured 29.667 -compression as reducing the amount of time required to clone a 29.668 -particularly large repository from~51 minutes to~17 minutes. 29.669 - 29.670 -Both \command{ssh} and \command{plink} accept a \cmdopt{ssh}{-C} 29.671 -option which turns on compression. You can easily edit your \hgrc\ to 29.672 -enable compression for all of Mercurial's uses of the ssh protocol. 29.673 -\begin{codesample2} 29.674 - [ui] 29.675 - ssh = ssh -C 29.676 -\end{codesample2} 29.677 - 29.678 -If you use \command{ssh}, you can configure it to always use 29.679 -compression when talking to your server. To do this, edit your 29.680 -\sfilename{.ssh/config} file (which may not yet exist), as follows. 29.681 -\begin{codesample2} 29.682 - Host hg 29.683 - Compression yes 29.684 - HostName hg.example.com 29.685 -\end{codesample2} 29.686 -This defines an alias, \texttt{hg}. When you use it on the 29.687 -\command{ssh} command line or in a Mercurial \texttt{ssh}-protocol 29.688 -URL, it will cause \command{ssh} to connect to \texttt{hg.example.com} 29.689 -and use compression. This gives you both a shorter name to type and 29.690 -compression, each of which is a good thing in its own right. 29.691 - 29.692 -\section{Serving over HTTP using CGI} 29.693 -\label{sec:collab:cgi} 29.694 - 29.695 -Depending on how ambitious you are, configuring Mercurial's CGI 29.696 -interface can take anything from a few moments to several hours. 29.697 - 29.698 -We'll begin with the simplest of examples, and work our way towards a 29.699 -more complex configuration. Even for the most basic case, you're 29.700 -almost certainly going to need to read and modify your web server's 29.701 -configuration. 29.702 - 29.703 -\begin{note} 29.704 - Configuring a web server is a complex, fiddly, and highly 29.705 - system-dependent activity. I can't possibly give you instructions 29.706 - that will cover anything like all of the cases you will encounter. 29.707 - Please use your discretion and judgment in following the sections 29.708 - below. Be prepared to make plenty of mistakes, and to spend a lot 29.709 - of time reading your server's error logs. 29.710 -\end{note} 29.711 - 29.712 -\subsection{Web server configuration checklist} 29.713 - 29.714 -Before you continue, do take a few moments to check a few aspects of 29.715 -your system's setup. 29.716 - 29.717 -\begin{enumerate} 29.718 -\item Do you have a web server installed at all? Mac OS X ships with 29.719 - Apache, but many other systems may not have a web server installed. 29.720 -\item If you have a web server installed, is it actually running? On 29.721 - most systems, even if one is present, it will be disabled by 29.722 - default. 29.723 -\item Is your server configured to allow you to run CGI programs in 29.724 - the directory where you plan to do so? Most servers default to 29.725 - explicitly disabling the ability to run CGI programs. 29.726 -\end{enumerate} 29.727 - 29.728 -If you don't have a web server installed, and don't have substantial 29.729 -experience configuring Apache, you should consider using the 29.730 -\texttt{lighttpd} web server instead of Apache. Apache has a 29.731 -well-deserved reputation for baroque and confusing configuration. 29.732 -While \texttt{lighttpd} is less capable in some ways than Apache, most 29.733 -of these capabilities are not relevant to serving Mercurial 29.734 -repositories. And \texttt{lighttpd} is undeniably \emph{much} easier 29.735 -to get started with than Apache. 29.736 - 29.737 -\subsection{Basic CGI configuration} 29.738 - 29.739 -On Unix-like systems, it's common for users to have a subdirectory 29.740 -named something like \dirname{public\_html} in their home directory, 29.741 -from which they can serve up web pages. A file named \filename{foo} 29.742 -in this directory will be accessible at a URL of the form 29.743 -\texttt{http://www.example.com/\~{}username/foo}. 29.744 - 29.745 -To get started, find the \sfilename{hgweb.cgi} script that should be 29.746 -present in your Mercurial installation. If you can't quickly find a 29.747 -local copy on your system, simply download one from the master 29.748 -Mercurial repository at 29.749 -\url{http://www.selenic.com/repo/hg/raw-file/tip/hgweb.cgi}. 29.750 - 29.751 -You'll need to copy this script into your \dirname{public\_html} 29.752 -directory, and ensure that it's executable. 29.753 -\begin{codesample2} 29.754 - cp .../hgweb.cgi ~/public_html 29.755 - chmod 755 ~/public_html/hgweb.cgi 29.756 -\end{codesample2} 29.757 -The \texttt{755} argument to \command{chmod} is a little more general 29.758 -than just making the script executable: it ensures that the script is 29.759 -executable by anyone, and that ``group'' and ``other'' write 29.760 -permissions are \emph{not} set. If you were to leave those write 29.761 -permissions enabled, Apache's \texttt{suexec} subsystem would likely 29.762 -refuse to execute the script. In fact, \texttt{suexec} also insists 29.763 -that the \emph{directory} in which the script resides must not be 29.764 -writable by others. 29.765 -\begin{codesample2} 29.766 - chmod 755 ~/public_html 29.767 -\end{codesample2} 29.768 - 29.769 -\subsubsection{What could \emph{possibly} go wrong?} 29.770 -\label{sec:collab:wtf} 29.771 - 29.772 -Once you've copied the CGI script into place, go into a web browser, 29.773 -and try to open the URL \url{http://myhostname/~myuser/hgweb.cgi}, 29.774 -\emph{but} brace yourself for instant failure. There's a high 29.775 -probability that trying to visit this URL will fail, and there are 29.776 -many possible reasons for this. In fact, you're likely to stumble 29.777 -over almost every one of the possible errors below, so please read 29.778 -carefully. The following are all of the problems I ran into on a 29.779 -system running Fedora~7, with a fresh installation of Apache, and a 29.780 -user account that I created specially to perform this exercise. 29.781 - 29.782 -Your web server may have per-user directories disabled. If you're 29.783 -using Apache, search your config file for a \texttt{UserDir} 29.784 -directive. If there's none present, per-user directories will be 29.785 -disabled. If one exists, but its value is \texttt{disabled}, then 29.786 -per-user directories will be disabled. Otherwise, the string after 29.787 -\texttt{UserDir} gives the name of the subdirectory that Apache will 29.788 -look in under your home directory, for example \dirname{public\_html}. 29.789 - 29.790 -Your file access permissions may be too restrictive. The web server 29.791 -must be able to traverse your home directory and directories under 29.792 -your \dirname{public\_html} directory, and read files under the latter 29.793 -too. Here's a quick recipe to help you to make your permissions more 29.794 -appropriate. 29.795 -\begin{codesample2} 29.796 - chmod 755 ~ 29.797 - find ~/public_html -type d -print0 | xargs -0r chmod 755 29.798 - find ~/public_html -type f -print0 | xargs -0r chmod 644 29.799 -\end{codesample2} 29.800 - 29.801 -The other possibility with permissions is that you might get a 29.802 -completely empty window when you try to load the script. In this 29.803 -case, it's likely that your access permissions are \emph{too 29.804 - permissive}. Apache's \texttt{suexec} subsystem won't execute a 29.805 -script that's group-~or world-writable, for example. 29.806 - 29.807 -Your web server may be configured to disallow execution of CGI 29.808 -programs in your per-user web directory. Here's Apache's 29.809 -default per-user configuration from my Fedora system. 29.810 -\begin{codesample2} 29.811 - <Directory /home/*/public_html> 29.812 - AllowOverride FileInfo AuthConfig Limit 29.813 - Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec 29.814 - <Limit GET POST OPTIONS> 29.815 - Order allow,deny 29.816 - Allow from all 29.817 - </Limit> 29.818 - <LimitExcept GET POST OPTIONS> 29.819 - Order deny,allow 29.820 - Deny from all 29.821 - </LimitExcept> 29.822 - </Directory> 29.823 -\end{codesample2} 29.824 -If you find a similar-looking \texttt{Directory} group in your Apache 29.825 -configuration, the directive to look at inside it is \texttt{Options}. 29.826 -Add \texttt{ExecCGI} to the end of this list if it's missing, and 29.827 -restart the web server. 29.828 - 29.829 -If you find that Apache serves you the text of the CGI script instead 29.830 -of executing it, you may need to either uncomment (if already present) 29.831 -or add a directive like this. 29.832 -\begin{codesample2} 29.833 - AddHandler cgi-script .cgi 29.834 -\end{codesample2} 29.835 - 29.836 -The next possibility is that you might be served with a colourful 29.837 -Python backtrace claiming that it can't import a 29.838 -\texttt{mercurial}-related module. This is actually progress! The 29.839 -server is now capable of executing your CGI script. This error is 29.840 -only likely to occur if you're running a private installation of 29.841 -Mercurial, instead of a system-wide version. Remember that the web 29.842 -server runs the CGI program without any of the environment variables 29.843 -that you take for granted in an interactive session. If this error 29.844 -happens to you, edit your copy of \sfilename{hgweb.cgi} and follow the 29.845 -directions inside it to correctly set your \envar{PYTHONPATH} 29.846 -environment variable. 29.847 - 29.848 -Finally, you are \emph{certain} to by served with another colourful 29.849 -Python backtrace: this one will complain that it can't find 29.850 -\dirname{/path/to/repository}. Edit your \sfilename{hgweb.cgi} script 29.851 -and replace the \dirname{/path/to/repository} string with the complete 29.852 -path to the repository you want to serve up. 29.853 - 29.854 -At this point, when you try to reload the page, you should be 29.855 -presented with a nice HTML view of your repository's history. Whew! 29.856 - 29.857 -\subsubsection{Configuring lighttpd} 29.858 - 29.859 -To be exhaustive in my experiments, I tried configuring the 29.860 -increasingly popular \texttt{lighttpd} web server to serve the same 29.861 -repository as I described with Apache above. I had already overcome 29.862 -all of the problems I outlined with Apache, many of which are not 29.863 -server-specific. As a result, I was fairly sure that my file and 29.864 -directory permissions were good, and that my \sfilename{hgweb.cgi} 29.865 -script was properly edited. 29.866 - 29.867 -Once I had Apache running, getting \texttt{lighttpd} to serve the 29.868 -repository was a snap (in other words, even if you're trying to use 29.869 -\texttt{lighttpd}, you should read the Apache section). I first had 29.870 -to edit the \texttt{mod\_access} section of its config file to enable 29.871 -\texttt{mod\_cgi} and \texttt{mod\_userdir}, both of which were 29.872 -disabled by default on my system. I then added a few lines to the end 29.873 -of the config file, to configure these modules. 29.874 -\begin{codesample2} 29.875 - userdir.path = "public_html" 29.876 - cgi.assign = ( ".cgi" => "" ) 29.877 -\end{codesample2} 29.878 -With this done, \texttt{lighttpd} ran immediately for me. If I had 29.879 -configured \texttt{lighttpd} before Apache, I'd almost certainly have 29.880 -run into many of the same system-level configuration problems as I did 29.881 -with Apache. However, I found \texttt{lighttpd} to be noticeably 29.882 -easier to configure than Apache, even though I've used Apache for over 29.883 -a decade, and this was my first exposure to \texttt{lighttpd}. 29.884 - 29.885 -\subsection{Sharing multiple repositories with one CGI script} 29.886 - 29.887 -The \sfilename{hgweb.cgi} script only lets you publish a single 29.888 -repository, which is an annoying restriction. If you want to publish 29.889 -more than one without wracking yourself with multiple copies of the 29.890 -same script, each with different names, a better choice is to use the 29.891 -\sfilename{hgwebdir.cgi} script. 29.892 - 29.893 -The procedure to configure \sfilename{hgwebdir.cgi} is only a little 29.894 -more involved than for \sfilename{hgweb.cgi}. First, you must obtain 29.895 -a copy of the script. If you don't have one handy, you can download a 29.896 -copy from the master Mercurial repository at 29.897 -\url{http://www.selenic.com/repo/hg/raw-file/tip/hgwebdir.cgi}. 29.898 - 29.899 -You'll need to copy this script into your \dirname{public\_html} 29.900 -directory, and ensure that it's executable. 29.901 -\begin{codesample2} 29.902 - cp .../hgwebdir.cgi ~/public_html 29.903 - chmod 755 ~/public_html ~/public_html/hgwebdir.cgi 29.904 -\end{codesample2} 29.905 -With basic configuration out of the way, try to visit 29.906 -\url{http://myhostname/~myuser/hgwebdir.cgi} in your browser. It 29.907 -should display an empty list of repositories. If you get a blank 29.908 -window or error message, try walking through the list of potential 29.909 -problems in section~\ref{sec:collab:wtf}. 29.910 - 29.911 -The \sfilename{hgwebdir.cgi} script relies on an external 29.912 -configuration file. By default, it searches for a file named 29.913 -\sfilename{hgweb.config} in the same directory as itself. You'll need 29.914 -to create this file, and make it world-readable. The format of the 29.915 -file is similar to a Windows ``ini'' file, as understood by Python's 29.916 -\texttt{ConfigParser}~\cite{web:configparser} module. 29.917 - 29.918 -The easiest way to configure \sfilename{hgwebdir.cgi} is with a 29.919 -section named \texttt{collections}. This will automatically publish 29.920 -\emph{every} repository under the directories you name. The section 29.921 -should look like this: 29.922 -\begin{codesample2} 29.923 - [collections] 29.924 - /my/root = /my/root 29.925 -\end{codesample2} 29.926 -Mercurial interprets this by looking at the directory name on the 29.927 -\emph{right} hand side of the ``\texttt{=}'' sign; finding 29.928 -repositories in that directory hierarchy; and using the text on the 29.929 -\emph{left} to strip off matching text from the names it will actually 29.930 -list in the web interface. The remaining component of a path after 29.931 -this stripping has occurred is called a ``virtual path''. 29.932 - 29.933 -Given the example above, if we have a repository whose local path is 29.934 -\dirname{/my/root/this/repo}, the CGI script will strip the leading 29.935 -\dirname{/my/root} from the name, and publish the repository with a 29.936 -virtual path of \dirname{this/repo}. If the base URL for our CGI 29.937 -script is \url{http://myhostname/~myuser/hgwebdir.cgi}, the complete 29.938 -URL for that repository will be 29.939 -\url{http://myhostname/~myuser/hgwebdir.cgi/this/repo}. 29.940 - 29.941 -If we replace \dirname{/my/root} on the left hand side of this example 29.942 -with \dirname{/my}, then \sfilename{hgwebdir.cgi} will only strip off 29.943 -\dirname{/my} from the repository name, and will give us a virtual 29.944 -path of \dirname{root/this/repo} instead of \dirname{this/repo}. 29.945 - 29.946 -The \sfilename{hgwebdir.cgi} script will recursively search each 29.947 -directory listed in the \texttt{collections} section of its 29.948 -configuration file, but it will \texttt{not} recurse into the 29.949 -repositories it finds. 29.950 - 29.951 -The \texttt{collections} mechanism makes it easy to publish many 29.952 -repositories in a ``fire and forget'' manner. You only need to set up 29.953 -the CGI script and configuration file one time. Afterwards, you can 29.954 -publish or unpublish a repository at any time by simply moving it 29.955 -into, or out of, the directory hierarchy in which you've configured 29.956 -\sfilename{hgwebdir.cgi} to look. 29.957 - 29.958 -\subsubsection{Explicitly specifying which repositories to publish} 29.959 - 29.960 -In addition to the \texttt{collections} mechanism, the 29.961 -\sfilename{hgwebdir.cgi} script allows you to publish a specific list 29.962 -of repositories. To do so, create a \texttt{paths} section, with 29.963 -contents of the following form. 29.964 -\begin{codesample2} 29.965 - [paths] 29.966 - repo1 = /my/path/to/some/repo 29.967 - repo2 = /some/path/to/another 29.968 -\end{codesample2} 29.969 -In this case, the virtual path (the component that will appear in a 29.970 -URL) is on the left hand side of each definition, while the path to 29.971 -the repository is on the right. Notice that there does not need to be 29.972 -any relationship between the virtual path you choose and the location 29.973 -of a repository in your filesystem. 29.974 - 29.975 -If you wish, you can use both the \texttt{collections} and 29.976 -\texttt{paths} mechanisms simultaneously in a single configuration 29.977 -file. 29.978 - 29.979 -\begin{note} 29.980 - If multiple repositories have the same virtual path, 29.981 - \sfilename{hgwebdir.cgi} will not report an error. Instead, it will 29.982 - behave unpredictably. 29.983 -\end{note} 29.984 - 29.985 -\subsection{Downloading source archives} 29.986 - 29.987 -Mercurial's web interface lets users download an archive of any 29.988 -revision. This archive will contain a snapshot of the working 29.989 -directory as of that revision, but it will not contain a copy of the 29.990 -repository data. 29.991 - 29.992 -By default, this feature is not enabled. To enable it, you'll need to 29.993 -add an \rcitem{web}{allow\_archive} item to the \rcsection{web} 29.994 -section of your \hgrc. 29.995 - 29.996 -\subsection{Web configuration options} 29.997 - 29.998 -Mercurial's web interfaces (the \hgcmd{serve} command, and the 29.999 -\sfilename{hgweb.cgi} and \sfilename{hgwebdir.cgi} scripts) have a 29.1000 -number of configuration options that you can set. These belong in a 29.1001 -section named \rcsection{web}. 29.1002 -\begin{itemize} 29.1003 -\item[\rcitem{web}{allow\_archive}] Determines which (if any) archive 29.1004 - download mechanisms Mercurial supports. If you enable this 29.1005 - feature, users of the web interface will be able to download an 29.1006 - archive of whatever revision of a repository they are viewing. 29.1007 - To enable the archive feature, this item must take the form of a 29.1008 - sequence of words drawn from the list below. 29.1009 - \begin{itemize} 29.1010 - \item[\texttt{bz2}] A \command{tar} archive, compressed using 29.1011 - \texttt{bzip2} compression. This has the best compression ratio, 29.1012 - but uses the most CPU time on the server. 29.1013 - \item[\texttt{gz}] A \command{tar} archive, compressed using 29.1014 - \texttt{gzip} compression. 29.1015 - \item[\texttt{zip}] A \command{zip} archive, compressed using LZW 29.1016 - compression. This format has the worst compression ratio, but is 29.1017 - widely used in the Windows world. 29.1018 - \end{itemize} 29.1019 - If you provide an empty list, or don't have an 29.1020 - \rcitem{web}{allow\_archive} entry at all, this feature will be 29.1021 - disabled. Here is an example of how to enable all three supported 29.1022 - formats. 29.1023 - \begin{codesample4} 29.1024 - [web] 29.1025 - allow_archive = bz2 gz zip 29.1026 - \end{codesample4} 29.1027 -\item[\rcitem{web}{allowpull}] Boolean. Determines whether the web 29.1028 - interface allows remote users to \hgcmd{pull} and \hgcmd{clone} this 29.1029 - repository over~HTTP. If set to \texttt{no} or \texttt{false}, only 29.1030 - the ``human-oriented'' portion of the web interface is available. 29.1031 -\item[\rcitem{web}{contact}] String. A free-form (but preferably 29.1032 - brief) string identifying the person or group in charge of the 29.1033 - repository. This often contains the name and email address of a 29.1034 - person or mailing list. It often makes sense to place this entry in 29.1035 - a repository's own \sfilename{.hg/hgrc} file, but it can make sense 29.1036 - to use in a global \hgrc\ if every repository has a single 29.1037 - maintainer. 29.1038 -\item[\rcitem{web}{maxchanges}] Integer. The default maximum number 29.1039 - of changesets to display in a single page of output. 29.1040 -\item[\rcitem{web}{maxfiles}] Integer. The default maximum number 29.1041 - of modified files to display in a single page of output. 29.1042 -\item[\rcitem{web}{stripes}] Integer. If the web interface displays 29.1043 - alternating ``stripes'' to make it easier to visually align rows 29.1044 - when you are looking at a table, this number controls the number of 29.1045 - rows in each stripe. 29.1046 -\item[\rcitem{web}{style}] Controls the template Mercurial uses to 29.1047 - display the web interface. Mercurial ships with two web templates, 29.1048 - named \texttt{default} and \texttt{gitweb} (the latter is much more 29.1049 - visually attractive). You can also specify a custom template of 29.1050 - your own; see chapter~\ref{chap:template} for details. Here, you 29.1051 - can see how to enable the \texttt{gitweb} style. 29.1052 - \begin{codesample4} 29.1053 - [web] 29.1054 - style = gitweb 29.1055 - \end{codesample4} 29.1056 -\item[\rcitem{web}{templates}] Path. The directory in which to search 29.1057 - for template files. By default, Mercurial searches in the directory 29.1058 - in which it was installed. 29.1059 -\end{itemize} 29.1060 -If you are using \sfilename{hgwebdir.cgi}, you can place a few 29.1061 -configuration items in a \rcsection{web} section of the 29.1062 -\sfilename{hgweb.config} file instead of a \hgrc\ file, for 29.1063 -convenience. These items are \rcitem{web}{motd} and 29.1064 -\rcitem{web}{style}. 29.1065 - 29.1066 -\subsubsection{Options specific to an individual repository} 29.1067 - 29.1068 -A few \rcsection{web} configuration items ought to be placed in a 29.1069 -repository's local \sfilename{.hg/hgrc}, rather than a user's or 29.1070 -global \hgrc. 29.1071 -\begin{itemize} 29.1072 -\item[\rcitem{web}{description}] String. A free-form (but preferably 29.1073 - brief) string that describes the contents or purpose of the 29.1074 - repository. 29.1075 -\item[\rcitem{web}{name}] String. The name to use for the repository 29.1076 - in the web interface. This overrides the default name, which is the 29.1077 - last component of the repository's path. 29.1078 -\end{itemize} 29.1079 - 29.1080 -\subsubsection{Options specific to the \hgcmd{serve} command} 29.1081 - 29.1082 -Some of the items in the \rcsection{web} section of a \hgrc\ file are 29.1083 -only for use with the \hgcmd{serve} command. 29.1084 -\begin{itemize} 29.1085 -\item[\rcitem{web}{accesslog}] Path. The name of a file into which to 29.1086 - write an access log. By default, the \hgcmd{serve} command writes 29.1087 - this information to standard output, not to a file. Log entries are 29.1088 - written in the standard ``combined'' file format used by almost all 29.1089 - web servers. 29.1090 -\item[\rcitem{web}{address}] String. The local address on which the 29.1091 - server should listen for incoming connections. By default, the 29.1092 - server listens on all addresses. 29.1093 -\item[\rcitem{web}{errorlog}] Path. The name of a file into which to 29.1094 - write an error log. By default, the \hgcmd{serve} command writes this 29.1095 - information to standard error, not to a file. 29.1096 -\item[\rcitem{web}{ipv6}] Boolean. Whether to use the IPv6 protocol. 29.1097 - By default, IPv6 is not used. 29.1098 -\item[\rcitem{web}{port}] Integer. The TCP~port number on which the 29.1099 - server should listen. The default port number used is~8000. 29.1100 -\end{itemize} 29.1101 - 29.1102 -\subsubsection{Choosing the right \hgrc\ file to add \rcsection{web} 29.1103 - items to} 29.1104 - 29.1105 -It is important to remember that a web server like Apache or 29.1106 -\texttt{lighttpd} will run under a user~ID that is different to yours. 29.1107 -CGI scripts run by your server, such as \sfilename{hgweb.cgi}, will 29.1108 -usually also run under that user~ID. 29.1109 - 29.1110 -If you add \rcsection{web} items to your own personal \hgrc\ file, CGI 29.1111 -scripts won't read that \hgrc\ file. Those settings will thus only 29.1112 -affect the behaviour of the \hgcmd{serve} command when you run it. To 29.1113 -cause CGI scripts to see your settings, either create a \hgrc\ file in 29.1114 -the home directory of the user ID that runs your web server, or add 29.1115 -those settings to a system-wide \hgrc\ file. 29.1116 - 29.1117 - 29.1118 -%%% Local Variables: 29.1119 -%%% mode: latex 29.1120 -%%% TeX-master: "00book" 29.1121 -%%% End:
30.1 --- a/fr/concepts.tex Sun Aug 16 03:41:39 2009 +0200 30.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 30.3 @@ -1,577 +0,0 @@ 30.4 -\chapter{Behind the scenes} 30.5 -\label{chap:concepts} 30.6 - 30.7 -Unlike many revision control systems, the concepts upon which 30.8 -Mercurial is built are simple enough that it's easy to understand how 30.9 -the software really works. Knowing this certainly isn't necessary, 30.10 -but I find it useful to have a ``mental model'' of what's going on. 30.11 - 30.12 -This understanding gives me confidence that Mercurial has been 30.13 -carefully designed to be both \emph{safe} and \emph{efficient}. And 30.14 -just as importantly, if it's easy for me to retain a good idea of what 30.15 -the software is doing when I perform a revision control task, I'm less 30.16 -likely to be surprised by its behaviour. 30.17 - 30.18 -In this chapter, we'll initially cover the core concepts behind 30.19 -Mercurial's design, then continue to discuss some of the interesting 30.20 -details of its implementation. 30.21 - 30.22 -\section{Mercurial's historical record} 30.23 - 30.24 -\subsection{Tracking the history of a single file} 30.25 - 30.26 -When Mercurial tracks modifications to a file, it stores the history 30.27 -of that file in a metadata object called a \emph{filelog}. Each entry 30.28 -in the filelog contains enough information to reconstruct one revision 30.29 -of the file that is being tracked. Filelogs are stored as files in 30.30 -the \sdirname{.hg/store/data} directory. A filelog contains two kinds 30.31 -of information: revision data, and an index to help Mercurial to find 30.32 -a revision efficiently. 30.33 - 30.34 -A file that is large, or has a lot of history, has its filelog stored 30.35 -in separate data (``\texttt{.d}'' suffix) and index (``\texttt{.i}'' 30.36 -suffix) files. For small files without much history, the revision 30.37 -data and index are combined in a single ``\texttt{.i}'' file. The 30.38 -correspondence between a file in the working directory and the filelog 30.39 -that tracks its history in the repository is illustrated in 30.40 -figure~\ref{fig:concepts:filelog}. 30.41 - 30.42 -\begin{figure}[ht] 30.43 - \centering 30.44 - \grafix{filelog} 30.45 - \caption{Relationships between files in working directory and 30.46 - filelogs in repository} 30.47 - \label{fig:concepts:filelog} 30.48 -\end{figure} 30.49 - 30.50 -\subsection{Managing tracked files} 30.51 - 30.52 -Mercurial uses a structure called a \emph{manifest} to collect 30.53 -together information about the files that it tracks. Each entry in 30.54 -the manifest contains information about the files present in a single 30.55 -changeset. An entry records which files are present in the changeset, 30.56 -the revision of each file, and a few other pieces of file metadata. 30.57 - 30.58 -\subsection{Recording changeset information} 30.59 - 30.60 -The \emph{changelog} contains information about each changeset. Each 30.61 -revision records who committed a change, the changeset comment, other 30.62 -pieces of changeset-related information, and the revision of the 30.63 -manifest to use. 30.64 - 30.65 -\subsection{Relationships between revisions} 30.66 - 30.67 -Within a changelog, a manifest, or a filelog, each revision stores a 30.68 -pointer to its immediate parent (or to its two parents, if it's a 30.69 -merge revision). As I mentioned above, there are also relationships 30.70 -between revisions \emph{across} these structures, and they are 30.71 -hierarchical in nature. 30.72 - 30.73 -For every changeset in a repository, there is exactly one revision 30.74 -stored in the changelog. Each revision of the changelog contains a 30.75 -pointer to a single revision of the manifest. A revision of the 30.76 -manifest stores a pointer to a single revision of each filelog tracked 30.77 -when that changeset was created. These relationships are illustrated 30.78 -in figure~\ref{fig:concepts:metadata}. 30.79 - 30.80 -\begin{figure}[ht] 30.81 - \centering 30.82 - \grafix{metadata} 30.83 - \caption{Metadata relationships} 30.84 - \label{fig:concepts:metadata} 30.85 -\end{figure} 30.86 - 30.87 -As the illustration shows, there is \emph{not} a ``one to one'' 30.88 -relationship between revisions in the changelog, manifest, or filelog. 30.89 -If the manifest hasn't changed between two changesets, the changelog 30.90 -entries for those changesets will point to the same revision of the 30.91 -manifest. If a file that Mercurial tracks hasn't changed between two 30.92 -changesets, the entry for that file in the two revisions of the 30.93 -manifest will point to the same revision of its filelog. 30.94 - 30.95 -\section{Safe, efficient storage} 30.96 - 30.97 -The underpinnings of changelogs, manifests, and filelogs are provided 30.98 -by a single structure called the \emph{revlog}. 30.99 - 30.100 -\subsection{Efficient storage} 30.101 - 30.102 -The revlog provides efficient storage of revisions using a 30.103 -\emph{delta} mechanism. Instead of storing a complete copy of a file 30.104 -for each revision, it stores the changes needed to transform an older 30.105 -revision into the new revision. For many kinds of file data, these 30.106 -deltas are typically a fraction of a percent of the size of a full 30.107 -copy of a file. 30.108 - 30.109 -Some obsolete revision control systems can only work with deltas of 30.110 -text files. They must either store binary files as complete snapshots 30.111 -or encoded into a text representation, both of which are wasteful 30.112 -approaches. Mercurial can efficiently handle deltas of files with 30.113 -arbitrary binary contents; it doesn't need to treat text as special. 30.114 - 30.115 -\subsection{Safe operation} 30.116 -\label{sec:concepts:txn} 30.117 - 30.118 -Mercurial only ever \emph{appends} data to the end of a revlog file. 30.119 -It never modifies a section of a file after it has written it. This 30.120 -is both more robust and efficient than schemes that need to modify or 30.121 -rewrite data. 30.122 - 30.123 -In addition, Mercurial treats every write as part of a 30.124 -\emph{transaction} that can span a number of files. A transaction is 30.125 -\emph{atomic}: either the entire transaction succeeds and its effects 30.126 -are all visible to readers in one go, or the whole thing is undone. 30.127 -This guarantee of atomicity means that if you're running two copies of 30.128 -Mercurial, where one is reading data and one is writing it, the reader 30.129 -will never see a partially written result that might confuse it. 30.130 - 30.131 -The fact that Mercurial only appends to files makes it easier to 30.132 -provide this transactional guarantee. The easier it is to do stuff 30.133 -like this, the more confident you should be that it's done correctly. 30.134 - 30.135 -\subsection{Fast retrieval} 30.136 - 30.137 -Mercurial cleverly avoids a pitfall common to all earlier 30.138 -revision control systems: the problem of \emph{inefficient retrieval}. 30.139 -Most revision control systems store the contents of a revision as an 30.140 -incremental series of modifications against a ``snapshot''. To 30.141 -reconstruct a specific revision, you must first read the snapshot, and 30.142 -then every one of the revisions between the snapshot and your target 30.143 -revision. The more history that a file accumulates, the more 30.144 -revisions you must read, hence the longer it takes to reconstruct a 30.145 -particular revision. 30.146 - 30.147 -\begin{figure}[ht] 30.148 - \centering 30.149 - \grafix{snapshot} 30.150 - \caption{Snapshot of a revlog, with incremental deltas} 30.151 - \label{fig:concepts:snapshot} 30.152 -\end{figure} 30.153 - 30.154 -The innovation that Mercurial applies to this problem is simple but 30.155 -effective. Once the cumulative amount of delta information stored 30.156 -since the last snapshot exceeds a fixed threshold, it stores a new 30.157 -snapshot (compressed, of course), instead of another delta. This 30.158 -makes it possible to reconstruct \emph{any} revision of a file 30.159 -quickly. This approach works so well that it has since been copied by 30.160 -several other revision control systems. 30.161 - 30.162 -Figure~\ref{fig:concepts:snapshot} illustrates the idea. In an entry 30.163 -in a revlog's index file, Mercurial stores the range of entries from 30.164 -the data file that it must read to reconstruct a particular revision. 30.165 - 30.166 -\subsubsection{Aside: the influence of video compression} 30.167 - 30.168 -If you're familiar with video compression or have ever watched a TV 30.169 -feed through a digital cable or satellite service, you may know that 30.170 -most video compression schemes store each frame of video as a delta 30.171 -against its predecessor frame. In addition, these schemes use 30.172 -``lossy'' compression techniques to increase the compression ratio, so 30.173 -visual errors accumulate over the course of a number of inter-frame 30.174 -deltas. 30.175 - 30.176 -Because it's possible for a video stream to ``drop out'' occasionally 30.177 -due to signal glitches, and to limit the accumulation of artefacts 30.178 -introduced by the lossy compression process, video encoders 30.179 -periodically insert a complete frame (called a ``key frame'') into the 30.180 -video stream; the next delta is generated against that frame. This 30.181 -means that if the video signal gets interrupted, it will resume once 30.182 -the next key frame is received. Also, the accumulation of encoding 30.183 -errors restarts anew with each key frame. 30.184 - 30.185 -\subsection{Identification and strong integrity} 30.186 - 30.187 -Along with delta or snapshot information, a revlog entry contains a 30.188 -cryptographic hash of the data that it represents. This makes it 30.189 -difficult to forge the contents of a revision, and easy to detect 30.190 -accidental corruption. 30.191 - 30.192 -Hashes provide more than a mere check against corruption; they are 30.193 -used as the identifiers for revisions. The changeset identification 30.194 -hashes that you see as an end user are from revisions of the 30.195 -changelog. Although filelogs and the manifest also use hashes, 30.196 -Mercurial only uses these behind the scenes. 30.197 - 30.198 -Mercurial verifies that hashes are correct when it retrieves file 30.199 -revisions and when it pulls changes from another repository. If it 30.200 -encounters an integrity problem, it will complain and stop whatever 30.201 -it's doing. 30.202 - 30.203 -In addition to the effect it has on retrieval efficiency, Mercurial's 30.204 -use of periodic snapshots makes it more robust against partial data 30.205 -corruption. If a revlog becomes partly corrupted due to a hardware 30.206 -error or system bug, it's often possible to reconstruct some or most 30.207 -revisions from the uncorrupted sections of the revlog, both before and 30.208 -after the corrupted section. This would not be possible with a 30.209 -delta-only storage model. 30.210 - 30.211 -\section{Revision history, branching, 30.212 - and merging} 30.213 - 30.214 -Every entry in a Mercurial revlog knows the identity of its immediate 30.215 -ancestor revision, usually referred to as its \emph{parent}. In fact, 30.216 -a revision contains room for not one parent, but two. Mercurial uses 30.217 -a special hash, called the ``null ID'', to represent the idea ``there 30.218 -is no parent here''. This hash is simply a string of zeroes. 30.219 - 30.220 -In figure~\ref{fig:concepts:revlog}, you can see an example of the 30.221 -conceptual structure of a revlog. Filelogs, manifests, and changelogs 30.222 -all have this same structure; they differ only in the kind of data 30.223 -stored in each delta or snapshot. 30.224 - 30.225 -The first revision in a revlog (at the bottom of the image) has the 30.226 -null ID in both of its parent slots. For a ``normal'' revision, its 30.227 -first parent slot contains the ID of its parent revision, and its 30.228 -second contains the null ID, indicating that the revision has only one 30.229 -real parent. Any two revisions that have the same parent ID are 30.230 -branches. A revision that represents a merge between branches has two 30.231 -normal revision IDs in its parent slots. 30.232 - 30.233 -\begin{figure}[ht] 30.234 - \centering 30.235 - \grafix{revlog} 30.236 - \caption{} 30.237 - \label{fig:concepts:revlog} 30.238 -\end{figure} 30.239 - 30.240 -\section{The working directory} 30.241 - 30.242 -In the working directory, Mercurial stores a snapshot of the files 30.243 -from the repository as of a particular changeset. 30.244 - 30.245 -The working directory ``knows'' which changeset it contains. When you 30.246 -update the working directory to contain a particular changeset, 30.247 -Mercurial looks up the appropriate revision of the manifest to find 30.248 -out which files it was tracking at the time that changeset was 30.249 -committed, and which revision of each file was then current. It then 30.250 -recreates a copy of each of those files, with the same contents it had 30.251 -when the changeset was committed. 30.252 - 30.253 -The \emph{dirstate} contains Mercurial's knowledge of the working 30.254 -directory. This details which changeset the working directory is 30.255 -updated to, and all of the files that Mercurial is tracking in the 30.256 -working directory. 30.257 - 30.258 -Just as a revision of a revlog has room for two parents, so that it 30.259 -can represent either a normal revision (with one parent) or a merge of 30.260 -two earlier revisions, the dirstate has slots for two parents. When 30.261 -you use the \hgcmd{update} command, the changeset that you update to 30.262 -is stored in the ``first parent'' slot, and the null ID in the second. 30.263 -When you \hgcmd{merge} with another changeset, the first parent 30.264 -remains unchanged, and the second parent is filled in with the 30.265 -changeset you're merging with. The \hgcmd{parents} command tells you 30.266 -what the parents of the dirstate are. 30.267 - 30.268 -\subsection{What happens when you commit} 30.269 - 30.270 -The dirstate stores parent information for more than just book-keeping 30.271 -purposes. Mercurial uses the parents of the dirstate as \emph{the 30.272 - parents of a new changeset} when you perform a commit. 30.273 - 30.274 -\begin{figure}[ht] 30.275 - \centering 30.276 - \grafix{wdir} 30.277 - \caption{The working directory can have two parents} 30.278 - \label{fig:concepts:wdir} 30.279 -\end{figure} 30.280 - 30.281 -Figure~\ref{fig:concepts:wdir} shows the normal state of the working 30.282 -directory, where it has a single changeset as parent. That changeset 30.283 -is the \emph{tip}, the newest changeset in the repository that has no 30.284 -children. 30.285 - 30.286 -\begin{figure}[ht] 30.287 - \centering 30.288 - \grafix{wdir-after-commit} 30.289 - \caption{The working directory gains new parents after a commit} 30.290 - \label{fig:concepts:wdir-after-commit} 30.291 -\end{figure} 30.292 - 30.293 -It's useful to think of the working directory as ``the changeset I'm 30.294 -about to commit''. Any files that you tell Mercurial that you've 30.295 -added, removed, renamed, or copied will be reflected in that 30.296 -changeset, as will modifications to any files that Mercurial is 30.297 -already tracking; the new changeset will have the parents of the 30.298 -working directory as its parents. 30.299 - 30.300 -After a commit, Mercurial will update the parents of the working 30.301 -directory, so that the first parent is the ID of the new changeset, 30.302 -and the second is the null ID. This is shown in 30.303 -figure~\ref{fig:concepts:wdir-after-commit}. Mercurial doesn't touch 30.304 -any of the files in the working directory when you commit; it just 30.305 -modifies the dirstate to note its new parents. 30.306 - 30.307 -\subsection{Creating a new head} 30.308 - 30.309 -It's perfectly normal to update the working directory to a changeset 30.310 -other than the current tip. For example, you might want to know what 30.311 -your project looked like last Tuesday, or you could be looking through 30.312 -changesets to see which one introduced a bug. In cases like this, the 30.313 -natural thing to do is update the working directory to the changeset 30.314 -you're interested in, and then examine the files in the working 30.315 -directory directly to see their contents as they were when you 30.316 -committed that changeset. The effect of this is shown in 30.317 -figure~\ref{fig:concepts:wdir-pre-branch}. 30.318 - 30.319 -\begin{figure}[ht] 30.320 - \centering 30.321 - \grafix{wdir-pre-branch} 30.322 - \caption{The working directory, updated to an older changeset} 30.323 - \label{fig:concepts:wdir-pre-branch} 30.324 -\end{figure} 30.325 - 30.326 -Having updated the working directory to an older changeset, what 30.327 -happens if you make some changes, and then commit? Mercurial behaves 30.328 -in the same way as I outlined above. The parents of the working 30.329 -directory become the parents of the new changeset. This new changeset 30.330 -has no children, so it becomes the new tip. And the repository now 30.331 -contains two changesets that have no children; we call these 30.332 -\emph{heads}. You can see the structure that this creates in 30.333 -figure~\ref{fig:concepts:wdir-branch}. 30.334 - 30.335 -\begin{figure}[ht] 30.336 - \centering 30.337 - \grafix{wdir-branch} 30.338 - \caption{After a commit made while synced to an older changeset} 30.339 - \label{fig:concepts:wdir-branch} 30.340 -\end{figure} 30.341 - 30.342 -\begin{note} 30.343 - If you're new to Mercurial, you should keep in mind a common 30.344 - ``error'', which is to use the \hgcmd{pull} command without any 30.345 - options. By default, the \hgcmd{pull} command \emph{does not} 30.346 - update the working directory, so you'll bring new changesets into 30.347 - your repository, but the working directory will stay synced at the 30.348 - same changeset as before the pull. If you make some changes and 30.349 - commit afterwards, you'll thus create a new head, because your 30.350 - working directory isn't synced to whatever the current tip is. 30.351 - 30.352 - I put the word ``error'' in quotes because all that you need to do 30.353 - to rectify this situation is \hgcmd{merge}, then \hgcmd{commit}. In 30.354 - other words, this almost never has negative consequences; it just 30.355 - surprises people. I'll discuss other ways to avoid this behaviour, 30.356 - and why Mercurial behaves in this initially surprising way, later 30.357 - on. 30.358 -\end{note} 30.359 - 30.360 -\subsection{Merging heads} 30.361 - 30.362 -When you run the \hgcmd{merge} command, Mercurial leaves the first 30.363 -parent of the working directory unchanged, and sets the second parent 30.364 -to the changeset you're merging with, as shown in 30.365 -figure~\ref{fig:concepts:wdir-merge}. 30.366 - 30.367 -\begin{figure}[ht] 30.368 - \centering 30.369 - \grafix{wdir-merge} 30.370 - \caption{Merging two heads} 30.371 - \label{fig:concepts:wdir-merge} 30.372 -\end{figure} 30.373 - 30.374 -Mercurial also has to modify the working directory, to merge the files 30.375 -managed in the two changesets. Simplified a little, the merging 30.376 -process goes like this, for every file in the manifests of both 30.377 -changesets. 30.378 -\begin{itemize} 30.379 -\item If neither changeset has modified a file, do nothing with that 30.380 - file. 30.381 -\item If one changeset has modified a file, and the other hasn't, 30.382 - create the modified copy of the file in the working directory. 30.383 -\item If one changeset has removed a file, and the other hasn't (or 30.384 - has also deleted it), delete the file from the working directory. 30.385 -\item If one changeset has removed a file, but the other has modified 30.386 - the file, ask the user what to do: keep the modified file, or remove 30.387 - it? 30.388 -\item If both changesets have modified a file, invoke an external 30.389 - merge program to choose the new contents for the merged file. This 30.390 - may require input from the user. 30.391 -\item If one changeset has modified a file, and the other has renamed 30.392 - or copied the file, make sure that the changes follow the new name 30.393 - of the file. 30.394 -\end{itemize} 30.395 -There are more details---merging has plenty of corner cases---but 30.396 -these are the most common choices that are involved in a merge. As 30.397 -you can see, most cases are completely automatic, and indeed most 30.398 -merges finish automatically, without requiring your input to resolve 30.399 -any conflicts. 30.400 - 30.401 -When you're thinking about what happens when you commit after a merge, 30.402 -once again the working directory is ``the changeset I'm about to 30.403 -commit''. After the \hgcmd{merge} command completes, the working 30.404 -directory has two parents; these will become the parents of the new 30.405 -changeset. 30.406 - 30.407 -Mercurial lets you perform multiple merges, but you must commit the 30.408 -results of each individual merge as you go. This is necessary because 30.409 -Mercurial only tracks two parents for both revisions and the working 30.410 -directory. While it would be technically possible to merge multiple 30.411 -changesets at once, the prospect of user confusion and making a 30.412 -terrible mess of a merge immediately becomes overwhelming. 30.413 - 30.414 -\section{Other interesting design features} 30.415 - 30.416 -In the sections above, I've tried to highlight some of the most 30.417 -important aspects of Mercurial's design, to illustrate that it pays 30.418 -careful attention to reliability and performance. However, the 30.419 -attention to detail doesn't stop there. There are a number of other 30.420 -aspects of Mercurial's construction that I personally find 30.421 -interesting. I'll detail a few of them here, separate from the ``big 30.422 -ticket'' items above, so that if you're interested, you can gain a 30.423 -better idea of the amount of thinking that goes into a well-designed 30.424 -system. 30.425 - 30.426 -\subsection{Clever compression} 30.427 - 30.428 -When appropriate, Mercurial will store both snapshots and deltas in 30.429 -compressed form. It does this by always \emph{trying to} compress a 30.430 -snapshot or delta, but only storing the compressed version if it's 30.431 -smaller than the uncompressed version. 30.432 - 30.433 -This means that Mercurial does ``the right thing'' when storing a file 30.434 -whose native form is compressed, such as a \texttt{zip} archive or a 30.435 -JPEG image. When these types of files are compressed a second time, 30.436 -the resulting file is usually bigger than the once-compressed form, 30.437 -and so Mercurial will store the plain \texttt{zip} or JPEG. 30.438 - 30.439 -Deltas between revisions of a compressed file are usually larger than 30.440 -snapshots of the file, and Mercurial again does ``the right thing'' in 30.441 -these cases. It finds that such a delta exceeds the threshold at 30.442 -which it should store a complete snapshot of the file, so it stores 30.443 -the snapshot, again saving space compared to a naive delta-only 30.444 -approach. 30.445 - 30.446 -\subsubsection{Network recompression} 30.447 - 30.448 -When storing revisions on disk, Mercurial uses the ``deflate'' 30.449 -compression algorithm (the same one used by the popular \texttt{zip} 30.450 -archive format), which balances good speed with a respectable 30.451 -compression ratio. However, when transmitting revision data over a 30.452 -network connection, Mercurial uncompresses the compressed revision 30.453 -data. 30.454 - 30.455 -If the connection is over HTTP, Mercurial recompresses the entire 30.456 -stream of data using a compression algorithm that gives a better 30.457 -compression ratio (the Burrows-Wheeler algorithm from the widely used 30.458 -\texttt{bzip2} compression package). This combination of algorithm 30.459 -and compression of the entire stream (instead of a revision at a time) 30.460 -substantially reduces the number of bytes to be transferred, yielding 30.461 -better network performance over almost all kinds of network. 30.462 - 30.463 -(If the connection is over \command{ssh}, Mercurial \emph{doesn't} 30.464 -recompress the stream, because \command{ssh} can already do this 30.465 -itself.) 30.466 - 30.467 -\subsection{Read/write ordering and atomicity} 30.468 - 30.469 -Appending to files isn't the whole story when it comes to guaranteeing 30.470 -that a reader won't see a partial write. If you recall 30.471 -figure~\ref{fig:concepts:metadata}, revisions in the changelog point to 30.472 -revisions in the manifest, and revisions in the manifest point to 30.473 -revisions in filelogs. This hierarchy is deliberate. 30.474 - 30.475 -A writer starts a transaction by writing filelog and manifest data, 30.476 -and doesn't write any changelog data until those are finished. A 30.477 -reader starts by reading changelog data, then manifest data, followed 30.478 -by filelog data. 30.479 - 30.480 -Since the writer has always finished writing filelog and manifest data 30.481 -before it writes to the changelog, a reader will never read a pointer 30.482 -to a partially written manifest revision from the changelog, and it will 30.483 -never read a pointer to a partially written filelog revision from the 30.484 -manifest. 30.485 - 30.486 -\subsection{Concurrent access} 30.487 - 30.488 -The read/write ordering and atomicity guarantees mean that Mercurial 30.489 -never needs to \emph{lock} a repository when it's reading data, even 30.490 -if the repository is being written to while the read is occurring. 30.491 -This has a big effect on scalability; you can have an arbitrary number 30.492 -of Mercurial processes safely reading data from a repository safely 30.493 -all at once, no matter whether it's being written to or not. 30.494 - 30.495 -The lockless nature of reading means that if you're sharing a 30.496 -repository on a multi-user system, you don't need to grant other local 30.497 -users permission to \emph{write} to your repository in order for them 30.498 -to be able to clone it or pull changes from it; they only need 30.499 -\emph{read} permission. (This is \emph{not} a common feature among 30.500 -revision control systems, so don't take it for granted! Most require 30.501 -readers to be able to lock a repository to access it safely, and this 30.502 -requires write permission on at least one directory, which of course 30.503 -makes for all kinds of nasty and annoying security and administrative 30.504 -problems.) 30.505 - 30.506 -Mercurial uses locks to ensure that only one process can write to a 30.507 -repository at a time (the locking mechanism is safe even over 30.508 -filesystems that are notoriously hostile to locking, such as NFS). If 30.509 -a repository is locked, a writer will wait for a while to retry if the 30.510 -repository becomes unlocked, but if the repository remains locked for 30.511 -too long, the process attempting to write will time out after a while. 30.512 -This means that your daily automated scripts won't get stuck forever 30.513 -and pile up if a system crashes unnoticed, for example. (Yes, the 30.514 -timeout is configurable, from zero to infinity.) 30.515 - 30.516 -\subsubsection{Safe dirstate access} 30.517 - 30.518 -As with revision data, Mercurial doesn't take a lock to read the 30.519 -dirstate file; it does acquire a lock to write it. To avoid the 30.520 -possibility of reading a partially written copy of the dirstate file, 30.521 -Mercurial writes to a file with a unique name in the same directory as 30.522 -the dirstate file, then renames the temporary file atomically to 30.523 -\filename{dirstate}. The file named \filename{dirstate} is thus 30.524 -guaranteed to be complete, not partially written. 30.525 - 30.526 -\subsection{Avoiding seeks} 30.527 - 30.528 -Critical to Mercurial's performance is the avoidance of seeks of the 30.529 -disk head, since any seek is far more expensive than even a 30.530 -comparatively large read operation. 30.531 - 30.532 -This is why, for example, the dirstate is stored in a single file. If 30.533 -there were a dirstate file per directory that Mercurial tracked, the 30.534 -disk would seek once per directory. Instead, Mercurial reads the 30.535 -entire single dirstate file in one step. 30.536 - 30.537 -Mercurial also uses a ``copy on write'' scheme when cloning a 30.538 -repository on local storage. Instead of copying every revlog file 30.539 -from the old repository into the new repository, it makes a ``hard 30.540 -link'', which is a shorthand way to say ``these two names point to the 30.541 -same file''. When Mercurial is about to write to one of a revlog's 30.542 -files, it checks to see if the number of names pointing at the file is 30.543 -greater than one. If it is, more than one repository is using the 30.544 -file, so Mercurial makes a new copy of the file that is private to 30.545 -this repository. 30.546 - 30.547 -A few revision control developers have pointed out that this idea of 30.548 -making a complete private copy of a file is not very efficient in its 30.549 -use of storage. While this is true, storage is cheap, and this method 30.550 -gives the highest performance while deferring most book-keeping to the 30.551 -operating system. An alternative scheme would most likely reduce 30.552 -performance and increase the complexity of the software, each of which 30.553 -is much more important to the ``feel'' of day-to-day use. 30.554 - 30.555 -\subsection{Other contents of the dirstate} 30.556 - 30.557 -Because Mercurial doesn't force you to tell it when you're modifying a 30.558 -file, it uses the dirstate to store some extra information so it can 30.559 -determine efficiently whether you have modified a file. For each file 30.560 -in the working directory, it stores the time that it last modified the 30.561 -file itself, and the size of the file at that time. 30.562 - 30.563 -When you explicitly \hgcmd{add}, \hgcmd{remove}, \hgcmd{rename} or 30.564 -\hgcmd{copy} files, Mercurial updates the dirstate so that it knows 30.565 -what to do with those files when you commit. 30.566 - 30.567 -When Mercurial is checking the states of files in the working 30.568 -directory, it first checks a file's modification time. If that has 30.569 -not changed, the file must not have been modified. If the file's size 30.570 -has changed, the file must have been modified. If the modification 30.571 -time has changed, but the size has not, only then does Mercurial need 30.572 -to read the actual contents of the file to see if they've changed. 30.573 -Storing these few extra pieces of information dramatically reduces the 30.574 -amount of data that Mercurial needs to read, which yields large 30.575 -performance improvements compared to other revision control systems. 30.576 - 30.577 -%%% Local Variables: 30.578 -%%% mode: latex 30.579 -%%% TeX-master: "00book" 30.580 -%%% End:
31.1 --- a/fr/daily.tex Sun Aug 16 03:41:39 2009 +0200 31.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 31.3 @@ -1,381 +0,0 @@ 31.4 -\chapter{Mercurial in daily use} 31.5 -\label{chap:daily} 31.6 - 31.7 -\section{Telling Mercurial which files to track} 31.8 - 31.9 -Mercurial does not work with files in your repository unless you tell 31.10 -it to manage them. The \hgcmd{status} command will tell you which 31.11 -files Mercurial doesn't know about; it uses a ``\texttt{?}'' to 31.12 -display such files. 31.13 - 31.14 -To tell Mercurial to track a file, use the \hgcmd{add} command. Once 31.15 -you have added a file, the entry in the output of \hgcmd{status} for 31.16 -that file changes from ``\texttt{?}'' to ``\texttt{A}''. 31.17 -\interaction{daily.files.add} 31.18 - 31.19 -After you run a \hgcmd{commit}, the files that you added before the 31.20 -commit will no longer be listed in the output of \hgcmd{status}. The 31.21 -reason for this is that \hgcmd{status} only tells you about 31.22 -``interesting'' files---those that you have modified or told Mercurial 31.23 -to do something with---by default. If you have a repository that 31.24 -contains thousands of files, you will rarely want to know about files 31.25 -that Mercurial is tracking, but that have not changed. (You can still 31.26 -get this information; we'll return to this later.) 31.27 - 31.28 -Once you add a file, Mercurial doesn't do anything with it 31.29 -immediately. Instead, it will take a snapshot of the file's state the 31.30 -next time you perform a commit. It will then continue to track the 31.31 -changes you make to the file every time you commit, until you remove 31.32 -the file. 31.33 - 31.34 -\subsection{Explicit versus implicit file naming} 31.35 - 31.36 -A useful behaviour that Mercurial has is that if you pass the name of 31.37 -a directory to a command, every Mercurial command will treat this as 31.38 -``I want to operate on every file in this directory and its 31.39 -subdirectories''. 31.40 -\interaction{daily.files.add-dir} 31.41 -Notice in this example that Mercurial printed the names of the files 31.42 -it added, whereas it didn't do so when we added the file named 31.43 -\filename{a} in the earlier example. 31.44 - 31.45 -What's going on is that in the former case, we explicitly named the 31.46 -file to add on the command line, so the assumption that Mercurial 31.47 -makes in such cases is that you know what you were doing, and it 31.48 -doesn't print any output. 31.49 - 31.50 -However, when we \emph{imply} the names of files by giving the name of 31.51 -a directory, Mercurial takes the extra step of printing the name of 31.52 -each file that it does something with. This makes it more clear what 31.53 -is happening, and reduces the likelihood of a silent and nasty 31.54 -surprise. This behaviour is common to most Mercurial commands. 31.55 - 31.56 -\subsection{Aside: Mercurial tracks files, not directories} 31.57 - 31.58 -Mercurial does not track directory information. Instead, it tracks 31.59 -the path to a file. Before creating a file, it first creates any 31.60 -missing directory components of the path. After it deletes a file, it 31.61 -then deletes any empty directories that were in the deleted file's 31.62 -path. This sounds like a trivial distinction, but it has one minor 31.63 -practical consequence: it is not possible to represent a completely 31.64 -empty directory in Mercurial. 31.65 - 31.66 -Empty directories are rarely useful, and there are unintrusive 31.67 -workarounds that you can use to achieve an appropriate effect. The 31.68 -developers of Mercurial thus felt that the complexity that would be 31.69 -required to manage empty directories was not worth the limited benefit 31.70 -this feature would bring. 31.71 - 31.72 -If you need an empty directory in your repository, there are a few 31.73 -ways to achieve this. One is to create a directory, then \hgcmd{add} a 31.74 -``hidden'' file to that directory. On Unix-like systems, any file 31.75 -name that begins with a period (``\texttt{.}'') is treated as hidden 31.76 -by most commands and GUI tools. This approach is illustrated in 31.77 -figure~\ref{ex:daily:hidden}. 31.78 - 31.79 -\begin{figure}[ht] 31.80 - \interaction{daily.files.hidden} 31.81 - \caption{Simulating an empty directory using a hidden file} 31.82 - \label{ex:daily:hidden} 31.83 -\end{figure} 31.84 - 31.85 -Another way to tackle a need for an empty directory is to simply 31.86 -create one in your automated build scripts before they will need it. 31.87 - 31.88 -\section{How to stop tracking a file} 31.89 - 31.90 -Once you decide that a file no longer belongs in your repository, use 31.91 -the \hgcmd{remove} command; this deletes the file, and tells Mercurial 31.92 -to stop tracking it. A removed file is represented in the output of 31.93 -\hgcmd{status} with a ``\texttt{R}''. 31.94 -\interaction{daily.files.remove} 31.95 - 31.96 -After you \hgcmd{remove} a file, Mercurial will no longer track 31.97 -changes to that file, even if you recreate a file with the same name 31.98 -in your working directory. If you do recreate a file with the same 31.99 -name and want Mercurial to track the new file, simply \hgcmd{add} it. 31.100 -Mercurial will know that the newly added file is not related to the 31.101 -old file of the same name. 31.102 - 31.103 -\subsection{Removing a file does not affect its history} 31.104 - 31.105 -It is important to understand that removing a file has only two 31.106 -effects. 31.107 -\begin{itemize} 31.108 -\item It removes the current version of the file from the working 31.109 - directory. 31.110 -\item It stops Mercurial from tracking changes to the file, from the 31.111 - time of the next commit. 31.112 -\end{itemize} 31.113 -Removing a file \emph{does not} in any way alter the \emph{history} of 31.114 -the file. 31.115 - 31.116 -If you update the working directory to a changeset in which a file 31.117 -that you have removed was still tracked, it will reappear in the 31.118 -working directory, with the contents it had when you committed that 31.119 -changeset. If you then update the working directory to a later 31.120 -changeset, in which the file had been removed, Mercurial will once 31.121 -again remove the file from the working directory. 31.122 - 31.123 -\subsection{Missing files} 31.124 - 31.125 -Mercurial considers a file that you have deleted, but not used 31.126 -\hgcmd{remove} to delete, to be \emph{missing}. A missing file is 31.127 -represented with ``\texttt{!}'' in the output of \hgcmd{status}. 31.128 -Mercurial commands will not generally do anything with missing files. 31.129 -\interaction{daily.files.missing} 31.130 - 31.131 -If your repository contains a file that \hgcmd{status} reports as 31.132 -missing, and you want the file to stay gone, you can run 31.133 -\hgcmdargs{remove}{\hgopt{remove}{--after}} at any time later on, to 31.134 -tell Mercurial that you really did mean to remove the file. 31.135 -\interaction{daily.files.remove-after} 31.136 - 31.137 -On the other hand, if you deleted the missing file by accident, use 31.138 -\hgcmdargs{revert}{\emph{filename}} to recover the file. It will 31.139 -reappear, in unmodified form. 31.140 -\interaction{daily.files.recover-missing} 31.141 - 31.142 -\subsection{Aside: why tell Mercurial explicitly to 31.143 - remove a file?} 31.144 - 31.145 -You might wonder why Mercurial requires you to explicitly tell it that 31.146 -you are deleting a file. Early during the development of Mercurial, 31.147 -it let you delete a file however you pleased; Mercurial would notice 31.148 -the absence of the file automatically when you next ran a 31.149 -\hgcmd{commit}, and stop tracking the file. In practice, this made it 31.150 -too easy to accidentally remove a file without noticing. 31.151 - 31.152 -\subsection{Useful shorthand---adding and removing files 31.153 - in one step} 31.154 - 31.155 -Mercurial offers a combination command, \hgcmd{addremove}, that adds 31.156 -untracked files and marks missing files as removed. 31.157 -\interaction{daily.files.addremove} 31.158 -The \hgcmd{commit} command also provides a \hgopt{commit}{-A} option 31.159 -that performs this same add-and-remove, immediately followed by a 31.160 -commit. 31.161 -\interaction{daily.files.commit-addremove} 31.162 - 31.163 -\section{Copying files} 31.164 - 31.165 -Mercurial provides a \hgcmd{copy} command that lets you make a new 31.166 -copy of a file. When you copy a file using this command, Mercurial 31.167 -makes a record of the fact that the new file is a copy of the original 31.168 -file. It treats these copied files specially when you merge your work 31.169 -with someone else's. 31.170 - 31.171 -\subsection{The results of copying during a merge} 31.172 - 31.173 -What happens during a merge is that changes ``follow'' a copy. To 31.174 -best illustrate what this means, let's create an example. We'll start 31.175 -with the usual tiny repository that contains a single file. 31.176 -\interaction{daily.copy.init} 31.177 -We need to do some work in parallel, so that we'll have something to 31.178 -merge. So let's clone our repository. 31.179 -\interaction{daily.copy.clone} 31.180 -Back in our initial repository, let's use the \hgcmd{copy} command to 31.181 -make a copy of the first file we created. 31.182 -\interaction{daily.copy.copy} 31.183 - 31.184 -If we look at the output of the \hgcmd{status} command afterwards, the 31.185 -copied file looks just like a normal added file. 31.186 -\interaction{daily.copy.status} 31.187 -But if we pass the \hgopt{status}{-C} option to \hgcmd{status}, it 31.188 -prints another line of output: this is the file that our newly-added 31.189 -file was copied \emph{from}. 31.190 -\interaction{daily.copy.status-copy} 31.191 - 31.192 -Now, back in the repository we cloned, let's make a change in 31.193 -parallel. We'll add a line of content to the original file that we 31.194 -created. 31.195 -\interaction{daily.copy.other} 31.196 -Now we have a modified \filename{file} in this repository. When we 31.197 -pull the changes from the first repository, and merge the two heads, 31.198 -Mercurial will propagate the changes that we made locally to 31.199 -\filename{file} into its copy, \filename{new-file}. 31.200 -\interaction{daily.copy.merge} 31.201 - 31.202 -\subsection{Why should changes follow copies?} 31.203 -\label{sec:daily:why-copy} 31.204 - 31.205 -This behaviour, of changes to a file propagating out to copies of the 31.206 -file, might seem esoteric, but in most cases it's highly desirable. 31.207 - 31.208 -First of all, remember that this propagation \emph{only} happens when 31.209 -you merge. So if you \hgcmd{copy} a file, and subsequently modify the 31.210 -original file during the normal course of your work, nothing will 31.211 -happen. 31.212 - 31.213 -The second thing to know is that modifications will only propagate 31.214 -across a copy as long as the repository that you're pulling changes 31.215 -from \emph{doesn't know} about the copy. 31.216 - 31.217 -The reason that Mercurial does this is as follows. Let's say I make 31.218 -an important bug fix in a source file, and commit my changes. 31.219 -Meanwhile, you've decided to \hgcmd{copy} the file in your repository, 31.220 -without knowing about the bug or having seen the fix, and you have 31.221 -started hacking on your copy of the file. 31.222 - 31.223 -If you pulled and merged my changes, and Mercurial \emph{didn't} 31.224 -propagate changes across copies, your source file would now contain 31.225 -the bug, and unless you remembered to propagate the bug fix by hand, 31.226 -the bug would \emph{remain} in your copy of the file. 31.227 - 31.228 -By automatically propagating the change that fixed the bug from the 31.229 -original file to the copy, Mercurial prevents this class of problem. 31.230 -To my knowledge, Mercurial is the \emph{only} revision control system 31.231 -that propagates changes across copies like this. 31.232 - 31.233 -Once your change history has a record that the copy and subsequent 31.234 -merge occurred, there's usually no further need to propagate changes 31.235 -from the original file to the copied file, and that's why Mercurial 31.236 -only propagates changes across copies until this point, and no 31.237 -further. 31.238 - 31.239 -\subsection{How to make changes \emph{not} follow a copy} 31.240 - 31.241 -If, for some reason, you decide that this business of automatically 31.242 -propagating changes across copies is not for you, simply use your 31.243 -system's normal file copy command (on Unix-like systems, that's 31.244 -\command{cp}) to make a copy of a file, then \hgcmd{add} the new copy 31.245 -by hand. Before you do so, though, please do reread 31.246 -section~\ref{sec:daily:why-copy}, and make an informed decision that 31.247 -this behaviour is not appropriate to your specific case. 31.248 - 31.249 -\subsection{Behaviour of the \hgcmd{copy} command} 31.250 - 31.251 -When you use the \hgcmd{copy} command, Mercurial makes a copy of each 31.252 -source file as it currently stands in the working directory. This 31.253 -means that if you make some modifications to a file, then \hgcmd{copy} 31.254 -it without first having committed those changes, the new copy will 31.255 -also contain the modifications you have made up until that point. (I 31.256 -find this behaviour a little counterintuitive, which is why I mention 31.257 -it here.) 31.258 - 31.259 -The \hgcmd{copy} command acts similarly to the Unix \command{cp} 31.260 -command (you can use the \hgcmd{cp} alias if you prefer). The last 31.261 -argument is the \emph{destination}, and all prior arguments are 31.262 -\emph{sources}. If you pass it a single file as the source, and the 31.263 -destination does not exist, it creates a new file with that name. 31.264 -\interaction{daily.copy.simple} 31.265 -If the destination is a directory, Mercurial copies its sources into 31.266 -that directory. 31.267 -\interaction{daily.copy.dir-dest} 31.268 -Copying a directory is recursive, and preserves the directory 31.269 -structure of the source. 31.270 -\interaction{daily.copy.dir-src} 31.271 -If the source and destination are both directories, the source tree is 31.272 -recreated in the destination directory. 31.273 -\interaction{daily.copy.dir-src-dest} 31.274 - 31.275 -As with the \hgcmd{rename} command, if you copy a file manually and 31.276 -then want Mercurial to know that you've copied the file, simply use 31.277 -the \hgopt{copy}{--after} option to \hgcmd{copy}. 31.278 -\interaction{daily.copy.after} 31.279 - 31.280 -\section{Renaming files} 31.281 - 31.282 -It's rather more common to need to rename a file than to make a copy 31.283 -of it. The reason I discussed the \hgcmd{copy} command before talking 31.284 -about renaming files is that Mercurial treats a rename in essentially 31.285 -the same way as a copy. Therefore, knowing what Mercurial does when 31.286 -you copy a file tells you what to expect when you rename a file. 31.287 - 31.288 -When you use the \hgcmd{rename} command, Mercurial makes a copy of 31.289 -each source file, then deletes it and marks the file as removed. 31.290 -\interaction{daily.rename.rename} 31.291 -The \hgcmd{status} command shows the newly copied file as added, and 31.292 -the copied-from file as removed. 31.293 -\interaction{daily.rename.status} 31.294 -As with the results of a \hgcmd{copy}, we must use the 31.295 -\hgopt{status}{-C} option to \hgcmd{status} to see that the added file 31.296 -is really being tracked by Mercurial as a copy of the original, now 31.297 -removed, file. 31.298 -\interaction{daily.rename.status-copy} 31.299 - 31.300 -As with \hgcmd{remove} and \hgcmd{copy}, you can tell Mercurial about 31.301 -a rename after the fact using the \hgopt{rename}{--after} option. In 31.302 -most other respects, the behaviour of the \hgcmd{rename} command, and 31.303 -the options it accepts, are similar to the \hgcmd{copy} command. 31.304 - 31.305 -\subsection{Renaming files and merging changes} 31.306 - 31.307 -Since Mercurial's rename is implemented as copy-and-remove, the same 31.308 -propagation of changes happens when you merge after a rename as after 31.309 -a copy. 31.310 - 31.311 -If I modify a file, and you rename it to a new name, and then we merge 31.312 -our respective changes, my modifications to the file under its 31.313 -original name will be propagated into the file under its new name. 31.314 -(This is something you might expect to ``simply work,'' but not all 31.315 -revision control systems actually do this.) 31.316 - 31.317 -Whereas having changes follow a copy is a feature where you can 31.318 -perhaps nod and say ``yes, that might be useful,'' it should be clear 31.319 -that having them follow a rename is definitely important. Without 31.320 -this facility, it would simply be too easy for changes to become 31.321 -orphaned when files are renamed. 31.322 - 31.323 -\subsection{Divergent renames and merging} 31.324 - 31.325 -The case of diverging names occurs when two developers start with a 31.326 -file---let's call it \filename{foo}---in their respective 31.327 -repositories. 31.328 - 31.329 -\interaction{rename.divergent.clone} 31.330 -Anne renames the file to \filename{bar}. 31.331 -\interaction{rename.divergent.rename.anne} 31.332 -Meanwhile, Bob renames it to \filename{quux}. 31.333 -\interaction{rename.divergent.rename.bob} 31.334 - 31.335 -I like to think of this as a conflict because each developer has 31.336 -expressed different intentions about what the file ought to be named. 31.337 - 31.338 -What do you think should happen when they merge their work? 31.339 -Mercurial's actual behaviour is that it always preserves \emph{both} 31.340 -names when it merges changesets that contain divergent renames. 31.341 -\interaction{rename.divergent.merge} 31.342 - 31.343 -Notice that Mercurial does warn about the divergent renames, but it 31.344 -leaves it up to you to do something about the divergence after the merge. 31.345 - 31.346 -\subsection{Convergent renames and merging} 31.347 - 31.348 -Another kind of rename conflict occurs when two people choose to 31.349 -rename different \emph{source} files to the same \emph{destination}. 31.350 -In this case, Mercurial runs its normal merge machinery, and lets you 31.351 -guide it to a suitable resolution. 31.352 - 31.353 -\subsection{Other name-related corner cases} 31.354 - 31.355 -Mercurial has a longstanding bug in which it fails to handle a merge 31.356 -where one side has a file with a given name, while another has a 31.357 -directory with the same name. This is documented as~\bug{29}. 31.358 -\interaction{issue29.go} 31.359 - 31.360 -\section{Recovering from mistakes} 31.361 - 31.362 -Mercurial has some useful commands that will help you to recover from 31.363 -some common mistakes. 31.364 - 31.365 -The \hgcmd{revert} command lets you undo changes that you have made to 31.366 -your working directory. For example, if you \hgcmd{add} a file by 31.367 -accident, just run \hgcmd{revert} with the name of the file you added, 31.368 -and while the file won't be touched in any way, it won't be tracked 31.369 -for adding by Mercurial any longer, either. You can also use 31.370 -\hgcmd{revert} to get rid of erroneous changes to a file. 31.371 - 31.372 -It's useful to remember that the \hgcmd{revert} command is useful for 31.373 -changes that you have not yet committed. Once you've committed a 31.374 -change, if you decide it was a mistake, you can still do something 31.375 -about it, though your options may be more limited. 31.376 - 31.377 -For more information about the \hgcmd{revert} command, and details 31.378 -about how to deal with changes you have already committed, see 31.379 -chapter~\ref{chap:undo}. 31.380 - 31.381 -%%% Local Variables: 31.382 -%%% mode: latex 31.383 -%%% TeX-master: "00book" 31.384 -%%% End:
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 32.2 +++ b/fr/examples/auto-snippets.xml Sun Aug 16 04:58:01 2009 +0200 32.3 @@ -0,0 +1,276 @@ 32.4 +<!ENTITY ch06-apache-config.lst SYSTEM "results/ch06-apache-config.lst.lxo"> 32.5 +<!ENTITY ch09-check_whitespace.py.lst SYSTEM "results/ch09-check_whitespace.py.lst.lxo"> 32.6 +<!ENTITY ch10-bugzilla-config.lst SYSTEM "results/ch10-bugzilla-config.lst.lxo"> 32.7 +<!ENTITY ch10-notify-config-mail.lst SYSTEM "results/ch10-notify-config-mail.lst.lxo"> 32.8 +<!ENTITY ch10-notify-config.lst SYSTEM "results/ch10-notify-config.lst.lxo"> 32.9 +<!ENTITY interaction.backout.init SYSTEM "results/backout.init.lxo"> 32.10 +<!ENTITY interaction.backout.manual.backout SYSTEM "results/backout.manual.backout.lxo"> 32.11 +<!ENTITY interaction.backout.manual.cat SYSTEM "results/backout.manual.cat.lxo"> 32.12 +<!ENTITY interaction.backout.manual.clone SYSTEM "results/backout.manual.clone.lxo"> 32.13 +<!ENTITY interaction.backout.manual.heads SYSTEM "results/backout.manual.heads.lxo"> 32.14 +<!ENTITY interaction.backout.manual.log SYSTEM "results/backout.manual.log.lxo"> 32.15 +<!ENTITY interaction.backout.manual.merge SYSTEM "results/backout.manual.merge.lxo"> 32.16 +<!ENTITY interaction.backout.manual.parents SYSTEM "results/backout.manual.parents.lxo"> 32.17 +<!ENTITY interaction.backout.non-tip.backout SYSTEM "results/backout.non-tip.backout.lxo"> 32.18 +<!ENTITY interaction.backout.non-tip.cat SYSTEM "results/backout.non-tip.cat.lxo"> 32.19 +<!ENTITY interaction.backout.non-tip.clone SYSTEM "results/backout.non-tip.clone.lxo"> 32.20 +<!ENTITY interaction.backout.simple SYSTEM "results/backout.simple.lxo"> 32.21 +<!ENTITY interaction.backout.simple.log SYSTEM "results/backout.simple.log.lxo"> 32.22 +<!ENTITY interaction.bisect.commits SYSTEM "results/bisect.commits.lxo"> 32.23 +<!ENTITY interaction.bisect.help SYSTEM "results/bisect.help.lxo"> 32.24 +<!ENTITY interaction.bisect.init SYSTEM "results/bisect.init.lxo"> 32.25 +<!ENTITY interaction.bisect.search.bad-init SYSTEM "results/bisect.search.bad-init.lxo"> 32.26 +<!ENTITY interaction.bisect.search.good-init SYSTEM "results/bisect.search.good-init.lxo"> 32.27 +<!ENTITY interaction.bisect.search.init SYSTEM "results/bisect.search.init.lxo"> 32.28 +<!ENTITY interaction.bisect.search.mytest SYSTEM "results/bisect.search.mytest.lxo"> 32.29 +<!ENTITY interaction.bisect.search.reset SYSTEM "results/bisect.search.reset.lxo"> 32.30 +<!ENTITY interaction.bisect.search.rest SYSTEM "results/bisect.search.rest.lxo"> 32.31 +<!ENTITY interaction.bisect.search.step1 SYSTEM "results/bisect.search.step1.lxo"> 32.32 +<!ENTITY interaction.bisect.search.step2 SYSTEM "results/bisect.search.step2.lxo"> 32.33 +<!ENTITY interaction.branch-named.branch SYSTEM "results/branch-named.branch.lxo"> 32.34 +<!ENTITY interaction.branch-named.branches SYSTEM "results/branch-named.branches.lxo"> 32.35 +<!ENTITY interaction.branch-named.commit SYSTEM "results/branch-named.commit.lxo"> 32.36 +<!ENTITY interaction.branch-named.create SYSTEM "results/branch-named.create.lxo"> 32.37 +<!ENTITY interaction.branch-named.foo-commit SYSTEM "results/branch-named.foo-commit.lxo"> 32.38 +<!ENTITY interaction.branch-named.merge SYSTEM "results/branch-named.merge.lxo"> 32.39 +<!ENTITY interaction.branch-named.parents SYSTEM "results/branch-named.parents.lxo"> 32.40 +<!ENTITY interaction.branch-named.rebranch SYSTEM "results/branch-named.rebranch.lxo"> 32.41 +<!ENTITY interaction.branch-named.status SYSTEM "results/branch-named.status.lxo"> 32.42 +<!ENTITY interaction.branch-named.update-bar SYSTEM "results/branch-named.update-bar.lxo"> 32.43 +<!ENTITY interaction.branch-named.update-nothing SYSTEM "results/branch-named.update-nothing.lxo"> 32.44 +<!ENTITY interaction.branch-named.update-switchy SYSTEM "results/branch-named.update-switchy.lxo"> 32.45 +<!ENTITY interaction.branch-repo.bugfix SYSTEM "results/branch-repo.bugfix.lxo"> 32.46 +<!ENTITY interaction.branch-repo.clone SYSTEM "results/branch-repo.clone.lxo"> 32.47 +<!ENTITY interaction.branch-repo.merge SYSTEM "results/branch-repo.merge.lxo"> 32.48 +<!ENTITY interaction.branch-repo.new SYSTEM "results/branch-repo.new.lxo"> 32.49 +<!ENTITY interaction.branch-repo.pull SYSTEM "results/branch-repo.pull.lxo"> 32.50 +<!ENTITY interaction.branch-repo.tag SYSTEM "results/branch-repo.tag.lxo"> 32.51 +<!ENTITY interaction.branching.clone SYSTEM "results/branching.clone.lxo"> 32.52 +<!ENTITY interaction.branching.init SYSTEM "results/branching.init.lxo"> 32.53 +<!ENTITY interaction.branching.main SYSTEM "results/branching.main.lxo"> 32.54 +<!ENTITY interaction.branching.merge SYSTEM "results/branching.merge.lxo"> 32.55 +<!ENTITY interaction.branching.stable SYSTEM "results/branching.stable.lxo"> 32.56 +<!ENTITY interaction.branching.tag SYSTEM "results/branching.tag.lxo"> 32.57 +<!ENTITY interaction.branching.update SYSTEM "results/branching.update.lxo"> 32.58 +<!ENTITY interaction.ch01-new.add SYSTEM "results/ch01-new.add.lxo"> 32.59 +<!ENTITY interaction.ch01-new.commit SYSTEM "results/ch01-new.commit.lxo"> 32.60 +<!ENTITY interaction.ch01-new.init SYSTEM "results/ch01-new.init.lxo"> 32.61 +<!ENTITY interaction.ch01-new.ls SYSTEM "results/ch01-new.ls.lxo"> 32.62 +<!ENTITY interaction.ch01-new.ls2 SYSTEM "results/ch01-new.ls2.lxo"> 32.63 +<!ENTITY interaction.ch02-rename.alice SYSTEM "results/ch02-rename.alice.lxo"> 32.64 +<!ENTITY interaction.ch02-rename.bob SYSTEM "results/ch02-rename.bob.lxo"> 32.65 +<!ENTITY interaction.ch02-rename.clone SYSTEM "results/ch02-rename.clone.lxo"> 32.66 +<!ENTITY interaction.ch02-rename.clone2 SYSTEM "results/ch02-rename.clone2.lxo"> 32.67 +<!ENTITY interaction.ch02-rename.init SYSTEM "results/ch02-rename.init.lxo"> 32.68 +<!ENTITY interaction.ch02-rename.merge SYSTEM "results/ch02-rename.merge.lxo"> 32.69 +<!ENTITY interaction.ch02-rename.merge2 SYSTEM "results/ch02-rename.merge2.lxo"> 32.70 +<!ENTITY interaction.ch02-rename.status SYSTEM "results/ch02-rename.status.lxo"> 32.71 +<!ENTITY interaction.ch02-rename.status2 SYSTEM "results/ch02-rename.status2.lxo"> 32.72 +<!ENTITY interaction.ch04-diff.chmod SYSTEM "results/ch04-diff.chmod.lxo"> 32.73 +<!ENTITY interaction.ch04-diff.chmod.git SYSTEM "results/ch04-diff.chmod.git.lxo"> 32.74 +<!ENTITY interaction.ch04-diff.rename.basic SYSTEM "results/ch04-diff.rename.basic.lxo"> 32.75 +<!ENTITY interaction.ch04-diff.rename.git SYSTEM "results/ch04-diff.rename.git.lxo"> 32.76 +<!ENTITY interaction.ch04-rename.basic SYSTEM "results/ch04-rename.basic.lxo"> 32.77 +<!ENTITY interaction.ch04-resolve.cifail SYSTEM "results/ch04-resolve.cifail.lxo"> 32.78 +<!ENTITY interaction.ch04-resolve.export SYSTEM "results/ch04-resolve.export.lxo"> 32.79 +<!ENTITY interaction.ch04-resolve.heads SYSTEM "results/ch04-resolve.heads.lxo"> 32.80 +<!ENTITY interaction.ch04-resolve.init SYSTEM "results/ch04-resolve.init.lxo"> 32.81 +<!ENTITY interaction.ch04-resolve.left SYSTEM "results/ch04-resolve.left.lxo"> 32.82 +<!ENTITY interaction.ch04-resolve.list SYSTEM "results/ch04-resolve.list.lxo"> 32.83 +<!ENTITY interaction.ch04-resolve.merge SYSTEM "results/ch04-resolve.merge.lxo"> 32.84 +<!ENTITY interaction.ch04-resolve.pull SYSTEM "results/ch04-resolve.pull.lxo"> 32.85 +<!ENTITY interaction.ch04-resolve.right SYSTEM "results/ch04-resolve.right.lxo"> 32.86 +<!ENTITY interaction.ch09-hook.ws.better SYSTEM "results/ch09-hook.ws.better.lxo"> 32.87 +<!ENTITY interaction.ch09-hook.ws.simple SYSTEM "results/ch09-hook.ws.simple.lxo"> 32.88 +<!ENTITY interaction.ch10-multiline.go SYSTEM "results/ch10-multiline.go.lxo"> 32.89 +<!ENTITY interaction.ch10-multiline.orig.go SYSTEM "results/ch10-multiline.orig.go.lxo"> 32.90 +<!ENTITY interaction.ch11-qdelete.convert SYSTEM "results/ch11-qdelete.convert.lxo"> 32.91 +<!ENTITY interaction.ch11-qdelete.go SYSTEM "results/ch11-qdelete.go.lxo"> 32.92 +<!ENTITY interaction.ch11-qdelete.import SYSTEM "results/ch11-qdelete.import.lxo"> 32.93 +<!ENTITY interaction.cmdref.diff-p SYSTEM "results/cmdref.diff-p.lxo"> 32.94 +<!ENTITY interaction.daily.copy.after SYSTEM "results/daily.copy.after.lxo"> 32.95 +<!ENTITY interaction.daily.copy.cat SYSTEM "results/daily.copy.cat.lxo"> 32.96 +<!ENTITY interaction.daily.copy.clone SYSTEM "results/daily.copy.clone.lxo"> 32.97 +<!ENTITY interaction.daily.copy.copy SYSTEM "results/daily.copy.copy.lxo"> 32.98 +<!ENTITY interaction.daily.copy.dir-dest SYSTEM "results/daily.copy.dir-dest.lxo"> 32.99 +<!ENTITY interaction.daily.copy.dir-src SYSTEM "results/daily.copy.dir-src.lxo"> 32.100 +<!ENTITY interaction.daily.copy.dir-src-dest SYSTEM "results/daily.copy.dir-src-dest.lxo"> 32.101 +<!ENTITY interaction.daily.copy.init SYSTEM "results/daily.copy.init.lxo"> 32.102 +<!ENTITY interaction.daily.copy.merge SYSTEM "results/daily.copy.merge.lxo"> 32.103 +<!ENTITY interaction.daily.copy.orig.after SYSTEM "results/daily.copy.orig.after.lxo"> 32.104 +<!ENTITY interaction.daily.copy.orig.cat SYSTEM "results/daily.copy.orig.cat.lxo"> 32.105 +<!ENTITY interaction.daily.copy.orig.clone SYSTEM "results/daily.copy.orig.clone.lxo"> 32.106 +<!ENTITY interaction.daily.copy.orig.copy SYSTEM "results/daily.copy.orig.copy.lxo"> 32.107 +<!ENTITY interaction.daily.copy.orig.dir-dest SYSTEM "results/daily.copy.orig.dir-dest.lxo"> 32.108 +<!ENTITY interaction.daily.copy.orig.dir-src SYSTEM "results/daily.copy.orig.dir-src.lxo"> 32.109 +<!ENTITY interaction.daily.copy.orig.dir-src-dest SYSTEM "results/daily.copy.orig.dir-src-dest.lxo"> 32.110 +<!ENTITY interaction.daily.copy.orig.init SYSTEM "results/daily.copy.orig.init.lxo"> 32.111 +<!ENTITY interaction.daily.copy.orig.merge SYSTEM "results/daily.copy.orig.merge.lxo"> 32.112 +<!ENTITY interaction.daily.copy.orig.other SYSTEM "results/daily.copy.orig.other.lxo"> 32.113 +<!ENTITY interaction.daily.copy.orig.simple SYSTEM "results/daily.copy.orig.simple.lxo"> 32.114 +<!ENTITY interaction.daily.copy.orig.status SYSTEM "results/daily.copy.orig.status.lxo"> 32.115 +<!ENTITY interaction.daily.copy.orig.status-copy SYSTEM "results/daily.copy.orig.status-copy.lxo"> 32.116 +<!ENTITY interaction.daily.copy.other SYSTEM "results/daily.copy.other.lxo"> 32.117 +<!ENTITY interaction.daily.copy.simple SYSTEM "results/daily.copy.simple.lxo"> 32.118 +<!ENTITY interaction.daily.copy.status SYSTEM "results/daily.copy.status.lxo"> 32.119 +<!ENTITY interaction.daily.copy.status-copy SYSTEM "results/daily.copy.status-copy.lxo"> 32.120 +<!ENTITY interaction.daily.files.add SYSTEM "results/daily.files.add.lxo"> 32.121 +<!ENTITY interaction.daily.files.add-dir SYSTEM "results/daily.files.add-dir.lxo"> 32.122 +<!ENTITY interaction.daily.files.addremove SYSTEM "results/daily.files.addremove.lxo"> 32.123 +<!ENTITY interaction.daily.files.commit-addremove SYSTEM "results/daily.files.commit-addremove.lxo"> 32.124 +<!ENTITY interaction.daily.files.hidden SYSTEM "results/daily.files.hidden.lxo"> 32.125 +<!ENTITY interaction.daily.files.missing SYSTEM "results/daily.files.missing.lxo"> 32.126 +<!ENTITY interaction.daily.files.recover-missing SYSTEM "results/daily.files.recover-missing.lxo"> 32.127 +<!ENTITY interaction.daily.files.remove SYSTEM "results/daily.files.remove.lxo"> 32.128 +<!ENTITY interaction.daily.files.remove-after SYSTEM "results/daily.files.remove-after.lxo"> 32.129 +<!ENTITY interaction.daily.rename.rename SYSTEM "results/daily.rename.rename.lxo"> 32.130 +<!ENTITY interaction.daily.rename.status SYSTEM "results/daily.rename.status.lxo"> 32.131 +<!ENTITY interaction.daily.rename.status-copy SYSTEM "results/daily.rename.status-copy.lxo"> 32.132 +<!ENTITY interaction.daily.revert.add SYSTEM "results/daily.revert.add.lxo"> 32.133 +<!ENTITY interaction.daily.revert.copy SYSTEM "results/daily.revert.copy.lxo"> 32.134 +<!ENTITY interaction.daily.revert.missing SYSTEM "results/daily.revert.missing.lxo"> 32.135 +<!ENTITY interaction.daily.revert.modify SYSTEM "results/daily.revert.modify.lxo"> 32.136 +<!ENTITY interaction.daily.revert.remove SYSTEM "results/daily.revert.remove.lxo"> 32.137 +<!ENTITY interaction.daily.revert.rename SYSTEM "results/daily.revert.rename.lxo"> 32.138 +<!ENTITY interaction.daily.revert.rename-orig SYSTEM "results/daily.revert.rename-orig.lxo"> 32.139 +<!ENTITY interaction.daily.revert.status SYSTEM "results/daily.revert.status.lxo"> 32.140 +<!ENTITY interaction.daily.revert.unmodify SYSTEM "results/daily.revert.unmodify.lxo"> 32.141 +<!ENTITY interaction.extdiff.diff SYSTEM "results/extdiff.diff.lxo"> 32.142 +<!ENTITY interaction.extdiff.extdiff SYSTEM "results/extdiff.extdiff.lxo"> 32.143 +<!ENTITY interaction.extdiff.extdiff-ctx SYSTEM "results/extdiff.extdiff-ctx.lxo"> 32.144 +<!ENTITY interaction.filenames.dirs SYSTEM "results/filenames.dirs.lxo"> 32.145 +<!ENTITY interaction.filenames.files SYSTEM "results/filenames.files.lxo"> 32.146 +<!ENTITY interaction.filenames.filter.exclude SYSTEM "results/filenames.filter.exclude.lxo"> 32.147 +<!ENTITY interaction.filenames.filter.include SYSTEM "results/filenames.filter.include.lxo"> 32.148 +<!ENTITY interaction.filenames.glob.group SYSTEM "results/filenames.glob.group.lxo"> 32.149 +<!ENTITY interaction.filenames.glob.question SYSTEM "results/filenames.glob.question.lxo"> 32.150 +<!ENTITY interaction.filenames.glob.range SYSTEM "results/filenames.glob.range.lxo"> 32.151 +<!ENTITY interaction.filenames.glob.star SYSTEM "results/filenames.glob.star.lxo"> 32.152 +<!ENTITY interaction.filenames.glob.star-starstar SYSTEM "results/filenames.glob.star-starstar.lxo"> 32.153 +<!ENTITY interaction.filenames.glob.starstar SYSTEM "results/filenames.glob.starstar.lxo"> 32.154 +<!ENTITY interaction.filenames.wdir-relname SYSTEM "results/filenames.wdir-relname.lxo"> 32.155 +<!ENTITY interaction.filenames.wdir-subdir SYSTEM "results/filenames.wdir-subdir.lxo"> 32.156 +<!ENTITY interaction.hook.msglen.go SYSTEM "results/hook.msglen.go.lxo"> 32.157 +<!ENTITY interaction.hook.simple.ext SYSTEM "results/hook.simple.ext.lxo"> 32.158 +<!ENTITY interaction.hook.simple.init SYSTEM "results/hook.simple.init.lxo"> 32.159 +<!ENTITY interaction.hook.simple.pretxncommit SYSTEM "results/hook.simple.pretxncommit.lxo"> 32.160 +<!ENTITY interaction.issue29.go SYSTEM "results/issue29.go.lxo"> 32.161 +<!ENTITY interaction.mq.dodiff.diff SYSTEM "results/mq.dodiff.diff.lxo"> 32.162 +<!ENTITY interaction.mq.guards.init SYSTEM "results/mq.guards.init.lxo"> 32.163 +<!ENTITY interaction.mq.guards.qguard SYSTEM "results/mq.guards.qguard.lxo"> 32.164 +<!ENTITY interaction.mq.guards.qguard.neg SYSTEM "results/mq.guards.qguard.neg.lxo"> 32.165 +<!ENTITY interaction.mq.guards.qguard.pos SYSTEM "results/mq.guards.qguard.pos.lxo"> 32.166 +<!ENTITY interaction.mq.guards.qselect.cat SYSTEM "results/mq.guards.qselect.cat.lxo"> 32.167 +<!ENTITY interaction.mq.guards.qselect.error SYSTEM "results/mq.guards.qselect.error.lxo"> 32.168 +<!ENTITY interaction.mq.guards.qselect.foo SYSTEM "results/mq.guards.qselect.foo.lxo"> 32.169 +<!ENTITY interaction.mq.guards.qselect.foobar SYSTEM "results/mq.guards.qselect.foobar.lxo"> 32.170 +<!ENTITY interaction.mq.guards.qselect.qpush SYSTEM "results/mq.guards.qselect.qpush.lxo"> 32.171 +<!ENTITY interaction.mq.guards.qselect.quux SYSTEM "results/mq.guards.qselect.quux.lxo"> 32.172 +<!ENTITY interaction.mq.guards.series SYSTEM "results/mq.guards.series.lxo"> 32.173 +<!ENTITY interaction.mq.id.lxoput SYSTEM "results/mq.id.lxoput.lxo"> 32.174 +<!ENTITY interaction.mq.id.output SYSTEM "results/mq.id.output.lxo"> 32.175 +<!ENTITY interaction.mq.qinit-help.help SYSTEM "results/mq.qinit-help.help.lxo"> 32.176 +<!ENTITY interaction.mq.tarball.download SYSTEM "results/mq.tarball.download.lxo"> 32.177 +<!ENTITY interaction.mq.tarball.newsource SYSTEM "results/mq.tarball.newsource.lxo"> 32.178 +<!ENTITY interaction.mq.tarball.qinit SYSTEM "results/mq.tarball.qinit.lxo"> 32.179 +<!ENTITY interaction.mq.tarball.repush SYSTEM "results/mq.tarball.repush.lxo"> 32.180 +<!ENTITY interaction.mq.tools.lsdiff SYSTEM "results/mq.tools.lsdiff.lxo"> 32.181 +<!ENTITY interaction.mq.tools.tools SYSTEM "results/mq.tools.tools.lxo"> 32.182 +<!ENTITY interaction.mq.tutorial.add SYSTEM "results/mq.tutorial.add.lxo"> 32.183 +<!ENTITY interaction.mq.tutorial.qinit SYSTEM "results/mq.tutorial.qinit.lxo"> 32.184 +<!ENTITY interaction.mq.tutorial.qnew SYSTEM "results/mq.tutorial.qnew.lxo"> 32.185 +<!ENTITY interaction.mq.tutorial.qnew2 SYSTEM "results/mq.tutorial.qnew2.lxo"> 32.186 +<!ENTITY interaction.mq.tutorial.qpop SYSTEM "results/mq.tutorial.qpop.lxo"> 32.187 +<!ENTITY interaction.mq.tutorial.qpush-a SYSTEM "results/mq.tutorial.qpush-a.lxo"> 32.188 +<!ENTITY interaction.mq.tutorial.qrefresh SYSTEM "results/mq.tutorial.qrefresh.lxo"> 32.189 +<!ENTITY interaction.mq.tutorial.qrefresh2 SYSTEM "results/mq.tutorial.qrefresh2.lxo"> 32.190 +<!ENTITY interaction.mq.tutorial.qseries SYSTEM "results/mq.tutorial.qseries.lxo"> 32.191 +<!ENTITY interaction.rename.divergent.clone SYSTEM "results/rename.divergent.clone.lxo"> 32.192 +<!ENTITY interaction.rename.divergent.merge SYSTEM "results/rename.divergent.merge.lxo"> 32.193 +<!ENTITY interaction.rename.divergent.rename.anne SYSTEM "results/rename.divergent.rename.anne.lxo"> 32.194 +<!ENTITY interaction.rename.divergent.rename.bob SYSTEM "results/rename.divergent.rename.bob.lxo"> 32.195 +<!ENTITY interaction.rollback.add SYSTEM "results/rollback.add.lxo"> 32.196 +<!ENTITY interaction.rollback.commit SYSTEM "results/rollback.commit.lxo"> 32.197 +<!ENTITY interaction.rollback.rollback SYSTEM "results/rollback.rollback.lxo"> 32.198 +<!ENTITY interaction.rollback.status SYSTEM "results/rollback.status.lxo"> 32.199 +<!ENTITY interaction.rollback.tip SYSTEM "results/rollback.tip.lxo"> 32.200 +<!ENTITY interaction.rollback.twice SYSTEM "results/rollback.twice.lxo"> 32.201 +<!ENTITY interaction.tag.init SYSTEM "results/tag.init.lxo"> 32.202 +<!ENTITY interaction.tag.log SYSTEM "results/tag.log.lxo"> 32.203 +<!ENTITY interaction.tag.log.v1.0 SYSTEM "results/tag.log.v1.0.lxo"> 32.204 +<!ENTITY interaction.tag.remove SYSTEM "results/tag.remove.lxo"> 32.205 +<!ENTITY interaction.tag.replace SYSTEM "results/tag.replace.lxo"> 32.206 +<!ENTITY interaction.tag.tag SYSTEM "results/tag.tag.lxo"> 32.207 +<!ENTITY interaction.tag.tags SYSTEM "results/tag.tags.lxo"> 32.208 +<!ENTITY interaction.tag.tip SYSTEM "results/tag.tip.lxo"> 32.209 +<!ENTITY interaction.template.simple.changelog SYSTEM "results/template.simple.changelog.lxo"> 32.210 +<!ENTITY interaction.template.simple.combine SYSTEM "results/template.simple.combine.lxo"> 32.211 +<!ENTITY interaction.template.simple.compact SYSTEM "results/template.simple.compact.lxo"> 32.212 +<!ENTITY interaction.template.simple.datekeyword SYSTEM "results/template.simple.datekeyword.lxo"> 32.213 +<!ENTITY interaction.template.simple.keywords SYSTEM "results/template.simple.keywords.lxo"> 32.214 +<!ENTITY interaction.template.simple.manyfilters SYSTEM "results/template.simple.manyfilters.lxo"> 32.215 +<!ENTITY interaction.template.simple.normal SYSTEM "results/template.simple.normal.lxo"> 32.216 +<!ENTITY interaction.template.simple.rev SYSTEM "results/template.simple.rev.lxo"> 32.217 +<!ENTITY interaction.template.simple.simplest SYSTEM "results/template.simple.simplest.lxo"> 32.218 +<!ENTITY interaction.template.simple.simplesub SYSTEM "results/template.simple.simplesub.lxo"> 32.219 +<!ENTITY interaction.template.svnstyle.id SYSTEM "results/template.svnstyle.id.lxo"> 32.220 +<!ENTITY interaction.template.svnstyle.result SYSTEM "results/template.svnstyle.result.lxo"> 32.221 +<!ENTITY interaction.template.svnstyle.short SYSTEM "results/template.svnstyle.short.lxo"> 32.222 +<!ENTITY interaction.template.svnstyle.simplest SYSTEM "results/template.svnstyle.simplest.lxo"> 32.223 +<!ENTITY interaction.template.svnstyle.style SYSTEM "results/template.svnstyle.style.lxo"> 32.224 +<!ENTITY interaction.template.svnstyle.syntax.error SYSTEM "results/template.svnstyle.syntax.error.lxo"> 32.225 +<!ENTITY interaction.template.svnstyle.syntax.input SYSTEM "results/template.svnstyle.syntax.input.lxo"> 32.226 +<!ENTITY interaction.template.svnstyle.template SYSTEM "results/template.svnstyle.template.lxo"> 32.227 +<!ENTITY interaction.tour-merge-conflict.commit SYSTEM "results/tour-merge-conflict.commit.lxo"> 32.228 +<!ENTITY interaction.tour-merge-conflict.cousin SYSTEM "results/tour-merge-conflict.cousin.lxo"> 32.229 +<!ENTITY interaction.tour-merge-conflict.merge SYSTEM "results/tour-merge-conflict.merge.lxo"> 32.230 +<!ENTITY interaction.tour-merge-conflict.pull SYSTEM "results/tour-merge-conflict.pull.lxo"> 32.231 +<!ENTITY interaction.tour-merge-conflict.son SYSTEM "results/tour-merge-conflict.son.lxo"> 32.232 +<!ENTITY interaction.tour-merge-conflict.wife SYSTEM "results/tour-merge-conflict.wife.lxo"> 32.233 +<!ENTITY interaction.tour.cat1 SYSTEM "results/tour.cat1.lxo"> 32.234 +<!ENTITY interaction.tour.cat2 SYSTEM "results/tour.cat2.lxo"> 32.235 +<!ENTITY interaction.tour.clone SYSTEM "results/tour.clone.lxo"> 32.236 +<!ENTITY interaction.tour.clone-pull SYSTEM "results/tour.clone-pull.lxo"> 32.237 +<!ENTITY interaction.tour.clone-push SYSTEM "results/tour.clone-push.lxo"> 32.238 +<!ENTITY interaction.tour.commit SYSTEM "results/tour.commit.lxo"> 32.239 +<!ENTITY interaction.tour.diff SYSTEM "results/tour.diff.lxo"> 32.240 +<!ENTITY interaction.tour.help SYSTEM "results/tour.help.lxo"> 32.241 +<!ENTITY interaction.tour.incoming SYSTEM "results/tour.incoming.lxo"> 32.242 +<!ENTITY interaction.tour.log SYSTEM "results/tour.log.lxo"> 32.243 +<!ENTITY interaction.tour.log-r SYSTEM "results/tour.log-r.lxo"> 32.244 +<!ENTITY interaction.tour.log-v SYSTEM "results/tour.log-v.lxo"> 32.245 +<!ENTITY interaction.tour.log-vp SYSTEM "results/tour.log-vp.lxo"> 32.246 +<!ENTITY interaction.tour.log.range SYSTEM "results/tour.log.range.lxo"> 32.247 +<!ENTITY interaction.tour.ls SYSTEM "results/tour.ls.lxo"> 32.248 +<!ENTITY interaction.tour.ls-a SYSTEM "results/tour.ls-a.lxo"> 32.249 +<!ENTITY interaction.tour.lxogoing SYSTEM "results/tour.lxogoing.lxo"> 32.250 +<!ENTITY interaction.tour.lxogoing.net SYSTEM "results/tour.lxogoing.net.lxo"> 32.251 +<!ENTITY interaction.tour.merge.cat SYSTEM "results/tour.merge.cat.lxo"> 32.252 +<!ENTITY interaction.tour.merge.cat1 SYSTEM "results/tour.merge.cat1.lxo"> 32.253 +<!ENTITY interaction.tour.merge.cat2 SYSTEM "results/tour.merge.cat2.lxo"> 32.254 +<!ENTITY interaction.tour.merge.clone SYSTEM "results/tour.merge.clone.lxo"> 32.255 +<!ENTITY interaction.tour.merge.commit SYSTEM "results/tour.merge.commit.lxo"> 32.256 +<!ENTITY interaction.tour.merge.dummy1 SYSTEM "results/tour.merge.dummy1.lxo"> 32.257 +<!ENTITY interaction.tour.merge.dummy2 SYSTEM "results/tour.merge.dummy2.lxo"> 32.258 +<!ENTITY interaction.tour.merge.dummy3 SYSTEM "results/tour.merge.dummy3.lxo"> 32.259 +<!ENTITY interaction.tour.merge.dummy4 SYSTEM "results/tour.merge.dummy4.lxo"> 32.260 +<!ENTITY interaction.tour.merge.heads SYSTEM "results/tour.merge.heads.lxo"> 32.261 +<!ENTITY interaction.tour.merge.merge SYSTEM "results/tour.merge.merge.lxo"> 32.262 +<!ENTITY interaction.tour.merge.parents SYSTEM "results/tour.merge.parents.lxo"> 32.263 +<!ENTITY interaction.tour.merge.pull SYSTEM "results/tour.merge.pull.lxo"> 32.264 +<!ENTITY interaction.tour.merge.tip SYSTEM "results/tour.merge.tip.lxo"> 32.265 +<!ENTITY interaction.tour.merge.update SYSTEM "results/tour.merge.update.lxo"> 32.266 +<!ENTITY interaction.tour.older SYSTEM "results/tour.older.lxo"> 32.267 +<!ENTITY interaction.tour.outgoing SYSTEM "results/tour.outgoing.lxo"> 32.268 +<!ENTITY interaction.tour.outgoing.net SYSTEM "results/tour.outgoing.net.lxo"> 32.269 +<!ENTITY interaction.tour.parents SYSTEM "results/tour.parents.lxo"> 32.270 +<!ENTITY interaction.tour.pull SYSTEM "results/tour.pull.lxo"> 32.271 +<!ENTITY interaction.tour.push SYSTEM "results/tour.push.lxo"> 32.272 +<!ENTITY interaction.tour.push.net SYSTEM "results/tour.push.net.lxo"> 32.273 +<!ENTITY interaction.tour.push.nothing SYSTEM "results/tour.push.nothing.lxo"> 32.274 +<!ENTITY interaction.tour.reclone SYSTEM "results/tour.reclone.lxo"> 32.275 +<!ENTITY interaction.tour.sed SYSTEM "results/tour.sed.lxo"> 32.276 +<!ENTITY interaction.tour.status SYSTEM "results/tour.status.lxo"> 32.277 +<!ENTITY interaction.tour.tip SYSTEM "results/tour.tip.lxo"> 32.278 +<!ENTITY interaction.tour.update SYSTEM "results/tour.update.lxo"> 32.279 +<!ENTITY interaction.tour.version SYSTEM "results/tour.version.lxo">
33.1 --- a/fr/examples/data/check_whitespace.py Sun Aug 16 03:41:39 2009 +0200 33.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 33.3 @@ -1,44 +0,0 @@ 33.4 -#!/usr/bin/python 33.5 - 33.6 -import re 33.7 - 33.8 -def trailing_whitespace(difflines): 33.9 - added, linenum, header = [], 0, False 33.10 - 33.11 - for line in difflines: 33.12 - if header: 33.13 - # remember the name of the file that this diff affects 33.14 - m = re.match(r'(?:---|\+\+\+) ([^\t]+)', line) 33.15 - if m and m.group(1) != '/dev/null': 33.16 - filename = m.group(1).split('/', 1)[-1] 33.17 - if line.startswith('+++ '): 33.18 - header = False 33.19 - continue 33.20 - if line.startswith('diff '): 33.21 - header = True 33.22 - continue 33.23 - # hunk header - save the line number 33.24 - m = re.match(r'@@ -\d+,\d+ \+(\d+),', line) 33.25 - if m: 33.26 - linenum = int(m.group(1)) 33.27 - continue 33.28 - # hunk body - check for an added line with trailing whitespace 33.29 - m = re.match(r'\+.*\s$', line) 33.30 - if m: 33.31 - added.append((filename, linenum)) 33.32 - if line and line[0] in ' +': 33.33 - linenum += 1 33.34 - return added 33.35 - 33.36 -if __name__ == '__main__': 33.37 - import os, sys 33.38 - 33.39 - added = trailing_whitespace(os.popen('hg export tip')) 33.40 - if added: 33.41 - for filename, linenum in added: 33.42 - print >> sys.stderr, ('%s, line %d: trailing whitespace added' % 33.43 - (filename, linenum)) 33.44 - # save the commit message so we don't need to retype it 33.45 - os.system('hg tip --template "{desc}" > .hg/commit.save') 33.46 - print >> sys.stderr, 'commit message saved to .hg/commit.save' 33.47 - sys.exit(1)
34.1 --- a/fr/examples/hook.ws Sun Aug 16 03:41:39 2009 +0200 34.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 34.3 @@ -1,31 +0,0 @@ 34.4 -#!/bin/bash 34.5 - 34.6 -hg init a 34.7 -cd a 34.8 -echo '[hooks]' > .hg/hgrc 34.9 -echo "pretxncommit.whitespace = hg export tip | (! egrep -q '^\\+.*[ \\t]$')" >> .hg/hgrc 34.10 - 34.11 -#$ name: simple 34.12 - 34.13 -cat .hg/hgrc 34.14 -echo 'a ' > a 34.15 -hg commit -A -m 'test with trailing whitespace' 34.16 -echo 'a' > a 34.17 -hg commit -A -m 'drop trailing whitespace and try again' 34.18 - 34.19 -#$ name: 34.20 - 34.21 -echo '[hooks]' > .hg/hgrc 34.22 -echo "pretxncommit.whitespace = .hg/check_whitespace.py" >> .hg/hgrc 34.23 -cp $EXAMPLE_DIR/data/check_whitespace.py .hg 34.24 - 34.25 -#$ name: better 34.26 - 34.27 -cat .hg/hgrc 34.28 -echo 'a ' >> a 34.29 -hg commit -A -m 'add new line with trailing whitespace' 34.30 -sed -i 's, *$,,' a 34.31 -hg commit -A -m 'trimmed trailing whitespace' 34.32 - 34.33 -#$ name: 34.34 -exit 0
35.1 --- a/fr/feature-branches.dot Sun Aug 16 03:41:39 2009 +0200 35.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 35.3 @@ -1,8 +0,0 @@ 35.4 -digraph feature_branches { 35.5 - master -> crypto; 35.6 - master -> filesystems; 35.7 - master -> ipc; 35.8 - master -> memory; 35.9 - master -> network; 35.10 - master -> security; 35.11 -}
36.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 36.2 +++ b/fr/figs/bad-merge-1.dot Sun Aug 16 04:58:01 2009 +0200 36.3 @@ -0,0 +1,13 @@ 36.4 +digraph bad_merge_1 { 36.5 + ancestor [label="1: ancestor"]; 36.6 + left [label="2: my change"]; 36.7 + right [label="3: your change"]; 36.8 + bad [label="4: bad merge"]; 36.9 + new [label="5: new change"]; 36.10 + 36.11 + ancestor -> left; 36.12 + ancestor -> right; 36.13 + left -> bad; 36.14 + right -> bad; 36.15 + bad -> new; 36.16 +}
37.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 37.2 +++ b/fr/figs/bad-merge-2.dot Sun Aug 16 04:58:01 2009 +0200 37.3 @@ -0,0 +1,18 @@ 37.4 +digraph bad_merge_2 { 37.5 + ancestor [label="1: ancestor",color=grey,fontcolor=grey]; 37.6 + left [label="2: my change",color=grey,fontcolor=grey]; 37.7 + right [label="3: your change",color=grey,fontcolor=grey]; 37.8 + bad [label="4: bad merge",color=grey,fontcolor=grey]; 37.9 + new [label="5: new change",color=grey,fontcolor=grey]; 37.10 + 37.11 + bak_left [label="6: backout 1 of\nbad merge",shape=box]; 37.12 + 37.13 + ancestor -> left [color=grey]; 37.14 + ancestor -> right [color=grey]; 37.15 + left -> bad [color=grey]; 37.16 + right -> bad [color=grey]; 37.17 + bad -> new [color=grey]; 37.18 + 37.19 + bad -> bak_left; 37.20 + left -> bak_left [style=dotted,label="--parent=2"]; 37.21 +}
38.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 38.2 +++ b/fr/figs/bad-merge-3.dot Sun Aug 16 04:58:01 2009 +0200 38.3 @@ -0,0 +1,22 @@ 38.4 +digraph bad_merge_3 { 38.5 + ancestor [label="1: ancestor",color="#bbbbbb",fontcolor="#bbbbbb"]; 38.6 + left [label="2: my change",color="#bbbbbb",fontcolor="#bbbbbb"]; 38.7 + right [label="3: your change",color="#bbbbbb",fontcolor="#bbbbbb"]; 38.8 + bad [label="4: bad merge",color="#bbbbbb",fontcolor="#bbbbbb"]; 38.9 + new [label="5: new change",color="#bbbbbb",fontcolor="#bbbbbb"]; 38.10 + 38.11 + bak_left [label="6: backout 1 of\nbad merge",color=grey,shape=box]; 38.12 + bak_right [label="8: backout 2 of\nbad merge",shape=box]; 38.13 + 38.14 + ancestor -> left [color="#bbbbbb"]; 38.15 + ancestor -> right [color="#bbbbbb"]; 38.16 + left -> bad [color="#bbbbbb"]; 38.17 + right -> bad [color="#bbbbbb"]; 38.18 + bad -> new [color="#bbbbbb"]; 38.19 + 38.20 + bad -> bak_left [color=grey]; 38.21 + left -> bak_left [style=dotted,label="--parent=2",color=grey,fontcolor=grey]; 38.22 + 38.23 + bad -> bak_right; 38.24 + right -> bak_right [style=dotted,label="--parent=3"]; 38.25 +}
39.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 39.2 +++ b/fr/figs/bad-merge-4.dot Sun Aug 16 04:58:01 2009 +0200 39.3 @@ -0,0 +1,26 @@ 39.4 +digraph bad_merge_4 { 39.5 + ancestor [label="1: ancestor",color="#bbbbbb",fontcolor="#bbbbbb"]; 39.6 + left [label="2: my change",color="#bbbbbb",fontcolor="#bbbbbb"]; 39.7 + right [label="3: your change",color="#bbbbbb",fontcolor="#bbbbbb"]; 39.8 + bad [label="4: bad merge",color="#bbbbbb",fontcolor="#bbbbbb"]; 39.9 + new [label="5: new change",color="#bbbbbb",fontcolor="#bbbbbb"]; 39.10 + 39.11 + bak_left [label="6: backout 1 of\nbad merge",color=grey,fontcolor=grey,shape=box]; 39.12 + bak_right [label="7: backout 2 of\nbad merge",color=grey,fontcolor=grey,shape=box]; 39.13 + good [label="8: merge\nof backouts",shape=box]; 39.14 + 39.15 + ancestor -> left [color="#bbbbbb"]; 39.16 + ancestor -> right [color="#bbbbbb"]; 39.17 + left -> bad [color="#bbbbbb"]; 39.18 + right -> bad [color="#bbbbbb"]; 39.19 + bad -> new [color="#bbbbbb"]; 39.20 + 39.21 + bad -> bak_left [color=grey]; 39.22 + left -> bak_left [style=dotted,label="--parent=2",color=grey,fontcolor=grey]; 39.23 + 39.24 + bad -> bak_right [color=grey]; 39.25 + right -> bak_right [style=dotted,label="--parent=3",color=grey,fontcolor=grey]; 39.26 + 39.27 + bak_left -> good; 39.28 + bak_right -> good; 39.29 +}
40.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 40.2 +++ b/fr/figs/bad-merge-5.dot Sun Aug 16 04:58:01 2009 +0200 40.3 @@ -0,0 +1,30 @@ 40.4 +digraph bad_merge_5 { 40.5 + ancestor [label="1: ancestor",color="#bbbbbb",fontcolor="#bbbbbb"]; 40.6 + left [label="2: my change",color="#bbbbbb",fontcolor="#bbbbbb"]; 40.7 + right [label="3: your change",color="#bbbbbb",fontcolor="#bbbbbb"]; 40.8 + bad [label="4: bad merge",color="#bbbbbb",fontcolor="#bbbbbb"]; 40.9 + new [label="5: new change",color=grey,fontcolor=grey]; 40.10 + 40.11 + bak_left [label="6: backout 1 of\nbad merge",color="#bbbbbb",fontcolor="#bbbbbb",shape=box]; 40.12 + bak_right [label="7: backout 2 of\nbad merge",color="#bbbbbb",fontcolor="#bbbbbb",shape=box]; 40.13 + good [label="8: merge\nof backouts",color=grey,fontcolor=grey,shape=box]; 40.14 + last [label="9: merge with\nnew change",shape=box]; 40.15 + 40.16 + ancestor -> left [color="#bbbbbb"]; 40.17 + ancestor -> right [color="#bbbbbb"]; 40.18 + left -> bad [color="#bbbbbb"]; 40.19 + right -> bad [color="#bbbbbb"]; 40.20 + bad -> new [color="#bbbbbb"]; 40.21 + 40.22 + bad -> bak_left [color="#bbbbbb"]; 40.23 + left -> bak_left [style=dotted,label="--parent=2",color="#bbbbbb",fontcolor="#bbbbbb"]; 40.24 + 40.25 + bad -> bak_right [color="#bbbbbb"]; 40.26 + right -> bak_right [style=dotted,label="--parent=3",color="#bbbbbb",fontcolor="#bbbbbb"]; 40.27 + 40.28 + bak_left -> good [color=grey]; 40.29 + bak_right -> good [color=grey]; 40.30 + 40.31 + good -> last; 40.32 + new -> last; 40.33 +}
41.1 Binary file fr/figs/caution.png has changed
42.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 42.2 +++ b/fr/figs/feature-branches.dot Sun Aug 16 04:58:01 2009 +0200 42.3 @@ -0,0 +1,8 @@ 42.4 +digraph feature_branches { 42.5 + master -> crypto; 42.6 + master -> filesystems; 42.7 + master -> ipc; 42.8 + master -> memory; 42.9 + master -> network; 42.10 + master -> security; 42.11 +}
43.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 43.2 +++ b/fr/figs/filelog.svg Sun Aug 16 04:58:01 2009 +0200 43.3 @@ -0,0 +1,381 @@ 43.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?> 43.5 +<!-- Created with Inkscape (http://www.inkscape.org/) --> 43.6 +<svg 43.7 + xmlns:dc="http://purl.org/dc/elements/1.1/" 43.8 + xmlns:cc="http://creativecommons.org/ns#" 43.9 + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 43.10 + xmlns:svg="http://www.w3.org/2000/svg" 43.11 + xmlns="http://www.w3.org/2000/svg" 43.12 + xmlns:xlink="http://www.w3.org/1999/xlink" 43.13 + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" 43.14 + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" 43.15 + width="744.09448819" 43.16 + height="1052.3622047" 43.17 + id="svg2" 43.18 + sodipodi:version="0.32" 43.19 + inkscape:version="0.46" 43.20 + sodipodi:docname="filelog.svg" 43.21 + sodipodi:docbase="/home/arun/hgbook/en" 43.22 + inkscape:output_extension="org.inkscape.output.svg.inkscape"> 43.23 + <defs 43.24 + id="defs4"> 43.25 + <inkscape:perspective 43.26 + sodipodi:type="inkscape:persp3d" 43.27 + inkscape:vp_x="0 : 526.18109 : 1" 43.28 + inkscape:vp_y="0 : 1000 : 0" 43.29 + inkscape:vp_z="744.09448 : 526.18109 : 1" 43.30 + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" 43.31 + id="perspective57" /> 43.32 + <marker 43.33 + inkscape:stockid="Arrow1Mend" 43.34 + orient="auto" 43.35 + refY="0.0" 43.36 + refX="0.0" 43.37 + id="Arrow1Mend" 43.38 + style="overflow:visible;"> 43.39 + <path 43.40 + id="path3128" 43.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 " 43.42 + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;" 43.43 + transform="scale(0.4) rotate(180) translate(10,0)" /> 43.44 + </marker> 43.45 + <linearGradient 43.46 + id="linearGradient2887"> 43.47 + <stop 43.48 + style="stop-color:#91cfcf;stop-opacity:1;" 43.49 + offset="0" 43.50 + id="stop2889" /> 43.51 + <stop 43.52 + style="stop-color:aqua;stop-opacity:0;" 43.53 + offset="1" 43.54 + id="stop2891" /> 43.55 + </linearGradient> 43.56 + <linearGradient 43.57 + id="linearGradient2795"> 43.58 + <stop 43.59 + style="stop-color:#ccc;stop-opacity:1;" 43.60 + offset="0" 43.61 + id="stop2797" /> 43.62 + <stop 43.63 + style="stop-color:#ccc;stop-opacity:0;" 43.64 + offset="1" 43.65 + id="stop2799" /> 43.66 + </linearGradient> 43.67 + <linearGradient 43.68 + inkscape:collect="always" 43.69 + xlink:href="#linearGradient2795" 43.70 + id="linearGradient3170" 43.71 + gradientUnits="userSpaceOnUse" 43.72 + gradientTransform="translate(121.2183,94.95434)" 43.73 + x1="81.322357" 43.74 + y1="404.34424" 43.75 + x2="201.52036" 43.76 + y2="373.03967" /> 43.77 + <linearGradient 43.78 + inkscape:collect="always" 43.79 + xlink:href="#linearGradient2887" 43.80 + id="linearGradient3172" 43.81 + gradientUnits="userSpaceOnUse" 43.82 + gradientTransform="translate(0,12)" 43.83 + x1="62.634491" 43.84 + y1="503.3392" 43.85 + x2="248.49242" 43.86 + y2="462.94327" /> 43.87 + <linearGradient 43.88 + inkscape:collect="always" 43.89 + xlink:href="#linearGradient2795" 43.90 + id="linearGradient3174" 43.91 + gradientUnits="userSpaceOnUse" 43.92 + gradientTransform="matrix(1.001035,0,0,0.653159,236.7075,153.0415)" 43.93 + x1="81.322357" 43.94 + y1="404.34424" 43.95 + x2="201.52036" 43.96 + y2="373.03967" /> 43.97 + <linearGradient 43.98 + inkscape:collect="always" 43.99 + xlink:href="#linearGradient2887" 43.100 + id="linearGradient3176" 43.101 + gradientUnits="userSpaceOnUse" 43.102 + gradientTransform="translate(0,12)" 43.103 + x1="62.634491" 43.104 + y1="503.3392" 43.105 + x2="248.49242" 43.106 + y2="462.94327" /> 43.107 + <linearGradient 43.108 + inkscape:collect="always" 43.109 + xlink:href="#linearGradient2795" 43.110 + id="linearGradient3208" 43.111 + gradientUnits="userSpaceOnUse" 43.112 + gradientTransform="matrix(1.001035,0,0,0.653159,236.7075,153.0415)" 43.113 + x1="81.322357" 43.114 + y1="404.34424" 43.115 + x2="201.52036" 43.116 + y2="373.03967" /> 43.117 + <linearGradient 43.118 + inkscape:collect="always" 43.119 + xlink:href="#linearGradient2887" 43.120 + id="linearGradient3210" 43.121 + gradientUnits="userSpaceOnUse" 43.122 + gradientTransform="translate(0,12)" 43.123 + x1="62.634491" 43.124 + y1="503.3392" 43.125 + x2="248.49242" 43.126 + y2="462.94327" /> 43.127 + <linearGradient 43.128 + inkscape:collect="always" 43.129 + xlink:href="#linearGradient2795" 43.130 + id="linearGradient3212" 43.131 + gradientUnits="userSpaceOnUse" 43.132 + gradientTransform="translate(121.2183,94.95434)" 43.133 + x1="81.322357" 43.134 + y1="404.34424" 43.135 + x2="201.52036" 43.136 + y2="373.03967" /> 43.137 + <linearGradient 43.138 + inkscape:collect="always" 43.139 + xlink:href="#linearGradient2887" 43.140 + id="linearGradient3214" 43.141 + gradientUnits="userSpaceOnUse" 43.142 + gradientTransform="translate(0,12)" 43.143 + x1="62.634491" 43.144 + y1="503.3392" 43.145 + x2="248.49242" 43.146 + y2="462.94327" /> 43.147 + <linearGradient 43.148 + inkscape:collect="always" 43.149 + xlink:href="#linearGradient2795" 43.150 + id="linearGradient3256" 43.151 + gradientUnits="userSpaceOnUse" 43.152 + gradientTransform="matrix(1.2343775,0,0,0.9981848,103.25588,95.681888)" 43.153 + x1="74.301666" 43.154 + y1="431.67441" 43.155 + x2="260.05884" 43.156 + y2="369.95322" /> 43.157 + <linearGradient 43.158 + inkscape:collect="always" 43.159 + xlink:href="#linearGradient2887" 43.160 + id="linearGradient3258" 43.161 + gradientUnits="userSpaceOnUse" 43.162 + gradientTransform="matrix(1.228929,0,0,0.9972824,-62.037003,13.312997)" 43.163 + x1="62.634491" 43.164 + y1="503.3392" 43.165 + x2="248.49242" 43.166 + y2="462.94327" /> 43.167 + <linearGradient 43.168 + inkscape:collect="always" 43.169 + xlink:href="#linearGradient2795" 43.170 + id="linearGradient3260" 43.171 + gradientUnits="userSpaceOnUse" 43.172 + gradientTransform="matrix(1.2300738,0,0,0.6517275,219.97511,153.61527)" 43.173 + x1="74.387527" 43.174 + y1="431.80576" 43.175 + x2="259.97339" 43.176 + y2="369.82224" /> 43.177 + <linearGradient 43.178 + inkscape:collect="always" 43.179 + xlink:href="#linearGradient2887" 43.180 + id="linearGradient3262" 43.181 + gradientUnits="userSpaceOnUse" 43.182 + gradientTransform="matrix(1.2289272,0,0,0.9972824,-62.036756,13.312985)" 43.183 + x1="62.634491" 43.184 + y1="503.3392" 43.185 + x2="248.49242" 43.186 + y2="462.94327" /> 43.187 + </defs> 43.188 + <sodipodi:namedview 43.189 + id="base" 43.190 + pagecolor="#ffffff" 43.191 + bordercolor="#666666" 43.192 + borderopacity="1.0" 43.193 + gridtolerance="10000" 43.194 + guidetolerance="10" 43.195 + objecttolerance="10" 43.196 + inkscape:pageopacity="0.0" 43.197 + inkscape:pageshadow="2" 43.198 + inkscape:zoom="1.4" 43.199 + inkscape:cx="455.8122" 43.200 + inkscape:cy="520" 43.201 + inkscape:document-units="px" 43.202 + inkscape:current-layer="g2940" 43.203 + inkscape:window-width="1680" 43.204 + inkscape:window-height="970" 43.205 + inkscape:window-x="3" 43.206 + inkscape:window-y="46" 43.207 + showgrid="false" /> 43.208 + <metadata 43.209 + id="metadata7"> 43.210 + <rdf:RDF> 43.211 + <cc:Work 43.212 + rdf:about=""> 43.213 + <dc:format>image/svg+xml</dc:format> 43.214 + <dc:type 43.215 + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 43.216 + </cc:Work> 43.217 + </rdf:RDF> 43.218 + </metadata> 43.219 + <g 43.220 + inkscape:label="Layer 1" 43.221 + inkscape:groupmode="layer" 43.222 + id="layer1"> 43.223 + <rect 43.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" 43.225 + id="rect3180" 43.226 + width="273.81375" 43.227 + height="199.06245" 43.228 + x="369.1796" 43.229 + y="351.79019" /> 43.230 + <rect 43.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" 43.232 + id="rect3178" 43.233 + width="273.81339" 43.234 + height="199.06233" 43.235 + x="72.699799" 43.236 + y="351.78983" /> 43.237 + <g 43.238 + id="g3144" 43.239 + transform="translate(80.467048,0.71578)"> 43.240 + <g 43.241 + id="g2940"> 43.242 + <rect 43.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" 43.244 + id="rect2914" 43.245 + width="227.38896" 43.246 + height="39.500999" 43.247 + x="311.92496" 43.248 + y="395.08627" /> 43.249 + <text 43.250 + xml:space="preserve" 43.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" 43.252 + x="323.72824" 43.253 + y="416.7626" 43.254 + id="text2918"><tspan 43.255 + sodipodi:role="line" 43.256 + id="tspan2920" 43.257 + x="323.72824" 43.258 + y="416.7626" 43.259 + style="font-family:Courier">.hg/store/data/_r_e_a_d_m_e.i</tspan></text> 43.260 + </g> 43.261 + <g 43.262 + transform="translate(3.79093e-5,-80.1853)" 43.263 + id="g2945"> 43.264 + <g 43.265 + id="g2955"> 43.266 + <rect 43.267 + y="475.4968" 43.268 + x="15.550935" 43.269 + height="39.500999" 43.270 + width="227.17694" 43.271 + id="rect2947" 43.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" /> 43.273 + <text 43.274 + id="text2949" 43.275 + y="498.35123" 43.276 + x="31.230644" 43.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" 43.278 + xml:space="preserve"><tspan 43.279 + style="font-family:Courier" 43.280 + y="498.35123" 43.281 + x="31.230644" 43.282 + id="tspan2951" 43.283 + sodipodi:role="line">README</tspan></text> 43.284 + </g> 43.285 + </g> 43.286 + <path 43.287 + inkscape:connector-type="polyline" 43.288 + id="path2960" 43.289 + d="M 242.94685,414.91115 C 242.94685,414.91115 293.61127,415.26754 310.16269,415.38633" 43.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" 43.291 + sodipodi:nodetypes="cz" /> 43.292 + </g> 43.293 + <g 43.294 + id="g3156" 43.295 + transform="translate(80.467048,0.71578)"> 43.296 + <g 43.297 + transform="translate(116,0)" 43.298 + id="g2831"> 43.299 + <rect 43.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" 43.301 + id="rect1906" 43.302 + width="228.18446" 43.303 + height="60.499123" 43.304 + x="195.52719" 43.305 + y="465.51859" /> 43.306 + <g 43.307 + id="g2803" 43.308 + transform="translate(-0.893671,1.833581)"> 43.309 + <text 43.310 + id="text1884" 43.311 + y="483.92801" 43.312 + x="208.95944" 43.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" 43.314 + xml:space="preserve"><tspan 43.315 + style="font-family:Courier" 43.316 + y="483.92801" 43.317 + x="208.95944" 43.318 + id="tspan1886" 43.319 + sodipodi:role="line">.hg/store/data/src/hello.c.d</tspan></text> 43.320 + <text 43.321 + id="text1888" 43.322 + y="507.79309" 43.323 + x="208.95944" 43.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" 43.325 + xml:space="preserve"><tspan 43.326 + style="font-family:Courier" 43.327 + y="507.79309" 43.328 + x="208.95944" 43.329 + id="tspan1890" 43.330 + sodipodi:role="line">.hg/store/data/src/hello.c.i</tspan></text> 43.331 + </g> 43.332 + </g> 43.333 + <g 43.334 + id="g2907"> 43.335 + <rect 43.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" 43.337 + id="rect2843" 43.338 + width="227.17728" 43.339 + height="39.500999" 43.340 + x="15.550805" 43.341 + y="475.4968" /> 43.342 + <text 43.343 + xml:space="preserve" 43.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" 43.345 + x="31.230644" 43.346 + y="498.35123" 43.347 + id="text2847"><tspan 43.348 + sodipodi:role="line" 43.349 + id="tspan2849" 43.350 + x="31.230644" 43.351 + y="498.35123" 43.352 + style="font-family:Courier">src/hello.c</tspan></text> 43.353 + </g> 43.354 + <path 43.355 + inkscape:connection-end="#g2831" 43.356 + inkscape:connection-start="#g2907" 43.357 + inkscape:connector-type="polyline" 43.358 + id="path2962" 43.359 + d="M 242.4315,495.88043 C 242.4315,495.88043 292.8861,495.99942 310.04102,496.03909" 43.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" 43.361 + sodipodi:nodetypes="cs" /> 43.362 + </g> 43.363 + <text 43.364 + xml:space="preserve" 43.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" 43.366 + x="98.496666" 43.367 + y="373.96353" 43.368 + id="text3216"><tspan 43.369 + sodipodi:role="line" 43.370 + id="tspan3218" 43.371 + x="98.496666" 43.372 + y="373.96353">Working directory</tspan></text> 43.373 + <text 43.374 + xml:space="preserve" 43.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" 43.376 + x="391.39197" 43.377 + y="373.96353" 43.378 + id="text3228"><tspan 43.379 + sodipodi:role="line" 43.380 + id="tspan3230" 43.381 + x="391.39197" 43.382 + y="373.96353">Repository</tspan></text> 43.383 + </g> 43.384 +</svg>
44.1 Binary file fr/figs/kdiff3.png has changed
45.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 45.2 +++ b/fr/figs/metadata.svg Sun Aug 16 04:58:01 2009 +0200 45.3 @@ -0,0 +1,328 @@ 45.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?> 45.5 +<!-- Created with Inkscape (http://www.inkscape.org/) --> 45.6 +<svg 45.7 + xmlns:dc="http://purl.org/dc/elements/1.1/" 45.8 + xmlns:cc="http://web.resource.org/cc/" 45.9 + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 45.10 + xmlns:svg="http://www.w3.org/2000/svg" 45.11 + xmlns="http://www.w3.org/2000/svg" 45.12 + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" 45.13 + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" 45.14 + width="744.09448819" 45.15 + height="1052.3622047" 45.16 + id="svg2" 45.17 + sodipodi:version="0.32" 45.18 + inkscape:version="0.44.1" 45.19 + sodipodi:docname="metadata.svg" 45.20 + sodipodi:docbase="/home/bos/hg/hgbook/en"> 45.21 + <defs 45.22 + id="defs4"> 45.23 + <marker 45.24 + inkscape:stockid="Arrow1Mend" 45.25 + orient="auto" 45.26 + refY="0.0" 45.27 + refX="0.0" 45.28 + id="Arrow1Mend" 45.29 + style="overflow:visible;"> 45.30 + <path 45.31 + id="path2944" 45.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 " 45.33 + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;" 45.34 + transform="scale(0.4) rotate(180) translate(10,0)" /> 45.35 + </marker> 45.36 + </defs> 45.37 + <sodipodi:namedview 45.38 + id="base" 45.39 + pagecolor="#ffffff" 45.40 + bordercolor="#666666" 45.41 + borderopacity="1.0" 45.42 + gridtolerance="10000" 45.43 + guidetolerance="10" 45.44 + objecttolerance="10" 45.45 + inkscape:pageopacity="0.0" 45.46 + inkscape:pageshadow="2" 45.47 + inkscape:zoom="1.4" 45.48 + inkscape:cx="232.14286" 45.49 + inkscape:cy="490.68696" 45.50 + inkscape:document-units="px" 45.51 + inkscape:current-layer="layer1" 45.52 + inkscape:window-width="906" 45.53 + inkscape:window-height="620" 45.54 + inkscape:window-x="181" 45.55 + inkscape:window-y="58" /> 45.56 + <metadata 45.57 + id="metadata7"> 45.58 + <rdf:RDF> 45.59 + <cc:Work 45.60 + rdf:about=""> 45.61 + <dc:format>image/svg+xml</dc:format> 45.62 + <dc:type 45.63 + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 45.64 + </cc:Work> 45.65 + </rdf:RDF> 45.66 + </metadata> 45.67 + <g 45.68 + inkscape:label="Layer 1" 45.69 + inkscape:groupmode="layer" 45.70 + id="layer1"> 45.71 + <path 45.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" 45.73 + d="M 326.94646,467.18359 L 326.94646,510.98123" 45.74 + id="path1910" 45.75 + inkscape:connector-type="polyline" 45.76 + inkscape:connection-end="#rect2962" 45.77 + inkscape:connection-start="#rect2764" /> 45.78 + <path 45.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" 45.80 + d="M 326.94646,531.98123 L 326.94646,591.77887" 45.81 + id="path1912" 45.82 + inkscape:connector-type="polyline" 45.83 + inkscape:connection-start="#rect2962" 45.84 + inkscape:connection-end="#rect3000" /> 45.85 + <path 45.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" 45.87 + d="M 316.1622,531.98123 L 192.30212,652.57648" 45.88 + id="path1916" 45.89 + inkscape:connector-type="polyline" 45.90 + inkscape:connection-end="#rect3038" 45.91 + inkscape:connection-start="#rect2962" /> 45.92 + <path 45.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" 45.94 + d="M 254.23217,467.18359 L 254.23216,510.98123" 45.95 + id="path3088" 45.96 + inkscape:connector-type="polyline" 45.97 + inkscape:connection-start="#rect1872" 45.98 + inkscape:connection-end="#rect2960" /> 45.99 + <path 45.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" 45.101 + d="M 254.23215,531.98123 L 254.23215,591.77887" 45.102 + id="path3090" 45.103 + inkscape:connector-type="polyline" 45.104 + inkscape:connection-start="#rect2960" 45.105 + inkscape:connection-end="#rect2998" /> 45.106 + <path 45.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" 45.108 + d="M 248.84002,531.98123 L 186.90999,652.57648" 45.109 + id="path3092" 45.110 + inkscape:connector-type="polyline" 45.111 + inkscape:connection-start="#rect2960" 45.112 + inkscape:connection-end="#rect3038" /> 45.113 + <rect 45.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" 45.115 + id="rect1872" 45.116 + width="51.42857" 45.117 + height="20" 45.118 + x="228.51788" 45.119 + y="446.68359" /> 45.120 + <rect 45.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" 45.122 + id="rect2764" 45.123 + width="51.42857" 45.124 + height="20" 45.125 + x="301.23218" 45.126 + y="446.68359" /> 45.127 + <rect 45.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" 45.129 + id="rect2766" 45.130 + width="51.42857" 45.131 + height="20" 45.132 + x="155.80359" 45.133 + y="446.68359" /> 45.134 + <rect 45.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" 45.136 + id="rect2768" 45.137 + width="51.42857" 45.138 + height="20" 45.139 + x="83.089294" 45.140 + y="446.68359" /> 45.141 + <path 45.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" 45.143 + d="M 135.01786,456.68359 L 155.30359,456.68359" 45.144 + id="path2770" 45.145 + inkscape:connector-type="polyline" 45.146 + inkscape:connection-start="#rect2768" 45.147 + inkscape:connection-end="#rect2766" /> 45.148 + <path 45.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" 45.150 + d="M 207.73216,456.68359 L 228.01788,456.68359" 45.151 + id="path2772" 45.152 + inkscape:connector-type="polyline" 45.153 + inkscape:connection-start="#rect2766" 45.154 + inkscape:connection-end="#rect1872" /> 45.155 + <path 45.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" 45.157 + d="M 280.44645,456.68359 L 300.73218,456.68359" 45.158 + id="path2774" 45.159 + inkscape:connector-type="polyline" 45.160 + inkscape:connection-start="#rect1872" 45.161 + inkscape:connection-end="#rect2764" /> 45.162 + <path 45.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" 45.164 + d="M 62.303571,456.68359 L 82.589294,456.68359" 45.165 + id="path2778" 45.166 + inkscape:connector-type="polyline" 45.167 + inkscape:connection-end="#rect2768" /> 45.168 + <rect 45.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" 45.170 + id="rect2960" 45.171 + width="51.42857" 45.172 + height="20" 45.173 + x="228.51787" 45.174 + y="511.48123" /> 45.175 + <rect 45.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" 45.177 + id="rect2962" 45.178 + width="51.42857" 45.179 + height="20" 45.180 + x="301.23218" 45.181 + y="511.48123" /> 45.182 + <rect 45.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" 45.184 + id="rect2964" 45.185 + width="51.42857" 45.186 + height="20" 45.187 + x="155.80357" 45.188 + y="511.48123" /> 45.189 + <rect 45.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" 45.191 + id="rect2966" 45.192 + width="51.42857" 45.193 + height="20" 45.194 + x="83.089287" 45.195 + y="511.48123" /> 45.196 + <path 45.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" 45.198 + d="M 135.01786,521.48121 L 155.30359,521.48121" 45.199 + id="path2968" 45.200 + inkscape:connector-type="polyline" /> 45.201 + <path 45.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" 45.203 + d="M 207.73216,521.48121 L 228.01788,521.48121" 45.204 + id="path2970" 45.205 + inkscape:connector-type="polyline" /> 45.206 + <path 45.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" 45.208 + d="M 280.44645,521.48121 L 300.73218,521.48121" 45.209 + id="path2972" 45.210 + inkscape:connector-type="polyline" /> 45.211 + <path 45.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" 45.213 + d="M 62.30358,521.48121 L 82.5893,521.48121" 45.214 + id="path2974" 45.215 + inkscape:connector-type="polyline" /> 45.216 + <rect 45.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" 45.218 + id="rect2998" 45.219 + width="51.42857" 45.220 + height="20" 45.221 + x="228.51787" 45.222 + y="592.27887" /> 45.223 + <rect 45.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" 45.225 + id="rect3000" 45.226 + width="51.42857" 45.227 + height="20" 45.228 + x="301.23218" 45.229 + y="592.27887" /> 45.230 + <rect 45.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" 45.232 + id="rect3002" 45.233 + width="51.42857" 45.234 + height="20" 45.235 + x="155.80357" 45.236 + y="592.27887" /> 45.237 + <rect 45.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" 45.239 + id="rect3004" 45.240 + width="51.42857" 45.241 + height="20" 45.242 + x="83.089287" 45.243 + y="592.27887" /> 45.244 + <path 45.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" 45.246 + d="M 135.01786,602.27884 L 155.30359,602.27884" 45.247 + id="path3006" 45.248 + inkscape:connector-type="polyline" /> 45.249 + <path 45.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" 45.251 + d="M 207.73216,602.27884 L 228.01788,602.27884" 45.252 + id="path3008" 45.253 + inkscape:connector-type="polyline" /> 45.254 + <path 45.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" 45.256 + d="M 280.44645,602.27884 L 300.73218,602.27884" 45.257 + id="path3010" 45.258 + inkscape:connector-type="polyline" /> 45.259 + <path 45.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" 45.261 + d="M 62.30358,602.27884 L 82.5893,602.27884" 45.262 + id="path3012" 45.263 + inkscape:connector-type="polyline" /> 45.264 + <rect 45.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" 45.266 + id="rect3034" 45.267 + width="51.42857" 45.268 + height="20" 45.269 + x="228.51787" 45.270 + y="653.07648" /> 45.271 + <rect 45.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" 45.273 + id="rect3038" 45.274 + width="51.42857" 45.275 + height="20" 45.276 + x="155.80357" 45.277 + y="653.07648" /> 45.278 + <rect 45.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" 45.280 + id="rect3040" 45.281 + width="51.42857" 45.282 + height="20" 45.283 + x="83.089287" 45.284 + y="653.07648" /> 45.285 + <path 45.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" 45.287 + d="M 135.01786,663.07646 L 155.30359,663.07646" 45.288 + id="path3042" 45.289 + inkscape:connector-type="polyline" /> 45.290 + <path 45.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" 45.292 + d="M 207.73216,663.07646 L 228.01788,663.07646" 45.293 + id="path3044" 45.294 + inkscape:connector-type="polyline" /> 45.295 + <path 45.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" 45.297 + d="M 62.30358,663.07646 L 82.5893,663.07646" 45.298 + id="path3048" 45.299 + inkscape:connector-type="polyline" /> 45.300 + <text 45.301 + xml:space="preserve" 45.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" 45.303 + x="82.072548" 45.304 + y="432.64789" 45.305 + id="text3094"><tspan 45.306 + sodipodi:role="line" 45.307 + id="tspan3096" 45.308 + x="82.072548" 45.309 + y="432.64789">Changelog</tspan></text> 45.310 + <text 45.311 + xml:space="preserve" 45.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" 45.313 + x="82.306923" 45.314 + y="498.97327" 45.315 + id="text3098"><tspan 45.316 + sodipodi:role="line" 45.317 + id="tspan3100" 45.318 + x="82.306923" 45.319 + y="498.97327">Manifest</tspan></text> 45.320 + <text 45.321 + xml:space="preserve" 45.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" 45.323 + x="82.14286" 45.324 + y="580.08569" 45.325 + id="text3102"><tspan 45.326 + sodipodi:role="line" 45.327 + id="tspan3104" 45.328 + x="82.14286" 45.329 + y="580.08569">Filelogs</tspan></text> 45.330 + </g> 45.331 +</svg>
46.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 46.2 +++ b/fr/figs/mq-stack.svg Sun Aug 16 04:58:01 2009 +0200 46.3 @@ -0,0 +1,270 @@ 46.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?> 46.5 +<!-- Created with Inkscape (http://www.inkscape.org/) --> 46.6 +<svg 46.7 + xmlns:dc="http://purl.org/dc/elements/1.1/" 46.8 + xmlns:cc="http://web.resource.org/cc/" 46.9 + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 46.10 + xmlns:svg="http://www.w3.org/2000/svg" 46.11 + xmlns="http://www.w3.org/2000/svg" 46.12 + xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd" 46.13 + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" 46.14 + width="744.09448819" 46.15 + height="1052.3622047" 46.16 + id="svg2" 46.17 + sodipodi:version="0.32" 46.18 + inkscape:version="0.43" 46.19 + sodipodi:docname="mq-stack.svg" 46.20 + sodipodi:docbase="/home/bos/hg/hgbook/en"> 46.21 + <defs 46.22 + id="defs4" /> 46.23 + <sodipodi:namedview 46.24 + id="base" 46.25 + pagecolor="#ffffff" 46.26 + bordercolor="#666666" 46.27 + borderopacity="1.0" 46.28 + inkscape:pageopacity="0.0" 46.29 + inkscape:pageshadow="2" 46.30 + inkscape:zoom="1.4142136" 46.31 + inkscape:cx="299.33323" 46.32 + inkscape:cy="815.646" 46.33 + inkscape:document-units="px" 46.34 + inkscape:current-layer="layer1" 46.35 + inkscape:window-width="1014" 46.36 + inkscape:window-height="689" 46.37 + inkscape:window-x="0" 46.38 + inkscape:window-y="25" /> 46.39 + <metadata 46.40 + id="metadata7"> 46.41 + <rdf:RDF> 46.42 + <cc:Work 46.43 + rdf:about=""> 46.44 + <dc:format>image/svg+xml</dc:format> 46.45 + <dc:type 46.46 + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 46.47 + </cc:Work> 46.48 + </rdf:RDF> 46.49 + </metadata> 46.50 + <g 46.51 + inkscape:label="Layer 1" 46.52 + inkscape:groupmode="layer" 46.53 + id="layer1"> 46.54 + <rect 46.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" 46.56 + id="rect1307" 46.57 + width="202.93683" 46.58 + height="24.243662" 46.59 + x="230.01944" 46.60 + y="221.70146" /> 46.61 + <text 46.62 + xml:space="preserve" 46.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" 46.64 + x="237.89606" 46.65 + y="237.13383" 46.66 + id="text1309"><tspan 46.67 + sodipodi:role="line" 46.68 + id="tspan1311" 46.69 + x="237.89606" 46.70 + y="237.13383">prevent-compiler-reorder.patch</tspan></text> 46.71 + <rect 46.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" 46.73 + id="rect1320" 46.74 + width="202.93683" 46.75 + height="24.243662" 46.76 + x="230.01936" 46.77 + y="251.34325" /> 46.78 + <text 46.79 + xml:space="preserve" 46.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" 46.81 + x="237.89598" 46.82 + y="266.77563" 46.83 + id="text1322"><tspan 46.84 + sodipodi:role="line" 46.85 + id="tspan1324" 46.86 + x="237.89598" 46.87 + y="266.77563">namespace-cleanup.patch</tspan></text> 46.88 + <rect 46.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" 46.90 + id="rect2217" 46.91 + width="202.93683" 46.92 + height="24.243662" 46.93 + x="230.01936" 46.94 + y="280.98505" /> 46.95 + <text 46.96 + xml:space="preserve" 46.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" 46.98 + x="237.89598" 46.99 + y="296.41742" 46.100 + id="text2219"><tspan 46.101 + sodipodi:role="line" 46.102 + id="tspan2221" 46.103 + x="237.89598" 46.104 + y="296.41742">powerpc-port-fixes.patch</tspan></text> 46.105 + <rect 46.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" 46.107 + id="rect3114" 46.108 + width="202.93683" 46.109 + height="24.243662" 46.110 + x="230.01936" 46.111 + y="310.6268" /> 46.112 + <text 46.113 + xml:space="preserve" 46.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" 46.115 + x="237.89598" 46.116 + y="326.05917" 46.117 + id="text3116"><tspan 46.118 + sodipodi:role="line" 46.119 + id="tspan3118" 46.120 + x="237.89598" 46.121 + y="326.05917">report-devinfo-correctly.patch</tspan></text> 46.122 + <text 46.123 + xml:space="preserve" 46.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" 46.125 + x="200.01021" 46.126 + y="191.68094" 46.127 + id="text3170" 46.128 + sodipodi:linespacing="125%"><tspan 46.129 + sodipodi:role="line" 46.130 + id="tspan3172" 46.131 + x="200.01021" 46.132 + y="191.68094" 46.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> 46.134 + <text 46.135 + xml:space="preserve" 46.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" 46.137 + x="255.26627" 46.138 + y="248.79449" 46.139 + id="text3190" 46.140 + sodipodi:linespacing="125%" 46.141 + transform="scale(0.786716,1.271107)"><tspan 46.142 + sodipodi:role="line" 46.143 + id="tspan3192" 46.144 + x="255.26627" 46.145 + y="248.79449" 46.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> 46.147 + <text 46.148 + xml:space="preserve" 46.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" 46.150 + x="195.86807" 46.151 + y="173.17117" 46.152 + id="text4085" 46.153 + sodipodi:linespacing="125%"><tspan 46.154 + sodipodi:role="line" 46.155 + id="tspan4087" 46.156 + x="195.86807" 46.157 + y="173.17117" 46.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 46.159 + sodipodi:role="line" 46.160 + x="195.86807" 46.161 + y="188.17117" 46.162 + id="tspan4089" 46.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> 46.164 + <text 46.165 + xml:space="preserve" 46.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" 46.167 + x="195.0712" 46.168 + y="288.91745" 46.169 + id="text4091" 46.170 + sodipodi:linespacing="125%"><tspan 46.171 + sodipodi:role="line" 46.172 + id="tspan4093" 46.173 + x="195.0712" 46.174 + y="288.91745" 46.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 46.176 + sodipodi:role="line" 46.177 + x="195.0712" 46.178 + y="303.91745" 46.179 + id="tspan4111" 46.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> 46.181 + <text 46.182 + xml:space="preserve" 46.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" 46.184 + x="195.0712" 46.185 + y="229.28813" 46.186 + id="text4095" 46.187 + sodipodi:linespacing="125%"><tspan 46.188 + sodipodi:role="line" 46.189 + id="tspan4097" 46.190 + x="195.0712" 46.191 + y="229.28813" 46.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 46.193 + sodipodi:role="line" 46.194 + x="195.0712" 46.195 + y="244.28813" 46.196 + id="tspan4109" 46.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> 46.198 + <text 46.199 + xml:space="preserve" 46.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" 46.201 + x="450.4975" 46.202 + y="238.29692" 46.203 + id="text4137"><tspan 46.204 + sodipodi:role="line" 46.205 + id="tspan4139" 46.206 + x="450.4975" 46.207 + y="238.29692">201ad3209902</tspan></text> 46.208 + <text 46.209 + xml:space="preserve" 46.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" 46.211 + x="450.05804" 46.212 + y="267.93872" 46.213 + id="text4141"><tspan 46.214 + sodipodi:role="line" 46.215 + id="tspan4143" 46.216 + x="450.05804" 46.217 + y="267.93872">126b84e593ae</tspan></text> 46.218 + <text 46.219 + xml:space="preserve" 46.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" 46.221 + x="450.6557" 46.222 + y="297.58051" 46.223 + id="text4145"><tspan 46.224 + sodipodi:role="line" 46.225 + id="tspan4147" 46.226 + x="450.6557" 46.227 + y="297.58051">a655daf15409</tspan></text> 46.228 + <text 46.229 + xml:space="preserve" 46.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" 46.231 + x="450.71429" 46.232 + y="327.22226" 46.233 + id="text4149"><tspan 46.234 + sodipodi:role="line" 46.235 + id="tspan4151" 46.236 + x="450.71429" 46.237 + y="327.22226">e50d59aaea3a</tspan></text> 46.238 + <rect 46.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" 46.240 + id="rect3106" 46.241 + width="202.93683" 46.242 + height="24.243662" 46.243 + x="230.01936" 46.244 + y="150.41792" /> 46.245 + <text 46.246 + xml:space="preserve" 46.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" 46.248 + x="237.89598" 46.249 + y="165.8503" 46.250 + id="text3108"><tspan 46.251 + sodipodi:role="line" 46.252 + id="tspan3110" 46.253 + x="237.89598" 46.254 + y="165.8503">forbid-illegal-params.patch</tspan></text> 46.255 + <rect 46.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" 46.257 + id="rect2241" 46.258 + width="202.93683" 46.259 + height="24.243662" 46.260 + x="230.16466" 46.261 + y="180.05968" /> 46.262 + <text 46.263 + xml:space="preserve" 46.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" 46.265 + x="238.04128" 46.266 + y="195.49205" 46.267 + id="text2243"><tspan 46.268 + sodipodi:role="line" 46.269 + id="tspan2245" 46.270 + x="238.04128" 46.271 + y="195.49205">fix-memory-leak.patch</tspan></text> 46.272 + </g> 46.273 +</svg>
47.1 Binary file fr/figs/note.png has changed
48.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 48.2 +++ b/fr/figs/revlog.svg Sun Aug 16 04:58:01 2009 +0200 48.3 @@ -0,0 +1,1155 @@ 48.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?> 48.5 +<!-- Created with Inkscape (http://www.inkscape.org/) --> 48.6 +<svg 48.7 + xmlns:dc="http://purl.org/dc/elements/1.1/" 48.8 + xmlns:cc="http://web.resource.org/cc/" 48.9 + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 48.10 + xmlns:svg="http://www.w3.org/2000/svg" 48.11 + xmlns="http://www.w3.org/2000/svg" 48.12 + xmlns:xlink="http://www.w3.org/1999/xlink" 48.13 + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" 48.14 + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" 48.15 + width="744.09448819" 48.16 + height="1052.3622047" 48.17 + id="svg2" 48.18 + sodipodi:version="0.32" 48.19 + inkscape:version="0.44.1" 48.20 + sodipodi:docbase="/home/bos/hg/hgbook/en" 48.21 + sodipodi:docname="revlog.svg"> 48.22 + <defs 48.23 + id="defs4"> 48.24 + <marker 48.25 + inkscape:stockid="Arrow1Mend" 48.26 + orient="auto" 48.27 + refY="0.0" 48.28 + refX="0.0" 48.29 + id="Arrow1Mend" 48.30 + style="overflow:visible;"> 48.31 + <path 48.32 + id="path4852" 48.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 " 48.34 + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;" 48.35 + transform="scale(0.4) rotate(180) translate(10,0)" /> 48.36 + </marker> 48.37 + <linearGradient 48.38 + id="linearGradient3092"> 48.39 + <stop 48.40 + style="stop-color:#44436f;stop-opacity:1;" 48.41 + offset="0" 48.42 + id="stop3094" /> 48.43 + <stop 48.44 + style="stop-color:#abade5;stop-opacity:1;" 48.45 + offset="1" 48.46 + id="stop3096" /> 48.47 + </linearGradient> 48.48 + <linearGradient 48.49 + inkscape:collect="always" 48.50 + xlink:href="#linearGradient3092" 48.51 + id="linearGradient3118" 48.52 + gradientUnits="userSpaceOnUse" 48.53 + x1="176.16635" 48.54 + y1="405.21934" 48.55 + x2="417.11935" 48.56 + y2="405.21934" /> 48.57 + <linearGradient 48.58 + inkscape:collect="always" 48.59 + xlink:href="#linearGradient3092" 48.60 + id="linearGradient3120" 48.61 + gradientUnits="userSpaceOnUse" 48.62 + x1="176.16635" 48.63 + y1="405.21934" 48.64 + x2="417.11935" 48.65 + y2="405.21934" /> 48.66 + <linearGradient 48.67 + inkscape:collect="always" 48.68 + xlink:href="#linearGradient3092" 48.69 + id="linearGradient3129" 48.70 + gradientUnits="userSpaceOnUse" 48.71 + x1="176.16635" 48.72 + y1="405.21934" 48.73 + x2="417.11935" 48.74 + y2="405.21934" 48.75 + gradientTransform="translate(-0.928574,-1.428574)" /> 48.76 + <linearGradient 48.77 + inkscape:collect="always" 48.78 + xlink:href="#linearGradient3092" 48.79 + id="linearGradient3133" 48.80 + gradientUnits="userSpaceOnUse" 48.81 + x1="176.16635" 48.82 + y1="405.21934" 48.83 + x2="417.11935" 48.84 + y2="405.21934" 48.85 + gradientTransform="translate(-0.928574,-1.428574)" /> 48.86 + <linearGradient 48.87 + inkscape:collect="always" 48.88 + xlink:href="#linearGradient3092" 48.89 + id="linearGradient3708" 48.90 + gradientUnits="userSpaceOnUse" 48.91 + gradientTransform="matrix(0.423343,0,0,0.423343,138.874,-67.01732)" 48.92 + x1="175.23776" 48.93 + y1="509.98154" 48.94 + x2="416.29077" 48.95 + y2="297.49997" /> 48.96 + <linearGradient 48.97 + inkscape:collect="always" 48.98 + xlink:href="#linearGradient3092" 48.99 + id="linearGradient5164" 48.100 + gradientUnits="userSpaceOnUse" 48.101 + gradientTransform="matrix(0.423343,0,0,0.423343,198.249,247.4358)" 48.102 + x1="175.23776" 48.103 + y1="509.98154" 48.104 + x2="416.29077" 48.105 + y2="297.49997" /> 48.106 + <linearGradient 48.107 + inkscape:collect="always" 48.108 + xlink:href="#linearGradient3092" 48.109 + id="linearGradient5584" 48.110 + gradientUnits="userSpaceOnUse" 48.111 + gradientTransform="matrix(0.423343,0,0,0.423343,143.9081,371.2915)" 48.112 + x1="175.23776" 48.113 + y1="509.98154" 48.114 + x2="416.29077" 48.115 + y2="297.49997" /> 48.116 + <linearGradient 48.117 + inkscape:collect="always" 48.118 + xlink:href="#linearGradient3092" 48.119 + id="linearGradient5784" 48.120 + gradientUnits="userSpaceOnUse" 48.121 + gradientTransform="matrix(0.423343,0,0,0.423343,76.37397,152.137)" 48.122 + x1="175.23776" 48.123 + y1="509.98154" 48.124 + x2="416.29077" 48.125 + y2="297.49997" /> 48.126 + <linearGradient 48.127 + inkscape:collect="always" 48.128 + xlink:href="#linearGradient3092" 48.129 + id="linearGradient5786" 48.130 + gradientUnits="userSpaceOnUse" 48.131 + gradientTransform="matrix(0.423343,0,0,0.423343,198.249,152.137)" 48.132 + x1="175.23776" 48.133 + y1="509.98154" 48.134 + x2="416.29077" 48.135 + y2="297.49997" /> 48.136 + <linearGradient 48.137 + inkscape:collect="always" 48.138 + xlink:href="#linearGradient3092" 48.139 + id="linearGradient5895" 48.140 + gradientUnits="userSpaceOnUse" 48.141 + gradientTransform="matrix(0.423343,0,0,0.423343,198.0215,261.7142)" 48.142 + x1="175.23776" 48.143 + y1="509.98154" 48.144 + x2="416.29077" 48.145 + y2="297.49997" /> 48.146 + <linearGradient 48.147 + inkscape:collect="always" 48.148 + xlink:href="#linearGradient3092" 48.149 + id="linearGradient5958" 48.150 + gradientUnits="userSpaceOnUse" 48.151 + gradientTransform="matrix(0.423343,0,0,0.423343,137.1978,42.55987)" 48.152 + x1="175.23776" 48.153 + y1="509.98154" 48.154 + x2="416.29077" 48.155 + y2="297.49997" /> 48.156 + </defs> 48.157 + <sodipodi:namedview 48.158 + id="base" 48.159 + pagecolor="#ffffff" 48.160 + bordercolor="#666666" 48.161 + borderopacity="1.0" 48.162 + gridtolerance="10000" 48.163 + guidetolerance="10" 48.164 + objecttolerance="10" 48.165 + inkscape:pageopacity="0.0" 48.166 + inkscape:pageshadow="2" 48.167 + inkscape:zoom="0.64" 48.168 + inkscape:cx="566.02368" 48.169 + inkscape:cy="688.16826" 48.170 + inkscape:document-units="px" 48.171 + inkscape:current-layer="layer1" 48.172 + inkscape:window-width="906" 48.173 + inkscape:window-height="620" 48.174 + inkscape:window-x="29" 48.175 + inkscape:window-y="79" 48.176 + inkscape:connector-spacing="11" /> 48.177 + <metadata 48.178 + id="metadata7"> 48.179 + <rdf:RDF> 48.180 + <cc:Work 48.181 + rdf:about=""> 48.182 + <dc:format>image/svg+xml</dc:format> 48.183 + <dc:type 48.184 + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 48.185 + </cc:Work> 48.186 + </rdf:RDF> 48.187 + </metadata> 48.188 + <g 48.189 + inkscape:label="Layer 1" 48.190 + inkscape:groupmode="layer" 48.191 + id="layer1"> 48.192 + <rect 48.193 + y="168.74846" 48.194 + x="211.58516" 48.195 + height="89.506805" 48.196 + width="101.60232" 48.197 + id="rect3068" 48.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" /> 48.199 + <g 48.200 + id="g3215" 48.201 + transform="matrix(0.423343,0,0,0.423343,137.1977,42.55985)"> 48.202 + <rect 48.203 + y="447.71451" 48.204 + x="299.67859" 48.205 + height="48.571426" 48.206 + width="103.14286" 48.207 + id="rect2899" 48.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" /> 48.209 + <text 48.210 + id="text2903" 48.211 + y="464.8139" 48.212 + x="308.89639" 48.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" 48.214 + xml:space="preserve"><tspan 48.215 + y="464.8139" 48.216 + x="308.89639" 48.217 + sodipodi:role="line" 48.218 + id="tspan2905">Second parent</tspan></text> 48.219 + <text 48.220 + id="text2907" 48.221 + y="485.50256" 48.222 + x="308.20175" 48.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" 48.224 + xml:space="preserve"><tspan 48.225 + style="font-family:Courier" 48.226 + y="485.50256" 48.227 + x="308.20175" 48.228 + id="tspan2909" 48.229 + sodipodi:role="line">32bf9a5f22c0</tspan></text> 48.230 + </g> 48.231 + <g 48.232 + id="g3250" 48.233 + transform="matrix(0.423343,0,0,0.423343,137.1977,42.55986)"> 48.234 + <rect 48.235 + y="311.28598" 48.236 + x="188.6071" 48.237 + height="48.571426" 48.238 + width="103.14286" 48.239 + id="rect2936" 48.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" /> 48.241 + <text 48.242 + id="text2940" 48.243 + y="328.38538" 48.244 + x="197.82495" 48.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" 48.246 + xml:space="preserve"><tspan 48.247 + y="328.38538" 48.248 + x="197.82495" 48.249 + sodipodi:role="line" 48.250 + id="tspan2942">Revision hash</tspan></text> 48.251 + <text 48.252 + id="text2944" 48.253 + y="349.07404" 48.254 + x="197.13031" 48.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" 48.256 + xml:space="preserve"><tspan 48.257 + style="font-family:Courier" 48.258 + y="349.07404" 48.259 + x="197.13031" 48.260 + id="tspan2946" 48.261 + sodipodi:role="line">34b8b7a15ea1</tspan></text> 48.262 + </g> 48.263 + <g 48.264 + id="g3243" 48.265 + transform="matrix(0.423343,0,0,0.423343,137.6664,43.91853)"> 48.266 + <rect 48.267 + y="363.07654" 48.268 + x="187.5" 48.269 + height="75" 48.270 + width="213.85715" 48.271 + id="rect2950" 48.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" /> 48.273 + <text 48.274 + id="text2958" 48.275 + y="400.86459" 48.276 + x="196.02321" 48.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" 48.278 + xml:space="preserve"><tspan 48.279 + style="fill:black;fill-opacity:1;font-family:Courier" 48.280 + y="400.86459" 48.281 + x="196.02321" 48.282 + id="tspan2960" 48.283 + sodipodi:role="line">...</tspan></text> 48.284 + <text 48.285 + id="text2954" 48.286 + y="380.17593" 48.287 + x="196.71785" 48.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" 48.289 + xml:space="preserve"><tspan 48.290 + y="380.17593" 48.291 + x="196.71785" 48.292 + sodipodi:role="line" 48.293 + id="tspan2956" 48.294 + style="fill:black;fill-opacity:1">Revision data (delta or snapshot)</tspan></text> 48.295 + </g> 48.296 + <g 48.297 + id="g5529" 48.298 + transform="translate(-6.710312,-8.165836e-6)"> 48.299 + <rect 48.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" 48.301 + id="rect3509" 48.302 + width="101.60232" 48.303 + height="89.506805" 48.304 + x="218.29547" 48.305 + y="497.4801" /> 48.306 + <g 48.307 + transform="matrix(0.423343,0,0,0.423343,143.908,371.2915)" 48.308 + id="g3513"> 48.309 + <g 48.310 + id="g3515"> 48.311 + <rect 48.312 + y="447.72418" 48.313 + x="188.6071" 48.314 + height="48.571426" 48.315 + width="103.14286" 48.316 + id="rect3517" 48.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" /> 48.318 + <text 48.319 + id="text3519" 48.320 + y="464.82358" 48.321 + x="197.82495" 48.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" 48.323 + xml:space="preserve"><tspan 48.324 + y="464.82358" 48.325 + x="197.82495" 48.326 + sodipodi:role="line" 48.327 + id="tspan3521">First parent</tspan></text> 48.328 + <text 48.329 + id="text3523" 48.330 + y="485.51224" 48.331 + x="197.13031" 48.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" 48.333 + xml:space="preserve"><tspan 48.334 + style="font-family:Courier" 48.335 + y="485.51224" 48.336 + x="197.13031" 48.337 + id="tspan3525" 48.338 + sodipodi:role="line">000000000000</tspan></text> 48.339 + </g> 48.340 + <g 48.341 + id="g3527"> 48.342 + <rect 48.343 + y="447.71451" 48.344 + x="299.67859" 48.345 + height="48.571426" 48.346 + width="103.14286" 48.347 + id="rect3529" 48.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" /> 48.349 + <text 48.350 + id="text3531" 48.351 + y="464.8139" 48.352 + x="308.89639" 48.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" 48.354 + xml:space="preserve"><tspan 48.355 + y="464.8139" 48.356 + x="308.89639" 48.357 + sodipodi:role="line" 48.358 + id="tspan3533">Second parent</tspan></text> 48.359 + <text 48.360 + id="text3535" 48.361 + y="485.50256" 48.362 + x="308.20175" 48.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" 48.364 + xml:space="preserve"><tspan 48.365 + style="font-family:Courier" 48.366 + y="485.50256" 48.367 + x="308.20175" 48.368 + id="tspan3537" 48.369 + sodipodi:role="line">000000000000</tspan></text> 48.370 + </g> 48.371 + </g> 48.372 + <g 48.373 + transform="matrix(0.423343,0,0,0.423343,143.908,371.2915)" 48.374 + id="g3539"> 48.375 + <rect 48.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" 48.377 + id="rect3541" 48.378 + width="103.14286" 48.379 + height="48.571426" 48.380 + x="188.6071" 48.381 + y="311.28598" /> 48.382 + <text 48.383 + xml:space="preserve" 48.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" 48.385 + x="197.82495" 48.386 + y="328.38538" 48.387 + id="text3543"><tspan 48.388 + id="tspan3545" 48.389 + sodipodi:role="line" 48.390 + x="197.82495" 48.391 + y="328.38538">Revision hash</tspan></text> 48.392 + <text 48.393 + xml:space="preserve" 48.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" 48.395 + x="197.13031" 48.396 + y="349.07404" 48.397 + id="text3547"><tspan 48.398 + sodipodi:role="line" 48.399 + id="tspan3549" 48.400 + x="197.13031" 48.401 + y="349.07404" 48.402 + style="font-family:Courier">ff9dc8bc2a8b</tspan></text> 48.403 + </g> 48.404 + <g 48.405 + transform="matrix(0.423343,0,0,0.423343,144.3767,372.6502)" 48.406 + id="g3551"> 48.407 + <rect 48.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" 48.409 + id="rect3553" 48.410 + width="213.85715" 48.411 + height="75" 48.412 + x="187.5" 48.413 + y="363.07654" /> 48.414 + <text 48.415 + xml:space="preserve" 48.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" 48.417 + x="196.02321" 48.418 + y="400.86459" 48.419 + id="text3555"><tspan 48.420 + sodipodi:role="line" 48.421 + id="tspan3557" 48.422 + x="196.02321" 48.423 + y="400.86459" 48.424 + style="fill:black;fill-opacity:1;font-family:Courier">...</tspan></text> 48.425 + <text 48.426 + xml:space="preserve" 48.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" 48.428 + x="196.71785" 48.429 + y="380.17593" 48.430 + id="text3559"><tspan 48.431 + style="fill:black;fill-opacity:1" 48.432 + id="tspan3561" 48.433 + sodipodi:role="line" 48.434 + x="196.71785" 48.435 + y="380.17593">Revision data (delta or snapshot)</tspan></text> 48.436 + </g> 48.437 + </g> 48.438 + <g 48.439 + id="g4868" 48.440 + transform="translate(-1.676208,-2.342463e-5)"> 48.441 + <rect 48.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" 48.443 + id="rect3567" 48.444 + width="101.60232" 48.445 + height="89.506805" 48.446 + x="213.26137" 48.447 + y="59.171272" /> 48.448 + <g 48.449 + transform="matrix(0.423343,0,0,0.423343,138.8739,-67.01734)" 48.450 + id="g3573"> 48.451 + <rect 48.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" 48.453 + id="rect3575" 48.454 + width="103.14286" 48.455 + height="48.571426" 48.456 + x="188.6071" 48.457 + y="447.72418" /> 48.458 + <text 48.459 + xml:space="preserve" 48.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" 48.461 + x="197.82495" 48.462 + y="464.82358" 48.463 + id="text3577"><tspan 48.464 + id="tspan3579" 48.465 + sodipodi:role="line" 48.466 + x="197.82495" 48.467 + y="464.82358">First parent</tspan></text> 48.468 + <text 48.469 + xml:space="preserve" 48.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" 48.471 + x="197.13031" 48.472 + y="485.51224" 48.473 + id="text3581"><tspan 48.474 + sodipodi:role="line" 48.475 + id="tspan3583" 48.476 + x="197.13031" 48.477 + y="485.51224" 48.478 + style="font-family:Courier">34b8b7a15ea1</tspan></text> 48.479 + </g> 48.480 + <g 48.481 + transform="matrix(0.423343,0,0,0.423343,138.8739,-67.01734)" 48.482 + id="g3585"> 48.483 + <rect 48.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" 48.485 + id="rect3587" 48.486 + width="103.14286" 48.487 + height="48.571426" 48.488 + x="299.67859" 48.489 + y="447.71451" /> 48.490 + <text 48.491 + xml:space="preserve" 48.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" 48.493 + x="308.89639" 48.494 + y="464.8139" 48.495 + id="text3589"><tspan 48.496 + id="tspan3591" 48.497 + sodipodi:role="line" 48.498 + x="308.89639" 48.499 + y="464.8139">Second parent</tspan></text> 48.500 + <text 48.501 + xml:space="preserve" 48.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" 48.503 + x="308.20175" 48.504 + y="485.50256" 48.505 + id="text3593"><tspan 48.506 + sodipodi:role="line" 48.507 + id="tspan3595" 48.508 + x="308.20175" 48.509 + y="485.50256" 48.510 + style="font-family:Courier">000000000000</tspan></text> 48.511 + </g> 48.512 + <g 48.513 + transform="matrix(0.423343,0,0,0.423343,138.8739,-67.01733)" 48.514 + id="g3597"> 48.515 + <rect 48.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" 48.517 + id="rect3599" 48.518 + width="103.14286" 48.519 + height="48.571426" 48.520 + x="188.6071" 48.521 + y="311.28598" /> 48.522 + <text 48.523 + xml:space="preserve" 48.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" 48.525 + x="197.82495" 48.526 + y="328.38538" 48.527 + id="text3601"><tspan 48.528 + id="tspan3603" 48.529 + sodipodi:role="line" 48.530 + x="197.82495" 48.531 + y="328.38538">Revision hash</tspan></text> 48.532 + <text 48.533 + xml:space="preserve" 48.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" 48.535 + x="197.13031" 48.536 + y="349.07404" 48.537 + id="text3605"><tspan 48.538 + sodipodi:role="line" 48.539 + id="tspan3607" 48.540 + x="197.13031" 48.541 + y="349.07404" 48.542 + style="font-family:Courier">1b67dc96f27a</tspan></text> 48.543 + </g> 48.544 + <g 48.545 + transform="matrix(0.423343,0,0,0.423343,139.3426,-65.65866)" 48.546 + id="g3609"> 48.547 + <rect 48.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" 48.549 + id="rect3611" 48.550 + width="213.85715" 48.551 + height="75" 48.552 + x="187.5" 48.553 + y="363.07654" /> 48.554 + <text 48.555 + xml:space="preserve" 48.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" 48.557 + x="196.02321" 48.558 + y="400.86459" 48.559 + id="text3613"><tspan 48.560 + sodipodi:role="line" 48.561 + id="tspan3615" 48.562 + x="196.02321" 48.563 + y="400.86459" 48.564 + style="fill:black;fill-opacity:1;font-family:Courier">...</tspan></text> 48.565 + <text 48.566 + xml:space="preserve" 48.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" 48.568 + x="196.71785" 48.569 + y="380.17593" 48.570 + id="text3617"><tspan 48.571 + style="fill:black;fill-opacity:1" 48.572 + id="tspan3619" 48.573 + sodipodi:role="line" 48.574 + x="196.71785" 48.575 + y="380.17593">Revision data (delta or snapshot)</tspan></text> 48.576 + </g> 48.577 + </g> 48.578 + <path 48.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)" 48.580 + d="M 240.78255,143.08593 L 241.42595,171.75349" 48.581 + id="path3801" 48.582 + inkscape:connector-type="polyline" 48.583 + inkscape:connection-start="#g3573" 48.584 + inkscape:connection-end="#g3250" /> 48.585 + <g 48.586 + id="g5677"> 48.587 + <rect 48.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" 48.589 + id="rect3393" 48.590 + width="101.60232" 48.591 + height="89.506805" 48.592 + x="150.76137" 48.593 + y="278.32565" /> 48.594 + <g 48.595 + transform="matrix(0.423343,0,0,0.423343,76.37397,152.137)" 48.596 + id="g3399"> 48.597 + <rect 48.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" 48.599 + id="rect3401" 48.600 + width="103.14286" 48.601 + height="48.571426" 48.602 + x="188.6071" 48.603 + y="447.72418" /> 48.604 + <text 48.605 + xml:space="preserve" 48.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" 48.607 + x="197.82495" 48.608 + y="464.82358" 48.609 + id="text3403"><tspan 48.610 + id="tspan3405" 48.611 + sodipodi:role="line" 48.612 + x="197.82495" 48.613 + y="464.82358">First parent</tspan></text> 48.614 + <text 48.615 + xml:space="preserve" 48.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" 48.617 + x="197.13031" 48.618 + y="485.51224" 48.619 + id="text3407"><tspan 48.620 + sodipodi:role="line" 48.621 + id="tspan3409" 48.622 + x="197.13031" 48.623 + y="485.51224" 48.624 + style="font-family:Courier">ff9dc8bc2a8b</tspan></text> 48.625 + </g> 48.626 + <g 48.627 + transform="matrix(0.423343,0,0,0.423343,76.37397,152.137)" 48.628 + id="g3411"> 48.629 + <rect 48.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" 48.631 + id="rect3413" 48.632 + width="103.14286" 48.633 + height="48.571426" 48.634 + x="299.67859" 48.635 + y="447.71451" /> 48.636 + <text 48.637 + xml:space="preserve" 48.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" 48.639 + x="308.89639" 48.640 + y="464.8139" 48.641 + id="text3415"><tspan 48.642 + id="tspan3417" 48.643 + sodipodi:role="line" 48.644 + x="308.89639" 48.645 + y="464.8139">Second parent</tspan></text> 48.646 + <text 48.647 + xml:space="preserve" 48.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" 48.649 + x="308.20175" 48.650 + y="485.50256" 48.651 + id="text3419"><tspan 48.652 + sodipodi:role="line" 48.653 + id="tspan3421" 48.654 + x="308.20175" 48.655 + y="485.50256" 48.656 + style="font-family:Courier">000000000000</tspan></text> 48.657 + </g> 48.658 + <g 48.659 + transform="matrix(0.423343,0,0,0.423343,76.37397,152.137)" 48.660 + id="g3423"> 48.661 + <rect 48.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" 48.663 + id="rect3425" 48.664 + width="103.14286" 48.665 + height="48.571426" 48.666 + x="188.6071" 48.667 + y="311.28598" /> 48.668 + <text 48.669 + xml:space="preserve" 48.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" 48.671 + x="197.82495" 48.672 + y="328.38538" 48.673 + id="text3427"><tspan 48.674 + id="tspan3429" 48.675 + sodipodi:role="line" 48.676 + x="197.82495" 48.677 + y="328.38538">Revision hash</tspan></text> 48.678 + <text 48.679 + xml:space="preserve" 48.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" 48.681 + x="197.13031" 48.682 + y="349.07404" 48.683 + id="text3431"><tspan 48.684 + sodipodi:role="line" 48.685 + id="tspan3433" 48.686 + x="197.13031" 48.687 + y="349.07404" 48.688 + style="font-family:Courier">5b80c922ebdd</tspan></text> 48.689 + </g> 48.690 + <g 48.691 + transform="matrix(0.423343,0,0,0.423343,76.84265,153.4957)" 48.692 + id="g3435"> 48.693 + <rect 48.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" 48.695 + id="rect3437" 48.696 + width="213.85715" 48.697 + height="75" 48.698 + x="187.5" 48.699 + y="363.07654" /> 48.700 + <text 48.701 + xml:space="preserve" 48.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" 48.703 + x="196.02321" 48.704 + y="400.86459" 48.705 + id="text3439"><tspan 48.706 + sodipodi:role="line" 48.707 + id="tspan3441" 48.708 + x="196.02321" 48.709 + y="400.86459" 48.710 + style="fill:black;fill-opacity:1;font-family:Courier">...</tspan></text> 48.711 + <text 48.712 + xml:space="preserve" 48.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" 48.714 + x="196.71785" 48.715 + y="380.17593" 48.716 + id="text3443"><tspan 48.717 + style="fill:black;fill-opacity:1" 48.718 + id="tspan3445" 48.719 + sodipodi:role="line" 48.720 + x="196.71785" 48.721 + y="380.17593">Revision data (delta or snapshot)</tspan></text> 48.722 + </g> 48.723 + </g> 48.724 + <g 48.725 + id="g5646" 48.726 + transform="translate(-0.227432,0)"> 48.727 + <rect 48.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" 48.729 + id="rect3451" 48.730 + width="101.60232" 48.731 + height="89.506805" 48.732 + x="272.63638" 48.733 + y="278.32565" /> 48.734 + <g 48.735 + transform="matrix(0.423343,0,0,0.423343,198.2489,152.137)" 48.736 + id="g3457"> 48.737 + <rect 48.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" 48.739 + id="rect3459" 48.740 + width="103.14286" 48.741 + height="48.571426" 48.742 + x="188.6071" 48.743 + y="447.72418" /> 48.744 + <text 48.745 + xml:space="preserve" 48.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" 48.747 + x="197.82495" 48.748 + y="464.82358" 48.749 + id="text3461"><tspan 48.750 + id="tspan3463" 48.751 + sodipodi:role="line" 48.752 + x="197.82495" 48.753 + y="464.82358">First parent</tspan></text> 48.754 + <text 48.755 + xml:space="preserve" 48.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" 48.757 + x="197.13031" 48.758 + y="485.51224" 48.759 + id="text3465"><tspan 48.760 + sodipodi:role="line" 48.761 + id="tspan3467" 48.762 + x="197.13031" 48.763 + y="485.51224" 48.764 + style="font-family:Courier">ecacb6b4c9fd</tspan></text> 48.765 + </g> 48.766 + <g 48.767 + transform="matrix(0.423343,0,0,0.423343,198.2489,152.137)" 48.768 + id="g3469"> 48.769 + <rect 48.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" 48.771 + id="rect3471" 48.772 + width="103.14286" 48.773 + height="48.571426" 48.774 + x="299.67859" 48.775 + y="447.71451" /> 48.776 + <text 48.777 + xml:space="preserve" 48.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" 48.779 + x="308.89639" 48.780 + y="464.8139" 48.781 + id="text3473"><tspan 48.782 + id="tspan3475" 48.783 + sodipodi:role="line" 48.784 + x="308.89639" 48.785 + y="464.8139">Second parent</tspan></text> 48.786 + <text 48.787 + xml:space="preserve" 48.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" 48.789 + x="308.20175" 48.790 + y="485.50256" 48.791 + id="text3477"><tspan 48.792 + sodipodi:role="line" 48.793 + id="tspan3479" 48.794 + x="308.20175" 48.795 + y="485.50256" 48.796 + style="font-family:Courier">000000000000</tspan></text> 48.797 + </g> 48.798 + <g 48.799 + transform="matrix(0.423343,0,0,0.423343,198.2489,152.137)" 48.800 + id="g3481"> 48.801 + <rect 48.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" 48.803 + id="rect3483" 48.804 + width="103.14286" 48.805 + height="48.571426" 48.806 + x="188.6071" 48.807 + y="311.28598" /> 48.808 + <text 48.809 + xml:space="preserve" 48.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" 48.811 + x="197.82495" 48.812 + y="328.38538" 48.813 + id="text3485"><tspan 48.814 + id="tspan3487" 48.815 + sodipodi:role="line" 48.816 + x="197.82495" 48.817 + y="328.38538">Revision hash</tspan></text> 48.818 + <text 48.819 + xml:space="preserve" 48.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" 48.821 + x="197.13031" 48.822 + y="349.07404" 48.823 + id="text3489"><tspan 48.824 + sodipodi:role="line" 48.825 + id="tspan3491" 48.826 + x="197.13031" 48.827 + y="349.07404" 48.828 + style="font-family:Courier">32bf9a5f22c0</tspan></text> 48.829 + </g> 48.830 + <g 48.831 + transform="matrix(0.423343,0,0,0.423343,198.7176,153.4957)" 48.832 + id="g3493"> 48.833 + <rect 48.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" 48.835 + id="rect3495" 48.836 + width="213.85715" 48.837 + height="75" 48.838 + x="187.5" 48.839 + y="363.07654" /> 48.840 + <text 48.841 + xml:space="preserve" 48.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" 48.843 + x="196.02321" 48.844 + y="400.86459" 48.845 + id="text3497"><tspan 48.846 + sodipodi:role="line" 48.847 + id="tspan3499" 48.848 + x="196.02321" 48.849 + y="400.86459" 48.850 + style="fill:black;fill-opacity:1;font-family:Courier">...</tspan></text> 48.851 + <text 48.852 + xml:space="preserve" 48.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" 48.854 + x="196.71785" 48.855 + y="380.17593" 48.856 + id="text3501"><tspan 48.857 + style="fill:black;fill-opacity:1" 48.858 + id="tspan3503" 48.859 + sodipodi:role="line" 48.860 + x="196.71785" 48.861 + y="380.17593">Revision data (delta or snapshot)</tspan></text> 48.862 + </g> 48.863 + </g> 48.864 + <rect 48.865 + y="387.90286" 48.866 + x="272.40894" 48.867 + height="89.506805" 48.868 + width="101.60232" 48.869 + id="rect5081" 48.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" /> 48.871 + <g 48.872 + id="g5087" 48.873 + transform="matrix(0.423343,0,0,0.423343,198.0214,261.7142)"> 48.874 + <rect 48.875 + y="447.72418" 48.876 + x="188.6071" 48.877 + height="48.571426" 48.878 + width="103.14286" 48.879 + id="rect5089" 48.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" /> 48.881 + <text 48.882 + id="text5091" 48.883 + y="464.82358" 48.884 + x="197.82495" 48.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" 48.886 + xml:space="preserve"><tspan 48.887 + y="464.82358" 48.888 + x="197.82495" 48.889 + sodipodi:role="line" 48.890 + id="tspan5093">First parent</tspan></text> 48.891 + <text 48.892 + id="text5095" 48.893 + y="485.51224" 48.894 + x="197.13031" 48.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" 48.896 + xml:space="preserve"><tspan 48.897 + style="font-family:Courier" 48.898 + y="485.51224" 48.899 + x="197.13031" 48.900 + id="tspan5097" 48.901 + sodipodi:role="line">ff9dc8bc2a8b</tspan></text> 48.902 + </g> 48.903 + <g 48.904 + id="g5099" 48.905 + transform="matrix(0.423343,0,0,0.423343,198.0214,261.7142)"> 48.906 + <rect 48.907 + y="447.71451" 48.908 + x="299.67859" 48.909 + height="48.571426" 48.910 + width="103.14286" 48.911 + id="rect5101" 48.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" /> 48.913 + <text 48.914 + id="text5103" 48.915 + y="464.8139" 48.916 + x="308.89639" 48.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" 48.918 + xml:space="preserve"><tspan 48.919 + y="464.8139" 48.920 + x="308.89639" 48.921 + sodipodi:role="line" 48.922 + id="tspan5105">Second parent</tspan></text> 48.923 + <text 48.924 + id="text5107" 48.925 + y="485.50256" 48.926 + x="308.20175" 48.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" 48.928 + xml:space="preserve"><tspan 48.929 + style="font-family:Courier" 48.930 + y="485.50256" 48.931 + x="308.20175" 48.932 + id="tspan5109" 48.933 + sodipodi:role="line">000000000000</tspan></text> 48.934 + </g> 48.935 + <g 48.936 + id="g5111" 48.937 + transform="matrix(0.423343,0,0,0.423343,198.0214,261.7142)"> 48.938 + <rect 48.939 + y="311.28598" 48.940 + x="188.6071" 48.941 + height="48.571426" 48.942 + width="103.14286" 48.943 + id="rect5113" 48.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" /> 48.945 + <text 48.946 + id="text5115" 48.947 + y="328.38538" 48.948 + x="197.82495" 48.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" 48.950 + xml:space="preserve"><tspan 48.951 + y="328.38538" 48.952 + x="197.82495" 48.953 + sodipodi:role="line" 48.954 + id="tspan5117">Revision hash</tspan></text> 48.955 + <text 48.956 + id="text5119" 48.957 + y="349.07404" 48.958 + x="197.13031" 48.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" 48.960 + xml:space="preserve"><tspan 48.961 + style="font-family:Courier" 48.962 + y="349.07404" 48.963 + x="197.13031" 48.964 + id="tspan5121" 48.965 + sodipodi:role="line">ecacb6b4c9fd</tspan></text> 48.966 + </g> 48.967 + <g 48.968 + id="g5123" 48.969 + transform="matrix(0.423343,0,0,0.423343,198.4901,263.0729)"> 48.970 + <rect 48.971 + y="363.07654" 48.972 + x="187.5" 48.973 + height="75" 48.974 + width="213.85715" 48.975 + id="rect5125" 48.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" /> 48.977 + <text 48.978 + id="text5127" 48.979 + y="400.86459" 48.980 + x="196.02321" 48.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" 48.982 + xml:space="preserve"><tspan 48.983 + style="fill:black;fill-opacity:1;font-family:Courier" 48.984 + y="400.86459" 48.985 + x="196.02321" 48.986 + id="tspan5129" 48.987 + sodipodi:role="line">...</tspan></text> 48.988 + <text 48.989 + id="text5131" 48.990 + y="380.17593" 48.991 + x="196.71785" 48.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" 48.993 + xml:space="preserve"><tspan 48.994 + y="380.17593" 48.995 + x="196.71785" 48.996 + sodipodi:role="line" 48.997 + id="tspan5133" 48.998 + style="fill:black;fill-opacity:1">Revision data (delta or snapshot)</tspan></text> 48.999 + </g> 48.1000 + <path 48.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" 48.1002 + d="M 299.69935,362.24027 L 299.69931,393.49494" 48.1003 + id="path5203" 48.1004 + inkscape:connector-type="polyline" 48.1005 + inkscape:connection-start="#g3457" 48.1006 + inkscape:connection-end="#g5111" /> 48.1007 + <path 48.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" 48.1009 + d="M 182.35357,362.22647 L 241.2842,503.07224" 48.1010 + id="path5271" 48.1011 + inkscape:connector-type="polyline" 48.1012 + inkscape:connection-start="#g3399" 48.1013 + inkscape:connection-end="#g3539" /> 48.1014 + <path 48.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" 48.1016 + d="M 287.63109,471.81747 L 250.9438,503.07223" 48.1017 + id="path5285" 48.1018 + inkscape:connector-type="polyline" 48.1019 + inkscape:connection-start="#g5087" 48.1020 + inkscape:connection-end="#g3539" /> 48.1021 + <path 48.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)" 48.1023 + d="M 290.80419,250.07192 L 297.80065,283.90394" 48.1024 + id="path5077" 48.1025 + inkscape:connector-type="polyline" 48.1026 + inkscape:connection-start="#g3215" 48.1027 + inkscape:connection-end="#g3481" /> 48.1028 + <path 48.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)" 48.1030 + d="M 229.63373,250.07601 L 190.07484,283.90394" 48.1031 + id="path5075" 48.1032 + inkscape:connector-type="polyline" 48.1033 + inkscape:connection-end="#g3423" /> 48.1034 + <text 48.1035 + xml:space="preserve" 48.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" 48.1037 + x="131.5625" 48.1038 + y="100.79968" 48.1039 + id="text5897"><tspan 48.1040 + sodipodi:role="line" 48.1041 + id="tspan5899" 48.1042 + x="131.5625" 48.1043 + y="100.79968" 48.1044 + style="text-align:end;text-anchor:end">Head revision</tspan><tspan 48.1045 + sodipodi:role="line" 48.1046 + x="131.5625" 48.1047 + y="115.79968" 48.1048 + id="tspan5901" 48.1049 + style="text-align:end;text-anchor:end">(no children)</tspan></text> 48.1050 + <text 48.1051 + xml:space="preserve" 48.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" 48.1053 + x="131.5625" 48.1054 + y="207.04968" 48.1055 + id="text5903"><tspan 48.1056 + sodipodi:role="line" 48.1057 + id="tspan5905" 48.1058 + x="131.5625" 48.1059 + y="207.04968" 48.1060 + style="text-align:end;text-anchor:end">Merge revision</tspan><tspan 48.1061 + sodipodi:role="line" 48.1062 + x="131.5625" 48.1063 + y="222.04968" 48.1064 + id="tspan5907" 48.1065 + style="text-align:end;text-anchor:end">(two parents)</tspan></text> 48.1066 + <text 48.1067 + xml:space="preserve" 48.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" 48.1069 + x="131.92578" 48.1070 + y="451.58093" 48.1071 + id="text5909"><tspan 48.1072 + sodipodi:role="line" 48.1073 + id="tspan5911" 48.1074 + x="131.92578" 48.1075 + y="451.58093" 48.1076 + style="text-align:end;text-anchor:end">Branches</tspan><tspan 48.1077 + sodipodi:role="line" 48.1078 + x="131.92578" 48.1079 + y="466.58093" 48.1080 + id="tspan5913" 48.1081 + style="text-align:end;text-anchor:end">(two revisions,</tspan><tspan 48.1082 + sodipodi:role="line" 48.1083 + x="131.92578" 48.1084 + y="481.58093" 48.1085 + id="tspan5915" 48.1086 + style="text-align:end;text-anchor:end">same parent)</tspan></text> 48.1087 + <path 48.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" 48.1089 + d="M 111.71875,433.61218 L 154.7268,368.52294" 48.1090 + id="path5917" 48.1091 + inkscape:connector-type="polyline" /> 48.1092 + <path 48.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" 48.1094 + d="M 134.375,464.86218 L 277.86691,440.37816" 48.1095 + id="path5919" 48.1096 + inkscape:connector-type="polyline" 48.1097 + inkscape:connection-end="#g5123" /> 48.1098 + <text 48.1099 + xml:space="preserve" 48.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" 48.1101 + x="131.5625" 48.1102 + y="536.73718" 48.1103 + id="text5927"><tspan 48.1104 + sodipodi:role="line" 48.1105 + id="tspan5929" 48.1106 + x="131.5625" 48.1107 + y="536.73718">First revision</tspan><tspan 48.1108 + sodipodi:role="line" 48.1109 + x="131.5625" 48.1110 + y="551.73718" 48.1111 + id="tspan5931">(both parents null)</tspan></text> 48.1112 + <rect 48.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" 48.1114 + id="rect2830" 48.1115 + width="43.664806" 48.1116 + height="20.562374" 48.1117 + x="217.0432" 48.1118 + y="232.10075" /> 48.1119 + <text 48.1120 + xml:space="preserve" 48.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" 48.1122 + x="220.94551" 48.1123 + y="239.33966" 48.1124 + id="text2832"><tspan 48.1125 + id="tspan2836" 48.1126 + sodipodi:role="line" 48.1127 + x="220.94551" 48.1128 + y="239.33966">First parent</tspan></text> 48.1129 + <text 48.1130 + xml:space="preserve" 48.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" 48.1132 + x="220.65144" 48.1133 + y="248.09805" 48.1134 + id="text2879"><tspan 48.1135 + sodipodi:role="line" 48.1136 + id="tspan2881" 48.1137 + x="220.65144" 48.1138 + y="248.09805" 48.1139 + style="font-family:Courier">5b80c922ebdd</tspan></text> 48.1140 + <path 48.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" 48.1142 + d="M 139.84375,107.83093 L 210.15625,107.83093" 48.1143 + id="path5965" 48.1144 + inkscape:connector-type="polyline" /> 48.1145 + <path 48.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" 48.1147 + d="M 137.5,213.29968 L 210.49036,214.09055" 48.1148 + id="path5967" 48.1149 + inkscape:connector-type="polyline" /> 48.1150 + <path 48.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" 48.1152 + d="M 136.34375,544.54968 L 206.65625,544.54968" 48.1153 + id="path5969" 48.1154 + inkscape:connector-type="polyline" 48.1155 + inkscape:transform-center-y="-171.09375" 48.1156 + inkscape:transform-center-x="53.90625" /> 48.1157 + </g> 48.1158 +</svg>
49.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 49.2 +++ b/fr/figs/snapshot.svg Sun Aug 16 04:58:01 2009 +0200 49.3 @@ -0,0 +1,202 @@ 49.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?> 49.5 +<!-- Created with Inkscape (http://www.inkscape.org/) --> 49.6 +<svg 49.7 + xmlns:dc="http://purl.org/dc/elements/1.1/" 49.8 + xmlns:cc="http://web.resource.org/cc/" 49.9 + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 49.10 + xmlns:svg="http://www.w3.org/2000/svg" 49.11 + xmlns="http://www.w3.org/2000/svg" 49.12 + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" 49.13 + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" 49.14 + width="744.09448819" 49.15 + height="1052.3622047" 49.16 + id="svg2807" 49.17 + sodipodi:version="0.32" 49.18 + inkscape:version="0.44.1" 49.19 + sodipodi:docbase="/home/bos/hg/hgbook/en" 49.20 + sodipodi:docname="snapshots.svg"> 49.21 + <defs 49.22 + id="defs2809" /> 49.23 + <sodipodi:namedview 49.24 + id="base" 49.25 + pagecolor="#ffffff" 49.26 + bordercolor="#666666" 49.27 + borderopacity="1.0" 49.28 + gridtolerance="10000" 49.29 + guidetolerance="10" 49.30 + objecttolerance="10" 49.31 + inkscape:pageopacity="0.0" 49.32 + inkscape:pageshadow="2" 49.33 + inkscape:zoom="1.4" 49.34 + inkscape:cx="252.04111" 49.35 + inkscape:cy="605.75448" 49.36 + inkscape:document-units="px" 49.37 + inkscape:current-layer="layer1" 49.38 + inkscape:window-width="906" 49.39 + inkscape:window-height="721" 49.40 + inkscape:window-x="0" 49.41 + inkscape:window-y="25" /> 49.42 + <metadata 49.43 + id="metadata2812"> 49.44 + <rdf:RDF> 49.45 + <cc:Work 49.46 + rdf:about=""> 49.47 + <dc:format>image/svg+xml</dc:format> 49.48 + <dc:type 49.49 + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 49.50 + </cc:Work> 49.51 + </rdf:RDF> 49.52 + </metadata> 49.53 + <g 49.54 + inkscape:label="Layer 1" 49.55 + inkscape:groupmode="layer" 49.56 + id="layer1"> 49.57 + <rect 49.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" 49.59 + id="rect2817" 49.60 + width="118.18347" 49.61 + height="245.32632" 49.62 + x="243.05112" 49.63 + y="315.4133" 49.64 + inkscape:transform-center-x="136.84403" 49.65 + inkscape:transform-center-y="-66.529183" /> 49.66 + <rect 49.67 + y="315.04153" 49.68 + x="46.965065" 49.69 + height="97.803009" 49.70 + width="108.92702" 49.71 + id="rect2815" 49.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" /> 49.73 + <g 49.74 + id="g3814"> 49.75 + <rect 49.76 + y="348.94302" 49.77 + x="59.285713" 49.78 + height="30" 49.79 + width="84.285713" 49.80 + id="rect2819" 49.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" 49.82 + ry="0" /> 49.83 + <text 49.84 + id="text2821" 49.85 + y="368.02701" 49.86 + x="72.717636" 49.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" 49.88 + xml:space="preserve"><tspan 49.89 + y="368.02701" 49.90 + x="72.717636" 49.91 + id="tspan2823" 49.92 + sodipodi:role="line">Index, rev 7</tspan></text> 49.93 + </g> 49.94 + <text 49.95 + id="text3722" 49.96 + y="301.29074" 49.97 + x="46.187778" 49.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" 49.99 + xml:space="preserve"><tspan 49.100 + y="301.29074" 49.101 + x="46.187778" 49.102 + id="tspan3724" 49.103 + sodipodi:role="line">Revlog index (.i file)</tspan></text> 49.104 + <text 49.105 + id="text3726" 49.106 + y="301.29074" 49.107 + x="241.90207" 49.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" 49.109 + xml:space="preserve"><tspan 49.110 + y="301.29074" 49.111 + x="241.90207" 49.112 + id="tspan3728" 49.113 + sodipodi:role="line">Revlog data (.d file)</tspan></text> 49.114 + <path 49.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" 49.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 " 49.117 + id="path3839" 49.118 + sodipodi:nodetypes="ccccc" /> 49.119 + <rect 49.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" 49.121 + id="rect3752" 49.122 + width="92.720184" 49.123 + height="67.005905" 49.124 + x="255.42564" 49.125 + y="368.64264" /> 49.126 + <text 49.127 + xml:space="preserve" 49.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" 49.129 + x="264.45859" 49.130 + y="387.30099" 49.131 + id="text3754"><tspan 49.132 + sodipodi:role="line" 49.133 + id="tspan3756" 49.134 + x="264.45859" 49.135 + y="387.30099">Snapshot, rev 4</tspan></text> 49.136 + <rect 49.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" 49.138 + id="rect3761" 49.139 + width="93.49366" 49.140 + height="29.922237" 49.141 + x="255.03891" 49.142 + y="442.04395" /> 49.143 + <text 49.144 + xml:space="preserve" 49.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" 49.146 + x="263.2662" 49.147 + y="460.17206" 49.148 + id="text3763"><tspan 49.149 + sodipodi:role="line" 49.150 + id="tspan3765" 49.151 + x="263.2662" 49.152 + y="460.17206">Delta, rev 4 to 5</tspan></text> 49.153 + <rect 49.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" 49.155 + id="rect3774" 49.156 + width="93.49366" 49.157 + height="29.922237" 49.158 + x="255.03891" 49.159 + y="477.97485" /> 49.160 + <text 49.161 + xml:space="preserve" 49.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" 49.163 + x="263.2662" 49.164 + y="496.10297" 49.165 + id="text3776"><tspan 49.166 + sodipodi:role="line" 49.167 + id="tspan3778" 49.168 + x="263.2662" 49.169 + y="496.10297">Delta, rev 5 to 6</tspan></text> 49.170 + <rect 49.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" 49.172 + id="rect3782" 49.173 + width="93.49366" 49.174 + height="29.922237" 49.175 + x="255.03891" 49.176 + y="513.90576" /> 49.177 + <text 49.178 + xml:space="preserve" 49.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" 49.180 + x="263.2662" 49.181 + y="532.03387" 49.182 + id="text3784"><tspan 49.183 + sodipodi:role="line" 49.184 + id="tspan3786" 49.185 + x="263.2662" 49.186 + y="532.03387">Delta, rev 6 to 7</tspan></text> 49.187 + <rect 49.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" 49.189 + id="rect3889" 49.190 + width="93.49366" 49.191 + height="29.922237" 49.192 + x="255.03891" 49.193 + y="332.32489" /> 49.194 + <text 49.195 + xml:space="preserve" 49.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" 49.197 + x="263.2662" 49.198 + y="350.453" 49.199 + id="text3891"><tspan 49.200 + sodipodi:role="line" 49.201 + id="tspan3893" 49.202 + x="263.2662" 49.203 + y="350.453">Delta, rev 2 to 3</tspan></text> 49.204 + </g> 49.205 +</svg>
50.1 Binary file fr/figs/throbber.gif has changed
51.1 Binary file fr/figs/tip.png has changed
52.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 52.2 +++ b/fr/figs/tour-history.svg Sun Aug 16 04:58:01 2009 +0200 52.3 @@ -0,0 +1,289 @@ 52.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?> 52.5 +<!-- Created with Inkscape (http://www.inkscape.org/) --> 52.6 +<svg 52.7 + xmlns:dc="http://purl.org/dc/elements/1.1/" 52.8 + xmlns:cc="http://web.resource.org/cc/" 52.9 + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 52.10 + xmlns:svg="http://www.w3.org/2000/svg" 52.11 + xmlns="http://www.w3.org/2000/svg" 52.12 + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" 52.13 + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" 52.14 + width="744.09448819" 52.15 + height="1052.3622047" 52.16 + id="svg2" 52.17 + sodipodi:version="0.32" 52.18 + inkscape:version="0.44.1" 52.19 + sodipodi:docname="tour-history.svg"> 52.20 + <defs 52.21 + id="defs4"> 52.22 + <marker 52.23 + inkscape:stockid="Arrow1Mstart" 52.24 + orient="auto" 52.25 + refY="0.0" 52.26 + refX="0.0" 52.27 + id="Arrow1Mstart" 52.28 + style="overflow:visible"> 52.29 + <path 52.30 + id="path2973" 52.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 " 52.32 + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none" 52.33 + transform="scale(0.4) translate(10,0)" /> 52.34 + </marker> 52.35 + <marker 52.36 + inkscape:stockid="Arrow1Mend" 52.37 + orient="auto" 52.38 + refY="0.0" 52.39 + refX="0.0" 52.40 + id="Arrow1Mend" 52.41 + style="overflow:visible;"> 52.42 + <path 52.43 + id="path3066" 52.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 " 52.45 + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;" 52.46 + transform="scale(0.4) rotate(180) translate(10,0)" /> 52.47 + </marker> 52.48 + </defs> 52.49 + <sodipodi:namedview 52.50 + id="base" 52.51 + pagecolor="#ffffff" 52.52 + bordercolor="#666666" 52.53 + borderopacity="1.0" 52.54 + gridtolerance="10000" 52.55 + guidetolerance="10" 52.56 + objecttolerance="10" 52.57 + inkscape:pageopacity="0.0" 52.58 + inkscape:pageshadow="2" 52.59 + inkscape:zoom="1.4" 52.60 + inkscape:cx="232.14286" 52.61 + inkscape:cy="672.75296" 52.62 + inkscape:document-units="px" 52.63 + inkscape:current-layer="layer1" 52.64 + inkscape:window-width="906" 52.65 + inkscape:window-height="620" 52.66 + inkscape:window-x="5" 52.67 + inkscape:window-y="49" /> 52.68 + <metadata 52.69 + id="metadata7"> 52.70 + <rdf:RDF> 52.71 + <cc:Work 52.72 + rdf:about=""> 52.73 + <dc:format>image/svg+xml</dc:format> 52.74 + <dc:type 52.75 + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 52.76 + </cc:Work> 52.77 + </rdf:RDF> 52.78 + </metadata> 52.79 + <g 52.80 + inkscape:label="Layer 1" 52.81 + inkscape:groupmode="layer" 52.82 + id="layer1"> 52.83 + <rect 52.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" 52.85 + id="rect1878" 52.86 + width="94.285713" 52.87 + height="20.714285" 52.88 + x="138" 52.89 + y="479.50504" /> 52.90 + <text 52.91 + xml:space="preserve" 52.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" 52.93 + x="162.09892" 52.94 + y="493.12619" 52.95 + id="text1872"><tspan 52.96 + sodipodi:role="line" 52.97 + id="tspan1874" 52.98 + x="162.09892" 52.99 + y="493.12619" 52.100 + style="font-family:Courier"><tspan 52.101 + style="font-weight:bold" 52.102 + id="tspan1876">0</tspan>: REV0</tspan></text> 52.103 + <rect 52.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" 52.105 + id="rect2800" 52.106 + width="94.285713" 52.107 + height="20.714285" 52.108 + x="138" 52.109 + y="432.63004" /> 52.110 + <text 52.111 + xml:space="preserve" 52.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" 52.113 + x="162.09892" 52.114 + y="446.25119" 52.115 + id="text2794"><tspan 52.116 + sodipodi:role="line" 52.117 + id="tspan2796" 52.118 + x="162.09892" 52.119 + y="446.25119" 52.120 + style="font-family:Courier"><tspan 52.121 + id="tspan2868" 52.122 + style="font-weight:bold">1</tspan>: REV1</tspan></text> 52.123 + <rect 52.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" 52.125 + id="rect2810" 52.126 + width="94.285713" 52.127 + height="20.714285" 52.128 + x="138" 52.129 + y="385.75504" /> 52.130 + <text 52.131 + xml:space="preserve" 52.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" 52.133 + x="162.09892" 52.134 + y="399.37619" 52.135 + id="text2804"><tspan 52.136 + sodipodi:role="line" 52.137 + id="tspan2806" 52.138 + x="162.09892" 52.139 + y="399.37619" 52.140 + style="font-family:Courier"><tspan 52.141 + style="font-weight:bold" 52.142 + id="tspan2866">2</tspan>: REV2</tspan></text> 52.143 + <rect 52.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" 52.145 + id="rect2820" 52.146 + width="94.285713" 52.147 + height="20.714285" 52.148 + x="138" 52.149 + y="338.88007" /> 52.150 + <text 52.151 + xml:space="preserve" 52.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" 52.153 + x="162.09892" 52.154 + y="352.50122" 52.155 + id="text2814"><tspan 52.156 + sodipodi:role="line" 52.157 + id="tspan2816" 52.158 + x="162.09892" 52.159 + y="352.50122" 52.160 + style="font-family:Courier"><tspan 52.161 + style="font-weight:bold" 52.162 + id="tspan2864">3</tspan>: REV3</tspan></text> 52.163 + <rect 52.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" 52.165 + id="rect2830" 52.166 + width="94.285713" 52.167 + height="20.714285" 52.168 + x="138" 52.169 + y="292.00504" /> 52.170 + <text 52.171 + xml:space="preserve" 52.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" 52.173 + x="162.09892" 52.174 + y="305.62619" 52.175 + id="text2824"><tspan 52.176 + sodipodi:role="line" 52.177 + id="tspan2826" 52.178 + x="162.09892" 52.179 + y="305.62619" 52.180 + style="font-family:Courier"><tspan 52.181 + style="font-weight:bold" 52.182 + id="tspan2862">4</tspan>: REV4</tspan></text> 52.183 + <text 52.184 + xml:space="preserve" 52.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" 52.186 + x="173.57143" 52.187 + y="443.79074" 52.188 + id="text2832"><tspan 52.189 + sodipodi:role="line" 52.190 + id="tspan2834" 52.191 + x="173.57143" 52.192 + y="443.79074" /></text> 52.193 + <path 52.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)" 52.195 + d="M 185.14286,478.50504 L 185.14286,454.34432" 52.196 + id="path2894" 52.197 + inkscape:connector-type="polyline" /> 52.198 + <path 52.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)" 52.200 + d="M 185.14286,431.63004 L 185.14286,407.46932" 52.201 + id="path2896" 52.202 + inkscape:connector-type="polyline" /> 52.203 + <path 52.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)" 52.205 + d="M 185.14286,384.75504 L 185.14286,360.59435" 52.206 + id="path2898" 52.207 + inkscape:connector-type="polyline" /> 52.208 + <path 52.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)" 52.210 + d="M 185.14286,337.88007 L 185.14286,313.71932" 52.211 + id="path2900" 52.212 + inkscape:connector-type="polyline" /> 52.213 + <text 52.214 + xml:space="preserve" 52.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" 52.216 + x="244.60992" 52.217 + y="305.245" 52.218 + id="text1902"><tspan 52.219 + sodipodi:role="line" 52.220 + id="tspan1904" 52.221 + x="244.60992" 52.222 + y="305.245">(newest)</tspan></text> 52.223 + <text 52.224 + xml:space="preserve" 52.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" 52.226 + x="244.60992" 52.227 + y="492.745" 52.228 + id="text1906"><tspan 52.229 + sodipodi:role="line" 52.230 + id="tspan1908" 52.231 + x="244.60992" 52.232 + y="492.745">(oldest)</tspan></text> 52.233 + <rect 52.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" 52.235 + id="rect1907" 52.236 + width="94.285713" 52.237 + height="20.714285" 52.238 + x="309.28571" 52.239 + y="324.86218" /> 52.240 + <text 52.241 + xml:space="preserve" 52.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" 52.243 + x="333.38464" 52.244 + y="338.48334" 52.245 + id="text1909"><tspan 52.246 + sodipodi:role="line" 52.247 + id="tspan1911" 52.248 + x="333.38464" 52.249 + y="338.48334" 52.250 + style="font-family:Courier"><tspan 52.251 + style="font-weight:bold" 52.252 + id="tspan1913">4</tspan>: REV4</tspan></text> 52.253 + <path 52.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" 52.255 + d="M 332.14286,375.21932 L 335.71429,347.36218" 52.256 + id="path2802" /> 52.257 + <path 52.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" 52.259 + d="M 372.69968,375.21932 L 369.12825,347.36218" 52.260 + id="path2986" /> 52.261 + <text 52.262 + xml:space="preserve" 52.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" 52.264 + x="335.14285" 52.265 + y="387.21933" 52.266 + id="text2988"><tspan 52.267 + sodipodi:role="line" 52.268 + x="335.14285" 52.269 + y="387.21933" 52.270 + id="tspan3020" 52.271 + style="text-align:end;text-anchor:end">revision</tspan><tspan 52.272 + sodipodi:role="line" 52.273 + x="335.14285" 52.274 + y="402.21933" 52.275 + id="tspan3014" 52.276 + style="text-align:end;text-anchor:end">number</tspan></text> 52.277 + <text 52.278 + xml:space="preserve" 52.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" 52.280 + x="368.71429" 52.281 + y="387.21933" 52.282 + id="text2994"><tspan 52.283 + sodipodi:role="line" 52.284 + id="tspan2996" 52.285 + x="368.71429" 52.286 + y="387.21933">changeset</tspan><tspan 52.287 + sodipodi:role="line" 52.288 + x="368.71429" 52.289 + y="402.21933" 52.290 + id="tspan2998">identifier</tspan></text> 52.291 + </g> 52.292 +</svg>
53.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 53.2 +++ b/fr/figs/tour-merge-conflict.svg Sun Aug 16 04:58:01 2009 +0200 53.3 @@ -0,0 +1,210 @@ 53.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?> 53.5 +<!-- Created with Inkscape (http://www.inkscape.org/) --> 53.6 +<svg 53.7 + xmlns:dc="http://purl.org/dc/elements/1.1/" 53.8 + xmlns:cc="http://web.resource.org/cc/" 53.9 + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 53.10 + xmlns:svg="http://www.w3.org/2000/svg" 53.11 + xmlns="http://www.w3.org/2000/svg" 53.12 + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" 53.13 + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" 53.14 + width="744.09448819" 53.15 + height="1052.3622047" 53.16 + id="svg2" 53.17 + sodipodi:version="0.32" 53.18 + inkscape:version="0.44.1" 53.19 + sodipodi:docname="tour-merge-conflict.svg"> 53.20 + <defs 53.21 + id="defs4"> 53.22 + <marker 53.23 + inkscape:stockid="Arrow1Mend" 53.24 + orient="auto" 53.25 + refY="0.0" 53.26 + refX="0.0" 53.27 + id="Arrow1Mend" 53.28 + style="overflow:visible;"> 53.29 + <path 53.30 + id="path3053" 53.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 " 53.32 + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;" 53.33 + transform="scale(0.4) rotate(180) translate(10,0)" /> 53.34 + </marker> 53.35 + </defs> 53.36 + <sodipodi:namedview 53.37 + id="base" 53.38 + pagecolor="#ffffff" 53.39 + bordercolor="#666666" 53.40 + borderopacity="1.0" 53.41 + gridtolerance="10000" 53.42 + guidetolerance="10" 53.43 + objecttolerance="10" 53.44 + inkscape:pageopacity="0.0" 53.45 + inkscape:pageshadow="2" 53.46 + inkscape:zoom="1.4" 53.47 + inkscape:cx="164.78349" 53.48 + inkscape:cy="590.07679" 53.49 + inkscape:document-units="px" 53.50 + inkscape:current-layer="layer1" 53.51 + inkscape:window-width="906" 53.52 + inkscape:window-height="620" 53.53 + inkscape:window-x="5" 53.54 + inkscape:window-y="49" /> 53.55 + <metadata 53.56 + id="metadata7"> 53.57 + <rdf:RDF> 53.58 + <cc:Work 53.59 + rdf:about=""> 53.60 + <dc:format>image/svg+xml</dc:format> 53.61 + <dc:type 53.62 + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 53.63 + </cc:Work> 53.64 + </rdf:RDF> 53.65 + </metadata> 53.66 + <g 53.67 + inkscape:label="Layer 1" 53.68 + inkscape:groupmode="layer" 53.69 + id="layer1"> 53.70 + <g 53.71 + id="g1988" 53.72 + transform="translate(84.85711,0)"> 53.73 + <g 53.74 + id="g1876"> 53.75 + <path 53.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" 53.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 " 53.78 + id="path1872" 53.79 + sodipodi:nodetypes="cccccc" /> 53.80 + <path 53.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" 53.82 + d="M 191.55484,563.36862 L 191.6923,560.98794 L 192.69126,552.44884 L 203.80416,551.31242" 53.83 + id="path1874" 53.84 + sodipodi:nodetypes="cccc" /> 53.85 + </g> 53.86 + <flowRoot 53.87 + style="font-size:8px;font-family:Times New Roman" 53.88 + id="flowRoot1898" 53.89 + xml:space="preserve"><flowRegion 53.90 + id="flowRegion1900"><rect 53.91 + style="font-size:8px;font-family:Times New Roman" 53.92 + y="464.50504" 53.93 + x="122.85714" 53.94 + height="93.571426" 53.95 + width="76.428574" 53.96 + id="rect1902" /></flowRegion><flowPara 53.97 + id="flowPara1904">Greetings!</flowPara><flowPara 53.98 + id="flowPara1906" /><flowPara 53.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> 53.100 + <g 53.101 + id="g1966" 53.102 + transform="translate(82,0.35715)"> 53.103 + <g 53.104 + transform="translate(-77.85718,-140.0714)" 53.105 + id="g1910"> 53.106 + <path 53.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" 53.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 " 53.109 + id="path1912" 53.110 + sodipodi:nodetypes="cccccc" /> 53.111 + <path 53.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" 53.113 + d="M 191.55484,563.36862 L 191.6923,560.98794 L 192.69126,552.44884 L 203.80416,551.31242" 53.114 + id="path1914" 53.115 + sodipodi:nodetypes="cccc" /> 53.116 + </g> 53.117 + <flowRoot 53.118 + transform="translate(-77.85718,-140.0714)" 53.119 + style="font-size:8px;font-family:Times New Roman" 53.120 + id="flowRoot1916" 53.121 + xml:space="preserve"><flowRegion 53.122 + id="flowRegion1918"><rect 53.123 + style="font-size:8px;font-family:Times New Roman" 53.124 + y="464.50504" 53.125 + x="122.85714" 53.126 + height="93.571426" 53.127 + width="76.428574" 53.128 + id="rect1920" /></flowRegion><flowPara 53.129 + id="flowPara1922">Greetings!</flowPara><flowPara 53.130 + id="flowPara1924" /><flowPara 53.131 + id="flowPara1926">I am <flowSpan 53.132 + style="font-style:italic;fill:red" 53.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> 53.134 + <g 53.135 + id="g1977" 53.136 + transform="translate(81.99999,-0.35715)"> 53.137 + <g 53.138 + transform="translate(83.57141,-139.3571)" 53.139 + id="g1932"> 53.140 + <path 53.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" 53.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 " 53.143 + id="path1934" 53.144 + sodipodi:nodetypes="cccccc" /> 53.145 + <path 53.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" 53.147 + d="M 191.55484,563.36862 L 191.6923,560.98794 L 192.69126,552.44884 L 203.80416,551.31242" 53.148 + id="path1936" 53.149 + sodipodi:nodetypes="cccc" /> 53.150 + </g> 53.151 + <flowRoot 53.152 + transform="translate(83.57141,-139.3571)" 53.153 + style="font-size:8px;font-family:Times New Roman" 53.154 + id="flowRoot1938" 53.155 + xml:space="preserve"><flowRegion 53.156 + id="flowRegion1940"><rect 53.157 + style="font-size:8px;font-family:Times New Roman" 53.158 + y="464.50504" 53.159 + x="122.85714" 53.160 + height="93.571426" 53.161 + width="76.428574" 53.162 + id="rect1942" /></flowRegion><flowPara 53.163 + id="flowPara1944">Greetings!</flowPara><flowPara 53.164 + id="flowPara1946" /><flowPara 53.165 + id="flowPara1948">I am <flowSpan 53.166 + style="font-style:italic;fill:red" 53.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> 53.168 + <path 53.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" 53.170 + d="M 215.502,457.71933 L 196.35507,424.5765" 53.171 + id="path1999" 53.172 + inkscape:connector-type="polyline" 53.173 + inkscape:connection-start="#g1988" 53.174 + inkscape:connection-end="#g1966" /> 53.175 + <path 53.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" 53.177 + d="M 277.06936,457.71933 L 296.21629,424.5765" 53.178 + id="path2001" 53.179 + inkscape:connector-type="polyline" 53.180 + inkscape:connection-start="#g1988" 53.181 + inkscape:connection-end="#g1977" /> 53.182 + <text 53.183 + xml:space="preserve" 53.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" 53.185 + x="302.42859" 53.186 + y="515.08905" 53.187 + id="text1905"><tspan 53.188 + sodipodi:role="line" 53.189 + id="tspan1907" 53.190 + x="302.42859" 53.191 + y="515.08905">Base version</tspan></text> 53.192 + <text 53.193 + xml:space="preserve" 53.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" 53.195 + x="45.57143" 53.196 + y="374.1619" 53.197 + id="text1917"><tspan 53.198 + sodipodi:role="line" 53.199 + id="tspan1919" 53.200 + x="45.57143" 53.201 + y="374.1619">Our changes</tspan></text> 53.202 + <text 53.203 + xml:space="preserve" 53.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" 53.205 + x="385.71429" 53.206 + y="374.1619" 53.207 + id="text1921"><tspan 53.208 + sodipodi:role="line" 53.209 + id="tspan1923" 53.210 + x="385.71429" 53.211 + y="374.1619">Their changes</tspan></text> 53.212 + </g> 53.213 +</svg>
54.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 54.2 +++ b/fr/figs/tour-merge-merge.svg Sun Aug 16 04:58:01 2009 +0200 54.3 @@ -0,0 +1,380 @@ 54.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?> 54.5 +<!-- Created with Inkscape (http://www.inkscape.org/) --> 54.6 +<svg 54.7 + xmlns:dc="http://purl.org/dc/elements/1.1/" 54.8 + xmlns:cc="http://web.resource.org/cc/" 54.9 + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 54.10 + xmlns:svg="http://www.w3.org/2000/svg" 54.11 + xmlns="http://www.w3.org/2000/svg" 54.12 + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" 54.13 + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" 54.14 + width="744.09448819" 54.15 + height="1052.3622047" 54.16 + id="svg2" 54.17 + sodipodi:version="0.32" 54.18 + inkscape:version="0.44.1" 54.19 + sodipodi:docname="tour-merge-merge.svg"> 54.20 + <defs 54.21 + id="defs4"> 54.22 + <marker 54.23 + inkscape:stockid="Arrow1Mstart" 54.24 + orient="auto" 54.25 + refY="0.0" 54.26 + refX="0.0" 54.27 + id="Arrow1Mstart" 54.28 + style="overflow:visible"> 54.29 + <path 54.30 + id="path2973" 54.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 " 54.32 + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none" 54.33 + transform="scale(0.4) translate(10,0)" /> 54.34 + </marker> 54.35 + <marker 54.36 + inkscape:stockid="Arrow1Mend" 54.37 + orient="auto" 54.38 + refY="0.0" 54.39 + refX="0.0" 54.40 + id="Arrow1Mend" 54.41 + style="overflow:visible;"> 54.42 + <path 54.43 + id="path3066" 54.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 " 54.45 + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;" 54.46 + transform="scale(0.4) rotate(180) translate(10,0)" /> 54.47 + </marker> 54.48 + </defs> 54.49 + <sodipodi:namedview 54.50 + id="base" 54.51 + pagecolor="#ffffff" 54.52 + bordercolor="#666666" 54.53 + borderopacity="1.0" 54.54 + gridtolerance="10000" 54.55 + guidetolerance="10" 54.56 + objecttolerance="10" 54.57 + inkscape:pageopacity="0.0" 54.58 + inkscape:pageshadow="2" 54.59 + inkscape:zoom="1.4" 54.60 + inkscape:cx="247.53795" 54.61 + inkscape:cy="871.05738" 54.62 + inkscape:document-units="px" 54.63 + inkscape:current-layer="layer1" 54.64 + inkscape:window-width="906" 54.65 + inkscape:window-height="620" 54.66 + inkscape:window-x="38" 54.67 + inkscape:window-y="95" /> 54.68 + <metadata 54.69 + id="metadata7"> 54.70 + <rdf:RDF> 54.71 + <cc:Work 54.72 + rdf:about=""> 54.73 + <dc:format>image/svg+xml</dc:format> 54.74 + <dc:type 54.75 + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 54.76 + </cc:Work> 54.77 + </rdf:RDF> 54.78 + </metadata> 54.79 + <g 54.80 + inkscape:label="Layer 1" 54.81 + inkscape:groupmode="layer" 54.82 + id="layer1"> 54.83 + <rect 54.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" 54.85 + id="rect2995" 54.86 + width="94.285713" 54.87 + height="20.714285" 54.88 + x="532.85718" 54.89 + y="203.0479" /> 54.90 + <text 54.91 + xml:space="preserve" 54.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" 54.93 + x="173.57143" 54.94 + y="443.79074" 54.95 + id="text2832"><tspan 54.96 + sodipodi:role="line" 54.97 + id="tspan2834" 54.98 + x="173.57143" 54.99 + y="443.79074" /></text> 54.100 + <rect 54.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" 54.102 + id="rect2830" 54.103 + width="94.285713" 54.104 + height="20.714285" 54.105 + x="138" 54.106 + y="297.76227" /> 54.107 + <text 54.108 + xml:space="preserve" 54.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" 54.110 + x="162.09892" 54.111 + y="311.38342" 54.112 + id="text2824"><tspan 54.113 + sodipodi:role="line" 54.114 + id="tspan2826" 54.115 + x="162.09892" 54.116 + y="311.38342" 54.117 + style="font-family:Courier"><tspan 54.118 + style="font-weight:bold" 54.119 + id="tspan2862">4</tspan>: REV4</tspan></text> 54.120 + <path 54.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" 54.122 + d="M 185.14286,343.63731 L 185.14286,319.47656" 54.123 + id="path2900" 54.124 + inkscape:connector-type="polyline" /> 54.125 + <rect 54.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" 54.127 + id="rect2863" 54.128 + width="94.285713" 54.129 + height="20.714285" 54.130 + x="91.428574" 54.131 + y="250.47656" /> 54.132 + <text 54.133 + xml:space="preserve" 54.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" 54.135 + x="116.09886" 54.136 + y="264.56592" 54.137 + id="text1965" 54.138 + transform="scale(1.000002,0.999998)"><tspan 54.139 + sodipodi:role="line" 54.140 + id="tspan1967" 54.141 + x="116.09886" 54.142 + y="264.56592" 54.143 + style="font-family:Courier"><tspan 54.144 + style="font-weight:bold" 54.145 + id="tspan1973">5</tspan>: REV_my_new_hello</tspan></text> 54.146 + <path 54.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" 54.148 + d="M 173.95727,296.76228 L 149.75702,272.19085" 54.149 + id="path1971" 54.150 + inkscape:connector-type="polyline" 54.151 + inkscape:connection-end="#rect2863" 54.152 + inkscape:connection-start="#rect2830" /> 54.153 + <rect 54.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" 54.155 + id="rect2911" 54.156 + width="94.285995" 54.157 + height="20.714283" 54.158 + x="186.71414" 54.159 + y="204.40514" /> 54.160 + <text 54.161 + xml:space="preserve" 54.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" 54.163 + x="210.81311" 54.164 + y="218.02673" 54.165 + id="text2913" 54.166 + transform="scale(1.000002,0.999998)"><tspan 54.167 + sodipodi:role="line" 54.168 + id="tspan2915" 54.169 + x="210.81311" 54.170 + y="218.02673" 54.171 + style="font-family:Courier"><tspan 54.172 + id="tspan1966" 54.173 + style="font-weight:bold">6</tspan>: REV6_my_new_hello</tspan></text> 54.174 + <path 54.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" 54.176 + d="M 191.06908,296.76228 L 227.93092,226.11942" 54.177 + id="path2919" 54.178 + inkscape:connector-type="polyline" 54.179 + inkscape:connection-start="#rect2830" /> 54.180 + <text 54.181 + xml:space="preserve" 54.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" 54.183 + x="295.28571" 54.184 + y="217.56711" 54.185 + id="text2871"><tspan 54.186 + sodipodi:role="line" 54.187 + id="tspan2873" 54.188 + x="295.28571" 54.189 + y="217.56711">tip (and head)</tspan></text> 54.190 + <text 54.191 + xml:space="preserve" 54.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" 54.193 + x="76" 54.194 + y="264.91769" 54.195 + id="text2875"><tspan 54.196 + sodipodi:role="line" 54.197 + id="tspan2877" 54.198 + x="76" 54.199 + y="264.91769" 54.200 + style="text-align:end;text-anchor:end">head</tspan></text> 54.201 + <rect 54.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" 54.203 + id="rect1913" 54.204 + width="94.285713" 54.205 + height="20.714285" 54.206 + x="138" 54.207 + y="156.90514" /> 54.208 + <path 54.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" 54.210 + d="M 144.22399,249.47657 L 179.49029,178.61943" 54.211 + id="path1915" 54.212 + inkscape:connector-type="polyline" 54.213 + inkscape:connection-start="#rect2863" 54.214 + inkscape:connection-end="#rect1913" /> 54.215 + <path 54.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" 54.217 + d="M 222.20966,203.40514 L 196.79033,178.61943" 54.218 + id="path1917" 54.219 + inkscape:connector-type="polyline" 54.220 + inkscape:connection-start="#rect2911" 54.221 + inkscape:connection-end="#rect1913" /> 54.222 + <text 54.223 + xml:space="preserve" 54.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" 54.225 + x="166.16823" 54.226 + y="168.52228" 54.227 + id="text2806"><tspan 54.228 + sodipodi:role="line" 54.229 + id="tspan2808" 54.230 + x="166.16823" 54.231 + y="168.52228" 54.232 + style="font-family:Courier">merge</tspan></text> 54.233 + <text 54.234 + xml:space="preserve" 54.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" 54.236 + x="246" 54.237 + y="162.63338" 54.238 + id="text2810"><tspan 54.239 + sodipodi:role="line" 54.240 + id="tspan2812" 54.241 + x="246" 54.242 + y="162.63338">working directory</tspan><tspan 54.243 + sodipodi:role="line" 54.244 + x="246" 54.245 + y="177.63338" 54.246 + id="tspan2814">during merge</tspan></text> 54.247 + <rect 54.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" 54.249 + id="rect2816" 54.250 + width="94.285713" 54.251 + height="20.714285" 54.252 + x="483.14636" 54.253 + y="297.76227" /> 54.254 + <text 54.255 + xml:space="preserve" 54.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" 54.257 + x="507.24527" 54.258 + y="311.38342" 54.259 + id="text2818"><tspan 54.260 + sodipodi:role="line" 54.261 + id="tspan2820" 54.262 + x="507.24527" 54.263 + y="311.38342" 54.264 + style="font-family:Courier"><tspan 54.265 + style="font-weight:bold" 54.266 + id="tspan2822">4</tspan>: REV4</tspan></text> 54.267 + <path 54.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" 54.269 + d="M 530.28921,343.6373 L 530.28921,319.47655" 54.270 + id="path2824" 54.271 + inkscape:connector-type="polyline" /> 54.272 + <rect 54.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" 54.274 + id="rect2826" 54.275 + width="94.285713" 54.276 + height="20.714285" 54.277 + x="436.57492" 54.278 + y="250.47656" /> 54.279 + <text 54.280 + xml:space="preserve" 54.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" 54.282 + x="461.24484" 54.283 + y="264.56613" 54.284 + id="text2828" 54.285 + transform="scale(1.000002,0.999998)"><tspan 54.286 + sodipodi:role="line" 54.287 + id="tspan2830" 54.288 + x="461.24484" 54.289 + y="264.56613" 54.290 + style="font-family:Courier"><tspan 54.291 + style="font-weight:bold" 54.292 + id="tspan2832">5</tspan>: REV_my_new_hello</tspan></text> 54.293 + <path 54.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" 54.295 + d="M 519.10362,296.76227 L 494.90337,272.19084" 54.296 + id="path2834" 54.297 + inkscape:connector-type="polyline" /> 54.298 + <rect 54.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" 54.300 + id="rect2836" 54.301 + width="94.285995" 54.302 + height="20.714283" 54.303 + x="483.14001" 54.304 + y="156.548" /> 54.305 + <text 54.306 + xml:space="preserve" 54.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" 54.308 + x="555.95911" 54.309 + y="218.02698" 54.310 + id="text2838" 54.311 + transform="scale(1.000002,0.999998)"><tspan 54.312 + sodipodi:role="line" 54.313 + id="tspan2840" 54.314 + x="555.95911" 54.315 + y="218.02698" 54.316 + style="font-family:Courier"><tspan 54.317 + id="tspan2842" 54.318 + style="font-weight:bold">6</tspan>: REV6_my_new_hello</tspan></text> 54.319 + <path 54.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" 54.321 + d="M 536.21543,296.76227 L 574.03453,224.76218" 54.322 + id="path2844" 54.323 + inkscape:connector-type="polyline" /> 54.324 + <text 54.325 + xml:space="preserve" 54.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" 54.327 + x="594.43207" 54.328 + y="169.78796" 54.329 + id="text2846"><tspan 54.330 + sodipodi:role="line" 54.331 + id="tspan2848" 54.332 + x="594.43207" 54.333 + y="169.78796">tip</tspan></text> 54.334 + <path 54.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" 54.336 + d="M 489.37034,249.47656 L 524.65575,178.26229" 54.337 + id="path2856" 54.338 + inkscape:connector-type="polyline" 54.339 + inkscape:connection-end="#rect2836" /> 54.340 + <path 54.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" 54.342 + d="M 567.85714,202.0479 L 542.42591,178.26229" 54.343 + id="path2858" 54.344 + inkscape:connector-type="polyline" 54.345 + inkscape:connection-end="#rect2836" 54.346 + inkscape:connection-start="#rect2995" /> 54.347 + <text 54.348 + xml:space="preserve" 54.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" 54.350 + x="504.54507" 54.351 + y="170.39714" 54.352 + id="text2860"><tspan 54.353 + sodipodi:role="line" 54.354 + id="tspan2863" 54.355 + x="504.54507" 54.356 + y="170.39714" 54.357 + style="font-family:Courier"><tspan 54.358 + style="font-weight:bold" 54.359 + id="tspan2997">7</tspan>: REV7_my_new_hello</tspan></text> 54.360 + <text 54.361 + xml:space="preserve" 54.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" 54.363 + x="90.323105" 54.364 + y="120.21933" 54.365 + id="text2929"><tspan 54.366 + sodipodi:role="line" 54.367 + id="tspan2931" 54.368 + x="90.323105" 54.369 + y="120.21933" 54.370 + style="font-weight:bold">Working directory during merge</tspan></text> 54.371 + <text 54.372 + xml:space="preserve" 54.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" 54.374 + x="435.35226" 54.375 + y="120.21933" 54.376 + id="text2937"><tspan 54.377 + sodipodi:role="line" 54.378 + id="tspan2939" 54.379 + x="435.35226" 54.380 + y="120.21933" 54.381 + style="font-weight:bold">Repository after merge committed</tspan></text> 54.382 + </g> 54.383 +</svg>
55.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 55.2 +++ b/fr/figs/tour-merge-pull.svg Sun Aug 16 04:58:01 2009 +0200 55.3 @@ -0,0 +1,288 @@ 55.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?> 55.5 +<!-- Created with Inkscape (http://www.inkscape.org/) --> 55.6 +<svg 55.7 + xmlns:dc="http://purl.org/dc/elements/1.1/" 55.8 + xmlns:cc="http://web.resource.org/cc/" 55.9 + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 55.10 + xmlns:svg="http://www.w3.org/2000/svg" 55.11 + xmlns="http://www.w3.org/2000/svg" 55.12 + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" 55.13 + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" 55.14 + width="744.09448819" 55.15 + height="1052.3622047" 55.16 + id="svg2" 55.17 + sodipodi:version="0.32" 55.18 + inkscape:version="0.44.1" 55.19 + sodipodi:docname="tour-merge-pull.svg" 55.20 + sodipodi:docbase="/home/bos/hg/hgbook/en"> 55.21 + <defs 55.22 + id="defs4"> 55.23 + <marker 55.24 + inkscape:stockid="Arrow1Mstart" 55.25 + orient="auto" 55.26 + refY="0.0" 55.27 + refX="0.0" 55.28 + id="Arrow1Mstart" 55.29 + style="overflow:visible"> 55.30 + <path 55.31 + id="path2973" 55.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 " 55.33 + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none" 55.34 + transform="scale(0.4) translate(10,0)" /> 55.35 + </marker> 55.36 + <marker 55.37 + inkscape:stockid="Arrow1Mend" 55.38 + orient="auto" 55.39 + refY="0.0" 55.40 + refX="0.0" 55.41 + id="Arrow1Mend" 55.42 + style="overflow:visible;"> 55.43 + <path 55.44 + id="path3066" 55.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 " 55.46 + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;" 55.47 + transform="scale(0.4) rotate(180) translate(10,0)" /> 55.48 + </marker> 55.49 + </defs> 55.50 + <sodipodi:namedview 55.51 + id="base" 55.52 + pagecolor="#ffffff" 55.53 + bordercolor="#666666" 55.54 + borderopacity="1.0" 55.55 + gridtolerance="10000" 55.56 + guidetolerance="10" 55.57 + objecttolerance="10" 55.58 + inkscape:pageopacity="0.0" 55.59 + inkscape:pageshadow="2" 55.60 + inkscape:zoom="1.4" 55.61 + inkscape:cx="233.63208" 55.62 + inkscape:cy="832.54381" 55.63 + inkscape:document-units="px" 55.64 + inkscape:current-layer="layer1" 55.65 + inkscape:window-width="906" 55.66 + inkscape:window-height="620" 55.67 + inkscape:window-x="237" 55.68 + inkscape:window-y="103" /> 55.69 + <metadata 55.70 + id="metadata7"> 55.71 + <rdf:RDF> 55.72 + <cc:Work 55.73 + rdf:about=""> 55.74 + <dc:format>image/svg+xml</dc:format> 55.75 + <dc:type 55.76 + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 55.77 + </cc:Work> 55.78 + </rdf:RDF> 55.79 + </metadata> 55.80 + <g 55.81 + inkscape:label="Layer 1" 55.82 + inkscape:groupmode="layer" 55.83 + id="layer1"> 55.84 + <text 55.85 + xml:space="preserve" 55.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" 55.87 + x="173.57143" 55.88 + y="443.79074" 55.89 + id="text2832"><tspan 55.90 + sodipodi:role="line" 55.91 + id="tspan2834" 55.92 + x="173.57143" 55.93 + y="443.79074" /></text> 55.94 + <rect 55.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" 55.96 + id="rect1878" 55.97 + width="94.285713" 55.98 + height="20.714285" 55.99 + x="138" 55.100 + y="479.50504" /> 55.101 + <text 55.102 + xml:space="preserve" 55.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" 55.104 + x="162.09892" 55.105 + y="493.12619" 55.106 + id="text1872"><tspan 55.107 + sodipodi:role="line" 55.108 + id="tspan1874" 55.109 + x="162.09892" 55.110 + y="493.12619" 55.111 + style="font-family:Courier"><tspan 55.112 + style="font-weight:bold" 55.113 + id="tspan1876">0</tspan>: REV0</tspan></text> 55.114 + <rect 55.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" 55.116 + id="rect2800" 55.117 + width="94.285713" 55.118 + height="20.714285" 55.119 + x="138" 55.120 + y="432.63004" /> 55.121 + <text 55.122 + xml:space="preserve" 55.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" 55.124 + x="162.09892" 55.125 + y="446.25119" 55.126 + id="text2794"><tspan 55.127 + sodipodi:role="line" 55.128 + id="tspan2796" 55.129 + x="162.09892" 55.130 + y="446.25119" 55.131 + style="font-family:Courier"><tspan 55.132 + id="tspan2868" 55.133 + style="font-weight:bold">1</tspan>: REV1</tspan></text> 55.134 + <rect 55.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" 55.136 + id="rect2810" 55.137 + width="94.285713" 55.138 + height="20.714285" 55.139 + x="138" 55.140 + y="385.75504" /> 55.141 + <text 55.142 + xml:space="preserve" 55.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" 55.144 + x="162.09892" 55.145 + y="399.37619" 55.146 + id="text2804"><tspan 55.147 + sodipodi:role="line" 55.148 + id="tspan2806" 55.149 + x="162.09892" 55.150 + y="399.37619" 55.151 + style="font-family:Courier"><tspan 55.152 + style="font-weight:bold" 55.153 + id="tspan2866">2</tspan>: REV2</tspan></text> 55.154 + <rect 55.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" 55.156 + id="rect2820" 55.157 + width="94.285713" 55.158 + height="20.714285" 55.159 + x="138" 55.160 + y="338.88007" /> 55.161 + <text 55.162 + xml:space="preserve" 55.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" 55.164 + x="162.09892" 55.165 + y="352.50122" 55.166 + id="text2814"><tspan 55.167 + sodipodi:role="line" 55.168 + id="tspan2816" 55.169 + x="162.09892" 55.170 + y="352.50122" 55.171 + style="font-family:Courier"><tspan 55.172 + style="font-weight:bold" 55.173 + id="tspan2864">3</tspan>: REV3</tspan></text> 55.174 + <rect 55.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" 55.176 + id="rect2830" 55.177 + width="94.285713" 55.178 + height="20.714285" 55.179 + x="138" 55.180 + y="292.00504" /> 55.181 + <text 55.182 + xml:space="preserve" 55.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" 55.184 + x="162.09892" 55.185 + y="305.62619" 55.186 + id="text2824"><tspan 55.187 + sodipodi:role="line" 55.188 + id="tspan2826" 55.189 + x="162.09892" 55.190 + y="305.62619" 55.191 + style="font-family:Courier"><tspan 55.192 + style="font-weight:bold" 55.193 + id="tspan2862">4</tspan>: REV4</tspan></text> 55.194 + <path 55.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" 55.196 + d="M 185.14286,478.50504 L 185.14286,454.34432" 55.197 + id="path2894" 55.198 + inkscape:connector-type="polyline" /> 55.199 + <path 55.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" 55.201 + d="M 185.14286,431.63004 L 185.14286,407.46932" 55.202 + id="path2896" 55.203 + inkscape:connector-type="polyline" /> 55.204 + <path 55.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" 55.206 + d="M 185.14286,384.75504 L 185.14286,360.59435" 55.207 + id="path2898" 55.208 + inkscape:connector-type="polyline" /> 55.209 + <path 55.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" 55.211 + d="M 185.14286,337.88007 L 185.14286,313.71932" 55.212 + id="path2900" 55.213 + inkscape:connector-type="polyline" /> 55.214 + <rect 55.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" 55.216 + id="rect2863" 55.217 + width="94.285713" 55.218 + height="20.714285" 55.219 + x="91.428574" 55.220 + y="244.71933" /> 55.221 + <text 55.222 + xml:space="preserve" 55.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" 55.224 + x="116.09886" 55.225 + y="258.80865" 55.226 + id="text1965" 55.227 + transform="scale(1.000002,0.999998)"><tspan 55.228 + sodipodi:role="line" 55.229 + id="tspan1967" 55.230 + x="116.09886" 55.231 + y="258.80865" 55.232 + style="font-family:Courier"><tspan 55.233 + style="font-weight:bold" 55.234 + id="tspan1973">5</tspan>: REV_my_new_hello</tspan></text> 55.235 + <path 55.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" 55.237 + d="M 173.95727,291.00504 L 149.75702,266.43361" 55.238 + id="path1971" 55.239 + inkscape:connector-type="polyline" 55.240 + inkscape:connection-end="#rect2863" 55.241 + inkscape:connection-start="#rect2830" /> 55.242 + <rect 55.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" 55.244 + id="rect2911" 55.245 + width="94.285995" 55.246 + height="20.714283" 55.247 + x="186.71414" 55.248 + y="198.6479" /> 55.249 + <text 55.250 + xml:space="preserve" 55.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" 55.252 + x="210.81311" 55.253 + y="212.26949" 55.254 + id="text2913" 55.255 + transform="scale(1.000002,0.999998)"><tspan 55.256 + sodipodi:role="line" 55.257 + id="tspan2915" 55.258 + x="210.81311" 55.259 + y="212.26949" 55.260 + style="font-family:Courier"><tspan 55.261 + id="tspan1966" 55.262 + style="font-weight:bold">6</tspan>: REV6_my_new_hello</tspan></text> 55.263 + <path 55.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" 55.265 + d="M 191.06908,291.00504 L 227.93092,220.36218" 55.266 + id="path2919" 55.267 + inkscape:connector-type="polyline" 55.268 + inkscape:connection-start="#rect2830" /> 55.269 + <text 55.270 + xml:space="preserve" 55.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" 55.272 + x="295.28571" 55.273 + y="211.80988" 55.274 + id="text2871"><tspan 55.275 + sodipodi:role="line" 55.276 + id="tspan2873" 55.277 + x="295.28571" 55.278 + y="211.80988">tip (and head)</tspan></text> 55.279 + <text 55.280 + xml:space="preserve" 55.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" 55.282 + x="76" 55.283 + y="259.16046" 55.284 + id="text2875"><tspan 55.285 + sodipodi:role="line" 55.286 + id="tspan2877" 55.287 + x="76" 55.288 + y="259.16046" 55.289 + style="text-align:end;text-anchor:end">head</tspan></text> 55.290 + </g> 55.291 +</svg>
56.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 56.2 +++ b/fr/figs/tour-merge-sep-repos.svg Sun Aug 16 04:58:01 2009 +0200 56.3 @@ -0,0 +1,466 @@ 56.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?> 56.5 +<!-- Created with Inkscape (http://www.inkscape.org/) --> 56.6 +<svg 56.7 + xmlns:dc="http://purl.org/dc/elements/1.1/" 56.8 + xmlns:cc="http://web.resource.org/cc/" 56.9 + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 56.10 + xmlns:svg="http://www.w3.org/2000/svg" 56.11 + xmlns="http://www.w3.org/2000/svg" 56.12 + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" 56.13 + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" 56.14 + width="744.09448819" 56.15 + height="1052.3622047" 56.16 + id="svg2" 56.17 + sodipodi:version="0.32" 56.18 + inkscape:version="0.44.1" 56.19 + sodipodi:docname="tour-merge-sep-repos.svg"> 56.20 + <defs 56.21 + id="defs4"> 56.22 + <marker 56.23 + inkscape:stockid="Arrow1Mstart" 56.24 + orient="auto" 56.25 + refY="0.0" 56.26 + refX="0.0" 56.27 + id="Arrow1Mstart" 56.28 + style="overflow:visible"> 56.29 + <path 56.30 + id="path2973" 56.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 " 56.32 + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none" 56.33 + transform="scale(0.4) translate(10,0)" /> 56.34 + </marker> 56.35 + <marker 56.36 + inkscape:stockid="Arrow1Mend" 56.37 + orient="auto" 56.38 + refY="0.0" 56.39 + refX="0.0" 56.40 + id="Arrow1Mend" 56.41 + style="overflow:visible;"> 56.42 + <path 56.43 + id="path3066" 56.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 " 56.45 + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;" 56.46 + transform="scale(0.4) rotate(180) translate(10,0)" /> 56.47 + </marker> 56.48 + </defs> 56.49 + <sodipodi:namedview 56.50 + id="base" 56.51 + pagecolor="#ffffff" 56.52 + bordercolor="#666666" 56.53 + borderopacity="1.0" 56.54 + gridtolerance="10000" 56.55 + guidetolerance="10" 56.56 + objecttolerance="10" 56.57 + inkscape:pageopacity="0.0" 56.58 + inkscape:pageshadow="2" 56.59 + inkscape:zoom="1.4" 56.60 + inkscape:cx="307.20351" 56.61 + inkscape:cy="716.87911" 56.62 + inkscape:document-units="px" 56.63 + inkscape:current-layer="layer1" 56.64 + inkscape:window-width="906" 56.65 + inkscape:window-height="620" 56.66 + inkscape:window-x="5" 56.67 + inkscape:window-y="49" /> 56.68 + <metadata 56.69 + id="metadata7"> 56.70 + <rdf:RDF> 56.71 + <cc:Work 56.72 + rdf:about=""> 56.73 + <dc:format>image/svg+xml</dc:format> 56.74 + <dc:type 56.75 + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 56.76 + </cc:Work> 56.77 + </rdf:RDF> 56.78 + </metadata> 56.79 + <g 56.80 + inkscape:label="Layer 1" 56.81 + inkscape:groupmode="layer" 56.82 + id="layer1"> 56.83 + <text 56.84 + xml:space="preserve" 56.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" 56.86 + x="173.57143" 56.87 + y="443.79074" 56.88 + id="text2832"><tspan 56.89 + sodipodi:role="line" 56.90 + id="tspan2834" 56.91 + x="173.57143" 56.92 + y="443.79074" /></text> 56.93 + <rect 56.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" 56.95 + id="rect1878" 56.96 + width="94.285713" 56.97 + height="20.714285" 56.98 + x="138" 56.99 + y="479.50504" /> 56.100 + <text 56.101 + xml:space="preserve" 56.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" 56.103 + x="162.09892" 56.104 + y="493.12619" 56.105 + id="text1872"><tspan 56.106 + sodipodi:role="line" 56.107 + id="tspan1874" 56.108 + x="162.09892" 56.109 + y="493.12619" 56.110 + style="font-family:Courier"><tspan 56.111 + style="font-weight:bold" 56.112 + id="tspan1876">0</tspan>: REV0</tspan></text> 56.113 + <rect 56.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" 56.115 + id="rect2800" 56.116 + width="94.285713" 56.117 + height="20.714285" 56.118 + x="138" 56.119 + y="432.63004" /> 56.120 + <text 56.121 + xml:space="preserve" 56.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" 56.123 + x="162.09892" 56.124 + y="446.25119" 56.125 + id="text2794"><tspan 56.126 + sodipodi:role="line" 56.127 + id="tspan2796" 56.128 + x="162.09892" 56.129 + y="446.25119" 56.130 + style="font-family:Courier"><tspan 56.131 + id="tspan2868" 56.132 + style="font-weight:bold">1</tspan>: REV1</tspan></text> 56.133 + <rect 56.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" 56.135 + id="rect2810" 56.136 + width="94.285713" 56.137 + height="20.714285" 56.138 + x="138" 56.139 + y="385.75504" /> 56.140 + <text 56.141 + xml:space="preserve" 56.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" 56.143 + x="162.09892" 56.144 + y="399.37619" 56.145 + id="text2804"><tspan 56.146 + sodipodi:role="line" 56.147 + id="tspan2806" 56.148 + x="162.09892" 56.149 + y="399.37619" 56.150 + style="font-family:Courier"><tspan 56.151 + style="font-weight:bold" 56.152 + id="tspan2866">2</tspan>: REV2</tspan></text> 56.153 + <rect 56.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" 56.155 + id="rect2820" 56.156 + width="94.285713" 56.157 + height="20.714285" 56.158 + x="138" 56.159 + y="338.88007" /> 56.160 + <text 56.161 + xml:space="preserve" 56.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" 56.163 + x="162.09892" 56.164 + y="352.50122" 56.165 + id="text2814"><tspan 56.166 + sodipodi:role="line" 56.167 + id="tspan2816" 56.168 + x="162.09892" 56.169 + y="352.50122" 56.170 + style="font-family:Courier"><tspan 56.171 + style="font-weight:bold" 56.172 + id="tspan2864">3</tspan>: REV3</tspan></text> 56.173 + <rect 56.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" 56.175 + id="rect2830" 56.176 + width="94.285713" 56.177 + height="20.714285" 56.178 + x="138" 56.179 + y="292.00504" /> 56.180 + <text 56.181 + xml:space="preserve" 56.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" 56.183 + x="162.09892" 56.184 + y="305.62619" 56.185 + id="text2824"><tspan 56.186 + sodipodi:role="line" 56.187 + id="tspan2826" 56.188 + x="162.09892" 56.189 + y="305.62619" 56.190 + style="font-family:Courier"><tspan 56.191 + style="font-weight:bold" 56.192 + id="tspan2862">4</tspan>: REV4</tspan></text> 56.193 + <path 56.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" 56.195 + d="M 185.14286,478.50504 L 185.14286,454.34432" 56.196 + id="path2894" 56.197 + inkscape:connector-type="polyline" /> 56.198 + <path 56.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" 56.200 + d="M 185.14286,431.63004 L 185.14286,407.46932" 56.201 + id="path2896" 56.202 + inkscape:connector-type="polyline" /> 56.203 + <path 56.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" 56.205 + d="M 185.14286,384.75504 L 185.14286,360.59435" 56.206 + id="path2898" 56.207 + inkscape:connector-type="polyline" /> 56.208 + <path 56.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" 56.210 + d="M 185.14286,337.88007 L 185.14286,313.71932" 56.211 + id="path2900" 56.212 + inkscape:connector-type="polyline" /> 56.213 + <rect 56.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" 56.215 + id="rect1963" 56.216 + width="94.285995" 56.217 + height="20.714283" 56.218 + x="138" 56.219 + y="245.18723" /> 56.220 + <text 56.221 + xml:space="preserve" 56.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" 56.223 + x="162.09877" 56.224 + y="258.80865" 56.225 + id="text1965" 56.226 + transform="scale(1.000002,0.999998)"><tspan 56.227 + sodipodi:role="line" 56.228 + id="tspan1967" 56.229 + x="162.09877" 56.230 + y="258.80865" 56.231 + style="font-family:Courier"><tspan 56.232 + style="font-weight:bold" 56.233 + id="tspan1973">5</tspan>: REV_my_hello</tspan></text> 56.234 + <path 56.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" 56.236 + d="M 185.143,291.06218 L 185.143,266.90143" 56.237 + id="path1971" 56.238 + inkscape:connector-type="polyline" /> 56.239 + <text 56.240 + xml:space="preserve" 56.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" 56.242 + x="136.90039" 56.243 + y="232.25546" 56.244 + id="text2921"><tspan 56.245 + sodipodi:role="line" 56.246 + id="tspan2923" 56.247 + x="136.90039" 56.248 + y="232.25546">my-hello</tspan></text> 56.249 + <rect 56.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" 56.251 + id="rect2863" 56.252 + width="94.285713" 56.253 + height="20.714285" 56.254 + x="370.71414" 56.255 + y="479.49289" /> 56.256 + <text 56.257 + xml:space="preserve" 56.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" 56.259 + x="394.81305" 56.260 + y="493.11404" 56.261 + id="text2865"><tspan 56.262 + sodipodi:role="line" 56.263 + id="tspan2867" 56.264 + x="394.81305" 56.265 + y="493.11404" 56.266 + style="font-family:Courier"><tspan 56.267 + style="font-weight:bold" 56.268 + id="tspan2869">0</tspan>: REV0</tspan></text> 56.269 + <rect 56.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" 56.271 + id="rect2871" 56.272 + width="94.285713" 56.273 + height="20.714285" 56.274 + x="370.71414" 56.275 + y="432.61789" /> 56.276 + <text 56.277 + xml:space="preserve" 56.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" 56.279 + x="394.81305" 56.280 + y="446.23904" 56.281 + id="text2873"><tspan 56.282 + sodipodi:role="line" 56.283 + id="tspan2875" 56.284 + x="394.81305" 56.285 + y="446.23904" 56.286 + style="font-family:Courier"><tspan 56.287 + id="tspan2877" 56.288 + style="font-weight:bold">1</tspan>: REV1</tspan></text> 56.289 + <rect 56.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" 56.291 + id="rect2879" 56.292 + width="94.285713" 56.293 + height="20.714285" 56.294 + x="370.71414" 56.295 + y="385.74289" /> 56.296 + <text 56.297 + xml:space="preserve" 56.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" 56.299 + x="394.81305" 56.300 + y="399.36404" 56.301 + id="text2881"><tspan 56.302 + sodipodi:role="line" 56.303 + id="tspan2883" 56.304 + x="394.81305" 56.305 + y="399.36404" 56.306 + style="font-family:Courier"><tspan 56.307 + style="font-weight:bold" 56.308 + id="tspan2885">2</tspan>: REV2</tspan></text> 56.309 + <rect 56.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" 56.311 + id="rect2887" 56.312 + width="94.285713" 56.313 + height="20.714285" 56.314 + x="370.71414" 56.315 + y="338.86792" /> 56.316 + <text 56.317 + xml:space="preserve" 56.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" 56.319 + x="394.81305" 56.320 + y="352.48907" 56.321 + id="text2889"><tspan 56.322 + sodipodi:role="line" 56.323 + id="tspan2891" 56.324 + x="394.81305" 56.325 + y="352.48907" 56.326 + style="font-family:Courier"><tspan 56.327 + style="font-weight:bold" 56.328 + id="tspan2893">3</tspan>: REV3</tspan></text> 56.329 + <rect 56.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" 56.331 + id="rect2895" 56.332 + width="94.285713" 56.333 + height="20.714285" 56.334 + x="370.71414" 56.335 + y="291.99289" /> 56.336 + <text 56.337 + xml:space="preserve" 56.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" 56.339 + x="394.81305" 56.340 + y="305.61404" 56.341 + id="text2897"><tspan 56.342 + sodipodi:role="line" 56.343 + id="tspan2899" 56.344 + x="394.81305" 56.345 + y="305.61404" 56.346 + style="font-family:Courier"><tspan 56.347 + style="font-weight:bold" 56.348 + id="tspan2901">4</tspan>: REV4</tspan></text> 56.349 + <path 56.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" 56.351 + d="M 417.85701,478.4929 L 417.85701,454.33218" 56.352 + id="path2903" 56.353 + inkscape:connector-type="polyline" /> 56.354 + <path 56.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" 56.356 + d="M 417.85701,431.6179 L 417.85701,407.45718" 56.357 + id="path2905" 56.358 + inkscape:connector-type="polyline" /> 56.359 + <path 56.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" 56.361 + d="M 417.85701,384.7429 L 417.85701,360.58221" 56.362 + id="path2907" 56.363 + inkscape:connector-type="polyline" /> 56.364 + <path 56.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" 56.366 + d="M 417.85701,337.86793 L 417.85701,313.70718" 56.367 + id="path2909" 56.368 + inkscape:connector-type="polyline" /> 56.369 + <rect 56.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" 56.371 + id="rect2911" 56.372 + width="94.285995" 56.373 + height="20.714283" 56.374 + x="370.71414" 56.375 + y="245.17511" /> 56.376 + <text 56.377 + xml:space="preserve" 56.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" 56.379 + x="394.81274" 56.380 + y="258.79678" 56.381 + id="text2913" 56.382 + transform="scale(1.000002,0.999998)"><tspan 56.383 + sodipodi:role="line" 56.384 + id="tspan2915" 56.385 + x="394.81274" 56.386 + y="258.79678" 56.387 + style="font-family:Courier"><tspan 56.388 + style="font-weight:bold" 56.389 + id="tspan2917">5</tspan>: REV_my_new_hello</tspan></text> 56.390 + <path 56.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" 56.392 + d="M 417.85715,291.05004 L 417.85715,266.88929" 56.393 + id="path2919" 56.394 + inkscape:connector-type="polyline" /> 56.395 + <text 56.396 + xml:space="preserve" 56.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" 56.398 + x="369.61453" 56.399 + y="232.25546" 56.400 + id="text2925"><tspan 56.401 + sodipodi:role="line" 56.402 + id="tspan2927" 56.403 + x="369.61453" 56.404 + y="232.25546">my-new-hello</tspan></text> 56.405 + <text 56.406 + xml:space="preserve" 56.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" 56.408 + x="300.54352" 56.409 + y="252.12723" 56.410 + id="text2933"><tspan 56.411 + sodipodi:role="line" 56.412 + id="tspan2935" 56.413 + x="300.54352" 56.414 + y="252.12723" 56.415 + style="text-align:center;text-anchor:middle">newest changes</tspan><tspan 56.416 + sodipodi:role="line" 56.417 + x="300.54352" 56.418 + y="267.12723" 56.419 + style="text-align:center;text-anchor:middle" 56.420 + id="tspan3132">differ</tspan></text> 56.421 + <text 56.422 + xml:space="preserve" 56.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" 56.424 + x="262.15436" 56.425 + y="398.37112" 56.426 + id="text2929"><tspan 56.427 + sodipodi:role="line" 56.428 + x="262.15436" 56.429 + y="398.37112" 56.430 + id="tspan3013" 56.431 + style="text-align:start;text-anchor:start">common history</tspan></text> 56.432 + <g 56.433 + id="g3107" 56.434 + transform="translate(0,0.855744)"> 56.435 + <path 56.436 + id="path3101" 56.437 + d="M 300.35713,381.29075 L 300.35713,304.50504" 56.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" /> 56.439 + <path 56.440 + id="path3105" 56.441 + d="M 291.07142,301.64789 L 309.28571,301.64789" 56.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" /> 56.443 + </g> 56.444 + <path 56.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" 56.446 + d="M 300.53571,486.38926 L 300.53571,409.60355" 56.447 + id="path3113" /> 56.448 + <path 56.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" 56.450 + d="M 291.25,488.49641 L 309.46429,488.49641" 56.451 + id="path3115" /> 56.452 + <text 56.453 + xml:space="preserve" 56.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" 56.455 + x="480.71429" 56.456 + y="250.91507" 56.457 + id="text1949"><tspan 56.458 + sodipodi:role="line" 56.459 + id="tspan1951" 56.460 + x="480.71429" 56.461 + y="250.91507" 56.462 + style="text-align:start;text-anchor:start">head revision</tspan><tspan 56.463 + sodipodi:role="line" 56.464 + x="480.71429" 56.465 + y="265.91507" 56.466 + id="tspan1953" 56.467 + style="text-align:start;text-anchor:start">(has no children)</tspan></text> 56.468 + </g> 56.469 +</svg>
57.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 57.2 +++ b/fr/figs/undo-manual-merge.dot Sun Aug 16 04:58:01 2009 +0200 57.3 @@ -0,0 +1,8 @@ 57.4 +digraph undo_manual { 57.5 + "first change" -> "second change"; 57.6 + "second change" -> "third change"; 57.7 + backout [label="back out\nsecond change", shape=box]; 57.8 + "second change" -> backout; 57.9 + "third change" -> "manual\nmerge"; 57.10 + backout -> "manual\nmerge"; 57.11 +}
58.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 58.2 +++ b/fr/figs/undo-manual.dot Sun Aug 16 04:58:01 2009 +0200 58.3 @@ -0,0 +1,6 @@ 58.4 +digraph undo_manual { 58.5 + "first change" -> "second change"; 58.6 + "second change" -> "third change"; 58.7 + backout [label="back out\nsecond change", shape=box]; 58.8 + "second change" -> backout; 58.9 +}
59.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 59.2 +++ b/fr/figs/undo-non-tip.dot Sun Aug 16 04:58:01 2009 +0200 59.3 @@ -0,0 +1,9 @@ 59.4 +digraph undo_non_tip { 59.5 + "first change" -> "second change"; 59.6 + "second change" -> "third change"; 59.7 + backout [label="back out\nsecond change", shape=box]; 59.8 + "second change" -> backout; 59.9 + merge [label="automated\nmerge", shape=box]; 59.10 + "third change" -> merge; 59.11 + backout -> merge; 59.12 +}
60.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 60.2 +++ b/fr/figs/undo-simple.dot Sun Aug 16 04:58:01 2009 +0200 60.3 @@ -0,0 +1,4 @@ 60.4 +digraph undo_simple { 60.5 + "first change" -> "second change"; 60.6 + "second change" -> "back out\nsecond change"; 60.7 +}
61.1 Binary file fr/figs/warning.png has changed
62.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 62.2 +++ b/fr/figs/wdir-after-commit.svg Sun Aug 16 04:58:01 2009 +0200 62.3 @@ -0,0 +1,394 @@ 62.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?> 62.5 +<!-- Created with Inkscape (http://www.inkscape.org/) --> 62.6 +<svg 62.7 + xmlns:dc="http://purl.org/dc/elements/1.1/" 62.8 + xmlns:cc="http://web.resource.org/cc/" 62.9 + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 62.10 + xmlns:svg="http://www.w3.org/2000/svg" 62.11 + xmlns="http://www.w3.org/2000/svg" 62.12 + xmlns:xlink="http://www.w3.org/1999/xlink" 62.13 + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" 62.14 + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" 62.15 + width="744.09448819" 62.16 + height="1052.3622047" 62.17 + id="svg5971" 62.18 + sodipodi:version="0.32" 62.19 + inkscape:version="0.44.1" 62.20 + sodipodi:docbase="/home/bos/hg/hgbook/en" 62.21 + sodipodi:docname="wdir-after-commit.svg"> 62.22 + <defs 62.23 + id="defs5973"> 62.24 + <linearGradient 62.25 + inkscape:collect="always" 62.26 + xlink:href="#linearGradient6049" 62.27 + id="linearGradient6445" 62.28 + gradientUnits="userSpaceOnUse" 62.29 + gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)" 62.30 + x1="333.91171" 62.31 + y1="488.79077" 62.32 + x2="508.94543" 62.33 + y2="263.79077" /> 62.34 + <marker 62.35 + inkscape:stockid="Arrow1Mstart" 62.36 + orient="auto" 62.37 + refY="0.0" 62.38 + refX="0.0" 62.39 + id="Arrow1Mstart" 62.40 + style="overflow:visible"> 62.41 + <path 62.42 + id="path4855" 62.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 " 62.44 + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none" 62.45 + transform="scale(0.4) translate(10,0)" /> 62.46 + </marker> 62.47 + <linearGradient 62.48 + id="linearGradient6049"> 62.49 + <stop 62.50 + style="stop-color:#686868;stop-opacity:1;" 62.51 + offset="0" 62.52 + id="stop6051" /> 62.53 + <stop 62.54 + style="stop-color:#f0f0f0;stop-opacity:1;" 62.55 + offset="1" 62.56 + id="stop6053" /> 62.57 + </linearGradient> 62.58 + <marker 62.59 + inkscape:stockid="Arrow1Mend" 62.60 + orient="auto" 62.61 + refY="0.0" 62.62 + refX="0.0" 62.63 + id="Arrow1Mend" 62.64 + style="overflow:visible;"> 62.65 + <path 62.66 + id="path4852" 62.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 " 62.68 + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;" 62.69 + transform="scale(0.4) rotate(180) translate(10,0)" /> 62.70 + </marker> 62.71 + <linearGradient 62.72 + inkscape:collect="always" 62.73 + xlink:href="#linearGradient6049" 62.74 + id="linearGradient6083" 62.75 + gradientUnits="userSpaceOnUse" 62.76 + gradientTransform="translate(-240.0462,-8.633237e-6)" 62.77 + x1="333.91171" 62.78 + y1="488.79077" 62.79 + x2="508.94543" 62.80 + y2="263.79077" /> 62.81 + <linearGradient 62.82 + inkscape:collect="always" 62.83 + xlink:href="#linearGradient6049" 62.84 + id="linearGradient6142" 62.85 + gradientUnits="userSpaceOnUse" 62.86 + gradientTransform="translate(-42.00893,-30.49544)" 62.87 + x1="333.91171" 62.88 + y1="488.79077" 62.89 + x2="508.94543" 62.90 + y2="263.79077" /> 62.91 + <linearGradient 62.92 + inkscape:collect="always" 62.93 + xlink:href="#linearGradient6049" 62.94 + id="linearGradient6193" 62.95 + gradientUnits="userSpaceOnUse" 62.96 + gradientTransform="translate(-240.0462,-8.633237e-6)" 62.97 + x1="333.91171" 62.98 + y1="488.79077" 62.99 + x2="508.94543" 62.100 + y2="263.79077" /> 62.101 + <linearGradient 62.102 + inkscape:collect="always" 62.103 + xlink:href="#linearGradient6049" 62.104 + id="linearGradient6216" 62.105 + gradientUnits="userSpaceOnUse" 62.106 + gradientTransform="translate(-6.0462,-0.664361)" 62.107 + x1="333.91171" 62.108 + y1="488.79077" 62.109 + x2="508.94543" 62.110 + y2="263.79077" /> 62.111 + <linearGradient 62.112 + inkscape:collect="always" 62.113 + xlink:href="#linearGradient6049" 62.114 + id="linearGradient6232" 62.115 + gradientUnits="userSpaceOnUse" 62.116 + gradientTransform="matrix(1.000474,0,0,0.790947,222.8399,50.85693)" 62.117 + x1="333.91171" 62.118 + y1="488.79077" 62.119 + x2="508.94543" 62.120 + y2="263.79077" /> 62.121 + <linearGradient 62.122 + inkscape:collect="always" 62.123 + xlink:href="#linearGradient6049" 62.124 + id="linearGradient6772" 62.125 + gradientUnits="userSpaceOnUse" 62.126 + gradientTransform="matrix(1.000474,0,0,0.790947,222.8399,50.85693)" 62.127 + x1="333.91171" 62.128 + y1="488.79077" 62.129 + x2="508.94543" 62.130 + y2="263.79077" /> 62.131 + </defs> 62.132 + <sodipodi:namedview 62.133 + id="base" 62.134 + pagecolor="#ffffff" 62.135 + bordercolor="#666666" 62.136 + borderopacity="1.0" 62.137 + gridtolerance="10000" 62.138 + guidetolerance="10" 62.139 + objecttolerance="10" 62.140 + inkscape:pageopacity="0.0" 62.141 + inkscape:pageshadow="2" 62.142 + inkscape:zoom="0.90509668" 62.143 + inkscape:cx="390.0539" 62.144 + inkscape:cy="690.49342" 62.145 + inkscape:document-units="px" 62.146 + inkscape:current-layer="layer1" 62.147 + showguides="true" 62.148 + inkscape:guide-bbox="true" 62.149 + inkscape:window-width="906" 62.150 + inkscape:window-height="620" 62.151 + inkscape:window-x="0" 62.152 + inkscape:window-y="25"> 62.153 + <sodipodi:guide 62.154 + orientation="vertical" 62.155 + position="-1.4285714" 62.156 + id="guide6022" /> 62.157 + </sodipodi:namedview> 62.158 + <metadata 62.159 + id="metadata5976"> 62.160 + <rdf:RDF> 62.161 + <cc:Work 62.162 + rdf:about=""> 62.163 + <dc:format>image/svg+xml</dc:format> 62.164 + <dc:type 62.165 + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 62.166 + </cc:Work> 62.167 + </rdf:RDF> 62.168 + </metadata> 62.169 + <g 62.170 + inkscape:label="Layer 1" 62.171 + inkscape:groupmode="layer" 62.172 + id="layer1"> 62.173 + <rect 62.174 + y="245.98355" 62.175 + x="328.23956" 62.176 + height="258.57144" 62.177 + width="174.28572" 62.178 + id="rect6047" 62.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" /> 62.180 + <g 62.181 + id="g6261" 62.182 + transform="translate(234,0)"> 62.183 + <rect 62.184 + y="258.7149" 62.185 + x="114.11369" 62.186 + height="44.537449" 62.187 + width="134.53746" 62.188 + id="rect5983" 62.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" /> 62.190 + <text 62.191 + id="text5985" 62.192 + y="284.47562" 62.193 + x="138.7962" 62.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" 62.195 + xml:space="preserve"><tspan 62.196 + style="font-family:Courier" 62.197 + y="284.47562" 62.198 + x="138.7962" 62.199 + id="tspan5987" 62.200 + sodipodi:role="line">dfbbb33f3fa3</tspan></text> 62.201 + </g> 62.202 + <rect 62.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" 62.204 + id="rect5996" 62.205 + width="134.53746" 62.206 + height="44.537449" 62.207 + x="348.11371" 62.208 + y="320.38159" /> 62.209 + <text 62.210 + xml:space="preserve" 62.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" 62.212 + x="372.7962" 62.213 + y="346.1423" 62.214 + id="text5998"><tspan 62.215 + sodipodi:role="line" 62.216 + id="tspan6000" 62.217 + x="372.7962" 62.218 + y="346.1423" 62.219 + style="font-family:Courier">e7639888bb2f</tspan></text> 62.220 + <rect 62.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" 62.222 + id="rect6004" 62.223 + width="134.53746" 62.224 + height="44.537449" 62.225 + x="348.11371" 62.226 + y="382.04825" /> 62.227 + <text 62.228 + xml:space="preserve" 62.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" 62.230 + x="370.65421" 62.231 + y="407.80896" 62.232 + id="text6006"><tspan 62.233 + sodipodi:role="line" 62.234 + id="tspan6008" 62.235 + x="370.65421" 62.236 + y="407.80896" 62.237 + style="font-family:Courier">7b064d8bac5e</tspan></text> 62.238 + <path 62.239 + inkscape:connector-type="polyline" 62.240 + id="path6018" 62.241 + d="M 415.38242,303.62646 L 415.38242,320.00744" 62.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" /> 62.243 + <path 62.244 + inkscape:connection-end="#rect6004" 62.245 + inkscape:connector-type="polyline" 62.246 + id="path6020" 62.247 + d="M 415.38242,365.29315 L 415.38243,381.67412" 62.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" /> 62.249 + <rect 62.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" 62.251 + id="rect6039" 62.252 + width="134.53746" 62.253 + height="44.537449" 62.254 + x="348.11359" 62.255 + y="443.71487" /> 62.256 + <text 62.257 + xml:space="preserve" 62.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" 62.259 + x="372.79706" 62.260 + y="469.47556" 62.261 + id="text6041"><tspan 62.262 + sodipodi:role="line" 62.263 + id="tspan6043" 62.264 + x="372.79706" 62.265 + y="469.47556" 62.266 + style="fill:#979797;fill-opacity:1;font-family:Courier">000000000000</tspan></text> 62.267 + <path 62.268 + inkscape:connection-end="#rect6039" 62.269 + inkscape:connector-type="polyline" 62.270 + id="path6045" 62.271 + d="M 415.38238,426.95981 L 415.38235,443.34087" 62.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" /> 62.273 + <text 62.274 + xml:space="preserve" 62.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" 62.276 + x="327.66046" 62.277 + y="231.36218" 62.278 + id="text6102"><tspan 62.279 + sodipodi:role="line" 62.280 + id="tspan6104" 62.281 + x="327.66046" 62.282 + y="231.36218">History in repository</tspan></text> 62.283 + <rect 62.284 + y="245.94225" 62.285 + x="557.28418" 62.286 + height="204.51619" 62.287 + width="174.36833" 62.288 + id="rect6140" 62.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" /> 62.290 + <g 62.291 + id="g6130" 62.292 + transform="translate(262.3254,24.38544)"> 62.293 + <rect 62.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" 62.295 + id="rect6106" 62.296 + width="134.53746" 62.297 + height="44.537449" 62.298 + x="314.87415" 62.299 + y="257.95059" /> 62.300 + <text 62.301 + xml:space="preserve" 62.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" 62.303 + x="339.55664" 62.304 + y="283.7113" 62.305 + id="text6108"><tspan 62.306 + sodipodi:role="line" 62.307 + id="tspan6110" 62.308 + x="339.55664" 62.309 + y="283.7113" 62.310 + style="font-family:Courier">dfbbb33f3fa3</tspan></text> 62.311 + </g> 62.312 + <g 62.313 + id="g6135" 62.314 + transform="translate(263.0396,49.83106)"> 62.315 + <rect 62.316 + inkscape:transform-center-y="102.85714" 62.317 + inkscape:transform-center-x="129.28571" 62.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" 62.319 + id="rect6112" 62.320 + width="134.53746" 62.321 + height="44.537449" 62.322 + x="314.15985" 62.323 + y="326.52203" /> 62.324 + <text 62.325 + inkscape:transform-center-y="102.7311" 62.326 + inkscape:transform-center-x="128.69672" 62.327 + xml:space="preserve" 62.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" 62.329 + x="338.84335" 62.330 + y="352.28271" 62.331 + id="text6114"><tspan 62.332 + sodipodi:role="line" 62.333 + id="tspan6116" 62.334 + x="338.84335" 62.335 + y="352.28271" 62.336 + style="fill:#979797;fill-opacity:1;font-family:Courier">000000000000</tspan></text> 62.337 + </g> 62.338 + <text 62.339 + xml:space="preserve" 62.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" 62.341 + x="576.63208" 62.342 + y="270.479" 62.343 + id="text6118"><tspan 62.344 + sodipodi:role="line" 62.345 + id="tspan6120" 62.346 + x="576.63208" 62.347 + y="270.479">First parent</tspan></text> 62.348 + <text 62.349 + xml:space="preserve" 62.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" 62.351 + x="576.07544" 62.352 + y="364.49615" 62.353 + id="text6122"><tspan 62.354 + sodipodi:role="line" 62.355 + id="tspan6124" 62.356 + x="576.07544" 62.357 + y="364.49615">Second parent</tspan></text> 62.358 + <text 62.359 + xml:space="preserve" 62.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" 62.361 + x="556.61743" 62.362 + y="231.36218" 62.363 + id="text6195"><tspan 62.364 + sodipodi:role="line" 62.365 + id="tspan6197" 62.366 + x="556.61743" 62.367 + y="231.36218">Parents of working directory</tspan></text> 62.368 + <path 62.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" 62.370 + d="M 576.82542,297.63008 L 483.02528,287.95831" 62.371 + id="path6266" 62.372 + inkscape:connector-type="polyline" 62.373 + inkscape:connection-start="#g6130" 62.374 + inkscape:connection-end="#g6261" /> 62.375 + <path 62.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" 62.377 + d="M 665.12232,418.17579 L 665.12232,418.17579" 62.378 + id="path6270" 62.379 + inkscape:connector-type="polyline" /> 62.380 + <text 62.381 + xml:space="preserve" 62.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" 62.383 + x="316.86407" 62.384 + y="275.6496" 62.385 + id="text6573"><tspan 62.386 + sodipodi:role="line" 62.387 + id="tspan6575" 62.388 + x="316.86407" 62.389 + y="275.6496" 62.390 + style="text-align:end;text-anchor:end">New</tspan><tspan 62.391 + sodipodi:role="line" 62.392 + x="316.86407" 62.393 + y="290.6496" 62.394 + id="tspan6577" 62.395 + style="text-align:end;text-anchor:end">changeset</tspan></text> 62.396 + </g> 62.397 +</svg>
63.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 63.2 +++ b/fr/figs/wdir-branch.svg Sun Aug 16 04:58:01 2009 +0200 63.3 @@ -0,0 +1,418 @@ 63.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?> 63.5 +<!-- Created with Inkscape (http://www.inkscape.org/) --> 63.6 +<svg 63.7 + xmlns:dc="http://purl.org/dc/elements/1.1/" 63.8 + xmlns:cc="http://web.resource.org/cc/" 63.9 + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 63.10 + xmlns:svg="http://www.w3.org/2000/svg" 63.11 + xmlns="http://www.w3.org/2000/svg" 63.12 + xmlns:xlink="http://www.w3.org/1999/xlink" 63.13 + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" 63.14 + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" 63.15 + width="744.09448819" 63.16 + height="1052.3622047" 63.17 + id="svg5971" 63.18 + sodipodi:version="0.32" 63.19 + inkscape:version="0.44.1" 63.20 + sodipodi:docbase="/home/bos/hg/hgbook/en" 63.21 + sodipodi:docname="wdir-branch.svg"> 63.22 + <defs 63.23 + id="defs5973"> 63.24 + <marker 63.25 + inkscape:stockid="Arrow1Mstart" 63.26 + orient="auto" 63.27 + refY="0.0" 63.28 + refX="0.0" 63.29 + id="Arrow1Mstart" 63.30 + style="overflow:visible"> 63.31 + <path 63.32 + id="path4855" 63.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 " 63.34 + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none" 63.35 + transform="scale(0.4) translate(10,0)" /> 63.36 + </marker> 63.37 + <linearGradient 63.38 + id="linearGradient6049"> 63.39 + <stop 63.40 + style="stop-color:#686868;stop-opacity:1;" 63.41 + offset="0" 63.42 + id="stop6051" /> 63.43 + <stop 63.44 + style="stop-color:#f0f0f0;stop-opacity:1;" 63.45 + offset="1" 63.46 + id="stop6053" /> 63.47 + </linearGradient> 63.48 + <marker 63.49 + inkscape:stockid="Arrow1Mend" 63.50 + orient="auto" 63.51 + refY="0.0" 63.52 + refX="0.0" 63.53 + id="Arrow1Mend" 63.54 + style="overflow:visible;"> 63.55 + <path 63.56 + id="path4852" 63.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 " 63.58 + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;" 63.59 + transform="scale(0.4) rotate(180) translate(10,0)" /> 63.60 + </marker> 63.61 + <linearGradient 63.62 + inkscape:collect="always" 63.63 + xlink:href="#linearGradient6049" 63.64 + id="linearGradient6083" 63.65 + gradientUnits="userSpaceOnUse" 63.66 + gradientTransform="translate(-240.0462,-8.633237e-6)" 63.67 + x1="333.91171" 63.68 + y1="488.79077" 63.69 + x2="508.94543" 63.70 + y2="263.79077" /> 63.71 + <linearGradient 63.72 + inkscape:collect="always" 63.73 + xlink:href="#linearGradient6049" 63.74 + id="linearGradient6142" 63.75 + gradientUnits="userSpaceOnUse" 63.76 + gradientTransform="translate(-42.00893,-30.49544)" 63.77 + x1="333.91171" 63.78 + y1="488.79077" 63.79 + x2="508.94543" 63.80 + y2="263.79077" /> 63.81 + <linearGradient 63.82 + inkscape:collect="always" 63.83 + xlink:href="#linearGradient6049" 63.84 + id="linearGradient6193" 63.85 + gradientUnits="userSpaceOnUse" 63.86 + gradientTransform="translate(-240.0462,-8.633237e-6)" 63.87 + x1="333.91171" 63.88 + y1="488.79077" 63.89 + x2="508.94543" 63.90 + y2="263.79077" /> 63.91 + <linearGradient 63.92 + inkscape:collect="always" 63.93 + xlink:href="#linearGradient6049" 63.94 + id="linearGradient6216" 63.95 + gradientUnits="userSpaceOnUse" 63.96 + gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)" 63.97 + x1="333.91171" 63.98 + y1="488.79077" 63.99 + x2="508.94543" 63.100 + y2="263.79077" /> 63.101 + <linearGradient 63.102 + inkscape:collect="always" 63.103 + xlink:href="#linearGradient6049" 63.104 + id="linearGradient6232" 63.105 + gradientUnits="userSpaceOnUse" 63.106 + gradientTransform="matrix(1.000473,0,0,0.790947,-11.16012,50.85693)" 63.107 + x1="333.91171" 63.108 + y1="488.79077" 63.109 + x2="508.94543" 63.110 + y2="263.79077" /> 63.111 + <linearGradient 63.112 + inkscape:collect="always" 63.113 + xlink:href="#linearGradient6049" 63.114 + id="linearGradient6445" 63.115 + gradientUnits="userSpaceOnUse" 63.116 + gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)" 63.117 + x1="333.91171" 63.118 + y1="488.79077" 63.119 + x2="508.94543" 63.120 + y2="263.79077" /> 63.121 + <linearGradient 63.122 + inkscape:collect="always" 63.123 + xlink:href="#linearGradient6049" 63.124 + id="linearGradient6974" 63.125 + gradientUnits="userSpaceOnUse" 63.126 + gradientTransform="matrix(1.911882,0,0,0.789965,-574.7896,51.22599)" 63.127 + x1="333.91171" 63.128 + y1="488.79077" 63.129 + x2="508.94543" 63.130 + y2="263.79077" /> 63.131 + <linearGradient 63.132 + inkscape:collect="always" 63.133 + xlink:href="#linearGradient6049" 63.134 + id="linearGradient6996" 63.135 + gradientUnits="userSpaceOnUse" 63.136 + gradientTransform="matrix(1.000473,0,0,0.790947,112.8399,50.85693)" 63.137 + x1="333.91171" 63.138 + y1="488.79077" 63.139 + x2="508.94543" 63.140 + y2="263.79077" /> 63.141 + </defs> 63.142 + <sodipodi:namedview 63.143 + id="base" 63.144 + pagecolor="#ffffff" 63.145 + bordercolor="#666666" 63.146 + borderopacity="1.0" 63.147 + gridtolerance="10000" 63.148 + guidetolerance="10" 63.149 + objecttolerance="10" 63.150 + inkscape:pageopacity="0.0" 63.151 + inkscape:pageshadow="2" 63.152 + inkscape:zoom="0.90509668" 63.153 + inkscape:cx="345.85973" 63.154 + inkscape:cy="690.49342" 63.155 + inkscape:document-units="px" 63.156 + inkscape:current-layer="layer1" 63.157 + showguides="true" 63.158 + inkscape:guide-bbox="true" 63.159 + inkscape:window-width="906" 63.160 + inkscape:window-height="620" 63.161 + inkscape:window-x="0" 63.162 + inkscape:window-y="25"> 63.163 + <sodipodi:guide 63.164 + orientation="vertical" 63.165 + position="-1.4285714" 63.166 + id="guide6022" /> 63.167 + </sodipodi:namedview> 63.168 + <metadata 63.169 + id="metadata5976"> 63.170 + <rdf:RDF> 63.171 + <cc:Work 63.172 + rdf:about=""> 63.173 + <dc:format>image/svg+xml</dc:format> 63.174 + <dc:type 63.175 + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 63.176 + </cc:Work> 63.177 + </rdf:RDF> 63.178 + </metadata> 63.179 + <g 63.180 + inkscape:label="Layer 1" 63.181 + inkscape:groupmode="layer" 63.182 + id="layer1"> 63.183 + <rect 63.184 + y="246.06918" 63.185 + x="64.325172" 63.186 + height="204.26233" 63.187 + width="333.2135" 63.188 + id="rect6047" 63.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" /> 63.190 + <g 63.191 + id="g1935"> 63.192 + <rect 63.193 + y="266.24374" 63.194 + x="84.113708" 63.195 + height="44.537449" 63.196 + width="134.53746" 63.197 + id="rect5996" 63.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" /> 63.199 + <text 63.200 + id="text5998" 63.201 + y="292.00446" 63.202 + x="108.7962" 63.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" 63.204 + xml:space="preserve"><tspan 63.205 + style="font-family:Courier" 63.206 + y="292.00446" 63.207 + x="108.7962" 63.208 + id="tspan6000" 63.209 + sodipodi:role="line">e7639888bb2f</tspan></text> 63.210 + </g> 63.211 + <g 63.212 + id="g6976" 63.213 + transform="translate(70,0)"> 63.214 + <rect 63.215 + y="327.9104" 63.216 + x="40.113693" 63.217 + height="44.537449" 63.218 + width="134.53746" 63.219 + id="rect6004" 63.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" /> 63.221 + <text 63.222 + id="text6006" 63.223 + y="353.67111" 63.224 + x="62.654205" 63.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" 63.226 + xml:space="preserve"><tspan 63.227 + style="font-family:Courier" 63.228 + y="353.67111" 63.229 + x="62.654205" 63.230 + id="tspan6008" 63.231 + sodipodi:role="line">7b064d8bac5e</tspan></text> 63.232 + </g> 63.233 + <path 63.234 + inkscape:connector-type="polyline" 63.235 + id="path6020" 63.236 + d="M 160.92915,311.15532 L 167.83571,327.53627" 63.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" 63.238 + inkscape:connection-end="#g6976" 63.239 + inkscape:connection-start="#g1935" /> 63.240 + <rect 63.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" 63.242 + id="rect6039" 63.243 + width="134.53746" 63.244 + height="44.537449" 63.245 + x="110.11359" 63.246 + y="389.57703" /> 63.247 + <text 63.248 + xml:space="preserve" 63.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" 63.250 + x="134.79706" 63.251 + y="415.33771" 63.252 + id="text6041"><tspan 63.253 + sodipodi:role="line" 63.254 + id="tspan6043" 63.255 + x="134.79706" 63.256 + y="415.33771" 63.257 + style="fill:#979797;fill-opacity:1;font-family:Courier">000000000000</tspan></text> 63.258 + <path 63.259 + inkscape:connection-end="#rect6039" 63.260 + inkscape:connector-type="polyline" 63.261 + id="path6045" 63.262 + d="M 177.38238,372.82195 L 177.38235,389.20303" 63.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" /> 63.264 + <rect 63.265 + y="245.94225" 63.266 + x="447.28412" 63.267 + height="204.51619" 63.268 + width="174.36833" 63.269 + id="rect6140" 63.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" /> 63.271 + <g 63.272 + id="g6130" 63.273 + transform="translate(152.3254,24.38544)"> 63.274 + <rect 63.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" 63.276 + id="rect6106" 63.277 + width="134.53746" 63.278 + height="44.537449" 63.279 + x="314.87415" 63.280 + y="257.95059" /> 63.281 + <text 63.282 + xml:space="preserve" 63.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" 63.284 + x="339.55664" 63.285 + y="283.7113" 63.286 + id="text6108"><tspan 63.287 + sodipodi:role="line" 63.288 + id="tspan6110" 63.289 + x="339.55664" 63.290 + y="283.7113" 63.291 + style="font-family:Courier">ffb20e1701ea</tspan></text> 63.292 + </g> 63.293 + <g 63.294 + id="g6135" 63.295 + transform="translate(153.0396,49.83106)"> 63.296 + <rect 63.297 + inkscape:transform-center-y="102.85714" 63.298 + inkscape:transform-center-x="129.28571" 63.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" 63.300 + id="rect6112" 63.301 + width="134.53746" 63.302 + height="44.537449" 63.303 + x="314.15985" 63.304 + y="326.52203" /> 63.305 + <text 63.306 + inkscape:transform-center-y="102.7311" 63.307 + inkscape:transform-center-x="128.69672" 63.308 + xml:space="preserve" 63.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" 63.310 + x="338.84335" 63.311 + y="352.28271" 63.312 + id="text6114"><tspan 63.313 + sodipodi:role="line" 63.314 + id="tspan6116" 63.315 + x="338.84335" 63.316 + y="352.28271" 63.317 + style="fill:#979797;fill-opacity:1;font-family:Courier">000000000000</tspan></text> 63.318 + </g> 63.319 + <text 63.320 + xml:space="preserve" 63.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" 63.322 + x="466.63208" 63.323 + y="270.479" 63.324 + id="text6118"><tspan 63.325 + sodipodi:role="line" 63.326 + id="tspan6120" 63.327 + x="466.63208" 63.328 + y="270.479">First parent</tspan></text> 63.329 + <text 63.330 + xml:space="preserve" 63.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" 63.332 + x="466.07544" 63.333 + y="364.49615" 63.334 + id="text6122"><tspan 63.335 + sodipodi:role="line" 63.336 + id="tspan6124" 63.337 + x="466.07544" 63.338 + y="364.49615">Second parent</tspan></text> 63.339 + <text 63.340 + xml:space="preserve" 63.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" 63.342 + x="446.61743" 63.343 + y="231.36218" 63.344 + id="text6195"><tspan 63.345 + sodipodi:role="line" 63.346 + id="tspan6197" 63.347 + x="446.61743" 63.348 + y="231.36218">Parents of working directory</tspan></text> 63.349 + <path 63.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" 63.351 + d="M 466.82542,300.21999 L 377.00207,294.39744" 63.352 + id="path6266" 63.353 + inkscape:connector-type="polyline" 63.354 + inkscape:connection-start="#g6130" 63.355 + inkscape:connection-end="#rect1925" /> 63.356 + <path 63.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" 63.358 + d="M 665.12232,418.17579 L 665.12232,418.17579" 63.359 + id="path6270" 63.360 + inkscape:connector-type="polyline" /> 63.361 + <g 63.362 + id="g2845"> 63.363 + <rect 63.364 + y="266.24374" 63.365 + x="242.09048" 63.366 + height="44.537449" 63.367 + width="134.53746" 63.368 + id="rect1925" 63.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" /> 63.370 + <text 63.371 + id="text1927" 63.372 + y="292.00446" 63.373 + x="266.77298" 63.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" 63.375 + xml:space="preserve"><tspan 63.376 + style="font-family:Courier" 63.377 + y="292.00446" 63.378 + x="266.77298" 63.379 + id="tspan1929" 63.380 + sodipodi:role="line">ffb20e1701ea</tspan></text> 63.381 + </g> 63.382 + <path 63.383 + inkscape:connector-type="polyline" 63.384 + id="path1933" 63.385 + d="M 260.89978,311.15532 L 225.84185,327.53627" 63.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" 63.387 + inkscape:connection-end="#g6976" /> 63.388 + <text 63.389 + xml:space="preserve" 63.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" 63.391 + x="109.45568" 63.392 + y="231.4554" 63.393 + id="text2837"><tspan 63.394 + sodipodi:role="line" 63.395 + id="tspan2839" 63.396 + x="109.45568" 63.397 + y="231.4554">Pre-existing head</tspan></text> 63.398 + <text 63.399 + xml:space="preserve" 63.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" 63.401 + x="237.54184" 63.402 + y="231.4554" 63.403 + id="text2841"><tspan 63.404 + sodipodi:role="line" 63.405 + id="tspan2843" 63.406 + x="237.54184" 63.407 + y="231.4554">Newly created head (and tip)</tspan></text> 63.408 + <path 63.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)" 63.410 + d="M 148.05048,235.87482 L 149.94915,265.86962" 63.411 + id="path2850" 63.412 + inkscape:connector-type="polyline" 63.413 + inkscape:connection-end="#g1935" /> 63.414 + <path 63.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)" 63.416 + d="M 303.83495,238.08453 L 306.87874,265.86962" 63.417 + id="path2852" 63.418 + inkscape:connector-type="polyline" 63.419 + inkscape:connection-end="#g2845" /> 63.420 + </g> 63.421 +</svg>
64.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 64.2 +++ b/fr/figs/wdir-merge.svg Sun Aug 16 04:58:01 2009 +0200 64.3 @@ -0,0 +1,425 @@ 64.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?> 64.5 +<!-- Created with Inkscape (http://www.inkscape.org/) --> 64.6 +<svg 64.7 + xmlns:dc="http://purl.org/dc/elements/1.1/" 64.8 + xmlns:cc="http://web.resource.org/cc/" 64.9 + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 64.10 + xmlns:svg="http://www.w3.org/2000/svg" 64.11 + xmlns="http://www.w3.org/2000/svg" 64.12 + xmlns:xlink="http://www.w3.org/1999/xlink" 64.13 + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" 64.14 + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" 64.15 + width="744.09448819" 64.16 + height="1052.3622047" 64.17 + id="svg5971" 64.18 + sodipodi:version="0.32" 64.19 + inkscape:version="0.44.1" 64.20 + sodipodi:docbase="/home/bos/hg/hgbook/en" 64.21 + sodipodi:docname="wdir-merge.svg"> 64.22 + <defs 64.23 + id="defs5973"> 64.24 + <marker 64.25 + inkscape:stockid="Arrow1Mstart" 64.26 + orient="auto" 64.27 + refY="0.0" 64.28 + refX="0.0" 64.29 + id="Arrow1Mstart" 64.30 + style="overflow:visible"> 64.31 + <path 64.32 + id="path4855" 64.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 " 64.34 + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none" 64.35 + transform="scale(0.4) translate(10,0)" /> 64.36 + </marker> 64.37 + <linearGradient 64.38 + id="linearGradient6049"> 64.39 + <stop 64.40 + style="stop-color:#686868;stop-opacity:1;" 64.41 + offset="0" 64.42 + id="stop6051" /> 64.43 + <stop 64.44 + style="stop-color:#f0f0f0;stop-opacity:1;" 64.45 + offset="1" 64.46 + id="stop6053" /> 64.47 + </linearGradient> 64.48 + <marker 64.49 + inkscape:stockid="Arrow1Mend" 64.50 + orient="auto" 64.51 + refY="0.0" 64.52 + refX="0.0" 64.53 + id="Arrow1Mend" 64.54 + style="overflow:visible;"> 64.55 + <path 64.56 + id="path4852" 64.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 " 64.58 + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;" 64.59 + transform="scale(0.4) rotate(180) translate(10,0)" /> 64.60 + </marker> 64.61 + <linearGradient 64.62 + inkscape:collect="always" 64.63 + xlink:href="#linearGradient6049" 64.64 + id="linearGradient6083" 64.65 + gradientUnits="userSpaceOnUse" 64.66 + gradientTransform="translate(-240.0462,-8.633237e-6)" 64.67 + x1="333.91171" 64.68 + y1="488.79077" 64.69 + x2="508.94543" 64.70 + y2="263.79077" /> 64.71 + <linearGradient 64.72 + inkscape:collect="always" 64.73 + xlink:href="#linearGradient6049" 64.74 + id="linearGradient6142" 64.75 + gradientUnits="userSpaceOnUse" 64.76 + gradientTransform="translate(-42.00893,-30.49544)" 64.77 + x1="333.91171" 64.78 + y1="488.79077" 64.79 + x2="508.94543" 64.80 + y2="263.79077" /> 64.81 + <linearGradient 64.82 + inkscape:collect="always" 64.83 + xlink:href="#linearGradient6049" 64.84 + id="linearGradient6193" 64.85 + gradientUnits="userSpaceOnUse" 64.86 + gradientTransform="translate(-240.0462,-8.633237e-6)" 64.87 + x1="333.91171" 64.88 + y1="488.79077" 64.89 + x2="508.94543" 64.90 + y2="263.79077" /> 64.91 + <linearGradient 64.92 + inkscape:collect="always" 64.93 + xlink:href="#linearGradient6049" 64.94 + id="linearGradient6216" 64.95 + gradientUnits="userSpaceOnUse" 64.96 + gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)" 64.97 + x1="333.91171" 64.98 + y1="488.79077" 64.99 + x2="508.94543" 64.100 + y2="263.79077" /> 64.101 + <linearGradient 64.102 + inkscape:collect="always" 64.103 + xlink:href="#linearGradient6049" 64.104 + id="linearGradient6232" 64.105 + gradientUnits="userSpaceOnUse" 64.106 + gradientTransform="matrix(1.000473,0,0,0.790947,-11.16012,50.85693)" 64.107 + x1="333.91171" 64.108 + y1="488.79077" 64.109 + x2="508.94543" 64.110 + y2="263.79077" /> 64.111 + <linearGradient 64.112 + inkscape:collect="always" 64.113 + xlink:href="#linearGradient6049" 64.114 + id="linearGradient6445" 64.115 + gradientUnits="userSpaceOnUse" 64.116 + gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)" 64.117 + x1="333.91171" 64.118 + y1="488.79077" 64.119 + x2="508.94543" 64.120 + y2="263.79077" /> 64.121 + <linearGradient 64.122 + inkscape:collect="always" 64.123 + xlink:href="#linearGradient6049" 64.124 + id="linearGradient6974" 64.125 + gradientUnits="userSpaceOnUse" 64.126 + gradientTransform="matrix(1.911882,0,0,0.789965,-574.7896,51.22599)" 64.127 + x1="333.91171" 64.128 + y1="488.79077" 64.129 + x2="508.94543" 64.130 + y2="263.79077" /> 64.131 + <linearGradient 64.132 + inkscape:collect="always" 64.133 + xlink:href="#linearGradient6049" 64.134 + id="linearGradient6996" 64.135 + gradientUnits="userSpaceOnUse" 64.136 + gradientTransform="matrix(1.000473,0,0,0.790947,112.8399,50.85693)" 64.137 + x1="333.91171" 64.138 + y1="488.79077" 64.139 + x2="508.94543" 64.140 + y2="263.79077" /> 64.141 + </defs> 64.142 + <sodipodi:namedview 64.143 + id="base" 64.144 + pagecolor="#ffffff" 64.145 + bordercolor="#666666" 64.146 + borderopacity="1.0" 64.147 + gridtolerance="10000" 64.148 + guidetolerance="10" 64.149 + objecttolerance="10" 64.150 + inkscape:pageopacity="0.0" 64.151 + inkscape:pageshadow="2" 64.152 + inkscape:zoom="1.28" 64.153 + inkscape:cx="345.85973" 64.154 + inkscape:cy="690.49342" 64.155 + inkscape:document-units="px" 64.156 + inkscape:current-layer="layer1" 64.157 + showguides="true" 64.158 + inkscape:guide-bbox="true" 64.159 + inkscape:window-width="906" 64.160 + inkscape:window-height="620" 64.161 + inkscape:window-x="0" 64.162 + inkscape:window-y="25"> 64.163 + <sodipodi:guide 64.164 + orientation="vertical" 64.165 + position="-1.4285714" 64.166 + id="guide6022" /> 64.167 + </sodipodi:namedview> 64.168 + <metadata 64.169 + id="metadata5976"> 64.170 + <rdf:RDF> 64.171 + <cc:Work 64.172 + rdf:about=""> 64.173 + <dc:format>image/svg+xml</dc:format> 64.174 + <dc:type 64.175 + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 64.176 + </cc:Work> 64.177 + </rdf:RDF> 64.178 + </metadata> 64.179 + <g 64.180 + inkscape:label="Layer 1" 64.181 + inkscape:groupmode="layer" 64.182 + id="layer1"> 64.183 + <rect 64.184 + y="246.06918" 64.185 + x="64.325172" 64.186 + height="204.26233" 64.187 + width="333.2135" 64.188 + id="rect6047" 64.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" /> 64.190 + <g 64.191 + id="g6976" 64.192 + transform="translate(70,0)"> 64.193 + <rect 64.194 + y="327.9104" 64.195 + x="40.113693" 64.196 + height="44.537449" 64.197 + width="134.53746" 64.198 + id="rect6004" 64.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" /> 64.200 + <text 64.201 + id="text6006" 64.202 + y="353.67111" 64.203 + x="62.654205" 64.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" 64.205 + xml:space="preserve"><tspan 64.206 + style="font-family:Courier" 64.207 + y="353.67111" 64.208 + x="62.654205" 64.209 + id="tspan6008" 64.210 + sodipodi:role="line">7b064d8bac5e</tspan></text> 64.211 + </g> 64.212 + <path 64.213 + inkscape:connector-type="polyline" 64.214 + id="path6020" 64.215 + d="M 160.92915,311.15532 L 167.83571,327.53627" 64.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" 64.217 + inkscape:connection-end="#g6976" 64.218 + inkscape:connection-start="#g1935" /> 64.219 + <rect 64.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" 64.221 + id="rect6039" 64.222 + width="134.53746" 64.223 + height="44.537449" 64.224 + x="110.11359" 64.225 + y="389.57703" /> 64.226 + <text 64.227 + xml:space="preserve" 64.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" 64.229 + x="134.79706" 64.230 + y="415.33771" 64.231 + id="text6041"><tspan 64.232 + sodipodi:role="line" 64.233 + id="tspan6043" 64.234 + x="134.79706" 64.235 + y="415.33771" 64.236 + style="fill:#979797;fill-opacity:1;font-family:Courier">000000000000</tspan></text> 64.237 + <path 64.238 + inkscape:connection-end="#rect6039" 64.239 + inkscape:connector-type="polyline" 64.240 + id="path6045" 64.241 + d="M 177.38238,372.82195 L 177.38235,389.20303" 64.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" /> 64.243 + <rect 64.244 + y="245.94225" 64.245 + x="447.28412" 64.246 + height="204.51619" 64.247 + width="174.36833" 64.248 + id="rect6140" 64.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" /> 64.250 + <g 64.251 + id="g6130" 64.252 + transform="translate(152.3254,24.38544)"> 64.253 + <rect 64.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" 64.255 + id="rect6106" 64.256 + width="134.53746" 64.257 + height="44.537449" 64.258 + x="314.87415" 64.259 + y="257.95059" /> 64.260 + <text 64.261 + xml:space="preserve" 64.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" 64.263 + x="339.55664" 64.264 + y="283.7113" 64.265 + id="text6108"><tspan 64.266 + sodipodi:role="line" 64.267 + id="tspan6110" 64.268 + x="339.55664" 64.269 + y="283.7113" 64.270 + style="font-family:Courier">ffb20e1701ea</tspan></text> 64.271 + </g> 64.272 + <g 64.273 + id="g6135" 64.274 + transform="translate(153.0396,49.83106)"> 64.275 + <rect 64.276 + inkscape:transform-center-y="102.85714" 64.277 + inkscape:transform-center-x="129.28571" 64.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" 64.279 + id="rect6112" 64.280 + width="134.53746" 64.281 + height="44.537449" 64.282 + x="314.15985" 64.283 + y="326.52203" /> 64.284 + <text 64.285 + inkscape:transform-center-y="102.7311" 64.286 + inkscape:transform-center-x="128.69672" 64.287 + xml:space="preserve" 64.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" 64.289 + x="338.84335" 64.290 + y="352.28271" 64.291 + id="text6114"><tspan 64.292 + sodipodi:role="line" 64.293 + id="tspan6116" 64.294 + x="338.84335" 64.295 + y="352.28271" 64.296 + style="fill:black;fill-opacity:1;font-family:Courier">e7639888bb2f</tspan></text> 64.297 + </g> 64.298 + <text 64.299 + xml:space="preserve" 64.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" 64.301 + x="466.63208" 64.302 + y="270.479" 64.303 + id="text6118"><tspan 64.304 + sodipodi:role="line" 64.305 + id="tspan6120" 64.306 + x="466.63208" 64.307 + y="270.479">First parent (unchanged)</tspan></text> 64.308 + <text 64.309 + xml:space="preserve" 64.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" 64.311 + x="466.07544" 64.312 + y="364.49615" 64.313 + id="text6122"><tspan 64.314 + sodipodi:role="line" 64.315 + id="tspan6124" 64.316 + x="466.07544" 64.317 + y="364.49615">Second parent</tspan></text> 64.318 + <text 64.319 + xml:space="preserve" 64.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" 64.321 + x="446.61743" 64.322 + y="231.36218" 64.323 + id="text6195"><tspan 64.324 + sodipodi:role="line" 64.325 + id="tspan6197" 64.326 + x="446.61743" 64.327 + y="231.36218">Parents of working directory</tspan></text> 64.328 + <path 64.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" 64.330 + d="M 466.82542,300.21999 L 377.00207,294.39744" 64.331 + id="path6266" 64.332 + inkscape:connector-type="polyline" 64.333 + inkscape:connection-start="#g6130" 64.334 + inkscape:connection-end="#rect1925" /> 64.335 + <path 64.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" 64.337 + d="M 665.12232,418.17579 L 665.12232,418.17579" 64.338 + id="path6270" 64.339 + inkscape:connector-type="polyline" /> 64.340 + <g 64.341 + id="g2845"> 64.342 + <rect 64.343 + y="266.24374" 64.344 + x="242.09048" 64.345 + height="44.537449" 64.346 + width="134.53746" 64.347 + id="rect1925" 64.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" /> 64.349 + <text 64.350 + id="text1927" 64.351 + y="292.00446" 64.352 + x="266.77298" 64.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" 64.354 + xml:space="preserve"><tspan 64.355 + style="font-family:Courier" 64.356 + y="292.00446" 64.357 + x="266.77298" 64.358 + id="tspan1929" 64.359 + sodipodi:role="line">ffb20e1701ea</tspan></text> 64.360 + </g> 64.361 + <path 64.362 + inkscape:connector-type="polyline" 64.363 + id="path1933" 64.364 + d="M 260.89978,311.15532 L 225.84185,327.53627" 64.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" 64.366 + inkscape:connection-end="#g6976" /> 64.367 + <text 64.368 + xml:space="preserve" 64.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" 64.370 + x="109.45568" 64.371 + y="231.4554" 64.372 + id="text2837"><tspan 64.373 + sodipodi:role="line" 64.374 + id="tspan2839" 64.375 + x="109.45568" 64.376 + y="231.4554">Pre-existing head</tspan></text> 64.377 + <text 64.378 + xml:space="preserve" 64.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" 64.380 + x="237.54184" 64.381 + y="231.4554" 64.382 + id="text2841"><tspan 64.383 + sodipodi:role="line" 64.384 + id="tspan2843" 64.385 + x="237.54184" 64.386 + y="231.4554">Newly created head (and tip)</tspan></text> 64.387 + <path 64.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)" 64.389 + d="M 148.05048,235.87482 L 149.94915,265.86962" 64.390 + id="path2850" 64.391 + inkscape:connector-type="polyline" 64.392 + inkscape:connection-end="#g1935" /> 64.393 + <path 64.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)" 64.395 + d="M 303.83495,238.08453 L 306.87874,265.86962" 64.396 + id="path2852" 64.397 + inkscape:connector-type="polyline" 64.398 + inkscape:connection-end="#g2845" /> 64.399 + <path 64.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" 64.401 + d="M 466.82545,379.17944 L 219.0253,307.95488" 64.402 + id="path3016" 64.403 + inkscape:connector-type="polyline" 64.404 + inkscape:connection-start="#g6135" 64.405 + inkscape:connection-end="#g1935" /> 64.406 + <g 64.407 + id="g1935"> 64.408 + <rect 64.409 + y="266.24374" 64.410 + x="84.113708" 64.411 + height="44.537449" 64.412 + width="134.53746" 64.413 + id="rect5996" 64.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" /> 64.415 + <text 64.416 + id="text5998" 64.417 + y="292.00446" 64.418 + x="108.7962" 64.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" 64.420 + xml:space="preserve"><tspan 64.421 + style="font-family:Courier" 64.422 + y="292.00446" 64.423 + x="108.7962" 64.424 + id="tspan6000" 64.425 + sodipodi:role="line">e7639888bb2f</tspan></text> 64.426 + </g> 64.427 + </g> 64.428 +</svg>
65.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 65.2 +++ b/fr/figs/wdir-pre-branch.svg Sun Aug 16 04:58:01 2009 +0200 65.3 @@ -0,0 +1,364 @@ 65.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?> 65.5 +<!-- Created with Inkscape (http://www.inkscape.org/) --> 65.6 +<svg 65.7 + xmlns:dc="http://purl.org/dc/elements/1.1/" 65.8 + xmlns:cc="http://web.resource.org/cc/" 65.9 + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 65.10 + xmlns:svg="http://www.w3.org/2000/svg" 65.11 + xmlns="http://www.w3.org/2000/svg" 65.12 + xmlns:xlink="http://www.w3.org/1999/xlink" 65.13 + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" 65.14 + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" 65.15 + width="744.09448819" 65.16 + height="1052.3622047" 65.17 + id="svg5971" 65.18 + sodipodi:version="0.32" 65.19 + inkscape:version="0.44.1" 65.20 + sodipodi:docbase="/home/bos/hg/hgbook/en" 65.21 + sodipodi:docname="wdir-branch.svg"> 65.22 + <defs 65.23 + id="defs5973"> 65.24 + <marker 65.25 + inkscape:stockid="Arrow1Mstart" 65.26 + orient="auto" 65.27 + refY="0.0" 65.28 + refX="0.0" 65.29 + id="Arrow1Mstart" 65.30 + style="overflow:visible"> 65.31 + <path 65.32 + id="path4855" 65.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 " 65.34 + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none" 65.35 + transform="scale(0.4) translate(10,0)" /> 65.36 + </marker> 65.37 + <linearGradient 65.38 + id="linearGradient6049"> 65.39 + <stop 65.40 + style="stop-color:#686868;stop-opacity:1;" 65.41 + offset="0" 65.42 + id="stop6051" /> 65.43 + <stop 65.44 + style="stop-color:#f0f0f0;stop-opacity:1;" 65.45 + offset="1" 65.46 + id="stop6053" /> 65.47 + </linearGradient> 65.48 + <marker 65.49 + inkscape:stockid="Arrow1Mend" 65.50 + orient="auto" 65.51 + refY="0.0" 65.52 + refX="0.0" 65.53 + id="Arrow1Mend" 65.54 + style="overflow:visible;"> 65.55 + <path 65.56 + id="path4852" 65.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 " 65.58 + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;" 65.59 + transform="scale(0.4) rotate(180) translate(10,0)" /> 65.60 + </marker> 65.61 + <linearGradient 65.62 + inkscape:collect="always" 65.63 + xlink:href="#linearGradient6049" 65.64 + id="linearGradient6083" 65.65 + gradientUnits="userSpaceOnUse" 65.66 + gradientTransform="translate(-240.0462,-8.633237e-6)" 65.67 + x1="333.91171" 65.68 + y1="488.79077" 65.69 + x2="508.94543" 65.70 + y2="263.79077" /> 65.71 + <linearGradient 65.72 + inkscape:collect="always" 65.73 + xlink:href="#linearGradient6049" 65.74 + id="linearGradient6142" 65.75 + gradientUnits="userSpaceOnUse" 65.76 + gradientTransform="translate(-42.00893,-30.49544)" 65.77 + x1="333.91171" 65.78 + y1="488.79077" 65.79 + x2="508.94543" 65.80 + y2="263.79077" /> 65.81 + <linearGradient 65.82 + inkscape:collect="always" 65.83 + xlink:href="#linearGradient6049" 65.84 + id="linearGradient6193" 65.85 + gradientUnits="userSpaceOnUse" 65.86 + gradientTransform="translate(-240.0462,-8.633237e-6)" 65.87 + x1="333.91171" 65.88 + y1="488.79077" 65.89 + x2="508.94543" 65.90 + y2="263.79077" /> 65.91 + <linearGradient 65.92 + inkscape:collect="always" 65.93 + xlink:href="#linearGradient6049" 65.94 + id="linearGradient6216" 65.95 + gradientUnits="userSpaceOnUse" 65.96 + gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)" 65.97 + x1="333.91171" 65.98 + y1="488.79077" 65.99 + x2="508.94543" 65.100 + y2="263.79077" /> 65.101 + <linearGradient 65.102 + inkscape:collect="always" 65.103 + xlink:href="#linearGradient6049" 65.104 + id="linearGradient6232" 65.105 + gradientUnits="userSpaceOnUse" 65.106 + gradientTransform="matrix(1.000473,0,0,0.790947,-11.16012,50.85693)" 65.107 + x1="333.91171" 65.108 + y1="488.79077" 65.109 + x2="508.94543" 65.110 + y2="263.79077" /> 65.111 + <linearGradient 65.112 + inkscape:collect="always" 65.113 + xlink:href="#linearGradient6049" 65.114 + id="linearGradient6445" 65.115 + gradientUnits="userSpaceOnUse" 65.116 + gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)" 65.117 + x1="333.91171" 65.118 + y1="488.79077" 65.119 + x2="508.94543" 65.120 + y2="263.79077" /> 65.121 + <linearGradient 65.122 + inkscape:collect="always" 65.123 + xlink:href="#linearGradient6049" 65.124 + id="linearGradient6974" 65.125 + gradientUnits="userSpaceOnUse" 65.126 + gradientTransform="matrix(1.000474,0,0,0.790947,-314.246,50.85694)" 65.127 + x1="333.91171" 65.128 + y1="488.79077" 65.129 + x2="508.94543" 65.130 + y2="263.79077" /> 65.131 + <linearGradient 65.132 + inkscape:collect="always" 65.133 + xlink:href="#linearGradient6049" 65.134 + id="linearGradient6996" 65.135 + gradientUnits="userSpaceOnUse" 65.136 + gradientTransform="matrix(1.000473,0,0,0.790947,-85.16012,50.85693)" 65.137 + x1="333.91171" 65.138 + y1="488.79077" 65.139 + x2="508.94543" 65.140 + y2="263.79077" /> 65.141 + </defs> 65.142 + <sodipodi:namedview 65.143 + id="base" 65.144 + pagecolor="#ffffff" 65.145 + bordercolor="#666666" 65.146 + borderopacity="1.0" 65.147 + gridtolerance="10000" 65.148 + guidetolerance="10" 65.149 + objecttolerance="10" 65.150 + inkscape:pageopacity="0.0" 65.151 + inkscape:pageshadow="2" 65.152 + inkscape:zoom="0.90509668" 65.153 + inkscape:cx="390.0539" 65.154 + inkscape:cy="690.49342" 65.155 + inkscape:document-units="px" 65.156 + inkscape:current-layer="layer1" 65.157 + showguides="true" 65.158 + inkscape:guide-bbox="true" 65.159 + inkscape:window-width="906" 65.160 + inkscape:window-height="620" 65.161 + inkscape:window-x="0" 65.162 + inkscape:window-y="25"> 65.163 + <sodipodi:guide 65.164 + orientation="vertical" 65.165 + position="-1.4285714" 65.166 + id="guide6022" /> 65.167 + </sodipodi:namedview> 65.168 + <metadata 65.169 + id="metadata5976"> 65.170 + <rdf:RDF> 65.171 + <cc:Work 65.172 + rdf:about=""> 65.173 + <dc:format>image/svg+xml</dc:format> 65.174 + <dc:type 65.175 + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 65.176 + </cc:Work> 65.177 + </rdf:RDF> 65.178 + </metadata> 65.179 + <g 65.180 + inkscape:label="Layer 1" 65.181 + inkscape:groupmode="layer" 65.182 + id="layer1"> 65.183 + <rect 65.184 + y="245.94225" 65.185 + x="20.198257" 65.186 + height="204.51619" 65.187 + width="174.36833" 65.188 + id="rect6047" 65.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" /> 65.190 + <rect 65.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" 65.192 + id="rect5996" 65.193 + width="134.53746" 65.194 + height="44.537449" 65.195 + x="40.113693" 65.196 + y="266.24374" /> 65.197 + <text 65.198 + xml:space="preserve" 65.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" 65.200 + x="64.796204" 65.201 + y="292.00446" 65.202 + id="text5998"><tspan 65.203 + sodipodi:role="line" 65.204 + id="tspan6000" 65.205 + x="64.796204" 65.206 + y="292.00446" 65.207 + style="font-family:Courier">e7639888bb2f</tspan></text> 65.208 + <g 65.209 + id="g6976"> 65.210 + <rect 65.211 + y="327.9104" 65.212 + x="40.113693" 65.213 + height="44.537449" 65.214 + width="134.53746" 65.215 + id="rect6004" 65.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" /> 65.217 + <text 65.218 + id="text6006" 65.219 + y="353.67111" 65.220 + x="62.654205" 65.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" 65.222 + xml:space="preserve"><tspan 65.223 + style="font-family:Courier" 65.224 + y="353.67111" 65.225 + x="62.654205" 65.226 + id="tspan6008" 65.227 + sodipodi:role="line">7b064d8bac5e</tspan></text> 65.228 + </g> 65.229 + <path 65.230 + inkscape:connection-end="#rect6004" 65.231 + inkscape:connector-type="polyline" 65.232 + id="path6020" 65.233 + d="M 107.38242,311.15529 L 107.38242,327.53626" 65.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" /> 65.235 + <rect 65.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" 65.237 + id="rect6039" 65.238 + width="134.53746" 65.239 + height="44.537449" 65.240 + x="40.113571" 65.241 + y="389.57703" /> 65.242 + <text 65.243 + xml:space="preserve" 65.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" 65.245 + x="64.797073" 65.246 + y="415.33771" 65.247 + id="text6041"><tspan 65.248 + sodipodi:role="line" 65.249 + id="tspan6043" 65.250 + x="64.797073" 65.251 + y="415.33771" 65.252 + style="fill:#979797;fill-opacity:1;font-family:Courier">000000000000</tspan></text> 65.253 + <path 65.254 + inkscape:connection-end="#rect6039" 65.255 + inkscape:connector-type="polyline" 65.256 + id="path6045" 65.257 + d="M 107.38238,372.82195 L 107.38235,389.20301" 65.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" /> 65.259 + <text 65.260 + xml:space="preserve" 65.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" 65.262 + x="19.660461" 65.263 + y="231.36218" 65.264 + id="text6102"><tspan 65.265 + sodipodi:role="line" 65.266 + id="tspan6104" 65.267 + x="19.660461" 65.268 + y="231.36218">History in repository</tspan></text> 65.269 + <rect 65.270 + y="245.94225" 65.271 + x="249.28412" 65.272 + height="204.51619" 65.273 + width="174.36833" 65.274 + id="rect6140" 65.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" /> 65.276 + <g 65.277 + id="g6130" 65.278 + transform="translate(-45.67459,24.38544)"> 65.279 + <rect 65.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" 65.281 + id="rect6106" 65.282 + width="134.53746" 65.283 + height="44.537449" 65.284 + x="314.87415" 65.285 + y="257.95059" /> 65.286 + <text 65.287 + xml:space="preserve" 65.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" 65.289 + x="339.55664" 65.290 + y="283.7113" 65.291 + id="text6108"><tspan 65.292 + sodipodi:role="line" 65.293 + id="tspan6110" 65.294 + x="339.55664" 65.295 + y="283.7113" 65.296 + style="font-family:Courier">7b064d8bac5e</tspan></text> 65.297 + </g> 65.298 + <g 65.299 + id="g6135" 65.300 + transform="translate(-44.96042,49.83106)"> 65.301 + <rect 65.302 + inkscape:transform-center-y="102.85714" 65.303 + inkscape:transform-center-x="129.28571" 65.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" 65.305 + id="rect6112" 65.306 + width="134.53746" 65.307 + height="44.537449" 65.308 + x="314.15985" 65.309 + y="326.52203" /> 65.310 + <text 65.311 + inkscape:transform-center-y="102.7311" 65.312 + inkscape:transform-center-x="128.69672" 65.313 + xml:space="preserve" 65.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" 65.315 + x="338.84335" 65.316 + y="352.28271" 65.317 + id="text6114"><tspan 65.318 + sodipodi:role="line" 65.319 + id="tspan6116" 65.320 + x="338.84335" 65.321 + y="352.28271" 65.322 + style="fill:#979797;fill-opacity:1;font-family:Courier">000000000000</tspan></text> 65.323 + </g> 65.324 + <text 65.325 + xml:space="preserve" 65.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" 65.327 + x="268.63208" 65.328 + y="270.479" 65.329 + id="text6118"><tspan 65.330 + sodipodi:role="line" 65.331 + id="tspan6120" 65.332 + x="268.63208" 65.333 + y="270.479">First parent</tspan></text> 65.334 + <text 65.335 + xml:space="preserve" 65.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" 65.337 + x="268.07544" 65.338 + y="364.49615" 65.339 + id="text6122"><tspan 65.340 + sodipodi:role="line" 65.341 + id="tspan6124" 65.342 + x="268.07544" 65.343 + y="364.49615">Second parent</tspan></text> 65.344 + <text 65.345 + xml:space="preserve" 65.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" 65.347 + x="248.61746" 65.348 + y="231.36218" 65.349 + id="text6195"><tspan 65.350 + sodipodi:role="line" 65.351 + id="tspan6197" 65.352 + x="248.61746" 65.353 + y="231.36218">Parents of working directory</tspan></text> 65.354 + <path 65.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" 65.356 + d="M 268.82543,318.06163 L 175.02528,336.72225" 65.357 + id="path6266" 65.358 + inkscape:connector-type="polyline" 65.359 + inkscape:connection-end="#g6976" 65.360 + inkscape:connection-start="#g6130" /> 65.361 + <path 65.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" 65.363 + d="M 665.12232,418.17579 L 665.12232,418.17579" 65.364 + id="path6270" 65.365 + inkscape:connector-type="polyline" /> 65.366 + </g> 65.367 +</svg>
66.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 66.2 +++ b/fr/figs/wdir.svg Sun Aug 16 04:58:01 2009 +0200 66.3 @@ -0,0 +1,348 @@ 66.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?> 66.5 +<!-- Created with Inkscape (http://www.inkscape.org/) --> 66.6 +<svg 66.7 + xmlns:dc="http://purl.org/dc/elements/1.1/" 66.8 + xmlns:cc="http://web.resource.org/cc/" 66.9 + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 66.10 + xmlns:svg="http://www.w3.org/2000/svg" 66.11 + xmlns="http://www.w3.org/2000/svg" 66.12 + xmlns:xlink="http://www.w3.org/1999/xlink" 66.13 + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" 66.14 + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" 66.15 + width="744.09448819" 66.16 + height="1052.3622047" 66.17 + id="svg5971" 66.18 + sodipodi:version="0.32" 66.19 + inkscape:version="0.44.1" 66.20 + sodipodi:docbase="/home/bos/hg/hgbook/en" 66.21 + sodipodi:docname="wdir.svg"> 66.22 + <defs 66.23 + id="defs5973"> 66.24 + <marker 66.25 + inkscape:stockid="Arrow1Mstart" 66.26 + orient="auto" 66.27 + refY="0.0" 66.28 + refX="0.0" 66.29 + id="Arrow1Mstart" 66.30 + style="overflow:visible"> 66.31 + <path 66.32 + id="path4855" 66.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 " 66.34 + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none" 66.35 + transform="scale(0.4) translate(10,0)" /> 66.36 + </marker> 66.37 + <linearGradient 66.38 + id="linearGradient6049"> 66.39 + <stop 66.40 + style="stop-color:#686868;stop-opacity:1;" 66.41 + offset="0" 66.42 + id="stop6051" /> 66.43 + <stop 66.44 + style="stop-color:#f0f0f0;stop-opacity:1;" 66.45 + offset="1" 66.46 + id="stop6053" /> 66.47 + </linearGradient> 66.48 + <marker 66.49 + inkscape:stockid="Arrow1Mend" 66.50 + orient="auto" 66.51 + refY="0.0" 66.52 + refX="0.0" 66.53 + id="Arrow1Mend" 66.54 + style="overflow:visible;"> 66.55 + <path 66.56 + id="path4852" 66.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 " 66.58 + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;" 66.59 + transform="scale(0.4) rotate(180) translate(10,0)" /> 66.60 + </marker> 66.61 + <linearGradient 66.62 + inkscape:collect="always" 66.63 + xlink:href="#linearGradient6049" 66.64 + id="linearGradient6083" 66.65 + gradientUnits="userSpaceOnUse" 66.66 + gradientTransform="translate(-240.0462,-8.633237e-6)" 66.67 + x1="333.91171" 66.68 + y1="488.79077" 66.69 + x2="508.94543" 66.70 + y2="263.79077" /> 66.71 + <linearGradient 66.72 + inkscape:collect="always" 66.73 + xlink:href="#linearGradient6049" 66.74 + id="linearGradient6142" 66.75 + gradientUnits="userSpaceOnUse" 66.76 + gradientTransform="translate(-42.00893,-30.49544)" 66.77 + x1="333.91171" 66.78 + y1="488.79077" 66.79 + x2="508.94543" 66.80 + y2="263.79077" /> 66.81 + <linearGradient 66.82 + inkscape:collect="always" 66.83 + xlink:href="#linearGradient6049" 66.84 + id="linearGradient6193" 66.85 + gradientUnits="userSpaceOnUse" 66.86 + gradientTransform="translate(-240.0462,-8.633237e-6)" 66.87 + x1="333.91171" 66.88 + y1="488.79077" 66.89 + x2="508.94543" 66.90 + y2="263.79077" /> 66.91 + <linearGradient 66.92 + inkscape:collect="always" 66.93 + xlink:href="#linearGradient6049" 66.94 + id="linearGradient6216" 66.95 + gradientUnits="userSpaceOnUse" 66.96 + gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)" 66.97 + x1="333.91171" 66.98 + y1="488.79077" 66.99 + x2="508.94543" 66.100 + y2="263.79077" /> 66.101 + <linearGradient 66.102 + inkscape:collect="always" 66.103 + xlink:href="#linearGradient6049" 66.104 + id="linearGradient6232" 66.105 + gradientUnits="userSpaceOnUse" 66.106 + gradientTransform="matrix(1.000473,0,0,0.790947,-11.16012,50.85693)" 66.107 + x1="333.91171" 66.108 + y1="488.79077" 66.109 + x2="508.94543" 66.110 + y2="263.79077" /> 66.111 + <linearGradient 66.112 + inkscape:collect="always" 66.113 + xlink:href="#linearGradient6049" 66.114 + id="linearGradient6445" 66.115 + gradientUnits="userSpaceOnUse" 66.116 + gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)" 66.117 + x1="333.91171" 66.118 + y1="488.79077" 66.119 + x2="508.94543" 66.120 + y2="263.79077" /> 66.121 + </defs> 66.122 + <sodipodi:namedview 66.123 + id="base" 66.124 + pagecolor="#ffffff" 66.125 + bordercolor="#666666" 66.126 + borderopacity="1.0" 66.127 + gridtolerance="10000" 66.128 + guidetolerance="10" 66.129 + objecttolerance="10" 66.130 + inkscape:pageopacity="0.0" 66.131 + inkscape:pageshadow="2" 66.132 + inkscape:zoom="0.90509668" 66.133 + inkscape:cx="390.0539" 66.134 + inkscape:cy="690.49342" 66.135 + inkscape:document-units="px" 66.136 + inkscape:current-layer="layer1" 66.137 + showguides="true" 66.138 + inkscape:guide-bbox="true" 66.139 + inkscape:window-width="906" 66.140 + inkscape:window-height="620" 66.141 + inkscape:window-x="0" 66.142 + inkscape:window-y="25"> 66.143 + <sodipodi:guide 66.144 + orientation="vertical" 66.145 + position="-1.4285714" 66.146 + id="guide6022" /> 66.147 + </sodipodi:namedview> 66.148 + <metadata 66.149 + id="metadata5976"> 66.150 + <rdf:RDF> 66.151 + <cc:Work 66.152 + rdf:about=""> 66.153 + <dc:format>image/svg+xml</dc:format> 66.154 + <dc:type 66.155 + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 66.156 + </cc:Work> 66.157 + </rdf:RDF> 66.158 + </metadata> 66.159 + <g 66.160 + inkscape:label="Layer 1" 66.161 + inkscape:groupmode="layer" 66.162 + id="layer1"> 66.163 + <g 66.164 + id="g6431" 66.165 + transform="translate(0,-0.137863)"> 66.166 + <rect 66.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" 66.168 + id="rect6047" 66.169 + width="174.36833" 66.170 + height="204.51619" 66.171 + x="94.198257" 66.172 + y="246.08011" /> 66.173 + <rect 66.174 + y="266.38159" 66.175 + x="114.11369" 66.176 + height="44.537449" 66.177 + width="134.53746" 66.178 + id="rect5996" 66.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" /> 66.180 + <text 66.181 + id="text5998" 66.182 + y="292.1423" 66.183 + x="138.7962" 66.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" 66.185 + xml:space="preserve"><tspan 66.186 + style="font-family:Courier" 66.187 + y="292.1423" 66.188 + x="138.7962" 66.189 + id="tspan6000" 66.190 + sodipodi:role="line">e7639888bb2f</tspan></text> 66.191 + <rect 66.192 + y="328.04825" 66.193 + x="114.11369" 66.194 + height="44.537449" 66.195 + width="134.53746" 66.196 + id="rect6004" 66.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" /> 66.198 + <text 66.199 + id="text6006" 66.200 + y="353.80896" 66.201 + x="136.65421" 66.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" 66.203 + xml:space="preserve"><tspan 66.204 + style="font-family:Courier" 66.205 + y="353.80896" 66.206 + x="136.65421" 66.207 + id="tspan6008" 66.208 + sodipodi:role="line">7b064d8bac5e</tspan></text> 66.209 + <path 66.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" 66.211 + d="M 181.38242,311.29315 L 181.38242,327.67412" 66.212 + id="path6020" 66.213 + inkscape:connector-type="polyline" 66.214 + inkscape:connection-end="#rect6004" /> 66.215 + <rect 66.216 + y="389.71487" 66.217 + x="114.11357" 66.218 + height="44.537449" 66.219 + width="134.53746" 66.220 + id="rect6039" 66.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" /> 66.222 + <text 66.223 + id="text6041" 66.224 + y="415.47556" 66.225 + x="138.79707" 66.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" 66.227 + xml:space="preserve"><tspan 66.228 + style="fill:#979797;fill-opacity:1;font-family:Courier" 66.229 + y="415.47556" 66.230 + x="138.79707" 66.231 + id="tspan6043" 66.232 + sodipodi:role="line">000000000000</tspan></text> 66.233 + <path 66.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" 66.235 + d="M 181.38238,372.95981 L 181.38235,389.34087" 66.236 + id="path6045" 66.237 + inkscape:connector-type="polyline" 66.238 + inkscape:connection-end="#rect6039" /> 66.239 + </g> 66.240 + <text 66.241 + xml:space="preserve" 66.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" 66.243 + x="93.660484" 66.244 + y="231.36218" 66.245 + id="text6102"><tspan 66.246 + sodipodi:role="line" 66.247 + id="tspan6104" 66.248 + x="93.660484" 66.249 + y="231.36218">History in repository</tspan></text> 66.250 + <g 66.251 + id="g6416"> 66.252 + <rect 66.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" 66.254 + id="rect6140" 66.255 + width="174.36833" 66.256 + height="204.51619" 66.257 + x="323.28412" 66.258 + y="245.94225" /> 66.259 + <g 66.260 + transform="translate(28.32541,24.38544)" 66.261 + id="g6130"> 66.262 + <rect 66.263 + y="257.95059" 66.264 + x="314.87415" 66.265 + height="44.537449" 66.266 + width="134.53746" 66.267 + id="rect6106" 66.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" /> 66.269 + <text 66.270 + id="text6108" 66.271 + y="283.7113" 66.272 + x="339.55664" 66.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" 66.274 + xml:space="preserve"><tspan 66.275 + style="font-family:Courier" 66.276 + y="283.7113" 66.277 + x="339.55664" 66.278 + id="tspan6110" 66.279 + sodipodi:role="line">e7639888bb2f</tspan></text> 66.280 + </g> 66.281 + <g 66.282 + transform="translate(29.03958,49.83106)" 66.283 + id="g6135"> 66.284 + <rect 66.285 + y="326.52203" 66.286 + x="314.15985" 66.287 + height="44.537449" 66.288 + width="134.53746" 66.289 + id="rect6112" 66.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" 66.291 + inkscape:transform-center-x="129.28571" 66.292 + inkscape:transform-center-y="102.85714" /> 66.293 + <text 66.294 + id="text6114" 66.295 + y="352.28271" 66.296 + x="338.84335" 66.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" 66.298 + xml:space="preserve" 66.299 + inkscape:transform-center-x="128.69672" 66.300 + inkscape:transform-center-y="102.7311"><tspan 66.301 + style="fill:#979797;fill-opacity:1;font-family:Courier" 66.302 + y="352.28271" 66.303 + x="338.84335" 66.304 + id="tspan6116" 66.305 + sodipodi:role="line">000000000000</tspan></text> 66.306 + </g> 66.307 + <text 66.308 + id="text6118" 66.309 + y="270.479" 66.310 + x="342.63208" 66.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" 66.312 + xml:space="preserve"><tspan 66.313 + y="270.479" 66.314 + x="342.63208" 66.315 + id="tspan6120" 66.316 + sodipodi:role="line">First parent</tspan></text> 66.317 + <text 66.318 + id="text6122" 66.319 + y="364.49615" 66.320 + x="342.07544" 66.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" 66.322 + xml:space="preserve"><tspan 66.323 + y="364.49615" 66.324 + x="342.07544" 66.325 + id="tspan6124" 66.326 + sodipodi:role="line">Second parent</tspan></text> 66.327 + </g> 66.328 + <text 66.329 + xml:space="preserve" 66.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" 66.331 + x="322.61746" 66.332 + y="231.36218" 66.333 + id="text6195"><tspan 66.334 + sodipodi:role="line" 66.335 + id="tspan6197" 66.336 + x="322.61746" 66.337 + y="231.36218">Parents of working directory</tspan></text> 66.338 + <path 66.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" 66.340 + d="M 342.82543,299.89384 L 249.02528,293.36123" 66.341 + id="path6266" 66.342 + inkscape:connector-type="polyline" 66.343 + inkscape:connection-start="#g6130" 66.344 + inkscape:connection-end="#rect5996" /> 66.345 + <path 66.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" 66.347 + d="M 665.12232,418.17579 L 665.12232,418.17579" 66.348 + id="path6270" 66.349 + inkscape:connector-type="polyline" /> 66.350 + </g> 66.351 +</svg>
67.1 --- a/fr/filelog.svg Sun Aug 16 03:41:39 2009 +0200 67.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 67.3 @@ -1,373 +0,0 @@ 67.4 -<?xml version="1.0" encoding="UTF-8" standalone="no"?> 67.5 -<!-- Created with Inkscape (http://www.inkscape.org/) --> 67.6 -<svg 67.7 - xmlns:dc="http://purl.org/dc/elements/1.1/" 67.8 - xmlns:cc="http://web.resource.org/cc/" 67.9 - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 67.10 - xmlns:svg="http://www.w3.org/2000/svg" 67.11 - xmlns="http://www.w3.org/2000/svg" 67.12 - xmlns:xlink="http://www.w3.org/1999/xlink" 67.13 - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" 67.14 - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" 67.15 - width="744.09448819" 67.16 - height="1052.3622047" 67.17 - id="svg2" 67.18 - sodipodi:version="0.32" 67.19 - inkscape:version="0.45.1" 67.20 - sodipodi:docname="filelog.svg" 67.21 - sodipodi:docbase="/home/arun/hgbook/en" 67.22 - inkscape:output_extension="org.inkscape.output.svg.inkscape"> 67.23 - <defs 67.24 - id="defs4"> 67.25 - <marker 67.26 - inkscape:stockid="Arrow1Mend" 67.27 - orient="auto" 67.28 - refY="0.0" 67.29 - refX="0.0" 67.30 - id="Arrow1Mend" 67.31 - style="overflow:visible;"> 67.32 - <path 67.33 - id="path3128" 67.34 - d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z " 67.35 - style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;" 67.36 - transform="scale(0.4) rotate(180) translate(10,0)" /> 67.37 - </marker> 67.38 - <linearGradient 67.39 - id="linearGradient2887"> 67.40 - <stop 67.41 - style="stop-color:#91cfcf;stop-opacity:1;" 67.42 - offset="0" 67.43 - id="stop2889" /> 67.44 - <stop 67.45 - style="stop-color:aqua;stop-opacity:0;" 67.46 - offset="1" 67.47 - id="stop2891" /> 67.48 - </linearGradient> 67.49 - <linearGradient 67.50 - id="linearGradient2795"> 67.51 - <stop 67.52 - style="stop-color:#ccc;stop-opacity:1;" 67.53 - offset="0" 67.54 - id="stop2797" /> 67.55 - <stop 67.56 - style="stop-color:#ccc;stop-opacity:0;" 67.57 - offset="1" 67.58 - id="stop2799" /> 67.59 - </linearGradient> 67.60 - <linearGradient 67.61 - inkscape:collect="always" 67.62 - xlink:href="#linearGradient2795" 67.63 - id="linearGradient3170" 67.64 - gradientUnits="userSpaceOnUse" 67.65 - gradientTransform="translate(121.2183,94.95434)" 67.66 - x1="81.322357" 67.67 - y1="404.34424" 67.68 - x2="201.52036" 67.69 - y2="373.03967" /> 67.70 - <linearGradient 67.71 - inkscape:collect="always" 67.72 - xlink:href="#linearGradient2887" 67.73 - id="linearGradient3172" 67.74 - gradientUnits="userSpaceOnUse" 67.75 - gradientTransform="translate(0,12)" 67.76 - x1="62.634491" 67.77 - y1="503.3392" 67.78 - x2="248.49242" 67.79 - y2="462.94327" /> 67.80 - <linearGradient 67.81 - inkscape:collect="always" 67.82 - xlink:href="#linearGradient2795" 67.83 - id="linearGradient3174" 67.84 - gradientUnits="userSpaceOnUse" 67.85 - gradientTransform="matrix(1.001035,0,0,0.653159,236.7075,153.0415)" 67.86 - x1="81.322357" 67.87 - y1="404.34424" 67.88 - x2="201.52036" 67.89 - y2="373.03967" /> 67.90 - <linearGradient 67.91 - inkscape:collect="always" 67.92 - xlink:href="#linearGradient2887" 67.93 - id="linearGradient3176" 67.94 - gradientUnits="userSpaceOnUse" 67.95 - gradientTransform="translate(0,12)" 67.96 - x1="62.634491" 67.97 - y1="503.3392" 67.98 - x2="248.49242" 67.99 - y2="462.94327" /> 67.100 - <linearGradient 67.101 - inkscape:collect="always" 67.102 - xlink:href="#linearGradient2795" 67.103 - id="linearGradient3208" 67.104 - gradientUnits="userSpaceOnUse" 67.105 - gradientTransform="matrix(1.001035,0,0,0.653159,236.7075,153.0415)" 67.106 - x1="81.322357" 67.107 - y1="404.34424" 67.108 - x2="201.52036" 67.109 - y2="373.03967" /> 67.110 - <linearGradient 67.111 - inkscape:collect="always" 67.112 - xlink:href="#linearGradient2887" 67.113 - id="linearGradient3210" 67.114 - gradientUnits="userSpaceOnUse" 67.115 - gradientTransform="translate(0,12)" 67.116 - x1="62.634491" 67.117 - y1="503.3392" 67.118 - x2="248.49242" 67.119 - y2="462.94327" /> 67.120 - <linearGradient 67.121 - inkscape:collect="always" 67.122 - xlink:href="#linearGradient2795" 67.123 - id="linearGradient3212" 67.124 - gradientUnits="userSpaceOnUse" 67.125 - gradientTransform="translate(121.2183,94.95434)" 67.126 - x1="81.322357" 67.127 - y1="404.34424" 67.128 - x2="201.52036" 67.129 - y2="373.03967" /> 67.130 - <linearGradient 67.131 - inkscape:collect="always" 67.132 - xlink:href="#linearGradient2887" 67.133 - id="linearGradient3214" 67.134 - gradientUnits="userSpaceOnUse" 67.135 - gradientTransform="translate(0,12)" 67.136 - x1="62.634491" 67.137 - y1="503.3392" 67.138 - x2="248.49242" 67.139 - y2="462.94327" /> 67.140 - <linearGradient 67.141 - inkscape:collect="always" 67.142 - xlink:href="#linearGradient2795" 67.143 - id="linearGradient3256" 67.144 - gradientUnits="userSpaceOnUse" 67.145 - gradientTransform="matrix(1.2343775,0,0,0.9981848,103.25588,95.681888)" 67.146 - x1="74.301666" 67.147 - y1="431.67441" 67.148 - x2="260.05884" 67.149 - y2="369.95322" /> 67.150 - <linearGradient 67.151 - inkscape:collect="always" 67.152 - xlink:href="#linearGradient2887" 67.153 - id="linearGradient3258" 67.154 - gradientUnits="userSpaceOnUse" 67.155 - gradientTransform="matrix(1.228929,0,0,0.9972824,-62.037003,13.312997)" 67.156 - x1="62.634491" 67.157 - y1="503.3392" 67.158 - x2="248.49242" 67.159 - y2="462.94327" /> 67.160 - <linearGradient 67.161 - inkscape:collect="always" 67.162 - xlink:href="#linearGradient2795" 67.163 - id="linearGradient3260" 67.164 - gradientUnits="userSpaceOnUse" 67.165 - gradientTransform="matrix(1.2300738,0,0,0.6517275,219.97511,153.61527)" 67.166 - x1="74.387527" 67.167 - y1="431.80576" 67.168 - x2="259.97339" 67.169 - y2="369.82224" /> 67.170 - <linearGradient 67.171 - inkscape:collect="always" 67.172 - xlink:href="#linearGradient2887" 67.173 - id="linearGradient3262" 67.174 - gradientUnits="userSpaceOnUse" 67.175 - gradientTransform="matrix(1.2289272,0,0,0.9972824,-62.036756,13.312985)" 67.176 - x1="62.634491" 67.177 - y1="503.3392" 67.178 - x2="248.49242" 67.179 - y2="462.94327" /> 67.180 - </defs> 67.181 - <sodipodi:namedview 67.182 - id="base" 67.183 - pagecolor="#ffffff" 67.184 - bordercolor="#666666" 67.185 - borderopacity="1.0" 67.186 - gridtolerance="10000" 67.187 - guidetolerance="10" 67.188 - objecttolerance="10" 67.189 - inkscape:pageopacity="0.0" 67.190 - inkscape:pageshadow="2" 67.191 - inkscape:zoom="1.4" 67.192 - inkscape:cx="455.8122" 67.193 - inkscape:cy="520" 67.194 - inkscape:document-units="px" 67.195 - inkscape:current-layer="layer1" 67.196 - inkscape:window-width="1680" 67.197 - inkscape:window-height="970" 67.198 - inkscape:window-x="0" 67.199 - inkscape:window-y="54" /> 67.200 - <metadata 67.201 - id="metadata7"> 67.202 - <rdf:RDF> 67.203 - <cc:Work 67.204 - rdf:about=""> 67.205 - <dc:format>image/svg+xml</dc:format> 67.206 - <dc:type 67.207 - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 67.208 - </cc:Work> 67.209 - </rdf:RDF> 67.210 - </metadata> 67.211 - <g 67.212 - inkscape:label="Layer 1" 67.213 - inkscape:groupmode="layer" 67.214 - id="layer1"> 67.215 - <rect 67.216 - style="opacity:1;fill:#abadf8;fill-opacity:1;stroke:#595959;stroke-width:0.93760371;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" 67.217 - id="rect3180" 67.218 - width="273.81375" 67.219 - height="199.06245" 67.220 - x="369.1796" 67.221 - y="351.79019" /> 67.222 - <rect 67.223 - style="opacity:1;fill:#a2f69c;fill-opacity:1;stroke:#595959;stroke-width:0.93760341;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" 67.224 - id="rect3178" 67.225 - width="273.81339" 67.226 - height="199.06233" 67.227 - x="72.699799" 67.228 - y="351.78983" /> 67.229 - <g 67.230 - id="g3144" 67.231 - transform="translate(80.467048,0.71578)"> 67.232 - <g 67.233 - id="g2940"> 67.234 - <rect 67.235 - style="fill:url(#linearGradient3260);fill-opacity:1;stroke:#000000;stroke-width:0.89536202;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" 67.236 - id="rect2914" 67.237 - width="227.38896" 67.238 - height="39.500999" 67.239 - x="311.92496" 67.240 - y="395.08627" /> 67.241 - <text 67.242 - xml:space="preserve" 67.243 - style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman" 67.244 - x="323.72824" 67.245 - y="416.7626" 67.246 - id="text2918"><tspan 67.247 - sodipodi:role="line" 67.248 - id="tspan2920" 67.249 - x="323.72824" 67.250 - y="416.7626" 67.251 - style="font-family:Courier">.hg/store/data/README.i</tspan></text> 67.252 - </g> 67.253 - <g 67.254 - transform="translate(3.79093e-5,-80.1853)" 67.255 - id="g2945"> 67.256 - <g 67.257 - id="g2955"> 67.258 - <rect 67.259 - y="475.4968" 67.260 - x="15.550935" 67.261 - height="39.500999" 67.262 - width="227.17694" 67.263 - id="rect2947" 67.264 - style="fill:url(#linearGradient3262);fill-opacity:1;stroke:#000000;stroke-width:1.10706258;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /> 67.265 - <text 67.266 - id="text2949" 67.267 - y="498.35123" 67.268 - x="31.230644" 67.269 - style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman" 67.270 - xml:space="preserve"><tspan 67.271 - style="font-family:Courier" 67.272 - y="498.35123" 67.273 - x="31.230644" 67.274 - id="tspan2951" 67.275 - sodipodi:role="line">README</tspan></text> 67.276 - </g> 67.277 - </g> 67.278 - <path 67.279 - inkscape:connector-type="polyline" 67.280 - id="path2960" 67.281 - d="M 242.94685,414.91115 C 242.94685,414.91115 293.61127,415.26754 310.16269,415.38633" 67.282 - style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1.02046943px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1" 67.283 - sodipodi:nodetypes="cz" /> 67.284 - </g> 67.285 - <g 67.286 - id="g3156" 67.287 - transform="translate(80.467048,0.71578)"> 67.288 - <g 67.289 - transform="translate(116,0)" 67.290 - id="g2831"> 67.291 - <rect 67.292 - style="fill:url(#linearGradient3256);fill-opacity:1;stroke:#000000;stroke-width:1.11001658;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" 67.293 - id="rect1906" 67.294 - width="228.18446" 67.295 - height="60.499123" 67.296 - x="195.52719" 67.297 - y="465.51859" /> 67.298 - <g 67.299 - id="g2803" 67.300 - transform="translate(-0.893671,1.833581)"> 67.301 - <text 67.302 - id="text1884" 67.303 - y="483.92801" 67.304 - x="208.95944" 67.305 - style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman" 67.306 - xml:space="preserve"><tspan 67.307 - style="font-family:Courier" 67.308 - y="483.92801" 67.309 - x="208.95944" 67.310 - id="tspan1886" 67.311 - sodipodi:role="line">.hg/store/data/src/hello.c.d</tspan></text> 67.312 - <text 67.313 - id="text1888" 67.314 - y="507.79309" 67.315 - x="208.95944" 67.316 - style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman" 67.317 - xml:space="preserve"><tspan 67.318 - style="font-family:Courier" 67.319 - y="507.79309" 67.320 - x="208.95944" 67.321 - id="tspan1890" 67.322 - sodipodi:role="line">.hg/store/data/src/hello.c.i</tspan></text> 67.323 - </g> 67.324 - </g> 67.325 - <g 67.326 - id="g2907"> 67.327 - <rect 67.328 - style="fill:url(#linearGradient3258);fill-opacity:1;stroke:#000000;stroke-width:1.10706329;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" 67.329 - id="rect2843" 67.330 - width="227.17728" 67.331 - height="39.500999" 67.332 - x="15.550805" 67.333 - y="475.4968" /> 67.334 - <text 67.335 - xml:space="preserve" 67.336 - style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman" 67.337 - x="31.230644" 67.338 - y="498.35123" 67.339 - id="text2847"><tspan 67.340 - sodipodi:role="line" 67.341 - id="tspan2849" 67.342 - x="31.230644" 67.343 - y="498.35123" 67.344 - style="font-family:Courier">src/hello.c</tspan></text> 67.345 - </g> 67.346 - <path 67.347 - inkscape:connection-end="#g2831" 67.348 - inkscape:connection-start="#g2907" 67.349 - inkscape:connector-type="polyline" 67.350 - id="path2962" 67.351 - d="M 242.4315,495.88043 C 242.4315,495.88043 292.8861,495.99942 310.04102,496.03909" 67.352 - style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1" 67.353 - sodipodi:nodetypes="cs" /> 67.354 - </g> 67.355 - <text 67.356 - xml:space="preserve" 67.357 - style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman" 67.358 - x="98.496666" 67.359 - y="373.96353" 67.360 - id="text3216"><tspan 67.361 - sodipodi:role="line" 67.362 - id="tspan3218" 67.363 - x="98.496666" 67.364 - y="373.96353">Working directory</tspan></text> 67.365 - <text 67.366 - xml:space="preserve" 67.367 - style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman" 67.368 - x="391.39197" 67.369 - y="373.96353" 67.370 - id="text3228"><tspan 67.371 - sodipodi:role="line" 67.372 - id="tspan3230" 67.373 - x="391.39197" 67.374 - y="373.96353">Repository</tspan></text> 67.375 - </g> 67.376 -</svg>
68.1 --- a/fr/filenames.tex Sun Aug 16 03:41:39 2009 +0200 68.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 68.3 @@ -1,306 +0,0 @@ 68.4 -\chapter{File names and pattern matching} 68.5 -\label{chap:names} 68.6 - 68.7 -Mercurial provides mechanisms that let you work with file names in a 68.8 -consistent and expressive way. 68.9 - 68.10 -\section{Simple file naming} 68.11 - 68.12 -Mercurial uses a unified piece of machinery ``under the hood'' to 68.13 -handle file names. Every command behaves uniformly with respect to 68.14 -file names. The way in which commands work with file names is as 68.15 -follows. 68.16 - 68.17 -If you explicitly name real files on the command line, Mercurial works 68.18 -with exactly those files, as you would expect. 68.19 -\interaction{filenames.files} 68.20 - 68.21 -When you provide a directory name, Mercurial will interpret this as 68.22 -``operate on every file in this directory and its subdirectories''. 68.23 -Mercurial traverses the files and subdirectories in a directory in 68.24 -alphabetical order. When it encounters a subdirectory, it will 68.25 -traverse that subdirectory before continuing with the current 68.26 -directory. 68.27 -\interaction{filenames.dirs} 68.28 - 68.29 -\section{Running commands without any file names} 68.30 - 68.31 -Mercurial's commands that work with file names have useful default 68.32 -behaviours when you invoke them without providing any file names or 68.33 -patterns. What kind of behaviour you should expect depends on what 68.34 -the command does. Here are a few rules of thumb you can use to 68.35 -predict what a command is likely to do if you don't give it any names 68.36 -to work with. 68.37 -\begin{itemize} 68.38 -\item Most commands will operate on the entire working directory. 68.39 - This is what the \hgcmd{add} command does, for example. 68.40 -\item If the command has effects that are difficult or impossible to 68.41 - reverse, it will force you to explicitly provide at least one name 68.42 - or pattern (see below). This protects you from accidentally 68.43 - deleting files by running \hgcmd{remove} with no arguments, for 68.44 - example. 68.45 -\end{itemize} 68.46 - 68.47 -It's easy to work around these default behaviours if they don't suit 68.48 -you. If a command normally operates on the whole working directory, 68.49 -you can invoke it on just the current directory and its subdirectories 68.50 -by giving it the name ``\dirname{.}''. 68.51 -\interaction{filenames.wdir-subdir} 68.52 - 68.53 -Along the same lines, some commands normally print file names relative 68.54 -to the root of the repository, even if you're invoking them from a 68.55 -subdirectory. Such a command will print file names relative to your 68.56 -subdirectory if you give it explicit names. Here, we're going to run 68.57 -\hgcmd{status} from a subdirectory, and get it to operate on the 68.58 -entire working directory while printing file names relative to our 68.59 -subdirectory, by passing it the output of the \hgcmd{root} command. 68.60 -\interaction{filenames.wdir-relname} 68.61 - 68.62 -\section{Telling you what's going on} 68.63 - 68.64 -The \hgcmd{add} example in the preceding section illustrates something 68.65 -else that's helpful about Mercurial commands. If a command operates 68.66 -on a file that you didn't name explicitly on the command line, it will 68.67 -usually print the name of the file, so that you will not be surprised 68.68 -what's going on. 68.69 - 68.70 -The principle here is of \emph{least surprise}. If you've exactly 68.71 -named a file on the command line, there's no point in repeating it 68.72 -back at you. If Mercurial is acting on a file \emph{implicitly}, 68.73 -because you provided no names, or a directory, or a pattern (see 68.74 -below), it's safest to tell you what it's doing. 68.75 - 68.76 -For commands that behave this way, you can silence them using the 68.77 -\hggopt{-q} option. You can also get them to print the name of every 68.78 -file, even those you've named explicitly, using the \hggopt{-v} 68.79 -option. 68.80 - 68.81 -\section{Using patterns to identify files} 68.82 - 68.83 -In addition to working with file and directory names, Mercurial lets 68.84 -you use \emph{patterns} to identify files. Mercurial's pattern 68.85 -handling is expressive. 68.86 - 68.87 -On Unix-like systems (Linux, MacOS, etc.), the job of matching file 68.88 -names to patterns normally falls to the shell. On these systems, you 68.89 -must explicitly tell Mercurial that a name is a pattern. On Windows, 68.90 -the shell does not expand patterns, so Mercurial will automatically 68.91 -identify names that are patterns, and expand them for you. 68.92 - 68.93 -To provide a pattern in place of a regular name on the command line, 68.94 -the mechanism is simple: 68.95 -\begin{codesample2} 68.96 - syntax:patternbody 68.97 -\end{codesample2} 68.98 -That is, a pattern is identified by a short text string that says what 68.99 -kind of pattern this is, followed by a colon, followed by the actual 68.100 -pattern. 68.101 - 68.102 -Mercurial supports two kinds of pattern syntax. The most frequently 68.103 -used is called \texttt{glob}; this is the same kind of pattern 68.104 -matching used by the Unix shell, and should be familiar to Windows 68.105 -command prompt users, too. 68.106 - 68.107 -When Mercurial does automatic pattern matching on Windows, it uses 68.108 -\texttt{glob} syntax. You can thus omit the ``\texttt{glob:}'' prefix 68.109 -on Windows, but it's safe to use it, too. 68.110 - 68.111 -The \texttt{re} syntax is more powerful; it lets you specify patterns 68.112 -using regular expressions, also known as regexps. 68.113 - 68.114 -By the way, in the examples that follow, notice that I'm careful to 68.115 -wrap all of my patterns in quote characters, so that they won't get 68.116 -expanded by the shell before Mercurial sees them. 68.117 - 68.118 -\subsection{Shell-style \texttt{glob} patterns} 68.119 - 68.120 -This is an overview of the kinds of patterns you can use when you're 68.121 -matching on glob patterns. 68.122 - 68.123 -The ``\texttt{*}'' character matches any string, within a single 68.124 -directory. 68.125 -\interaction{filenames.glob.star} 68.126 - 68.127 -The ``\texttt{**}'' pattern matches any string, and crosses directory 68.128 -boundaries. It's not a standard Unix glob token, but it's accepted by 68.129 -several popular Unix shells, and is very useful. 68.130 -\interaction{filenames.glob.starstar} 68.131 - 68.132 -The ``\texttt{?}'' pattern matches any single character. 68.133 -\interaction{filenames.glob.question} 68.134 - 68.135 -The ``\texttt{[}'' character begins a \emph{character class}. This 68.136 -matches any single character within the class. The class ends with a 68.137 -``\texttt{]}'' character. A class may contain multiple \emph{range}s 68.138 -of the form ``\texttt{a-f}'', which is shorthand for 68.139 -``\texttt{abcdef}''. 68.140 -\interaction{filenames.glob.range} 68.141 -If the first character after the ``\texttt{[}'' in a character class 68.142 -is a ``\texttt{!}'', it \emph{negates} the class, making it match any 68.143 -single character not in the class. 68.144 - 68.145 -A ``\texttt{\{}'' begins a group of subpatterns, where the whole group 68.146 -matches if any subpattern in the group matches. The ``\texttt{,}'' 68.147 -character separates subpatterns, and ``\texttt{\}}'' ends the group. 68.148 -\interaction{filenames.glob.group} 68.149 - 68.150 -\subsubsection{Watch out!} 68.151 - 68.152 -Don't forget that if you want to match a pattern in any directory, you 68.153 -should not be using the ``\texttt{*}'' match-any token, as this will 68.154 -only match within one directory. Instead, use the ``\texttt{**}'' 68.155 -token. This small example illustrates the difference between the two. 68.156 -\interaction{filenames.glob.star-starstar} 68.157 - 68.158 -\subsection{Regular expression matching with \texttt{re} patterns} 68.159 - 68.160 -Mercurial accepts the same regular expression syntax as the Python 68.161 -programming language (it uses Python's regexp engine internally). 68.162 -This is based on the Perl language's regexp syntax, which is the most 68.163 -popular dialect in use (it's also used in Java, for example). 68.164 - 68.165 -I won't discuss Mercurial's regexp dialect in any detail here, as 68.166 -regexps are not often used. Perl-style regexps are in any case 68.167 -already exhaustively documented on a multitude of web sites, and in 68.168 -many books. Instead, I will focus here on a few things you should 68.169 -know if you find yourself needing to use regexps with Mercurial. 68.170 - 68.171 -A regexp is matched against an entire file name, relative to the root 68.172 -of the repository. In other words, even if you're already in 68.173 -subbdirectory \dirname{foo}, if you want to match files under this 68.174 -directory, your pattern must start with ``\texttt{foo/}''. 68.175 - 68.176 -One thing to note, if you're familiar with Perl-style regexps, is that 68.177 -Mercurial's are \emph{rooted}. That is, a regexp starts matching 68.178 -against the beginning of a string; it doesn't look for a match 68.179 -anywhere within the string. To match anywhere in a string, start 68.180 -your pattern with ``\texttt{.*}''. 68.181 - 68.182 -\section{Filtering files} 68.183 - 68.184 -Not only does Mercurial give you a variety of ways to specify files; 68.185 -it lets you further winnow those files using \emph{filters}. Commands 68.186 -that work with file names accept two filtering options. 68.187 -\begin{itemize} 68.188 -\item \hggopt{-I}, or \hggopt{--include}, lets you specify a pattern 68.189 - that file names must match in order to be processed. 68.190 -\item \hggopt{-X}, or \hggopt{--exclude}, gives you a way to 68.191 - \emph{avoid} processing files, if they match this pattern. 68.192 -\end{itemize} 68.193 -You can provide multiple \hggopt{-I} and \hggopt{-X} options on the 68.194 -command line, and intermix them as you please. Mercurial interprets 68.195 -the patterns you provide using glob syntax by default (but you can use 68.196 -regexps if you need to). 68.197 - 68.198 -You can read a \hggopt{-I} filter as ``process only the files that 68.199 -match this filter''. 68.200 -\interaction{filenames.filter.include} 68.201 -The \hggopt{-X} filter is best read as ``process only the files that 68.202 -don't match this pattern''. 68.203 -\interaction{filenames.filter.exclude} 68.204 - 68.205 -\section{Ignoring unwanted files and directories} 68.206 - 68.207 -XXX. 68.208 - 68.209 -\section{Case sensitivity} 68.210 -\label{sec:names:case} 68.211 - 68.212 -If you're working in a mixed development environment that contains 68.213 -both Linux (or other Unix) systems and Macs or Windows systems, you 68.214 -should keep in the back of your mind the knowledge that they treat the 68.215 -case (``N'' versus ``n'') of file names in incompatible ways. This is 68.216 -not very likely to affect you, and it's easy to deal with if it does, 68.217 -but it could surprise you if you don't know about it. 68.218 - 68.219 -Operating systems and filesystems differ in the way they handle the 68.220 -\emph{case} of characters in file and directory names. There are 68.221 -three common ways to handle case in names. 68.222 -\begin{itemize} 68.223 -\item Completely case insensitive. Uppercase and lowercase versions 68.224 - of a letter are treated as identical, both when creating a file and 68.225 - during subsequent accesses. This is common on older DOS-based 68.226 - systems. 68.227 -\item Case preserving, but insensitive. When a file or directory is 68.228 - created, the case of its name is stored, and can be retrieved and 68.229 - displayed by the operating system. When an existing file is being 68.230 - looked up, its case is ignored. This is the standard arrangement on 68.231 - Windows and MacOS. The names \filename{foo} and \filename{FoO} 68.232 - identify the same file. This treatment of uppercase and lowercase 68.233 - letters as interchangeable is also referred to as \emph{case 68.234 - folding}. 68.235 -\item Case sensitive. The case of a name is significant at all times. 68.236 - The names \filename{foo} and {FoO} identify different files. This 68.237 - is the way Linux and Unix systems normally work. 68.238 -\end{itemize} 68.239 - 68.240 -On Unix-like systems, it is possible to have any or all of the above 68.241 -ways of handling case in action at once. For example, if you use a 68.242 -USB thumb drive formatted with a FAT32 filesystem on a Linux system, 68.243 -Linux will handle names on that filesystem in a case preserving, but 68.244 -insensitive, way. 68.245 - 68.246 -\subsection{Safe, portable repository storage} 68.247 - 68.248 -Mercurial's repository storage mechanism is \emph{case safe}. It 68.249 -translates file names so that they can be safely stored on both case 68.250 -sensitive and case insensitive filesystems. This means that you can 68.251 -use normal file copying tools to transfer a Mercurial repository onto, 68.252 -for example, a USB thumb drive, and safely move that drive and 68.253 -repository back and forth between a Mac, a PC running Windows, and a 68.254 -Linux box. 68.255 - 68.256 -\subsection{Detecting case conflicts} 68.257 - 68.258 -When operating in the working directory, Mercurial honours the naming 68.259 -policy of the filesystem where the working directory is located. If 68.260 -the filesystem is case preserving, but insensitive, Mercurial will 68.261 -treat names that differ only in case as the same. 68.262 - 68.263 -An important aspect of this approach is that it is possible to commit 68.264 -a changeset on a case sensitive (typically Linux or Unix) filesystem 68.265 -that will cause trouble for users on case insensitive (usually Windows 68.266 -and MacOS) users. If a Linux user commits changes to two files, one 68.267 -named \filename{myfile.c} and the other named \filename{MyFile.C}, 68.268 -they will be stored correctly in the repository. And in the working 68.269 -directories of other Linux users, they will be correctly represented 68.270 -as separate files. 68.271 - 68.272 -If a Windows or Mac user pulls this change, they will not initially 68.273 -have a problem, because Mercurial's repository storage mechanism is 68.274 -case safe. However, once they try to \hgcmd{update} the working 68.275 -directory to that changeset, or \hgcmd{merge} with that changeset, 68.276 -Mercurial will spot the conflict between the two file names that the 68.277 -filesystem would treat as the same, and forbid the update or merge 68.278 -from occurring. 68.279 - 68.280 -\subsection{Fixing a case conflict} 68.281 - 68.282 -If you are using Windows or a Mac in a mixed environment where some of 68.283 -your collaborators are using Linux or Unix, and Mercurial reports a 68.284 -case folding conflict when you try to \hgcmd{update} or \hgcmd{merge}, 68.285 -the procedure to fix the problem is simple. 68.286 - 68.287 -Just find a nearby Linux or Unix box, clone the problem repository 68.288 -onto it, and use Mercurial's \hgcmd{rename} command to change the 68.289 -names of any offending files or directories so that they will no 68.290 -longer cause case folding conflicts. Commit this change, \hgcmd{pull} 68.291 -or \hgcmd{push} it across to your Windows or MacOS system, and 68.292 -\hgcmd{update} to the revision with the non-conflicting names. 68.293 - 68.294 -The changeset with case-conflicting names will remain in your 68.295 -project's history, and you still won't be able to \hgcmd{update} your 68.296 -working directory to that changeset on a Windows or MacOS system, but 68.297 -you can continue development unimpeded. 68.298 - 68.299 -\begin{note} 68.300 - Prior to version~0.9.3, Mercurial did not use a case safe repository 68.301 - storage mechanism, and did not detect case folding conflicts. If 68.302 - you are using an older version of Mercurial on Windows or MacOS, I 68.303 - strongly recommend that you upgrade. 68.304 -\end{note} 68.305 - 68.306 -%%% Local Variables: 68.307 -%%% mode: latex 68.308 -%%% TeX-master: "00book" 68.309 -%%% End:
69.1 --- a/fr/fixhtml.py Sun Aug 16 03:41:39 2009 +0200 69.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 69.3 @@ -1,50 +0,0 @@ 69.4 -#!/usr/bin/env python 69.5 -# 69.6 -# This script attempts to work around some of the more bizarre and 69.7 -# quirky behaviours of htlatex. 69.8 -# 69.9 -# - We've persuaded htlatex to produce UTF-8, which unfortunately 69.10 -# causes it to use huge character sequences to represent even the 69.11 -# safe 7-bit ASCII subset of UTF-8. We fix that up. 69.12 -# 69.13 -# - BUT we have to treat angle brackets (for example, redirections in 69.14 -# shell script snippets) specially, otherwise they'll break the 69.15 -# generated HTML. (Reported by Johannes Hoff.) 69.16 -# 69.17 -# - For some reason, htlatex gives a unique ID to each fancyvrb 69.18 -# environment, which makes writing a sane, small CSS stylesheet 69.19 -# impossible. We squish all those IDs down to nothing. 69.20 - 69.21 -import os 69.22 -import sys 69.23 -import re 69.24 - 69.25 -angle_re = re.compile(r'([CE];)') 69.26 -unicode_re = re.compile(r'�([0-7][0-9A-F]);') 69.27 -fancyvrb_re = re.compile(r'id="fancyvrb\d+"', re.I) 69.28 -ligature_re = re.compile(r'ྰ([0-4]);') 69.29 - 69.30 -tmpsuffix = '.tmp.' + str(os.getpid()) 69.31 - 69.32 -def hide_angle(m): 69.33 - return m.group(1).lower() 69.34 - 69.35 -def fix_ascii(m): 69.36 - return chr(int(m.group(1), 16)) 69.37 - 69.38 -ligatures = ['ff', 'fi', 'fl', 'ffi', 'ffl'] 69.39 - 69.40 -def expand_ligature(m): 69.41 - return ligatures[int(m.group(1))] 69.42 - 69.43 -for name in sys.argv[1:]: 69.44 - tmpname = name + tmpsuffix 69.45 - ofp = file(tmpname, 'w') 69.46 - for line in file(name): 69.47 - line = angle_re.sub(hide_angle, line) 69.48 - line = unicode_re.sub(fix_ascii, line) 69.49 - line = ligature_re.sub(expand_ligature, line) 69.50 - line = fancyvrb_re.sub('id="fancyvrb"', line) 69.51 - ofp.write(line) 69.52 - ofp.close() 69.53 - os.rename(tmpname, name)
70.1 --- a/fr/hgbook.css Sun Aug 16 03:41:39 2009 +0200 70.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 70.3 @@ -1,441 +0,0 @@ 70.4 -body { 70.5 - font: 12px/1.5 Verdana, sans-serif; 70.6 - padding-top: 50px; 70.7 - padding-left: 80px; 70.8 - padding-right: 80px; 70.9 - padding-bottom: 90px; 70.10 -} 70.11 -.ptmr7t- { 70.12 - font-family: monospace; 70.13 -} 70.14 -.ptmr7t-x-x-172 { 70.15 - font-size: 172%; 70.16 - font-family: monospace; 70.17 -} 70.18 -.ptmr7t-x-x-120 { 70.19 - font-size: 120%; 70.20 -} 70.21 -.zpzccmry-x-x-120 { 70.22 - font-size: 120%; 70.23 - font-weight: bold; 70.24 - font-style: italic; 70.25 -} 70.26 -.zpzccmry-x-x-120 { 70.27 - font-weight: bold; 70.28 - font-style: italic; 70.29 -} 70.30 -.pcrr7tn- { 70.31 - font-family: monospace; 70.32 -} 70.33 -.ptmri7t- { 70.34 - font-style: italic; 70.35 -} 70.36 -.ptmr7t-x-x-50 { 70.37 - font-size: 50%; 70.38 - font-family: monospace; 70.39 -} 70.40 -.ptmb7t- { 70.41 - font-weight: bold; 70.42 -} 70.43 -.zptmcmr- { 70.44 - font-style: italic; 70.45 -} 70.46 -.zptmcmrm- { 70.47 - font-style: italic; 70.48 -} 70.49 -.zpzccmry- { 70.50 - font-weight: bold; 70.51 - font-style: italic; 70.52 -} 70.53 -.pcrb7t- { 70.54 - font-family: monospace; 70.55 - font-weight: bold; 70.56 -} 70.57 -.pcrro7t- { 70.58 - font-family: monospace; 70.59 - font-style: oblique; 70.60 -} 70.61 -p.noindent { 70.62 - text-indent: 0em; 70.63 - margin: 0em; 70.64 -} 70.65 -p.nopar { 70.66 - text-indent: 0em; 70.67 -} 70.68 -p.indent { 70.69 - text-indent: 1.5em; 70.70 - margin: 0em; 70.71 -} 70.72 -a img { 70.73 - border-top: 0; 70.74 - border-left: 0; 70.75 - border-right: 0; 70.76 -} 70.77 -center { 70.78 - margin-top: 1em; 70.79 - margin-bottom: 1em; 70.80 -} 70.81 -td center { 70.82 - margin-top: 0em; 70.83 - margin-bottom: 0em; 70.84 -} 70.85 -.Canvas { 70.86 - position: relative; 70.87 -} 70.88 -img.math { 70.89 - vertical-align: middle; 70.90 -} 70.91 -li p.indent { 70.92 - text-indent: 0em; 70.93 -} 70.94 -.enumerate1 { 70.95 - list-style-type: decimal; 70.96 -} 70.97 -.enumerate2 { 70.98 - list-style-type: lower-alpha; 70.99 -} 70.100 -.enumerate3 { 70.101 - list-style-type: lower-roman; 70.102 -} 70.103 -.enumerate4 { 70.104 - list-style-type: upper-alpha; 70.105 -} 70.106 -div.newtheorem { 70.107 - margin-bottom: 2em; 70.108 - margin-top: 2em; 70.109 -} 70.110 -.obeylines-h,.obeylines-v { 70.111 - white-space: nowrap; 70.112 -} 70.113 -div.obeylines-v p { 70.114 - margin-top: 0; 70.115 - margin-bottom: 0; 70.116 -} 70.117 -.overline { 70.118 - text-decoration: overline; 70.119 -} 70.120 -.overline img { 70.121 - border-top: 1px solid black; 70.122 -} 70.123 -td.displaylines { 70.124 - text-align: center; 70.125 - white-space: nowrap; 70.126 -} 70.127 -.centerline { 70.128 - text-align: center; 70.129 -} 70.130 -.rightline { 70.131 - text-align: right; 70.132 -} 70.133 -div.verbatim { 70.134 - font-family: monospace; 70.135 - white-space: nowrap; 70.136 -} 70.137 -table.verbatim { 70.138 - width: 100%; 70.139 -} 70.140 -.fbox { 70.141 - background: url(note.png) no-repeat #cec; 70.142 - padding-left: 65px; 70.143 - padding-top: 1em; 70.144 - padding-bottom: 1em; 70.145 - padding-right: 1em; 70.146 - text-indent: 0pt; 70.147 - border: dotted black 1px; 70.148 -} 70.149 -div.center div.fbox { 70.150 - text-align: center; 70.151 - clear: both; 70.152 - padding-left: 3.0pt; 70.153 - padding-right: 3.0pt; 70.154 - text-indent: 0pt; 70.155 - border: solid black 0.4pt; 70.156 -} 70.157 -table.minipage { 70.158 - width: 100%; 70.159 -} 70.160 -div.center, div.center div.center { 70.161 - text-align: center; 70.162 - margin-left: 1em; 70.163 - margin-right: 1em; 70.164 -} 70.165 -div.center div { 70.166 - text-align: left; 70.167 -} 70.168 -div.flushright, div.flushright div.flushright { 70.169 - text-align: right; 70.170 -} 70.171 -div.flushright div { 70.172 - text-align: left; 70.173 -} 70.174 -div.flushleft { 70.175 - text-align: left; 70.176 -} 70.177 -.underline { 70.178 - text-decoration: underline; 70.179 -} 70.180 -.underline img { 70.181 - border-bottom: 1px solid black; 70.182 - margin-bottom: 1pt; 70.183 -} 70.184 -.framebox-c, .framebox-l, .framebox-r { 70.185 - padding-left: 3.0pt; 70.186 - padding-right: 3.0pt; 70.187 - text-indent: 0pt; 70.188 - border: solid black 0.4pt; 70.189 -} 70.190 -.framebox-c { 70.191 - text-align: center; 70.192 -} 70.193 -.framebox-l { 70.194 - text-align: left; 70.195 -} 70.196 -.framebox-r { 70.197 - text-align: right; 70.198 -} 70.199 -span.thank-mark { 70.200 - vertical-align: super 70.201 -} 70.202 -span.footnote-mark sup.textsuperscript, span.footnote-mark a sup.textsuperscript { 70.203 - font-size: 80%; 70.204 -} 70.205 -div.tabular, div.center div.tabular { 70.206 - text-align: center; 70.207 - margin-top: 0.5em; 70.208 - margin-bottom: 0.5em; 70.209 -} 70.210 -table.tabular td p { 70.211 - margin-top: 0em; 70.212 -} 70.213 -table.tabular { 70.214 - margin-left: auto; 70.215 - margin-right: auto; 70.216 -} 70.217 -div.td00 { 70.218 - margin-left: 0pt; 70.219 - margin-right: 0pt; 70.220 -} 70.221 -div.td01 { 70.222 - margin-left: 0pt; 70.223 - margin-right: 5pt; 70.224 -} 70.225 -div.td10 { 70.226 - margin-left: 5pt; 70.227 - margin-right: 0pt; 70.228 -} 70.229 -div.td11 { 70.230 - margin-left: 5pt; 70.231 - margin-right: 5pt; 70.232 -} 70.233 -table[rules] { 70.234 - border-left: solid black 0.4pt; 70.235 - border-right: solid black 0.4pt; 70.236 -} 70.237 -td.td00 { 70.238 - padding-left: 0pt; 70.239 - padding-right: 0pt; 70.240 -} 70.241 -td.td01 { 70.242 - padding-left: 0pt; 70.243 - padding-right: 5pt; 70.244 -} 70.245 -td.td10 { 70.246 - padding-left: 5pt; 70.247 - padding-right: 0pt; 70.248 -} 70.249 -td.td11 { 70.250 - padding-left: 5pt; 70.251 - padding-right: 5pt; 70.252 -} 70.253 -table[rules] { 70.254 - border-left: solid black 0.4pt; 70.255 - border-right: solid black 0.4pt; 70.256 -} 70.257 -.hline hr, .cline hr { 70.258 - height : 1px; 70.259 - margin: 0px; 70.260 -} 70.261 -.tabbing-right { 70.262 - text-align: right; 70.263 -} 70.264 -span.TEX { 70.265 - letter-spacing: -0.125em; 70.266 -} 70.267 -span.TEX span.E { 70.268 - position: relative;top: 0.5ex;left: -0.0417em; 70.269 -} 70.270 -a span.TEX span.E { 70.271 - text-decoration: none; 70.272 -} 70.273 -span.LATEX span.A { 70.274 - position: relative; 70.275 - top: -0.5ex; 70.276 - left: -0.4em; 70.277 - font-size: 85%; 70.278 -} 70.279 -span.LATEX span.TEX { 70.280 - position: relative; 70.281 - left: -0.4em; 70.282 -} 70.283 -div.float img, div.float .caption { 70.284 - text-align: center; 70.285 -} 70.286 -div.figure img, div.figure .caption { 70.287 - text-align: center; 70.288 -} 70.289 -.marginpar { 70.290 - width: 20%; 70.291 - float: right; 70.292 - text-align: left; 70.293 - margin-left: auto; 70.294 - margin-top: 0.5em; 70.295 - font-size: 85%; 70.296 - text-decoration: underline; 70.297 -} 70.298 -.marginpar p { 70.299 - margin-top: 0.4em; 70.300 - margin-bottom: 0.4em; 70.301 -} 70.302 -table.equation { 70.303 - width: 100%; 70.304 -} 70.305 -.equation td { 70.306 - text-align: center; 70.307 -} 70.308 -td.equation { 70.309 - margin-top: 1em; 70.310 - margin-bottom: 1em; 70.311 -} 70.312 -td.equation-label { 70.313 - width: 5%; 70.314 - text-align: center; 70.315 -} 70.316 -td.eqnarray4 { 70.317 - width: 5%; 70.318 - white-space: normal; 70.319 -} 70.320 -td.eqnarray2 { 70.321 - width: 5%; 70.322 -} 70.323 -table.eqnarray-star, table.eqnarray { 70.324 - width: 100%; 70.325 -} 70.326 -div.eqnarray { 70.327 - text-align: center; 70.328 -} 70.329 -div.array { 70.330 - text-align: center; 70.331 -} 70.332 -div.pmatrix { 70.333 - text-align: center; 70.334 -} 70.335 -table.pmatrix { 70.336 - width: 100%; 70.337 -} 70.338 -span.pmatrix img { 70.339 - vertical-align: middle; 70.340 -} 70.341 -div.pmatrix { 70.342 - text-align: center; 70.343 -} 70.344 -table.pmatrix { 70.345 - width: 100%; 70.346 -} 70.347 -img.cdots { 70.348 - vertical-align: middle; 70.349 -} 70.350 -.partToc a, .partToc, .likepartToc a, .likepartToc { 70.351 - line-height: 200%; 70.352 - font-weight: bold; 70.353 - font-size: 110%; 70.354 -} 70.355 -.chapterToc a, .chapterToc, .likechapterToc a, .likechapterToc, .appendixToc a, .appendixToc { 70.356 - line-height: 200%; 70.357 - font-weight: bold; 70.358 -} 70.359 -.caption td.id { 70.360 - font-weight: bold; 70.361 - white-space: nowrap; 70.362 -} 70.363 -table.caption { 70.364 - text-align: center; 70.365 -} 70.366 -h1.partHead { 70.367 - text-align: center; 70.368 -} 70.369 -p.bibitem { 70.370 - text-indent: -2em; 70.371 - margin-left: 2em; 70.372 - margin-top: 0.6em; 70.373 - margin-bottom: 0.6em; 70.374 -} 70.375 -p.bibitem-p { 70.376 - text-indent: 0em; 70.377 - margin-left: 2em; 70.378 - margin-top: 0.6em; 70.379 - margin-bottom: 0.6em; 70.380 -} 70.381 -.paragraphHead, .likeparagraphHead { 70.382 - margin-top: 2em; 70.383 - font-weight: bold; 70.384 -} 70.385 -.subparagraphHead, .likesubparagraphHead { 70.386 - font-weight: bold; 70.387 -} 70.388 -.quote { 70.389 - margin-bottom: 0.25em; 70.390 - margin-top: 0.25em; 70.391 - margin-left: 1em; 70.392 - margin-right: 1em; 70.393 - text-align: justify; 70.394 -} 70.395 -.verse { 70.396 - white-space: nowrap; 70.397 - margin-left: 2em} 70.398 -div.maketitle { 70.399 - text-align: center; 70.400 -} 70.401 -h2.titleHead { 70.402 - text-align: center; 70.403 -} 70.404 -div.maketitle { 70.405 - margin-bottom: 2em; 70.406 -} 70.407 -div.author, div.date { 70.408 - text-align: center; 70.409 -} 70.410 -div.thanks { 70.411 - text-align: left; 70.412 - margin-left: 10%; 70.413 - font-size: 85%; 70.414 - font-style: italic; 70.415 -} 70.416 -div.author { 70.417 - white-space: nowrap; 70.418 -} 70.419 -.quotation { 70.420 - margin-bottom: 0.25em; 70.421 - margin-top: 0.25em; 70.422 - margin-left: 1em; 70.423 -} 70.424 -h1.partHead { 70.425 - text-align: center; 70.426 -} 70.427 -img.graphics { 70.428 - margin-left: 10%; 70.429 -} 70.430 -.figure { 70.431 - width: 100%; 70.432 -} 70.433 -P.fancyvrb { 70.434 - white-space: nowrap; 70.435 -} 70.436 -hr { 70.437 - border: 0; 70.438 - height: 1px; 70.439 -} 70.440 -div#fancyvrb { 70.441 - white-space: nowrap; 70.442 - background: #eee; 70.443 - padding: 1em; 70.444 -}
71.1 --- a/fr/hgext.tex Sun Aug 16 03:41:39 2009 +0200 71.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 71.3 @@ -1,429 +0,0 @@ 71.4 -\chapter{Adding functionality with extensions} 71.5 -\label{chap:hgext} 71.6 - 71.7 -While the core of Mercurial is quite complete from a functionality 71.8 -standpoint, it's deliberately shorn of fancy features. This approach 71.9 -of preserving simplicity keeps the software easy to deal with for both 71.10 -maintainers and users. 71.11 - 71.12 -However, Mercurial doesn't box you in with an inflexible command set: 71.13 -you can add features to it as \emph{extensions} (sometimes known as 71.14 -\emph{plugins}). We've already discussed a few of these extensions in 71.15 -earlier chapters. 71.16 -\begin{itemize} 71.17 -\item Section~\ref{sec:tour-merge:fetch} covers the \hgext{fetch} 71.18 - extension; this combines pulling new changes and merging them with 71.19 - local changes into a single command, \hgxcmd{fetch}{fetch}. 71.20 -\item In chapter~\ref{chap:hook}, we covered several extensions that 71.21 - are useful for hook-related functionality: \hgext{acl} adds access 71.22 - control lists; \hgext{bugzilla} adds integration with the Bugzilla 71.23 - bug tracking system; and \hgext{notify} sends notification emails on 71.24 - new changes. 71.25 -\item The Mercurial Queues patch management extension is so invaluable 71.26 - that it merits two chapters and an appendix all to itself. 71.27 - Chapter~\ref{chap:mq} covers the basics; 71.28 - chapter~\ref{chap:mq-collab} discusses advanced topics; and 71.29 - appendix~\ref{chap:mqref} goes into detail on each command. 71.30 -\end{itemize} 71.31 - 71.32 -In this chapter, we'll cover some of the other extensions that are 71.33 -available for Mercurial, and briefly touch on some of the machinery 71.34 -you'll need to know about if you want to write an extension of your 71.35 -own. 71.36 -\begin{itemize} 71.37 -\item In section~\ref{sec:hgext:inotify}, we'll discuss the 71.38 - possibility of \emph{huge} performance improvements using the 71.39 - \hgext{inotify} extension. 71.40 -\end{itemize} 71.41 - 71.42 -\section{Improve performance with the \hgext{inotify} extension} 71.43 -\label{sec:hgext:inotify} 71.44 - 71.45 -Are you interested in having some of the most common Mercurial 71.46 -operations run as much as a hundred times faster? Read on! 71.47 - 71.48 -Mercurial has great performance under normal circumstances. For 71.49 -example, when you run the \hgcmd{status} command, Mercurial has to 71.50 -scan almost every directory and file in your repository so that it can 71.51 -display file status. Many other Mercurial commands need to do the 71.52 -same work behind the scenes; for example, the \hgcmd{diff} command 71.53 -uses the status machinery to avoid doing an expensive comparison 71.54 -operation on files that obviously haven't changed. 71.55 - 71.56 -Because obtaining file status is crucial to good performance, the 71.57 -authors of Mercurial have optimised this code to within an inch of its 71.58 -life. However, there's no avoiding the fact that when you run 71.59 -\hgcmd{status}, Mercurial is going to have to perform at least one 71.60 -expensive system call for each managed file to determine whether it's 71.61 -changed since the last time Mercurial checked. For a sufficiently 71.62 -large repository, this can take a long time. 71.63 - 71.64 -To put a number on the magnitude of this effect, I created a 71.65 -repository containing 150,000 managed files. I timed \hgcmd{status} 71.66 -as taking ten seconds to run, even when \emph{none} of those files had 71.67 -been modified. 71.68 - 71.69 -Many modern operating systems contain a file notification facility. 71.70 -If a program signs up to an appropriate service, the operating system 71.71 -will notify it every time a file of interest is created, modified, or 71.72 -deleted. On Linux systems, the kernel component that does this is 71.73 -called \texttt{inotify}. 71.74 - 71.75 -Mercurial's \hgext{inotify} extension talks to the kernel's 71.76 -\texttt{inotify} component to optimise \hgcmd{status} commands. The 71.77 -extension has two components. A daemon sits in the background and 71.78 -receives notifications from the \texttt{inotify} subsystem. It also 71.79 -listens for connections from a regular Mercurial command. The 71.80 -extension modifies Mercurial's behaviour so that instead of scanning 71.81 -the filesystem, it queries the daemon. Since the daemon has perfect 71.82 -information about the state of the repository, it can respond with a 71.83 -result instantaneously, avoiding the need to scan every directory and 71.84 -file in the repository. 71.85 - 71.86 -Recall the ten seconds that I measured plain Mercurial as taking to 71.87 -run \hgcmd{status} on a 150,000 file repository. With the 71.88 -\hgext{inotify} extension enabled, the time dropped to 0.1~seconds, a 71.89 -factor of \emph{one hundred} faster. 71.90 - 71.91 -Before we continue, please pay attention to some caveats. 71.92 -\begin{itemize} 71.93 -\item The \hgext{inotify} extension is Linux-specific. Because it 71.94 - interfaces directly to the Linux kernel's \texttt{inotify} 71.95 - subsystem, it does not work on other operating systems. 71.96 -\item It should work on any Linux distribution that was released after 71.97 - early~2005. Older distributions are likely to have a kernel that 71.98 - lacks \texttt{inotify}, or a version of \texttt{glibc} that does not 71.99 - have the necessary interfacing support. 71.100 -\item Not all filesystems are suitable for use with the 71.101 - \hgext{inotify} extension. Network filesystems such as NFS are a 71.102 - non-starter, for example, particularly if you're running Mercurial 71.103 - on several systems, all mounting the same network filesystem. The 71.104 - kernel's \texttt{inotify} system has no way of knowing about changes 71.105 - made on another system. Most local filesystems (e.g.~ext3, XFS, 71.106 - ReiserFS) should work fine. 71.107 -\end{itemize} 71.108 - 71.109 -The \hgext{inotify} extension is not yet shipped with Mercurial as of 71.110 -May~2007, so it's a little more involved to set up than other 71.111 -extensions. But the performance improvement is worth it! 71.112 - 71.113 -The extension currently comes in two parts: a set of patches to the 71.114 -Mercurial source code, and a library of Python bindings to the 71.115 -\texttt{inotify} subsystem. 71.116 -\begin{note} 71.117 - There are \emph{two} Python \texttt{inotify} binding libraries. One 71.118 - of them is called \texttt{pyinotify}, and is packaged by some Linux 71.119 - distributions as \texttt{python-inotify}. This is \emph{not} the 71.120 - one you'll need, as it is too buggy and inefficient to be practical. 71.121 -\end{note} 71.122 -To get going, it's best to already have a functioning copy of 71.123 -Mercurial installed. 71.124 -\begin{note} 71.125 - If you follow the instructions below, you'll be \emph{replacing} and 71.126 - overwriting any existing installation of Mercurial that you might 71.127 - already have, using the latest ``bleeding edge'' Mercurial code. 71.128 - Don't say you weren't warned! 71.129 -\end{note} 71.130 -\begin{enumerate} 71.131 -\item Clone the Python \texttt{inotify} binding repository. Build and 71.132 - install it. 71.133 - \begin{codesample4} 71.134 - hg clone http://hg.kublai.com/python/inotify 71.135 - cd inotify 71.136 - python setup.py build --force 71.137 - sudo python setup.py install --skip-build 71.138 - \end{codesample4} 71.139 -\item Clone the \dirname{crew} Mercurial repository. Clone the 71.140 - \hgext{inotify} patch repository so that Mercurial Queues will be 71.141 - able to apply patches to your cope of the \dirname{crew} repository. 71.142 - \begin{codesample4} 71.143 - hg clone http://hg.intevation.org/mercurial/crew 71.144 - hg clone crew inotify 71.145 - hg clone http://hg.kublai.com/mercurial/patches/inotify inotify/.hg/patches 71.146 - \end{codesample4} 71.147 -\item Make sure that you have the Mercurial Queues extension, 71.148 - \hgext{mq}, enabled. If you've never used MQ, read 71.149 - section~\ref{sec:mq:start} to get started quickly. 71.150 -\item Go into the \dirname{inotify} repo, and apply all of the 71.151 - \hgext{inotify} patches using the \hgxopt{mq}{qpush}{-a} option to 71.152 - the \hgxcmd{mq}{qpush} command. 71.153 - \begin{codesample4} 71.154 - cd inotify 71.155 - hg qpush -a 71.156 - \end{codesample4} 71.157 - If you get an error message from \hgxcmd{mq}{qpush}, you should not 71.158 - continue. Instead, ask for help. 71.159 -\item Build and install the patched version of Mercurial. 71.160 - \begin{codesample4} 71.161 - python setup.py build --force 71.162 - sudo python setup.py install --skip-build 71.163 - \end{codesample4} 71.164 -\end{enumerate} 71.165 -Once you've build a suitably patched version of Mercurial, all you 71.166 -need to do to enable the \hgext{inotify} extension is add an entry to 71.167 -your \hgrc. 71.168 -\begin{codesample2} 71.169 - [extensions] 71.170 - inotify = 71.171 -\end{codesample2} 71.172 -When the \hgext{inotify} extension is enabled, Mercurial will 71.173 -automatically and transparently start the status daemon the first time 71.174 -you run a command that needs status in a repository. It runs one 71.175 -status daemon per repository. 71.176 - 71.177 -The status daemon is started silently, and runs in the background. If 71.178 -you look at a list of running processes after you've enabled the 71.179 -\hgext{inotify} extension and run a few commands in different 71.180 -repositories, you'll thus see a few \texttt{hg} processes sitting 71.181 -around, waiting for updates from the kernel and queries from 71.182 -Mercurial. 71.183 - 71.184 -The first time you run a Mercurial command in a repository when you 71.185 -have the \hgext{inotify} extension enabled, it will run with about the 71.186 -same performance as a normal Mercurial command. This is because the 71.187 -status daemon needs to perform a normal status scan so that it has a 71.188 -baseline against which to apply later updates from the kernel. 71.189 -However, \emph{every} subsequent command that does any kind of status 71.190 -check should be noticeably faster on repositories of even fairly 71.191 -modest size. Better yet, the bigger your repository is, the greater a 71.192 -performance advantage you'll see. The \hgext{inotify} daemon makes 71.193 -status operations almost instantaneous on repositories of all sizes! 71.194 - 71.195 -If you like, you can manually start a status daemon using the 71.196 -\hgxcmd{inotify}{inserve} command. This gives you slightly finer 71.197 -control over how the daemon ought to run. This command will of course 71.198 -only be available when the \hgext{inotify} extension is enabled. 71.199 - 71.200 -When you're using the \hgext{inotify} extension, you should notice 71.201 -\emph{no difference at all} in Mercurial's behaviour, with the sole 71.202 -exception of status-related commands running a whole lot faster than 71.203 -they used to. You should specifically expect that commands will not 71.204 -print different output; neither should they give different results. 71.205 -If either of these situations occurs, please report a bug. 71.206 - 71.207 -\section{Flexible diff support with the \hgext{extdiff} extension} 71.208 -\label{sec:hgext:extdiff} 71.209 - 71.210 -Mercurial's built-in \hgcmd{diff} command outputs plaintext unified 71.211 -diffs. 71.212 -\interaction{extdiff.diff} 71.213 -If you would like to use an external tool to display modifications, 71.214 -you'll want to use the \hgext{extdiff} extension. This will let you 71.215 -use, for example, a graphical diff tool. 71.216 - 71.217 -The \hgext{extdiff} extension is bundled with Mercurial, so it's easy 71.218 -to set up. In the \rcsection{extensions} section of your \hgrc, 71.219 -simply add a one-line entry to enable the extension. 71.220 -\begin{codesample2} 71.221 - [extensions] 71.222 - extdiff = 71.223 -\end{codesample2} 71.224 -This introduces a command named \hgxcmd{extdiff}{extdiff}, which by 71.225 -default uses your system's \command{diff} command to generate a 71.226 -unified diff in the same form as the built-in \hgcmd{diff} command. 71.227 -\interaction{extdiff.extdiff} 71.228 -The result won't be exactly the same as with the built-in \hgcmd{diff} 71.229 -variations, because the output of \command{diff} varies from one 71.230 -system to another, even when passed the same options. 71.231 - 71.232 -As the ``\texttt{making snapshot}'' lines of output above imply, the 71.233 -\hgxcmd{extdiff}{extdiff} command works by creating two snapshots of 71.234 -your source tree. The first snapshot is of the source revision; the 71.235 -second, of the target revision or working directory. The 71.236 -\hgxcmd{extdiff}{extdiff} command generates these snapshots in a 71.237 -temporary directory, passes the name of each directory to an external 71.238 -diff viewer, then deletes the temporary directory. For efficiency, it 71.239 -only snapshots the directories and files that have changed between the 71.240 -two revisions. 71.241 - 71.242 -Snapshot directory names have the same base name as your repository. 71.243 -If your repository path is \dirname{/quux/bar/foo}, then \dirname{foo} 71.244 -will be the name of each snapshot directory. Each snapshot directory 71.245 -name has its changeset ID appended, if appropriate. If a snapshot is 71.246 -of revision \texttt{a631aca1083f}, the directory will be named 71.247 -\dirname{foo.a631aca1083f}. A snapshot of the working directory won't 71.248 -have a changeset ID appended, so it would just be \dirname{foo} in 71.249 -this example. To see what this looks like in practice, look again at 71.250 -the \hgxcmd{extdiff}{extdiff} example above. Notice that the diff has 71.251 -the snapshot directory names embedded in its header. 71.252 - 71.253 -The \hgxcmd{extdiff}{extdiff} command accepts two important options. 71.254 -The \hgxopt{extdiff}{extdiff}{-p} option lets you choose a program to 71.255 -view differences with, instead of \command{diff}. With the 71.256 -\hgxopt{extdiff}{extdiff}{-o} option, you can change the options that 71.257 -\hgxcmd{extdiff}{extdiff} passes to the program (by default, these 71.258 -options are ``\texttt{-Npru}'', which only make sense if you're 71.259 -running \command{diff}). In other respects, the 71.260 -\hgxcmd{extdiff}{extdiff} command acts similarly to the built-in 71.261 -\hgcmd{diff} command: you use the same option names, syntax, and 71.262 -arguments to specify the revisions you want, the files you want, and 71.263 -so on. 71.264 - 71.265 -As an example, here's how to run the normal system \command{diff} 71.266 -command, getting it to generate context diffs (using the 71.267 -\cmdopt{diff}{-c} option) instead of unified diffs, and five lines of 71.268 -context instead of the default three (passing \texttt{5} as the 71.269 -argument to the \cmdopt{diff}{-C} option). 71.270 -\interaction{extdiff.extdiff-ctx} 71.271 - 71.272 -Launching a visual diff tool is just as easy. Here's how to launch 71.273 -the \command{kdiff3} viewer. 71.274 -\begin{codesample2} 71.275 - hg extdiff -p kdiff3 -o '' 71.276 -\end{codesample2} 71.277 - 71.278 -If your diff viewing command can't deal with directories, you can 71.279 -easily work around this with a little scripting. For an example of 71.280 -such scripting in action with the \hgext{mq} extension and the 71.281 -\command{interdiff} command, see 71.282 -section~\ref{mq-collab:tips:interdiff}. 71.283 - 71.284 -\subsection{Defining command aliases} 71.285 - 71.286 -It can be cumbersome to remember the options to both the 71.287 -\hgxcmd{extdiff}{extdiff} command and the diff viewer you want to use, 71.288 -so the \hgext{extdiff} extension lets you define \emph{new} commands 71.289 -that will invoke your diff viewer with exactly the right options. 71.290 - 71.291 -All you need to do is edit your \hgrc, and add a section named 71.292 -\rcsection{extdiff}. Inside this section, you can define multiple 71.293 -commands. Here's how to add a \texttt{kdiff3} command. Once you've 71.294 -defined this, you can type ``\texttt{hg kdiff3}'' and the 71.295 -\hgext{extdiff} extension will run \command{kdiff3} for you. 71.296 -\begin{codesample2} 71.297 - [extdiff] 71.298 - cmd.kdiff3 = 71.299 -\end{codesample2} 71.300 -If you leave the right hand side of the definition empty, as above, 71.301 -the \hgext{extdiff} extension uses the name of the command you defined 71.302 -as the name of the external program to run. But these names don't 71.303 -have to be the same. Here, we define a command named ``\texttt{hg 71.304 - wibble}'', which runs \command{kdiff3}. 71.305 -\begin{codesample2} 71.306 - [extdiff] 71.307 - cmd.wibble = kdiff3 71.308 -\end{codesample2} 71.309 - 71.310 -You can also specify the default options that you want to invoke your 71.311 -diff viewing program with. The prefix to use is ``\texttt{opts.}'', 71.312 -followed by the name of the command to which the options apply. This 71.313 -example defines a ``\texttt{hg vimdiff}'' command that runs the 71.314 -\command{vim} editor's \texttt{DirDiff} extension. 71.315 -\begin{codesample2} 71.316 - [extdiff] 71.317 - cmd.vimdiff = vim 71.318 - opts.vimdiff = -f '+next' '+execute "DirDiff" argv(0) argv(1)' 71.319 -\end{codesample2} 71.320 - 71.321 -\section{Cherrypicking changes with the \hgext{transplant} extension} 71.322 -\label{sec:hgext:transplant} 71.323 - 71.324 -Need to have a long chat with Brendan about this. 71.325 - 71.326 -\section{Send changes via email with the \hgext{patchbomb} extension} 71.327 -\label{sec:hgext:patchbomb} 71.328 - 71.329 -Many projects have a culture of ``change review'', in which people 71.330 -send their modifications to a mailing list for others to read and 71.331 -comment on before they commit the final version to a shared 71.332 -repository. Some projects have people who act as gatekeepers; they 71.333 -apply changes from other people to a repository to which those others 71.334 -don't have access. 71.335 - 71.336 -Mercurial makes it easy to send changes over email for review or 71.337 -application, via its \hgext{patchbomb} extension. The extension is so 71.338 -namd because changes are formatted as patches, and it's usual to send 71.339 -one changeset per email message. Sending a long series of changes by 71.340 -email is thus much like ``bombing'' the recipient's inbox, hence 71.341 -``patchbomb''. 71.342 - 71.343 -As usual, the basic configuration of the \hgext{patchbomb} extension 71.344 -takes just one or two lines in your \hgrc. 71.345 -\begin{codesample2} 71.346 - [extensions] 71.347 - patchbomb = 71.348 -\end{codesample2} 71.349 -Once you've enabled the extension, you will have a new command 71.350 -available, named \hgxcmd{patchbomb}{email}. 71.351 - 71.352 -The safest and best way to invoke the \hgxcmd{patchbomb}{email} 71.353 -command is to \emph{always} run it first with the 71.354 -\hgxopt{patchbomb}{email}{-n} option. This will show you what the 71.355 -command \emph{would} send, without actually sending anything. Once 71.356 -you've had a quick glance over the changes and verified that you are 71.357 -sending the right ones, you can rerun the same command, with the 71.358 -\hgxopt{patchbomb}{email}{-n} option removed. 71.359 - 71.360 -The \hgxcmd{patchbomb}{email} command accepts the same kind of 71.361 -revision syntax as every other Mercurial command. For example, this 71.362 -command will send every revision between 7 and \texttt{tip}, 71.363 -inclusive. 71.364 -\begin{codesample2} 71.365 - hg email -n 7:tip 71.366 -\end{codesample2} 71.367 -You can also specify a \emph{repository} to compare with. If you 71.368 -provide a repository but no revisions, the \hgxcmd{patchbomb}{email} 71.369 -command will send all revisions in the local repository that are not 71.370 -present in the remote repository. If you additionally specify 71.371 -revisions or a branch name (the latter using the 71.372 -\hgxopt{patchbomb}{email}{-b} option), this will constrain the 71.373 -revisions sent. 71.374 - 71.375 -It's perfectly safe to run the \hgxcmd{patchbomb}{email} command 71.376 -without the names of the people you want to send to: if you do this, 71.377 -it will just prompt you for those values interactively. (If you're 71.378 -using a Linux or Unix-like system, you should have enhanced 71.379 -\texttt{readline}-style editing capabilities when entering those 71.380 -headers, too, which is useful.) 71.381 - 71.382 -When you are sending just one revision, the \hgxcmd{patchbomb}{email} 71.383 -command will by default use the first line of the changeset 71.384 -description as the subject of the single email message it sends. 71.385 - 71.386 -If you send multiple revisions, the \hgxcmd{patchbomb}{email} command 71.387 -will usually send one message per changeset. It will preface the 71.388 -series with an introductory message, in which you should describe the 71.389 -purpose of the series of changes you're sending. 71.390 - 71.391 -\subsection{Changing the behaviour of patchbombs} 71.392 - 71.393 -Not every project has exactly the same conventions for sending changes 71.394 -in email; the \hgext{patchbomb} extension tries to accommodate a 71.395 -number of variations through command line options. 71.396 -\begin{itemize} 71.397 -\item You can write a subject for the introductory message on the 71.398 - command line using the \hgxopt{patchbomb}{email}{-s} option. This 71.399 - takes one argument, the text of the subject to use. 71.400 -\item To change the email address from which the messages originate, 71.401 - use the \hgxopt{patchbomb}{email}{-f} option. This takes one 71.402 - argument, the email address to use. 71.403 -\item The default behaviour is to send unified diffs (see 71.404 - section~\ref{sec:mq:patch} for a description of the format), one per 71.405 - message. You can send a binary bundle instead with the 71.406 - \hgxopt{patchbomb}{email}{-b} option. 71.407 -\item Unified diffs are normally prefaced with a metadata header. You 71.408 - can omit this, and send unadorned diffs, with the 71.409 - \hgxopt{patchbomb}{email}{--plain} option. 71.410 -\item Diffs are normally sent ``inline'', in the same body part as the 71.411 - description of a patch. This makes it easiest for the largest 71.412 - number of readers to quote and respond to parts of a diff, as some 71.413 - mail clients will only quote the first MIME body part in a message. 71.414 - If you'd prefer to send the description and the diff in separate 71.415 - body parts, use the \hgxopt{patchbomb}{email}{-a} option. 71.416 -\item Instead of sending mail messages, you can write them to an 71.417 - \texttt{mbox}-format mail folder using the 71.418 - \hgxopt{patchbomb}{email}{-m} option. That option takes one 71.419 - argument, the name of the file to write to. 71.420 -\item If you would like to add a \command{diffstat}-format summary to 71.421 - each patch, and one to the introductory message, use the 71.422 - \hgxopt{patchbomb}{email}{-d} option. The \command{diffstat} 71.423 - command displays a table containing the name of each file patched, 71.424 - the number of lines affected, and a histogram showing how much each 71.425 - file is modified. This gives readers a qualitative glance at how 71.426 - complex a patch is. 71.427 -\end{itemize} 71.428 - 71.429 -%%% Local Variables: 71.430 -%%% mode: latex 71.431 -%%% TeX-master: "00book" 71.432 -%%% End:
72.1 --- a/fr/hook.tex Sun Aug 16 03:41:39 2009 +0200 72.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 72.3 @@ -1,1413 +0,0 @@ 72.4 -\chapter{Handling repository events with hooks} 72.5 -\label{chap:hook} 72.6 - 72.7 -Mercurial offers a powerful mechanism to let you perform automated 72.8 -actions in response to events that occur in a repository. In some 72.9 -cases, you can even control Mercurial's response to those events. 72.10 - 72.11 -The name Mercurial uses for one of these actions is a \emph{hook}. 72.12 -Hooks are called ``triggers'' in some revision control systems, but 72.13 -the two names refer to the same idea. 72.14 - 72.15 -\section{An overview of hooks in Mercurial} 72.16 - 72.17 -Here is a brief list of the hooks that Mercurial supports. We will 72.18 -revisit each of these hooks in more detail later, in 72.19 -section~\ref{sec:hook:ref}. 72.20 - 72.21 -\begin{itemize} 72.22 -\item[\small\hook{changegroup}] This is run after a group of 72.23 - changesets has been brought into the repository from elsewhere. 72.24 -\item[\small\hook{commit}] This is run after a new changeset has been 72.25 - created in the local repository. 72.26 -\item[\small\hook{incoming}] This is run once for each new changeset 72.27 - that is brought into the repository from elsewhere. Notice the 72.28 - difference from \hook{changegroup}, which is run once per 72.29 - \emph{group} of changesets brought in. 72.30 -\item[\small\hook{outgoing}] This is run after a group of changesets 72.31 - has been transmitted from this repository. 72.32 -\item[\small\hook{prechangegroup}] This is run before starting to 72.33 - bring a group of changesets into the repository. 72.34 -\item[\small\hook{precommit}] Controlling. This is run before starting 72.35 - a commit. 72.36 -\item[\small\hook{preoutgoing}] Controlling. This is run before 72.37 - starting to transmit a group of changesets from this repository. 72.38 -\item[\small\hook{pretag}] Controlling. This is run before creating a tag. 72.39 -\item[\small\hook{pretxnchangegroup}] Controlling. This is run after a 72.40 - group of changesets has been brought into the local repository from 72.41 - another, but before the transaction completes that will make the 72.42 - changes permanent in the repository. 72.43 -\item[\small\hook{pretxncommit}] Controlling. This is run after a new 72.44 - changeset has been created in the local repository, but before the 72.45 - transaction completes that will make it permanent. 72.46 -\item[\small\hook{preupdate}] Controlling. This is run before starting 72.47 - an update or merge of the working directory. 72.48 -\item[\small\hook{tag}] This is run after a tag is created. 72.49 -\item[\small\hook{update}] This is run after an update or merge of the 72.50 - working directory has finished. 72.51 -\end{itemize} 72.52 -Each of the hooks whose description begins with the word 72.53 -``Controlling'' has the ability to determine whether an activity can 72.54 -proceed. If the hook succeeds, the activity may proceed; if it fails, 72.55 -the activity is either not permitted or undone, depending on the hook. 72.56 - 72.57 -\section{Hooks and security} 72.58 - 72.59 -\subsection{Hooks are run with your privileges} 72.60 - 72.61 -When you run a Mercurial command in a repository, and the command 72.62 -causes a hook to run, that hook runs on \emph{your} system, under 72.63 -\emph{your} user account, with \emph{your} privilege level. Since 72.64 -hooks are arbitrary pieces of executable code, you should treat them 72.65 -with an appropriate level of suspicion. Do not install a hook unless 72.66 -you are confident that you know who created it and what it does. 72.67 - 72.68 -In some cases, you may be exposed to hooks that you did not install 72.69 -yourself. If you work with Mercurial on an unfamiliar system, 72.70 -Mercurial will run hooks defined in that system's global \hgrc\ file. 72.71 - 72.72 -If you are working with a repository owned by another user, Mercurial 72.73 -can run hooks defined in that user's repository, but it will still run 72.74 -them as ``you''. For example, if you \hgcmd{pull} from that 72.75 -repository, and its \sfilename{.hg/hgrc} defines a local 72.76 -\hook{outgoing} hook, that hook will run under your user account, even 72.77 -though you don't own that repository. 72.78 - 72.79 -\begin{note} 72.80 - This only applies if you are pulling from a repository on a local or 72.81 - network filesystem. If you're pulling over http or ssh, any 72.82 - \hook{outgoing} hook will run under whatever account is executing 72.83 - the server process, on the server. 72.84 -\end{note} 72.85 - 72.86 -XXX To see what hooks are defined in a repository, use the 72.87 -\hgcmdargs{config}{hooks} command. If you are working in one 72.88 -repository, but talking to another that you do not own (e.g.~using 72.89 -\hgcmd{pull} or \hgcmd{incoming}), remember that it is the other 72.90 -repository's hooks you should be checking, not your own. 72.91 - 72.92 -\subsection{Hooks do not propagate} 72.93 - 72.94 -In Mercurial, hooks are not revision controlled, and do not propagate 72.95 -when you clone, or pull from, a repository. The reason for this is 72.96 -simple: a hook is a completely arbitrary piece of executable code. It 72.97 -runs under your user identity, with your privilege level, on your 72.98 -machine. 72.99 - 72.100 -It would be extremely reckless for any distributed revision control 72.101 -system to implement revision-controlled hooks, as this would offer an 72.102 -easily exploitable way to subvert the accounts of users of the 72.103 -revision control system. 72.104 - 72.105 -Since Mercurial does not propagate hooks, if you are collaborating 72.106 -with other people on a common project, you should not assume that they 72.107 -are using the same Mercurial hooks as you are, or that theirs are 72.108 -correctly configured. You should document the hooks you expect people 72.109 -to use. 72.110 - 72.111 -In a corporate intranet, this is somewhat easier to control, as you 72.112 -can for example provide a ``standard'' installation of Mercurial on an 72.113 -NFS filesystem, and use a site-wide \hgrc\ file to define hooks that 72.114 -all users will see. However, this too has its limits; see below. 72.115 - 72.116 -\subsection{Hooks can be overridden} 72.117 - 72.118 -Mercurial allows you to override a hook definition by redefining the 72.119 -hook. You can disable it by setting its value to the empty string, or 72.120 -change its behaviour as you wish. 72.121 - 72.122 -If you deploy a system-~or site-wide \hgrc\ file that defines some 72.123 -hooks, you should thus understand that your users can disable or 72.124 -override those hooks. 72.125 - 72.126 -\subsection{Ensuring that critical hooks are run} 72.127 - 72.128 -Sometimes you may want to enforce a policy that you do not want others 72.129 -to be able to work around. For example, you may have a requirement 72.130 -that every changeset must pass a rigorous set of tests. Defining this 72.131 -requirement via a hook in a site-wide \hgrc\ won't work for remote 72.132 -users on laptops, and of course local users can subvert it at will by 72.133 -overriding the hook. 72.134 - 72.135 -Instead, you can set up your policies for use of Mercurial so that 72.136 -people are expected to propagate changes through a well-known 72.137 -``canonical'' server that you have locked down and configured 72.138 -appropriately. 72.139 - 72.140 -One way to do this is via a combination of social engineering and 72.141 -technology. Set up a restricted-access account; users can push 72.142 -changes over the network to repositories managed by this account, but 72.143 -they cannot log into the account and run normal shell commands. In 72.144 -this scenario, a user can commit a changeset that contains any old 72.145 -garbage they want. 72.146 - 72.147 -When someone pushes a changeset to the server that everyone pulls 72.148 -from, the server will test the changeset before it accepts it as 72.149 -permanent, and reject it if it fails to pass the test suite. If 72.150 -people only pull changes from this filtering server, it will serve to 72.151 -ensure that all changes that people pull have been automatically 72.152 -vetted. 72.153 - 72.154 -\section{Care with \texttt{pretxn} hooks in a shared-access repository} 72.155 - 72.156 -If you want to use hooks to do some automated work in a repository 72.157 -that a number of people have shared access to, you need to be careful 72.158 -in how you do this. 72.159 - 72.160 -Mercurial only locks a repository when it is writing to the 72.161 -repository, and only the parts of Mercurial that write to the 72.162 -repository pay attention to locks. Write locks are necessary to 72.163 -prevent multiple simultaneous writers from scribbling on each other's 72.164 -work, corrupting the repository. 72.165 - 72.166 -Because Mercurial is careful with the order in which it reads and 72.167 -writes data, it does not need to acquire a lock when it wants to read 72.168 -data from the repository. The parts of Mercurial that read from the 72.169 -repository never pay attention to locks. This lockless reading scheme 72.170 -greatly increases performance and concurrency. 72.171 - 72.172 -With great performance comes a trade-off, though, one which has the 72.173 -potential to cause you trouble unless you're aware of it. To describe 72.174 -this requires a little detail about how Mercurial adds changesets to a 72.175 -repository and reads those changes. 72.176 - 72.177 -When Mercurial \emph{writes} metadata, it writes it straight into the 72.178 -destination file. It writes file data first, then manifest data 72.179 -(which contains pointers to the new file data), then changelog data 72.180 -(which contains pointers to the new manifest data). Before the first 72.181 -write to each file, it stores a record of where the end of the file 72.182 -was in its transaction log. If the transaction must be rolled back, 72.183 -Mercurial simply truncates each file back to the size it was before the 72.184 -transaction began. 72.185 - 72.186 -When Mercurial \emph{reads} metadata, it reads the changelog first, 72.187 -then everything else. Since a reader will only access parts of the 72.188 -manifest or file metadata that it can see in the changelog, it can 72.189 -never see partially written data. 72.190 - 72.191 -Some controlling hooks (\hook{pretxncommit} and 72.192 -\hook{pretxnchangegroup}) run when a transaction is almost complete. 72.193 -All of the metadata has been written, but Mercurial can still roll the 72.194 -transaction back and cause the newly-written data to disappear. 72.195 - 72.196 -If one of these hooks runs for long, it opens a window of time during 72.197 -which a reader can see the metadata for changesets that are not yet 72.198 -permanent, and should not be thought of as ``really there''. The 72.199 -longer the hook runs, the longer that window is open. 72.200 - 72.201 -\subsection{The problem illustrated} 72.202 - 72.203 -In principle, a good use for the \hook{pretxnchangegroup} hook would 72.204 -be to automatically build and test incoming changes before they are 72.205 -accepted into a central repository. This could let you guarantee that 72.206 -nobody can push changes to this repository that ``break the build''. 72.207 -But if a client can pull changes while they're being tested, the 72.208 -usefulness of the test is zero; an unsuspecting someone can pull 72.209 -untested changes, potentially breaking their build. 72.210 - 72.211 -The safest technological answer to this challenge is to set up such a 72.212 -``gatekeeper'' repository as \emph{unidirectional}. Let it take 72.213 -changes pushed in from the outside, but do not allow anyone to pull 72.214 -changes from it (use the \hook{preoutgoing} hook to lock it down). 72.215 -Configure a \hook{changegroup} hook so that if a build or test 72.216 -succeeds, the hook will push the new changes out to another repository 72.217 -that people \emph{can} pull from. 72.218 - 72.219 -In practice, putting a centralised bottleneck like this in place is 72.220 -not often a good idea, and transaction visibility has nothing to do 72.221 -with the problem. As the size of a project---and the time it takes to 72.222 -build and test---grows, you rapidly run into a wall with this ``try 72.223 -before you buy'' approach, where you have more changesets to test than 72.224 -time in which to deal with them. The inevitable result is frustration 72.225 -on the part of all involved. 72.226 - 72.227 -An approach that scales better is to get people to build and test 72.228 -before they push, then run automated builds and tests centrally 72.229 -\emph{after} a push, to be sure all is well. The advantage of this 72.230 -approach is that it does not impose a limit on the rate at which the 72.231 -repository can accept changes. 72.232 - 72.233 -\section{A short tutorial on using hooks} 72.234 -\label{sec:hook:simple} 72.235 - 72.236 -It is easy to write a Mercurial hook. Let's start with a hook that 72.237 -runs when you finish a \hgcmd{commit}, and simply prints the hash of 72.238 -the changeset you just created. The hook is called \hook{commit}. 72.239 - 72.240 -\begin{figure}[ht] 72.241 - \interaction{hook.simple.init} 72.242 - \caption{A simple hook that runs when a changeset is committed} 72.243 - \label{ex:hook:init} 72.244 -\end{figure} 72.245 - 72.246 -All hooks follow the pattern in example~\ref{ex:hook:init}. You add 72.247 -an entry to the \rcsection{hooks} section of your \hgrc. On the left 72.248 -is the name of the event to trigger on; on the right is the action to 72.249 -take. As you can see, you can run an arbitrary shell command in a 72.250 -hook. Mercurial passes extra information to the hook using 72.251 -environment variables (look for \envar{HG\_NODE} in the example). 72.252 - 72.253 -\subsection{Performing multiple actions per event} 72.254 - 72.255 -Quite often, you will want to define more than one hook for a 72.256 -particular kind of event, as shown in example~\ref{ex:hook:ext}. 72.257 -Mercurial lets you do this by adding an \emph{extension} to the end of 72.258 -a hook's name. You extend a hook's name by giving the name of the 72.259 -hook, followed by a full stop (the ``\texttt{.}'' character), followed 72.260 -by some more text of your choosing. For example, Mercurial will run 72.261 -both \texttt{commit.foo} and \texttt{commit.bar} when the 72.262 -\texttt{commit} event occurs. 72.263 - 72.264 -\begin{figure}[ht] 72.265 - \interaction{hook.simple.ext} 72.266 - \caption{Defining a second \hook{commit} hook} 72.267 - \label{ex:hook:ext} 72.268 -\end{figure} 72.269 - 72.270 -To give a well-defined order of execution when there are multiple 72.271 -hooks defined for an event, Mercurial sorts hooks by extension, and 72.272 -executes the hook commands in this sorted order. In the above 72.273 -example, it will execute \texttt{commit.bar} before 72.274 -\texttt{commit.foo}, and \texttt{commit} before both. 72.275 - 72.276 -It is a good idea to use a somewhat descriptive extension when you 72.277 -define a new hook. This will help you to remember what the hook was 72.278 -for. If the hook fails, you'll get an error message that contains the 72.279 -hook name and extension, so using a descriptive extension could give 72.280 -you an immediate hint as to why the hook failed (see 72.281 -section~\ref{sec:hook:perm} for an example). 72.282 - 72.283 -\subsection{Controlling whether an activity can proceed} 72.284 -\label{sec:hook:perm} 72.285 - 72.286 -In our earlier examples, we used the \hook{commit} hook, which is 72.287 -run after a commit has completed. This is one of several Mercurial 72.288 -hooks that run after an activity finishes. Such hooks have no way of 72.289 -influencing the activity itself. 72.290 - 72.291 -Mercurial defines a number of events that occur before an activity 72.292 -starts; or after it starts, but before it finishes. Hooks that 72.293 -trigger on these events have the added ability to choose whether the 72.294 -activity can continue, or will abort. 72.295 - 72.296 -The \hook{pretxncommit} hook runs after a commit has all but 72.297 -completed. In other words, the metadata representing the changeset 72.298 -has been written out to disk, but the transaction has not yet been 72.299 -allowed to complete. The \hook{pretxncommit} hook has the ability to 72.300 -decide whether the transaction can complete, or must be rolled back. 72.301 - 72.302 -If the \hook{pretxncommit} hook exits with a status code of zero, the 72.303 -transaction is allowed to complete; the commit finishes; and the 72.304 -\hook{commit} hook is run. If the \hook{pretxncommit} hook exits with 72.305 -a non-zero status code, the transaction is rolled back; the metadata 72.306 -representing the changeset is erased; and the \hook{commit} hook is 72.307 -not run. 72.308 - 72.309 -\begin{figure}[ht] 72.310 - \interaction{hook.simple.pretxncommit} 72.311 - \caption{Using the \hook{pretxncommit} hook to control commits} 72.312 - \label{ex:hook:pretxncommit} 72.313 -\end{figure} 72.314 - 72.315 -The hook in example~\ref{ex:hook:pretxncommit} checks that a commit 72.316 -comment contains a bug ID. If it does, the commit can complete. If 72.317 -not, the commit is rolled back. 72.318 - 72.319 -\section{Writing your own hooks} 72.320 - 72.321 -When you are writing a hook, you might find it useful to run Mercurial 72.322 -either with the \hggopt{-v} option, or the \rcitem{ui}{verbose} config 72.323 -item set to ``true''. When you do so, Mercurial will print a message 72.324 -before it calls each hook. 72.325 - 72.326 -\subsection{Choosing how your hook should run} 72.327 -\label{sec:hook:lang} 72.328 - 72.329 -You can write a hook either as a normal program---typically a shell 72.330 -script---or as a Python function that is executed within the Mercurial 72.331 -process. 72.332 - 72.333 -Writing a hook as an external program has the advantage that it 72.334 -requires no knowledge of Mercurial's internals. You can call normal 72.335 -Mercurial commands to get any added information you need. The 72.336 -trade-off is that external hooks are slower than in-process hooks. 72.337 - 72.338 -An in-process Python hook has complete access to the Mercurial API, 72.339 -and does not ``shell out'' to another process, so it is inherently 72.340 -faster than an external hook. It is also easier to obtain much of the 72.341 -information that a hook requires by using the Mercurial API than by 72.342 -running Mercurial commands. 72.343 - 72.344 -If you are comfortable with Python, or require high performance, 72.345 -writing your hooks in Python may be a good choice. However, when you 72.346 -have a straightforward hook to write and you don't need to care about 72.347 -performance (probably the majority of hooks), a shell script is 72.348 -perfectly fine. 72.349 - 72.350 -\subsection{Hook parameters} 72.351 -\label{sec:hook:param} 72.352 - 72.353 -Mercurial calls each hook with a set of well-defined parameters. In 72.354 -Python, a parameter is passed as a keyword argument to your hook 72.355 -function. For an external program, a parameter is passed as an 72.356 -environment variable. 72.357 - 72.358 -Whether your hook is written in Python or as a shell script, the 72.359 -hook-specific parameter names and values will be the same. A boolean 72.360 -parameter will be represented as a boolean value in Python, but as the 72.361 -number 1 (for ``true'') or 0 (for ``false'') as an environment 72.362 -variable for an external hook. If a hook parameter is named 72.363 -\texttt{foo}, the keyword argument for a Python hook will also be 72.364 -named \texttt{foo}, while the environment variable for an external 72.365 -hook will be named \texttt{HG\_FOO}. 72.366 - 72.367 -\subsection{Hook return values and activity control} 72.368 - 72.369 -A hook that executes successfully must exit with a status of zero if 72.370 -external, or return boolean ``false'' if in-process. Failure is 72.371 -indicated with a non-zero exit status from an external hook, or an 72.372 -in-process hook returning boolean ``true''. If an in-process hook 72.373 -raises an exception, the hook is considered to have failed. 72.374 - 72.375 -For a hook that controls whether an activity can proceed, zero/false 72.376 -means ``allow'', while non-zero/true/exception means ``deny''. 72.377 - 72.378 -\subsection{Writing an external hook} 72.379 - 72.380 -When you define an external hook in your \hgrc\ and the hook is run, 72.381 -its value is passed to your shell, which interprets it. This means 72.382 -that you can use normal shell constructs in the body of the hook. 72.383 - 72.384 -An executable hook is always run with its current directory set to a 72.385 -repository's root directory. 72.386 - 72.387 -Each hook parameter is passed in as an environment variable; the name 72.388 -is upper-cased, and prefixed with the string ``\texttt{HG\_}''. 72.389 - 72.390 -With the exception of hook parameters, Mercurial does not set or 72.391 -modify any environment variables when running a hook. This is useful 72.392 -to remember if you are writing a site-wide hook that may be run by a 72.393 -number of different users with differing environment variables set. 72.394 -In multi-user situations, you should not rely on environment variables 72.395 -being set to the values you have in your environment when testing the 72.396 -hook. 72.397 - 72.398 -\subsection{Telling Mercurial to use an in-process hook} 72.399 - 72.400 -The \hgrc\ syntax for defining an in-process hook is slightly 72.401 -different than for an executable hook. The value of the hook must 72.402 -start with the text ``\texttt{python:}'', and continue with the 72.403 -fully-qualified name of a callable object to use as the hook's value. 72.404 - 72.405 -The module in which a hook lives is automatically imported when a hook 72.406 -is run. So long as you have the module name and \envar{PYTHONPATH} 72.407 -right, it should ``just work''. 72.408 - 72.409 -The following \hgrc\ example snippet illustrates the syntax and 72.410 -meaning of the notions we just described. 72.411 -\begin{codesample2} 72.412 - [hooks] 72.413 - commit.example = python:mymodule.submodule.myhook 72.414 -\end{codesample2} 72.415 -When Mercurial runs the \texttt{commit.example} hook, it imports 72.416 -\texttt{mymodule.submodule}, looks for the callable object named 72.417 -\texttt{myhook}, and calls it. 72.418 - 72.419 -\subsection{Writing an in-process hook} 72.420 - 72.421 -The simplest in-process hook does nothing, but illustrates the basic 72.422 -shape of the hook API: 72.423 -\begin{codesample2} 72.424 - def myhook(ui, repo, **kwargs): 72.425 - pass 72.426 -\end{codesample2} 72.427 -The first argument to a Python hook is always a 72.428 -\pymodclass{mercurial.ui}{ui} object. The second is a repository object; 72.429 -at the moment, it is always an instance of 72.430 -\pymodclass{mercurial.localrepo}{localrepository}. Following these two 72.431 -arguments are other keyword arguments. Which ones are passed in 72.432 -depends on the hook being called, but a hook can ignore arguments it 72.433 -doesn't care about by dropping them into a keyword argument dict, as 72.434 -with \texttt{**kwargs} above. 72.435 - 72.436 -\section{Some hook examples} 72.437 - 72.438 -\subsection{Writing meaningful commit messages} 72.439 - 72.440 -It's hard to imagine a useful commit message being very short. The 72.441 -simple \hook{pretxncommit} hook of figure~\ref{ex:hook:msglen.go} 72.442 -will prevent you from committing a changeset with a message that is 72.443 -less than ten bytes long. 72.444 - 72.445 -\begin{figure}[ht] 72.446 - \interaction{hook.msglen.go} 72.447 - \caption{A hook that forbids overly short commit messages} 72.448 - \label{ex:hook:msglen.go} 72.449 -\end{figure} 72.450 - 72.451 -\subsection{Checking for trailing whitespace} 72.452 - 72.453 -An interesting use of a commit-related hook is to help you to write 72.454 -cleaner code. A simple example of ``cleaner code'' is the dictum that 72.455 -a change should not add any new lines of text that contain ``trailing 72.456 -whitespace''. Trailing whitespace is a series of space and tab 72.457 -characters at the end of a line of text. In most cases, trailing 72.458 -whitespace is unnecessary, invisible noise, but it is occasionally 72.459 -problematic, and people often prefer to get rid of it. 72.460 - 72.461 -You can use either the \hook{precommit} or \hook{pretxncommit} hook to 72.462 -tell whether you have a trailing whitespace problem. If you use the 72.463 -\hook{precommit} hook, the hook will not know which files you are 72.464 -committing, so it will have to check every modified file in the 72.465 -repository for trailing white space. If you want to commit a change 72.466 -to just the file \filename{foo}, but the file \filename{bar} contains 72.467 -trailing whitespace, doing a check in the \hook{precommit} hook will 72.468 -prevent you from committing \filename{foo} due to the problem with 72.469 -\filename{bar}. This doesn't seem right. 72.470 - 72.471 -Should you choose the \hook{pretxncommit} hook, the check won't occur 72.472 -until just before the transaction for the commit completes. This will 72.473 -allow you to check for problems only the exact files that are being 72.474 -committed. However, if you entered the commit message interactively 72.475 -and the hook fails, the transaction will roll back; you'll have to 72.476 -re-enter the commit message after you fix the trailing whitespace and 72.477 -run \hgcmd{commit} again. 72.478 - 72.479 -\begin{figure}[ht] 72.480 - \interaction{hook.ws.simple} 72.481 - \caption{A simple hook that checks for trailing whitespace} 72.482 - \label{ex:hook:ws.simple} 72.483 -\end{figure} 72.484 - 72.485 -Figure~\ref{ex:hook:ws.simple} introduces a simple \hook{pretxncommit} 72.486 -hook that checks for trailing whitespace. This hook is short, but not 72.487 -very helpful. It exits with an error status if a change adds a line 72.488 -with trailing whitespace to any file, but does not print any 72.489 -information that might help us to identify the offending file or 72.490 -line. It also has the nice property of not paying attention to 72.491 -unmodified lines; only lines that introduce new trailing whitespace 72.492 -cause problems. 72.493 - 72.494 -\begin{figure}[ht] 72.495 - \interaction{hook.ws.better} 72.496 - \caption{A better trailing whitespace hook} 72.497 - \label{ex:hook:ws.better} 72.498 -\end{figure} 72.499 - 72.500 -The example of figure~\ref{ex:hook:ws.better} is much more complex, 72.501 -but also more useful. It parses a unified diff to see if any lines 72.502 -add trailing whitespace, and prints the name of the file and the line 72.503 -number of each such occurrence. Even better, if the change adds 72.504 -trailing whitespace, this hook saves the commit comment and prints the 72.505 -name of the save file before exiting and telling Mercurial to roll the 72.506 -transaction back, so you can use 72.507 -\hgcmdargs{commit}{\hgopt{commit}{-l}~\emph{filename}} to reuse the 72.508 -saved commit message once you've corrected the problem. 72.509 - 72.510 -As a final aside, note in figure~\ref{ex:hook:ws.better} the use of 72.511 -\command{perl}'s in-place editing feature to get rid of trailing 72.512 -whitespace from a file. This is concise and useful enough that I will 72.513 -reproduce it here. 72.514 -\begin{codesample2} 72.515 - perl -pi -e 's,\textbackslash{}s+\$,,' filename 72.516 -\end{codesample2} 72.517 - 72.518 -\section{Bundled hooks} 72.519 - 72.520 -Mercurial ships with several bundled hooks. You can find them in the 72.521 -\dirname{hgext} directory of a Mercurial source tree. If you are 72.522 -using a Mercurial binary package, the hooks will be located in the 72.523 -\dirname{hgext} directory of wherever your package installer put 72.524 -Mercurial. 72.525 - 72.526 -\subsection{\hgext{acl}---access control for parts of a repository} 72.527 - 72.528 -The \hgext{acl} extension lets you control which remote users are 72.529 -allowed to push changesets to a networked server. You can protect any 72.530 -portion of a repository (including the entire repo), so that a 72.531 -specific remote user can push changes that do not affect the protected 72.532 -portion. 72.533 - 72.534 -This extension implements access control based on the identity of the 72.535 -user performing a push, \emph{not} on who committed the changesets 72.536 -they're pushing. It makes sense to use this hook only if you have a 72.537 -locked-down server environment that authenticates remote users, and 72.538 -you want to be sure that only specific users are allowed to push 72.539 -changes to that server. 72.540 - 72.541 -\subsubsection{Configuring the \hook{acl} hook} 72.542 - 72.543 -In order to manage incoming changesets, the \hgext{acl} hook must be 72.544 -used as a \hook{pretxnchangegroup} hook. This lets it see which files 72.545 -are modified by each incoming changeset, and roll back a group of 72.546 -changesets if they modify ``forbidden'' files. Example: 72.547 -\begin{codesample2} 72.548 - [hooks] 72.549 - pretxnchangegroup.acl = python:hgext.acl.hook 72.550 -\end{codesample2} 72.551 - 72.552 -The \hgext{acl} extension is configured using three sections. 72.553 - 72.554 -The \rcsection{acl} section has only one entry, \rcitem{acl}{sources}, 72.555 -which lists the sources of incoming changesets that the hook should 72.556 -pay attention to. You don't normally need to configure this section. 72.557 -\begin{itemize} 72.558 -\item[\rcitem{acl}{serve}] Control incoming changesets that are arriving 72.559 - from a remote repository over http or ssh. This is the default 72.560 - value of \rcitem{acl}{sources}, and usually the only setting you'll 72.561 - need for this configuration item. 72.562 -\item[\rcitem{acl}{pull}] Control incoming changesets that are 72.563 - arriving via a pull from a local repository. 72.564 -\item[\rcitem{acl}{push}] Control incoming changesets that are 72.565 - arriving via a push from a local repository. 72.566 -\item[\rcitem{acl}{bundle}] Control incoming changesets that are 72.567 - arriving from another repository via a bundle. 72.568 -\end{itemize} 72.569 - 72.570 -The \rcsection{acl.allow} section controls the users that are allowed to 72.571 -add changesets to the repository. If this section is not present, all 72.572 -users that are not explicitly denied are allowed. If this section is 72.573 -present, all users that are not explicitly allowed are denied (so an 72.574 -empty section means that all users are denied). 72.575 - 72.576 -The \rcsection{acl.deny} section determines which users are denied 72.577 -from adding changesets to the repository. If this section is not 72.578 -present or is empty, no users are denied. 72.579 - 72.580 -The syntaxes for the \rcsection{acl.allow} and \rcsection{acl.deny} 72.581 -sections are identical. On the left of each entry is a glob pattern 72.582 -that matches files or directories, relative to the root of the 72.583 -repository; on the right, a user name. 72.584 - 72.585 -In the following example, the user \texttt{docwriter} can only push 72.586 -changes to the \dirname{docs} subtree of the repository, while 72.587 -\texttt{intern} can push changes to any file or directory except 72.588 -\dirname{source/sensitive}. 72.589 -\begin{codesample2} 72.590 - [acl.allow] 72.591 - docs/** = docwriter 72.592 - 72.593 - [acl.deny] 72.594 - source/sensitive/** = intern 72.595 -\end{codesample2} 72.596 - 72.597 -\subsubsection{Testing and troubleshooting} 72.598 - 72.599 -If you want to test the \hgext{acl} hook, run it with Mercurial's 72.600 -debugging output enabled. Since you'll probably be running it on a 72.601 -server where it's not convenient (or sometimes possible) to pass in 72.602 -the \hggopt{--debug} option, don't forget that you can enable 72.603 -debugging output in your \hgrc: 72.604 -\begin{codesample2} 72.605 - [ui] 72.606 - debug = true 72.607 -\end{codesample2} 72.608 -With this enabled, the \hgext{acl} hook will print enough information 72.609 -to let you figure out why it is allowing or forbidding pushes from 72.610 -specific users. 72.611 - 72.612 -\subsection{\hgext{bugzilla}---integration with Bugzilla} 72.613 - 72.614 -The \hgext{bugzilla} extension adds a comment to a Bugzilla bug 72.615 -whenever it finds a reference to that bug ID in a commit comment. You 72.616 -can install this hook on a shared server, so that any time a remote 72.617 -user pushes changes to this server, the hook gets run. 72.618 - 72.619 -It adds a comment to the bug that looks like this (you can configure 72.620 -the contents of the comment---see below): 72.621 -\begin{codesample2} 72.622 - Changeset aad8b264143a, made by Joe User <joe.user@domain.com> in 72.623 - the frobnitz repository, refers to this bug. 72.624 - 72.625 - For complete details, see 72.626 - http://hg.domain.com/frobnitz?cmd=changeset;node=aad8b264143a 72.627 - 72.628 - Changeset description: 72.629 - Fix bug 10483 by guarding against some NULL pointers 72.630 -\end{codesample2} 72.631 -The value of this hook is that it automates the process of updating a 72.632 -bug any time a changeset refers to it. If you configure the hook 72.633 -properly, it makes it easy for people to browse straight from a 72.634 -Bugzilla bug to a changeset that refers to that bug. 72.635 - 72.636 -You can use the code in this hook as a starting point for some more 72.637 -exotic Bugzilla integration recipes. Here are a few possibilities: 72.638 -\begin{itemize} 72.639 -\item Require that every changeset pushed to the server have a valid 72.640 - bug~ID in its commit comment. In this case, you'd want to configure 72.641 - the hook as a \hook{pretxncommit} hook. This would allow the hook 72.642 - to reject changes that didn't contain bug IDs. 72.643 -\item Allow incoming changesets to automatically modify the 72.644 - \emph{state} of a bug, as well as simply adding a comment. For 72.645 - example, the hook could recognise the string ``fixed bug 31337'' as 72.646 - indicating that it should update the state of bug 31337 to 72.647 - ``requires testing''. 72.648 -\end{itemize} 72.649 - 72.650 -\subsubsection{Configuring the \hook{bugzilla} hook} 72.651 -\label{sec:hook:bugzilla:config} 72.652 - 72.653 -You should configure this hook in your server's \hgrc\ as an 72.654 -\hook{incoming} hook, for example as follows: 72.655 -\begin{codesample2} 72.656 - [hooks] 72.657 - incoming.bugzilla = python:hgext.bugzilla.hook 72.658 -\end{codesample2} 72.659 - 72.660 -Because of the specialised nature of this hook, and because Bugzilla 72.661 -was not written with this kind of integration in mind, configuring 72.662 -this hook is a somewhat involved process. 72.663 - 72.664 -Before you begin, you must install the MySQL bindings for Python on 72.665 -the host(s) where you'll be running the hook. If this is not 72.666 -available as a binary package for your system, you can download it 72.667 -from~\cite{web:mysql-python}. 72.668 - 72.669 -Configuration information for this hook lives in the 72.670 -\rcsection{bugzilla} section of your \hgrc. 72.671 -\begin{itemize} 72.672 -\item[\rcitem{bugzilla}{version}] The version of Bugzilla installed on 72.673 - the server. The database schema that Bugzilla uses changes 72.674 - occasionally, so this hook has to know exactly which schema to use. 72.675 - At the moment, the only version supported is \texttt{2.16}. 72.676 -\item[\rcitem{bugzilla}{host}] The hostname of the MySQL server that 72.677 - stores your Bugzilla data. The database must be configured to allow 72.678 - connections from whatever host you are running the \hook{bugzilla} 72.679 - hook on. 72.680 -\item[\rcitem{bugzilla}{user}] The username with which to connect to 72.681 - the MySQL server. The database must be configured to allow this 72.682 - user to connect from whatever host you are running the 72.683 - \hook{bugzilla} hook on. This user must be able to access and 72.684 - modify Bugzilla tables. The default value of this item is 72.685 - \texttt{bugs}, which is the standard name of the Bugzilla user in a 72.686 - MySQL database. 72.687 -\item[\rcitem{bugzilla}{password}] The MySQL password for the user you 72.688 - configured above. This is stored as plain text, so you should make 72.689 - sure that unauthorised users cannot read the \hgrc\ file where you 72.690 - store this information. 72.691 -\item[\rcitem{bugzilla}{db}] The name of the Bugzilla database on the 72.692 - MySQL server. The default value of this item is \texttt{bugs}, 72.693 - which is the standard name of the MySQL database where Bugzilla 72.694 - stores its data. 72.695 -\item[\rcitem{bugzilla}{notify}] If you want Bugzilla to send out a 72.696 - notification email to subscribers after this hook has added a 72.697 - comment to a bug, you will need this hook to run a command whenever 72.698 - it updates the database. The command to run depends on where you 72.699 - have installed Bugzilla, but it will typically look something like 72.700 - this, if you have Bugzilla installed in 72.701 - \dirname{/var/www/html/bugzilla}: 72.702 - \begin{codesample4} 72.703 - cd /var/www/html/bugzilla && ./processmail %s nobody@nowhere.com 72.704 - \end{codesample4} 72.705 - The Bugzilla \texttt{processmail} program expects to be given a 72.706 - bug~ID (the hook replaces ``\texttt{\%s}'' with the bug~ID) and an 72.707 - email address. It also expects to be able to write to some files in 72.708 - the directory that it runs in. If Bugzilla and this hook are not 72.709 - installed on the same machine, you will need to find a way to run 72.710 - \texttt{processmail} on the server where Bugzilla is installed. 72.711 -\end{itemize} 72.712 - 72.713 -\subsubsection{Mapping committer names to Bugzilla user names} 72.714 - 72.715 -By default, the \hgext{bugzilla} hook tries to use the email address 72.716 -of a changeset's committer as the Bugzilla user name with which to 72.717 -update a bug. If this does not suit your needs, you can map committer 72.718 -email addresses to Bugzilla user names using a \rcsection{usermap} 72.719 -section. 72.720 - 72.721 -Each item in the \rcsection{usermap} section contains an email address 72.722 -on the left, and a Bugzilla user name on the right. 72.723 -\begin{codesample2} 72.724 - [usermap] 72.725 - jane.user@example.com = jane 72.726 -\end{codesample2} 72.727 -You can either keep the \rcsection{usermap} data in a normal \hgrc, or 72.728 -tell the \hgext{bugzilla} hook to read the information from an 72.729 -external \filename{usermap} file. In the latter case, you can store 72.730 -\filename{usermap} data by itself in (for example) a user-modifiable 72.731 -repository. This makes it possible to let your users maintain their 72.732 -own \rcitem{bugzilla}{usermap} entries. The main \hgrc\ file might 72.733 -look like this: 72.734 -\begin{codesample2} 72.735 - # regular hgrc file refers to external usermap file 72.736 - [bugzilla] 72.737 - usermap = /home/hg/repos/userdata/bugzilla-usermap.conf 72.738 -\end{codesample2} 72.739 -While the \filename{usermap} file that it refers to might look like 72.740 -this: 72.741 -\begin{codesample2} 72.742 - # bugzilla-usermap.conf - inside a hg repository 72.743 - [usermap] 72.744 - stephanie@example.com = steph 72.745 -\end{codesample2} 72.746 - 72.747 -\subsubsection{Configuring the text that gets added to a bug} 72.748 - 72.749 -You can configure the text that this hook adds as a comment; you 72.750 -specify it in the form of a Mercurial template. Several \hgrc\ 72.751 -entries (still in the \rcsection{bugzilla} section) control this 72.752 -behaviour. 72.753 -\begin{itemize} 72.754 -\item[\texttt{strip}] The number of leading path elements to strip 72.755 - from a repository's path name to construct a partial path for a URL. 72.756 - For example, if the repositories on your server live under 72.757 - \dirname{/home/hg/repos}, and you have a repository whose path is 72.758 - \dirname{/home/hg/repos/app/tests}, then setting \texttt{strip} to 72.759 - \texttt{4} will give a partial path of \dirname{app/tests}. The 72.760 - hook will make this partial path available when expanding a 72.761 - template, as \texttt{webroot}. 72.762 -\item[\texttt{template}] The text of the template to use. In addition 72.763 - to the usual changeset-related variables, this template can use 72.764 - \texttt{hgweb} (the value of the \texttt{hgweb} configuration item 72.765 - above) and \texttt{webroot} (the path constructed using 72.766 - \texttt{strip} above). 72.767 -\end{itemize} 72.768 - 72.769 -In addition, you can add a \rcitem{web}{baseurl} item to the 72.770 -\rcsection{web} section of your \hgrc. The \hgext{bugzilla} hook will 72.771 -make this available when expanding a template, as the base string to 72.772 -use when constructing a URL that will let users browse from a Bugzilla 72.773 -comment to view a changeset. Example: 72.774 -\begin{codesample2} 72.775 - [web] 72.776 - baseurl = http://hg.domain.com/ 72.777 -\end{codesample2} 72.778 - 72.779 -Here is an example set of \hgext{bugzilla} hook config information. 72.780 -\begin{codesample2} 72.781 - [bugzilla] 72.782 - host = bugzilla.example.com 72.783 - password = mypassword 72.784 - version = 2.16 72.785 - # server-side repos live in /home/hg/repos, so strip 4 leading 72.786 - # separators 72.787 - strip = 4 72.788 - hgweb = http://hg.example.com/ 72.789 - usermap = /home/hg/repos/notify/bugzilla.conf 72.790 - template = Changeset \{node|short\}, made by \{author\} in the \{webroot\} 72.791 - repo, refers to this bug.\\nFor complete details, see 72.792 - \{hgweb\}\{webroot\}?cmd=changeset;node=\{node|short\}\\nChangeset 72.793 - description:\\n\\t\{desc|tabindent\} 72.794 -\end{codesample2} 72.795 - 72.796 -\subsubsection{Testing and troubleshooting} 72.797 - 72.798 -The most common problems with configuring the \hgext{bugzilla} hook 72.799 -relate to running Bugzilla's \filename{processmail} script and mapping 72.800 -committer names to user names. 72.801 - 72.802 -Recall from section~\ref{sec:hook:bugzilla:config} above that the user 72.803 -that runs the Mercurial process on the server is also the one that 72.804 -will run the \filename{processmail} script. The 72.805 -\filename{processmail} script sometimes causes Bugzilla to write to 72.806 -files in its configuration directory, and Bugzilla's configuration 72.807 -files are usually owned by the user that your web server runs under. 72.808 - 72.809 -You can cause \filename{processmail} to be run with the suitable 72.810 -user's identity using the \command{sudo} command. Here is an example 72.811 -entry for a \filename{sudoers} file. 72.812 -\begin{codesample2} 72.813 - hg_user = (httpd_user) NOPASSWD: /var/www/html/bugzilla/processmail-wrapper %s 72.814 -\end{codesample2} 72.815 -This allows the \texttt{hg\_user} user to run a 72.816 -\filename{processmail-wrapper} program under the identity of 72.817 -\texttt{httpd\_user}. 72.818 - 72.819 -This indirection through a wrapper script is necessary, because 72.820 -\filename{processmail} expects to be run with its current directory 72.821 -set to wherever you installed Bugzilla; you can't specify that kind of 72.822 -constraint in a \filename{sudoers} file. The contents of the wrapper 72.823 -script are simple: 72.824 -\begin{codesample2} 72.825 - #!/bin/sh 72.826 - cd `dirname $0` && ./processmail "$1" nobody@example.com 72.827 -\end{codesample2} 72.828 -It doesn't seem to matter what email address you pass to 72.829 -\filename{processmail}. 72.830 - 72.831 -If your \rcsection{usermap} is not set up correctly, users will see an 72.832 -error message from the \hgext{bugzilla} hook when they push changes 72.833 -to the server. The error message will look like this: 72.834 -\begin{codesample2} 72.835 - cannot find bugzilla user id for john.q.public@example.com 72.836 -\end{codesample2} 72.837 -What this means is that the committer's address, 72.838 -\texttt{john.q.public@example.com}, is not a valid Bugzilla user name, 72.839 -nor does it have an entry in your \rcsection{usermap} that maps it to 72.840 -a valid Bugzilla user name. 72.841 - 72.842 -\subsection{\hgext{notify}---send email notifications} 72.843 - 72.844 -Although Mercurial's built-in web server provides RSS feeds of changes 72.845 -in every repository, many people prefer to receive change 72.846 -notifications via email. The \hgext{notify} hook lets you send out 72.847 -notifications to a set of email addresses whenever changesets arrive 72.848 -that those subscribers are interested in. 72.849 - 72.850 -As with the \hgext{bugzilla} hook, the \hgext{notify} hook is 72.851 -template-driven, so you can customise the contents of the notification 72.852 -messages that it sends. 72.853 - 72.854 -By default, the \hgext{notify} hook includes a diff of every changeset 72.855 -that it sends out; you can limit the size of the diff, or turn this 72.856 -feature off entirely. It is useful for letting subscribers review 72.857 -changes immediately, rather than clicking to follow a URL. 72.858 - 72.859 -\subsubsection{Configuring the \hgext{notify} hook} 72.860 - 72.861 -You can set up the \hgext{notify} hook to send one email message per 72.862 -incoming changeset, or one per incoming group of changesets (all those 72.863 -that arrived in a single pull or push). 72.864 -\begin{codesample2} 72.865 - [hooks] 72.866 - # send one email per group of changes 72.867 - changegroup.notify = python:hgext.notify.hook 72.868 - # send one email per change 72.869 - incoming.notify = python:hgext.notify.hook 72.870 -\end{codesample2} 72.871 - 72.872 -Configuration information for this hook lives in the 72.873 -\rcsection{notify} section of a \hgrc\ file. 72.874 -\begin{itemize} 72.875 -\item[\rcitem{notify}{test}] By default, this hook does not send out 72.876 - email at all; instead, it prints the message that it \emph{would} 72.877 - send. Set this item to \texttt{false} to allow email to be sent. 72.878 - The reason that sending of email is turned off by default is that it 72.879 - takes several tries to configure this extension exactly as you would 72.880 - like, and it would be bad form to spam subscribers with a number of 72.881 - ``broken'' notifications while you debug your configuration. 72.882 -\item[\rcitem{notify}{config}] The path to a configuration file that 72.883 - contains subscription information. This is kept separate from the 72.884 - main \hgrc\ so that you can maintain it in a repository of its own. 72.885 - People can then clone that repository, update their subscriptions, 72.886 - and push the changes back to your server. 72.887 -\item[\rcitem{notify}{strip}] The number of leading path separator 72.888 - characters to strip from a repository's path, when deciding whether 72.889 - a repository has subscribers. For example, if the repositories on 72.890 - your server live in \dirname{/home/hg/repos}, and \hgext{notify} is 72.891 - considering a repository named \dirname{/home/hg/repos/shared/test}, 72.892 - setting \rcitem{notify}{strip} to \texttt{4} will cause 72.893 - \hgext{notify} to trim the path it considers down to 72.894 - \dirname{shared/test}, and it will match subscribers against that. 72.895 -\item[\rcitem{notify}{template}] The template text to use when sending 72.896 - messages. This specifies both the contents of the message header 72.897 - and its body. 72.898 -\item[\rcitem{notify}{maxdiff}] The maximum number of lines of diff 72.899 - data to append to the end of a message. If a diff is longer than 72.900 - this, it is truncated. By default, this is set to 300. Set this to 72.901 - \texttt{0} to omit diffs from notification emails. 72.902 -\item[\rcitem{notify}{sources}] A list of sources of changesets to 72.903 - consider. This lets you limit \hgext{notify} to only sending out 72.904 - email about changes that remote users pushed into this repository 72.905 - via a server, for example. See section~\ref{sec:hook:sources} for 72.906 - the sources you can specify here. 72.907 -\end{itemize} 72.908 - 72.909 -If you set the \rcitem{web}{baseurl} item in the \rcsection{web} 72.910 -section, you can use it in a template; it will be available as 72.911 -\texttt{webroot}. 72.912 - 72.913 -Here is an example set of \hgext{notify} configuration information. 72.914 -\begin{codesample2} 72.915 - [notify] 72.916 - # really send email 72.917 - test = false 72.918 - # subscriber data lives in the notify repo 72.919 - config = /home/hg/repos/notify/notify.conf 72.920 - # repos live in /home/hg/repos on server, so strip 4 "/" chars 72.921 - strip = 4 72.922 - template = X-Hg-Repo: \{webroot\} 72.923 - Subject: \{webroot\}: \{desc|firstline|strip\} 72.924 - From: \{author\} 72.925 - 72.926 - changeset \{node|short\} in \{root\} 72.927 - details: \{baseurl\}\{webroot\}?cmd=changeset;node=\{node|short\} 72.928 - description: 72.929 - \{desc|tabindent|strip\} 72.930 - 72.931 - [web] 72.932 - baseurl = http://hg.example.com/ 72.933 -\end{codesample2} 72.934 - 72.935 -This will produce a message that looks like the following: 72.936 -\begin{codesample2} 72.937 - X-Hg-Repo: tests/slave 72.938 - Subject: tests/slave: Handle error case when slave has no buffers 72.939 - Date: Wed, 2 Aug 2006 15:25:46 -0700 (PDT) 72.940 - 72.941 - changeset 3cba9bfe74b5 in /home/hg/repos/tests/slave 72.942 - details: http://hg.example.com/tests/slave?cmd=changeset;node=3cba9bfe74b5 72.943 - description: 72.944 - Handle error case when slave has no buffers 72.945 - diffs (54 lines): 72.946 - 72.947 - diff -r 9d95df7cf2ad -r 3cba9bfe74b5 include/tests.h 72.948 - --- a/include/tests.h Wed Aug 02 15:19:52 2006 -0700 72.949 - +++ b/include/tests.h Wed Aug 02 15:25:26 2006 -0700 72.950 - @@ -212,6 +212,15 @@ static __inline__ void test_headers(void *h) 72.951 - [...snip...] 72.952 -\end{codesample2} 72.953 - 72.954 -\subsubsection{Testing and troubleshooting} 72.955 - 72.956 -Do not forget that by default, the \hgext{notify} extension \emph{will 72.957 - not send any mail} until you explicitly configure it to do so, by 72.958 -setting \rcitem{notify}{test} to \texttt{false}. Until you do that, 72.959 -it simply prints the message it \emph{would} send. 72.960 - 72.961 -\section{Information for writers of hooks} 72.962 -\label{sec:hook:ref} 72.963 - 72.964 -\subsection{In-process hook execution} 72.965 - 72.966 -An in-process hook is called with arguments of the following form: 72.967 -\begin{codesample2} 72.968 - def myhook(ui, repo, **kwargs): 72.969 - pass 72.970 -\end{codesample2} 72.971 -The \texttt{ui} parameter is a \pymodclass{mercurial.ui}{ui} object. 72.972 -The \texttt{repo} parameter is a 72.973 -\pymodclass{mercurial.localrepo}{localrepository} object. The 72.974 -names and values of the \texttt{**kwargs} parameters depend on the 72.975 -hook being invoked, with the following common features: 72.976 -\begin{itemize} 72.977 -\item If a parameter is named \texttt{node} or 72.978 - \texttt{parent\emph{N}}, it will contain a hexadecimal changeset ID. 72.979 - The empty string is used to represent ``null changeset ID'' instead 72.980 - of a string of zeroes. 72.981 -\item If a parameter is named \texttt{url}, it will contain the URL of 72.982 - a remote repository, if that can be determined. 72.983 -\item Boolean-valued parameters are represented as Python 72.984 - \texttt{bool} objects. 72.985 -\end{itemize} 72.986 - 72.987 -An in-process hook is called without a change to the process's working 72.988 -directory (unlike external hooks, which are run in the root of the 72.989 -repository). It must not change the process's working directory, or 72.990 -it will cause any calls it makes into the Mercurial API to fail. 72.991 - 72.992 -If a hook returns a boolean ``false'' value, it is considered to have 72.993 -succeeded. If it returns a boolean ``true'' value or raises an 72.994 -exception, it is considered to have failed. A useful way to think of 72.995 -the calling convention is ``tell me if you fail''. 72.996 - 72.997 -Note that changeset IDs are passed into Python hooks as hexadecimal 72.998 -strings, not the binary hashes that Mercurial's APIs normally use. To 72.999 -convert a hash from hex to binary, use the 72.1000 -\pymodfunc{mercurial.node}{bin} function. 72.1001 - 72.1002 -\subsection{External hook execution} 72.1003 - 72.1004 -An external hook is passed to the shell of the user running Mercurial. 72.1005 -Features of that shell, such as variable substitution and command 72.1006 -redirection, are available. The hook is run in the root directory of 72.1007 -the repository (unlike in-process hooks, which are run in the same 72.1008 -directory that Mercurial was run in). 72.1009 - 72.1010 -Hook parameters are passed to the hook as environment variables. Each 72.1011 -environment variable's name is converted in upper case and prefixed 72.1012 -with the string ``\texttt{HG\_}''. For example, if the name of a 72.1013 -parameter is ``\texttt{node}'', the name of the environment variable 72.1014 -representing that parameter will be ``\texttt{HG\_NODE}''. 72.1015 - 72.1016 -A boolean parameter is represented as the string ``\texttt{1}'' for 72.1017 -``true'', ``\texttt{0}'' for ``false''. If an environment variable is 72.1018 -named \envar{HG\_NODE}, \envar{HG\_PARENT1} or \envar{HG\_PARENT2}, it 72.1019 -contains a changeset ID represented as a hexadecimal string. The 72.1020 -empty string is used to represent ``null changeset ID'' instead of a 72.1021 -string of zeroes. If an environment variable is named 72.1022 -\envar{HG\_URL}, it will contain the URL of a remote repository, if 72.1023 -that can be determined. 72.1024 - 72.1025 -If a hook exits with a status of zero, it is considered to have 72.1026 -succeeded. If it exits with a non-zero status, it is considered to 72.1027 -have failed. 72.1028 - 72.1029 -\subsection{Finding out where changesets come from} 72.1030 - 72.1031 -A hook that involves the transfer of changesets between a local 72.1032 -repository and another may be able to find out information about the 72.1033 -``far side''. Mercurial knows \emph{how} changes are being 72.1034 -transferred, and in many cases \emph{where} they are being transferred 72.1035 -to or from. 72.1036 - 72.1037 -\subsubsection{Sources of changesets} 72.1038 -\label{sec:hook:sources} 72.1039 - 72.1040 -Mercurial will tell a hook what means are, or were, used to transfer 72.1041 -changesets between repositories. This is provided by Mercurial in a 72.1042 -Python parameter named \texttt{source}, or an environment variable named 72.1043 -\envar{HG\_SOURCE}. 72.1044 - 72.1045 -\begin{itemize} 72.1046 -\item[\texttt{serve}] Changesets are transferred to or from a remote 72.1047 - repository over http or ssh. 72.1048 -\item[\texttt{pull}] Changesets are being transferred via a pull from 72.1049 - one repository into another. 72.1050 -\item[\texttt{push}] Changesets are being transferred via a push from 72.1051 - one repository into another. 72.1052 -\item[\texttt{bundle}] Changesets are being transferred to or from a 72.1053 - bundle. 72.1054 -\end{itemize} 72.1055 - 72.1056 -\subsubsection{Where changes are going---remote repository URLs} 72.1057 -\label{sec:hook:url} 72.1058 - 72.1059 -When possible, Mercurial will tell a hook the location of the ``far 72.1060 -side'' of an activity that transfers changeset data between 72.1061 -repositories. This is provided by Mercurial in a Python parameter 72.1062 -named \texttt{url}, or an environment variable named \envar{HG\_URL}. 72.1063 - 72.1064 -This information is not always known. If a hook is invoked in a 72.1065 -repository that is being served via http or ssh, Mercurial cannot tell 72.1066 -where the remote repository is, but it may know where the client is 72.1067 -connecting from. In such cases, the URL will take one of the 72.1068 -following forms: 72.1069 -\begin{itemize} 72.1070 -\item \texttt{remote:ssh:\emph{ip-address}}---remote ssh client, at 72.1071 - the given IP address. 72.1072 -\item \texttt{remote:http:\emph{ip-address}}---remote http client, at 72.1073 - the given IP address. If the client is using SSL, this will be of 72.1074 - the form \texttt{remote:https:\emph{ip-address}}. 72.1075 -\item Empty---no information could be discovered about the remote 72.1076 - client. 72.1077 -\end{itemize} 72.1078 - 72.1079 -\section{Hook reference} 72.1080 - 72.1081 -\subsection{\hook{changegroup}---after remote changesets added} 72.1082 -\label{sec:hook:changegroup} 72.1083 - 72.1084 -This hook is run after a group of pre-existing changesets has been 72.1085 -added to the repository, for example via a \hgcmd{pull} or 72.1086 -\hgcmd{unbundle}. This hook is run once per operation that added one 72.1087 -or more changesets. This is in contrast to the \hook{incoming} hook, 72.1088 -which is run once per changeset, regardless of whether the changesets 72.1089 -arrive in a group. 72.1090 - 72.1091 -Some possible uses for this hook include kicking off an automated 72.1092 -build or test of the added changesets, updating a bug database, or 72.1093 -notifying subscribers that a repository contains new changes. 72.1094 - 72.1095 -Parameters to this hook: 72.1096 -\begin{itemize} 72.1097 -\item[\texttt{node}] A changeset ID. The changeset ID of the first 72.1098 - changeset in the group that was added. All changesets between this 72.1099 - and \index{tags!\texttt{tip}}\texttt{tip}, inclusive, were added by 72.1100 - a single \hgcmd{pull}, \hgcmd{push} or \hgcmd{unbundle}. 72.1101 -\item[\texttt{source}] A string. The source of these changes. See 72.1102 - section~\ref{sec:hook:sources} for details. 72.1103 -\item[\texttt{url}] A URL. The location of the remote repository, if 72.1104 - known. See section~\ref{sec:hook:url} for more information. 72.1105 -\end{itemize} 72.1106 - 72.1107 -See also: \hook{incoming} (section~\ref{sec:hook:incoming}), 72.1108 -\hook{prechangegroup} (section~\ref{sec:hook:prechangegroup}), 72.1109 -\hook{pretxnchangegroup} (section~\ref{sec:hook:pretxnchangegroup}) 72.1110 - 72.1111 -\subsection{\hook{commit}---after a new changeset is created} 72.1112 -\label{sec:hook:commit} 72.1113 - 72.1114 -This hook is run after a new changeset has been created. 72.1115 - 72.1116 -Parameters to this hook: 72.1117 -\begin{itemize} 72.1118 -\item[\texttt{node}] A changeset ID. The changeset ID of the newly 72.1119 - committed changeset. 72.1120 -\item[\texttt{parent1}] A changeset ID. The changeset ID of the first 72.1121 - parent of the newly committed changeset. 72.1122 -\item[\texttt{parent2}] A changeset ID. The changeset ID of the second 72.1123 - parent of the newly committed changeset. 72.1124 -\end{itemize} 72.1125 - 72.1126 -See also: \hook{precommit} (section~\ref{sec:hook:precommit}), 72.1127 -\hook{pretxncommit} (section~\ref{sec:hook:pretxncommit}) 72.1128 - 72.1129 -\subsection{\hook{incoming}---after one remote changeset is added} 72.1130 -\label{sec:hook:incoming} 72.1131 - 72.1132 -This hook is run after a pre-existing changeset has been added to the 72.1133 -repository, for example via a \hgcmd{push}. If a group of changesets 72.1134 -was added in a single operation, this hook is called once for each 72.1135 -added changeset. 72.1136 - 72.1137 -You can use this hook for the same purposes as the \hook{changegroup} 72.1138 -hook (section~\ref{sec:hook:changegroup}); it's simply more convenient 72.1139 -sometimes to run a hook once per group of changesets, while other 72.1140 -times it's handier once per changeset. 72.1141 - 72.1142 -Parameters to this hook: 72.1143 -\begin{itemize} 72.1144 -\item[\texttt{node}] A changeset ID. The ID of the newly added 72.1145 - changeset. 72.1146 -\item[\texttt{source}] A string. The source of these changes. See 72.1147 - section~\ref{sec:hook:sources} for details. 72.1148 -\item[\texttt{url}] A URL. The location of the remote repository, if 72.1149 - known. See section~\ref{sec:hook:url} for more information. 72.1150 -\end{itemize} 72.1151 - 72.1152 -See also: \hook{changegroup} (section~\ref{sec:hook:changegroup}) \hook{prechangegroup} (section~\ref{sec:hook:prechangegroup}), \hook{pretxnchangegroup} (section~\ref{sec:hook:pretxnchangegroup}) 72.1153 - 72.1154 -\subsection{\hook{outgoing}---after changesets are propagated} 72.1155 -\label{sec:hook:outgoing} 72.1156 - 72.1157 -This hook is run after a group of changesets has been propagated out 72.1158 -of this repository, for example by a \hgcmd{push} or \hgcmd{bundle} 72.1159 -command. 72.1160 - 72.1161 -One possible use for this hook is to notify administrators that 72.1162 -changes have been pulled. 72.1163 - 72.1164 -Parameters to this hook: 72.1165 -\begin{itemize} 72.1166 -\item[\texttt{node}] A changeset ID. The changeset ID of the first 72.1167 - changeset of the group that was sent. 72.1168 -\item[\texttt{source}] A string. The source of the of the operation 72.1169 - (see section~\ref{sec:hook:sources}). If a remote client pulled 72.1170 - changes from this repository, \texttt{source} will be 72.1171 - \texttt{serve}. If the client that obtained changes from this 72.1172 - repository was local, \texttt{source} will be \texttt{bundle}, 72.1173 - \texttt{pull}, or \texttt{push}, depending on the operation the 72.1174 - client performed. 72.1175 -\item[\texttt{url}] A URL. The location of the remote repository, if 72.1176 - known. See section~\ref{sec:hook:url} for more information. 72.1177 -\end{itemize} 72.1178 - 72.1179 -See also: \hook{preoutgoing} (section~\ref{sec:hook:preoutgoing}) 72.1180 - 72.1181 -\subsection{\hook{prechangegroup}---before starting to add remote changesets} 72.1182 -\label{sec:hook:prechangegroup} 72.1183 - 72.1184 -This controlling hook is run before Mercurial begins to add a group of 72.1185 -changesets from another repository. 72.1186 - 72.1187 -This hook does not have any information about the changesets to be 72.1188 -added, because it is run before transmission of those changesets is 72.1189 -allowed to begin. If this hook fails, the changesets will not be 72.1190 -transmitted. 72.1191 - 72.1192 -One use for this hook is to prevent external changes from being added 72.1193 -to a repository. For example, you could use this to ``freeze'' a 72.1194 -server-hosted branch temporarily or permanently so that users cannot 72.1195 -push to it, while still allowing a local administrator to modify the 72.1196 -repository. 72.1197 - 72.1198 -Parameters to this hook: 72.1199 -\begin{itemize} 72.1200 -\item[\texttt{source}] A string. The source of these changes. See 72.1201 - section~\ref{sec:hook:sources} for details. 72.1202 -\item[\texttt{url}] A URL. The location of the remote repository, if 72.1203 - known. See section~\ref{sec:hook:url} for more information. 72.1204 -\end{itemize} 72.1205 - 72.1206 -See also: \hook{changegroup} (section~\ref{sec:hook:changegroup}), 72.1207 -\hook{incoming} (section~\ref{sec:hook:incoming}), , 72.1208 -\hook{pretxnchangegroup} (section~\ref{sec:hook:pretxnchangegroup}) 72.1209 - 72.1210 -\subsection{\hook{precommit}---before starting to commit a changeset} 72.1211 -\label{sec:hook:precommit} 72.1212 - 72.1213 -This hook is run before Mercurial begins to commit a new changeset. 72.1214 -It is run before Mercurial has any of the metadata for the commit, 72.1215 -such as the files to be committed, the commit message, or the commit 72.1216 -date. 72.1217 - 72.1218 -One use for this hook is to disable the ability to commit new 72.1219 -changesets, while still allowing incoming changesets. Another is to 72.1220 -run a build or test, and only allow the commit to begin if the build 72.1221 -or test succeeds. 72.1222 - 72.1223 -Parameters to this hook: 72.1224 -\begin{itemize} 72.1225 -\item[\texttt{parent1}] A changeset ID. The changeset ID of the first 72.1226 - parent of the working directory. 72.1227 -\item[\texttt{parent2}] A changeset ID. The changeset ID of the second 72.1228 - parent of the working directory. 72.1229 -\end{itemize} 72.1230 -If the commit proceeds, the parents of the working directory will 72.1231 -become the parents of the new changeset. 72.1232 - 72.1233 -See also: \hook{commit} (section~\ref{sec:hook:commit}), 72.1234 -\hook{pretxncommit} (section~\ref{sec:hook:pretxncommit}) 72.1235 - 72.1236 -\subsection{\hook{preoutgoing}---before starting to propagate changesets} 72.1237 -\label{sec:hook:preoutgoing} 72.1238 - 72.1239 -This hook is invoked before Mercurial knows the identities of the 72.1240 -changesets to be transmitted. 72.1241 - 72.1242 -One use for this hook is to prevent changes from being transmitted to 72.1243 -another repository. 72.1244 - 72.1245 -Parameters to this hook: 72.1246 -\begin{itemize} 72.1247 -\item[\texttt{source}] A string. The source of the operation that is 72.1248 - attempting to obtain changes from this repository (see 72.1249 - section~\ref{sec:hook:sources}). See the documentation for the 72.1250 - \texttt{source} parameter to the \hook{outgoing} hook, in 72.1251 - section~\ref{sec:hook:outgoing}, for possible values of this 72.1252 - parameter. 72.1253 -\item[\texttt{url}] A URL. The location of the remote repository, if 72.1254 - known. See section~\ref{sec:hook:url} for more information. 72.1255 -\end{itemize} 72.1256 - 72.1257 -See also: \hook{outgoing} (section~\ref{sec:hook:outgoing}) 72.1258 - 72.1259 -\subsection{\hook{pretag}---before tagging a changeset} 72.1260 -\label{sec:hook:pretag} 72.1261 - 72.1262 -This controlling hook is run before a tag is created. If the hook 72.1263 -succeeds, creation of the tag proceeds. If the hook fails, the tag is 72.1264 -not created. 72.1265 - 72.1266 -Parameters to this hook: 72.1267 -\begin{itemize} 72.1268 -\item[\texttt{local}] A boolean. Whether the tag is local to this 72.1269 - repository instance (i.e.~stored in \sfilename{.hg/localtags}) or 72.1270 - managed by Mercurial (stored in \sfilename{.hgtags}). 72.1271 -\item[\texttt{node}] A changeset ID. The ID of the changeset to be tagged. 72.1272 -\item[\texttt{tag}] A string. The name of the tag to be created. 72.1273 -\end{itemize} 72.1274 - 72.1275 -If the tag to be created is revision-controlled, the \hook{precommit} 72.1276 -and \hook{pretxncommit} hooks (sections~\ref{sec:hook:commit} 72.1277 -and~\ref{sec:hook:pretxncommit}) will also be run. 72.1278 - 72.1279 -See also: \hook{tag} (section~\ref{sec:hook:tag}) 72.1280 - 72.1281 -\subsection{\hook{pretxnchangegroup}---before completing addition of 72.1282 - remote changesets} 72.1283 -\label{sec:hook:pretxnchangegroup} 72.1284 - 72.1285 -This controlling hook is run before a transaction---that manages the 72.1286 -addition of a group of new changesets from outside the 72.1287 -repository---completes. If the hook succeeds, the transaction 72.1288 -completes, and all of the changesets become permanent within this 72.1289 -repository. If the hook fails, the transaction is rolled back, and 72.1290 -the data for the changesets is erased. 72.1291 - 72.1292 -This hook can access the metadata associated with the almost-added 72.1293 -changesets, but it should not do anything permanent with this data. 72.1294 -It must also not modify the working directory. 72.1295 - 72.1296 -While this hook is running, if other Mercurial processes access this 72.1297 -repository, they will be able to see the almost-added changesets as if 72.1298 -they are permanent. This may lead to race conditions if you do not 72.1299 -take steps to avoid them. 72.1300 - 72.1301 -This hook can be used to automatically vet a group of changesets. If 72.1302 -the hook fails, all of the changesets are ``rejected'' when the 72.1303 -transaction rolls back. 72.1304 - 72.1305 -Parameters to this hook: 72.1306 -\begin{itemize} 72.1307 -\item[\texttt{node}] A changeset ID. The changeset ID of the first 72.1308 - changeset in the group that was added. All changesets between this 72.1309 - and \index{tags!\texttt{tip}}\texttt{tip}, inclusive, were added by 72.1310 - a single \hgcmd{pull}, \hgcmd{push} or \hgcmd{unbundle}. 72.1311 -\item[\texttt{source}] A string. The source of these changes. See 72.1312 - section~\ref{sec:hook:sources} for details. 72.1313 -\item[\texttt{url}] A URL. The location of the remote repository, if 72.1314 - known. See section~\ref{sec:hook:url} for more information. 72.1315 -\end{itemize} 72.1316 - 72.1317 -See also: \hook{changegroup} (section~\ref{sec:hook:changegroup}), 72.1318 -\hook{incoming} (section~\ref{sec:hook:incoming}), 72.1319 -\hook{prechangegroup} (section~\ref{sec:hook:prechangegroup}) 72.1320 - 72.1321 -\subsection{\hook{pretxncommit}---before completing commit of new changeset} 72.1322 -\label{sec:hook:pretxncommit} 72.1323 - 72.1324 -This controlling hook is run before a transaction---that manages a new 72.1325 -commit---completes. If the hook succeeds, the transaction completes 72.1326 -and the changeset becomes permanent within this repository. If the 72.1327 -hook fails, the transaction is rolled back, and the commit data is 72.1328 -erased. 72.1329 - 72.1330 -This hook can access the metadata associated with the almost-new 72.1331 -changeset, but it should not do anything permanent with this data. It 72.1332 -must also not modify the working directory. 72.1333 - 72.1334 -While this hook is running, if other Mercurial processes access this 72.1335 -repository, they will be able to see the almost-new changeset as if it 72.1336 -is permanent. This may lead to race conditions if you do not take 72.1337 -steps to avoid them. 72.1338 - 72.1339 -Parameters to this hook: 72.1340 -\begin{itemize} 72.1341 -\item[\texttt{node}] A changeset ID. The changeset ID of the newly 72.1342 - committed changeset. 72.1343 -\item[\texttt{parent1}] A changeset ID. The changeset ID of the first 72.1344 - parent of the newly committed changeset. 72.1345 -\item[\texttt{parent2}] A changeset ID. The changeset ID of the second 72.1346 - parent of the newly committed changeset. 72.1347 -\end{itemize} 72.1348 - 72.1349 -See also: \hook{precommit} (section~\ref{sec:hook:precommit}) 72.1350 - 72.1351 -\subsection{\hook{preupdate}---before updating or merging working directory} 72.1352 -\label{sec:hook:preupdate} 72.1353 - 72.1354 -This controlling hook is run before an update or merge of the working 72.1355 -directory begins. It is run only if Mercurial's normal pre-update 72.1356 -checks determine that the update or merge can proceed. If the hook 72.1357 -succeeds, the update or merge may proceed; if it fails, the update or 72.1358 -merge does not start. 72.1359 - 72.1360 -Parameters to this hook: 72.1361 -\begin{itemize} 72.1362 -\item[\texttt{parent1}] A changeset ID. The ID of the parent that the 72.1363 - working directory is to be updated to. If the working directory is 72.1364 - being merged, it will not change this parent. 72.1365 -\item[\texttt{parent2}] A changeset ID. Only set if the working 72.1366 - directory is being merged. The ID of the revision that the working 72.1367 - directory is being merged with. 72.1368 -\end{itemize} 72.1369 - 72.1370 -See also: \hook{update} (section~\ref{sec:hook:update}) 72.1371 - 72.1372 -\subsection{\hook{tag}---after tagging a changeset} 72.1373 -\label{sec:hook:tag} 72.1374 - 72.1375 -This hook is run after a tag has been created. 72.1376 - 72.1377 -Parameters to this hook: 72.1378 -\begin{itemize} 72.1379 -\item[\texttt{local}] A boolean. Whether the new tag is local to this 72.1380 - repository instance (i.e.~stored in \sfilename{.hg/localtags}) or 72.1381 - managed by Mercurial (stored in \sfilename{.hgtags}). 72.1382 -\item[\texttt{node}] A changeset ID. The ID of the changeset that was 72.1383 - tagged. 72.1384 -\item[\texttt{tag}] A string. The name of the tag that was created. 72.1385 -\end{itemize} 72.1386 - 72.1387 -If the created tag is revision-controlled, the \hook{commit} hook 72.1388 -(section~\ref{sec:hook:commit}) is run before this hook. 72.1389 - 72.1390 -See also: \hook{pretag} (section~\ref{sec:hook:pretag}) 72.1391 - 72.1392 -\subsection{\hook{update}---after updating or merging working directory} 72.1393 -\label{sec:hook:update} 72.1394 - 72.1395 -This hook is run after an update or merge of the working directory 72.1396 -completes. Since a merge can fail (if the external \command{hgmerge} 72.1397 -command fails to resolve conflicts in a file), this hook communicates 72.1398 -whether the update or merge completed cleanly. 72.1399 - 72.1400 -\begin{itemize} 72.1401 -\item[\texttt{error}] A boolean. Indicates whether the update or 72.1402 - merge completed successfully. 72.1403 -\item[\texttt{parent1}] A changeset ID. The ID of the parent that the 72.1404 - working directory was updated to. If the working directory was 72.1405 - merged, it will not have changed this parent. 72.1406 -\item[\texttt{parent2}] A changeset ID. Only set if the working 72.1407 - directory was merged. The ID of the revision that the working 72.1408 - directory was merged with. 72.1409 -\end{itemize} 72.1410 - 72.1411 -See also: \hook{preupdate} (section~\ref{sec:hook:preupdate}) 72.1412 - 72.1413 -%%% Local Variables: 72.1414 -%%% mode: latex 72.1415 -%%% TeX-master: "00book" 72.1416 -%%% End:
73.1 --- a/fr/htlatex.book Sun Aug 16 03:41:39 2009 +0200 73.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 73.3 @@ -1,12 +0,0 @@ 73.4 -#!/bin/bash 73.5 -# 73.6 -# This script is horrible. It's essentially a hacked copy of 73.7 -# /usr/bin/htlatex from Fedora Core 6. I apologise for any lasting 73.8 -# pain reading it causes. 73.9 - 73.10 -latex $5 '\makeatletter\def\HCode{\futurelet\HCode\HChar}\def\HChar{\ifx"\HCode\def\HCode"##1"{\Link##1}\expandafter\HCode\else\expandafter\Link\fi}\def\Link#1.a.b.c.{\g@addto@macro\@documentclasshook{\RequirePackage[#1,html]{tex4ht}}\let\HCode\documentstyle\def\documentstyle{\let\documentstyle\HCode\expandafter\def\csname tex4ht\endcsname{#1,html}\def\HCode####1{\documentstyle[tex4ht,}\@ifnextchar[{\HCode}{\documentstyle[tex4ht]}}}\makeatother\HCode '$2'.a.b.c.\input ' $1 73.11 -(cd $4 && bibtex hgbook) 73.12 -(cd $4 && makeindex hgbook) 73.13 -latex $5 '\makeatletter\def\HCode{\futurelet\HCode\HChar}\def\HChar{\ifx"\HCode\def\HCode"##1"{\Link##1}\expandafter\HCode\else\expandafter\Link\fi}\def\Link#1.a.b.c.{\g@addto@macro\@documentclasshook{\RequirePackage[#1,html]{tex4ht}}\let\HCode\documentstyle\def\documentstyle{\let\documentstyle\HCode\expandafter\def\csname tex4ht\endcsname{#1,html}\def\HCode####1{\documentstyle[tex4ht,}\@ifnextchar[{\HCode}{\documentstyle[tex4ht]}}}\makeatother\HCode '$2'.a.b.c.\input ' $1 73.14 -latex $5 '\makeatletter\def\HCode{\futurelet\HCode\HChar}\def\HChar{\ifx"\HCode\def\HCode"##1"{\Link##1}\expandafter\HCode\else\expandafter\Link\fi}\def\Link#1.a.b.c.{\g@addto@macro\@documentclasshook{\RequirePackage[#1,html]{tex4ht}}\let\HCode\documentstyle\def\documentstyle{\let\documentstyle\HCode\expandafter\def\csname tex4ht\endcsname{#1,html}\def\HCode####1{\documentstyle[tex4ht,}\@ifnextchar[{\HCode}{\documentstyle[tex4ht]}}}\makeatother\HCode '$2'.a.b.c.\input ' $1 73.15 -echo status $$
74.1 --- a/fr/intro.tex Sun Aug 16 03:41:39 2009 +0200 74.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 74.3 @@ -1,617 +0,0 @@ 74.4 -\chapter{Introduction} 74.5 -\label{chap:intro} 74.6 - 74.7 -\section{À propos de la gestion source} 74.8 - 74.9 -La gestion de sources est un processus permettant de gérer différentes 74.10 -versions de la même information. Dans sa forme la plus simple, c'est 74.11 -ce que tout le monde fait manuellement : quand vous modifiez 74.12 -un fichier, vous le sauvegardez sous un nouveau nom contenant un numéro, 74.13 -à chaque fois plus grand que celui de la version précédente. 74.14 - 74.15 -Ce genre de gestion de version manuelle est cependant facilement sujette 74.16 -à des erreurs, ainsi, depuis longtemps, des logiciels existent pour 74.17 -résoudre cette problématique. Les premiers outils de gestion de sources 74.18 -étaient destinés à aider un seul utilisateur, à automatiser la gestion 74.19 -des versions d'un seul fichier. Dans les dernières décades, cette cible 74.20 -s'est largement agrandie, ils gèrent désormais de multiples fichiers, et 74.21 -aident un grand nombre de personnes à travailler ensemble. Les outils les 74.22 -plus modernes n'ont aucune difficulté à gérer plusieurs milliers de 74.23 -personnes travaillant ensemble sur des projets regroupant plusieurs 74.24 -centaines de milliers de fichiers. 74.25 - 74.26 -\subsection{Pourquoi utiliser un gestionnaire de source ?} 74.27 - 74.28 -Il y a de nombreuses raisons pour que vous ou votre équipe souhaitiez 74.29 -utiliser un outil automatisant la gestion de version pour votre projet. 74.30 -\begin{itemize} 74.31 -\item L'outil se chargera de suivre l'évolution de votre projet, sans 74.32 -que vous n'ayez à le faire. Pour chaque modification, vous aurez à votre 74.33 -disposition un journal indiquant \emph{qui} a fait quoi, \emph{pourquoi} 74.34 -ils l'ont fait, \emph{quand} ils l'ont fait, et \emph{ce} qu'ils ont 74.35 -modifiés. 74.36 -\item Quand vous travaillez avec d'autres personnes, les logiciels de 74.37 -gestion de source facilitent le travail collaboratif. Par exemple, quand 74.38 -plusieurs personnes font, plus ou moins simultanément, des modifications 74.39 -incompatibles, le logiciel vous aidera à identifier et à résoudre les conflits. 74.40 -\item L'outil vous aidera à réparer vos erreurs. Si vous effectuez un changement 74.41 -qui se révèle être une erreur, vous pourrez revenir à une version 74.42 -antérieure d'un fichier ou même d'un ensemble de fichiers. En fait, un outil de 74.43 -gestion de source \emph{vraiment} efficace vous permettra d'identifier à quel 74.44 -moment le problème est apparu (voir la section~\ref{sec:undo:bisect} pour plus 74.45 -de détails). 74.46 -\item L'outil vous permettra aussi de travailler sur plusieurs versions différentes 74.47 -de votre projet et à gérer l'écart entre chacune. 74.48 -\end{itemize} 74.49 -La plupart de ces raisons ont autant d'importances ---du moins en théorie--- que 74.50 -vous travailliez sur un projet pour vous, ou avec une centaine d'autres 74.51 -personnes. 74.52 - 74.53 -Une question fondamentale à propos des outils de gestion de source, qu'il s'agisse 74.54 -du projet d'une personne ou d'une grande équipe, est quels sont ses 74.55 -\emph{avantages} par rapport à ses \emph{coûts}. Un outil qui est difficile à 74.56 -utiliser ou à comprendre exigera un lourd effort d'adaptation. 74.57 - 74.58 -Un projet de cinq milles personnes s'effondrera très certainement de lui même 74.59 -sans aucun processus et outil de gestion de source. Dans ce cas, le coût 74.60 -d'utilisation d'un logiciel de gestion de source est dérisoire puisque 74.61 -\emph{sans}, l'échec est presque garanti. 74.62 - 74.63 -D'un autre coté, un ``rapide hack'' d'une personne peut sembler un contexte 74.64 -bien pauvre pour utiliser un outil de gestion de source, car, bien évidement 74.65 -le coût d'utilisation dépasse le coût total du projet. N'est ce pas ? 74.66 - 74.67 -Mercurial supporte ces \emph{deux} échelles de travail. Vous pouvez apprendre 74.68 -les bases en quelques minutes seulement, et, grâce à sa performance, vous pouvez 74.69 -l'utiliser avec facilité sur le plus petit des projets. Cette simplicité 74.70 -signifie que vous n'avez pas de concept obscurs ou de séquence de commandes 74.71 -défiant l'imagination, sans aucune corrélation avec \emph{ce que vous êtes 74.72 -vraiment en train de faire}. En même temps, ces mêmes performances et sa 74.73 -nature ``peer-to-peer'' vous permettent d'augmenter, sans difficulté, son 74.74 -utilisation à de très grands projets. 74.75 - 74.76 -Aucun outil de gestion de source ne peut sauver un projet mal mené, mais un 74.77 -bon outil peut rendre beaucoup plus fluide votre travail. 74.78 - 74.79 -\subsection{Les multiples noms de la gestion de source} 74.80 - 74.81 -La gestion de source\footnote{NdT: J'ai utilisé systématiquement le terme 74.82 -``gestion de source'' à travers tout l'ouvrage. Ce n'est pas forcement la 74.83 -meilleure traduction, et ceci peut rendre la lecture un peu lourde, mais je 74.84 -pense que le document y gagne en clarté et en précision.} est un domaine 74.85 -divers, tellement qu'il n'existe pas une seul nom ou acronyme pour le désigner. 74.86 -Voilà quelqu'uns des noms ou 74.87 -acronymes que vous rencontrerez le plus souvent\footnote{NdT: J'ai conservé la 74.88 -liste des noms en anglais pour des raisons de commodité (ils sont plus 74.89 -``googelable''). En outre, j'ai opté pour conserver l'ensemble des opérations de 74.90 -Mercurial (\textit{commit},\textit{push}, \textit{pull},...) en anglais, là 74.91 -aussi pour faciliter la lecture d'autres documents en anglais, ainsi que 74.92 -l'utilisation de Mercurial}. 74.93 - 74.94 -: 74.95 -\begin{itemize} 74.96 -\item \textit{Revision control (RCS)} ; 74.97 -\item Software configuration management (SCM), ou \textit{configuration management} ; 74.98 -\item \textit{Source code management} ; 74.99 -\item \textit{Source code control}, ou \textit{source control} ; 74.100 -\item \textit{Version control (VCS)}. 74.101 -\end{itemize} 74.102 - 74.103 -Certaines personnes prétendent que ces termes ont en fait des sens 74.104 -différents mais en pratique ils se recouvrent tellement qu'il n'y a pas 74.105 -réellement de manière pertinente de les distinguer. 74.106 - 74.107 -\section{Une courte histoire de la gestion de source} 74.108 - 74.109 -Le plus célèbre des anciens outils de gestion de source est \textit{SCCS 74.110 -(Source Code Control System)}, que Marc Rochkind conçu dans les laboratoires de 74.111 -recherche de Bell (\textit{Bell Labs}), dans le début des années 70. 74.112 -\textit{SCCS} ne fonctionnait que sur des fichiers individuels, et obligeait chaque 74.113 -personne travaillant sur le projet d'avoir un accès à un répertoire de 74.114 -travail commun, sur le même système. Seulement une seule personne pouvait 74.115 -modifier un fichier au même moment, ce fonctionnement était assuré par 74.116 -l'utilisation de verrou (``lock''). Il était courant que des personnes 74.117 -verrouillent des fichiers, et plus tard, oublient de le déverrouiller; 74.118 -empêchant n'importe qui d'autre de travailler sur ces fichiers sans l'aide de 74.119 -l'administrateur... 74.120 - 74.121 -Walter Tichy a développé une alternative libre à \textit{SCCS} au début des 74.122 -années 80, qu'il nomma \textit{RSC (Revison Control System)}. Comme 74.123 -\textit{SCCS}, \textit{RCS} demandait aux développeurs de travailler sur le même 74.124 -répertoire partagé, et de verrouiller les 74.125 -fichiers pour se prémunir de tout conflit issu de modifications concurrentes. 74.126 - 74.127 -Un peu plus tard dans les années 1980, Dick Grune utilisa \textit{RCS} comme 74.128 -une brique de base pour un ensemble de scripts \textit{shell} qu'il intitula 74.129 -cmt, avant de la renommer en \textit{CVS (Concurrent Versions System)}. La 74.130 -grande innovation de CVS était que les développeurs pouvaient travailler 74.131 -simultanément et indépendamment dans leur propre espace de travail. Ces espaces 74.132 -de travail privés assuraient que les développeurs ne se marchent pas 74.133 -mutuellement sur les pieds, comme c'était souvent le cas avec RCS et SCCS. 74.134 -Chaque développeur disposait donc de sa copie de tous les fichiers du projet, 74.135 -et ils pouvaient donc librement les modifier. Ils devaient néanmoins effectuer 74.136 -la ``fusion'' (\textit{``merge''}) de leurs fichiers, avant d'effectuer le 74.137 -``commit'' de leur modifications sur le dépôt central. 74.138 - 74.139 -Brian Berliner reprit les scripts de Grune's et les réécrit en~C, qu'il publia 74.140 -en 1989. Depuis, ce code a été modifié jusqu'à devenir la version moderne de 74.141 -CVS. CVS a acquis ainsi la capacité de fonctionner en réseau, transformant son 74.142 -architecture en client/serveur. L'architecture de CVS est centralisée, seul le 74.143 -serveur a une copie de l'historique du projet. L'espace de travail client ne 74.144 -contient qu'une copie de la dernière version du projet, et quelques métadonnées 74.145 -pour indiquer où le serveur se trouve. CVS a été un grand succès, aujourd'hui 74.146 -il est probablement l'outil de gestion de contrôle le plus utilisé au monde. 74.147 - 74.148 -Au début des années 1990, Sun Microsystmes développa un premier outil de 74.149 -gestion de source distribué, nommé TeamWare. Un espace de travail TeamWare 74.150 -contient une copie complète de l'historique du projet. TeamWare n'a pas de 74.151 -notion de dépôt central. (CVS utilisait RCS pour le stockage de l'historique, 74.152 -TeamWare utilisait SCCS). 74.153 - 74.154 -Alors que les années 1990 avançaient, les utilisateurs ont pris conscience d'un 74.155 -certain nombre de problèmes avec CVS. Il enregistrait simultanément des 74.156 -modifications sur différents fichiers individuellement, au lieu de les 74.157 -regrouper dans une seule opération cohérente et atomique. Il ne gère pas bien 74.158 -sa hiérarchie de fichier, il est donc assez aisé de créer le chaos en renommant 74.159 -les fichiers et les répertoires. Pire encore, son code source est difficile à 74.160 -lire et à maintenir, ce qui agrandit largement le ``niveau de souffrance'' 74.161 -associé à la réparation de ces problèmes d'architecture de manière prohibitive. 74.162 - 74.163 -En 2001, Jim Blandy et Karl Fogel, deux développeurs qui avaient travaillé sur 74.164 -CVS, initièrent un projet pour le remplacer par un outil qui aurait une 74.165 -meilleure architecture et un code plus propre. Le résultat, Subversion, ne 74.166 -quitte pas le modèle centralisé et client/server de CVS, mais ajoute les 74.167 -opérations de ``commit'' atomique sur de multiples fichiers, une meilleure 74.168 -gestion des espaces de noms, et d'autres fonctionnalités qui en font un 74.169 -meilleur outil que CVS. Depuis sa première publication, il est rapidement 74.170 -devenu très populaire. 74.171 - 74.172 -Plus ou moins simultanément, Graydon Hoare a commencé sur l'ambitieux 74.173 -système de gestion distribué Monotone. Bien que Monotone corrige plusieurs 74.174 -défauts de CVS's tout en offrant une architecture ``peer-to-peer'', il va aussi 74.175 -plus loin que la plupart des outils de révision de manière assez innovante. Il 74.176 -utilise des ``hash'' cryptographiques comme identifiants, et il a une notion 74.177 -complète de ``confiance'' du code issu des différentes sources. 74.178 - 74.179 -Mercurial est né en 2005. Bien que très influencé par Monotone, Mercurial se 74.180 -concentre sur la facilité d'utilisation, les performances et la capacité à 74.181 -monter en charge pour de très gros projets. 74.182 - 74.183 -\section{Tendances de la gestion de source} 74.184 - 74.185 -Il y a eu une tendance évidente dans le développement et l'utilisation d'outils 74.186 -de gestion de source depuis les quatre dernières décades, au fur et à mesure 74.187 -que les utilisateurs se sont habitués à leur outils et se sont sentis contraints 74.188 -par leurs limitations. 74.189 - 74.190 -La première génération commença simplement par gérer un fichier unique sur un 74.191 -ordinateur individuel. Cependant, même si ces outils présentaient une grande 74.192 -avancée par rapport à la gestion manuelle des versions, leur modèle de 74.193 -verrouillage et leur utilisation limitée à un seul ordinateur rendaient leur 74.194 -utilisation possible uniquement dans une très petite équipe. 74.195 - 74.196 -La seconde génération a assoupli ces contraintes en adoptant une architecture 74.197 -réseau et centralisée, permettant de gérer plusieurs projets entiers en même 74.198 -temps. Alors que les projets grandirent en taille, ils rencontrèrent de nouveaux 74.199 -problèmes. Avec les clients discutant régulièrement avec le serveurs, la montée 74.200 -en charge devint un réel problème sur les gros projets. Une connexion réseau 74.201 -peu fiable pouvait complètement empêcher les utilisateurs distants de dialoguer 74.202 -avec le serveur. Alors que les projets \textit{Open Source} commencèrent à 74.203 -mettre en place des accès en lecture seule disponible anonymement, les 74.204 -utilisateurs sans les privilèges de ``commit'' réalisèrent qu'ils ne pouvaient 74.205 -pas utiliser les outils pour collaborer naturellement avec le projet, comme ils 74.206 -ne pouvaient pas non plus enregistrer leurs modifications. 74.207 - 74.208 -La génération actuelle des outils de gestion de source est ``peer-to-peer'' par 74.209 -nature. Tout ces systèmes ont abandonné la dépendance à un serveur central, et 74.210 -ont permis à leur utilisateur de distribuer les données de leur gestion de 74.211 -source à qui en a besoin. La collaboration à travers Internet a transformé la 74.212 -contrainte technologique en une simple question de choix et de consencus. Les 74.213 -outils modernes peuvent maintenant fonctionner en mode déconnecté sans limite et 74.214 -de manière autonome, la connexion au réseau n'étant nécessaire que pour 74.215 -synchroniser les modifications avec les autres dépôts. 74.216 - 74.217 -\section{Quelques avantages des gestionnaires de source distribués} 74.218 - 74.219 -Même si les gestionnaire de source distribués sont depuis plusieurs années 74.220 -assez robustes et aussi utilisables que leurs prédécesseurs, les utilisateurs 74.221 -d'autres outils n'y ont pas encore été sensibilisés. Les gestionnaires 74.222 -de source distribués se distinguent particulièrement de leurs équivalents 74.223 -centralisés de nombreuses manières. 74.224 - 74.225 -Pour un développeur individuel, ils restent beaucoup plus rapides que les 74.226 -outils centralisés. Cela pour une raison simple : un outil centralisé doit 74.227 -toujours dialoguer à travers le réseau pour la plupart des opérations, car 74.228 -presque toutes les métadonnées sont stockées sur la seule copie du serveur 74.229 -central. Un outil distribué stocke toute ses métadonnées localement. À tâche 74.230 -égale, effectuer un échange avec le réseau ajoute un délai aux outils 74.231 -centralisés. Ne sous-estimez pas la valeur d'un outil rapide : vous allez 74.232 -passer beaucoup de temps à interagir avec un logiciel de gestion de source. 74.233 - 74.234 -Les outils distribués sont complètement indépendants des aléas de votre serveur, 74.235 -d'autant plus qu'ils répliquent les métadonnées à beaucoup d'endroits. Si 74.236 -votre serveur central prend feu, vous avez intérêt à ce que les médias de 74.237 -sauvegardes soient fiables, et que votre dernier ``backup'' soit récent et 74.238 -fonctionne sans problème. Avec un outil distribué, vous avez autant de 74.239 -``backup'' que de contributeurs. 74.240 - 74.241 -En outre, la fiabilité de votre réseau affectera beaucoup moins les 74.242 -outils distribués. Vous ne pouvez même pas utiliser un outil centralisé 74.243 -sans connexion réseau, à l'exception de quelques commandes, très limitées. 74.244 -Avec un outil distribué, si votre connexion réseau tombe pendant que vous 74.245 -travaillez, vous pouvez ne même pas vous en rendre compte. La seule chose 74.246 -que vous ne serez pas capable de faire sera de communiquer avec des dépôts 74.247 -distants, opération somme toute assez rare en comparaison aux opérations 74.248 -locales. Si vous avez une équipe de collaborateurs très dispersée ceci peut 74.249 -être significatif. 74.250 - 74.251 -\subsection{Avantages pour les projets \textit{Open Source}} 74.252 - 74.253 -Si vous prenez goût à un projet \textit{Open Source} et que vous 74.254 -décidez de commencer à toucher à son code, et que le projet utilise 74.255 -un gestionnaire de source distribué, vous êtes immédiatement un "pair" 74.256 -avec les personnes formant le ``cœur'' du projet. Si ils publient 74.257 -leurs dépôts, vous pouvez immédiatement copier leurs historiques de 74.258 -projet, faire des modifications, enregistrer votre travail en utilisant 74.259 -les même outils qu'eux. Par comparaison, avec un outil centralisé, vous 74.260 -devez utiliser un logiciel en mode ``lecture seule'' à moins que 74.261 -quelqu'un ne vous donne les privilèges de ``commit'' sur le serveur 74.262 -central. Avant ça, vous ne serez pas capable d'enregistrer vos 74.263 -modifications, et vos propres modifications risqueront de se 74.264 -corrompre chaque fois que vous essayerez de mettre à jour à votre 74.265 -espace de travail avec le serveur central. 74.266 - 74.267 -\subsubsection{Le non-problème du \textit{fork}} 74.268 - 74.269 -Il a été souvent suggéré que les gestionnaires de source distribués 74.270 -posent un risque pour les projets \textit{Open Source} car ils 74.271 -facilitent grandement la création de ``fork''\footnote{NdT:Création 74.272 -d'une 74.273 -\url{version alternative du logiciel}{http://fr.wikipedia.org/wiki/Fork\#Embranchement\_d.27un\_projet\_informatique}.} 74.274 -Un ``fork'' apparait quand il y des divergences d'opinion ou d'attitude 74.275 -au sein d'un groupe de développeurs qui aboutissent à la décision de ne 74.276 -plus travailler ensemble. Chaque parti s'empare d'une copie plus ou moins 74.277 -complète du code source du projet et continue dans sa propre direction. 74.278 - 74.279 -Parfois ces différents partis décident de se réconcilier. Avec un 74.280 -serveur central, l'aspect \emph{technique} de cette réconciliation 74.281 -est un processus douloureux, et essentiellement manuel. Vous devez 74.282 -décider quelle modification est ``la gagnante'', et replacer, par un 74.283 -moyen ou un autre, les modifications de l'autre équipe dans l'arborescence 74.284 -du projet. Ceci implique généralement la perte d'une partie de l'historique 74.285 -d'un des partis, ou même des deux. 74.286 - 74.287 -Ce que les outils distribués permettent à ce sujet est probablement 74.288 -la \emph{meilleure} façon de développer un projet. Chaque modification 74.289 -que vous effectuez est potentiellement un ``fork''. La grande force de 74.290 -cette approche est que les gestionnaires de source distribués doivent être 74.291 -vraiment très efficaces pour \emph{fusionner}\footnote{NdT:j'ai choisi de 74.292 -traduire ici \textit{merging} par ``fusionner'' pour des raisons de clarté} 74.293 -des ``forks'', car les ``forks'', dans ce contexte, arrivent tout le 74.294 -temps. 74.295 - 74.296 -Si chaque altération que n'importe qui effectue, à tout moment, est vue 74.297 -comme un ``fork'' à fusionner, alors ce que le monde de l'\textit{Open 74.298 -Source} voit comme un ``fork'' devient \emph{uniquement} une problématique 74.299 -sociale. En fait, les outils de gestions de source distribués \emph{réduisent} 74.300 -les chances de ``fork'': 74.301 -\begin{itemize} 74.302 -\item Ils éliminent la distinction sociale qu'imposent les outils centralisés 74.303 - entre les membres du projets (ceux qui ont accès au ``commit'') et ceux de 74.304 - l'extérieur (ce qui ne l'ont pas). \item Ils rendent plus facile la 74.305 - réconciliation après un ``fork'' social, car 74.306 - tout ce qu'elle implique est une simple fusion. 74.307 -\end{itemize} 74.308 - 74.309 -Certaines personnes font de la résistance envers les gestionnaires de source 74.310 -distribués parce qu'ils veulent garder un contrôle ferme sur leur projet, et 74.311 -ils pensent que les outils centralisés leur fournissent ce contrôle. Néanmoins, 74.312 -si c'est votre cas, sachez que si vous publiez votre dépôt CVS ou Subversion 74.313 -de manière publique, il existe une quantité d'outils disponibles pour récupérer 74.314 -entièrement votre projet et son historique (quoique lentement) et le récréer 74.315 -ailleurs, sans votre contrôle. En fait, votre contrôle sur votre projet est 74.316 -illusoire, vous ne faites qu'interdire à vos collaborateurs de travailler 74.317 -de manière fluide, en disposant d'un miroir ou d'un ``fork'' de votre 74.318 -historique. 74.319 -%%%TODO: Fussy, those last sentences are not really well translated: 74.320 -%%%no problem for me (wilk) 74.321 -%However, if you're of this belief, and you publish your CVS or Subversion 74.322 -%repositories publically, there are plenty of tools available that can pull 74.323 -%out your entire project's history (albeit slowly) and recreate it somewhere 74.324 -%that you don't control. So while your control in this case is illusory, you are 74.325 -%forgoing the ability to fluidly collaborate with whatever people feel 74.326 -%compelled to mirror and fork your history. 74.327 - 74.328 -\subsection{Avantages pour les projets commerciaux} 74.329 - 74.330 -Beaucoup de projets commerciaux sont réalisés par des équipes éparpillées 74.331 -à travers le globe. Les contributeurs qui sont loin du serveur central 74.332 -devront subir des commandes lentes et même parfois peu fiables. Les 74.333 -solutions propriétaires de gestion de source tentent de palier ce problème 74.334 -avec des réplications de sites distants qui sont à la fois coûteuses à mettre 74.335 -en place et lourdes à administrer. Un système distribué ne souffre pas 74.336 -de ce genre de problèmes. En outre, il est très aisé de mettre en place 74.337 -plusieurs serveurs de références, disons un par site, de manière à ce qu'il 74.338 -n'y ait pas de communication redondante entre les dépôts, sur une connexion 74.339 -longue distance souvent onéreuse. 74.340 - 74.341 -Les systèmes de gestion de source supportent généralement assez mal la 74.342 -montée en charge. Ce n'est pas rare pour un gestionnaire de source centralisé 74.343 -pourtant onéreux de s'effondrer sous la charge combinée d'une douzaine 74.344 -d'utilisateurs concurrents seulement. Une fois encore, la réponse à cette problématique 74.345 -est généralement encore la mise en place d'un ensemble complexe de serveurs 74.346 -synchronisés par un mécanisme de réplication. Dans le cas d'un gestionnaire 74.347 -de source distribué, la charge du serveur central --- si vous avez un--- est 74.348 -plusieurs fois inférieure (car toutes les données sont déjà répliquées ailleurs), 74.349 -un simple serveur, pas très cher, peut gérer les besoins d'une plus grande 74.350 -équipe, et la réplication pour balancer la charge devient le 74.351 -travail d'un simple script. 74.352 - 74.353 -Si vous avez des employés sur le terrain, en train de chercher à résoudre un souci sur 74.354 -le site d'un client, ils bénéficieront aussi d'un gestionnaire de source 74.355 -distribué. Cet outil leur permettra de générer des versions personnalisées, 74.356 -d'essayer différentes solutions, en les isolant aisément les unes des autres, 74.357 -et de rechercher efficacement à travers l'historique des sources, la cause 74.358 -des bugs ou des régressions, tout ceci sans avoir besoin de la moindre 74.359 -connexion au réseau de votre compagnie. 74.360 - 74.361 -\section{Pourquoi choisir Mercurial?} 74.362 - 74.363 -Mercurial a plusieurs caractéristiques qui en font un choix particulièrement 74.364 -pertinent pour la gestion de source: 74.365 -\begin{itemize} 74.366 - \item Il est facile à apprendre et à utiliser ; 74.367 - \item Il est léger et performant ; 74.368 - \item Il monte facilement en charge ; 74.369 - \item Il est facile à personnaliser ; 74.370 -\end{itemize} 74.371 - 74.372 -Si vous êtes déjà familier d'un outil de gestion de source, vous serez 74.373 -capable de l'utiliser en moins de 5 minutes. Sinon, ça ne sera pas beaucoup 74.374 -plus long\footnote{NdT: Pour appuyer le propos de l'auteur, je signale que 74.375 -j'utilise Mercurial comme outil d'initiation à la gestion de contrôle dans 74.376 -des travaux pratiques à l'ESME Sudria (\url{http://www.esme.fr}) et que les 74.377 -élèves le prennent en main sans difficulté majeure malgré l'approche distribuée.}. 74.378 -Les commandes utilisées par Mercurial, comme ses fonctionnalités, sont 74.379 -généralement uniformes et cohérentes, et vous pouvez donc ainsi garder en tête 74.380 -simplement quelques règles générales, plutôt qu'un lot complexe d'exceptions. 74.381 - 74.382 -Sur un petit projet, vous pouvez commencer à travailler avec Mercurial en 74.383 -quelques instants. Ajouter des modifications ou des branches, transférer 74.384 -ces modifications (localement ou via le réseau), et les opérations 74.385 -d'historique ou de statut sont aussi très rapides. Mercurial reste hors de 74.386 -votre chemin grâce à sa simplicité d'utilisation et sa rapidité d'exécution. 74.387 - 74.388 -L'utilité de Mercurial ne se limite pas à de petits projets: il est 74.389 -aussi utilisé par des projets ayant des centaines ou même des milliers 74.390 -de contributeurs, avec plusieurs dizaines de milliers de fichiers, et des 74.391 -centaines de méga de code source. 74.392 - 74.393 -Voici une liste non exhaustive des projets complexes ou critiques utilisant 74.394 -Mercurial : 74.395 -%TODO 74.396 -% For both spanish and english version, add the following examples: 74.397 -\begin{itemize} 74.398 - \item \url{Firefox}{https://developer.mozilla.org/en/Mozilla\_Source\_Code\_(Mercurial)} ; 74.399 - \item \url{OpenSolaris}{http://opensolaris.org/os/community/tools/scm/hg\_help/} ; 74.400 - \item \url{OpenJDK}{http://hg.openjdk.java.net/} (utilisant en outre l'extension 74.401 - ``forest'' pour gérer ses sous modules); 74.402 -\end{itemize} 74.403 - 74.404 -Si les fonctionnalités cœur de Mercurial ne sont pas suffisantes pour vous, 74.405 -il est très aisé d'en construire d'autres. Mercurial est adapté à l'utilisation 74.406 -de scripts, et son implémentation interne en Python, propre et claire, 74.407 -rend encore plus facile l'ajout de fonctionnalités sous forme d'extensions. Il 74.408 -en existe déjà un certain nombre de très populaires et très utiles, 74.409 -dont le périmètre va de la recherche de bugs à l'amélioration des performances. 74.410 - 74.411 -\section{Mercurial comparé aux autres outils} 74.412 - 74.413 -Avant que vous n'alliez plus loin, comprenez bien que cette section 74.414 -reflète mes propres expériences, et elle est donc (j'ose le dire) 74.415 -peu objective. Néanmoins, j'ai utilisé les outils de gestion de source 74.416 -listés ci dessous, dans la plupart des cas, pendant plusieurs années. 74.417 -%% TODO: Fussy translation. 74.418 - 74.419 -\subsection{Subversion} 74.420 - 74.421 -Subversion est un des outils de gestion de source les plus populaire, il fût 74.422 -développé pour remplacer CVS. Il a une architecture client/server centralisée. 74.423 - 74.424 -Subversion et Mercurial ont des noms de commandes très similaires pour 74.425 -les mêmes opérations, ainsi si vous êtes familier avec l'un, c'est facile 74.426 -d'apprendre l'autre. Ces deux outils sont portables sur les systèmes 74.427 -d'exploitation les plus populaires\footnote{NdT:Mercurial fonctionne sans problème 74.428 -sur OpenVMS à l'ESME Sudria \url{http://www.esme.fr}, compte tenu que Subversion a été 74.429 -développé en C, je ne suis pas sûr que son portage aurait été aussi aisé.}. 74.430 -%TODO: Backport this statement in english and spanish 74.431 - 74.432 -Avant la version 1.5, Subversion n'offrait aucune forme de support pour les fusions. Lors 74.433 -de l'écriture de ce livre, ses capacités de fusion étaient nouvelles, et réputées pour être 74.434 -\href{http://svnbook.red-bean.com/nightly/en/svn.branchmerge.advanced.html#svn.branchmerge.advanced.finalword}{complexes 74.435 -et bugguées}. 74.436 - 74.437 -Mercurial dispose d'un avantage substantiel en terme de performance par rapport à 74.438 -Subversion sur la plupart des opérations que j'ai pu tester. J'ai mesuré 74.439 -une différence de performance allant de deux à six fois plus rapide avec 74.440 -le système de stockage de fichier local de Subversion~1.4.3 74.441 -(\emph{ra\_local}), qui est la méthode d'accès la plus rapide disponible. Dans 74.442 -un déploiement plus réaliste, impliquant un stockage réseau, Subversion 74.443 -serait encore plus désavantagé. Parce que la plupart des commandes Subversion 74.444 -doivent communiquer avec le serveur et que Subversion n'a pas de mécanisme 74.445 -de réplication, la capacité du serveur et la bande passante sont devenues des 74.446 -goulots d'étranglement pour les projets de taille moyenne ou grande. 74.447 - 74.448 -En outre, Subversion implique une surcharge substantielle dans le stockage local 74.449 -de certaines données, pour éviter des transactions avec le serveur, pour 74.450 -certaines opérations communes, telles que la recherche des fichiers modifiés 74.451 -(\texttt{status}) et l'affichage des modifications par rapport à la révision 74.452 -courante (\texttt{diff}). En conséquence, un répertoire de travail Subversion 74.453 -a souvent la même taille, ou est plus grand, qu'un dépôt Mercurial et son 74.454 -espace de travail, et ceci bien que le dépôt Mercurial contienne l'intégralité 74.455 -de l'historique. 74.456 - 74.457 -Subversion est largement supporté par les outils tierces. Mercurial est 74.458 -actuellement encore en retrait de ce point de vue. L'écart se réduit, néanmoins, 74.459 -et en effet certains des outils graphiques sont maintenant supérieurs à leurs 74.460 -équivalents Subversion. Comme Mercurial, Subversion dispose d'un excellent 74.461 -manuel utilisateur. 74.462 - 74.463 -Parce que Subversion ne stocke pas l'historique chez ses clients, il est 74.464 -parfaitement adapté à la gestion de projets qui doivent suivre un ensemble 74.465 -de larges fichiers binaires et opaques. Si vous suivez une cinquantaine de 74.466 -versions d'un fichier incompressible de 10MB, l'occupation disque coté client 74.467 -d'un projet sous Subversion restera à peu près constante. A l'inverse, 74.468 -l'occupation disque du même projet sous n'importe lequel des gestionnaires 74.469 -de source distribués grandira rapidement, proportionnellement aux nombres 74.470 -de versions, car les différences entre chaque révisions seront très grandes. 74.471 - 74.472 -En outre, c'est souvent difficile ou, généralement, impossible de fusionner 74.473 -des différences dans un fichier binaire. La capacité de Subversion de 74.474 -verrouiller des fichiers, pour permettre à l'utilisateur d'être le seul 74.475 -à le mettre à jour (``commit'') temporairement, est un avantage significatif 74.476 -dans un projet doté de beaucoup de fichiers binaires. 74.477 - 74.478 -Mercurial peut importer l'historique depuis un dépôt Subversion. Il peut 74.479 -aussi exporter l'ensemble des révisions d'un projet vers un dépôt Subversion. 74.480 -Ceci rend très facile de ``prendre la température'' et d'utiliser Mercurial et Subversion 74.481 -en parallèle, avant de décider de migrer vers Mercurial. La conversion de 74.482 -l'historique est incrémentale, donc vous pouvez effectuer une conversion 74.483 -initiale, puis de petites additions par la suite pour ajouter les nouvelles 74.484 -modifications. 74.485 - 74.486 -\subsection{Git} 74.487 - 74.488 -Git est un outil de gestion de source distribué qui fût développé pour gérer 74.489 -le code source de noyau de Linux. Comme Mercurial, sa conception initiale a 74.490 -été inspirée par Monotone. 74.491 - 74.492 -Git dispose d'un ensemble conséquent de commandes, avec plus de~139 commandes 74.493 -individuelles pour la version~1.5.0. Il a aussi la réputation d'être difficile 74.494 -à apprendre. Comparé à Git, le point fort de Mercurial est clairement sa 74.495 -simplicité. 74.496 - 74.497 -En terme de performance, Git est extrêmement rapide. Dans la plupart des 74.498 -cas, il est plus rapide que Mercurial, tout du moins sur Linux, alors que 74.499 -Mercurial peut être plus performant sur d'autres opérations. Néanmoins, sur 74.500 -Windows, les performances et le niveau de support général fourni par Git, 74.501 -au moment de l'écriture de cet ouvrage, est bien derrière celui de Mercurial. 74.502 - 74.503 -Alors que le dépôt Mercurial ne demande aucune maintenance, un dépôt Git 74.504 -exige d'exécuter manuellement et régulièrement la commande ``repacks'' sur 74.505 -ces métadonnées. Sans ceci, les performances de git se dégradent et la 74.506 -consommation de l'espace disque augmente rapidement. Un serveur qui contient 74.507 -plusieurs dépôts Git qui ne sont pas régulièrement et fréquemment ``repacked'' 74.508 -deviendra un vrai problème lors des ``backups'' du disque, et il y eu des 74.509 -cas, où un ``backup'' journalier pouvait durer plus de~24 heures. Un dépôt 74.510 -fraichement ``repacked'' sera légèrement plus petit qu'un dépôt Mercurial, 74.511 -mais un dépôt non ``repacked'' est beaucoup plus grand. 74.512 - 74.513 -Le cœur de Git est écrit en C. La plupart des commandes Git sont implémentées 74.514 -sous forme de scripts Shell ou Perl, et la qualité de ces scripts varie 74.515 -grandement. J'ai plusieurs fois constaté que certains de ces scripts étaient 74.516 -chargés en mémoire aveuglément et que la présence d'erreurs pouvait s'avérer 74.517 -fatal. 74.518 - 74.519 -Mercurial peut importer l'historique d'un dépôt Git. 74.520 - 74.521 -\subsection{CVS} 74.522 - 74.523 -CVS est probablement l'outil de gestion de source le plus utilisé aujourd'hui 74.524 -dans le monde. À cause de son manque de clarté interne, il n'est plus 74.525 -maintenu depuis plusieurs années. 74.526 - 74.527 -Il a une architecture client/serveur centralisée. Il ne regroupe pas les 74.528 -modifications de fichiers dans une opération de ``commit'' atomique, ce 74.529 -qui permet à ses utilisateurs de ``casser le \textit{build}'' assez 74.530 -facilement : une personne peut effectuer une opération de ``commit'' 74.531 -sans problème puis être bloquée par besoin de fusion, avec comme conséquence 74.532 -néfaste, que les autres utilisateurs ne récupèreront qu'une partie de ses 74.533 -modifications. Ce problème affecte aussi la manière de travailler avec 74.534 -l'historique du projet. Si vous voulez voir toutes les modifications d'une 74.535 -personne du projet, vous devrez injecter manuellement les descriptions et les 74.536 -\textit{timestamps} des modifications de chacun des fichiers impliqués (si 74.537 -vous savez au moins quels sont ces fichiers). 74.538 - 74.539 -CVS a une notion étrange des \textit{tags} et des branches que je n'essayerai 74.540 -même pas de décrire ici. Il ne supporte pas bien les opérations de renommage d'un 74.541 -fichier ou d'un répertoire, ce qui facilite la corruption de son dépôt. Il n'a 74.542 -presque pas pour ainsi dire de contrôle de cohérence interne, il est donc 74.543 -pratiquement impossible de dire si un dépôt est corrompu ni à quel point. Je 74.544 -ne recommanderai pas CVS pour un projet existant ou nouveau. 74.545 - 74.546 -Mercurial peut importer l'historique d'un projet CVS. Néanmoins, il y a 74.547 -quelques principes à respecter; ce qui est vrai aussi pour les autres 74.548 -outils d'import de projet CVS. À cause de l'absence de ``commit'' atomique 74.549 -et gestion de version de l'arborescence, il n'est pas possible de reconstruire 74.550 -de manière précise l'ensemble de l'historique. Un travail de ``devinette'' 74.551 -est donc nécessaire, et les fichiers renommés ne sont pas détectés. Parce 74.552 -qu'une bonne part de l'administration d'un dépôt CVS est effectuée manuellement, 74.553 -et est donc, sujette à erreur, il est courant que les imports CVS rencontrent 74.554 -de nombreux problèmes avec les dépôt corrompus (des \textit{timestamps} 74.555 -de révision complètement buggés et des fichiers verrouillés depuis des années 74.556 -sont deux des problèmes les moins intéressants dont je me souvienne). 74.557 - 74.558 -Mercurial peut importer l'historique depuis un dépôt CVS. 74.559 - 74.560 -\subsection{Outils propriétaires} 74.561 - 74.562 -Perforce a une architecture client/serveur centralisée, sans aucun 74.563 -mécanisme de mise en cache de données coté client. Contrairement à la plupart 74.564 -des outils modernes de gestion de source, Perforce exige de ses 74.565 -utilisateurs d'exécuter une commande pour informer le serveur 74.566 -central de tout fichier qu'ils souhaitent modifier. 74.567 - 74.568 -Les performances de Perforce sont plutôt bonnes pour des petites 74.569 -équipes, mais elles s'effondrent rapidement lorsque le nombre 74.570 -d'utilisateurs augmente au delà de la douzaine. Des installations 74.571 -de Perforce assez larges nécessitent le déploiement de proxies pour 74.572 -supporter la montée en charge associée. 74.573 - 74.574 -\subsection{Choisir un outil de gestion de source} 74.575 - 74.576 -A l'exception de CVS, tous les outils listés ci-dessus ont des 74.577 -forces qui leur sont propres et qui correspondent à certaines 74.578 -formes de projet. Il n'y a pas un seul meilleur outil de gestion 74.579 -de source qui correspondrait le mieux à toutes les situations. 74.580 - 74.581 -Par exemple, Subversion est un très bon choix lorsqu'on travaille 74.582 -avec beaucoup de fichiers binaires, qui évoluent régulièrement, grâce 74.583 -à sa nature centralisée et sa capacité à verrouiller des fichiers. 74.584 - 74.585 -Personnellement, je préfère Mercurial pour sa simplicité, ses 74.586 -performances et sa bonne capacité de fusion, et il m'a très bien rendu service 74.587 -de plusieurs années maintenant. 74.588 - 74.589 -\section{Migrer depuis un outil à Mercurial} 74.590 - 74.591 -Mercurial est livré avec une extension nommée \hgext{convert}, qui 74.592 -peut de manière incrémentale importer des révisions depuis différents 74.593 -autres outils de gestion de source. Par ``incrémental'', j'entends que 74.594 -vous pouvez convertir l'historique entier du projet en une seule fois, 74.595 -puis relancer l'outil d'import plus tard pour obtenir les modifications 74.596 -effectuées depuis votre import initial. 74.597 - 74.598 -Les outils de gestion de source supportés par \hgext{convert} sont : 74.599 -\begin{itemize} 74.600 - \item Subversion 74.601 - \item CVS 74.602 - \item Git 74.603 - \item Darcs 74.604 -\end{itemize} 74.605 - 74.606 -En outre, \hgext{convert} peut exporter les modifications depuis Mercurial 74.607 -vers Subversion. Ceci rend possible d'essayer Subversion en parallèle 74.608 -avant de choisir une solution définitive, sans aucun risque de perte de 74.609 -données. 74.610 - 74.611 -La commande \hgxcmd{conver}{convert} est très simple à utiliser. Simplement, 74.612 -indiquez le chemin ou l'URL du dépôt de source, en lui indiquant éventuellement 74.613 -le nom du chemin de destination, et la conversion se met en route. Après cet 74.614 -import initial, il suffit de relancer la commande encore une fois pour 74.615 -importer les modifications effectuées depuis. 74.616 - 74.617 -%%% Local Variables: 74.618 -%%% mode: latex 74.619 -%%% TeX-master: "00book" 74.620 -%%% End:
75.1 Binary file fr/kdiff3.png has changed
76.1 --- a/fr/license.tex Sun Aug 16 03:41:39 2009 +0200 76.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 76.3 @@ -1,138 +0,0 @@ 76.4 -\chapter{Open Publication License} 76.5 -\label{cha:opl} 76.6 - 76.7 -Version 1.0, 8 June 1999 76.8 - 76.9 -\section{Requirements on both unmodified and modified versions} 76.10 - 76.11 -The Open Publication works may be reproduced and distributed in whole 76.12 -or in part, in any medium physical or electronic, provided that the 76.13 -terms of this license are adhered to, and that this license or an 76.14 -incorporation of it by reference (with any options elected by the 76.15 -author(s) and/or publisher) is displayed in the reproduction. 76.16 - 76.17 -Proper form for an incorporation by reference is as follows: 76.18 - 76.19 -\begin{quote} 76.20 - Copyright (c) \emph{year} by \emph{author's name or designee}. This 76.21 - material may be distributed only subject to the terms and conditions 76.22 - set forth in the Open Publication License, v\emph{x.y} or later (the 76.23 - latest version is presently available at 76.24 - \url{http://www.opencontent.org/openpub/}). 76.25 -\end{quote} 76.26 - 76.27 -The reference must be immediately followed with any options elected by 76.28 -the author(s) and/or publisher of the document (see 76.29 -section~\ref{sec:opl:options}). 76.30 - 76.31 -Commercial redistribution of Open Publication-licensed material is 76.32 -permitted. 76.33 - 76.34 -Any publication in standard (paper) book form shall require the 76.35 -citation of the original publisher and author. The publisher and 76.36 -author's names shall appear on all outer surfaces of the book. On all 76.37 -outer surfaces of the book the original publisher's name shall be as 76.38 -large as the title of the work and cited as possessive with respect to 76.39 -the title. 76.40 - 76.41 -\section{Copyright} 76.42 - 76.43 -The copyright to each Open Publication is owned by its author(s) or 76.44 -designee. 76.45 - 76.46 -\section{Scope of license} 76.47 - 76.48 -The following license terms apply to all Open Publication works, 76.49 -unless otherwise explicitly stated in the document. 76.50 - 76.51 -Mere aggregation of Open Publication works or a portion of an Open 76.52 -Publication work with other works or programs on the same media shall 76.53 -not cause this license to apply to those other works. The aggregate 76.54 -work shall contain a notice specifying the inclusion of the Open 76.55 -Publication material and appropriate copyright notice. 76.56 - 76.57 -\textbf{Severability}. If any part of this license is found to be 76.58 -unenforceable in any jurisdiction, the remaining portions of the 76.59 -license remain in force. 76.60 - 76.61 -\textbf{No warranty}. Open Publication works are licensed and provided 76.62 -``as is'' without warranty of any kind, express or implied, including, 76.63 -but not limited to, the implied warranties of merchantability and 76.64 -fitness for a particular purpose or a warranty of non-infringement. 76.65 - 76.66 -\section{Requirements on modified works} 76.67 - 76.68 -All modified versions of documents covered by this license, including 76.69 -translations, anthologies, compilations and partial documents, must 76.70 -meet the following requirements: 76.71 - 76.72 -\begin{enumerate} 76.73 -\item The modified version must be labeled as such. 76.74 -\item The person making the modifications must be identified and the 76.75 - modifications dated. 76.76 -\item Acknowledgement of the original author and publisher if 76.77 - applicable must be retained according to normal academic citation 76.78 - practices. 76.79 -\item The location of the original unmodified document must be 76.80 - identified. 76.81 -\item The original author's (or authors') name(s) may not be used to 76.82 - assert or imply endorsement of the resulting document without the 76.83 - original author's (or authors') permission. 76.84 -\end{enumerate} 76.85 - 76.86 -\section{Good-practice recommendations} 76.87 - 76.88 -In addition to the requirements of this license, it is requested from 76.89 -and strongly recommended of redistributors that: 76.90 - 76.91 -\begin{enumerate} 76.92 -\item If you are distributing Open Publication works on hardcopy or 76.93 - CD-ROM, you provide email notification to the authors of your intent 76.94 - to redistribute at least thirty days before your manuscript or media 76.95 - freeze, to give the authors time to provide updated documents. This 76.96 - notification should describe modifications, if any, made to the 76.97 - document. 76.98 -\item All substantive modifications (including deletions) be either 76.99 - clearly marked up in the document or else described in an attachment 76.100 - to the document. 76.101 -\item Finally, while it is not mandatory under this license, it is 76.102 - considered good form to offer a free copy of any hardcopy and CD-ROM 76.103 - expression of an Open Publication-licensed work to its author(s). 76.104 -\end{enumerate} 76.105 - 76.106 -\section{License options} 76.107 -\label{sec:opl:options} 76.108 - 76.109 -The author(s) and/or publisher of an Open Publication-licensed 76.110 -document may elect certain options by appending language to the 76.111 -reference to or copy of the license. These options are considered part 76.112 -of the license instance and must be included with the license (or its 76.113 -incorporation by reference) in derived works. 76.114 - 76.115 -\begin{enumerate}[A] 76.116 -\item To prohibit distribution of substantively modified versions 76.117 - without the explicit permission of the author(s). ``Substantive 76.118 - modification'' is defined as a change to the semantic content of the 76.119 - document, and excludes mere changes in format or typographical 76.120 - corrections. 76.121 - 76.122 - To accomplish this, add the phrase ``Distribution of substantively 76.123 - modified versions of this document is prohibited without the 76.124 - explicit permission of the copyright holder.'' to the license 76.125 - reference or copy. 76.126 - 76.127 -\item To prohibit any publication of this work or derivative works in 76.128 - whole or in part in standard (paper) book form for commercial 76.129 - purposes is prohibited unless prior permission is obtained from the 76.130 - copyright holder. 76.131 - 76.132 - To accomplish this, add the phrase ``Distribution of the work or 76.133 - derivative of the work in any standard (paper) book form is 76.134 - prohibited unless prior permission is obtained from the copyright 76.135 - holder.'' to the license reference or copy. 76.136 -\end{enumerate} 76.137 - 76.138 -%%% Local Variables: 76.139 -%%% mode: latex 76.140 -%%% TeX-master: "00book" 76.141 -%%% End:
77.1 --- a/fr/metadata.svg Sun Aug 16 03:41:39 2009 +0200 77.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 77.3 @@ -1,328 +0,0 @@ 77.4 -<?xml version="1.0" encoding="UTF-8" standalone="no"?> 77.5 -<!-- Created with Inkscape (http://www.inkscape.org/) --> 77.6 -<svg 77.7 - xmlns:dc="http://purl.org/dc/elements/1.1/" 77.8 - xmlns:cc="http://web.resource.org/cc/" 77.9 - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 77.10 - xmlns:svg="http://www.w3.org/2000/svg" 77.11 - xmlns="http://www.w3.org/2000/svg" 77.12 - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" 77.13 - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" 77.14 - width="744.09448819" 77.15 - height="1052.3622047" 77.16 - id="svg2" 77.17 - sodipodi:version="0.32" 77.18 - inkscape:version="0.44.1" 77.19 - sodipodi:docname="metadata.svg" 77.20 - sodipodi:docbase="/home/bos/hg/hgbook/en"> 77.21 - <defs 77.22 - id="defs4"> 77.23 - <marker 77.24 - inkscape:stockid="Arrow1Mend" 77.25 - orient="auto" 77.26 - refY="0.0" 77.27 - refX="0.0" 77.28 - id="Arrow1Mend" 77.29 - style="overflow:visible;"> 77.30 - <path 77.31 - id="path2944" 77.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 " 77.33 - style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;" 77.34 - transform="scale(0.4) rotate(180) translate(10,0)" /> 77.35 - </marker> 77.36 - </defs> 77.37 - <sodipodi:namedview 77.38 - id="base" 77.39 - pagecolor="#ffffff" 77.40 - bordercolor="#666666" 77.41 - borderopacity="1.0" 77.42 - gridtolerance="10000" 77.43 - guidetolerance="10" 77.44 - objecttolerance="10" 77.45 - inkscape:pageopacity="0.0" 77.46 - inkscape:pageshadow="2" 77.47 - inkscape:zoom="1.4" 77.48 - inkscape:cx="232.14286" 77.49 - inkscape:cy="490.68696" 77.50 - inkscape:document-units="px" 77.51 - inkscape:current-layer="layer1" 77.52 - inkscape:window-width="906" 77.53 - inkscape:window-height="620" 77.54 - inkscape:window-x="181" 77.55 - inkscape:window-y="58" /> 77.56 - <metadata 77.57 - id="metadata7"> 77.58 - <rdf:RDF> 77.59 - <cc:Work 77.60 - rdf:about=""> 77.61 - <dc:format>image/svg+xml</dc:format> 77.62 - <dc:type 77.63 - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 77.64 - </cc:Work> 77.65 - </rdf:RDF> 77.66 - </metadata> 77.67 - <g 77.68 - inkscape:label="Layer 1" 77.69 - inkscape:groupmode="layer" 77.70 - id="layer1"> 77.71 - <path 77.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" 77.73 - d="M 326.94646,467.18359 L 326.94646,510.98123" 77.74 - id="path1910" 77.75 - inkscape:connector-type="polyline" 77.76 - inkscape:connection-end="#rect2962" 77.77 - inkscape:connection-start="#rect2764" /> 77.78 - <path 77.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" 77.80 - d="M 326.94646,531.98123 L 326.94646,591.77887" 77.81 - id="path1912" 77.82 - inkscape:connector-type="polyline" 77.83 - inkscape:connection-start="#rect2962" 77.84 - inkscape:connection-end="#rect3000" /> 77.85 - <path 77.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" 77.87 - d="M 316.1622,531.98123 L 192.30212,652.57648" 77.88 - id="path1916" 77.89 - inkscape:connector-type="polyline" 77.90 - inkscape:connection-end="#rect3038" 77.91 - inkscape:connection-start="#rect2962" /> 77.92 - <path 77.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" 77.94 - d="M 254.23217,467.18359 L 254.23216,510.98123" 77.95 - id="path3088" 77.96 - inkscape:connector-type="polyline" 77.97 - inkscape:connection-start="#rect1872" 77.98 - inkscape:connection-end="#rect2960" /> 77.99 - <path 77.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" 77.101 - d="M 254.23215,531.98123 L 254.23215,591.77887" 77.102 - id="path3090" 77.103 - inkscape:connector-type="polyline" 77.104 - inkscape:connection-start="#rect2960" 77.105 - inkscape:connection-end="#rect2998" /> 77.106 - <path 77.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" 77.108 - d="M 248.84002,531.98123 L 186.90999,652.57648" 77.109 - id="path3092" 77.110 - inkscape:connector-type="polyline" 77.111 - inkscape:connection-start="#rect2960" 77.112 - inkscape:connection-end="#rect3038" /> 77.113 - <rect 77.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" 77.115 - id="rect1872" 77.116 - width="51.42857" 77.117 - height="20" 77.118 - x="228.51788" 77.119 - y="446.68359" /> 77.120 - <rect 77.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" 77.122 - id="rect2764" 77.123 - width="51.42857" 77.124 - height="20" 77.125 - x="301.23218" 77.126 - y="446.68359" /> 77.127 - <rect 77.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" 77.129 - id="rect2766" 77.130 - width="51.42857" 77.131 - height="20" 77.132 - x="155.80359" 77.133 - y="446.68359" /> 77.134 - <rect 77.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" 77.136 - id="rect2768" 77.137 - width="51.42857" 77.138 - height="20" 77.139 - x="83.089294" 77.140 - y="446.68359" /> 77.141 - <path 77.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" 77.143 - d="M 135.01786,456.68359 L 155.30359,456.68359" 77.144 - id="path2770" 77.145 - inkscape:connector-type="polyline" 77.146 - inkscape:connection-start="#rect2768" 77.147 - inkscape:connection-end="#rect2766" /> 77.148 - <path 77.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" 77.150 - d="M 207.73216,456.68359 L 228.01788,456.68359" 77.151 - id="path2772" 77.152 - inkscape:connector-type="polyline" 77.153 - inkscape:connection-start="#rect2766" 77.154 - inkscape:connection-end="#rect1872" /> 77.155 - <path 77.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" 77.157 - d="M 280.44645,456.68359 L 300.73218,456.68359" 77.158 - id="path2774" 77.159 - inkscape:connector-type="polyline" 77.160 - inkscape:connection-start="#rect1872" 77.161 - inkscape:connection-end="#rect2764" /> 77.162 - <path 77.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" 77.164 - d="M 62.303571,456.68359 L 82.589294,456.68359" 77.165 - id="path2778" 77.166 - inkscape:connector-type="polyline" 77.167 - inkscape:connection-end="#rect2768" /> 77.168 - <rect 77.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" 77.170 - id="rect2960" 77.171 - width="51.42857" 77.172 - height="20" 77.173 - x="228.51787" 77.174 - y="511.48123" /> 77.175 - <rect 77.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" 77.177 - id="rect2962" 77.178 - width="51.42857" 77.179 - height="20" 77.180 - x="301.23218" 77.181 - y="511.48123" /> 77.182 - <rect 77.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" 77.184 - id="rect2964" 77.185 - width="51.42857" 77.186 - height="20" 77.187 - x="155.80357" 77.188 - y="511.48123" /> 77.189 - <rect 77.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" 77.191 - id="rect2966" 77.192 - width="51.42857" 77.193 - height="20" 77.194 - x="83.089287" 77.195 - y="511.48123" /> 77.196 - <path 77.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" 77.198 - d="M 135.01786,521.48121 L 155.30359,521.48121" 77.199 - id="path2968" 77.200 - inkscape:connector-type="polyline" /> 77.201 - <path 77.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" 77.203 - d="M 207.73216,521.48121 L 228.01788,521.48121" 77.204 - id="path2970" 77.205 - inkscape:connector-type="polyline" /> 77.206 - <path 77.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" 77.208 - d="M 280.44645,521.48121 L 300.73218,521.48121" 77.209 - id="path2972" 77.210 - inkscape:connector-type="polyline" /> 77.211 - <path 77.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" 77.213 - d="M 62.30358,521.48121 L 82.5893,521.48121" 77.214 - id="path2974" 77.215 - inkscape:connector-type="polyline" /> 77.216 - <rect 77.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" 77.218 - id="rect2998" 77.219 - width="51.42857" 77.220 - height="20" 77.221 - x="228.51787" 77.222 - y="592.27887" /> 77.223 - <rect 77.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" 77.225 - id="rect3000" 77.226 - width="51.42857" 77.227 - height="20" 77.228 - x="301.23218" 77.229 - y="592.27887" /> 77.230 - <rect 77.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" 77.232 - id="rect3002" 77.233 - width="51.42857" 77.234 - height="20" 77.235 - x="155.80357" 77.236 - y="592.27887" /> 77.237 - <rect 77.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" 77.239 - id="rect3004" 77.240 - width="51.42857" 77.241 - height="20" 77.242 - x="83.089287" 77.243 - y="592.27887" /> 77.244 - <path 77.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" 77.246 - d="M 135.01786,602.27884 L 155.30359,602.27884" 77.247 - id="path3006" 77.248 - inkscape:connector-type="polyline" /> 77.249 - <path 77.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" 77.251 - d="M 207.73216,602.27884 L 228.01788,602.27884" 77.252 - id="path3008" 77.253 - inkscape:connector-type="polyline" /> 77.254 - <path 77.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" 77.256 - d="M 280.44645,602.27884 L 300.73218,602.27884" 77.257 - id="path3010" 77.258 - inkscape:connector-type="polyline" /> 77.259 - <path 77.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" 77.261 - d="M 62.30358,602.27884 L 82.5893,602.27884" 77.262 - id="path3012" 77.263 - inkscape:connector-type="polyline" /> 77.264 - <rect 77.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" 77.266 - id="rect3034" 77.267 - width="51.42857" 77.268 - height="20" 77.269 - x="228.51787" 77.270 - y="653.07648" /> 77.271 - <rect 77.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" 77.273 - id="rect3038" 77.274 - width="51.42857" 77.275 - height="20" 77.276 - x="155.80357" 77.277 - y="653.07648" /> 77.278 - <rect 77.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" 77.280 - id="rect3040" 77.281 - width="51.42857" 77.282 - height="20" 77.283 - x="83.089287" 77.284 - y="653.07648" /> 77.285 - <path 77.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" 77.287 - d="M 135.01786,663.07646 L 155.30359,663.07646" 77.288 - id="path3042" 77.289 - inkscape:connector-type="polyline" /> 77.290 - <path 77.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" 77.292 - d="M 207.73216,663.07646 L 228.01788,663.07646" 77.293 - id="path3044" 77.294 - inkscape:connector-type="polyline" /> 77.295 - <path 77.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" 77.297 - d="M 62.30358,663.07646 L 82.5893,663.07646" 77.298 - id="path3048" 77.299 - inkscape:connector-type="polyline" /> 77.300 - <text 77.301 - xml:space="preserve" 77.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" 77.303 - x="82.072548" 77.304 - y="432.64789" 77.305 - id="text3094"><tspan 77.306 - sodipodi:role="line" 77.307 - id="tspan3096" 77.308 - x="82.072548" 77.309 - y="432.64789">Changelog</tspan></text> 77.310 - <text 77.311 - xml:space="preserve" 77.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" 77.313 - x="82.306923" 77.314 - y="498.97327" 77.315 - id="text3098"><tspan 77.316 - sodipodi:role="line" 77.317 - id="tspan3100" 77.318 - x="82.306923" 77.319 - y="498.97327">Manifest</tspan></text> 77.320 - <text 77.321 - xml:space="preserve" 77.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" 77.323 - x="82.14286" 77.324 - y="580.08569" 77.325 - id="text3102"><tspan 77.326 - sodipodi:role="line" 77.327 - id="tspan3104" 77.328 - x="82.14286" 77.329 - y="580.08569">Filelogs</tspan></text> 77.330 - </g> 77.331 -</svg>
78.1 --- a/fr/mq-collab.tex Sun Aug 16 03:41:39 2009 +0200 78.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 78.3 @@ -1,393 +0,0 @@ 78.4 -\chapter{Advanced uses of Mercurial Queues} 78.5 -\label{chap:mq-collab} 78.6 - 78.7 -While it's easy to pick up straightforward uses of Mercurial Queues, 78.8 -use of a little discipline and some of MQ's less frequently used 78.9 -capabilities makes it possible to work in complicated development 78.10 -environments. 78.11 - 78.12 -In this chapter, I will use as an example a technique I have used to 78.13 -manage the development of an Infiniband device driver for the Linux 78.14 -kernel. The driver in question is large (at least as drivers go), 78.15 -with 25,000 lines of code spread across 35 source files. It is 78.16 -maintained by a small team of developers. 78.17 - 78.18 -While much of the material in this chapter is specific to Linux, the 78.19 -same principles apply to any code base for which you're not the 78.20 -primary owner, and upon which you need to do a lot of development. 78.21 - 78.22 -\section{The problem of many targets} 78.23 - 78.24 -The Linux kernel changes rapidly, and has never been internally 78.25 -stable; developers frequently make drastic changes between releases. 78.26 -This means that a version of the driver that works well with a 78.27 -particular released version of the kernel will not even \emph{compile} 78.28 -correctly against, typically, any other version. 78.29 - 78.30 -To maintain a driver, we have to keep a number of distinct versions of 78.31 -Linux in mind. 78.32 -\begin{itemize} 78.33 -\item One target is the main Linux kernel development tree. 78.34 - Maintenance of the code is in this case partly shared by other 78.35 - developers in the kernel community, who make ``drive-by'' 78.36 - modifications to the driver as they develop and refine kernel 78.37 - subsystems. 78.38 -\item We also maintain a number of ``backports'' to older versions of 78.39 - the Linux kernel, to support the needs of customers who are running 78.40 - older Linux distributions that do not incorporate our drivers. (To 78.41 - \emph{backport} a piece of code is to modify it to work in an older 78.42 - version of its target environment than the version it was developed 78.43 - for.) 78.44 -\item Finally, we make software releases on a schedule that is 78.45 - necessarily not aligned with those used by Linux distributors and 78.46 - kernel developers, so that we can deliver new features to customers 78.47 - without forcing them to upgrade their entire kernels or 78.48 - distributions. 78.49 -\end{itemize} 78.50 - 78.51 -\subsection{Tempting approaches that don't work well} 78.52 - 78.53 -There are two ``standard'' ways to maintain a piece of software that 78.54 -has to target many different environments. 78.55 - 78.56 -The first is to maintain a number of branches, each intended for a 78.57 -single target. The trouble with this approach is that you must 78.58 -maintain iron discipline in the flow of changes between repositories. 78.59 -A new feature or bug fix must start life in a ``pristine'' repository, 78.60 -then percolate out to every backport repository. Backport changes are 78.61 -more limited in the branches they should propagate to; a backport 78.62 -change that is applied to a branch where it doesn't belong will 78.63 -probably stop the driver from compiling. 78.64 - 78.65 -The second is to maintain a single source tree filled with conditional 78.66 -statements that turn chunks of code on or off depending on the 78.67 -intended target. Because these ``ifdefs'' are not allowed in the 78.68 -Linux kernel tree, a manual or automatic process must be followed to 78.69 -strip them out and yield a clean tree. A code base maintained in this 78.70 -fashion rapidly becomes a rat's nest of conditional blocks that are 78.71 -difficult to understand and maintain. 78.72 - 78.73 -Neither of these approaches is well suited to a situation where you 78.74 -don't ``own'' the canonical copy of a source tree. In the case of a 78.75 -Linux driver that is distributed with the standard kernel, Linus's 78.76 -tree contains the copy of the code that will be treated by the world 78.77 -as canonical. The upstream version of ``my'' driver can be modified 78.78 -by people I don't know, without me even finding out about it until 78.79 -after the changes show up in Linus's tree. 78.80 - 78.81 -These approaches have the added weakness of making it difficult to 78.82 -generate well-formed patches to submit upstream. 78.83 - 78.84 -In principle, Mercurial Queues seems like a good candidate to manage a 78.85 -development scenario such as the above. While this is indeed the 78.86 -case, MQ contains a few added features that make the job more 78.87 -pleasant. 78.88 - 78.89 -\section{Conditionally applying patches with 78.90 - guards} 78.91 - 78.92 -Perhaps the best way to maintain sanity with so many targets is to be 78.93 -able to choose specific patches to apply for a given situation. MQ 78.94 -provides a feature called ``guards'' (which originates with quilt's 78.95 -\texttt{guards} command) that does just this. To start off, let's 78.96 -create a simple repository for experimenting in. 78.97 -\interaction{mq.guards.init} 78.98 -This gives us a tiny repository that contains two patches that don't 78.99 -have any dependencies on each other, because they touch different files. 78.100 - 78.101 -The idea behind conditional application is that you can ``tag'' a 78.102 -patch with a \emph{guard}, which is simply a text string of your 78.103 -choosing, then tell MQ to select specific guards to use when applying 78.104 -patches. MQ will then either apply, or skip over, a guarded patch, 78.105 -depending on the guards that you have selected. 78.106 - 78.107 -A patch can have an arbitrary number of guards; 78.108 -each one is \emph{positive} (``apply this patch if this guard is 78.109 -selected'') or \emph{negative} (``skip this patch if this guard is 78.110 -selected''). A patch with no guards is always applied. 78.111 - 78.112 -\section{Controlling the guards on a patch} 78.113 - 78.114 -The \hgxcmd{mq}{qguard} command lets you determine which guards should 78.115 -apply to a patch, or display the guards that are already in effect. 78.116 -Without any arguments, it displays the guards on the current topmost 78.117 -patch. 78.118 -\interaction{mq.guards.qguard} 78.119 -To set a positive guard on a patch, prefix the name of the guard with 78.120 -a ``\texttt{+}''. 78.121 -\interaction{mq.guards.qguard.pos} 78.122 -To set a negative guard on a patch, prefix the name of the guard with 78.123 -a ``\texttt{-}''. 78.124 -\interaction{mq.guards.qguard.neg} 78.125 - 78.126 -\begin{note} 78.127 - The \hgxcmd{mq}{qguard} command \emph{sets} the guards on a patch; it 78.128 - doesn't \emph{modify} them. What this means is that if you run 78.129 - \hgcmdargs{qguard}{+a +b} on a patch, then \hgcmdargs{qguard}{+c} on 78.130 - the same patch, the \emph{only} guard that will be set on it 78.131 - afterwards is \texttt{+c}. 78.132 -\end{note} 78.133 - 78.134 -Mercurial stores guards in the \sfilename{series} file; the form in 78.135 -which they are stored is easy both to understand and to edit by hand. 78.136 -(In other words, you don't have to use the \hgxcmd{mq}{qguard} command if 78.137 -you don't want to; it's okay to simply edit the \sfilename{series} 78.138 -file.) 78.139 -\interaction{mq.guards.series} 78.140 - 78.141 -\section{Selecting the guards to use} 78.142 - 78.143 -The \hgxcmd{mq}{qselect} command determines which guards are active at a 78.144 -given time. The effect of this is to determine which patches MQ will 78.145 -apply the next time you run \hgxcmd{mq}{qpush}. It has no other effect; in 78.146 -particular, it doesn't do anything to patches that are already 78.147 -applied. 78.148 - 78.149 -With no arguments, the \hgxcmd{mq}{qselect} command lists the guards 78.150 -currently in effect, one per line of output. Each argument is treated 78.151 -as the name of a guard to apply. 78.152 -\interaction{mq.guards.qselect.foo} 78.153 -In case you're interested, the currently selected guards are stored in 78.154 -the \sfilename{guards} file. 78.155 -\interaction{mq.guards.qselect.cat} 78.156 -We can see the effect the selected guards have when we run 78.157 -\hgxcmd{mq}{qpush}. 78.158 -\interaction{mq.guards.qselect.qpush} 78.159 - 78.160 -A guard cannot start with a ``\texttt{+}'' or ``\texttt{-}'' 78.161 -character. The name of a guard must not contain white space, but most 78.162 -other characters are acceptable. If you try to use a guard with an 78.163 -invalid name, MQ will complain: 78.164 -\interaction{mq.guards.qselect.error} 78.165 -Changing the selected guards changes the patches that are applied. 78.166 -\interaction{mq.guards.qselect.quux} 78.167 -You can see in the example below that negative guards take precedence 78.168 -over positive guards. 78.169 -\interaction{mq.guards.qselect.foobar} 78.170 - 78.171 -\section{MQ's rules for applying patches} 78.172 - 78.173 -The rules that MQ uses when deciding whether to apply a patch 78.174 -are as follows. 78.175 -\begin{itemize} 78.176 -\item A patch that has no guards is always applied. 78.177 -\item If the patch has any negative guard that matches any currently 78.178 - selected guard, the patch is skipped. 78.179 -\item If the patch has any positive guard that matches any currently 78.180 - selected guard, the patch is applied. 78.181 -\item If the patch has positive or negative guards, but none matches 78.182 - any currently selected guard, the patch is skipped. 78.183 -\end{itemize} 78.184 - 78.185 -\section{Trimming the work environment} 78.186 - 78.187 -In working on the device driver I mentioned earlier, I don't apply the 78.188 -patches to a normal Linux kernel tree. Instead, I use a repository 78.189 -that contains only a snapshot of the source files and headers that are 78.190 -relevant to Infiniband development. This repository is~1\% the size 78.191 -of a kernel repository, so it's easier to work with. 78.192 - 78.193 -I then choose a ``base'' version on top of which the patches are 78.194 -applied. This is a snapshot of the Linux kernel tree as of a revision 78.195 -of my choosing. When I take the snapshot, I record the changeset ID 78.196 -from the kernel repository in the commit message. Since the snapshot 78.197 -preserves the ``shape'' and content of the relevant parts of the 78.198 -kernel tree, I can apply my patches on top of either my tiny 78.199 -repository or a normal kernel tree. 78.200 - 78.201 -Normally, the base tree atop which the patches apply should be a 78.202 -snapshot of a very recent upstream tree. This best facilitates the 78.203 -development of patches that can easily be submitted upstream with few 78.204 -or no modifications. 78.205 - 78.206 -\section{Dividing up the \sfilename{series} file} 78.207 - 78.208 -I categorise the patches in the \sfilename{series} file into a number 78.209 -of logical groups. Each section of like patches begins with a block 78.210 -of comments that describes the purpose of the patches that follow. 78.211 - 78.212 -The sequence of patch groups that I maintain follows. The ordering of 78.213 -these groups is important; I'll describe why after I introduce the 78.214 -groups. 78.215 -\begin{itemize} 78.216 -\item The ``accepted'' group. Patches that the development team has 78.217 - submitted to the maintainer of the Infiniband subsystem, and which 78.218 - he has accepted, but which are not present in the snapshot that the 78.219 - tiny repository is based on. These are ``read only'' patches, 78.220 - present only to transform the tree into a similar state as it is in 78.221 - the upstream maintainer's repository. 78.222 -\item The ``rework'' group. Patches that I have submitted, but that 78.223 - the upstream maintainer has requested modifications to before he 78.224 - will accept them. 78.225 -\item The ``pending'' group. Patches that I have not yet submitted to 78.226 - the upstream maintainer, but which we have finished working on. 78.227 - These will be ``read only'' for a while. If the upstream maintainer 78.228 - accepts them upon submission, I'll move them to the end of the 78.229 - ``accepted'' group. If he requests that I modify any, I'll move 78.230 - them to the beginning of the ``rework'' group. 78.231 -\item The ``in progress'' group. Patches that are actively being 78.232 - developed, and should not be submitted anywhere yet. 78.233 -\item The ``backport'' group. Patches that adapt the source tree to 78.234 - older versions of the kernel tree. 78.235 -\item The ``do not ship'' group. Patches that for some reason should 78.236 - never be submitted upstream. For example, one such patch might 78.237 - change embedded driver identification strings to make it easier to 78.238 - distinguish, in the field, between an out-of-tree version of the 78.239 - driver and a version shipped by a distribution vendor. 78.240 -\end{itemize} 78.241 - 78.242 -Now to return to the reasons for ordering groups of patches in this 78.243 -way. We would like the lowest patches in the stack to be as stable as 78.244 -possible, so that we will not need to rework higher patches due to 78.245 -changes in context. Putting patches that will never be changed first 78.246 -in the \sfilename{series} file serves this purpose. 78.247 - 78.248 -We would also like the patches that we know we'll need to modify to be 78.249 -applied on top of a source tree that resembles the upstream tree as 78.250 -closely as possible. This is why we keep accepted patches around for 78.251 -a while. 78.252 - 78.253 -The ``backport'' and ``do not ship'' patches float at the end of the 78.254 -\sfilename{series} file. The backport patches must be applied on top 78.255 -of all other patches, and the ``do not ship'' patches might as well 78.256 -stay out of harm's way. 78.257 - 78.258 -\section{Maintaining the patch series} 78.259 - 78.260 -In my work, I use a number of guards to control which patches are to 78.261 -be applied. 78.262 - 78.263 -\begin{itemize} 78.264 -\item ``Accepted'' patches are guarded with \texttt{accepted}. I 78.265 - enable this guard most of the time. When I'm applying the patches 78.266 - on top of a tree where the patches are already present, I can turn 78.267 - this patch off, and the patches that follow it will apply cleanly. 78.268 -\item Patches that are ``finished'', but not yet submitted, have no 78.269 - guards. If I'm applying the patch stack to a copy of the upstream 78.270 - tree, I don't need to enable any guards in order to get a reasonably 78.271 - safe source tree. 78.272 -\item Those patches that need reworking before being resubmitted are 78.273 - guarded with \texttt{rework}. 78.274 -\item For those patches that are still under development, I use 78.275 - \texttt{devel}. 78.276 -\item A backport patch may have several guards, one for each version 78.277 - of the kernel to which it applies. For example, a patch that 78.278 - backports a piece of code to~2.6.9 will have a~\texttt{2.6.9} guard. 78.279 -\end{itemize} 78.280 -This variety of guards gives me considerable flexibility in 78.281 -determining what kind of source tree I want to end up with. For most 78.282 -situations, the selection of appropriate guards is automated during 78.283 -the build process, but I can manually tune the guards to use for less 78.284 -common circumstances. 78.285 - 78.286 -\subsection{The art of writing backport patches} 78.287 - 78.288 -Using MQ, writing a backport patch is a simple process. All such a 78.289 -patch has to do is modify a piece of code that uses a kernel feature 78.290 -not present in the older version of the kernel, so that the driver 78.291 -continues to work correctly under that older version. 78.292 - 78.293 -A useful goal when writing a good backport patch is to make your code 78.294 -look as if it was written for the older version of the kernel you're 78.295 -targeting. The less obtrusive the patch, the easier it will be to 78.296 -understand and maintain. If you're writing a collection of backport 78.297 -patches to avoid the ``rat's nest'' effect of lots of 78.298 -\texttt{\#ifdef}s (hunks of source code that are only used 78.299 -conditionally) in your code, don't introduce version-dependent 78.300 -\texttt{\#ifdef}s into the patches. Instead, write several patches, 78.301 -each of which makes unconditional changes, and control their 78.302 -application using guards. 78.303 - 78.304 -There are two reasons to divide backport patches into a distinct 78.305 -group, away from the ``regular'' patches whose effects they modify. 78.306 -The first is that intermingling the two makes it more difficult to use 78.307 -a tool like the \hgext{patchbomb} extension to automate the process of 78.308 -submitting the patches to an upstream maintainer. The second is that 78.309 -a backport patch could perturb the context in which a subsequent 78.310 -regular patch is applied, making it impossible to apply the regular 78.311 -patch cleanly \emph{without} the earlier backport patch already being 78.312 -applied. 78.313 - 78.314 -\section{Useful tips for developing with MQ} 78.315 - 78.316 -\subsection{Organising patches in directories} 78.317 - 78.318 -If you're working on a substantial project with MQ, it's not difficult 78.319 -to accumulate a large number of patches. For example, I have one 78.320 -patch repository that contains over 250 patches. 78.321 - 78.322 -If you can group these patches into separate logical categories, you 78.323 -can if you like store them in different directories; MQ has no 78.324 -problems with patch names that contain path separators. 78.325 - 78.326 -\subsection{Viewing the history of a patch} 78.327 -\label{mq-collab:tips:interdiff} 78.328 - 78.329 -If you're developing a set of patches over a long time, it's a good 78.330 -idea to maintain them in a repository, as discussed in 78.331 -section~\ref{sec:mq:repo}. If you do so, you'll quickly discover that 78.332 -using the \hgcmd{diff} command to look at the history of changes to a 78.333 -patch is unworkable. This is in part because you're looking at the 78.334 -second derivative of the real code (a diff of a diff), but also 78.335 -because MQ adds noise to the process by modifying time stamps and 78.336 -directory names when it updates a patch. 78.337 - 78.338 -However, you can use the \hgext{extdiff} extension, which is bundled 78.339 -with Mercurial, to turn a diff of two versions of a patch into 78.340 -something readable. To do this, you will need a third-party package 78.341 -called \package{patchutils}~\cite{web:patchutils}. This provides a 78.342 -command named \command{interdiff}, which shows the differences between 78.343 -two diffs as a diff. Used on two versions of the same diff, it 78.344 -generates a diff that represents the diff from the first to the second 78.345 -version. 78.346 - 78.347 -You can enable the \hgext{extdiff} extension in the usual way, by 78.348 -adding a line to the \rcsection{extensions} section of your \hgrc. 78.349 -\begin{codesample2} 78.350 - [extensions] 78.351 - extdiff = 78.352 -\end{codesample2} 78.353 -The \command{interdiff} command expects to be passed the names of two 78.354 -files, but the \hgext{extdiff} extension passes the program it runs a 78.355 -pair of directories, each of which can contain an arbitrary number of 78.356 -files. We thus need a small program that will run \command{interdiff} 78.357 -on each pair of files in these two directories. This program is 78.358 -available as \sfilename{hg-interdiff} in the \dirname{examples} 78.359 -directory of the source code repository that accompanies this book. 78.360 -\excode{hg-interdiff} 78.361 - 78.362 -With the \sfilename{hg-interdiff} program in your shell's search path, 78.363 -you can run it as follows, from inside an MQ patch directory: 78.364 -\begin{codesample2} 78.365 - hg extdiff -p hg-interdiff -r A:B my-change.patch 78.366 -\end{codesample2} 78.367 -Since you'll probably want to use this long-winded command a lot, you 78.368 -can get \hgext{hgext} to make it available as a normal Mercurial 78.369 -command, again by editing your \hgrc. 78.370 -\begin{codesample2} 78.371 - [extdiff] 78.372 - cmd.interdiff = hg-interdiff 78.373 -\end{codesample2} 78.374 -This directs \hgext{hgext} to make an \texttt{interdiff} command 78.375 -available, so you can now shorten the previous invocation of 78.376 -\hgxcmd{extdiff}{extdiff} to something a little more wieldy. 78.377 -\begin{codesample2} 78.378 - hg interdiff -r A:B my-change.patch 78.379 -\end{codesample2} 78.380 - 78.381 -\begin{note} 78.382 - The \command{interdiff} command works well only if the underlying 78.383 - files against which versions of a patch are generated remain the 78.384 - same. If you create a patch, modify the underlying files, and then 78.385 - regenerate the patch, \command{interdiff} may not produce useful 78.386 - output. 78.387 -\end{note} 78.388 - 78.389 -The \hgext{extdiff} extension is useful for more than merely improving 78.390 -the presentation of MQ~patches. To read more about it, go to 78.391 -section~\ref{sec:hgext:extdiff}. 78.392 - 78.393 -%%% Local Variables: 78.394 -%%% mode: latex 78.395 -%%% TeX-master: "00book" 78.396 -%%% End:
79.1 --- a/fr/mq-ref.tex Sun Aug 16 03:41:39 2009 +0200 79.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 79.3 @@ -1,349 +0,0 @@ 79.4 -\chapter{Mercurial Queues reference} 79.5 -\label{chap:mqref} 79.6 - 79.7 -\section{MQ command reference} 79.8 -\label{sec:mqref:cmdref} 79.9 - 79.10 -For an overview of the commands provided by MQ, use the command 79.11 -\hgcmdargs{help}{mq}. 79.12 - 79.13 -\subsection{\hgxcmd{mq}{qapplied}---print applied patches} 79.14 - 79.15 -The \hgxcmd{mq}{qapplied} command prints the current stack of applied 79.16 -patches. Patches are printed in oldest-to-newest order, so the last 79.17 -patch in the list is the ``top'' patch. 79.18 - 79.19 -\subsection{\hgxcmd{mq}{qcommit}---commit changes in the queue repository} 79.20 - 79.21 -The \hgxcmd{mq}{qcommit} command commits any outstanding changes in the 79.22 -\sdirname{.hg/patches} repository. This command only works if the 79.23 -\sdirname{.hg/patches} directory is a repository, i.e.~you created the 79.24 -directory using \hgcmdargs{qinit}{\hgxopt{mq}{qinit}{-c}} or ran 79.25 -\hgcmd{init} in the directory after running \hgxcmd{mq}{qinit}. 79.26 - 79.27 -This command is shorthand for \hgcmdargs{commit}{--cwd .hg/patches}. 79.28 - 79.29 -\subsection{\hgxcmd{mq}{qdelete}---delete a patch from the 79.30 - \sfilename{series} file} 79.31 - 79.32 -The \hgxcmd{mq}{qdelete} command removes the entry for a patch from the 79.33 -\sfilename{series} file in the \sdirname{.hg/patches} directory. It 79.34 -does not pop the patch if the patch is already applied. By default, 79.35 -it does not delete the patch file; use the \hgxopt{mq}{qdel}{-f} option to 79.36 -do that. 79.37 - 79.38 -Options: 79.39 -\begin{itemize} 79.40 -\item[\hgxopt{mq}{qdel}{-f}] Delete the patch file. 79.41 -\end{itemize} 79.42 - 79.43 -\subsection{\hgxcmd{mq}{qdiff}---print a diff of the topmost applied patch} 79.44 - 79.45 -The \hgxcmd{mq}{qdiff} command prints a diff of the topmost applied patch. 79.46 -It is equivalent to \hgcmdargs{diff}{-r-2:-1}. 79.47 - 79.48 -\subsection{\hgxcmd{mq}{qfold}---merge (``fold'') several patches into one} 79.49 - 79.50 -The \hgxcmd{mq}{qfold} command merges multiple patches into the topmost 79.51 -applied patch, so that the topmost applied patch makes the union of 79.52 -all of the changes in the patches in question. 79.53 - 79.54 -The patches to fold must not be applied; \hgxcmd{mq}{qfold} will exit with 79.55 -an error if any is. The order in which patches are folded is 79.56 -significant; \hgcmdargs{qfold}{a b} means ``apply the current topmost 79.57 -patch, followed by \texttt{a}, followed by \texttt{b}''. 79.58 - 79.59 -The comments from the folded patches are appended to the comments of 79.60 -the destination patch, with each block of comments separated by three 79.61 -asterisk (``\texttt{*}'') characters. Use the \hgxopt{mq}{qfold}{-e} 79.62 -option to edit the commit message for the combined patch/changeset 79.63 -after the folding has completed. 79.64 - 79.65 -Options: 79.66 -\begin{itemize} 79.67 -\item[\hgxopt{mq}{qfold}{-e}] Edit the commit message and patch description 79.68 - for the newly folded patch. 79.69 -\item[\hgxopt{mq}{qfold}{-l}] Use the contents of the given file as the new 79.70 - commit message and patch description for the folded patch. 79.71 -\item[\hgxopt{mq}{qfold}{-m}] Use the given text as the new commit message 79.72 - and patch description for the folded patch. 79.73 -\end{itemize} 79.74 - 79.75 -\subsection{\hgxcmd{mq}{qheader}---display the header/description of a patch} 79.76 - 79.77 -The \hgxcmd{mq}{qheader} command prints the header, or description, of a 79.78 -patch. By default, it prints the header of the topmost applied patch. 79.79 -Given an argument, it prints the header of the named patch. 79.80 - 79.81 -\subsection{\hgxcmd{mq}{qimport}---import a third-party patch into the queue} 79.82 - 79.83 -The \hgxcmd{mq}{qimport} command adds an entry for an external patch to the 79.84 -\sfilename{series} file, and copies the patch into the 79.85 -\sdirname{.hg/patches} directory. It adds the entry immediately after 79.86 -the topmost applied patch, but does not push the patch. 79.87 - 79.88 -If the \sdirname{.hg/patches} directory is a repository, 79.89 -\hgxcmd{mq}{qimport} automatically does an \hgcmd{add} of the imported 79.90 -patch. 79.91 - 79.92 -\subsection{\hgxcmd{mq}{qinit}---prepare a repository to work with MQ} 79.93 - 79.94 -The \hgxcmd{mq}{qinit} command prepares a repository to work with MQ. It 79.95 -creates a directory called \sdirname{.hg/patches}. 79.96 - 79.97 -Options: 79.98 -\begin{itemize} 79.99 -\item[\hgxopt{mq}{qinit}{-c}] Create \sdirname{.hg/patches} as a repository 79.100 - in its own right. Also creates a \sfilename{.hgignore} file that 79.101 - will ignore the \sfilename{status} file. 79.102 -\end{itemize} 79.103 - 79.104 -When the \sdirname{.hg/patches} directory is a repository, the 79.105 -\hgxcmd{mq}{qimport} and \hgxcmd{mq}{qnew} commands automatically \hgcmd{add} 79.106 -new patches. 79.107 - 79.108 -\subsection{\hgxcmd{mq}{qnew}---create a new patch} 79.109 - 79.110 -The \hgxcmd{mq}{qnew} command creates a new patch. It takes one mandatory 79.111 -argument, the name to use for the patch file. The newly created patch 79.112 -is created empty by default. It is added to the \sfilename{series} 79.113 -file after the current topmost applied patch, and is immediately 79.114 -pushed on top of that patch. 79.115 - 79.116 -If \hgxcmd{mq}{qnew} finds modified files in the working directory, it will 79.117 -refuse to create a new patch unless the \hgxopt{mq}{qnew}{-f} option is 79.118 -used (see below). This behaviour allows you to \hgxcmd{mq}{qrefresh} your 79.119 -topmost applied patch before you apply a new patch on top of it. 79.120 - 79.121 -Options: 79.122 -\begin{itemize} 79.123 -\item[\hgxopt{mq}{qnew}{-f}] Create a new patch if the contents of the 79.124 - working directory are modified. Any outstanding modifications are 79.125 - added to the newly created patch, so after this command completes, 79.126 - the working directory will no longer be modified. 79.127 -\item[\hgxopt{mq}{qnew}{-m}] Use the given text as the commit message. 79.128 - This text will be stored at the beginning of the patch file, before 79.129 - the patch data. 79.130 -\end{itemize} 79.131 - 79.132 -\subsection{\hgxcmd{mq}{qnext}---print the name of the next patch} 79.133 - 79.134 -The \hgxcmd{mq}{qnext} command prints the name name of the next patch in 79.135 -the \sfilename{series} file after the topmost applied patch. This 79.136 -patch will become the topmost applied patch if you run \hgxcmd{mq}{qpush}. 79.137 - 79.138 -\subsection{\hgxcmd{mq}{qpop}---pop patches off the stack} 79.139 - 79.140 -The \hgxcmd{mq}{qpop} command removes applied patches from the top of the 79.141 -stack of applied patches. By default, it removes only one patch. 79.142 - 79.143 -This command removes the changesets that represent the popped patches 79.144 -from the repository, and updates the working directory to undo the 79.145 -effects of the patches. 79.146 - 79.147 -This command takes an optional argument, which it uses as the name or 79.148 -index of the patch to pop to. If given a name, it will pop patches 79.149 -until the named patch is the topmost applied patch. If given a 79.150 -number, \hgxcmd{mq}{qpop} treats the number as an index into the entries in 79.151 -the series file, counting from zero (empty lines and lines containing 79.152 -only comments do not count). It pops patches until the patch 79.153 -identified by the given index is the topmost applied patch. 79.154 - 79.155 -The \hgxcmd{mq}{qpop} command does not read or write patches or the 79.156 -\sfilename{series} file. It is thus safe to \hgxcmd{mq}{qpop} a patch that 79.157 -you have removed from the \sfilename{series} file, or a patch that you 79.158 -have renamed or deleted entirely. In the latter two cases, use the 79.159 -name of the patch as it was when you applied it. 79.160 - 79.161 -By default, the \hgxcmd{mq}{qpop} command will not pop any patches if the 79.162 -working directory has been modified. You can override this behaviour 79.163 -using the \hgxopt{mq}{qpop}{-f} option, which reverts all modifications in 79.164 -the working directory. 79.165 - 79.166 -Options: 79.167 -\begin{itemize} 79.168 -\item[\hgxopt{mq}{qpop}{-a}] Pop all applied patches. This returns the 79.169 - repository to its state before you applied any patches. 79.170 -\item[\hgxopt{mq}{qpop}{-f}] Forcibly revert any modifications to the 79.171 - working directory when popping. 79.172 -\item[\hgxopt{mq}{qpop}{-n}] Pop a patch from the named queue. 79.173 -\end{itemize} 79.174 - 79.175 -The \hgxcmd{mq}{qpop} command removes one line from the end of the 79.176 -\sfilename{status} file for each patch that it pops. 79.177 - 79.178 -\subsection{\hgxcmd{mq}{qprev}---print the name of the previous patch} 79.179 - 79.180 -The \hgxcmd{mq}{qprev} command prints the name of the patch in the 79.181 -\sfilename{series} file that comes before the topmost applied patch. 79.182 -This will become the topmost applied patch if you run \hgxcmd{mq}{qpop}. 79.183 - 79.184 -\subsection{\hgxcmd{mq}{qpush}---push patches onto the stack} 79.185 -\label{sec:mqref:cmd:qpush} 79.186 - 79.187 -The \hgxcmd{mq}{qpush} command adds patches onto the applied stack. By 79.188 -default, it adds only one patch. 79.189 - 79.190 -This command creates a new changeset to represent each applied patch, 79.191 -and updates the working directory to apply the effects of the patches. 79.192 - 79.193 -The default data used when creating a changeset are as follows: 79.194 -\begin{itemize} 79.195 -\item The commit date and time zone are the current date and time 79.196 - zone. Because these data are used to compute the identity of a 79.197 - changeset, this means that if you \hgxcmd{mq}{qpop} a patch and 79.198 - \hgxcmd{mq}{qpush} it again, the changeset that you push will have a 79.199 - different identity than the changeset you popped. 79.200 -\item The author is the same as the default used by the \hgcmd{commit} 79.201 - command. 79.202 -\item The commit message is any text from the patch file that comes 79.203 - before the first diff header. If there is no such text, a default 79.204 - commit message is used that identifies the name of the patch. 79.205 -\end{itemize} 79.206 -If a patch contains a Mercurial patch header (XXX add link), the 79.207 -information in the patch header overrides these defaults. 79.208 - 79.209 -Options: 79.210 -\begin{itemize} 79.211 -\item[\hgxopt{mq}{qpush}{-a}] Push all unapplied patches from the 79.212 - \sfilename{series} file until there are none left to push. 79.213 -\item[\hgxopt{mq}{qpush}{-l}] Add the name of the patch to the end 79.214 - of the commit message. 79.215 -\item[\hgxopt{mq}{qpush}{-m}] If a patch fails to apply cleanly, use the 79.216 - entry for the patch in another saved queue to compute the parameters 79.217 - for a three-way merge, and perform a three-way merge using the 79.218 - normal Mercurial merge machinery. Use the resolution of the merge 79.219 - as the new patch content. 79.220 -\item[\hgxopt{mq}{qpush}{-n}] Use the named queue if merging while pushing. 79.221 -\end{itemize} 79.222 - 79.223 -The \hgxcmd{mq}{qpush} command reads, but does not modify, the 79.224 -\sfilename{series} file. It appends one line to the \hgcmd{status} 79.225 -file for each patch that it pushes. 79.226 - 79.227 -\subsection{\hgxcmd{mq}{qrefresh}---update the topmost applied patch} 79.228 - 79.229 -The \hgxcmd{mq}{qrefresh} command updates the topmost applied patch. It 79.230 -modifies the patch, removes the old changeset that represented the 79.231 -patch, and creates a new changeset to represent the modified patch. 79.232 - 79.233 -The \hgxcmd{mq}{qrefresh} command looks for the following modifications: 79.234 -\begin{itemize} 79.235 -\item Changes to the commit message, i.e.~the text before the first 79.236 - diff header in the patch file, are reflected in the new changeset 79.237 - that represents the patch. 79.238 -\item Modifications to tracked files in the working directory are 79.239 - added to the patch. 79.240 -\item Changes to the files tracked using \hgcmd{add}, \hgcmd{copy}, 79.241 - \hgcmd{remove}, or \hgcmd{rename}. Added files and copy and rename 79.242 - destinations are added to the patch, while removed files and rename 79.243 - sources are removed. 79.244 -\end{itemize} 79.245 - 79.246 -Even if \hgxcmd{mq}{qrefresh} detects no changes, it still recreates the 79.247 -changeset that represents the patch. This causes the identity of the 79.248 -changeset to differ from the previous changeset that identified the 79.249 -patch. 79.250 - 79.251 -Options: 79.252 -\begin{itemize} 79.253 -\item[\hgxopt{mq}{qrefresh}{-e}] Modify the commit and patch description, 79.254 - using the preferred text editor. 79.255 -\item[\hgxopt{mq}{qrefresh}{-m}] Modify the commit message and patch 79.256 - description, using the given text. 79.257 -\item[\hgxopt{mq}{qrefresh}{-l}] Modify the commit message and patch 79.258 - description, using text from the given file. 79.259 -\end{itemize} 79.260 - 79.261 -\subsection{\hgxcmd{mq}{qrename}---rename a patch} 79.262 - 79.263 -The \hgxcmd{mq}{qrename} command renames a patch, and changes the entry for 79.264 -the patch in the \sfilename{series} file. 79.265 - 79.266 -With a single argument, \hgxcmd{mq}{qrename} renames the topmost applied 79.267 -patch. With two arguments, it renames its first argument to its 79.268 -second. 79.269 - 79.270 -\subsection{\hgxcmd{mq}{qrestore}---restore saved queue state} 79.271 - 79.272 -XXX No idea what this does. 79.273 - 79.274 -\subsection{\hgxcmd{mq}{qsave}---save current queue state} 79.275 - 79.276 -XXX Likewise. 79.277 - 79.278 -\subsection{\hgxcmd{mq}{qseries}---print the entire patch series} 79.279 - 79.280 -The \hgxcmd{mq}{qseries} command prints the entire patch series from the 79.281 -\sfilename{series} file. It prints only patch names, not empty lines 79.282 -or comments. It prints in order from first to be applied to last. 79.283 - 79.284 -\subsection{\hgxcmd{mq}{qtop}---print the name of the current patch} 79.285 - 79.286 -The \hgxcmd{mq}{qtop} prints the name of the topmost currently applied 79.287 -patch. 79.288 - 79.289 -\subsection{\hgxcmd{mq}{qunapplied}---print patches not yet applied} 79.290 - 79.291 -The \hgxcmd{mq}{qunapplied} command prints the names of patches from the 79.292 -\sfilename{series} file that are not yet applied. It prints them in 79.293 -order from the next patch that will be pushed to the last. 79.294 - 79.295 -\subsection{\hgcmd{strip}---remove a revision and descendants} 79.296 - 79.297 -The \hgcmd{strip} command removes a revision, and all of its 79.298 -descendants, from the repository. It undoes the effects of the 79.299 -removed revisions from the repository, and updates the working 79.300 -directory to the first parent of the removed revision. 79.301 - 79.302 -The \hgcmd{strip} command saves a backup of the removed changesets in 79.303 -a bundle, so that they can be reapplied if removed in error. 79.304 - 79.305 -Options: 79.306 -\begin{itemize} 79.307 -\item[\hgopt{strip}{-b}] Save unrelated changesets that are intermixed 79.308 - with the stripped changesets in the backup bundle. 79.309 -\item[\hgopt{strip}{-f}] If a branch has multiple heads, remove all 79.310 - heads. XXX This should be renamed, and use \texttt{-f} to strip revs 79.311 - when there are pending changes. 79.312 -\item[\hgopt{strip}{-n}] Do not save a backup bundle. 79.313 -\end{itemize} 79.314 - 79.315 -\section{MQ file reference} 79.316 - 79.317 -\subsection{The \sfilename{series} file} 79.318 - 79.319 -The \sfilename{series} file contains a list of the names of all 79.320 -patches that MQ can apply. It is represented as a list of names, with 79.321 -one name saved per line. Leading and trailing white space in each 79.322 -line are ignored. 79.323 - 79.324 -Lines may contain comments. A comment begins with the ``\texttt{\#}'' 79.325 -character, and extends to the end of the line. Empty lines, and lines 79.326 -that contain only comments, are ignored. 79.327 - 79.328 -You will often need to edit the \sfilename{series} file by hand, hence 79.329 -the support for comments and empty lines noted above. For example, 79.330 -you can comment out a patch temporarily, and \hgxcmd{mq}{qpush} will skip 79.331 -over that patch when applying patches. You can also change the order 79.332 -in which patches are applied by reordering their entries in the 79.333 -\sfilename{series} file. 79.334 - 79.335 -Placing the \sfilename{series} file under revision control is also 79.336 -supported; it is a good idea to place all of the patches that it 79.337 -refers to under revision control, as well. If you create a patch 79.338 -directory using the \hgxopt{mq}{qinit}{-c} option to \hgxcmd{mq}{qinit}, this 79.339 -will be done for you automatically. 79.340 - 79.341 -\subsection{The \sfilename{status} file} 79.342 - 79.343 -The \sfilename{status} file contains the names and changeset hashes of 79.344 -all patches that MQ currently has applied. Unlike the 79.345 -\sfilename{series} file, this file is not intended for editing. You 79.346 -should not place this file under revision control, or modify it in any 79.347 -way. It is used by MQ strictly for internal book-keeping. 79.348 - 79.349 -%%% Local Variables: 79.350 -%%% mode: latex 79.351 -%%% TeX-master: "00book" 79.352 -%%% End:
80.1 --- a/fr/mq-stack.svg Sun Aug 16 03:41:39 2009 +0200 80.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 80.3 @@ -1,270 +0,0 @@ 80.4 -<?xml version="1.0" encoding="UTF-8" standalone="no"?> 80.5 -<!-- Created with Inkscape (http://www.inkscape.org/) --> 80.6 -<svg 80.7 - xmlns:dc="http://purl.org/dc/elements/1.1/" 80.8 - xmlns:cc="http://web.resource.org/cc/" 80.9 - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 80.10 - xmlns:svg="http://www.w3.org/2000/svg" 80.11 - xmlns="http://www.w3.org/2000/svg" 80.12 - xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd" 80.13 - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" 80.14 - width="744.09448819" 80.15 - height="1052.3622047" 80.16 - id="svg2" 80.17 - sodipodi:version="0.32" 80.18 - inkscape:version="0.43" 80.19 - sodipodi:docname="mq-stack.svg" 80.20 - sodipodi:docbase="/home/bos/hg/hgbook/en"> 80.21 - <defs 80.22 - id="defs4" /> 80.23 - <sodipodi:namedview 80.24 - id="base" 80.25 - pagecolor="#ffffff" 80.26 - bordercolor="#666666" 80.27 - borderopacity="1.0" 80.28 - inkscape:pageopacity="0.0" 80.29 - inkscape:pageshadow="2" 80.30 - inkscape:zoom="1.4142136" 80.31 - inkscape:cx="299.33323" 80.32 - inkscape:cy="815.646" 80.33 - inkscape:document-units="px" 80.34 - inkscape:current-layer="layer1" 80.35 - inkscape:window-width="1014" 80.36 - inkscape:window-height="689" 80.37 - inkscape:window-x="0" 80.38 - inkscape:window-y="25" /> 80.39 - <metadata 80.40 - id="metadata7"> 80.41 - <rdf:RDF> 80.42 - <cc:Work 80.43 - rdf:about=""> 80.44 - <dc:format>image/svg+xml</dc:format> 80.45 - <dc:type 80.46 - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 80.47 - </cc:Work> 80.48 - </rdf:RDF> 80.49 - </metadata> 80.50 - <g 80.51 - inkscape:label="Layer 1" 80.52 - inkscape:groupmode="layer" 80.53 - id="layer1"> 80.54 - <rect 80.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" 80.56 - id="rect1307" 80.57 - width="202.93683" 80.58 - height="24.243662" 80.59 - x="230.01944" 80.60 - y="221.70146" /> 80.61 - <text 80.62 - xml:space="preserve" 80.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" 80.64 - x="237.89606" 80.65 - y="237.13383" 80.66 - id="text1309"><tspan 80.67 - sodipodi:role="line" 80.68 - id="tspan1311" 80.69 - x="237.89606" 80.70 - y="237.13383">prevent-compiler-reorder.patch</tspan></text> 80.71 - <rect 80.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" 80.73 - id="rect1320" 80.74 - width="202.93683" 80.75 - height="24.243662" 80.76 - x="230.01936" 80.77 - y="251.34325" /> 80.78 - <text 80.79 - xml:space="preserve" 80.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" 80.81 - x="237.89598" 80.82 - y="266.77563" 80.83 - id="text1322"><tspan 80.84 - sodipodi:role="line" 80.85 - id="tspan1324" 80.86 - x="237.89598" 80.87 - y="266.77563">namespace-cleanup.patch</tspan></text> 80.88 - <rect 80.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" 80.90 - id="rect2217" 80.91 - width="202.93683" 80.92 - height="24.243662" 80.93 - x="230.01936" 80.94 - y="280.98505" /> 80.95 - <text 80.96 - xml:space="preserve" 80.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" 80.98 - x="237.89598" 80.99 - y="296.41742" 80.100 - id="text2219"><tspan 80.101 - sodipodi:role="line" 80.102 - id="tspan2221" 80.103 - x="237.89598" 80.104 - y="296.41742">powerpc-port-fixes.patch</tspan></text> 80.105 - <rect 80.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" 80.107 - id="rect3114" 80.108 - width="202.93683" 80.109 - height="24.243662" 80.110 - x="230.01936" 80.111 - y="310.6268" /> 80.112 - <text 80.113 - xml:space="preserve" 80.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" 80.115 - x="237.89598" 80.116 - y="326.05917" 80.117 - id="text3116"><tspan 80.118 - sodipodi:role="line" 80.119 - id="tspan3118" 80.120 - x="237.89598" 80.121 - y="326.05917">report-devinfo-correctly.patch</tspan></text> 80.122 - <text 80.123 - xml:space="preserve" 80.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" 80.125 - x="200.01021" 80.126 - y="191.68094" 80.127 - id="text3170" 80.128 - sodipodi:linespacing="125%"><tspan 80.129 - sodipodi:role="line" 80.130 - id="tspan3172" 80.131 - x="200.01021" 80.132 - y="191.68094" 80.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> 80.134 - <text 80.135 - xml:space="preserve" 80.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" 80.137 - x="255.26627" 80.138 - y="248.79449" 80.139 - id="text3190" 80.140 - sodipodi:linespacing="125%" 80.141 - transform="scale(0.786716,1.271107)"><tspan 80.142 - sodipodi:role="line" 80.143 - id="tspan3192" 80.144 - x="255.26627" 80.145 - y="248.79449" 80.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> 80.147 - <text 80.148 - xml:space="preserve" 80.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" 80.150 - x="195.86807" 80.151 - y="173.17117" 80.152 - id="text4085" 80.153 - sodipodi:linespacing="125%"><tspan 80.154 - sodipodi:role="line" 80.155 - id="tspan4087" 80.156 - x="195.86807" 80.157 - y="173.17117" 80.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 80.159 - sodipodi:role="line" 80.160 - x="195.86807" 80.161 - y="188.17117" 80.162 - id="tspan4089" 80.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> 80.164 - <text 80.165 - xml:space="preserve" 80.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" 80.167 - x="195.0712" 80.168 - y="288.91745" 80.169 - id="text4091" 80.170 - sodipodi:linespacing="125%"><tspan 80.171 - sodipodi:role="line" 80.172 - id="tspan4093" 80.173 - x="195.0712" 80.174 - y="288.91745" 80.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 80.176 - sodipodi:role="line" 80.177 - x="195.0712" 80.178 - y="303.91745" 80.179 - id="tspan4111" 80.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> 80.181 - <text 80.182 - xml:space="preserve" 80.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" 80.184 - x="195.0712" 80.185 - y="229.28813" 80.186 - id="text4095" 80.187 - sodipodi:linespacing="125%"><tspan 80.188 - sodipodi:role="line" 80.189 - id="tspan4097" 80.190 - x="195.0712" 80.191 - y="229.28813" 80.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 80.193 - sodipodi:role="line" 80.194 - x="195.0712" 80.195 - y="244.28813" 80.196 - id="tspan4109" 80.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> 80.198 - <text 80.199 - xml:space="preserve" 80.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" 80.201 - x="450.4975" 80.202 - y="238.29692" 80.203 - id="text4137"><tspan 80.204 - sodipodi:role="line" 80.205 - id="tspan4139" 80.206 - x="450.4975" 80.207 - y="238.29692">201ad3209902</tspan></text> 80.208 - <text 80.209 - xml:space="preserve" 80.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" 80.211 - x="450.05804" 80.212 - y="267.93872" 80.213 - id="text4141"><tspan 80.214 - sodipodi:role="line" 80.215 - id="tspan4143" 80.216 - x="450.05804" 80.217 - y="267.93872">126b84e593ae</tspan></text> 80.218 - <text 80.219 - xml:space="preserve" 80.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" 80.221 - x="450.6557" 80.222 - y="297.58051" 80.223 - id="text4145"><tspan 80.224 - sodipodi:role="line" 80.225 - id="tspan4147" 80.226 - x="450.6557" 80.227 - y="297.58051">a655daf15409</tspan></text> 80.228 - <text 80.229 - xml:space="preserve" 80.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" 80.231 - x="450.71429" 80.232 - y="327.22226" 80.233 - id="text4149"><tspan 80.234 - sodipodi:role="line" 80.235 - id="tspan4151" 80.236 - x="450.71429" 80.237 - y="327.22226">e50d59aaea3a</tspan></text> 80.238 - <rect 80.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" 80.240 - id="rect3106" 80.241 - width="202.93683" 80.242 - height="24.243662" 80.243 - x="230.01936" 80.244 - y="150.41792" /> 80.245 - <text 80.246 - xml:space="preserve" 80.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" 80.248 - x="237.89598" 80.249 - y="165.8503" 80.250 - id="text3108"><tspan 80.251 - sodipodi:role="line" 80.252 - id="tspan3110" 80.253 - x="237.89598" 80.254 - y="165.8503">forbid-illegal-params.patch</tspan></text> 80.255 - <rect 80.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" 80.257 - id="rect2241" 80.258 - width="202.93683" 80.259 - height="24.243662" 80.260 - x="230.16466" 80.261 - y="180.05968" /> 80.262 - <text 80.263 - xml:space="preserve" 80.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" 80.265 - x="238.04128" 80.266 - y="195.49205" 80.267 - id="text2243"><tspan 80.268 - sodipodi:role="line" 80.269 - id="tspan2245" 80.270 - x="238.04128" 80.271 - y="195.49205">fix-memory-leak.patch</tspan></text> 80.272 - </g> 80.273 -</svg>
81.1 --- a/fr/mq.tex Sun Aug 16 03:41:39 2009 +0200 81.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 81.3 @@ -1,1043 +0,0 @@ 81.4 -\chapter{Managing change with Mercurial Queues} 81.5 -\label{chap:mq} 81.6 - 81.7 -\section{The patch management problem} 81.8 -\label{sec:mq:patch-mgmt} 81.9 - 81.10 -Here is a common scenario: you need to install a software package from 81.11 -source, but you find a bug that you must fix in the source before you 81.12 -can start using the package. You make your changes, forget about the 81.13 -package for a while, and a few months later you need to upgrade to a 81.14 -newer version of the package. If the newer version of the package 81.15 -still has the bug, you must extract your fix from the older source 81.16 -tree and apply it against the newer version. This is a tedious task, 81.17 -and it's easy to make mistakes. 81.18 - 81.19 -This is a simple case of the ``patch management'' problem. You have 81.20 -an ``upstream'' source tree that you can't change; you need to make 81.21 -some local changes on top of the upstream tree; and you'd like to be 81.22 -able to keep those changes separate, so that you can apply them to 81.23 -newer versions of the upstream source. 81.24 - 81.25 -The patch management problem arises in many situations. Probably the 81.26 -most visible is that a user of an open source software project will 81.27 -contribute a bug fix or new feature to the project's maintainers in the 81.28 -form of a patch. 81.29 - 81.30 -Distributors of operating systems that include open source software 81.31 -often need to make changes to the packages they distribute so that 81.32 -they will build properly in their environments. 81.33 - 81.34 -When you have few changes to maintain, it is easy to manage a single 81.35 -patch using the standard \command{diff} and \command{patch} programs 81.36 -(see section~\ref{sec:mq:patch} for a discussion of these tools). 81.37 -Once the number of changes grows, it starts to make sense to maintain 81.38 -patches as discrete ``chunks of work,'' so that for example a single 81.39 -patch will contain only one bug fix (the patch might modify several 81.40 -files, but it's doing ``only one thing''), and you may have a number 81.41 -of such patches for different bugs you need fixed and local changes 81.42 -you require. In this situation, if you submit a bug fix patch to the 81.43 -upstream maintainers of a package and they include your fix in a 81.44 -subsequent release, you can simply drop that single patch when you're 81.45 -updating to the newer release. 81.46 - 81.47 -Maintaining a single patch against an upstream tree is a little 81.48 -tedious and error-prone, but not difficult. However, the complexity 81.49 -of the problem grows rapidly as the number of patches you have to 81.50 -maintain increases. With more than a tiny number of patches in hand, 81.51 -understanding which ones you have applied and maintaining them moves 81.52 -from messy to overwhelming. 81.53 - 81.54 -Fortunately, Mercurial includes a powerful extension, Mercurial Queues 81.55 -(or simply ``MQ''), that massively simplifies the patch management 81.56 -problem. 81.57 - 81.58 -\section{The prehistory of Mercurial Queues} 81.59 -\label{sec:mq:history} 81.60 - 81.61 -During the late 1990s, several Linux kernel developers started to 81.62 -maintain ``patch series'' that modified the behaviour of the Linux 81.63 -kernel. Some of these series were focused on stability, some on 81.64 -feature coverage, and others were more speculative. 81.65 - 81.66 -The sizes of these patch series grew rapidly. In 2002, Andrew Morton 81.67 -published some shell scripts he had been using to automate the task of 81.68 -managing his patch queues. Andrew was successfully using these 81.69 -scripts to manage hundreds (sometimes thousands) of patches on top of 81.70 -the Linux kernel. 81.71 - 81.72 -\subsection{A patchwork quilt} 81.73 -\label{sec:mq:quilt} 81.74 - 81.75 -In early 2003, Andreas Gruenbacher and Martin Quinson borrowed the 81.76 -approach of Andrew's scripts and published a tool called ``patchwork 81.77 -quilt''~\cite{web:quilt}, or simply ``quilt'' 81.78 -(see~\cite{gruenbacher:2005} for a paper describing it). Because 81.79 -quilt substantially automated patch management, it rapidly gained a 81.80 -large following among open source software developers. 81.81 - 81.82 -Quilt manages a \emph{stack of patches} on top of a directory tree. 81.83 -To begin, you tell quilt to manage a directory tree, and tell it which 81.84 -files you want to manage; it stores away the names and contents of 81.85 -those files. To fix a bug, you create a new patch (using a single 81.86 -command), edit the files you need to fix, then ``refresh'' the patch. 81.87 - 81.88 -The refresh step causes quilt to scan the directory tree; it updates 81.89 -the patch with all of the changes you have made. You can create 81.90 -another patch on top of the first, which will track the changes 81.91 -required to modify the tree from ``tree with one patch applied'' to 81.92 -``tree with two patches applied''. 81.93 - 81.94 -You can \emph{change} which patches are applied to the tree. If you 81.95 -``pop'' a patch, the changes made by that patch will vanish from the 81.96 -directory tree. Quilt remembers which patches you have popped, 81.97 -though, so you can ``push'' a popped patch again, and the directory 81.98 -tree will be restored to contain the modifications in the patch. Most 81.99 -importantly, you can run the ``refresh'' command at any time, and the 81.100 -topmost applied patch will be updated. This means that you can, at 81.101 -any time, change both which patches are applied and what 81.102 -modifications those patches make. 81.103 - 81.104 -Quilt knows nothing about revision control tools, so it works equally 81.105 -well on top of an unpacked tarball or a Subversion working copy. 81.106 - 81.107 -\subsection{From patchwork quilt to Mercurial Queues} 81.108 -\label{sec:mq:quilt-mq} 81.109 - 81.110 -In mid-2005, Chris Mason took the features of quilt and wrote an 81.111 -extension that he called Mercurial Queues, which added quilt-like 81.112 -behaviour to Mercurial. 81.113 - 81.114 -The key difference between quilt and MQ is that quilt knows nothing 81.115 -about revision control systems, while MQ is \emph{integrated} into 81.116 -Mercurial. Each patch that you push is represented as a Mercurial 81.117 -changeset. Pop a patch, and the changeset goes away. 81.118 - 81.119 -Because quilt does not care about revision control tools, it is still 81.120 -a tremendously useful piece of software to know about for situations 81.121 -where you cannot use Mercurial and MQ. 81.122 - 81.123 -\section{The huge advantage of MQ} 81.124 - 81.125 -I cannot overstate the value that MQ offers through the unification of 81.126 -patches and revision control. 81.127 - 81.128 -A major reason that patches have persisted in the free software and 81.129 -open source world---in spite of the availability of increasingly 81.130 -capable revision control tools over the years---is the \emph{agility} 81.131 -they offer. 81.132 - 81.133 -Traditional revision control tools make a permanent, irreversible 81.134 -record of everything that you do. While this has great value, it's 81.135 -also somewhat stifling. If you want to perform a wild-eyed 81.136 -experiment, you have to be careful in how you go about it, or you risk 81.137 -leaving unneeded---or worse, misleading or destabilising---traces of 81.138 -your missteps and errors in the permanent revision record. 81.139 - 81.140 -By contrast, MQ's marriage of distributed revision control with 81.141 -patches makes it much easier to isolate your work. Your patches live 81.142 -on top of normal revision history, and you can make them disappear or 81.143 -reappear at will. If you don't like a patch, you can drop it. If a 81.144 -patch isn't quite as you want it to be, simply fix it---as many times 81.145 -as you need to, until you have refined it into the form you desire. 81.146 - 81.147 -As an example, the integration of patches with revision control makes 81.148 -understanding patches and debugging their effects---and their 81.149 -interplay with the code they're based on---\emph{enormously} easier. 81.150 -Since every applied patch has an associated changeset, you can use 81.151 -\hgcmdargs{log}{\emph{filename}} to see which changesets and patches 81.152 -affected a file. You can use the \hgext{bisect} command to 81.153 -binary-search through all changesets and applied patches to see where 81.154 -a bug got introduced or fixed. You can use the \hgcmd{annotate} 81.155 -command to see which changeset or patch modified a particular line of 81.156 -a source file. And so on. 81.157 - 81.158 -\section{Understanding patches} 81.159 -\label{sec:mq:patch} 81.160 - 81.161 -Because MQ doesn't hide its patch-oriented nature, it is helpful to 81.162 -understand what patches are, and a little about the tools that work 81.163 -with them. 81.164 - 81.165 -The traditional Unix \command{diff} command compares two files, and 81.166 -prints a list of differences between them. The \command{patch} command 81.167 -understands these differences as \emph{modifications} to make to a 81.168 -file. Take a look at figure~\ref{ex:mq:diff} for a simple example of 81.169 -these commands in action. 81.170 - 81.171 -\begin{figure}[ht] 81.172 - \interaction{mq.dodiff.diff} 81.173 - \caption{Simple uses of the \command{diff} and \command{patch} commands} 81.174 - \label{ex:mq:diff} 81.175 -\end{figure} 81.176 - 81.177 -The type of file that \command{diff} generates (and \command{patch} 81.178 -takes as input) is called a ``patch'' or a ``diff''; there is no 81.179 -difference between a patch and a diff. (We'll use the term ``patch'', 81.180 -since it's more commonly used.) 81.181 - 81.182 -A patch file can start with arbitrary text; the \command{patch} 81.183 -command ignores this text, but MQ uses it as the commit message when 81.184 -creating changesets. To find the beginning of the patch content, 81.185 -\command{patch} searches for the first line that starts with the 81.186 -string ``\texttt{diff~-}''. 81.187 - 81.188 -MQ works with \emph{unified} diffs (\command{patch} can accept several 81.189 -other diff formats, but MQ doesn't). A unified diff contains two 81.190 -kinds of header. The \emph{file header} describes the file being 81.191 -modified; it contains the name of the file to modify. When 81.192 -\command{patch} sees a new file header, it looks for a file with that 81.193 -name to start modifying. 81.194 - 81.195 -After the file header comes a series of \emph{hunks}. Each hunk 81.196 -starts with a header; this identifies the range of line numbers within 81.197 -the file that the hunk should modify. Following the header, a hunk 81.198 -starts and ends with a few (usually three) lines of text from the 81.199 -unmodified file; these are called the \emph{context} for the hunk. If 81.200 -there's only a small amount of context between successive hunks, 81.201 -\command{diff} doesn't print a new hunk header; it just runs the hunks 81.202 -together, with a few lines of context between modifications. 81.203 - 81.204 -Each line of context begins with a space character. Within the hunk, 81.205 -a line that begins with ``\texttt{-}'' means ``remove this line,'' 81.206 -while a line that begins with ``\texttt{+}'' means ``insert this 81.207 -line.'' For example, a line that is modified is represented by one 81.208 -deletion and one insertion. 81.209 - 81.210 -We will return to some of the more subtle aspects of patches later (in 81.211 -section~\ref{sec:mq:adv-patch}), but you should have enough information 81.212 -now to use MQ. 81.213 - 81.214 -\section{Getting started with Mercurial Queues} 81.215 -\label{sec:mq:start} 81.216 - 81.217 -Because MQ is implemented as an extension, you must explicitly enable 81.218 -before you can use it. (You don't need to download anything; MQ ships 81.219 -with the standard Mercurial distribution.) To enable MQ, edit your 81.220 -\tildefile{.hgrc} file, and add the lines in figure~\ref{ex:mq:config}. 81.221 - 81.222 -\begin{figure}[ht] 81.223 - \begin{codesample4} 81.224 - [extensions] 81.225 - hgext.mq = 81.226 - \end{codesample4} 81.227 - \label{ex:mq:config} 81.228 - \caption{Contents to add to \tildefile{.hgrc} to enable the MQ extension} 81.229 -\end{figure} 81.230 - 81.231 -Once the extension is enabled, it will make a number of new commands 81.232 -available. To verify that the extension is working, you can use 81.233 -\hgcmd{help} to see if the \hgxcmd{mq}{qinit} command is now available; see 81.234 -the example in figure~\ref{ex:mq:enabled}. 81.235 - 81.236 -\begin{figure}[ht] 81.237 - \interaction{mq.qinit-help.help} 81.238 - \caption{How to verify that MQ is enabled} 81.239 - \label{ex:mq:enabled} 81.240 -\end{figure} 81.241 - 81.242 -You can use MQ with \emph{any} Mercurial repository, and its commands 81.243 -only operate within that repository. To get started, simply prepare 81.244 -the repository using the \hgxcmd{mq}{qinit} command (see 81.245 -figure~\ref{ex:mq:qinit}). This command creates an empty directory 81.246 -called \sdirname{.hg/patches}, where MQ will keep its metadata. As 81.247 -with many Mercurial commands, the \hgxcmd{mq}{qinit} command prints nothing 81.248 -if it succeeds. 81.249 - 81.250 -\begin{figure}[ht] 81.251 - \interaction{mq.tutorial.qinit} 81.252 - \caption{Preparing a repository for use with MQ} 81.253 - \label{ex:mq:qinit} 81.254 -\end{figure} 81.255 - 81.256 -\begin{figure}[ht] 81.257 - \interaction{mq.tutorial.qnew} 81.258 - \caption{Creating a new patch} 81.259 - \label{ex:mq:qnew} 81.260 -\end{figure} 81.261 - 81.262 -\subsection{Creating a new patch} 81.263 - 81.264 -To begin work on a new patch, use the \hgxcmd{mq}{qnew} command. This 81.265 -command takes one argument, the name of the patch to create. MQ will 81.266 -use this as the name of an actual file in the \sdirname{.hg/patches} 81.267 -directory, as you can see in figure~\ref{ex:mq:qnew}. 81.268 - 81.269 -Also newly present in the \sdirname{.hg/patches} directory are two 81.270 -other files, \sfilename{series} and \sfilename{status}. The 81.271 -\sfilename{series} file lists all of the patches that MQ knows about 81.272 -for this repository, with one patch per line. Mercurial uses the 81.273 -\sfilename{status} file for internal book-keeping; it tracks all of the 81.274 -patches that MQ has \emph{applied} in this repository. 81.275 - 81.276 -\begin{note} 81.277 - You may sometimes want to edit the \sfilename{series} file by hand; 81.278 - for example, to change the sequence in which some patches are 81.279 - applied. However, manually editing the \sfilename{status} file is 81.280 - almost always a bad idea, as it's easy to corrupt MQ's idea of what 81.281 - is happening. 81.282 -\end{note} 81.283 - 81.284 -Once you have created your new patch, you can edit files in the 81.285 -working directory as you usually would. All of the normal Mercurial 81.286 -commands, such as \hgcmd{diff} and \hgcmd{annotate}, work exactly as 81.287 -they did before. 81.288 - 81.289 -\subsection{Refreshing a patch} 81.290 - 81.291 -When you reach a point where you want to save your work, use the 81.292 -\hgxcmd{mq}{qrefresh} command (figure~\ref{ex:mq:qnew}) to update the patch 81.293 -you are working on. This command folds the changes you have made in 81.294 -the working directory into your patch, and updates its corresponding 81.295 -changeset to contain those changes. 81.296 - 81.297 -\begin{figure}[ht] 81.298 - \interaction{mq.tutorial.qrefresh} 81.299 - \caption{Refreshing a patch} 81.300 - \label{ex:mq:qrefresh} 81.301 -\end{figure} 81.302 - 81.303 -You can run \hgxcmd{mq}{qrefresh} as often as you like, so it's a good way 81.304 -to ``checkpoint'' your work. Refresh your patch at an opportune 81.305 -time; try an experiment; and if the experiment doesn't work out, 81.306 -\hgcmd{revert} your modifications back to the last time you refreshed. 81.307 - 81.308 -\begin{figure}[ht] 81.309 - \interaction{mq.tutorial.qrefresh2} 81.310 - \caption{Refresh a patch many times to accumulate changes} 81.311 - \label{ex:mq:qrefresh2} 81.312 -\end{figure} 81.313 - 81.314 -\subsection{Stacking and tracking patches} 81.315 - 81.316 -Once you have finished working on a patch, or need to work on another, 81.317 -you can use the \hgxcmd{mq}{qnew} command again to create a new patch. 81.318 -Mercurial will apply this patch on top of your existing patch. See 81.319 -figure~\ref{ex:mq:qnew2} for an example. Notice that the patch 81.320 -contains the changes in our prior patch as part of its context (you 81.321 -can see this more clearly in the output of \hgcmd{annotate}). 81.322 - 81.323 -\begin{figure}[ht] 81.324 - \interaction{mq.tutorial.qnew2} 81.325 - \caption{Stacking a second patch on top of the first} 81.326 - \label{ex:mq:qnew2} 81.327 -\end{figure} 81.328 - 81.329 -So far, with the exception of \hgxcmd{mq}{qnew} and \hgxcmd{mq}{qrefresh}, we've 81.330 -been careful to only use regular Mercurial commands. However, MQ 81.331 -provides many commands that are easier to use when you are thinking 81.332 -about patches, as illustrated in figure~\ref{ex:mq:qseries}: 81.333 - 81.334 -\begin{itemize} 81.335 -\item The \hgxcmd{mq}{qseries} command lists every patch that MQ knows 81.336 - about in this repository, from oldest to newest (most recently 81.337 - \emph{created}). 81.338 -\item The \hgxcmd{mq}{qapplied} command lists every patch that MQ has 81.339 - \emph{applied} in this repository, again from oldest to newest (most 81.340 - recently applied). 81.341 -\end{itemize} 81.342 - 81.343 -\begin{figure}[ht] 81.344 - \interaction{mq.tutorial.qseries} 81.345 - \caption{Understanding the patch stack with \hgxcmd{mq}{qseries} and 81.346 - \hgxcmd{mq}{qapplied}} 81.347 - \label{ex:mq:qseries} 81.348 -\end{figure} 81.349 - 81.350 -\subsection{Manipulating the patch stack} 81.351 - 81.352 -The previous discussion implied that there must be a difference 81.353 -between ``known'' and ``applied'' patches, and there is. MQ can 81.354 -manage a patch without it being applied in the repository. 81.355 - 81.356 -An \emph{applied} patch has a corresponding changeset in the 81.357 -repository, and the effects of the patch and changeset are visible in 81.358 -the working directory. You can undo the application of a patch using 81.359 -the \hgxcmd{mq}{qpop} command. MQ still \emph{knows about}, or manages, a 81.360 -popped patch, but the patch no longer has a corresponding changeset in 81.361 -the repository, and the working directory does not contain the changes 81.362 -made by the patch. Figure~\ref{fig:mq:stack} illustrates the 81.363 -difference between applied and tracked patches. 81.364 - 81.365 -\begin{figure}[ht] 81.366 - \centering 81.367 - \grafix{mq-stack} 81.368 - \caption{Applied and unapplied patches in the MQ patch stack} 81.369 - \label{fig:mq:stack} 81.370 -\end{figure} 81.371 - 81.372 -You can reapply an unapplied, or popped, patch using the \hgxcmd{mq}{qpush} 81.373 -command. This creates a new changeset to correspond to the patch, and 81.374 -the patch's changes once again become present in the working 81.375 -directory. See figure~\ref{ex:mq:qpop} for examples of \hgxcmd{mq}{qpop} 81.376 -and \hgxcmd{mq}{qpush} in action. Notice that once we have popped a patch 81.377 -or two patches, the output of \hgxcmd{mq}{qseries} remains the same, while 81.378 -that of \hgxcmd{mq}{qapplied} has changed. 81.379 - 81.380 -\begin{figure}[ht] 81.381 - \interaction{mq.tutorial.qpop} 81.382 - \caption{Modifying the stack of applied patches} 81.383 - \label{ex:mq:qpop} 81.384 -\end{figure} 81.385 - 81.386 -\subsection{Pushing and popping many patches} 81.387 - 81.388 -While \hgxcmd{mq}{qpush} and \hgxcmd{mq}{qpop} each operate on a single patch at 81.389 -a time by default, you can push and pop many patches in one go. The 81.390 -\hgxopt{mq}{qpush}{-a} option to \hgxcmd{mq}{qpush} causes it to push all 81.391 -unapplied patches, while the \hgxopt{mq}{qpop}{-a} option to \hgxcmd{mq}{qpop} 81.392 -causes it to pop all applied patches. (For some more ways to push and 81.393 -pop many patches, see section~\ref{sec:mq:perf} below.) 81.394 - 81.395 -\begin{figure}[ht] 81.396 - \interaction{mq.tutorial.qpush-a} 81.397 - \caption{Pushing all unapplied patches} 81.398 - \label{ex:mq:qpush-a} 81.399 -\end{figure} 81.400 - 81.401 -\subsection{Safety checks, and overriding them} 81.402 - 81.403 -Several MQ commands check the working directory before they do 81.404 -anything, and fail if they find any modifications. They do this to 81.405 -ensure that you won't lose any changes that you have made, but not yet 81.406 -incorporated into a patch. Figure~\ref{ex:mq:add} illustrates this; 81.407 -the \hgxcmd{mq}{qnew} command will not create a new patch if there are 81.408 -outstanding changes, caused in this case by the \hgcmd{add} of 81.409 -\filename{file3}. 81.410 - 81.411 -\begin{figure}[ht] 81.412 - \interaction{mq.tutorial.add} 81.413 - \caption{Forcibly creating a patch} 81.414 - \label{ex:mq:add} 81.415 -\end{figure} 81.416 - 81.417 -Commands that check the working directory all take an ``I know what 81.418 -I'm doing'' option, which is always named \option{-f}. The exact 81.419 -meaning of \option{-f} depends on the command. For example, 81.420 -\hgcmdargs{qnew}{\hgxopt{mq}{qnew}{-f}} will incorporate any outstanding 81.421 -changes into the new patch it creates, but 81.422 -\hgcmdargs{qpop}{\hgxopt{mq}{qpop}{-f}} will revert modifications to any 81.423 -files affected by the patch that it is popping. Be sure to read the 81.424 -documentation for a command's \option{-f} option before you use it! 81.425 - 81.426 -\subsection{Working on several patches at once} 81.427 - 81.428 -The \hgxcmd{mq}{qrefresh} command always refreshes the \emph{topmost} 81.429 -applied patch. This means that you can suspend work on one patch (by 81.430 -refreshing it), pop or push to make a different patch the top, and 81.431 -work on \emph{that} patch for a while. 81.432 - 81.433 -Here's an example that illustrates how you can use this ability. 81.434 -Let's say you're developing a new feature as two patches. The first 81.435 -is a change to the core of your software, and the second---layered on 81.436 -top of the first---changes the user interface to use the code you just 81.437 -added to the core. If you notice a bug in the core while you're 81.438 -working on the UI patch, it's easy to fix the core. Simply 81.439 -\hgxcmd{mq}{qrefresh} the UI patch to save your in-progress changes, and 81.440 -\hgxcmd{mq}{qpop} down to the core patch. Fix the core bug, 81.441 -\hgxcmd{mq}{qrefresh} the core patch, and \hgxcmd{mq}{qpush} back to the UI 81.442 -patch to continue where you left off. 81.443 - 81.444 -\section{More about patches} 81.445 -\label{sec:mq:adv-patch} 81.446 - 81.447 -MQ uses the GNU \command{patch} command to apply patches, so it's 81.448 -helpful to know a few more detailed aspects of how \command{patch} 81.449 -works, and about patches themselves. 81.450 - 81.451 -\subsection{The strip count} 81.452 - 81.453 -If you look at the file headers in a patch, you will notice that the 81.454 -pathnames usually have an extra component on the front that isn't 81.455 -present in the actual path name. This is a holdover from the way that 81.456 -people used to generate patches (people still do this, but it's 81.457 -somewhat rare with modern revision control tools). 81.458 - 81.459 -Alice would unpack a tarball, edit her files, then decide that she 81.460 -wanted to create a patch. So she'd rename her working directory, 81.461 -unpack the tarball again (hence the need for the rename), and use the 81.462 -\cmdopt{diff}{-r} and \cmdopt{diff}{-N} options to \command{diff} to 81.463 -recursively generate a patch between the unmodified directory and the 81.464 -modified one. The result would be that the name of the unmodified 81.465 -directory would be at the front of the left-hand path in every file 81.466 -header, and the name of the modified directory would be at the front 81.467 -of the right-hand path. 81.468 - 81.469 -Since someone receiving a patch from the Alices of the net would be 81.470 -unlikely to have unmodified and modified directories with exactly the 81.471 -same names, the \command{patch} command has a \cmdopt{patch}{-p} 81.472 -option that indicates the number of leading path name components to 81.473 -strip when trying to apply a patch. This number is called the 81.474 -\emph{strip count}. 81.475 - 81.476 -An option of ``\texttt{-p1}'' means ``use a strip count of one''. If 81.477 -\command{patch} sees a file name \filename{foo/bar/baz} in a file 81.478 -header, it will strip \filename{foo} and try to patch a file named 81.479 -\filename{bar/baz}. (Strictly speaking, the strip count refers to the 81.480 -number of \emph{path separators} (and the components that go with them 81.481 -) to strip. A strip count of one will turn \filename{foo/bar} into 81.482 -\filename{bar}, but \filename{/foo/bar} (notice the extra leading 81.483 -slash) into \filename{foo/bar}.) 81.484 - 81.485 -The ``standard'' strip count for patches is one; almost all patches 81.486 -contain one leading path name component that needs to be stripped. 81.487 -Mercurial's \hgcmd{diff} command generates path names in this form, 81.488 -and the \hgcmd{import} command and MQ expect patches to have a strip 81.489 -count of one. 81.490 - 81.491 -If you receive a patch from someone that you want to add to your patch 81.492 -queue, and the patch needs a strip count other than one, you cannot 81.493 -just \hgxcmd{mq}{qimport} the patch, because \hgxcmd{mq}{qimport} does not yet 81.494 -have a \texttt{-p} option (see~\bug{311}). Your best bet is to 81.495 -\hgxcmd{mq}{qnew} a patch of your own, then use \cmdargs{patch}{-p\emph{N}} 81.496 -to apply their patch, followed by \hgcmd{addremove} to pick up any 81.497 -files added or removed by the patch, followed by \hgxcmd{mq}{qrefresh}. 81.498 -This complexity may become unnecessary; see~\bug{311} for details. 81.499 -\subsection{Strategies for applying a patch} 81.500 - 81.501 -When \command{patch} applies a hunk, it tries a handful of 81.502 -successively less accurate strategies to try to make the hunk apply. 81.503 -This falling-back technique often makes it possible to take a patch 81.504 -that was generated against an old version of a file, and apply it 81.505 -against a newer version of that file. 81.506 - 81.507 -First, \command{patch} tries an exact match, where the line numbers, 81.508 -the context, and the text to be modified must apply exactly. If it 81.509 -cannot make an exact match, it tries to find an exact match for the 81.510 -context, without honouring the line numbering information. If this 81.511 -succeeds, it prints a line of output saying that the hunk was applied, 81.512 -but at some \emph{offset} from the original line number. 81.513 - 81.514 -If a context-only match fails, \command{patch} removes the first and 81.515 -last lines of the context, and tries a \emph{reduced} context-only 81.516 -match. If the hunk with reduced context succeeds, it prints a message 81.517 -saying that it applied the hunk with a \emph{fuzz factor} (the number 81.518 -after the fuzz factor indicates how many lines of context 81.519 -\command{patch} had to trim before the patch applied). 81.520 - 81.521 -When neither of these techniques works, \command{patch} prints a 81.522 -message saying that the hunk in question was rejected. It saves 81.523 -rejected hunks (also simply called ``rejects'') to a file with the 81.524 -same name, and an added \sfilename{.rej} extension. It also saves an 81.525 -unmodified copy of the file with a \sfilename{.orig} extension; the 81.526 -copy of the file without any extensions will contain any changes made 81.527 -by hunks that \emph{did} apply cleanly. If you have a patch that 81.528 -modifies \filename{foo} with six hunks, and one of them fails to 81.529 -apply, you will have: an unmodified \filename{foo.orig}, a 81.530 -\filename{foo.rej} containing one hunk, and \filename{foo}, containing 81.531 -the changes made by the five successful hunks. 81.532 - 81.533 -\subsection{Some quirks of patch representation} 81.534 - 81.535 -There are a few useful things to know about how \command{patch} works 81.536 -with files. 81.537 -\begin{itemize} 81.538 -\item This should already be obvious, but \command{patch} cannot 81.539 - handle binary files. 81.540 -\item Neither does it care about the executable bit; it creates new 81.541 - files as readable, but not executable. 81.542 -\item \command{patch} treats the removal of a file as a diff between 81.543 - the file to be removed and the empty file. So your idea of ``I 81.544 - deleted this file'' looks like ``every line of this file was 81.545 - deleted'' in a patch. 81.546 -\item It treats the addition of a file as a diff between the empty 81.547 - file and the file to be added. So in a patch, your idea of ``I 81.548 - added this file'' looks like ``every line of this file was added''. 81.549 -\item It treats a renamed file as the removal of the old name, and the 81.550 - addition of the new name. This means that renamed files have a big 81.551 - footprint in patches. (Note also that Mercurial does not currently 81.552 - try to infer when files have been renamed or copied in a patch.) 81.553 -\item \command{patch} cannot represent empty files, so you cannot use 81.554 - a patch to represent the notion ``I added this empty file to the 81.555 - tree''. 81.556 -\end{itemize} 81.557 -\subsection{Beware the fuzz} 81.558 - 81.559 -While applying a hunk at an offset, or with a fuzz factor, will often 81.560 -be completely successful, these inexact techniques naturally leave 81.561 -open the possibility of corrupting the patched file. The most common 81.562 -cases typically involve applying a patch twice, or at an incorrect 81.563 -location in the file. If \command{patch} or \hgxcmd{mq}{qpush} ever 81.564 -mentions an offset or fuzz factor, you should make sure that the 81.565 -modified files are correct afterwards. 81.566 - 81.567 -It's often a good idea to refresh a patch that has applied with an 81.568 -offset or fuzz factor; refreshing the patch generates new context 81.569 -information that will make it apply cleanly. I say ``often,'' not 81.570 -``always,'' because sometimes refreshing a patch will make it fail to 81.571 -apply against a different revision of the underlying files. In some 81.572 -cases, such as when you're maintaining a patch that must sit on top of 81.573 -multiple versions of a source tree, it's acceptable to have a patch 81.574 -apply with some fuzz, provided you've verified the results of the 81.575 -patching process in such cases. 81.576 - 81.577 -\subsection{Handling rejection} 81.578 - 81.579 -If \hgxcmd{mq}{qpush} fails to apply a patch, it will print an error 81.580 -message and exit. If it has left \sfilename{.rej} files behind, it is 81.581 -usually best to fix up the rejected hunks before you push more patches 81.582 -or do any further work. 81.583 - 81.584 -If your patch \emph{used to} apply cleanly, and no longer does because 81.585 -you've changed the underlying code that your patches are based on, 81.586 -Mercurial Queues can help; see section~\ref{sec:mq:merge} for details. 81.587 - 81.588 -Unfortunately, there aren't any great techniques for dealing with 81.589 -rejected hunks. Most often, you'll need to view the \sfilename{.rej} 81.590 -file and edit the target file, applying the rejected hunks by hand. 81.591 - 81.592 -If you're feeling adventurous, Neil Brown, a Linux kernel hacker, 81.593 -wrote a tool called \command{wiggle}~\cite{web:wiggle}, which is more 81.594 -vigorous than \command{patch} in its attempts to make a patch apply. 81.595 - 81.596 -Another Linux kernel hacker, Chris Mason (the author of Mercurial 81.597 -Queues), wrote a similar tool called 81.598 -\command{mpatch}~\cite{web:mpatch}, which takes a simple approach to 81.599 -automating the application of hunks rejected by \command{patch}. The 81.600 -\command{mpatch} command can help with four common reasons that a hunk 81.601 -may be rejected: 81.602 - 81.603 -\begin{itemize} 81.604 -\item The context in the middle of a hunk has changed. 81.605 -\item A hunk is missing some context at the beginning or end. 81.606 -\item A large hunk might apply better---either entirely or in 81.607 - part---if it was broken up into smaller hunks. 81.608 -\item A hunk removes lines with slightly different content than those 81.609 - currently present in the file. 81.610 -\end{itemize} 81.611 - 81.612 -If you use \command{wiggle} or \command{mpatch}, you should be doubly 81.613 -careful to check your results when you're done. In fact, 81.614 -\command{mpatch} enforces this method of double-checking the tool's 81.615 -output, by automatically dropping you into a merge program when it has 81.616 -done its job, so that you can verify its work and finish off any 81.617 -remaining merges. 81.618 - 81.619 -\section{Getting the best performance out of MQ} 81.620 -\label{sec:mq:perf} 81.621 - 81.622 -MQ is very efficient at handling a large number of patches. I ran 81.623 -some performance experiments in mid-2006 for a talk that I gave at the 81.624 -2006 EuroPython conference~\cite{web:europython}. I used as my data 81.625 -set the Linux 2.6.17-mm1 patch series, which consists of 1,738 81.626 -patches. I applied these on top of a Linux kernel repository 81.627 -containing all 27,472 revisions between Linux 2.6.12-rc2 and Linux 81.628 -2.6.17. 81.629 - 81.630 -On my old, slow laptop, I was able to 81.631 -\hgcmdargs{qpush}{\hgxopt{mq}{qpush}{-a}} all 1,738 patches in 3.5 minutes, 81.632 -and \hgcmdargs{qpop}{\hgxopt{mq}{qpop}{-a}} them all in 30 seconds. (On a 81.633 -newer laptop, the time to push all patches dropped to two minutes.) I 81.634 -could \hgxcmd{mq}{qrefresh} one of the biggest patches (which made 22,779 81.635 -lines of changes to 287 files) in 6.6 seconds. 81.636 - 81.637 -Clearly, MQ is well suited to working in large trees, but there are a 81.638 -few tricks you can use to get the best performance of it. 81.639 - 81.640 -First of all, try to ``batch'' operations together. Every time you 81.641 -run \hgxcmd{mq}{qpush} or \hgxcmd{mq}{qpop}, these commands scan the working 81.642 -directory once to make sure you haven't made some changes and then 81.643 -forgotten to run \hgxcmd{mq}{qrefresh}. On a small tree, the time that 81.644 -this scan takes is unnoticeable. However, on a medium-sized tree 81.645 -(containing tens of thousands of files), it can take a second or more. 81.646 - 81.647 -The \hgxcmd{mq}{qpush} and \hgxcmd{mq}{qpop} commands allow you to push and pop 81.648 -multiple patches at a time. You can identify the ``destination 81.649 -patch'' that you want to end up at. When you \hgxcmd{mq}{qpush} with a 81.650 -destination specified, it will push patches until that patch is at the 81.651 -top of the applied stack. When you \hgxcmd{mq}{qpop} to a destination, MQ 81.652 -will pop patches until the destination patch is at the top. 81.653 - 81.654 -You can identify a destination patch using either the name of the 81.655 -patch, or by number. If you use numeric addressing, patches are 81.656 -counted from zero; this means that the first patch is zero, the second 81.657 -is one, and so on. 81.658 - 81.659 -\section{Updating your patches when the underlying code changes} 81.660 -\label{sec:mq:merge} 81.661 - 81.662 -It's common to have a stack of patches on top of an underlying 81.663 -repository that you don't modify directly. If you're working on 81.664 -changes to third-party code, or on a feature that is taking longer to 81.665 -develop than the rate of change of the code beneath, you will often 81.666 -need to sync up with the underlying code, and fix up any hunks in your 81.667 -patches that no longer apply. This is called \emph{rebasing} your 81.668 -patch series. 81.669 - 81.670 -The simplest way to do this is to \hgcmdargs{qpop}{\hgxopt{mq}{qpop}{-a}} 81.671 -your patches, then \hgcmd{pull} changes into the underlying 81.672 -repository, and finally \hgcmdargs{qpush}{\hgxopt{mq}{qpop}{-a}} your 81.673 -patches again. MQ will stop pushing any time it runs across a patch 81.674 -that fails to apply during conflicts, allowing you to fix your 81.675 -conflicts, \hgxcmd{mq}{qrefresh} the affected patch, and continue pushing 81.676 -until you have fixed your entire stack. 81.677 - 81.678 -This approach is easy to use and works well if you don't expect 81.679 -changes to the underlying code to affect how well your patches apply. 81.680 -If your patch stack touches code that is modified frequently or 81.681 -invasively in the underlying repository, however, fixing up rejected 81.682 -hunks by hand quickly becomes tiresome. 81.683 - 81.684 -It's possible to partially automate the rebasing process. If your 81.685 -patches apply cleanly against some revision of the underlying repo, MQ 81.686 -can use this information to help you to resolve conflicts between your 81.687 -patches and a different revision. 81.688 - 81.689 -The process is a little involved. 81.690 -\begin{enumerate} 81.691 -\item To begin, \hgcmdargs{qpush}{-a} all of your patches on top of 81.692 - the revision where you know that they apply cleanly. 81.693 -\item Save a backup copy of your patch directory using 81.694 - \hgcmdargs{qsave}{\hgxopt{mq}{qsave}{-e} \hgxopt{mq}{qsave}{-c}}. This prints 81.695 - the name of the directory that it has saved the patches in. It will 81.696 - save the patches to a directory called 81.697 - \sdirname{.hg/patches.\emph{N}}, where \texttt{\emph{N}} is a small 81.698 - integer. It also commits a ``save changeset'' on top of your 81.699 - applied patches; this is for internal book-keeping, and records the 81.700 - states of the \sfilename{series} and \sfilename{status} files. 81.701 -\item Use \hgcmd{pull} to bring new changes into the underlying 81.702 - repository. (Don't run \hgcmdargs{pull}{-u}; see below for why.) 81.703 -\item Update to the new tip revision, using 81.704 - \hgcmdargs{update}{\hgopt{update}{-C}} to override the patches you 81.705 - have pushed. 81.706 -\item Merge all patches using \hgcmdargs{qpush}{\hgxopt{mq}{qpush}{-m} 81.707 - \hgxopt{mq}{qpush}{-a}}. The \hgxopt{mq}{qpush}{-m} option to \hgxcmd{mq}{qpush} 81.708 - tells MQ to perform a three-way merge if the patch fails to apply. 81.709 -\end{enumerate} 81.710 - 81.711 -During the \hgcmdargs{qpush}{\hgxopt{mq}{qpush}{-m}}, each patch in the 81.712 -\sfilename{series} file is applied normally. If a patch applies with 81.713 -fuzz or rejects, MQ looks at the queue you \hgxcmd{mq}{qsave}d, and 81.714 -performs a three-way merge with the corresponding changeset. This 81.715 -merge uses Mercurial's normal merge machinery, so it may pop up a GUI 81.716 -merge tool to help you to resolve problems. 81.717 - 81.718 -When you finish resolving the effects of a patch, MQ refreshes your 81.719 -patch based on the result of the merge. 81.720 - 81.721 -At the end of this process, your repository will have one extra head 81.722 -from the old patch queue, and a copy of the old patch queue will be in 81.723 -\sdirname{.hg/patches.\emph{N}}. You can remove the extra head using 81.724 -\hgcmdargs{qpop}{\hgxopt{mq}{qpop}{-a} \hgxopt{mq}{qpop}{-n} patches.\emph{N}} 81.725 -or \hgcmd{strip}. You can delete \sdirname{.hg/patches.\emph{N}} once 81.726 -you are sure that you no longer need it as a backup. 81.727 - 81.728 -\section{Identifying patches} 81.729 - 81.730 -MQ commands that work with patches let you refer to a patch either by 81.731 -using its name or by a number. By name is obvious enough; pass the 81.732 -name \filename{foo.patch} to \hgxcmd{mq}{qpush}, for example, and it will 81.733 -push patches until \filename{foo.patch} is applied. 81.734 - 81.735 -As a shortcut, you can refer to a patch using both a name and a 81.736 -numeric offset; \texttt{foo.patch-2} means ``two patches before 81.737 -\texttt{foo.patch}'', while \texttt{bar.patch+4} means ``four patches 81.738 -after \texttt{bar.patch}''. 81.739 - 81.740 -Referring to a patch by index isn't much different. The first patch 81.741 -printed in the output of \hgxcmd{mq}{qseries} is patch zero (yes, it's one 81.742 -of those start-at-zero counting systems); the second is patch one; and 81.743 -so on. 81.744 - 81.745 -MQ also makes it easy to work with patches when you are using normal 81.746 -Mercurial commands. Every command that accepts a changeset ID will 81.747 -also accept the name of an applied patch. MQ augments the tags 81.748 -normally in the repository with an eponymous one for each applied 81.749 -patch. In addition, the special tags \index{tags!special tag 81.750 - names!\texttt{qbase}}\texttt{qbase} and \index{tags!special tag 81.751 - names!\texttt{qtip}}\texttt{qtip} identify the ``bottom-most'' and 81.752 -topmost applied patches, respectively. 81.753 - 81.754 -These additions to Mercurial's normal tagging capabilities make 81.755 -dealing with patches even more of a breeze. 81.756 -\begin{itemize} 81.757 -\item Want to patchbomb a mailing list with your latest series of 81.758 - changes? 81.759 - \begin{codesample4} 81.760 - hg email qbase:qtip 81.761 - \end{codesample4} 81.762 - (Don't know what ``patchbombing'' is? See 81.763 - section~\ref{sec:hgext:patchbomb}.) 81.764 -\item Need to see all of the patches since \texttt{foo.patch} that 81.765 - have touched files in a subdirectory of your tree? 81.766 - \begin{codesample4} 81.767 - hg log -r foo.patch:qtip \emph{subdir} 81.768 - \end{codesample4} 81.769 -\end{itemize} 81.770 - 81.771 -Because MQ makes the names of patches available to the rest of 81.772 -Mercurial through its normal internal tag machinery, you don't need to 81.773 -type in the entire name of a patch when you want to identify it by 81.774 -name. 81.775 - 81.776 -\begin{figure}[ht] 81.777 - \interaction{mq.id.output} 81.778 - \caption{Using MQ's tag features to work with patches} 81.779 - \label{ex:mq:id} 81.780 -\end{figure} 81.781 - 81.782 -Another nice consequence of representing patch names as tags is that 81.783 -when you run the \hgcmd{log} command, it will display a patch's name 81.784 -as a tag, simply as part of its normal output. This makes it easy to 81.785 -visually distinguish applied patches from underlying ``normal'' 81.786 -revisions. Figure~\ref{ex:mq:id} shows a few normal Mercurial 81.787 -commands in use with applied patches. 81.788 - 81.789 -\section{Useful things to know about} 81.790 - 81.791 -There are a number of aspects of MQ usage that don't fit tidily into 81.792 -sections of their own, but that are good to know. Here they are, in 81.793 -one place. 81.794 - 81.795 -\begin{itemize} 81.796 -\item Normally, when you \hgxcmd{mq}{qpop} a patch and \hgxcmd{mq}{qpush} it 81.797 - again, the changeset that represents the patch after the pop/push 81.798 - will have a \emph{different identity} than the changeset that 81.799 - represented the hash beforehand. See 81.800 - section~\ref{sec:mqref:cmd:qpush} for information as to why this is. 81.801 -\item It's not a good idea to \hgcmd{merge} changes from another 81.802 - branch with a patch changeset, at least if you want to maintain the 81.803 - ``patchiness'' of that changeset and changesets below it on the 81.804 - patch stack. If you try to do this, it will appear to succeed, but 81.805 - MQ will become confused. 81.806 -\end{itemize} 81.807 - 81.808 -\section{Managing patches in a repository} 81.809 -\label{sec:mq:repo} 81.810 - 81.811 -Because MQ's \sdirname{.hg/patches} directory resides outside a 81.812 -Mercurial repository's working directory, the ``underlying'' Mercurial 81.813 -repository knows nothing about the management or presence of patches. 81.814 - 81.815 -This presents the interesting possibility of managing the contents of 81.816 -the patch directory as a Mercurial repository in its own right. This 81.817 -can be a useful way to work. For example, you can work on a patch for 81.818 -a while, \hgxcmd{mq}{qrefresh} it, then \hgcmd{commit} the current state of 81.819 -the patch. This lets you ``roll back'' to that version of the patch 81.820 -later on. 81.821 - 81.822 -You can then share different versions of the same patch stack among 81.823 -multiple underlying repositories. I use this when I am developing a 81.824 -Linux kernel feature. I have a pristine copy of my kernel sources for 81.825 -each of several CPU architectures, and a cloned repository under each 81.826 -that contains the patches I am working on. When I want to test a 81.827 -change on a different architecture, I push my current patches to the 81.828 -patch repository associated with that kernel tree, pop and push all of 81.829 -my patches, and build and test that kernel. 81.830 - 81.831 -Managing patches in a repository makes it possible for multiple 81.832 -developers to work on the same patch series without colliding with 81.833 -each other, all on top of an underlying source base that they may or 81.834 -may not control. 81.835 - 81.836 -\subsection{MQ support for patch repositories} 81.837 - 81.838 -MQ helps you to work with the \sdirname{.hg/patches} directory as a 81.839 -repository; when you prepare a repository for working with patches 81.840 -using \hgxcmd{mq}{qinit}, you can pass the \hgxopt{mq}{qinit}{-c} option to 81.841 -create the \sdirname{.hg/patches} directory as a Mercurial repository. 81.842 - 81.843 -\begin{note} 81.844 - If you forget to use the \hgxopt{mq}{qinit}{-c} option, you can simply go 81.845 - into the \sdirname{.hg/patches} directory at any time and run 81.846 - \hgcmd{init}. Don't forget to add an entry for the 81.847 - \sfilename{status} file to the \sfilename{.hgignore} file, though 81.848 - 81.849 - (\hgcmdargs{qinit}{\hgxopt{mq}{qinit}{-c}} does this for you 81.850 - automatically); you \emph{really} don't want to manage the 81.851 - \sfilename{status} file. 81.852 -\end{note} 81.853 - 81.854 -As a convenience, if MQ notices that the \dirname{.hg/patches} 81.855 -directory is a repository, it will automatically \hgcmd{add} every 81.856 -patch that you create and import. 81.857 - 81.858 -MQ provides a shortcut command, \hgxcmd{mq}{qcommit}, that runs 81.859 -\hgcmd{commit} in the \sdirname{.hg/patches} directory. This saves 81.860 -some bothersome typing. 81.861 - 81.862 -Finally, as a convenience to manage the patch directory, you can 81.863 -define the alias \command{mq} on Unix systems. For example, on Linux 81.864 -systems using the \command{bash} shell, you can include the following 81.865 -snippet in your \tildefile{.bashrc}. 81.866 - 81.867 -\begin{codesample2} 81.868 - alias mq=`hg -R \$(hg root)/.hg/patches' 81.869 -\end{codesample2} 81.870 - 81.871 -You can then issue commands of the form \cmdargs{mq}{pull} from 81.872 -the main repository. 81.873 - 81.874 -\subsection{A few things to watch out for} 81.875 - 81.876 -MQ's support for working with a repository full of patches is limited 81.877 -in a few small respects. 81.878 - 81.879 -MQ cannot automatically detect changes that you make to the patch 81.880 -directory. If you \hgcmd{pull}, manually edit, or \hgcmd{update} 81.881 -changes to patches or the \sfilename{series} file, you will have to 81.882 -\hgcmdargs{qpop}{\hgxopt{mq}{qpop}{-a}} and then 81.883 -\hgcmdargs{qpush}{\hgxopt{mq}{qpush}{-a}} in the underlying repository to 81.884 -see those changes show up there. If you forget to do this, you can 81.885 -confuse MQ's idea of which patches are applied. 81.886 - 81.887 -\section{Third party tools for working with patches} 81.888 -\label{sec:mq:tools} 81.889 - 81.890 -Once you've been working with patches for a while, you'll find 81.891 -yourself hungry for tools that will help you to understand and 81.892 -manipulate the patches you're dealing with. 81.893 - 81.894 -The \command{diffstat} command~\cite{web:diffstat} generates a 81.895 -histogram of the modifications made to each file in a patch. It 81.896 -provides a good way to ``get a sense of'' a patch---which files it 81.897 -affects, and how much change it introduces to each file and as a 81.898 -whole. (I find that it's a good idea to use \command{diffstat}'s 81.899 -\cmdopt{diffstat}{-p} option as a matter of course, as otherwise it 81.900 -will try to do clever things with prefixes of file names that 81.901 -inevitably confuse at least me.) 81.902 - 81.903 -\begin{figure}[ht] 81.904 - \interaction{mq.tools.tools} 81.905 - \caption{The \command{diffstat}, \command{filterdiff}, and \command{lsdiff} commands} 81.906 - \label{ex:mq:tools} 81.907 -\end{figure} 81.908 - 81.909 -The \package{patchutils} package~\cite{web:patchutils} is invaluable. 81.910 -It provides a set of small utilities that follow the ``Unix 81.911 -philosophy;'' each does one useful thing with a patch. The 81.912 -\package{patchutils} command I use most is \command{filterdiff}, which 81.913 -extracts subsets from a patch file. For example, given a patch that 81.914 -modifies hundreds of files across dozens of directories, a single 81.915 -invocation of \command{filterdiff} can generate a smaller patch that 81.916 -only touches files whose names match a particular glob pattern. See 81.917 -section~\ref{mq-collab:tips:interdiff} for another example. 81.918 - 81.919 -\section{Good ways to work with patches} 81.920 - 81.921 -Whether you are working on a patch series to submit to a free software 81.922 -or open source project, or a series that you intend to treat as a 81.923 -sequence of regular changesets when you're done, you can use some 81.924 -simple techniques to keep your work well organised. 81.925 - 81.926 -Give your patches descriptive names. A good name for a patch might be 81.927 -\filename{rework-device-alloc.patch}, because it will immediately give 81.928 -you a hint what the purpose of the patch is. Long names shouldn't be 81.929 -a problem; you won't be typing the names often, but you \emph{will} be 81.930 -running commands like \hgxcmd{mq}{qapplied} and \hgxcmd{mq}{qtop} over and over. 81.931 -Good naming becomes especially important when you have a number of 81.932 -patches to work with, or if you are juggling a number of different 81.933 -tasks and your patches only get a fraction of your attention. 81.934 - 81.935 -Be aware of what patch you're working on. Use the \hgxcmd{mq}{qtop} 81.936 -command and skim over the text of your patches frequently---for 81.937 -example, using \hgcmdargs{tip}{\hgopt{tip}{-p}})---to be sure of where 81.938 -you stand. I have several times worked on and \hgxcmd{mq}{qrefresh}ed a 81.939 -patch other than the one I intended, and it's often tricky to migrate 81.940 -changes into the right patch after making them in the wrong one. 81.941 - 81.942 -For this reason, it is very much worth investing a little time to 81.943 -learn how to use some of the third-party tools I described in 81.944 -section~\ref{sec:mq:tools}, particularly \command{diffstat} and 81.945 -\command{filterdiff}. The former will give you a quick idea of what 81.946 -changes your patch is making, while the latter makes it easy to splice 81.947 -hunks selectively out of one patch and into another. 81.948 - 81.949 -\section{MQ cookbook} 81.950 - 81.951 -\subsection{Manage ``trivial'' patches} 81.952 - 81.953 -Because the overhead of dropping files into a new Mercurial repository 81.954 -is so low, it makes a lot of sense to manage patches this way even if 81.955 -you simply want to make a few changes to a source tarball that you 81.956 -downloaded. 81.957 - 81.958 -Begin by downloading and unpacking the source tarball, 81.959 -and turning it into a Mercurial repository. 81.960 -\interaction{mq.tarball.download} 81.961 - 81.962 -Continue by creating a patch stack and making your changes. 81.963 -\interaction{mq.tarball.qinit} 81.964 - 81.965 -Let's say a few weeks or months pass, and your package author releases 81.966 -a new version. First, bring their changes into the repository. 81.967 -\interaction{mq.tarball.newsource} 81.968 -The pipeline starting with \hgcmd{locate} above deletes all files in 81.969 -the working directory, so that \hgcmd{commit}'s 81.970 -\hgopt{commit}{--addremove} option can actually tell which files have 81.971 -really been removed in the newer version of the source. 81.972 - 81.973 -Finally, you can apply your patches on top of the new tree. 81.974 -\interaction{mq.tarball.repush} 81.975 - 81.976 -\subsection{Combining entire patches} 81.977 -\label{sec:mq:combine} 81.978 - 81.979 -MQ provides a command, \hgxcmd{mq}{qfold} that lets you combine entire 81.980 -patches. This ``folds'' the patches you name, in the order you name 81.981 -them, into the topmost applied patch, and concatenates their 81.982 -descriptions onto the end of its description. The patches that you 81.983 -fold must be unapplied before you fold them. 81.984 - 81.985 -The order in which you fold patches matters. If your topmost applied 81.986 -patch is \texttt{foo}, and you \hgxcmd{mq}{qfold} \texttt{bar} and 81.987 -\texttt{quux} into it, you will end up with a patch that has the same 81.988 -effect as if you applied first \texttt{foo}, then \texttt{bar}, 81.989 -followed by \texttt{quux}. 81.990 - 81.991 -\subsection{Merging part of one patch into another} 81.992 - 81.993 -Merging \emph{part} of one patch into another is more difficult than 81.994 -combining entire patches. 81.995 - 81.996 -If you want to move changes to entire files, you can use 81.997 -\command{filterdiff}'s \cmdopt{filterdiff}{-i} and 81.998 -\cmdopt{filterdiff}{-x} options to choose the modifications to snip 81.999 -out of one patch, concatenating its output onto the end of the patch 81.1000 -you want to merge into. You usually won't need to modify the patch 81.1001 -you've merged the changes from. Instead, MQ will report some rejected 81.1002 -hunks when you \hgxcmd{mq}{qpush} it (from the hunks you moved into the 81.1003 -other patch), and you can simply \hgxcmd{mq}{qrefresh} the patch to drop 81.1004 -the duplicate hunks. 81.1005 - 81.1006 -If you have a patch that has multiple hunks modifying a file, and you 81.1007 -only want to move a few of those hunks, the job becomes more messy, 81.1008 -but you can still partly automate it. Use \cmdargs{lsdiff}{-nvv} to 81.1009 -print some metadata about the patch. 81.1010 -\interaction{mq.tools.lsdiff} 81.1011 - 81.1012 -This command prints three different kinds of number: 81.1013 -\begin{itemize} 81.1014 -\item (in the first column) a \emph{file number} to identify each file 81.1015 - modified in the patch; 81.1016 -\item (on the next line, indented) the line number within a modified 81.1017 - file where a hunk starts; and 81.1018 -\item (on the same line) a \emph{hunk number} to identify that hunk. 81.1019 -\end{itemize} 81.1020 - 81.1021 -You'll have to use some visual inspection, and reading of the patch, 81.1022 -to identify the file and hunk numbers you'll want, but you can then 81.1023 -pass them to to \command{filterdiff}'s \cmdopt{filterdiff}{--files} 81.1024 -and \cmdopt{filterdiff}{--hunks} options, to select exactly the file 81.1025 -and hunk you want to extract. 81.1026 - 81.1027 -Once you have this hunk, you can concatenate it onto the end of your 81.1028 -destination patch and continue with the remainder of 81.1029 -section~\ref{sec:mq:combine}. 81.1030 - 81.1031 -\section{Differences between quilt and MQ} 81.1032 - 81.1033 -If you are already familiar with quilt, MQ provides a similar command 81.1034 -set. There are a few differences in the way that it works. 81.1035 - 81.1036 -You will already have noticed that most quilt commands have MQ 81.1037 -counterparts that simply begin with a ``\texttt{q}''. The exceptions 81.1038 -are quilt's \texttt{add} and \texttt{remove} commands, the 81.1039 -counterparts for which are the normal Mercurial \hgcmd{add} and 81.1040 -\hgcmd{remove} commands. There is no MQ equivalent of the quilt 81.1041 -\texttt{edit} command. 81.1042 - 81.1043 -%%% Local Variables: 81.1044 -%%% mode: latex 81.1045 -%%% TeX-master: "00book" 81.1046 -%%% End:
82.1 Binary file fr/note.png has changed
83.1 --- a/fr/preface.tex Sun Aug 16 03:41:39 2009 +0200 83.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 83.3 @@ -1,65 +0,0 @@ 83.4 -\chapter*{Préface} 83.5 -\addcontentsline{toc}{chapter}{Préface} 83.6 -\label{chap:preface} 83.7 - 83.8 -La gestion de source distribuée est encore un territoire peu exploré 83.9 -et qui, par conséquent, a grandi très rapidement grâce à la seule 83.10 -volonté de ses explorateurs. 83.11 - 83.12 -Je rédige un livre sur ce sujet car je crois que c'est un sujet 83.13 -important qui mérite bien un guide du ``terrain''. J'ai choisi d'écrire 83.14 -ce livre sur Mercurial car c'est l'outil le plus simple pour découvrir 83.15 -ce nouveau monde et qu'en outre, il répond très bien au besoin de 83.16 -réels environnements, là où d'autres outils de gestion de source n'y 83.17 -parviennent pas. 83.18 - 83.19 -\section{Cet ouvrage est un travail en cours} 83.20 - 83.21 -Je publie ce livre tout en continuant à l'écrire, dans l'espoir qu'il 83.22 -vous sera utile. J'espère aussi que les lecteurs pourront ainsi y contribuer 83.23 -si ils le souhaitent. 83.24 - 83.25 -\section{À propros des exemples de ce livre} 83.26 - 83.27 -Ce livre a une approche particulière des exemples d'exécution. Ils sont 83.28 -toujours ``dynamiques''---chacun est le résultat d'un script shell qui 83.29 -exécute les commandes Mercurial que vous voyez. Chaque fois qu'une 83.30 -image du livre est construite à partir des sources, tous les scripts d'exemple 83.31 -sont exécutés automatiquement, et les résultats comparés à ceux attendus. 83.32 - 83.33 -Cette approche a l'avantage de garantir que les exemples sont toujours 83.34 -justes ; ils montrent \emph{exactement} le comportement de la version de 83.35 -Mercurial spécifiée dans la couverture de ce livre. Si je mets à jour cette 83.36 -version, et que les commandes changent, la génération du livre échouera. 83.37 - 83.38 -Il y a un petit désavantage à cette approche, les dates et les 83.39 -durées que vous verrez dans ces exemples ont tendances à être 83.40 -``réduits'' de manière très différente d'une exécution manuelle. Un être humain 83.41 -ne peut exécuter qu'une commande toutes les secondes, alors que mes scripts 83.42 -automatisés en exécutent plusieurs en une seule seconde. 83.43 - 83.44 -Ainsi, en une seule seconde, plusieurs ``commits'' peuvent avoir lieu 83.45 -au sein d'un exemple. Vous le constatez, entre autres, dans les 83.46 -exemples sur \hgext{bisect}, dans la section~\ref{sec:undo:bisect}. 83.47 - 83.48 -En conséquence, quand vous lisez les exemples, n'accordez pas trop 83.49 -d'importance aux dates et aux durées d'exécution des commandes. Mais 83.50 -\emph{soyez sûr} que le comportement que vous voyez est cohérent et 83.51 -reproductible. 83.52 - 83.53 -\section{Colophon---Cet ouvrage est libre} 83.54 - 83.55 -Ce livre est publié sous la licence ``Open Publication License'' 83.56 -\footnote{Pour plus de renseignements : 83.57 -\url{http://opencontent.org/openpub/}{Open Publication License} }, 83.58 -et est construit uniquement à l'aide de logiciels libres. Il est mis 83.59 -en forme avec \LaTex{}; et les illustrations sont réalisées avec 83.60 -\href{http://www.inkscape.org/}{Inkscape}. 83.61 - 83.62 -L'ensemble des fichiers sources de cet ouvrage est publié dans un 83.63 -dépot mercurial \url{http://hg.serpentine.com/mercurial/book}. 83.64 - 83.65 -%%% Local Variables: 83.66 -%%% mode: latex 83.67 -%%% TeX-master: "00book" 83.68 -%%% End:
84.1 --- a/fr/revlog.svg Sun Aug 16 03:41:39 2009 +0200 84.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 84.3 @@ -1,1155 +0,0 @@ 84.4 -<?xml version="1.0" encoding="UTF-8" standalone="no"?> 84.5 -<!-- Created with Inkscape (http://www.inkscape.org/) --> 84.6 -<svg 84.7 - xmlns:dc="http://purl.org/dc/elements/1.1/" 84.8 - xmlns:cc="http://web.resource.org/cc/" 84.9 - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 84.10 - xmlns:svg="http://www.w3.org/2000/svg" 84.11 - xmlns="http://www.w3.org/2000/svg" 84.12 - xmlns:xlink="http://www.w3.org/1999/xlink" 84.13 - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" 84.14 - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" 84.15 - width="744.09448819" 84.16 - height="1052.3622047" 84.17 - id="svg2" 84.18 - sodipodi:version="0.32" 84.19 - inkscape:version="0.44.1" 84.20 - sodipodi:docbase="/home/bos/hg/hgbook/en" 84.21 - sodipodi:docname="revlog.svg"> 84.22 - <defs 84.23 - id="defs4"> 84.24 - <marker 84.25 - inkscape:stockid="Arrow1Mend" 84.26 - orient="auto" 84.27 - refY="0.0" 84.28 - refX="0.0" 84.29 - id="Arrow1Mend" 84.30 - style="overflow:visible;"> 84.31 - <path 84.32 - id="path4852" 84.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 " 84.34 - style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;" 84.35 - transform="scale(0.4) rotate(180) translate(10,0)" /> 84.36 - </marker> 84.37 - <linearGradient 84.38 - id="linearGradient3092"> 84.39 - <stop 84.40 - style="stop-color:#44436f;stop-opacity:1;" 84.41 - offset="0" 84.42 - id="stop3094" /> 84.43 - <stop 84.44 - style="stop-color:#abade5;stop-opacity:1;" 84.45 - offset="1" 84.46 - id="stop3096" /> 84.47 - </linearGradient> 84.48 - <linearGradient 84.49 - inkscape:collect="always" 84.50 - xlink:href="#linearGradient3092" 84.51 - id="linearGradient3118" 84.52 - gradientUnits="userSpaceOnUse" 84.53 - x1="176.16635" 84.54 - y1="405.21934" 84.55 - x2="417.11935" 84.56 - y2="405.21934" /> 84.57 - <linearGradient 84.58 - inkscape:collect="always" 84.59 - xlink:href="#linearGradient3092" 84.60 - id="linearGradient3120" 84.61 - gradientUnits="userSpaceOnUse" 84.62 - x1="176.16635" 84.63 - y1="405.21934" 84.64 - x2="417.11935" 84.65 - y2="405.21934" /> 84.66 - <linearGradient 84.67 - inkscape:collect="always" 84.68 - xlink:href="#linearGradient3092" 84.69 - id="linearGradient3129" 84.70 - gradientUnits="userSpaceOnUse" 84.71 - x1="176.16635" 84.72 - y1="405.21934" 84.73 - x2="417.11935" 84.74 - y2="405.21934" 84.75 - gradientTransform="translate(-0.928574,-1.428574)" /> 84.76 - <linearGradient 84.77 - inkscape:collect="always" 84.78 - xlink:href="#linearGradient3092" 84.79 - id="linearGradient3133" 84.80 - gradientUnits="userSpaceOnUse" 84.81 - x1="176.16635" 84.82 - y1="405.21934" 84.83 - x2="417.11935" 84.84 - y2="405.21934" 84.85 - gradientTransform="translate(-0.928574,-1.428574)" /> 84.86 - <linearGradient 84.87 - inkscape:collect="always" 84.88 - xlink:href="#linearGradient3092" 84.89 - id="linearGradient3708" 84.90 - gradientUnits="userSpaceOnUse" 84.91 - gradientTransform="matrix(0.423343,0,0,0.423343,138.874,-67.01732)" 84.92 - x1="175.23776" 84.93 - y1="509.98154" 84.94 - x2="416.29077" 84.95 - y2="297.49997" /> 84.96 - <linearGradient 84.97 - inkscape:collect="always" 84.98 - xlink:href="#linearGradient3092" 84.99 - id="linearGradient5164" 84.100 - gradientUnits="userSpaceOnUse" 84.101 - gradientTransform="matrix(0.423343,0,0,0.423343,198.249,247.4358)" 84.102 - x1="175.23776" 84.103 - y1="509.98154" 84.104 - x2="416.29077" 84.105 - y2="297.49997" /> 84.106 - <linearGradient 84.107 - inkscape:collect="always" 84.108 - xlink:href="#linearGradient3092" 84.109 - id="linearGradient5584" 84.110 - gradientUnits="userSpaceOnUse" 84.111 - gradientTransform="matrix(0.423343,0,0,0.423343,143.9081,371.2915)" 84.112 - x1="175.23776" 84.113 - y1="509.98154" 84.114 - x2="416.29077" 84.115 - y2="297.49997" /> 84.116 - <linearGradient 84.117 - inkscape:collect="always" 84.118 - xlink:href="#linearGradient3092" 84.119 - id="linearGradient5784" 84.120 - gradientUnits="userSpaceOnUse" 84.121 - gradientTransform="matrix(0.423343,0,0,0.423343,76.37397,152.137)" 84.122 - x1="175.23776" 84.123 - y1="509.98154" 84.124 - x2="416.29077" 84.125 - y2="297.49997" /> 84.126 - <linearGradient 84.127 - inkscape:collect="always" 84.128 - xlink:href="#linearGradient3092" 84.129 - id="linearGradient5786" 84.130 - gradientUnits="userSpaceOnUse" 84.131 - gradientTransform="matrix(0.423343,0,0,0.423343,198.249,152.137)" 84.132 - x1="175.23776" 84.133 - y1="509.98154" 84.134 - x2="416.29077" 84.135 - y2="297.49997" /> 84.136 - <linearGradient 84.137 - inkscape:collect="always" 84.138 - xlink:href="#linearGradient3092" 84.139 - id="linearGradient5895" 84.140 - gradientUnits="userSpaceOnUse" 84.141 - gradientTransform="matrix(0.423343,0,0,0.423343,198.0215,261.7142)" 84.142 - x1="175.23776" 84.143 - y1="509.98154" 84.144 - x2="416.29077" 84.145 - y2="297.49997" /> 84.146 - <linearGradient 84.147 - inkscape:collect="always" 84.148 - xlink:href="#linearGradient3092" 84.149 - id="linearGradient5958" 84.150 - gradientUnits="userSpaceOnUse" 84.151 - gradientTransform="matrix(0.423343,0,0,0.423343,137.1978,42.55987)" 84.152 - x1="175.23776" 84.153 - y1="509.98154" 84.154 - x2="416.29077" 84.155 - y2="297.49997" /> 84.156 - </defs> 84.157 - <sodipodi:namedview 84.158 - id="base" 84.159 - pagecolor="#ffffff" 84.160 - bordercolor="#666666" 84.161 - borderopacity="1.0" 84.162 - gridtolerance="10000" 84.163 - guidetolerance="10" 84.164 - objecttolerance="10" 84.165 - inkscape:pageopacity="0.0" 84.166 - inkscape:pageshadow="2" 84.167 - inkscape:zoom="0.64" 84.168 - inkscape:cx="566.02368" 84.169 - inkscape:cy="688.16826" 84.170 - inkscape:document-units="px" 84.171 - inkscape:current-layer="layer1" 84.172 - inkscape:window-width="906" 84.173 - inkscape:window-height="620" 84.174 - inkscape:window-x="29" 84.175 - inkscape:window-y="79" 84.176 - inkscape:connector-spacing="11" /> 84.177 - <metadata 84.178 - id="metadata7"> 84.179 - <rdf:RDF> 84.180 - <cc:Work 84.181 - rdf:about=""> 84.182 - <dc:format>image/svg+xml</dc:format> 84.183 - <dc:type 84.184 - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 84.185 - </cc:Work> 84.186 - </rdf:RDF> 84.187 - </metadata> 84.188 - <g 84.189 - inkscape:label="Layer 1" 84.190 - inkscape:groupmode="layer" 84.191 - id="layer1"> 84.192 - <rect 84.193 - y="168.74846" 84.194 - x="211.58516" 84.195 - height="89.506805" 84.196 - width="101.60232" 84.197 - id="rect3068" 84.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" /> 84.199 - <g 84.200 - id="g3215" 84.201 - transform="matrix(0.423343,0,0,0.423343,137.1977,42.55985)"> 84.202 - <rect 84.203 - y="447.71451" 84.204 - x="299.67859" 84.205 - height="48.571426" 84.206 - width="103.14286" 84.207 - id="rect2899" 84.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" /> 84.209 - <text 84.210 - id="text2903" 84.211 - y="464.8139" 84.212 - x="308.89639" 84.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" 84.214 - xml:space="preserve"><tspan 84.215 - y="464.8139" 84.216 - x="308.89639" 84.217 - sodipodi:role="line" 84.218 - id="tspan2905">Second parent</tspan></text> 84.219 - <text 84.220 - id="text2907" 84.221 - y="485.50256" 84.222 - x="308.20175" 84.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" 84.224 - xml:space="preserve"><tspan 84.225 - style="font-family:Courier" 84.226 - y="485.50256" 84.227 - x="308.20175" 84.228 - id="tspan2909" 84.229 - sodipodi:role="line">32bf9a5f22c0</tspan></text> 84.230 - </g> 84.231 - <g 84.232 - id="g3250" 84.233 - transform="matrix(0.423343,0,0,0.423343,137.1977,42.55986)"> 84.234 - <rect 84.235 - y="311.28598" 84.236 - x="188.6071" 84.237 - height="48.571426" 84.238 - width="103.14286" 84.239 - id="rect2936" 84.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" /> 84.241 - <text 84.242 - id="text2940" 84.243 - y="328.38538" 84.244 - x="197.82495" 84.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" 84.246 - xml:space="preserve"><tspan 84.247 - y="328.38538" 84.248 - x="197.82495" 84.249 - sodipodi:role="line" 84.250 - id="tspan2942">Revision hash</tspan></text> 84.251 - <text 84.252 - id="text2944" 84.253 - y="349.07404" 84.254 - x="197.13031" 84.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" 84.256 - xml:space="preserve"><tspan 84.257 - style="font-family:Courier" 84.258 - y="349.07404" 84.259 - x="197.13031" 84.260 - id="tspan2946" 84.261 - sodipodi:role="line">34b8b7a15ea1</tspan></text> 84.262 - </g> 84.263 - <g 84.264 - id="g3243" 84.265 - transform="matrix(0.423343,0,0,0.423343,137.6664,43.91853)"> 84.266 - <rect 84.267 - y="363.07654" 84.268 - x="187.5" 84.269 - height="75" 84.270 - width="213.85715" 84.271 - id="rect2950" 84.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" /> 84.273 - <text 84.274 - id="text2958" 84.275 - y="400.86459" 84.276 - x="196.02321" 84.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" 84.278 - xml:space="preserve"><tspan 84.279 - style="fill:black;fill-opacity:1;font-family:Courier" 84.280 - y="400.86459" 84.281 - x="196.02321" 84.282 - id="tspan2960" 84.283 - sodipodi:role="line">...</tspan></text> 84.284 - <text 84.285 - id="text2954" 84.286 - y="380.17593" 84.287 - x="196.71785" 84.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" 84.289 - xml:space="preserve"><tspan 84.290 - y="380.17593" 84.291 - x="196.71785" 84.292 - sodipodi:role="line" 84.293 - id="tspan2956" 84.294 - style="fill:black;fill-opacity:1">Revision data (delta or snapshot)</tspan></text> 84.295 - </g> 84.296 - <g 84.297 - id="g5529" 84.298 - transform="translate(-6.710312,-8.165836e-6)"> 84.299 - <rect 84.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" 84.301 - id="rect3509" 84.302 - width="101.60232" 84.303 - height="89.506805" 84.304 - x="218.29547" 84.305 - y="497.4801" /> 84.306 - <g 84.307 - transform="matrix(0.423343,0,0,0.423343,143.908,371.2915)" 84.308 - id="g3513"> 84.309 - <g 84.310 - id="g3515"> 84.311 - <rect 84.312 - y="447.72418" 84.313 - x="188.6071" 84.314 - height="48.571426" 84.315 - width="103.14286" 84.316 - id="rect3517" 84.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" /> 84.318 - <text 84.319 - id="text3519" 84.320 - y="464.82358" 84.321 - x="197.82495" 84.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" 84.323 - xml:space="preserve"><tspan 84.324 - y="464.82358" 84.325 - x="197.82495" 84.326 - sodipodi:role="line" 84.327 - id="tspan3521">First parent</tspan></text> 84.328 - <text 84.329 - id="text3523" 84.330 - y="485.51224" 84.331 - x="197.13031" 84.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" 84.333 - xml:space="preserve"><tspan 84.334 - style="font-family:Courier" 84.335 - y="485.51224" 84.336 - x="197.13031" 84.337 - id="tspan3525" 84.338 - sodipodi:role="line">000000000000</tspan></text> 84.339 - </g> 84.340 - <g 84.341 - id="g3527"> 84.342 - <rect 84.343 - y="447.71451" 84.344 - x="299.67859" 84.345 - height="48.571426" 84.346 - width="103.14286" 84.347 - id="rect3529" 84.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" /> 84.349 - <text 84.350 - id="text3531" 84.351 - y="464.8139" 84.352 - x="308.89639" 84.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" 84.354 - xml:space="preserve"><tspan 84.355 - y="464.8139" 84.356 - x="308.89639" 84.357 - sodipodi:role="line" 84.358 - id="tspan3533">Second parent</tspan></text> 84.359 - <text 84.360 - id="text3535" 84.361 - y="485.50256" 84.362 - x="308.20175" 84.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" 84.364 - xml:space="preserve"><tspan 84.365 - style="font-family:Courier" 84.366 - y="485.50256" 84.367 - x="308.20175" 84.368 - id="tspan3537" 84.369 - sodipodi:role="line">000000000000</tspan></text> 84.370 - </g> 84.371 - </g> 84.372 - <g 84.373 - transform="matrix(0.423343,0,0,0.423343,143.908,371.2915)" 84.374 - id="g3539"> 84.375 - <rect 84.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" 84.377 - id="rect3541" 84.378 - width="103.14286" 84.379 - height="48.571426" 84.380 - x="188.6071" 84.381 - y="311.28598" /> 84.382 - <text 84.383 - xml:space="preserve" 84.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" 84.385 - x="197.82495" 84.386 - y="328.38538" 84.387 - id="text3543"><tspan 84.388 - id="tspan3545" 84.389 - sodipodi:role="line" 84.390 - x="197.82495" 84.391 - y="328.38538">Revision hash</tspan></text> 84.392 - <text 84.393 - xml:space="preserve" 84.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" 84.395 - x="197.13031" 84.396 - y="349.07404" 84.397 - id="text3547"><tspan 84.398 - sodipodi:role="line" 84.399 - id="tspan3549" 84.400 - x="197.13031" 84.401 - y="349.07404" 84.402 - style="font-family:Courier">ff9dc8bc2a8b</tspan></text> 84.403 - </g> 84.404 - <g 84.405 - transform="matrix(0.423343,0,0,0.423343,144.3767,372.6502)" 84.406 - id="g3551"> 84.407 - <rect 84.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" 84.409 - id="rect3553" 84.410 - width="213.85715" 84.411 - height="75" 84.412 - x="187.5" 84.413 - y="363.07654" /> 84.414 - <text 84.415 - xml:space="preserve" 84.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" 84.417 - x="196.02321" 84.418 - y="400.86459" 84.419 - id="text3555"><tspan 84.420 - sodipodi:role="line" 84.421 - id="tspan3557" 84.422 - x="196.02321" 84.423 - y="400.86459" 84.424 - style="fill:black;fill-opacity:1;font-family:Courier">...</tspan></text> 84.425 - <text 84.426 - xml:space="preserve" 84.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" 84.428 - x="196.71785" 84.429 - y="380.17593" 84.430 - id="text3559"><tspan 84.431 - style="fill:black;fill-opacity:1" 84.432 - id="tspan3561" 84.433 - sodipodi:role="line" 84.434 - x="196.71785" 84.435 - y="380.17593">Revision data (delta or snapshot)</tspan></text> 84.436 - </g> 84.437 - </g> 84.438 - <g 84.439 - id="g4868" 84.440 - transform="translate(-1.676208,-2.342463e-5)"> 84.441 - <rect 84.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" 84.443 - id="rect3567" 84.444 - width="101.60232" 84.445 - height="89.506805" 84.446 - x="213.26137" 84.447 - y="59.171272" /> 84.448 - <g 84.449 - transform="matrix(0.423343,0,0,0.423343,138.8739,-67.01734)" 84.450 - id="g3573"> 84.451 - <rect 84.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" 84.453 - id="rect3575" 84.454 - width="103.14286" 84.455 - height="48.571426" 84.456 - x="188.6071" 84.457 - y="447.72418" /> 84.458 - <text 84.459 - xml:space="preserve" 84.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" 84.461 - x="197.82495" 84.462 - y="464.82358" 84.463 - id="text3577"><tspan 84.464 - id="tspan3579" 84.465 - sodipodi:role="line" 84.466 - x="197.82495" 84.467 - y="464.82358">First parent</tspan></text> 84.468 - <text 84.469 - xml:space="preserve" 84.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" 84.471 - x="197.13031" 84.472 - y="485.51224" 84.473 - id="text3581"><tspan 84.474 - sodipodi:role="line" 84.475 - id="tspan3583" 84.476 - x="197.13031" 84.477 - y="485.51224" 84.478 - style="font-family:Courier">34b8b7a15ea1</tspan></text> 84.479 - </g> 84.480 - <g 84.481 - transform="matrix(0.423343,0,0,0.423343,138.8739,-67.01734)" 84.482 - id="g3585"> 84.483 - <rect 84.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" 84.485 - id="rect3587" 84.486 - width="103.14286" 84.487 - height="48.571426" 84.488 - x="299.67859" 84.489 - y="447.71451" /> 84.490 - <text 84.491 - xml:space="preserve" 84.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" 84.493 - x="308.89639" 84.494 - y="464.8139" 84.495 - id="text3589"><tspan 84.496 - id="tspan3591" 84.497 - sodipodi:role="line" 84.498 - x="308.89639" 84.499 - y="464.8139">Second parent</tspan></text> 84.500 - <text 84.501 - xml:space="preserve" 84.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" 84.503 - x="308.20175" 84.504 - y="485.50256" 84.505 - id="text3593"><tspan 84.506 - sodipodi:role="line" 84.507 - id="tspan3595" 84.508 - x="308.20175" 84.509 - y="485.50256" 84.510 - style="font-family:Courier">000000000000</tspan></text> 84.511 - </g> 84.512 - <g 84.513 - transform="matrix(0.423343,0,0,0.423343,138.8739,-67.01733)" 84.514 - id="g3597"> 84.515 - <rect 84.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" 84.517 - id="rect3599" 84.518 - width="103.14286" 84.519 - height="48.571426" 84.520 - x="188.6071" 84.521 - y="311.28598" /> 84.522 - <text 84.523 - xml:space="preserve" 84.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" 84.525 - x="197.82495" 84.526 - y="328.38538" 84.527 - id="text3601"><tspan 84.528 - id="tspan3603" 84.529 - sodipodi:role="line" 84.530 - x="197.82495" 84.531 - y="328.38538">Revision hash</tspan></text> 84.532 - <text 84.533 - xml:space="preserve" 84.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" 84.535 - x="197.13031" 84.536 - y="349.07404" 84.537 - id="text3605"><tspan 84.538 - sodipodi:role="line" 84.539 - id="tspan3607" 84.540 - x="197.13031" 84.541 - y="349.07404" 84.542 - style="font-family:Courier">1b67dc96f27a</tspan></text> 84.543 - </g> 84.544 - <g 84.545 - transform="matrix(0.423343,0,0,0.423343,139.3426,-65.65866)" 84.546 - id="g3609"> 84.547 - <rect 84.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" 84.549 - id="rect3611" 84.550 - width="213.85715" 84.551 - height="75" 84.552 - x="187.5" 84.553 - y="363.07654" /> 84.554 - <text 84.555 - xml:space="preserve" 84.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" 84.557 - x="196.02321" 84.558 - y="400.86459" 84.559 - id="text3613"><tspan 84.560 - sodipodi:role="line" 84.561 - id="tspan3615" 84.562 - x="196.02321" 84.563 - y="400.86459" 84.564 - style="fill:black;fill-opacity:1;font-family:Courier">...</tspan></text> 84.565 - <text 84.566 - xml:space="preserve" 84.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" 84.568 - x="196.71785" 84.569 - y="380.17593" 84.570 - id="text3617"><tspan 84.571 - style="fill:black;fill-opacity:1" 84.572 - id="tspan3619" 84.573 - sodipodi:role="line" 84.574 - x="196.71785" 84.575 - y="380.17593">Revision data (delta or snapshot)</tspan></text> 84.576 - </g> 84.577 - </g> 84.578 - <path 84.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)" 84.580 - d="M 240.78255,143.08593 L 241.42595,171.75349" 84.581 - id="path3801" 84.582 - inkscape:connector-type="polyline" 84.583 - inkscape:connection-start="#g3573" 84.584 - inkscape:connection-end="#g3250" /> 84.585 - <g 84.586 - id="g5677"> 84.587 - <rect 84.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" 84.589 - id="rect3393" 84.590 - width="101.60232" 84.591 - height="89.506805" 84.592 - x="150.76137" 84.593 - y="278.32565" /> 84.594 - <g 84.595 - transform="matrix(0.423343,0,0,0.423343,76.37397,152.137)" 84.596 - id="g3399"> 84.597 - <rect 84.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" 84.599 - id="rect3401" 84.600 - width="103.14286" 84.601 - height="48.571426" 84.602 - x="188.6071" 84.603 - y="447.72418" /> 84.604 - <text 84.605 - xml:space="preserve" 84.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" 84.607 - x="197.82495" 84.608 - y="464.82358" 84.609 - id="text3403"><tspan 84.610 - id="tspan3405" 84.611 - sodipodi:role="line" 84.612 - x="197.82495" 84.613 - y="464.82358">First parent</tspan></text> 84.614 - <text 84.615 - xml:space="preserve" 84.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" 84.617 - x="197.13031" 84.618 - y="485.51224" 84.619 - id="text3407"><tspan 84.620 - sodipodi:role="line" 84.621 - id="tspan3409" 84.622 - x="197.13031" 84.623 - y="485.51224" 84.624 - style="font-family:Courier">ff9dc8bc2a8b</tspan></text> 84.625 - </g> 84.626 - <g 84.627 - transform="matrix(0.423343,0,0,0.423343,76.37397,152.137)" 84.628 - id="g3411"> 84.629 - <rect 84.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" 84.631 - id="rect3413" 84.632 - width="103.14286" 84.633 - height="48.571426" 84.634 - x="299.67859" 84.635 - y="447.71451" /> 84.636 - <text 84.637 - xml:space="preserve" 84.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" 84.639 - x="308.89639" 84.640 - y="464.8139" 84.641 - id="text3415"><tspan 84.642 - id="tspan3417" 84.643 - sodipodi:role="line" 84.644 - x="308.89639" 84.645 - y="464.8139">Second parent</tspan></text> 84.646 - <text 84.647 - xml:space="preserve" 84.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" 84.649 - x="308.20175" 84.650 - y="485.50256" 84.651 - id="text3419"><tspan 84.652 - sodipodi:role="line" 84.653 - id="tspan3421" 84.654 - x="308.20175" 84.655 - y="485.50256" 84.656 - style="font-family:Courier">000000000000</tspan></text> 84.657 - </g> 84.658 - <g 84.659 - transform="matrix(0.423343,0,0,0.423343,76.37397,152.137)" 84.660 - id="g3423"> 84.661 - <rect 84.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" 84.663 - id="rect3425" 84.664 - width="103.14286" 84.665 - height="48.571426" 84.666 - x="188.6071" 84.667 - y="311.28598" /> 84.668 - <text 84.669 - xml:space="preserve" 84.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" 84.671 - x="197.82495" 84.672 - y="328.38538" 84.673 - id="text3427"><tspan 84.674 - id="tspan3429" 84.675 - sodipodi:role="line" 84.676 - x="197.82495" 84.677 - y="328.38538">Revision hash</tspan></text> 84.678 - <text 84.679 - xml:space="preserve" 84.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" 84.681 - x="197.13031" 84.682 - y="349.07404" 84.683 - id="text3431"><tspan 84.684 - sodipodi:role="line" 84.685 - id="tspan3433" 84.686 - x="197.13031" 84.687 - y="349.07404" 84.688 - style="font-family:Courier">5b80c922ebdd</tspan></text> 84.689 - </g> 84.690 - <g 84.691 - transform="matrix(0.423343,0,0,0.423343,76.84265,153.4957)" 84.692 - id="g3435"> 84.693 - <rect 84.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" 84.695 - id="rect3437" 84.696 - width="213.85715" 84.697 - height="75" 84.698 - x="187.5" 84.699 - y="363.07654" /> 84.700 - <text 84.701 - xml:space="preserve" 84.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" 84.703 - x="196.02321" 84.704 - y="400.86459" 84.705 - id="text3439"><tspan 84.706 - sodipodi:role="line" 84.707 - id="tspan3441" 84.708 - x="196.02321" 84.709 - y="400.86459" 84.710 - style="fill:black;fill-opacity:1;font-family:Courier">...</tspan></text> 84.711 - <text 84.712 - xml:space="preserve" 84.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" 84.714 - x="196.71785" 84.715 - y="380.17593" 84.716 - id="text3443"><tspan 84.717 - style="fill:black;fill-opacity:1" 84.718 - id="tspan3445" 84.719 - sodipodi:role="line" 84.720 - x="196.71785" 84.721 - y="380.17593">Revision data (delta or snapshot)</tspan></text> 84.722 - </g> 84.723 - </g> 84.724 - <g 84.725 - id="g5646" 84.726 - transform="translate(-0.227432,0)"> 84.727 - <rect 84.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" 84.729 - id="rect3451" 84.730 - width="101.60232" 84.731 - height="89.506805" 84.732 - x="272.63638" 84.733 - y="278.32565" /> 84.734 - <g 84.735 - transform="matrix(0.423343,0,0,0.423343,198.2489,152.137)" 84.736 - id="g3457"> 84.737 - <rect 84.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" 84.739 - id="rect3459" 84.740 - width="103.14286" 84.741 - height="48.571426" 84.742 - x="188.6071" 84.743 - y="447.72418" /> 84.744 - <text 84.745 - xml:space="preserve" 84.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" 84.747 - x="197.82495" 84.748 - y="464.82358" 84.749 - id="text3461"><tspan 84.750 - id="tspan3463" 84.751 - sodipodi:role="line" 84.752 - x="197.82495" 84.753 - y="464.82358">First parent</tspan></text> 84.754 - <text 84.755 - xml:space="preserve" 84.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" 84.757 - x="197.13031" 84.758 - y="485.51224" 84.759 - id="text3465"><tspan 84.760 - sodipodi:role="line" 84.761 - id="tspan3467" 84.762 - x="197.13031" 84.763 - y="485.51224" 84.764 - style="font-family:Courier">ecacb6b4c9fd</tspan></text> 84.765 - </g> 84.766 - <g 84.767 - transform="matrix(0.423343,0,0,0.423343,198.2489,152.137)" 84.768 - id="g3469"> 84.769 - <rect 84.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" 84.771 - id="rect3471" 84.772 - width="103.14286" 84.773 - height="48.571426" 84.774 - x="299.67859" 84.775 - y="447.71451" /> 84.776 - <text 84.777 - xml:space="preserve" 84.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" 84.779 - x="308.89639" 84.780 - y="464.8139" 84.781 - id="text3473"><tspan 84.782 - id="tspan3475" 84.783 - sodipodi:role="line" 84.784 - x="308.89639" 84.785 - y="464.8139">Second parent</tspan></text> 84.786 - <text 84.787 - xml:space="preserve" 84.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" 84.789 - x="308.20175" 84.790 - y="485.50256" 84.791 - id="text3477"><tspan 84.792 - sodipodi:role="line" 84.793 - id="tspan3479" 84.794 - x="308.20175" 84.795 - y="485.50256" 84.796 - style="font-family:Courier">000000000000</tspan></text> 84.797 - </g> 84.798 - <g 84.799 - transform="matrix(0.423343,0,0,0.423343,198.2489,152.137)" 84.800 - id="g3481"> 84.801 - <rect 84.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" 84.803 - id="rect3483" 84.804 - width="103.14286" 84.805 - height="48.571426" 84.806 - x="188.6071" 84.807 - y="311.28598" /> 84.808 - <text 84.809 - xml:space="preserve" 84.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" 84.811 - x="197.82495" 84.812 - y="328.38538" 84.813 - id="text3485"><tspan 84.814 - id="tspan3487" 84.815 - sodipodi:role="line" 84.816 - x="197.82495" 84.817 - y="328.38538">Revision hash</tspan></text> 84.818 - <text 84.819 - xml:space="preserve" 84.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" 84.821 - x="197.13031" 84.822 - y="349.07404" 84.823 - id="text3489"><tspan 84.824 - sodipodi:role="line" 84.825 - id="tspan3491" 84.826 - x="197.13031" 84.827 - y="349.07404" 84.828 - style="font-family:Courier">32bf9a5f22c0</tspan></text> 84.829 - </g> 84.830 - <g 84.831 - transform="matrix(0.423343,0,0,0.423343,198.7176,153.4957)" 84.832 - id="g3493"> 84.833 - <rect 84.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" 84.835 - id="rect3495" 84.836 - width="213.85715" 84.837 - height="75" 84.838 - x="187.5" 84.839 - y="363.07654" /> 84.840 - <text 84.841 - xml:space="preserve" 84.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" 84.843 - x="196.02321" 84.844 - y="400.86459" 84.845 - id="text3497"><tspan 84.846 - sodipodi:role="line" 84.847 - id="tspan3499" 84.848 - x="196.02321" 84.849 - y="400.86459" 84.850 - style="fill:black;fill-opacity:1;font-family:Courier">...</tspan></text> 84.851 - <text 84.852 - xml:space="preserve" 84.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" 84.854 - x="196.71785" 84.855 - y="380.17593" 84.856 - id="text3501"><tspan 84.857 - style="fill:black;fill-opacity:1" 84.858 - id="tspan3503" 84.859 - sodipodi:role="line" 84.860 - x="196.71785" 84.861 - y="380.17593">Revision data (delta or snapshot)</tspan></text> 84.862 - </g> 84.863 - </g> 84.864 - <rect 84.865 - y="387.90286" 84.866 - x="272.40894" 84.867 - height="89.506805" 84.868 - width="101.60232" 84.869 - id="rect5081" 84.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" /> 84.871 - <g 84.872 - id="g5087" 84.873 - transform="matrix(0.423343,0,0,0.423343,198.0214,261.7142)"> 84.874 - <rect 84.875 - y="447.72418" 84.876 - x="188.6071" 84.877 - height="48.571426" 84.878 - width="103.14286" 84.879 - id="rect5089" 84.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" /> 84.881 - <text 84.882 - id="text5091" 84.883 - y="464.82358" 84.884 - x="197.82495" 84.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" 84.886 - xml:space="preserve"><tspan 84.887 - y="464.82358" 84.888 - x="197.82495" 84.889 - sodipodi:role="line" 84.890 - id="tspan5093">First parent</tspan></text> 84.891 - <text 84.892 - id="text5095" 84.893 - y="485.51224" 84.894 - x="197.13031" 84.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" 84.896 - xml:space="preserve"><tspan 84.897 - style="font-family:Courier" 84.898 - y="485.51224" 84.899 - x="197.13031" 84.900 - id="tspan5097" 84.901 - sodipodi:role="line">ff9dc8bc2a8b</tspan></text> 84.902 - </g> 84.903 - <g 84.904 - id="g5099" 84.905 - transform="matrix(0.423343,0,0,0.423343,198.0214,261.7142)"> 84.906 - <rect 84.907 - y="447.71451" 84.908 - x="299.67859" 84.909 - height="48.571426" 84.910 - width="103.14286" 84.911 - id="rect5101" 84.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" /> 84.913 - <text 84.914 - id="text5103" 84.915 - y="464.8139" 84.916 - x="308.89639" 84.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" 84.918 - xml:space="preserve"><tspan 84.919 - y="464.8139" 84.920 - x="308.89639" 84.921 - sodipodi:role="line" 84.922 - id="tspan5105">Second parent</tspan></text> 84.923 - <text 84.924 - id="text5107" 84.925 - y="485.50256" 84.926 - x="308.20175" 84.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" 84.928 - xml:space="preserve"><tspan 84.929 - style="font-family:Courier" 84.930 - y="485.50256" 84.931 - x="308.20175" 84.932 - id="tspan5109" 84.933 - sodipodi:role="line">000000000000</tspan></text> 84.934 - </g> 84.935 - <g 84.936 - id="g5111" 84.937 - transform="matrix(0.423343,0,0,0.423343,198.0214,261.7142)"> 84.938 - <rect 84.939 - y="311.28598" 84.940 - x="188.6071" 84.941 - height="48.571426" 84.942 - width="103.14286" 84.943 - id="rect5113" 84.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" /> 84.945 - <text 84.946 - id="text5115" 84.947 - y="328.38538" 84.948 - x="197.82495" 84.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" 84.950 - xml:space="preserve"><tspan 84.951 - y="328.38538" 84.952 - x="197.82495" 84.953 - sodipodi:role="line" 84.954 - id="tspan5117">Revision hash</tspan></text> 84.955 - <text 84.956 - id="text5119" 84.957 - y="349.07404" 84.958 - x="197.13031" 84.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" 84.960 - xml:space="preserve"><tspan 84.961 - style="font-family:Courier" 84.962 - y="349.07404" 84.963 - x="197.13031" 84.964 - id="tspan5121" 84.965 - sodipodi:role="line">ecacb6b4c9fd</tspan></text> 84.966 - </g> 84.967 - <g 84.968 - id="g5123" 84.969 - transform="matrix(0.423343,0,0,0.423343,198.4901,263.0729)"> 84.970 - <rect 84.971 - y="363.07654" 84.972 - x="187.5" 84.973 - height="75" 84.974 - width="213.85715" 84.975 - id="rect5125" 84.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" /> 84.977 - <text 84.978 - id="text5127" 84.979 - y="400.86459" 84.980 - x="196.02321" 84.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" 84.982 - xml:space="preserve"><tspan 84.983 - style="fill:black;fill-opacity:1;font-family:Courier" 84.984 - y="400.86459" 84.985 - x="196.02321" 84.986 - id="tspan5129" 84.987 - sodipodi:role="line">...</tspan></text> 84.988 - <text 84.989 - id="text5131" 84.990 - y="380.17593" 84.991 - x="196.71785" 84.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" 84.993 - xml:space="preserve"><tspan 84.994 - y="380.17593" 84.995 - x="196.71785" 84.996 - sodipodi:role="line" 84.997 - id="tspan5133" 84.998 - style="fill:black;fill-opacity:1">Revision data (delta or snapshot)</tspan></text> 84.999 - </g> 84.1000 - <path 84.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" 84.1002 - d="M 299.69935,362.24027 L 299.69931,393.49494" 84.1003 - id="path5203" 84.1004 - inkscape:connector-type="polyline" 84.1005 - inkscape:connection-start="#g3457" 84.1006 - inkscape:connection-end="#g5111" /> 84.1007 - <path 84.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" 84.1009 - d="M 182.35357,362.22647 L 241.2842,503.07224" 84.1010 - id="path5271" 84.1011 - inkscape:connector-type="polyline" 84.1012 - inkscape:connection-start="#g3399" 84.1013 - inkscape:connection-end="#g3539" /> 84.1014 - <path 84.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" 84.1016 - d="M 287.63109,471.81747 L 250.9438,503.07223" 84.1017 - id="path5285" 84.1018 - inkscape:connector-type="polyline" 84.1019 - inkscape:connection-start="#g5087" 84.1020 - inkscape:connection-end="#g3539" /> 84.1021 - <path 84.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)" 84.1023 - d="M 290.80419,250.07192 L 297.80065,283.90394" 84.1024 - id="path5077" 84.1025 - inkscape:connector-type="polyline" 84.1026 - inkscape:connection-start="#g3215" 84.1027 - inkscape:connection-end="#g3481" /> 84.1028 - <path 84.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)" 84.1030 - d="M 229.63373,250.07601 L 190.07484,283.90394" 84.1031 - id="path5075" 84.1032 - inkscape:connector-type="polyline" 84.1033 - inkscape:connection-end="#g3423" /> 84.1034 - <text 84.1035 - xml:space="preserve" 84.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" 84.1037 - x="131.5625" 84.1038 - y="100.79968" 84.1039 - id="text5897"><tspan 84.1040 - sodipodi:role="line" 84.1041 - id="tspan5899" 84.1042 - x="131.5625" 84.1043 - y="100.79968" 84.1044 - style="text-align:end;text-anchor:end">Head revision</tspan><tspan 84.1045 - sodipodi:role="line" 84.1046 - x="131.5625" 84.1047 - y="115.79968" 84.1048 - id="tspan5901" 84.1049 - style="text-align:end;text-anchor:end">(no children)</tspan></text> 84.1050 - <text 84.1051 - xml:space="preserve" 84.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" 84.1053 - x="131.5625" 84.1054 - y="207.04968" 84.1055 - id="text5903"><tspan 84.1056 - sodipodi:role="line" 84.1057 - id="tspan5905" 84.1058 - x="131.5625" 84.1059 - y="207.04968" 84.1060 - style="text-align:end;text-anchor:end">Merge revision</tspan><tspan 84.1061 - sodipodi:role="line" 84.1062 - x="131.5625" 84.1063 - y="222.04968" 84.1064 - id="tspan5907" 84.1065 - style="text-align:end;text-anchor:end">(two parents)</tspan></text> 84.1066 - <text 84.1067 - xml:space="preserve" 84.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" 84.1069 - x="131.92578" 84.1070 - y="451.58093" 84.1071 - id="text5909"><tspan 84.1072 - sodipodi:role="line" 84.1073 - id="tspan5911" 84.1074 - x="131.92578" 84.1075 - y="451.58093" 84.1076 - style="text-align:end;text-anchor:end">Branches</tspan><tspan 84.1077 - sodipodi:role="line" 84.1078 - x="131.92578" 84.1079 - y="466.58093" 84.1080 - id="tspan5913" 84.1081 - style="text-align:end;text-anchor:end">(two revisions,</tspan><tspan 84.1082 - sodipodi:role="line" 84.1083 - x="131.92578" 84.1084 - y="481.58093" 84.1085 - id="tspan5915" 84.1086 - style="text-align:end;text-anchor:end">same parent)</tspan></text> 84.1087 - <path 84.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" 84.1089 - d="M 111.71875,433.61218 L 154.7268,368.52294" 84.1090 - id="path5917" 84.1091 - inkscape:connector-type="polyline" /> 84.1092 - <path 84.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" 84.1094 - d="M 134.375,464.86218 L 277.86691,440.37816" 84.1095 - id="path5919" 84.1096 - inkscape:connector-type="polyline" 84.1097 - inkscape:connection-end="#g5123" /> 84.1098 - <text 84.1099 - xml:space="preserve" 84.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" 84.1101 - x="131.5625" 84.1102 - y="536.73718" 84.1103 - id="text5927"><tspan 84.1104 - sodipodi:role="line" 84.1105 - id="tspan5929" 84.1106 - x="131.5625" 84.1107 - y="536.73718">First revision</tspan><tspan 84.1108 - sodipodi:role="line" 84.1109 - x="131.5625" 84.1110 - y="551.73718" 84.1111 - id="tspan5931">(both parents null)</tspan></text> 84.1112 - <rect 84.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" 84.1114 - id="rect2830" 84.1115 - width="43.664806" 84.1116 - height="20.562374" 84.1117 - x="217.0432" 84.1118 - y="232.10075" /> 84.1119 - <text 84.1120 - xml:space="preserve" 84.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" 84.1122 - x="220.94551" 84.1123 - y="239.33966" 84.1124 - id="text2832"><tspan 84.1125 - id="tspan2836" 84.1126 - sodipodi:role="line" 84.1127 - x="220.94551" 84.1128 - y="239.33966">First parent</tspan></text> 84.1129 - <text 84.1130 - xml:space="preserve" 84.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" 84.1132 - x="220.65144" 84.1133 - y="248.09805" 84.1134 - id="text2879"><tspan 84.1135 - sodipodi:role="line" 84.1136 - id="tspan2881" 84.1137 - x="220.65144" 84.1138 - y="248.09805" 84.1139 - style="font-family:Courier">5b80c922ebdd</tspan></text> 84.1140 - <path 84.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" 84.1142 - d="M 139.84375,107.83093 L 210.15625,107.83093" 84.1143 - id="path5965" 84.1144 - inkscape:connector-type="polyline" /> 84.1145 - <path 84.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" 84.1147 - d="M 137.5,213.29968 L 210.49036,214.09055" 84.1148 - id="path5967" 84.1149 - inkscape:connector-type="polyline" /> 84.1150 - <path 84.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" 84.1152 - d="M 136.34375,544.54968 L 206.65625,544.54968" 84.1153 - id="path5969" 84.1154 - inkscape:connector-type="polyline" 84.1155 - inkscape:transform-center-y="-171.09375" 84.1156 - inkscape:transform-center-x="53.90625" /> 84.1157 - </g> 84.1158 -</svg>
85.1 --- a/fr/snapshot.svg Sun Aug 16 03:41:39 2009 +0200 85.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 85.3 @@ -1,202 +0,0 @@ 85.4 -<?xml version="1.0" encoding="UTF-8" standalone="no"?> 85.5 -<!-- Created with Inkscape (http://www.inkscape.org/) --> 85.6 -<svg 85.7 - xmlns:dc="http://purl.org/dc/elements/1.1/" 85.8 - xmlns:cc="http://web.resource.org/cc/" 85.9 - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 85.10 - xmlns:svg="http://www.w3.org/2000/svg" 85.11 - xmlns="http://www.w3.org/2000/svg" 85.12 - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" 85.13 - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" 85.14 - width="744.09448819" 85.15 - height="1052.3622047" 85.16 - id="svg2807" 85.17 - sodipodi:version="0.32" 85.18 - inkscape:version="0.44.1" 85.19 - sodipodi:docbase="/home/bos/hg/hgbook/en" 85.20 - sodipodi:docname="snapshots.svg"> 85.21 - <defs 85.22 - id="defs2809" /> 85.23 - <sodipodi:namedview 85.24 - id="base" 85.25 - pagecolor="#ffffff" 85.26 - bordercolor="#666666" 85.27 - borderopacity="1.0" 85.28 - gridtolerance="10000" 85.29 - guidetolerance="10" 85.30 - objecttolerance="10" 85.31 - inkscape:pageopacity="0.0" 85.32 - inkscape:pageshadow="2" 85.33 - inkscape:zoom="1.4" 85.34 - inkscape:cx="252.04111" 85.35 - inkscape:cy="605.75448" 85.36 - inkscape:document-units="px" 85.37 - inkscape:current-layer="layer1" 85.38 - inkscape:window-width="906" 85.39 - inkscape:window-height="721" 85.40 - inkscape:window-x="0" 85.41 - inkscape:window-y="25" /> 85.42 - <metadata 85.43 - id="metadata2812"> 85.44 - <rdf:RDF> 85.45 - <cc:Work 85.46 - rdf:about=""> 85.47 - <dc:format>image/svg+xml</dc:format> 85.48 - <dc:type 85.49 - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 85.50 - </cc:Work> 85.51 - </rdf:RDF> 85.52 - </metadata> 85.53 - <g 85.54 - inkscape:label="Layer 1" 85.55 - inkscape:groupmode="layer" 85.56 - id="layer1"> 85.57 - <rect 85.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" 85.59 - id="rect2817" 85.60 - width="118.18347" 85.61 - height="245.32632" 85.62 - x="243.05112" 85.63 - y="315.4133" 85.64 - inkscape:transform-center-x="136.84403" 85.65 - inkscape:transform-center-y="-66.529183" /> 85.66 - <rect 85.67 - y="315.04153" 85.68 - x="46.965065" 85.69 - height="97.803009" 85.70 - width="108.92702" 85.71 - id="rect2815" 85.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" /> 85.73 - <g 85.74 - id="g3814"> 85.75 - <rect 85.76 - y="348.94302" 85.77 - x="59.285713" 85.78 - height="30" 85.79 - width="84.285713" 85.80 - id="rect2819" 85.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" 85.82 - ry="0" /> 85.83 - <text 85.84 - id="text2821" 85.85 - y="368.02701" 85.86 - x="72.717636" 85.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" 85.88 - xml:space="preserve"><tspan 85.89 - y="368.02701" 85.90 - x="72.717636" 85.91 - id="tspan2823" 85.92 - sodipodi:role="line">Index, rev 7</tspan></text> 85.93 - </g> 85.94 - <text 85.95 - id="text3722" 85.96 - y="301.29074" 85.97 - x="46.187778" 85.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" 85.99 - xml:space="preserve"><tspan 85.100 - y="301.29074" 85.101 - x="46.187778" 85.102 - id="tspan3724" 85.103 - sodipodi:role="line">Revlog index (.i file)</tspan></text> 85.104 - <text 85.105 - id="text3726" 85.106 - y="301.29074" 85.107 - x="241.90207" 85.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" 85.109 - xml:space="preserve"><tspan 85.110 - y="301.29074" 85.111 - x="241.90207" 85.112 - id="tspan3728" 85.113 - sodipodi:role="line">Revlog data (.d file)</tspan></text> 85.114 - <path 85.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" 85.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 " 85.117 - id="path3839" 85.118 - sodipodi:nodetypes="ccccc" /> 85.119 - <rect 85.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" 85.121 - id="rect3752" 85.122 - width="92.720184" 85.123 - height="67.005905" 85.124 - x="255.42564" 85.125 - y="368.64264" /> 85.126 - <text 85.127 - xml:space="preserve" 85.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" 85.129 - x="264.45859" 85.130 - y="387.30099" 85.131 - id="text3754"><tspan 85.132 - sodipodi:role="line" 85.133 - id="tspan3756" 85.134 - x="264.45859" 85.135 - y="387.30099">Snapshot, rev 4</tspan></text> 85.136 - <rect 85.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" 85.138 - id="rect3761" 85.139 - width="93.49366" 85.140 - height="29.922237" 85.141 - x="255.03891" 85.142 - y="442.04395" /> 85.143 - <text 85.144 - xml:space="preserve" 85.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" 85.146 - x="263.2662" 85.147 - y="460.17206" 85.148 - id="text3763"><tspan 85.149 - sodipodi:role="line" 85.150 - id="tspan3765" 85.151 - x="263.2662" 85.152 - y="460.17206">Delta, rev 4 to 5</tspan></text> 85.153 - <rect 85.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" 85.155 - id="rect3774" 85.156 - width="93.49366" 85.157 - height="29.922237" 85.158 - x="255.03891" 85.159 - y="477.97485" /> 85.160 - <text 85.161 - xml:space="preserve" 85.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" 85.163 - x="263.2662" 85.164 - y="496.10297" 85.165 - id="text3776"><tspan 85.166 - sodipodi:role="line" 85.167 - id="tspan3778" 85.168 - x="263.2662" 85.169 - y="496.10297">Delta, rev 5 to 6</tspan></text> 85.170 - <rect 85.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" 85.172 - id="rect3782" 85.173 - width="93.49366" 85.174 - height="29.922237" 85.175 - x="255.03891" 85.176 - y="513.90576" /> 85.177 - <text 85.178 - xml:space="preserve" 85.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" 85.180 - x="263.2662" 85.181 - y="532.03387" 85.182 - id="text3784"><tspan 85.183 - sodipodi:role="line" 85.184 - id="tspan3786" 85.185 - x="263.2662" 85.186 - y="532.03387">Delta, rev 6 to 7</tspan></text> 85.187 - <rect 85.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" 85.189 - id="rect3889" 85.190 - width="93.49366" 85.191 - height="29.922237" 85.192 - x="255.03891" 85.193 - y="332.32489" /> 85.194 - <text 85.195 - xml:space="preserve" 85.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" 85.197 - x="263.2662" 85.198 - y="350.453" 85.199 - id="text3891"><tspan 85.200 - sodipodi:role="line" 85.201 - id="tspan3893" 85.202 - x="263.2662" 85.203 - y="350.453">Delta, rev 2 to 3</tspan></text> 85.204 - </g> 85.205 -</svg>
86.1 --- a/fr/srcinstall.tex Sun Aug 16 03:41:39 2009 +0200 86.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 86.3 @@ -1,53 +0,0 @@ 86.4 -\chapter{Installing Mercurial from source} 86.5 -\label{chap:srcinstall} 86.6 - 86.7 -\section{On a Unix-like system} 86.8 -\label{sec:srcinstall:unixlike} 86.9 - 86.10 -If you are using a Unix-like system that has a sufficiently recent 86.11 -version of Python (2.3~or newer) available, it is easy to install 86.12 -Mercurial from source. 86.13 -\begin{enumerate} 86.14 -\item Download a recent source tarball from 86.15 - \url{http://www.selenic.com/mercurial/download}. 86.16 -\item Unpack the tarball: 86.17 - \begin{codesample4} 86.18 - gzip -dc mercurial-\emph{version}.tar.gz | tar xf - 86.19 - \end{codesample4} 86.20 -\item Go into the source directory and run the installer script. This 86.21 - will build Mercurial and install it in your home directory. 86.22 - \begin{codesample4} 86.23 - cd mercurial-\emph{version} 86.24 - python setup.py install --force --home=\$HOME 86.25 - \end{codesample4} 86.26 -\end{enumerate} 86.27 -Once the install finishes, Mercurial will be in the \texttt{bin} 86.28 -subdirectory of your home directory. Don't forget to make sure that 86.29 -this directory is present in your shell's search path. 86.30 - 86.31 -You will probably need to set the \envar{PYTHONPATH} environment 86.32 -variable so that the Mercurial executable can find the rest of the 86.33 -Mercurial packages. For example, on my laptop, I have set it to 86.34 -\texttt{/home/bos/lib/python}. The exact path that you will need to 86.35 -use depends on how Python was built for your system, but should be 86.36 -easy to figure out. If you're uncertain, look through the output of 86.37 -the installer script above, and see where the contents of the 86.38 -\texttt{mercurial} directory were installed to. 86.39 - 86.40 -\section{On Windows} 86.41 - 86.42 -Building and installing Mercurial on Windows requires a variety of 86.43 -tools, a fair amount of technical knowledge, and considerable 86.44 -patience. I very much \emph{do not recommend} this route if you are a 86.45 -``casual user''. Unless you intend to hack on Mercurial, I strongly 86.46 -suggest that you use a binary package instead. 86.47 - 86.48 -If you are intent on building Mercurial from source on Windows, follow 86.49 -the ``hard way'' directions on the Mercurial wiki at 86.50 -\url{http://www.selenic.com/mercurial/wiki/index.cgi/WindowsInstall}, 86.51 -and expect the process to involve a lot of fiddly work. 86.52 - 86.53 -%%% Local Variables: 86.54 -%%% mode: latex 86.55 -%%% TeX-master: "00book" 86.56 -%%% End:
87.1 --- a/fr/template.tex Sun Aug 16 03:41:39 2009 +0200 87.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 87.3 @@ -1,475 +0,0 @@ 87.4 -\chapter{Customising the output of Mercurial} 87.5 -\label{chap:template} 87.6 - 87.7 -Mercurial provides a powerful mechanism to let you control how it 87.8 -displays information. The mechanism is based on templates. You can 87.9 -use templates to generate specific output for a single command, or to 87.10 -customise the entire appearance of the built-in web interface. 87.11 - 87.12 -\section{Using precanned output styles} 87.13 -\label{sec:style} 87.14 - 87.15 -Packaged with Mercurial are some output styles that you can use 87.16 -immediately. A style is simply a precanned template that someone 87.17 -wrote and installed somewhere that Mercurial can find. 87.18 - 87.19 -Before we take a look at Mercurial's bundled styles, let's review its 87.20 -normal output. 87.21 - 87.22 -\interaction{template.simple.normal} 87.23 - 87.24 -This is somewhat informative, but it takes up a lot of space---five 87.25 -lines of output per changeset. The \texttt{compact} style reduces 87.26 -this to three lines, presented in a sparse manner. 87.27 - 87.28 -\interaction{template.simple.compact} 87.29 - 87.30 -The \texttt{changelog} style hints at the expressive power of 87.31 -Mercurial's templating engine. This style attempts to follow the GNU 87.32 -Project's changelog guidelines\cite{web:changelog}. 87.33 - 87.34 -\interaction{template.simple.changelog} 87.35 - 87.36 -You will not be shocked to learn that Mercurial's default output style 87.37 -is named \texttt{default}. 87.38 - 87.39 -\subsection{Setting a default style} 87.40 - 87.41 -You can modify the output style that Mercurial will use for every 87.42 -command by editing your \hgrc\ file, naming the style you would 87.43 -prefer to use. 87.44 - 87.45 -\begin{codesample2} 87.46 - [ui] 87.47 - style = compact 87.48 -\end{codesample2} 87.49 - 87.50 -If you write a style of your own, you can use it by either providing 87.51 -the path to your style file, or copying your style file into a 87.52 -location where Mercurial can find it (typically the \texttt{templates} 87.53 -subdirectory of your Mercurial install directory). 87.54 - 87.55 -\section{Commands that support styles and templates} 87.56 - 87.57 -All of Mercurial's ``\texttt{log}-like'' commands let you use styles 87.58 -and templates: \hgcmd{incoming}, \hgcmd{log}, \hgcmd{outgoing}, and 87.59 -\hgcmd{tip}. 87.60 - 87.61 -As I write this manual, these are so far the only commands that 87.62 -support styles and templates. Since these are the most important 87.63 -commands that need customisable output, there has been little pressure 87.64 -from the Mercurial user community to add style and template support to 87.65 -other commands. 87.66 - 87.67 -\section{The basics of templating} 87.68 - 87.69 -At its simplest, a Mercurial template is a piece of text. Some of the 87.70 -text never changes, while other parts are \emph{expanded}, or replaced 87.71 -with new text, when necessary. 87.72 - 87.73 -Before we continue, let's look again at a simple example of 87.74 -Mercurial's normal output. 87.75 - 87.76 -\interaction{template.simple.normal} 87.77 - 87.78 -Now, let's run the same command, but using a template to change its 87.79 -output. 87.80 - 87.81 -\interaction{template.simple.simplest} 87.82 - 87.83 -The example above illustrates the simplest possible template; it's 87.84 -just a piece of static text, printed once for each changeset. The 87.85 -\hgopt{log}{--template} option to the \hgcmd{log} command tells 87.86 -Mercurial to use the given text as the template when printing each 87.87 -changeset. 87.88 - 87.89 -Notice that the template string above ends with the text 87.90 -``\Verb+\n+''. This is an \emph{escape sequence}, telling Mercurial 87.91 -to print a newline at the end of each template item. If you omit this 87.92 -newline, Mercurial will run each piece of output together. See 87.93 -section~\ref{sec:template:escape} for more details of escape sequences. 87.94 - 87.95 -A template that prints a fixed string of text all the time isn't very 87.96 -useful; let's try something a bit more complex. 87.97 - 87.98 -\interaction{template.simple.simplesub} 87.99 - 87.100 -As you can see, the string ``\Verb+{desc}+'' in the template has been 87.101 -replaced in the output with the description of each changeset. Every 87.102 -time Mercurial finds text enclosed in curly braces (``\texttt{\{}'' 87.103 -and ``\texttt{\}}''), it will try to replace the braces and text with 87.104 -the expansion of whatever is inside. To print a literal curly brace, 87.105 -you must escape it, as described in section~\ref{sec:template:escape}. 87.106 - 87.107 -\section{Common template keywords} 87.108 -\label{sec:template:keyword} 87.109 - 87.110 -You can start writing simple templates immediately using the keywords 87.111 -below. 87.112 - 87.113 -\begin{itemize} 87.114 -\item[\tplkword{author}] String. The unmodified author of the changeset. 87.115 -\item[\tplkword{branches}] String. The name of the branch on which 87.116 - the changeset was committed. Will be empty if the branch name was 87.117 - \texttt{default}. 87.118 -\item[\tplkword{date}] Date information. The date when the changeset 87.119 - was committed. This is \emph{not} human-readable; you must pass it 87.120 - through a filter that will render it appropriately. See 87.121 - section~\ref{sec:template:filter} for more information on filters. 87.122 - The date is expressed as a pair of numbers. The first number is a 87.123 - Unix UTC timestamp (seconds since January 1, 1970); the second is 87.124 - the offset of the committer's timezone from UTC, in seconds. 87.125 -\item[\tplkword{desc}] String. The text of the changeset description. 87.126 -\item[\tplkword{files}] List of strings. All files modified, added, or 87.127 - removed by this changeset. 87.128 -\item[\tplkword{file\_adds}] List of strings. Files added by this 87.129 - changeset. 87.130 -\item[\tplkword{file\_dels}] List of strings. Files removed by this 87.131 - changeset. 87.132 -\item[\tplkword{node}] String. The changeset identification hash, as a 87.133 - 40-character hexadecimal string. 87.134 -\item[\tplkword{parents}] List of strings. The parents of the 87.135 - changeset. 87.136 -\item[\tplkword{rev}] Integer. The repository-local changeset revision 87.137 - number. 87.138 -\item[\tplkword{tags}] List of strings. Any tags associated with the 87.139 - changeset. 87.140 -\end{itemize} 87.141 - 87.142 -A few simple experiments will show us what to expect when we use these 87.143 -keywords; you can see the results in 87.144 -figure~\ref{fig:template:keywords}. 87.145 - 87.146 -\begin{figure} 87.147 - \interaction{template.simple.keywords} 87.148 - \caption{Template keywords in use} 87.149 - \label{fig:template:keywords} 87.150 -\end{figure} 87.151 - 87.152 -As we noted above, the date keyword does not produce human-readable 87.153 -output, so we must treat it specially. This involves using a 87.154 -\emph{filter}, about which more in section~\ref{sec:template:filter}. 87.155 - 87.156 -\interaction{template.simple.datekeyword} 87.157 - 87.158 -\section{Escape sequences} 87.159 -\label{sec:template:escape} 87.160 - 87.161 -Mercurial's templating engine recognises the most commonly used escape 87.162 -sequences in strings. When it sees a backslash (``\Verb+\+'') 87.163 -character, it looks at the following character and substitutes the two 87.164 -characters with a single replacement, as described below. 87.165 - 87.166 -\begin{itemize} 87.167 -\item[\Verb+\textbackslash\textbackslash+] Backslash, ``\Verb+\+'', 87.168 - ASCII~134. 87.169 -\item[\Verb+\textbackslash n+] Newline, ASCII~12. 87.170 -\item[\Verb+\textbackslash r+] Carriage return, ASCII~15. 87.171 -\item[\Verb+\textbackslash t+] Tab, ASCII~11. 87.172 -\item[\Verb+\textbackslash v+] Vertical tab, ASCII~13. 87.173 -\item[\Verb+\textbackslash \{+] Open curly brace, ``\Verb+{+'', ASCII~173. 87.174 -\item[\Verb+\textbackslash \}+] Close curly brace, ``\Verb+}+'', ASCII~175. 87.175 -\end{itemize} 87.176 - 87.177 -As indicated above, if you want the expansion of a template to contain 87.178 -a literal ``\Verb+\+'', ``\Verb+{+'', or ``\Verb+{+'' character, you 87.179 -must escape it. 87.180 - 87.181 -\section{Filtering keywords to change their results} 87.182 -\label{sec:template:filter} 87.183 - 87.184 -Some of the results of template expansion are not immediately easy to 87.185 -use. Mercurial lets you specify an optional chain of \emph{filters} 87.186 -to modify the result of expanding a keyword. You have already seen a 87.187 -common filter, \tplkwfilt{date}{isodate}, in action above, to make a 87.188 -date readable. 87.189 - 87.190 -Below is a list of the most commonly used filters that Mercurial 87.191 -supports. While some filters can be applied to any text, others can 87.192 -only be used in specific circumstances. The name of each filter is 87.193 -followed first by an indication of where it can be used, then a 87.194 -description of its effect. 87.195 - 87.196 -\begin{itemize} 87.197 -\item[\tplfilter{addbreaks}] Any text. Add an XHTML ``\Verb+<br/>+'' 87.198 - tag before the end of every line except the last. For example, 87.199 - ``\Verb+foo\nbar+'' becomes ``\Verb+foo<br/>\nbar+''. 87.200 -\item[\tplkwfilt{date}{age}] \tplkword{date} keyword. Render the 87.201 - age of the date, relative to the current time. Yields a string like 87.202 - ``\Verb+10 minutes+''. 87.203 -\item[\tplfilter{basename}] Any text, but most useful for the 87.204 - \tplkword{files} keyword and its relatives. Treat the text as a 87.205 - path, and return the basename. For example, ``\Verb+foo/bar/baz+'' 87.206 - becomes ``\Verb+baz+''. 87.207 -\item[\tplkwfilt{date}{date}] \tplkword{date} keyword. Render a date 87.208 - in a similar format to the Unix \tplkword{date} command, but with 87.209 - timezone included. Yields a string like 87.210 - ``\Verb+Mon Sep 04 15:13:13 2006 -0700+''. 87.211 -\item[\tplkwfilt{author}{domain}] Any text, but most useful for the 87.212 - \tplkword{author} keyword. Finds the first string that looks like 87.213 - an email address, and extract just the domain component. For 87.214 - example, ``\Verb+Bryan O'Sullivan <bos@serpentine.com>+'' becomes 87.215 - ``\Verb+serpentine.com+''. 87.216 -\item[\tplkwfilt{author}{email}] Any text, but most useful for the 87.217 - \tplkword{author} keyword. Extract the first string that looks like 87.218 - an email address. For example, 87.219 - ``\Verb+Bryan O'Sullivan <bos@serpentine.com>+'' becomes 87.220 - ``\Verb+bos@serpentine.com+''. 87.221 -\item[\tplfilter{escape}] Any text. Replace the special XML/XHTML 87.222 - characters ``\Verb+&+'', ``\Verb+<+'' and ``\Verb+>+'' with 87.223 - XML entities. 87.224 -\item[\tplfilter{fill68}] Any text. Wrap the text to fit in 68 87.225 - columns. This is useful before you pass text through the 87.226 - \tplfilter{tabindent} filter, and still want it to fit in an 87.227 - 80-column fixed-font window. 87.228 -\item[\tplfilter{fill76}] Any text. Wrap the text to fit in 76 87.229 - columns. 87.230 -\item[\tplfilter{firstline}] Any text. Yield the first line of text, 87.231 - without any trailing newlines. 87.232 -\item[\tplkwfilt{date}{hgdate}] \tplkword{date} keyword. Render the 87.233 - date as a pair of readable numbers. Yields a string like 87.234 - ``\Verb+1157407993 25200+''. 87.235 -\item[\tplkwfilt{date}{isodate}] \tplkword{date} keyword. Render the 87.236 - date as a text string in ISO~8601 format. Yields a string like 87.237 - ``\Verb+2006-09-04 15:13:13 -0700+''. 87.238 -\item[\tplfilter{obfuscate}] Any text, but most useful for the 87.239 - \tplkword{author} keyword. Yield the input text rendered as a 87.240 - sequence of XML entities. This helps to defeat some particularly 87.241 - stupid screen-scraping email harvesting spambots. 87.242 -\item[\tplkwfilt{author}{person}] Any text, but most useful for the 87.243 - \tplkword{author} keyword. Yield the text before an email address. 87.244 - For example, ``\Verb+Bryan O'Sullivan <bos@serpentine.com>+'' 87.245 - becomes ``\Verb+Bryan O'Sullivan+''. 87.246 -\item[\tplkwfilt{date}{rfc822date}] \tplkword{date} keyword. Render a 87.247 - date using the same format used in email headers. Yields a string 87.248 - like ``\Verb+Mon, 04 Sep 2006 15:13:13 -0700+''. 87.249 -\item[\tplkwfilt{node}{short}] Changeset hash. Yield the short form 87.250 - of a changeset hash, i.e.~a 12-character hexadecimal string. 87.251 -\item[\tplkwfilt{date}{shortdate}] \tplkword{date} keyword. Render 87.252 - the year, month, and day of the date. Yields a string like 87.253 - ``\Verb+2006-09-04+''. 87.254 -\item[\tplfilter{strip}] Any text. Strip all leading and trailing 87.255 - whitespace from the string. 87.256 -\item[\tplfilter{tabindent}] Any text. Yield the text, with every line 87.257 - except the first starting with a tab character. 87.258 -\item[\tplfilter{urlescape}] Any text. Escape all characters that are 87.259 - considered ``special'' by URL parsers. For example, \Verb+foo bar+ 87.260 - becomes \Verb+foo%20bar+. 87.261 -\item[\tplkwfilt{author}{user}] Any text, but most useful for the 87.262 - \tplkword{author} keyword. Return the ``user'' portion of an email 87.263 - address. For example, 87.264 - ``\Verb+Bryan O'Sullivan <bos@serpentine.com>+'' becomes 87.265 - ``\Verb+bos+''. 87.266 -\end{itemize} 87.267 - 87.268 -\begin{figure} 87.269 - \interaction{template.simple.manyfilters} 87.270 - \caption{Template filters in action} 87.271 - \label{fig:template:filters} 87.272 -\end{figure} 87.273 - 87.274 -\begin{note} 87.275 - If you try to apply a filter to a piece of data that it cannot 87.276 - process, Mercurial will fail and print a Python exception. For 87.277 - example, trying to run the output of the \tplkword{desc} keyword 87.278 - into the \tplkwfilt{date}{isodate} filter is not a good idea. 87.279 -\end{note} 87.280 - 87.281 -\subsection{Combining filters} 87.282 - 87.283 -It is easy to combine filters to yield output in the form you would 87.284 -like. The following chain of filters tidies up a description, then 87.285 -makes sure that it fits cleanly into 68 columns, then indents it by a 87.286 -further 8~characters (at least on Unix-like systems, where a tab is 87.287 -conventionally 8~characters wide). 87.288 - 87.289 -\interaction{template.simple.combine} 87.290 - 87.291 -Note the use of ``\Verb+\t+'' (a tab character) in the template to 87.292 -force the first line to be indented; this is necessary since 87.293 -\tplkword{tabindent} indents all lines \emph{except} the first. 87.294 - 87.295 -Keep in mind that the order of filters in a chain is significant. The 87.296 -first filter is applied to the result of the keyword; the second to 87.297 -the result of the first filter; and so on. For example, using 87.298 -\Verb+fill68|tabindent+ gives very different results from 87.299 -\Verb+tabindent|fill68+. 87.300 - 87.301 - 87.302 -\section{From templates to styles} 87.303 - 87.304 -A command line template provides a quick and simple way to format some 87.305 -output. Templates can become verbose, though, and it's useful to be 87.306 -able to give a template a name. A style file is a template with a 87.307 -name, stored in a file. 87.308 - 87.309 -More than that, using a style file unlocks the power of Mercurial's 87.310 -templating engine in ways that are not possible using the command line 87.311 -\hgopt{log}{--template} option. 87.312 - 87.313 -\subsection{The simplest of style files} 87.314 - 87.315 -Our simple style file contains just one line: 87.316 - 87.317 -\interaction{template.simple.rev} 87.318 - 87.319 -This tells Mercurial, ``if you're printing a changeset, use the text 87.320 -on the right as the template''. 87.321 - 87.322 -\subsection{Style file syntax} 87.323 - 87.324 -The syntax rules for a style file are simple. 87.325 - 87.326 -\begin{itemize} 87.327 -\item The file is processed one line at a time. 87.328 - 87.329 -\item Leading and trailing white space are ignored. 87.330 - 87.331 -\item Empty lines are skipped. 87.332 - 87.333 -\item If a line starts with either of the characters ``\texttt{\#}'' or 87.334 - ``\texttt{;}'', the entire line is treated as a comment, and skipped 87.335 - as if empty. 87.336 - 87.337 -\item A line starts with a keyword. This must start with an 87.338 - alphabetic character or underscore, and can subsequently contain any 87.339 - alphanumeric character or underscore. (In regexp notation, a 87.340 - keyword must match \Verb+[A-Za-z_][A-Za-z0-9_]*+.) 87.341 - 87.342 -\item The next element must be an ``\texttt{=}'' character, which can 87.343 - be preceded or followed by an arbitrary amount of white space. 87.344 - 87.345 -\item If the rest of the line starts and ends with matching quote 87.346 - characters (either single or double quote), it is treated as a 87.347 - template body. 87.348 - 87.349 -\item If the rest of the line \emph{does not} start with a quote 87.350 - character, it is treated as the name of a file; the contents of this 87.351 - file will be read and used as a template body. 87.352 -\end{itemize} 87.353 - 87.354 -\section{Style files by example} 87.355 - 87.356 -To illustrate how to write a style file, we will construct a few by 87.357 -example. Rather than provide a complete style file and walk through 87.358 -it, we'll mirror the usual process of developing a style file by 87.359 -starting with something very simple, and walking through a series of 87.360 -successively more complete examples. 87.361 - 87.362 -\subsection{Identifying mistakes in style files} 87.363 - 87.364 -If Mercurial encounters a problem in a style file you are working on, 87.365 -it prints a terse error message that, once you figure out what it 87.366 -means, is actually quite useful. 87.367 - 87.368 -\interaction{template.svnstyle.syntax.input} 87.369 - 87.370 -Notice that \filename{broken.style} attempts to define a 87.371 -\texttt{changeset} keyword, but forgets to give any content for it. 87.372 -When instructed to use this style file, Mercurial promptly complains. 87.373 - 87.374 -\interaction{template.svnstyle.syntax.error} 87.375 - 87.376 -This error message looks intimidating, but it is not too hard to 87.377 -follow. 87.378 - 87.379 -\begin{itemize} 87.380 -\item The first component is simply Mercurial's way of saying ``I am 87.381 - giving up''. 87.382 - \begin{codesample4} 87.383 - \textbf{abort:} broken.style:1: parse error 87.384 - \end{codesample4} 87.385 - 87.386 -\item Next comes the name of the style file that contains the error. 87.387 - \begin{codesample4} 87.388 - abort: \textbf{broken.style}:1: parse error 87.389 - \end{codesample4} 87.390 - 87.391 -\item Following the file name is the line number where the error was 87.392 - encountered. 87.393 - \begin{codesample4} 87.394 - abort: broken.style:\textbf{1}: parse error 87.395 - \end{codesample4} 87.396 - 87.397 -\item Finally, a description of what went wrong. 87.398 - \begin{codesample4} 87.399 - abort: broken.style:1: \textbf{parse error} 87.400 - \end{codesample4} 87.401 - The description of the problem is not always clear (as in this 87.402 - case), but even when it is cryptic, it is almost always trivial to 87.403 - visually inspect the offending line in the style file and see what 87.404 - is wrong. 87.405 -\end{itemize} 87.406 - 87.407 -\subsection{Uniquely identifying a repository} 87.408 - 87.409 -If you would like to be able to identify a Mercurial repository 87.410 -``fairly uniquely'' using a short string as an identifier, you can 87.411 -use the first revision in the repository. 87.412 -\interaction{template.svnstyle.id} 87.413 -This is not guaranteed to be unique, but it is nevertheless useful in 87.414 -many cases. 87.415 -\begin{itemize} 87.416 -\item It will not work in a completely empty repository, because such 87.417 - a repository does not have a revision~zero. 87.418 -\item Neither will it work in the (extremely rare) case where a 87.419 - repository is a merge of two or more formerly independent 87.420 - repositories, and you still have those repositories around. 87.421 -\end{itemize} 87.422 -Here are some uses to which you could put this identifier: 87.423 -\begin{itemize} 87.424 -\item As a key into a table for a database that manages repositories 87.425 - on a server. 87.426 -\item As half of a \{\emph{repository~ID}, \emph{revision~ID}\} tuple. 87.427 - Save this information away when you run an automated build or other 87.428 - activity, so that you can ``replay'' the build later if necessary. 87.429 -\end{itemize} 87.430 - 87.431 -\subsection{Mimicking Subversion's output} 87.432 - 87.433 -Let's try to emulate the default output format used by another 87.434 -revision control tool, Subversion. 87.435 -\interaction{template.svnstyle.short} 87.436 - 87.437 -Since Subversion's output style is fairly simple, it is easy to 87.438 -copy-and-paste a hunk of its output into a file, and replace the text 87.439 -produced above by Subversion with the template values we'd like to see 87.440 -expanded. 87.441 -\interaction{template.svnstyle.template} 87.442 - 87.443 -There are a few small ways in which this template deviates from the 87.444 -output produced by Subversion. 87.445 -\begin{itemize} 87.446 -\item Subversion prints a ``readable'' date (the ``\texttt{Wed, 27 Sep 87.447 - 2006}'' in the example output above) in parentheses. Mercurial's 87.448 - templating engine does not provide a way to display a date in this 87.449 - format without also printing the time and time zone. 87.450 -\item We emulate Subversion's printing of ``separator'' lines full of 87.451 - ``\texttt{-}'' characters by ending the template with such a line. 87.452 - We use the templating engine's \tplkword{header} keyword to print a 87.453 - separator line as the first line of output (see below), thus 87.454 - achieving similar output to Subversion. 87.455 -\item Subversion's output includes a count in the header of the number 87.456 - of lines in the commit message. We cannot replicate this in 87.457 - Mercurial; the templating engine does not currently provide a filter 87.458 - that counts the number of lines the template generates. 87.459 -\end{itemize} 87.460 -It took me no more than a minute or two of work to replace literal 87.461 -text from an example of Subversion's output with some keywords and 87.462 -filters to give the template above. The style file simply refers to 87.463 -the template. 87.464 -\interaction{template.svnstyle.style} 87.465 - 87.466 -We could have included the text of the template file directly in the 87.467 -style file by enclosing it in quotes and replacing the newlines with 87.468 -``\verb!\n!'' sequences, but it would have made the style file too 87.469 -difficult to read. Readability is a good guide when you're trying to 87.470 -decide whether some text belongs in a style file, or in a template 87.471 -file that the style file points to. If the style file will look too 87.472 -big or cluttered if you insert a literal piece of text, drop it into a 87.473 -template instead. 87.474 - 87.475 -%%% Local Variables: 87.476 -%%% mode: latex 87.477 -%%% TeX-master: "00book" 87.478 -%%% End:
88.1 --- a/fr/tour-basic.tex Sun Aug 16 03:41:39 2009 +0200 88.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 88.3 @@ -1,696 +0,0 @@ 88.4 -\chapter{Un rapide tour de Mercurial} 88.5 -\label{chap:tour-basic} 88.6 - 88.7 -\section{Installer Mercurial sur votre système} 88.8 -\label{sec:tour:install} 88.9 - 88.10 -Des paquetages binaires de Mercurial sont disponibles pour la plupart 88.11 -des systèmes d'exploitation, ce qui rend facile l'utilisation immédiate 88.12 -de Mercurial sur votre ordinateur. 88.13 - 88.14 -\subsection{Linux} 88.15 - 88.16 -Parce que chaque distribution de Linux a ses propres outils de gestion 88.17 -de paquets, politiques et rythmes de développements, il est difficile de 88.18 -donner un ensemble d'instructions uniques pour installer les binaires de 88.19 -Mercurial. La version de Mercurial avec laquelle vous vous retrouverez 88.20 -dépendra grandement de l'activité de la personne en charge du paquetage 88.21 -pour la distribution. 88.22 - 88.23 -Pour rester simple, je me concentrerai sur l'installation de Mercurial 88.24 -en ligne de commande, sous les distributions les plus courantes. La 88.25 -plupart des distributions fournissent des gestionnaires graphiques de 88.26 -paquetage qui vous permettront d'installer Mercurial en quelques clicks. 88.27 -Le paquetage devrait se nommer \textit{mercurial}. 88.28 - 88.29 -\begin{itemize} 88.30 -\item[Debian] 88.31 - \begin{codesample4} 88.32 - apt-get install mercurial 88.33 - \end{codesample4} 88.34 - 88.35 -\item[Fedora Core] 88.36 - \begin{codesample4} 88.37 - yum install mercurial 88.38 - \end{codesample4} 88.39 - 88.40 -\item[Gentoo] 88.41 - \begin{codesample4} 88.42 - emerge mercurial 88.43 - \end{codesample4} 88.44 - 88.45 -\item[OpenSUSE] 88.46 - \begin{codesample4} 88.47 - yum install mercurial 88.48 - \end{codesample4} 88.49 - 88.50 -\item[Ubuntu] Le paquetage de Mercurial d'Ubuntu est construit sur celui de Debian. 88.51 - Pour l'installer, exécutez simplement les commandes suivantes: 88.52 - \begin{codesample4} 88.53 - apt-get install mercurial 88.54 - \end{codesample4} 88.55 - Les paquetages Ubuntu pour Mercurial ont tendance à être un peu en retard 88.56 - par rapport au paquetage Debian (au moment de l'écriture de ce livre, il 88.57 - faut compter à peu près un retard de 7 mois), ce qui signifie que parfois 88.58 - sur Ubuntu, vous risquez de rencontrer des problèmes qui ont été corrigés 88.59 - depuis longtemps dans les paquetages Debian. 88.60 -\end{itemize} 88.61 - 88.62 -\subsection{Solaris} 88.63 - 88.64 -SunFreeWare, à \url{http://www.saufreeware.com}, est une bonne source 88.65 -pour trouver un vaste nombre de paquets précompilés pour 32 ou 64 bits 88.66 -Intel et les architecture Sparc, dont les versions courantes de Mercurial. 88.67 - 88.68 -\subsection{Mac OS X} 88.69 - 88.70 -Lee Cantey publie un installateur de Mercurial pour Mac OS~X sur le site 88.71 -\url{http://mercurial.berkwood.com}. Ce paquetage fonctionne sur les 88.72 -architectures Intel-~et PowerPC. Avant de vous en servir, vous devez 88.73 -installer une version Universelle MacPython~\cite{web:macpython}. C'est 88.74 -assez facile à faire : suivez simplement les instructions sur le site 88.75 -de Lee. 88.76 - 88.77 -Il est aussi possible d'installer Mercurial en utilisant Fink ou MacPorts, 88.78 -deux outils de gestion de paquetage libres pour Mac OS X. Si vous avez 88.79 -Fink, utilisez \command{sudo fink install mercurial-py25}. Si vous avez 88.80 -MacPorts, \command{sudo port install mercurial}. 88.81 - 88.82 -\subsection{Windows} 88.83 - 88.84 -Lee Cantey publie aussi un installateur de Mercurial pour Windows sur le site 88.85 -\url{http://mercurial.berkwood.com}. Ce paquetage n'a aucune dépendance 88.86 -externe, il fonctionne ``tout court''. 88.87 - 88.88 -\begin{note} 88.89 - La version de Windows de Mercurial ne convertie pas automatiquement 88.90 - les retours chariot Windows et Unix. Si vous désirez partager votre 88.91 - travail avec des utilisateurs Unix, vous devez faire un peu de configuration 88.92 - supplémentaire. XXX En dire plus. 88.93 -\end{note} 88.94 - 88.95 -\section{Commencer à utiliser Mercurial} 88.96 - 88.97 -Pour commencer, nous utiliserons la commande \hgcmd{version} pour vérifier 88.98 -si Mercurial est installé proprement. Les informations affichées sur la 88.99 -version ne sont pas réellement importantes en soit, c'est surtout de savoir 88.100 -si elles s'affichent qui nous intéresse. 88.101 -\interaction{tour.version} 88.102 - 88.103 -\subsection{L'aide intégrée} 88.104 - 88.105 -Mercurial fournit un système d'aide intégré, ce qui est inestimable quand 88.106 -vous vous retrouvez coincé à essayer de vous rappeler comment lancer telle 88.107 -ou telle commande. 88.108 -Si c'est le cas, exécutez simplement \hgcmd{help}; il vous aidera à imprimer 88.109 -une brève liste de commandes, avec une description de ce qu'elles font. Si vous 88.110 -demandez de l'aide sur une commande spécifique (voir ci-dessous), il affichera 88.111 -des informations plus détaillées. 88.112 -\interaction{tour.help} 88.113 -Pour un niveau d'informations encore plus détaillées (ce dont vous aurez rarement 88.114 -besoin), exécuter \hgcmdargs{help}{\hggopt{-v}}. L'option \hggopt{-v} est 88.115 -l'abréviation de \hggopt{--verbose}, et indique à Mercurial d'afficher plus 88.116 -d'informations que d'habitude. 88.117 - 88.118 -\section{Travailler avec un dépôt} 88.119 - 88.120 -Avec Mercurial, tout se déroule au sein du \emph{dépôt}\footnote{NdT: Dépôt est 88.121 -la traduction que j'ai retenue pour tout l'ouvrage du terme anglais \textit{repository}}. 88.122 -Le dépôt d'un projet contient tous les fichiers qui ``appartiennent'' au projet. 88.123 - 88.124 -Il n'y a rien de particulièrement magique au sujet de ce dépôt, c'est 88.125 -simplement une arborescence sur votre système de fichiers que Mercurial 88.126 -traite de manière spéciale. Vous pouvez renommer ou effacer ce répertoire 88.127 -à n'importe quel moment, en utilisant la ligne de commande ou votre 88.128 -explorateur de fichiers. 88.129 - 88.130 -\subsection{Faire une copie locale de votre dépôt} 88.131 - 88.132 -\emph{Copier} un dépôt est juste un peu spécial. Bien que vous 88.133 -puissiez utiliser une commande habituelle de copie pour copier 88.134 -votre dépôt, il vaut mieux utiliser une commande fournie par 88.135 -Mercurial. Cette commande est appelée \hgcmd{clone}, car elle 88.136 -crée une copie identique à un dépôt existant. 88.137 -\interaction{tour.clone} 88.138 -Si votre opération de clonage réussit, vous devriez maintenant 88.139 -avoir un répertoire local appelé \dirname{hello}. Ce répertoire 88.140 -contiendra quelques fichiers. 88.141 -\interaction{tour.ls} 88.142 -Ces fichiers ont le même contenu et historique dans votre dépôt 88.143 -qu'ils ont dans le dépôt que vous avez cloné. 88.144 - 88.145 -Chaque dépôt Mercurial est complet, autonome et indépendant. Il 88.146 -contient sa propre copie privée des fichiers du projet et de leur 88.147 -historique. Le clone d'un dépôt se souvient de la localisation du 88.148 -dépôt à partir duquel il a été clôné, mais il ne communique pas avec 88.149 -ce dernier, ou un autre, à moins que vous ne lui demandiez. 88.150 - 88.151 -Ce que tout ceci signifie pour le moment est que nous sommes libres 88.152 -d'expérimenter avec ce dépôt, confiants dans le fait qu'il s'agit d'un 88.153 -``bac à sable'' qui n'affectera personne d'autre. 88.154 - 88.155 -\subsection{Quel est le contenu d'un dépôt ?} 88.156 - 88.157 -Prêtons plus attention un instant au contenu d'un dépôt. Nous voyons 88.158 -qu'il contient un répertoire nommé \dirname{.hg}. C'est ici que Mercurial 88.159 -conserve toutes ses métadonnées. 88.160 -\interaction{tour.ls-a} 88.161 - 88.162 -Le contenu du répertoire \dirname{.hg} et ses sous répertoires sont les 88.163 -seuls propres à Mercurial. Tous les autres fichiers et répertoires dans 88.164 -le dépôt sont à vous, et vous pouvez en faire ce que vous voulez. 88.165 - 88.166 -Pour introduire un peu de terminologie, le répertoire \dirname{.hg} est 88.167 -un ``vrai'' dépôt, et tous les fichiers et les répertoires qui coexistent 88.168 -avec lui, sont désignés sous le nom \emph{espace de travail}\footnote{NdT: 88.169 -\textit{working directory}}. Une manière facile de se rappeler cette 88.170 -distinction est de retenir que le \emph{dépôt} contient l'\emph{historique} 88.171 -de votre projet, alors que l'\emph{espace de travail} contient une \emph{copie 88.172 -ponctuelle}\footnote{NdT: Ce terme est une traduction du terme anglais 88.173 -\textit{snapshot}. Il est traduit ici pour faciliter la lecture, mais ne sera 88.174 -plus traduit par la suite.} de votre projet à un certain point de son 88.175 -historique. 88.176 - 88.177 -\section{Une ballade dans l'historique} 88.178 - 88.179 -Une des premières choses que vous aurez envie de faire avec un nouveau 88.180 -dépôt, sera de comprendre son historique. La commande \hgcmd{log} vous 88.181 -donne une vue de l'historique. 88.182 -\interaction{tour.log} 88.183 -Par défaut, cette commande affiche à l'écran un bref paragraphe pour chaque 88.184 -révision enregistrée pour ce projet. Dans la terminologie de Mercurial, nous 88.185 -appelons chacun de ces évènements enregistrés un \emph{changeset}, parce 88.186 -qu'il contient un ensemble de modifications sur plusieurs fichiers. 88.187 - 88.188 -La commande \hgcmd{log} affiche ainsi ces informations: 88.189 -\begin{itemize} 88.190 -\item[\texttt{changeset}] Ce champ contient un nombre, séparé par deux points 88.191 - (:), d'une chaine hexadécimale. Il s'agit en fait d'\emph{identifiants} 88.192 - d'un \textit{changeset}. Il y a deux identifiants car le numéro de 88.193 - la révision est plus court et plus à facile à saisir qu'une séquence 88.194 - hexadécimale. 88.195 -\item[\texttt{user}] L'identité de la personne qui a créée ce %%% laisser le terme anglais car il sera affiché 88.196 - \textit{changeset}. C'est un champ libre de forme, mais la plupart du 88.197 - temps il contient le nom et l'email de la personne. 88.198 -\item[\texttt{date}] La date et l'heure à laquelle le \textit{changeset} 88.199 - a été créé, ainsi que le \textit{fuseau horaire} dans laquelle il a été créé. %%%TODO: Translate 'timezone' properly : FUSEAU 88.200 - (La date et l'heure sont locales à ce \textit{fuseau}, elles indiquent 88.201 - donc quelle date et heure il était pour la personne qui a créé ce %%%TODO: je suppose (quelle "heure") OUI 88.202 - \textit{changeset}.) 88.203 -\item[\texttt{résumé}] La première du message que le créateur a associé à 88.204 - son \textit{changeset} pour le décrire. 88.205 -\end{itemize} 88.206 - 88.207 -Par défaut, la commande \hgcmd{log} n'affiche qu'un résumé, il manque 88.208 -beaucoup de détails. 88.209 - 88.210 -La figure~\ref{fig:tour-basic:history} fournit une représentation graphique 88.211 -de l'historique du dépôt \dirname{hello}, pour rendre plus facile de voir 88.212 -dans quelle direction l'historique se ``déroule''\footnote{NdT: \textit{flowing in}.}. 88.213 -Nous reviendrons régulièrement sur cette représentation dans ce chapitre et 88.214 -ceux qui suivent. 88.215 - 88.216 -\begin{figure}[ht] 88.217 - \centering 88.218 - \grafix{tour-history} 88.219 - \caption{Représentation graphique du dépôt \dirname{hello} } 88.220 - \label{fig:tour-basic:history} 88.221 -\end{figure} 88.222 - 88.223 -\subsection{Changesets, révisions, et discuter avec les autres}%%%TODO: je propose : "discussion" (3 noms communs) 88.224 -%%% je propose "colaboration" 88.225 - 88.226 -Comme l'anglais est réputé pour être un langage maladroit, et que l'informatique 88.227 -est la source de bien des erreurs de terminologies (pourquoi utiliser un 88.228 -seul terme quand quatre feront l'affaire ?), la gestion de version a une 88.229 -variété de mots et de phrases qui veulent dire la même chose. Si vous 88.230 -discutez d'historique de Mercurial avec d'autres personnes, 88.231 -%%%TODO: ça ne veut rien dire: il faut supprimer une des personnes : soit "quelqu'un", 88.232 -% soit "à d'autres personnes" 88.233 -vous constaterez que souvent le mot ``\textit{changeset}'' est contracté simplement 88.234 -en ``change'' ou (à l'écrit) ``cset'', et même parfois un 88.235 -\textit{changeset} simplement ``révision'', abrégé en ``rev''. 88.236 - 88.237 -Bien que le \emph{mot} que vous utilisez pour désigner le concept de 88.238 -\textit{changeset} importe peu, l'\emph{identifiant} que vous utilisez 88.239 -pour désigner un \emph{changeset} \textit{spécifique} a une grande 88.240 -importance. Rappelez vous que le champ \textit{changeset} affiché par la 88.241 -commande \hgcmd{log} identifie un \textit{changeset} à la fois avec 88.242 -un numéro de révision et une séquence hexadécimale. 88.243 - 88.244 -\begin{itemize} 88.245 -\item Le numéro de révision est \emph{seulement valable dans ce dépôt}, 88.246 -\item alors que la séquence hexadécimale est un \emph{identifiant 88.247 - permanent, et invariant } qui pourra toujours être associé au 88.248 - \textit{changeset} exact de \emph{chaque} copie de votre dépôt. 88.249 -\end{itemize} 88.250 - 88.251 -La distinction est importante. Si vous envoyez un email à quelqu'un en 88.252 -parlant de la ``révision 33'', il est très probable que sa révision~33 88.253 -\emph{ne sera pas la même} que la votre. La raison de ceci est que le 88.254 -numéro de révision dépend de l'ordre dans lequel les modifications sont 88.255 -arrivées dans le dépôt, et il n'y a aucune garantie que les mêmes changements 88.256 -soient arrivés dans le même ordre dans différents dépôts. Trois modifications 88.257 -$a,b,c$ peuvent aisément apparaitre dans un dépôt comme $0,1,2$, et dans 88.258 -un autre comme $1,0,2$. 88.259 - 88.260 -Mercurial utilise les numéros de révision uniquement comme des raccourcis 88.261 -pratiques. Si vous devez discuter d'un \textit{changeset} avec quelqu'un, 88.262 -ou identifer un \textit{changeset} pour une quelquonque %%%TODO: our : "pour" ou "ou" 88.263 -raison (par exemple, un rapport de \textit{bug}), utilisez la séquence 88.264 -hexadécimale. 88.265 - 88.266 -\subsection{Afficher une révision spécifique} 88.267 - 88.268 -Pour réduire la sortie de \hgcmd{log} à une seule révision, utilisez 88.269 -l'option \hgopt{log}{-r} (ou \hgopt{log}{--rev}). Vous pouvez utiliser 88.270 -le numéro de révision ou la séquence hexadécimale comme identifiant, et 88.271 -demander autant de révisions que vous le souhaitez. 88.272 -\interaction{tour.log-r} 88.273 - 88.274 -Si vous voulez voir l'historique de plusieurs révisions sans avoir à 88.275 -les énumérer, vous pouvez utiliser la \emph{\textit{range notation}} 88.276 -\footnote{NdT: Il n'est pas aisé de traduire ce terme, donc je le %%%TODO : intervalle de numérotation ? 88.277 -laisse en anglais} qui vous permet d'exprimer l'idée ``je veux toutes 88.278 -les révisions entre $a$ et $b$, inclus''. 88.279 -\interaction{tour.log.range} 88.280 -Mercurial respecte aussi l'ordre dans lequel vous spécifiez les 88.281 -révisions, ainsi \hgcmdargs{log}{-r 2:4} affichera $2,3,4$ alors que 88.282 -\hgcmdargs{log}{-r 4:2} affichera $4,3,2$. 88.283 - 88.284 -\subsection{Informations détaillées} 88.285 - 88.286 - 88.287 -Le résumé affiché par \hgcmd{log} est suffisant si vous savez déjà ce %%%TODO: je pense que le premier "si" est de trop : exact 88.288 -que vous cherchez. En revanche, vous aurez probablement besoin de voir une description 88.289 -complète du changement, ou une liste des fichiers modifiés si vous 88.290 -cherchez à déterminer qu'un \textit{changeset} est bien celui que vous%%%TODO: les propositions sont mal construites : après un "si...." il faut une proposition sans "si... donc ici : "si ... recherchez", ben quoi ? 88.291 -recherchez. L'option \hgopt{-v} de la commande \hgcmd{log} (ou 88.292 -\hgopt{--verbose}) vous donne ces informations supplémentaires. 88.293 -\interaction{tour.log-v} 88.294 - 88.295 -Si vous voulez voir à la fois la description et le contenu d'une 88.296 -modification, ajouter l'option \hgopt{log}{-p} (ou \hgopt{log}{--patch}). 88.297 -Ceci affiche le contenu d'une modification comme un \emph{diff unifié} 88.298 -\footnote{NdT: \textit{unified diff}} (si vous n'avez jamais vu de diff 88.299 -unifié avant, consultez la section~\ref{sec:mq:patch} pour un rapide 88.300 -survol). 88.301 - 88.302 -\interaction{tour.log-vp} 88.303 - 88.304 -\section{Tout sur les options de commandes} 88.305 - 88.306 - 88.307 -Avant d'aller plus loin sur le fonctionnement des commandes de Mercurial, 88.308 -étudions un moment comment elles fonctionnent de manière générale. Vous 88.309 -trouverez ça probablement utile pour la suite de notre parcours. 88.310 - 88.311 -Mercurial utilise une approche directe et cohérente pour interpréter %%%TODO: une manière d'approche ? 88.312 -les options que vous passez aux commandes. Il suit une convention commune 88.313 -à la plupart des systèmes Unix et Linux modernes. 88.314 - 88.315 -\begin{itemize} 88.316 -\item Chaque option a un nom complet. Par exemple, comme nous l'avons déjà 88.317 - vu, la commande \hgcmd{log} accepte l'option \hgopt{log}{--rev}.%%%TODO: commande ou command e\hgcmd...? 88.318 -\item La plupart des options disposent de noms abrégés. Aussi, au lieu d'utiliser 88.319 - \hgopt{log}{--rev}, vous pouvez utiliser \hgopt{log}{-r}. (Les options qui 88.320 - n'ont pas de noms abrégés sont généralement rarement utilisées, pour cette raison). 88.321 -\item Les noms complets commencent par deux tirets (i.e.~\hgopt{log}{--rev}), 88.322 - alors que les options courtes commencent avec un seul (i.e.~\hgopt{log}{-r}). 88.323 -\item Les noms des options sont cohérents entre les commandes. Par exemple, 88.324 - chaque commande qui accepte un \textit{changeset~ID} ou un numéro de révision 88.325 - accepte aussi \hgopt{log}{-r} et \hgopt{log}{--rev} comme arguments. 88.326 - %TODO: Small mistake here, shouldn't have log here... shouldn't it ? 88.327 -\end{itemize} 88.328 - 88.329 -Dans les exemples de ce livre, j'utilise les noms abrégés plutôt que les noms 88.330 -complets. Ceci est une préférence personnelle, pas une recommandation. 88.331 - 88.332 -La plupart des commandes qui affichent une quelconque sortie à l'écran, 88.333 -afficheront davantage avec l'option \hggopt{-v} (ou \hggopt{--verbose}), et 88.334 -moins avec l'option \hggopt{-q} (ou \hggopt{--quiet}). 88.335 - 88.336 -\section{Faire et vérifier des modifications} 88.337 - 88.338 -Maintenant que nous avons une bonne idée des commandes pour consulter 88.339 -l'historique de Mercurial, regardons comment faire des modifications et 88.340 -les examiner. 88.341 - 88.342 - 88.343 -La première chose que nous allons faire c'est isoler notre expérience dans 88.344 -un dépôt à part. Nous allons utiliser la commande \hgcmd{clone}, mais nous 88.345 -n'avons pas besoin de faire une copie de dépôt distant. Comme nous avons 88.346 -déjà une copie locale, nous pouvons juste faire un clone de celle-ci à la 88.347 -place. C'est beaucoup plus rapide que de faire une copie à travers le 88.348 -réseau, et un dépôt cloné localement prend également moins d'espace disque. 88.349 - 88.350 -\interaction{tour.reclone} 88.351 - 88.352 -On notera au passage qu'il est souvent considéré comme une bonne pratique 88.353 -de conserver une copie ``immaculée'' du dépôt distant, à partir de laquelle 88.354 -vous pourrez faire des copies locales temporaires pour créer des ``bacs à 88.355 -sable'' pour chaque tâche sur laquelle vous souhaitez travailler. Ceci vous 88.356 -permet de travailler sur plusieurs choses en parallèle, chacune isolée les 88.357 -unes des autres en attendant que ces tâches soient finies et que vous soyez 88.358 -prêt à les réintégrer. Parce que les copies locales sont peu coûteuses, il 88.359 -est très rapide de créer ou détruire des dépôts dès que vous en avez besoin. 88.360 - 88.361 -%% Note: la dernière phrase n'est pas une traduction littérale, mais je 88.362 -%% pense qu'elle exprime plus clairement en français ce que veut dire son 88.363 -%% équivalent anglais. : OUI 88.364 - 88.365 -Dans notre dépôt \dirname{my-hello}, nous avons un fichier \filename{hello.c} 88.366 -qui contient le classique programme ``hello, world''. Nous allons utiliser 88.367 -l'ancienne et vénérable commande \command{sed} pour l'éditer afin qu'il 88.368 -affiche une seconde ligne à l'écran. (J'utilise \command{sed} seulement parce 88.369 -qu'il est ainsi facile d'écrire des exemples sous forme de script. Comme 88.370 -vous n'avez pas ces contraintes, vous n'utiliserez probablement pas \command{sed} 88.371 -mais plutôt votre éditeur de texte favori). 88.372 - 88.373 -\interaction{tour.sed} 88.374 - 88.375 -La commande \hgcmd{status} de Mercurial nous dira de quels fichiers Mercurial 88.376 -s'occupe au sein de ce dépôt. 88.377 -\interaction{tour.status} 88.378 -La commande \hgcmd{status} n'affiche rien sur la sortie pour quelques fichiers 88.379 -mais une ligne commence par ``\texttt{M}'' for \filename{hello.c}. À moins que 88.380 -vous ne lui indiquiez de le faire, \hgcmd{status} n'affichera aucune sortie 88.381 -pour les fichiers qui n'ont pas été modifiés. 88.382 - 88.383 -Le caractère ``\texttt{M}'' indique que Mercurial a remarqué que nous avions 88.384 -modifié le fichier \filename{hello.c}. Nous n'avons pas besoin d'\emph{informer} 88.385 -Mercurial que nous allons modifier un fichier avant de le faire, ou que nous 88.386 -venons de le modifier, il est capable de s'en rendre compte tout seul. 88.387 - 88.388 -C'est pratique de savoir que nous avons modifié \filename{hello.c}, mais il 88.389 -serait encore plus pratique de savoir ce que nous avons modifié exactement. Pour 88.390 -cela, nous avons la commande \hgcmd{diff}. 88.391 - 88.392 -\interaction{tour.diff} 88.393 - 88.394 -\section{Enregister les modifications dans un nouveau \textit{changeset}} 88.395 - 88.396 -Nous pouvons modifier des fichiers, compiler et tester nos modifications, 88.397 -et utiliser les commandes \hgcmd{status} et \hgcmd{diff} pour voir les 88.398 -modifications effectuées, jusqu'au moment où nous serons assez satisfaits 88.399 -pour décider d'enregistrer notre travail dans un \textit{changeset}. 88.400 - 88.401 -La commande \hgcmd{commit} vous laisse créer un nouveau \textit{changeset}, 88.402 -nous désignerons généralement cette opération par ``faire un commit'' ou 88.403 -``commiter''\footnote{NdT: De mon expérience, la plupart des francophones 88.404 -utilisent régulièrement, à l'oral, cette expression, mais bien évidement 88.405 -il ne s'agit pas d'un terme de terminologie correcte, ni même français.} 88.406 - 88.407 -\subsection{Définir le nom d'utilisateur} 88.408 - 88.409 -Quand vous exécutez la commande \hgcmd{commit} pour la première fois, elle 88.410 -n'est pas garantie de réussir. Mercurial enregistre votre nom et votre 88.411 -adresse avec chaque modification que vous effectuez, de manière à ce que 88.412 -vous soyez capable (ou d'autres le soient) de savoir qui a fait quelle 88.413 -modification. Mercurial essaye automatiquement de découvrir un nom 88.414 -d'utilisateur qui ait un minimum de sens pour effectuer l'opération 88.415 -de \textit{commit} avec. Il va essayer chacune des méthodes suivantes, 88.416 -dans l'ordre: 88.417 -\begin{enumerate} 88.418 -\item Si vous spécifiez l'option \hgopt{commit}{-u} avec la commande 88.419 - \hgcmd{commit}, suivi d'un nom d'utilisateur, ceci aura toujours la 88.420 - priorité sur les autres méthodes ci dessous. 88.421 -\item Si vous avez défini une variable d'environnement \envar{HGUSER}, 88.422 - c'est cette valeur qui est alors utilisée. 88.423 -\item Si vous créez un fichier nommé \sfilename{.hgrc} dans votre 88.424 - répertoire \textit{home}, avec une entrée \rcitem{ui}{username}, 88.425 - c'est la valeur associée qui sera utilisée. Pour voir à quoi 88.426 - ressemble le contenu de ce fichier regardez la 88.427 - section~\ref{sec:tour-basic:username} ci-dessous. 88.428 -\item Si vous avez défini une variable d'environnement \envar{EMAIL} 88.429 - celle ci sera utilisée ensuite. 88.430 -\item Enfin, Mercurial interrogera votre système pour trouver votre 88.431 - nom d'utilisateur local ainsi que le nom de la machine hôte, et il 88.432 - fabriquera un nom d'utilisateur à partir de ces données. Comme il arrive 88.433 - souvent que ce genre de noms soit totalement inutile, il vous 88.434 - préviendra en affichant un message d'avertissement. 88.435 -\end{enumerate} 88.436 - 88.437 -Si tous ces mécanismes échouent, Mercurial n'exécutera pas la commande, 88.438 -affichant un message d'erreur. Dans ce cas, il ne vous laissera pas 88.439 -effectuer de \textit{commit} tant que vous n'aurez pas défini un nom 88.440 -d'utilisateur. 88.441 - 88.442 -Vous devriez penser à utiliser la variable d'environement \envar{HGUSER} 88.443 -et l'option \hgopt{commit}{-u} comme moyen pour \emph{changer le nom 88.444 -d'utilisateur} par défaut. Pour une utilisation normale, la manière la plus 88.445 -simple et robuste d'opérer est de créer un fichier \sfilename{.hgrc}, 88.446 -voir ci-dessous pour les détails à ce sujet. 88.447 - 88.448 -\subsubsection{Créer un fichier de configuration pour Mercurial} 88.449 -\label{sec:tour-basic:username} 88.450 - 88.451 -Pour définir un nom d'utilisateur, utilisez votre éditeur de texte favori 88.452 -pour créer un fichier \sfilename{.hgrc} dans votre répertoire \textit{home}. 88.453 -Mercurial va utiliser ce fichier pour retrouver votre configuration personnelle. 88.454 -Le contenu initial devrait ressembler à ceci: 88.455 -\begin{codesample2} 88.456 - # This is a Mercurial configuration file. 88.457 - [ui] 88.458 - username = Firstname Lastname <email.address@domain.net> 88.459 -\end{codesample2} 88.460 -La ligne avec \texttt{[ui]} commence une \emph{section} du fichier de 88.461 -configuration, ainsi la ligne ``\texttt{username = ...}'' signifie `` 88.462 -définir la valeur de l'élément \texttt{username} dans la section 88.463 -\texttt{ui}''. Une section continue jusqu'à ce qu'une nouvelle 88.464 -commence, ou que la fin du fichier soit atteinte. Mercurial ignore 88.465 -les lignes vides et traite tout texte situé à la suite d'un 88.466 -``\texttt{\#}'' jusqu'à la fin de la ligne comme un commentaire. 88.467 - 88.468 -\subsubsection{Choisir un nom d'utilisateur} 88.469 - 88.470 -Vous pouvez utiliser n'importe quelle valeur pour votre \texttt{username}, 88.471 -car cette information est destinée à d'autres personnes et non à être 88.472 -interprétée par Mercurial. La convention que la plupart des personnes 88.473 -<<<<<<< local 88.474 -suivent est d'utiliser leurs noms suivies de leurs adresses emails, 88.475 -comme montrée ci-dessus: 88.476 - 88.477 -\begin{note} 88.478 - Le mécanisme interne du serveur \textit{web} intégré à Mercurial, 88.479 - masque les adresses emails, pour rendre plus difficile leurs 88.480 - récupérations par les outils utilisés par les \textit{spammmers}. 88.481 - Ceci réduit la probabilité que de recevoir encore plus de 88.482 - \textit{spam} si vous vous publiez un dépôt sur internet. 88.483 -\end{note} 88.484 - 88.485 -\subsection{Rédiger un message de \textit{commit}} 88.486 - 88.487 -Lorsqu'on effectue une opération de \textit{commit}, Mercurial 88.488 -lance automatiquement un éditeur de texte pour permettre de saisir 88.489 -un message qui décrira les modifications effectuées dans ce 88.490 -\textit{changeset}. Ce message est nommé le \emph{message de 88.491 -\textit{commit}}. Ce sera un enregistrement pour tout lecteur 88.492 -expliquant le pourquoi et le comment de vos modifications, et il sera 88.493 -affiché par la commande \hgcmd{log}. 88.494 -\interaction{tour.commit} 88.495 - 88.496 -L'éditeur que la commande \hgcmd{commit} déclenche ne contiendra 88.497 -qu'une ligne vide suivi d'un certain nombre de lignes commençant 88.498 -par ``\texttt{HG:}''. 88.499 -\begin{codesample2} 88.500 - \emph{empty line} 88.501 - HG: changed hello.c 88.502 -\end{codesample2} 88.503 -Mercurial ignore les lignes qui commencent avec ``\texttt{HG:}'', il 88.504 -ne les utilise que pour nous indiquer quels fichiers modifiés il se 88.505 -prépare à \textit{commiter}. Modifier ou effacer ces lignes n'a 88.506 -aucune conséquence sur l'opération de \textit{commit}. 88.507 - 88.508 -\subsection{Rédiger un message \textit{approprié}} 88.509 - 88.510 -Comme \hgcmd{log} n'affiche que la première ligne du message de 88.511 -\textit{commit} par défaut, il est souvent considéré comme une bonne 88.512 -pratique de rédiger des messages de \textit{commit} qui tiennent 88.513 -sur une seule ligne. Voilà un exemple concret de message de 88.514 -\textit{commit} qui \emph{ne suit pas} cette directive, et qui a donc 88.515 -un résumé peu lisible. 88.516 - 88.517 -\begin{codesample2} 88.518 - changeset: 73:584af0e231be 88.519 - user: Censored Person <censored.person@example.org> 88.520 - date: Tue Sep 26 21:37:07 2006 -0700 88.521 - summary: include buildmeister/commondefs. Add an exports and install 88.522 -\end{codesample2} 88.523 - 88.524 -A ce sujet, il faut noter qu'il n'existe pas de règle absolue dans ce 88.525 -domaine. Mercurial lui-même n'interprète pas les contenus des messages 88.526 -de \textit{commit}, ainsi votre projet est libre de concevoir différentes 88.527 -politiques de mise en page des messages. 88.528 - 88.529 -Ma préférence personnelle va au message court, mais informatif, qui offre 88.530 -des précisions supplémentaires par rapport à ce que pourrait m'apprendre une commande 88.531 -\hgcmdargs{log}{--patch}. 88.532 - 88.533 -\subsection{Annuler un \textit{commit}} 88.534 - 88.535 -Si, en rédigeant le message, vous décidez que finalement vous ne 88.536 -voulez pas effectuer ce \textit{commit}, il suffit de quitter simplement 88.537 -l'éditeur sans sauver. Ceci n'aura aucune conséquence sur le dépôt ou 88.538 -les fichiers de l'espace de travail. 88.539 - 88.540 -Si vous exécuter la commande \hgcmd{commit} sans aucun argument, elle 88.541 -enregistre toutes les modifications que vous avez faites, comme le montre 88.542 -les commandes \hgcmd{status} et \hgcmd{diff}. 88.543 - 88.544 -\subsection{Admirer votre travail} 88.545 - 88.546 -Une fois que votre \textit{commit} est terminé, vous pouvez utiliser 88.547 -la commande \hgcmd{tip} pour afficher le \textit{changeset} que nous 88.548 -venons de créer. Cette commande produit une sortie à l'écran qui est 88.549 -identique à celle du \hgcmd{log}, mais qui n'affiche que la dernière 88.550 -révision du dépôt. 88.551 -\interaction{tour.tip} 88.552 -On fait couramment référence à la dernière révision du dépôt comme 88.553 -étant la révision \textit{tip}, ou plus simplement le \textit{tip}. 88.554 - 88.555 -\section{Partager ses modifications} 88.556 - 88.557 -Nous avons mentionné plus haut que les dépôts de Mercurial 88.558 -sont autosuffisants. Ce qui signifie que le \textit{changeset} 88.559 -que vous venez de créer existe seulement dans votre répertoire 88.560 -\dirname{my-hello}. Étudions comment propager cette modification 88.561 -dans d'autres dépôts. 88.562 - 88.563 -\subsection{Récupérer les modifications d'autres dépôts} 88.564 -\label{sec:tour:pull} 88.565 - 88.566 -Pour commencer, construisons un clone de notre dépôt \dirname{hello} 88.567 -qui ne contiendra pas le changement que nous venons d'effectuer. Nous 88.568 -l'appellerons notre dépôt temporaire \dirname{hello-pull}. 88.569 - 88.570 -\interaction{tour.clone-pull} 88.571 - 88.572 -Nous allons utiliser la commande \hgcmd{pull} pour apporter les 88.573 -modifications depuis \dirname{my-hello} dans \dirname{hello-pull}. 88.574 -Néanmoins, récupérer aveuglement des modifications depuis un dépôt 88.575 -a quelque chose d'un peu effrayant. Mercurial propose donc une 88.576 -commande \hgcmd{incoming} qui permet de savoir quelles modifications 88.577 -la commande \hgcmd{pull} \emph{pourrait} entraîner dans notre dépôt, 88.578 -et ceci sans effectuer réellement de modification dessus. 88.579 -\interaction{tour.incoming} 88.580 -(Bien évidement, quelqu'un pourrait ajouter des modifications 88.581 -supplémentaires sur le dépôt que nous étudions avec \hgcmd{incoming}, 88.582 -avant que nous ayons effectué notre \hgcmd{pull}, avec comme 88.583 -triste conséquence que nous aurons récupéré des modifications que 88.584 -nous n'attendions pas.) 88.585 - 88.586 -Apporter les modifications rapatriées dans un dépôt se résume donc 88.587 -à exécuter la commande \hgcmd{pull}, et préciser depuis quel dépôt 88.588 -effectuer le \hgcmd{pull}. 88.589 -\interaction{tour.pull} 88.590 - 88.591 -Comme vous le voyez avec une sortie avant et après de la commande 88.592 -\hgcmd{tip}, nous avons réussi à récupérer aisément les modifications 88.593 -dans notre dépôt. Il reste néanmoins quelque chose à faire avant de 88.594 -placer ces modifications dans l'espace de travail. 88.595 - 88.596 -\subsection{Mise à jour de l'espace de travail} 88.597 - 88.598 -Nous avons jusqu'à maintenant grossièrement définie la relation 88.599 -entre un dépôt et un espace de travail. La commande \hgcmd{pull} que 88.600 -nous avons exécutée dans la section~\ref{sec:tour:pull} a apporté 88.601 -des modifications, que nous avons vérifiées, dans notre dépôt, mais 88.602 -il n'y a aucune trace de ces modifications dans notre espace de travail. 88.603 -En effet, \hgcmd{pull} ne touche pas (par défaut) à l'espace de 88.604 -travail. C'est la commande \hgcmd{update} qui s'en charge. 88.605 -\interaction{tour.update} 88.606 - 88.607 -Il peut sembler un peu étrange que la commande \hgcmd{pull} ne mette 88.608 -pas à jour l'espace de travail automatiquement. Il y a en fait une 88.609 -très bonne raison à cela : vous pouvez utilisez la commande 88.610 - 88.611 -\hgcmd{update} pour mettre à jour votre espace de travail à l'état 88.612 -dans lequel il était à \emph{n'importe quelle révision} de l'historique 88.613 -du dépôt. Si vous aviez un espace de travail contenant une ancienne 88.614 -révision---pour chercher l'origine d'un \textit{bug}, par exemple---et 88.615 -que vous effectuiez un \hgcmd{pull} qui mettrait à jour automatiquement 88.616 -votre espace de travail, vous ne seriez probablement pas très satisfait. 88.617 - 88.618 -Néanmoins, comme les opérations de \textit{pull} sont très souvent 88.619 -suivies d'un \textit{update}, Mercurial vous permet de combiner les 88.620 -deux aisément en passant l'option \hgopt{pull}{-u} à la commande 88.621 -\hgcmd{pull} 88.622 -\begin{codesample2} 88.623 - hg pull -u 88.624 -\end{codesample2} 88.625 - 88.626 -Si vous étudiez de nouveau la sortie de la commande \hgcmd{pull} dans 88.627 -la section~\ref{sec:tour:pull} quand nous l'avons exécutée sans l'option 88.628 -\hgopt{pull}{-u}, vous pouvez constater qu'elle a affiché un rappel assez 88.629 -utile : vous devez encore effectuer une opération pour mettre à jour 88.630 -votre espace de travail: 88.631 - 88.632 -\begin{codesample2} 88.633 - (run 'hg update' to get a working copy) 88.634 -\end{codesample2} 88.635 - 88.636 -Pour découvrir sur quelle révision de l'espace de travail on est, utilisez 88.637 -la commande \hgcmd{parents}. 88.638 -\interaction{tour.parents} 88.639 -Si vous regardez de nouveau le dessin~\ref{fig:tour-basic:history}, vous 88.640 -<<<<<<< local 88.641 -verrez les flèches reliant entre eux les \textit{changeset}. Le nœud 88.642 -d'où la flèche \emph{part} est dans chaque cas un parent, 88.643 -et le nœud où la flèche \emph{arrive} est un enfant. 88.644 - 88.645 -L'espace de travail a un parent de la même manière, c'est ce \textit{changeset} 88.646 -que l'espace de travail contient à ce moment. 88.647 -%%%TODO : difficile à comprendre : l'espace de travail a un parent, de la même manière, c'est ce changeset que l'espace... 88.648 - 88.649 -Pour mettre à jour l'espace de travail d'une révision particulière, 88.650 -indiquez un numéro de révision ou un \textit{changeset~ID} à la commande 88.651 -\hgcmd{update}. 88.652 -\interaction{tour.older} 88.653 -Si vous ne précisez pas de manière explicite de numéro de révision 88.654 -la commande \hgcmd{update} mettra à jour votre espace de travail avec 88.655 -le contenu de la révsion \textit{tip}, comme montré dans l'exemple 88.656 -ci dessus lors du second appel à \hgcmd{update}. 88.657 - 88.658 -\subsection{Transférer les modifications à un autre dépôt} 88.659 - 88.660 -Mercurial vous laisse transférer les modifications à un autre 88.661 -dépôt, depuis votre dépôt actuel. Comme dans l'exemple du 88.662 -\hgcmd{pull} ci-dessus, nous allons créer un dépôt temporaire 88.663 -vers lequel transférer\footnote{NdT: Les francophones disent souvent 88.664 -``pousser'' tout simplement} nos modifications. 88.665 -\interaction{tour.clone-push} 88.666 -La commande \hgcmd{outgoing} nous indique quels changements nous 88.667 -allons transférer vers l'autre serveur ? 88.668 -\interaction{tour.outgoing} 88.669 -Et la commande \hgcmd{push} effectue réellement le transfert. 88.670 -\interaction{tour.push} 88.671 -Comme avec \hgcmd{pull}, la commande \hgcmd{push} ne met pas à jour 88.672 -le répertoire de travail du dépôt dans lequel il transfère les 88.673 -modifications. (À l'inverse de \hgcmd{pull}, \hgcmd{push} ne fournit 88.674 -pas d'option \texttt{-u} pour forcer la mise à jour de l'espace 88.675 -de travail cible). 88.676 - 88.677 -Qu'est ce qui se passe lorsque vous essayez de récupérer ou de transférer 88.678 -vos modifications et que le dépôt cible a déjà reçu ces modifications ? 88.679 -Rien de bien excitant. 88.680 -\interaction{tour.push.nothing} 88.681 - 88.682 -\subsection{Partager ses modifications à travers le réseau} 88.683 - 88.684 -Les commandes que nous avons étudiées dans les sections précédentes 88.685 -ne sont pas limitées aux dépôt locaux. Chacune fonctionne de la même 88.686 -manière à travers une connexion réseau, il suffit de lui passer une 88.687 -URL à la place d'un chemin de fichier local. 88.688 - 88.689 -\interaction{tour.outgoing.net} 88.690 -Dans cet exemple, nous allons voir quels changements nous pourrions 88.691 -transférer vers le dépôt distant, mais le dépôt est, de manière tout 88.692 -à fait compréhensible, pas configuré pour accepter des modifications 88.693 -d'utilisateurs anonymes. 88.694 -\interaction{tour.push.net} 88.695 - 88.696 -%%% Local Variables: 88.697 -%%% mode: latex 88.698 -%%% TeX-master: "00book" 88.699 -%%% End:
89.1 --- a/fr/tour-history.svg Sun Aug 16 03:41:39 2009 +0200 89.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 89.3 @@ -1,289 +0,0 @@ 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://sodipodi.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.44.1" 89.19 - sodipodi:docname="tour-history.svg"> 89.20 - <defs 89.21 - id="defs4"> 89.22 - <marker 89.23 - inkscape:stockid="Arrow1Mstart" 89.24 - orient="auto" 89.25 - refY="0.0" 89.26 - refX="0.0" 89.27 - id="Arrow1Mstart" 89.28 - style="overflow:visible"> 89.29 - <path 89.30 - id="path2973" 89.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 " 89.32 - style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none" 89.33 - transform="scale(0.4) translate(10,0)" /> 89.34 - </marker> 89.35 - <marker 89.36 - inkscape:stockid="Arrow1Mend" 89.37 - orient="auto" 89.38 - refY="0.0" 89.39 - refX="0.0" 89.40 - id="Arrow1Mend" 89.41 - style="overflow:visible;"> 89.42 - <path 89.43 - id="path3066" 89.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 " 89.45 - style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;" 89.46 - transform="scale(0.4) rotate(180) translate(10,0)" /> 89.47 - </marker> 89.48 - </defs> 89.49 - <sodipodi:namedview 89.50 - id="base" 89.51 - pagecolor="#ffffff" 89.52 - bordercolor="#666666" 89.53 - borderopacity="1.0" 89.54 - gridtolerance="10000" 89.55 - guidetolerance="10" 89.56 - objecttolerance="10" 89.57 - inkscape:pageopacity="0.0" 89.58 - inkscape:pageshadow="2" 89.59 - inkscape:zoom="1.4" 89.60 - inkscape:cx="232.14286" 89.61 - inkscape:cy="672.75296" 89.62 - inkscape:document-units="px" 89.63 - inkscape:current-layer="layer1" 89.64 - inkscape:window-width="906" 89.65 - inkscape:window-height="620" 89.66 - inkscape:window-x="5" 89.67 - inkscape:window-y="49" /> 89.68 - <metadata 89.69 - id="metadata7"> 89.70 - <rdf:RDF> 89.71 - <cc:Work 89.72 - rdf:about=""> 89.73 - <dc:format>image/svg+xml</dc:format> 89.74 - <dc:type 89.75 - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 89.76 - </cc:Work> 89.77 - </rdf:RDF> 89.78 - </metadata> 89.79 - <g 89.80 - inkscape:label="Layer 1" 89.81 - inkscape:groupmode="layer" 89.82 - id="layer1"> 89.83 - <rect 89.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" 89.85 - id="rect1878" 89.86 - width="94.285713" 89.87 - height="20.714285" 89.88 - x="138" 89.89 - y="479.50504" /> 89.90 - <text 89.91 - xml:space="preserve" 89.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" 89.93 - x="162.09892" 89.94 - y="493.12619" 89.95 - id="text1872"><tspan 89.96 - sodipodi:role="line" 89.97 - id="tspan1874" 89.98 - x="162.09892" 89.99 - y="493.12619" 89.100 - style="font-family:Courier"><tspan 89.101 - style="font-weight:bold" 89.102 - id="tspan1876">0</tspan>: REV0</tspan></text> 89.103 - <rect 89.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" 89.105 - id="rect2800" 89.106 - width="94.285713" 89.107 - height="20.714285" 89.108 - x="138" 89.109 - y="432.63004" /> 89.110 - <text 89.111 - xml:space="preserve" 89.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" 89.113 - x="162.09892" 89.114 - y="446.25119" 89.115 - id="text2794"><tspan 89.116 - sodipodi:role="line" 89.117 - id="tspan2796" 89.118 - x="162.09892" 89.119 - y="446.25119" 89.120 - style="font-family:Courier"><tspan 89.121 - id="tspan2868" 89.122 - style="font-weight:bold">1</tspan>: REV1</tspan></text> 89.123 - <rect 89.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" 89.125 - id="rect2810" 89.126 - width="94.285713" 89.127 - height="20.714285" 89.128 - x="138" 89.129 - y="385.75504" /> 89.130 - <text 89.131 - xml:space="preserve" 89.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" 89.133 - x="162.09892" 89.134 - y="399.37619" 89.135 - id="text2804"><tspan 89.136 - sodipodi:role="line" 89.137 - id="tspan2806" 89.138 - x="162.09892" 89.139 - y="399.37619" 89.140 - style="font-family:Courier"><tspan 89.141 - style="font-weight:bold" 89.142 - id="tspan2866">2</tspan>: REV2</tspan></text> 89.143 - <rect 89.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" 89.145 - id="rect2820" 89.146 - width="94.285713" 89.147 - height="20.714285" 89.148 - x="138" 89.149 - y="338.88007" /> 89.150 - <text 89.151 - xml:space="preserve" 89.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" 89.153 - x="162.09892" 89.154 - y="352.50122" 89.155 - id="text2814"><tspan 89.156 - sodipodi:role="line" 89.157 - id="tspan2816" 89.158 - x="162.09892" 89.159 - y="352.50122" 89.160 - style="font-family:Courier"><tspan 89.161 - style="font-weight:bold" 89.162 - id="tspan2864">3</tspan>: REV3</tspan></text> 89.163 - <rect 89.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" 89.165 - id="rect2830" 89.166 - width="94.285713" 89.167 - height="20.714285" 89.168 - x="138" 89.169 - y="292.00504" /> 89.170 - <text 89.171 - xml:space="preserve" 89.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" 89.173 - x="162.09892" 89.174 - y="305.62619" 89.175 - id="text2824"><tspan 89.176 - sodipodi:role="line" 89.177 - id="tspan2826" 89.178 - x="162.09892" 89.179 - y="305.62619" 89.180 - style="font-family:Courier"><tspan 89.181 - style="font-weight:bold" 89.182 - id="tspan2862">4</tspan>: REV4</tspan></text> 89.183 - <text 89.184 - xml:space="preserve" 89.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" 89.186 - x="173.57143" 89.187 - y="443.79074" 89.188 - id="text2832"><tspan 89.189 - sodipodi:role="line" 89.190 - id="tspan2834" 89.191 - x="173.57143" 89.192 - y="443.79074" /></text> 89.193 - <path 89.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)" 89.195 - d="M 185.14286,478.50504 L 185.14286,454.34432" 89.196 - id="path2894" 89.197 - inkscape:connector-type="polyline" /> 89.198 - <path 89.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)" 89.200 - d="M 185.14286,431.63004 L 185.14286,407.46932" 89.201 - id="path2896" 89.202 - inkscape:connector-type="polyline" /> 89.203 - <path 89.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)" 89.205 - d="M 185.14286,384.75504 L 185.14286,360.59435" 89.206 - id="path2898" 89.207 - inkscape:connector-type="polyline" /> 89.208 - <path 89.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)" 89.210 - d="M 185.14286,337.88007 L 185.14286,313.71932" 89.211 - id="path2900" 89.212 - inkscape:connector-type="polyline" /> 89.213 - <text 89.214 - xml:space="preserve" 89.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" 89.216 - x="244.60992" 89.217 - y="305.245" 89.218 - id="text1902"><tspan 89.219 - sodipodi:role="line" 89.220 - id="tspan1904" 89.221 - x="244.60992" 89.222 - y="305.245">(newest)</tspan></text> 89.223 - <text 89.224 - xml:space="preserve" 89.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" 89.226 - x="244.60992" 89.227 - y="492.745" 89.228 - id="text1906"><tspan 89.229 - sodipodi:role="line" 89.230 - id="tspan1908" 89.231 - x="244.60992" 89.232 - y="492.745">(oldest)</tspan></text> 89.233 - <rect 89.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" 89.235 - id="rect1907" 89.236 - width="94.285713" 89.237 - height="20.714285" 89.238 - x="309.28571" 89.239 - y="324.86218" /> 89.240 - <text 89.241 - xml:space="preserve" 89.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" 89.243 - x="333.38464" 89.244 - y="338.48334" 89.245 - id="text1909"><tspan 89.246 - sodipodi:role="line" 89.247 - id="tspan1911" 89.248 - x="333.38464" 89.249 - y="338.48334" 89.250 - style="font-family:Courier"><tspan 89.251 - style="font-weight:bold" 89.252 - id="tspan1913">4</tspan>: REV4</tspan></text> 89.253 - <path 89.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" 89.255 - d="M 332.14286,375.21932 L 335.71429,347.36218" 89.256 - id="path2802" /> 89.257 - <path 89.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" 89.259 - d="M 372.69968,375.21932 L 369.12825,347.36218" 89.260 - id="path2986" /> 89.261 - <text 89.262 - xml:space="preserve" 89.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" 89.264 - x="335.14285" 89.265 - y="387.21933" 89.266 - id="text2988"><tspan 89.267 - sodipodi:role="line" 89.268 - x="335.14285" 89.269 - y="387.21933" 89.270 - id="tspan3020" 89.271 - style="text-align:end;text-anchor:end">revision</tspan><tspan 89.272 - sodipodi:role="line" 89.273 - x="335.14285" 89.274 - y="402.21933" 89.275 - id="tspan3014" 89.276 - style="text-align:end;text-anchor:end">number</tspan></text> 89.277 - <text 89.278 - xml:space="preserve" 89.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" 89.280 - x="368.71429" 89.281 - y="387.21933" 89.282 - id="text2994"><tspan 89.283 - sodipodi:role="line" 89.284 - id="tspan2996" 89.285 - x="368.71429" 89.286 - y="387.21933">changeset</tspan><tspan 89.287 - sodipodi:role="line" 89.288 - x="368.71429" 89.289 - y="402.21933" 89.290 - id="tspan2998">identifier</tspan></text> 89.291 - </g> 89.292 -</svg>
90.1 --- a/fr/tour-merge-conflict.svg Sun Aug 16 03:41:39 2009 +0200 90.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 90.3 @@ -1,210 +0,0 @@ 90.4 -<?xml version="1.0" encoding="UTF-8" standalone="no"?> 90.5 -<!-- Created with Inkscape (http://www.inkscape.org/) --> 90.6 -<svg 90.7 - xmlns:dc="http://purl.org/dc/elements/1.1/" 90.8 - xmlns:cc="http://web.resource.org/cc/" 90.9 - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 90.10 - xmlns:svg="http://www.w3.org/2000/svg" 90.11 - xmlns="http://www.w3.org/2000/svg" 90.12 - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" 90.13 - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" 90.14 - width="744.09448819" 90.15 - height="1052.3622047" 90.16 - id="svg2" 90.17 - sodipodi:version="0.32" 90.18 - inkscape:version="0.44.1" 90.19 - sodipodi:docname="tour-merge-conflict.svg"> 90.20 - <defs 90.21 - id="defs4"> 90.22 - <marker 90.23 - inkscape:stockid="Arrow1Mend" 90.24 - orient="auto" 90.25 - refY="0.0" 90.26 - refX="0.0" 90.27 - id="Arrow1Mend" 90.28 - style="overflow:visible;"> 90.29 - <path 90.30 - id="path3053" 90.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 " 90.32 - style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;" 90.33 - transform="scale(0.4) rotate(180) translate(10,0)" /> 90.34 - </marker> 90.35 - </defs> 90.36 - <sodipodi:namedview 90.37 - id="base" 90.38 - pagecolor="#ffffff" 90.39 - bordercolor="#666666" 90.40 - borderopacity="1.0" 90.41 - gridtolerance="10000" 90.42 - guidetolerance="10" 90.43 - objecttolerance="10" 90.44 - inkscape:pageopacity="0.0" 90.45 - inkscape:pageshadow="2" 90.46 - inkscape:zoom="1.4" 90.47 - inkscape:cx="164.78349" 90.48 - inkscape:cy="590.07679" 90.49 - inkscape:document-units="px" 90.50 - inkscape:current-layer="layer1" 90.51 - inkscape:window-width="906" 90.52 - inkscape:window-height="620" 90.53 - inkscape:window-x="5" 90.54 - inkscape:window-y="49" /> 90.55 - <metadata 90.56 - id="metadata7"> 90.57 - <rdf:RDF> 90.58 - <cc:Work 90.59 - rdf:about=""> 90.60 - <dc:format>image/svg+xml</dc:format> 90.61 - <dc:type 90.62 - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 90.63 - </cc:Work> 90.64 - </rdf:RDF> 90.65 - </metadata> 90.66 - <g 90.67 - inkscape:label="Layer 1" 90.68 - inkscape:groupmode="layer" 90.69 - id="layer1"> 90.70 - <g 90.71 - id="g1988" 90.72 - transform="translate(84.85711,0)"> 90.73 - <g 90.74 - id="g1876"> 90.75 - <path 90.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" 90.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 " 90.78 - id="path1872" 90.79 - sodipodi:nodetypes="cccccc" /> 90.80 - <path 90.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" 90.82 - d="M 191.55484,563.36862 L 191.6923,560.98794 L 192.69126,552.44884 L 203.80416,551.31242" 90.83 - id="path1874" 90.84 - sodipodi:nodetypes="cccc" /> 90.85 - </g> 90.86 - <flowRoot 90.87 - style="font-size:8px;font-family:Times New Roman" 90.88 - id="flowRoot1898" 90.89 - xml:space="preserve"><flowRegion 90.90 - id="flowRegion1900"><rect 90.91 - style="font-size:8px;font-family:Times New Roman" 90.92 - y="464.50504" 90.93 - x="122.85714" 90.94 - height="93.571426" 90.95 - width="76.428574" 90.96 - id="rect1902" /></flowRegion><flowPara 90.97 - id="flowPara1904">Greetings!</flowPara><flowPara 90.98 - id="flowPara1906" /><flowPara 90.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> 90.100 - <g 90.101 - id="g1966" 90.102 - transform="translate(82,0.35715)"> 90.103 - <g 90.104 - transform="translate(-77.85718,-140.0714)" 90.105 - id="g1910"> 90.106 - <path 90.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" 90.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 " 90.109 - id="path1912" 90.110 - sodipodi:nodetypes="cccccc" /> 90.111 - <path 90.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" 90.113 - d="M 191.55484,563.36862 L 191.6923,560.98794 L 192.69126,552.44884 L 203.80416,551.31242" 90.114 - id="path1914" 90.115 - sodipodi:nodetypes="cccc" /> 90.116 - </g> 90.117 - <flowRoot 90.118 - transform="translate(-77.85718,-140.0714)" 90.119 - style="font-size:8px;font-family:Times New Roman" 90.120 - id="flowRoot1916" 90.121 - xml:space="preserve"><flowRegion 90.122 - id="flowRegion1918"><rect 90.123 - style="font-size:8px;font-family:Times New Roman" 90.124 - y="464.50504" 90.125 - x="122.85714" 90.126 - height="93.571426" 90.127 - width="76.428574" 90.128 - id="rect1920" /></flowRegion><flowPara 90.129 - id="flowPara1922">Greetings!</flowPara><flowPara 90.130 - id="flowPara1924" /><flowPara 90.131 - id="flowPara1926">I am <flowSpan 90.132 - style="font-style:italic;fill:red" 90.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> 90.134 - <g 90.135 - id="g1977" 90.136 - transform="translate(81.99999,-0.35715)"> 90.137 - <g 90.138 - transform="translate(83.57141,-139.3571)" 90.139 - id="g1932"> 90.140 - <path 90.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" 90.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 " 90.143 - id="path1934" 90.144 - sodipodi:nodetypes="cccccc" /> 90.145 - <path 90.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" 90.147 - d="M 191.55484,563.36862 L 191.6923,560.98794 L 192.69126,552.44884 L 203.80416,551.31242" 90.148 - id="path1936" 90.149 - sodipodi:nodetypes="cccc" /> 90.150 - </g> 90.151 - <flowRoot 90.152 - transform="translate(83.57141,-139.3571)" 90.153 - style="font-size:8px;font-family:Times New Roman" 90.154 - id="flowRoot1938" 90.155 - xml:space="preserve"><flowRegion 90.156 - id="flowRegion1940"><rect 90.157 - style="font-size:8px;font-family:Times New Roman" 90.158 - y="464.50504" 90.159 - x="122.85714" 90.160 - height="93.571426" 90.161 - width="76.428574" 90.162 - id="rect1942" /></flowRegion><flowPara 90.163 - id="flowPara1944">Greetings!</flowPara><flowPara 90.164 - id="flowPara1946" /><flowPara 90.165 - id="flowPara1948">I am <flowSpan 90.166 - style="font-style:italic;fill:red" 90.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> 90.168 - <path 90.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" 90.170 - d="M 215.502,457.71933 L 196.35507,424.5765" 90.171 - id="path1999" 90.172 - inkscape:connector-type="polyline" 90.173 - inkscape:connection-start="#g1988" 90.174 - inkscape:connection-end="#g1966" /> 90.175 - <path 90.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" 90.177 - d="M 277.06936,457.71933 L 296.21629,424.5765" 90.178 - id="path2001" 90.179 - inkscape:connector-type="polyline" 90.180 - inkscape:connection-start="#g1988" 90.181 - inkscape:connection-end="#g1977" /> 90.182 - <text 90.183 - xml:space="preserve" 90.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" 90.185 - x="302.42859" 90.186 - y="515.08905" 90.187 - id="text1905"><tspan 90.188 - sodipodi:role="line" 90.189 - id="tspan1907" 90.190 - x="302.42859" 90.191 - y="515.08905">Base version</tspan></text> 90.192 - <text 90.193 - xml:space="preserve" 90.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" 90.195 - x="45.57143" 90.196 - y="374.1619" 90.197 - id="text1917"><tspan 90.198 - sodipodi:role="line" 90.199 - id="tspan1919" 90.200 - x="45.57143" 90.201 - y="374.1619">Our changes</tspan></text> 90.202 - <text 90.203 - xml:space="preserve" 90.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" 90.205 - x="385.71429" 90.206 - y="374.1619" 90.207 - id="text1921"><tspan 90.208 - sodipodi:role="line" 90.209 - id="tspan1923" 90.210 - x="385.71429" 90.211 - y="374.1619">Their changes</tspan></text> 90.212 - </g> 90.213 -</svg>
91.1 --- a/fr/tour-merge-merge.svg Sun Aug 16 03:41:39 2009 +0200 91.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 91.3 @@ -1,380 +0,0 @@ 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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" 91.13 - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" 91.14 - width="744.09448819" 91.15 - height="1052.3622047" 91.16 - id="svg2" 91.17 - sodipodi:version="0.32" 91.18 - inkscape:version="0.44.1" 91.19 - sodipodi:docname="tour-merge-merge.svg"> 91.20 - <defs 91.21 - id="defs4"> 91.22 - <marker 91.23 - inkscape:stockid="Arrow1Mstart" 91.24 - orient="auto" 91.25 - refY="0.0" 91.26 - refX="0.0" 91.27 - id="Arrow1Mstart" 91.28 - style="overflow:visible"> 91.29 - <path 91.30 - id="path2973" 91.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 " 91.32 - style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none" 91.33 - transform="scale(0.4) translate(10,0)" /> 91.34 - </marker> 91.35 - <marker 91.36 - inkscape:stockid="Arrow1Mend" 91.37 - orient="auto" 91.38 - refY="0.0" 91.39 - refX="0.0" 91.40 - id="Arrow1Mend" 91.41 - style="overflow:visible;"> 91.42 - <path 91.43 - id="path3066" 91.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 " 91.45 - style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;" 91.46 - transform="scale(0.4) rotate(180) translate(10,0)" /> 91.47 - </marker> 91.48 - </defs> 91.49 - <sodipodi:namedview 91.50 - id="base" 91.51 - pagecolor="#ffffff" 91.52 - bordercolor="#666666" 91.53 - borderopacity="1.0" 91.54 - gridtolerance="10000" 91.55 - guidetolerance="10" 91.56 - objecttolerance="10" 91.57 - inkscape:pageopacity="0.0" 91.58 - inkscape:pageshadow="2" 91.59 - inkscape:zoom="1.4" 91.60 - inkscape:cx="247.53795" 91.61 - inkscape:cy="871.05738" 91.62 - inkscape:document-units="px" 91.63 - inkscape:current-layer="layer1" 91.64 - inkscape:window-width="906" 91.65 - inkscape:window-height="620" 91.66 - inkscape:window-x="38" 91.67 - inkscape:window-y="95" /> 91.68 - <metadata 91.69 - id="metadata7"> 91.70 - <rdf:RDF> 91.71 - <cc:Work 91.72 - rdf:about=""> 91.73 - <dc:format>image/svg+xml</dc:format> 91.74 - <dc:type 91.75 - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 91.76 - </cc:Work> 91.77 - </rdf:RDF> 91.78 - </metadata> 91.79 - <g 91.80 - inkscape:label="Layer 1" 91.81 - inkscape:groupmode="layer" 91.82 - id="layer1"> 91.83 - <rect 91.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" 91.85 - id="rect2995" 91.86 - width="94.285713" 91.87 - height="20.714285" 91.88 - x="532.85718" 91.89 - y="203.0479" /> 91.90 - <text 91.91 - xml:space="preserve" 91.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" 91.93 - x="173.57143" 91.94 - y="443.79074" 91.95 - id="text2832"><tspan 91.96 - sodipodi:role="line" 91.97 - id="tspan2834" 91.98 - x="173.57143" 91.99 - y="443.79074" /></text> 91.100 - <rect 91.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" 91.102 - id="rect2830" 91.103 - width="94.285713" 91.104 - height="20.714285" 91.105 - x="138" 91.106 - y="297.76227" /> 91.107 - <text 91.108 - xml:space="preserve" 91.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" 91.110 - x="162.09892" 91.111 - y="311.38342" 91.112 - id="text2824"><tspan 91.113 - sodipodi:role="line" 91.114 - id="tspan2826" 91.115 - x="162.09892" 91.116 - y="311.38342" 91.117 - style="font-family:Courier"><tspan 91.118 - style="font-weight:bold" 91.119 - id="tspan2862">4</tspan>: REV4</tspan></text> 91.120 - <path 91.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" 91.122 - d="M 185.14286,343.63731 L 185.14286,319.47656" 91.123 - id="path2900" 91.124 - inkscape:connector-type="polyline" /> 91.125 - <rect 91.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" 91.127 - id="rect2863" 91.128 - width="94.285713" 91.129 - height="20.714285" 91.130 - x="91.428574" 91.131 - y="250.47656" /> 91.132 - <text 91.133 - xml:space="preserve" 91.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" 91.135 - x="116.09886" 91.136 - y="264.56592" 91.137 - id="text1965" 91.138 - transform="scale(1.000002,0.999998)"><tspan 91.139 - sodipodi:role="line" 91.140 - id="tspan1967" 91.141 - x="116.09886" 91.142 - y="264.56592" 91.143 - style="font-family:Courier"><tspan 91.144 - style="font-weight:bold" 91.145 - id="tspan1973">5</tspan>: REV_my_new_hello</tspan></text> 91.146 - <path 91.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" 91.148 - d="M 173.95727,296.76228 L 149.75702,272.19085" 91.149 - id="path1971" 91.150 - inkscape:connector-type="polyline" 91.151 - inkscape:connection-end="#rect2863" 91.152 - inkscape:connection-start="#rect2830" /> 91.153 - <rect 91.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" 91.155 - id="rect2911" 91.156 - width="94.285995" 91.157 - height="20.714283" 91.158 - x="186.71414" 91.159 - y="204.40514" /> 91.160 - <text 91.161 - xml:space="preserve" 91.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" 91.163 - x="210.81311" 91.164 - y="218.02673" 91.165 - id="text2913" 91.166 - transform="scale(1.000002,0.999998)"><tspan 91.167 - sodipodi:role="line" 91.168 - id="tspan2915" 91.169 - x="210.81311" 91.170 - y="218.02673" 91.171 - style="font-family:Courier"><tspan 91.172 - id="tspan1966" 91.173 - style="font-weight:bold">6</tspan>: REV6_my_new_hello</tspan></text> 91.174 - <path 91.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" 91.176 - d="M 191.06908,296.76228 L 227.93092,226.11942" 91.177 - id="path2919" 91.178 - inkscape:connector-type="polyline" 91.179 - inkscape:connection-start="#rect2830" /> 91.180 - <text 91.181 - xml:space="preserve" 91.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" 91.183 - x="295.28571" 91.184 - y="217.56711" 91.185 - id="text2871"><tspan 91.186 - sodipodi:role="line" 91.187 - id="tspan2873" 91.188 - x="295.28571" 91.189 - y="217.56711">tip (and head)</tspan></text> 91.190 - <text 91.191 - xml:space="preserve" 91.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" 91.193 - x="76" 91.194 - y="264.91769" 91.195 - id="text2875"><tspan 91.196 - sodipodi:role="line" 91.197 - id="tspan2877" 91.198 - x="76" 91.199 - y="264.91769" 91.200 - style="text-align:end;text-anchor:end">head</tspan></text> 91.201 - <rect 91.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" 91.203 - id="rect1913" 91.204 - width="94.285713" 91.205 - height="20.714285" 91.206 - x="138" 91.207 - y="156.90514" /> 91.208 - <path 91.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" 91.210 - d="M 144.22399,249.47657 L 179.49029,178.61943" 91.211 - id="path1915" 91.212 - inkscape:connector-type="polyline" 91.213 - inkscape:connection-start="#rect2863" 91.214 - inkscape:connection-end="#rect1913" /> 91.215 - <path 91.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" 91.217 - d="M 222.20966,203.40514 L 196.79033,178.61943" 91.218 - id="path1917" 91.219 - inkscape:connector-type="polyline" 91.220 - inkscape:connection-start="#rect2911" 91.221 - inkscape:connection-end="#rect1913" /> 91.222 - <text 91.223 - xml:space="preserve" 91.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" 91.225 - x="166.16823" 91.226 - y="168.52228" 91.227 - id="text2806"><tspan 91.228 - sodipodi:role="line" 91.229 - id="tspan2808" 91.230 - x="166.16823" 91.231 - y="168.52228" 91.232 - style="font-family:Courier">merge</tspan></text> 91.233 - <text 91.234 - xml:space="preserve" 91.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" 91.236 - x="246" 91.237 - y="162.63338" 91.238 - id="text2810"><tspan 91.239 - sodipodi:role="line" 91.240 - id="tspan2812" 91.241 - x="246" 91.242 - y="162.63338">working directory</tspan><tspan 91.243 - sodipodi:role="line" 91.244 - x="246" 91.245 - y="177.63338" 91.246 - id="tspan2814">during merge</tspan></text> 91.247 - <rect 91.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" 91.249 - id="rect2816" 91.250 - width="94.285713" 91.251 - height="20.714285" 91.252 - x="483.14636" 91.253 - y="297.76227" /> 91.254 - <text 91.255 - xml:space="preserve" 91.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" 91.257 - x="507.24527" 91.258 - y="311.38342" 91.259 - id="text2818"><tspan 91.260 - sodipodi:role="line" 91.261 - id="tspan2820" 91.262 - x="507.24527" 91.263 - y="311.38342" 91.264 - style="font-family:Courier"><tspan 91.265 - style="font-weight:bold" 91.266 - id="tspan2822">4</tspan>: REV4</tspan></text> 91.267 - <path 91.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" 91.269 - d="M 530.28921,343.6373 L 530.28921,319.47655" 91.270 - id="path2824" 91.271 - inkscape:connector-type="polyline" /> 91.272 - <rect 91.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" 91.274 - id="rect2826" 91.275 - width="94.285713" 91.276 - height="20.714285" 91.277 - x="436.57492" 91.278 - y="250.47656" /> 91.279 - <text 91.280 - xml:space="preserve" 91.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" 91.282 - x="461.24484" 91.283 - y="264.56613" 91.284 - id="text2828" 91.285 - transform="scale(1.000002,0.999998)"><tspan 91.286 - sodipodi:role="line" 91.287 - id="tspan2830" 91.288 - x="461.24484" 91.289 - y="264.56613" 91.290 - style="font-family:Courier"><tspan 91.291 - style="font-weight:bold" 91.292 - id="tspan2832">5</tspan>: REV_my_new_hello</tspan></text> 91.293 - <path 91.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" 91.295 - d="M 519.10362,296.76227 L 494.90337,272.19084" 91.296 - id="path2834" 91.297 - inkscape:connector-type="polyline" /> 91.298 - <rect 91.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" 91.300 - id="rect2836" 91.301 - width="94.285995" 91.302 - height="20.714283" 91.303 - x="483.14001" 91.304 - y="156.548" /> 91.305 - <text 91.306 - xml:space="preserve" 91.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" 91.308 - x="555.95911" 91.309 - y="218.02698" 91.310 - id="text2838" 91.311 - transform="scale(1.000002,0.999998)"><tspan 91.312 - sodipodi:role="line" 91.313 - id="tspan2840" 91.314 - x="555.95911" 91.315 - y="218.02698" 91.316 - style="font-family:Courier"><tspan 91.317 - id="tspan2842" 91.318 - style="font-weight:bold">6</tspan>: REV6_my_new_hello</tspan></text> 91.319 - <path 91.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" 91.321 - d="M 536.21543,296.76227 L 574.03453,224.76218" 91.322 - id="path2844" 91.323 - inkscape:connector-type="polyline" /> 91.324 - <text 91.325 - xml:space="preserve" 91.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" 91.327 - x="594.43207" 91.328 - y="169.78796" 91.329 - id="text2846"><tspan 91.330 - sodipodi:role="line" 91.331 - id="tspan2848" 91.332 - x="594.43207" 91.333 - y="169.78796">tip</tspan></text> 91.334 - <path 91.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" 91.336 - d="M 489.37034,249.47656 L 524.65575,178.26229" 91.337 - id="path2856" 91.338 - inkscape:connector-type="polyline" 91.339 - inkscape:connection-end="#rect2836" /> 91.340 - <path 91.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" 91.342 - d="M 567.85714,202.0479 L 542.42591,178.26229" 91.343 - id="path2858" 91.344 - inkscape:connector-type="polyline" 91.345 - inkscape:connection-end="#rect2836" 91.346 - inkscape:connection-start="#rect2995" /> 91.347 - <text 91.348 - xml:space="preserve" 91.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" 91.350 - x="504.54507" 91.351 - y="170.39714" 91.352 - id="text2860"><tspan 91.353 - sodipodi:role="line" 91.354 - id="tspan2863" 91.355 - x="504.54507" 91.356 - y="170.39714" 91.357 - style="font-family:Courier"><tspan 91.358 - style="font-weight:bold" 91.359 - id="tspan2997">7</tspan>: REV7_my_new_hello</tspan></text> 91.360 - <text 91.361 - xml:space="preserve" 91.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" 91.363 - x="90.323105" 91.364 - y="120.21933" 91.365 - id="text2929"><tspan 91.366 - sodipodi:role="line" 91.367 - id="tspan2931" 91.368 - x="90.323105" 91.369 - y="120.21933" 91.370 - style="font-weight:bold">Working directory during merge</tspan></text> 91.371 - <text 91.372 - xml:space="preserve" 91.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" 91.374 - x="435.35226" 91.375 - y="120.21933" 91.376 - id="text2937"><tspan 91.377 - sodipodi:role="line" 91.378 - id="tspan2939" 91.379 - x="435.35226" 91.380 - y="120.21933" 91.381 - style="font-weight:bold">Repository after merge committed</tspan></text> 91.382 - </g> 91.383 -</svg>
92.1 --- a/fr/tour-merge-pull.svg Sun Aug 16 03:41:39 2009 +0200 92.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 92.3 @@ -1,288 +0,0 @@ 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="svg2" 92.17 - sodipodi:version="0.32" 92.18 - inkscape:version="0.44.1" 92.19 - sodipodi:docname="tour-merge-pull.svg" 92.20 - sodipodi:docbase="/home/bos/hg/hgbook/en"> 92.21 - <defs 92.22 - id="defs4"> 92.23 - <marker 92.24 - inkscape:stockid="Arrow1Mstart" 92.25 - orient="auto" 92.26 - refY="0.0" 92.27 - refX="0.0" 92.28 - id="Arrow1Mstart" 92.29 - style="overflow:visible"> 92.30 - <path 92.31 - id="path2973" 92.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 " 92.33 - style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none" 92.34 - transform="scale(0.4) translate(10,0)" /> 92.35 - </marker> 92.36 - <marker 92.37 - inkscape:stockid="Arrow1Mend" 92.38 - orient="auto" 92.39 - refY="0.0" 92.40 - refX="0.0" 92.41 - id="Arrow1Mend" 92.42 - style="overflow:visible;"> 92.43 - <path 92.44 - id="path3066" 92.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 " 92.46 - style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;" 92.47 - transform="scale(0.4) rotate(180) translate(10,0)" /> 92.48 - </marker> 92.49 - </defs> 92.50 - <sodipodi:namedview 92.51 - id="base" 92.52 - pagecolor="#ffffff" 92.53 - bordercolor="#666666" 92.54 - borderopacity="1.0" 92.55 - gridtolerance="10000" 92.56 - guidetolerance="10" 92.57 - objecttolerance="10" 92.58 - inkscape:pageopacity="0.0" 92.59 - inkscape:pageshadow="2" 92.60 - inkscape:zoom="1.4" 92.61 - inkscape:cx="233.63208" 92.62 - inkscape:cy="832.54381" 92.63 - inkscape:document-units="px" 92.64 - inkscape:current-layer="layer1" 92.65 - inkscape:window-width="906" 92.66 - inkscape:window-height="620" 92.67 - inkscape:window-x="237" 92.68 - inkscape:window-y="103" /> 92.69 - <metadata 92.70 - id="metadata7"> 92.71 - <rdf:RDF> 92.72 - <cc:Work 92.73 - rdf:about=""> 92.74 - <dc:format>image/svg+xml</dc:format> 92.75 - <dc:type 92.76 - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 92.77 - </cc:Work> 92.78 - </rdf:RDF> 92.79 - </metadata> 92.80 - <g 92.81 - inkscape:label="Layer 1" 92.82 - inkscape:groupmode="layer" 92.83 - id="layer1"> 92.84 - <text 92.85 - xml:space="preserve" 92.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" 92.87 - x="173.57143" 92.88 - y="443.79074" 92.89 - id="text2832"><tspan 92.90 - sodipodi:role="line" 92.91 - id="tspan2834" 92.92 - x="173.57143" 92.93 - y="443.79074" /></text> 92.94 - <rect 92.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" 92.96 - id="rect1878" 92.97 - width="94.285713" 92.98 - height="20.714285" 92.99 - x="138" 92.100 - y="479.50504" /> 92.101 - <text 92.102 - xml:space="preserve" 92.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" 92.104 - x="162.09892" 92.105 - y="493.12619" 92.106 - id="text1872"><tspan 92.107 - sodipodi:role="line" 92.108 - id="tspan1874" 92.109 - x="162.09892" 92.110 - y="493.12619" 92.111 - style="font-family:Courier"><tspan 92.112 - style="font-weight:bold" 92.113 - id="tspan1876">0</tspan>: REV0</tspan></text> 92.114 - <rect 92.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" 92.116 - id="rect2800" 92.117 - width="94.285713" 92.118 - height="20.714285" 92.119 - x="138" 92.120 - y="432.63004" /> 92.121 - <text 92.122 - xml:space="preserve" 92.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" 92.124 - x="162.09892" 92.125 - y="446.25119" 92.126 - id="text2794"><tspan 92.127 - sodipodi:role="line" 92.128 - id="tspan2796" 92.129 - x="162.09892" 92.130 - y="446.25119" 92.131 - style="font-family:Courier"><tspan 92.132 - id="tspan2868" 92.133 - style="font-weight:bold">1</tspan>: REV1</tspan></text> 92.134 - <rect 92.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" 92.136 - id="rect2810" 92.137 - width="94.285713" 92.138 - height="20.714285" 92.139 - x="138" 92.140 - y="385.75504" /> 92.141 - <text 92.142 - xml:space="preserve" 92.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" 92.144 - x="162.09892" 92.145 - y="399.37619" 92.146 - id="text2804"><tspan 92.147 - sodipodi:role="line" 92.148 - id="tspan2806" 92.149 - x="162.09892" 92.150 - y="399.37619" 92.151 - style="font-family:Courier"><tspan 92.152 - style="font-weight:bold" 92.153 - id="tspan2866">2</tspan>: REV2</tspan></text> 92.154 - <rect 92.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" 92.156 - id="rect2820" 92.157 - width="94.285713" 92.158 - height="20.714285" 92.159 - x="138" 92.160 - y="338.88007" /> 92.161 - <text 92.162 - xml:space="preserve" 92.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" 92.164 - x="162.09892" 92.165 - y="352.50122" 92.166 - id="text2814"><tspan 92.167 - sodipodi:role="line" 92.168 - id="tspan2816" 92.169 - x="162.09892" 92.170 - y="352.50122" 92.171 - style="font-family:Courier"><tspan 92.172 - style="font-weight:bold" 92.173 - id="tspan2864">3</tspan>: REV3</tspan></text> 92.174 - <rect 92.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" 92.176 - id="rect2830" 92.177 - width="94.285713" 92.178 - height="20.714285" 92.179 - x="138" 92.180 - y="292.00504" /> 92.181 - <text 92.182 - xml:space="preserve" 92.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" 92.184 - x="162.09892" 92.185 - y="305.62619" 92.186 - id="text2824"><tspan 92.187 - sodipodi:role="line" 92.188 - id="tspan2826" 92.189 - x="162.09892" 92.190 - y="305.62619" 92.191 - style="font-family:Courier"><tspan 92.192 - style="font-weight:bold" 92.193 - id="tspan2862">4</tspan>: REV4</tspan></text> 92.194 - <path 92.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" 92.196 - d="M 185.14286,478.50504 L 185.14286,454.34432" 92.197 - id="path2894" 92.198 - inkscape:connector-type="polyline" /> 92.199 - <path 92.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" 92.201 - d="M 185.14286,431.63004 L 185.14286,407.46932" 92.202 - id="path2896" 92.203 - inkscape:connector-type="polyline" /> 92.204 - <path 92.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" 92.206 - d="M 185.14286,384.75504 L 185.14286,360.59435" 92.207 - id="path2898" 92.208 - inkscape:connector-type="polyline" /> 92.209 - <path 92.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" 92.211 - d="M 185.14286,337.88007 L 185.14286,313.71932" 92.212 - id="path2900" 92.213 - inkscape:connector-type="polyline" /> 92.214 - <rect 92.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" 92.216 - id="rect2863" 92.217 - width="94.285713" 92.218 - height="20.714285" 92.219 - x="91.428574" 92.220 - y="244.71933" /> 92.221 - <text 92.222 - xml:space="preserve" 92.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" 92.224 - x="116.09886" 92.225 - y="258.80865" 92.226 - id="text1965" 92.227 - transform="scale(1.000002,0.999998)"><tspan 92.228 - sodipodi:role="line" 92.229 - id="tspan1967" 92.230 - x="116.09886" 92.231 - y="258.80865" 92.232 - style="font-family:Courier"><tspan 92.233 - style="font-weight:bold" 92.234 - id="tspan1973">5</tspan>: REV_my_new_hello</tspan></text> 92.235 - <path 92.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" 92.237 - d="M 173.95727,291.00504 L 149.75702,266.43361" 92.238 - id="path1971" 92.239 - inkscape:connector-type="polyline" 92.240 - inkscape:connection-end="#rect2863" 92.241 - inkscape:connection-start="#rect2830" /> 92.242 - <rect 92.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" 92.244 - id="rect2911" 92.245 - width="94.285995" 92.246 - height="20.714283" 92.247 - x="186.71414" 92.248 - y="198.6479" /> 92.249 - <text 92.250 - xml:space="preserve" 92.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" 92.252 - x="210.81311" 92.253 - y="212.26949" 92.254 - id="text2913" 92.255 - transform="scale(1.000002,0.999998)"><tspan 92.256 - sodipodi:role="line" 92.257 - id="tspan2915" 92.258 - x="210.81311" 92.259 - y="212.26949" 92.260 - style="font-family:Courier"><tspan 92.261 - id="tspan1966" 92.262 - style="font-weight:bold">6</tspan>: REV6_my_new_hello</tspan></text> 92.263 - <path 92.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" 92.265 - d="M 191.06908,291.00504 L 227.93092,220.36218" 92.266 - id="path2919" 92.267 - inkscape:connector-type="polyline" 92.268 - inkscape:connection-start="#rect2830" /> 92.269 - <text 92.270 - xml:space="preserve" 92.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" 92.272 - x="295.28571" 92.273 - y="211.80988" 92.274 - id="text2871"><tspan 92.275 - sodipodi:role="line" 92.276 - id="tspan2873" 92.277 - x="295.28571" 92.278 - y="211.80988">tip (and head)</tspan></text> 92.279 - <text 92.280 - xml:space="preserve" 92.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" 92.282 - x="76" 92.283 - y="259.16046" 92.284 - id="text2875"><tspan 92.285 - sodipodi:role="line" 92.286 - id="tspan2877" 92.287 - x="76" 92.288 - y="259.16046" 92.289 - style="text-align:end;text-anchor:end">head</tspan></text> 92.290 - </g> 92.291 -</svg>
93.1 --- a/fr/tour-merge-sep-repos.svg Sun Aug 16 03:41:39 2009 +0200 93.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 93.3 @@ -1,466 +0,0 @@ 93.4 -<?xml version="1.0" encoding="UTF-8" standalone="no"?> 93.5 -<!-- Created with Inkscape (http://www.inkscape.org/) --> 93.6 -<svg 93.7 - xmlns:dc="http://purl.org/dc/elements/1.1/" 93.8 - xmlns:cc="http://web.resource.org/cc/" 93.9 - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 93.10 - xmlns:svg="http://www.w3.org/2000/svg" 93.11 - xmlns="http://www.w3.org/2000/svg" 93.12 - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" 93.13 - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" 93.14 - width="744.09448819" 93.15 - height="1052.3622047" 93.16 - id="svg2" 93.17 - sodipodi:version="0.32" 93.18 - inkscape:version="0.44.1" 93.19 - sodipodi:docname="tour-merge-sep-repos.svg"> 93.20 - <defs 93.21 - id="defs4"> 93.22 - <marker 93.23 - inkscape:stockid="Arrow1Mstart" 93.24 - orient="auto" 93.25 - refY="0.0" 93.26 - refX="0.0" 93.27 - id="Arrow1Mstart" 93.28 - style="overflow:visible"> 93.29 - <path 93.30 - id="path2973" 93.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 " 93.32 - style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none" 93.33 - transform="scale(0.4) translate(10,0)" /> 93.34 - </marker> 93.35 - <marker 93.36 - inkscape:stockid="Arrow1Mend" 93.37 - orient="auto" 93.38 - refY="0.0" 93.39 - refX="0.0" 93.40 - id="Arrow1Mend" 93.41 - style="overflow:visible;"> 93.42 - <path 93.43 - id="path3066" 93.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 " 93.45 - style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;" 93.46 - transform="scale(0.4) rotate(180) translate(10,0)" /> 93.47 - </marker> 93.48 - </defs> 93.49 - <sodipodi:namedview 93.50 - id="base" 93.51 - pagecolor="#ffffff" 93.52 - bordercolor="#666666" 93.53 - borderopacity="1.0" 93.54 - gridtolerance="10000" 93.55 - guidetolerance="10" 93.56 - objecttolerance="10" 93.57 - inkscape:pageopacity="0.0" 93.58 - inkscape:pageshadow="2" 93.59 - inkscape:zoom="1.4" 93.60 - inkscape:cx="307.20351" 93.61 - inkscape:cy="716.87911" 93.62 - inkscape:document-units="px" 93.63 - inkscape:current-layer="layer1" 93.64 - inkscape:window-width="906" 93.65 - inkscape:window-height="620" 93.66 - inkscape:window-x="5" 93.67 - inkscape:window-y="49" /> 93.68 - <metadata 93.69 - id="metadata7"> 93.70 - <rdf:RDF> 93.71 - <cc:Work 93.72 - rdf:about=""> 93.73 - <dc:format>image/svg+xml</dc:format> 93.74 - <dc:type 93.75 - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 93.76 - </cc:Work> 93.77 - </rdf:RDF> 93.78 - </metadata> 93.79 - <g 93.80 - inkscape:label="Layer 1" 93.81 - inkscape:groupmode="layer" 93.82 - id="layer1"> 93.83 - <text 93.84 - xml:space="preserve" 93.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" 93.86 - x="173.57143" 93.87 - y="443.79074" 93.88 - id="text2832"><tspan 93.89 - sodipodi:role="line" 93.90 - id="tspan2834" 93.91 - x="173.57143" 93.92 - y="443.79074" /></text> 93.93 - <rect 93.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" 93.95 - id="rect1878" 93.96 - width="94.285713" 93.97 - height="20.714285" 93.98 - x="138" 93.99 - y="479.50504" /> 93.100 - <text 93.101 - xml:space="preserve" 93.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" 93.103 - x="162.09892" 93.104 - y="493.12619" 93.105 - id="text1872"><tspan 93.106 - sodipodi:role="line" 93.107 - id="tspan1874" 93.108 - x="162.09892" 93.109 - y="493.12619" 93.110 - style="font-family:Courier"><tspan 93.111 - style="font-weight:bold" 93.112 - id="tspan1876">0</tspan>: REV0</tspan></text> 93.113 - <rect 93.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" 93.115 - id="rect2800" 93.116 - width="94.285713" 93.117 - height="20.714285" 93.118 - x="138" 93.119 - y="432.63004" /> 93.120 - <text 93.121 - xml:space="preserve" 93.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" 93.123 - x="162.09892" 93.124 - y="446.25119" 93.125 - id="text2794"><tspan 93.126 - sodipodi:role="line" 93.127 - id="tspan2796" 93.128 - x="162.09892" 93.129 - y="446.25119" 93.130 - style="font-family:Courier"><tspan 93.131 - id="tspan2868" 93.132 - style="font-weight:bold">1</tspan>: REV1</tspan></text> 93.133 - <rect 93.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" 93.135 - id="rect2810" 93.136 - width="94.285713" 93.137 - height="20.714285" 93.138 - x="138" 93.139 - y="385.75504" /> 93.140 - <text 93.141 - xml:space="preserve" 93.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" 93.143 - x="162.09892" 93.144 - y="399.37619" 93.145 - id="text2804"><tspan 93.146 - sodipodi:role="line" 93.147 - id="tspan2806" 93.148 - x="162.09892" 93.149 - y="399.37619" 93.150 - style="font-family:Courier"><tspan 93.151 - style="font-weight:bold" 93.152 - id="tspan2866">2</tspan>: REV2</tspan></text> 93.153 - <rect 93.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" 93.155 - id="rect2820" 93.156 - width="94.285713" 93.157 - height="20.714285" 93.158 - x="138" 93.159 - y="338.88007" /> 93.160 - <text 93.161 - xml:space="preserve" 93.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" 93.163 - x="162.09892" 93.164 - y="352.50122" 93.165 - id="text2814"><tspan 93.166 - sodipodi:role="line" 93.167 - id="tspan2816" 93.168 - x="162.09892" 93.169 - y="352.50122" 93.170 - style="font-family:Courier"><tspan 93.171 - style="font-weight:bold" 93.172 - id="tspan2864">3</tspan>: REV3</tspan></text> 93.173 - <rect 93.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" 93.175 - id="rect2830" 93.176 - width="94.285713" 93.177 - height="20.714285" 93.178 - x="138" 93.179 - y="292.00504" /> 93.180 - <text 93.181 - xml:space="preserve" 93.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" 93.183 - x="162.09892" 93.184 - y="305.62619" 93.185 - id="text2824"><tspan 93.186 - sodipodi:role="line" 93.187 - id="tspan2826" 93.188 - x="162.09892" 93.189 - y="305.62619" 93.190 - style="font-family:Courier"><tspan 93.191 - style="font-weight:bold" 93.192 - id="tspan2862">4</tspan>: REV4</tspan></text> 93.193 - <path 93.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" 93.195 - d="M 185.14286,478.50504 L 185.14286,454.34432" 93.196 - id="path2894" 93.197 - inkscape:connector-type="polyline" /> 93.198 - <path 93.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" 93.200 - d="M 185.14286,431.63004 L 185.14286,407.46932" 93.201 - id="path2896" 93.202 - inkscape:connector-type="polyline" /> 93.203 - <path 93.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" 93.205 - d="M 185.14286,384.75504 L 185.14286,360.59435" 93.206 - id="path2898" 93.207 - inkscape:connector-type="polyline" /> 93.208 - <path 93.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" 93.210 - d="M 185.14286,337.88007 L 185.14286,313.71932" 93.211 - id="path2900" 93.212 - inkscape:connector-type="polyline" /> 93.213 - <rect 93.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" 93.215 - id="rect1963" 93.216 - width="94.285995" 93.217 - height="20.714283" 93.218 - x="138" 93.219 - y="245.18723" /> 93.220 - <text 93.221 - xml:space="preserve" 93.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" 93.223 - x="162.09877" 93.224 - y="258.80865" 93.225 - id="text1965" 93.226 - transform="scale(1.000002,0.999998)"><tspan 93.227 - sodipodi:role="line" 93.228 - id="tspan1967" 93.229 - x="162.09877" 93.230 - y="258.80865" 93.231 - style="font-family:Courier"><tspan 93.232 - style="font-weight:bold" 93.233 - id="tspan1973">5</tspan>: REV_my_hello</tspan></text> 93.234 - <path 93.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" 93.236 - d="M 185.143,291.06218 L 185.143,266.90143" 93.237 - id="path1971" 93.238 - inkscape:connector-type="polyline" /> 93.239 - <text 93.240 - xml:space="preserve" 93.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" 93.242 - x="136.90039" 93.243 - y="232.25546" 93.244 - id="text2921"><tspan 93.245 - sodipodi:role="line" 93.246 - id="tspan2923" 93.247 - x="136.90039" 93.248 - y="232.25546">my-hello</tspan></text> 93.249 - <rect 93.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" 93.251 - id="rect2863" 93.252 - width="94.285713" 93.253 - height="20.714285" 93.254 - x="370.71414" 93.255 - y="479.49289" /> 93.256 - <text 93.257 - xml:space="preserve" 93.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" 93.259 - x="394.81305" 93.260 - y="493.11404" 93.261 - id="text2865"><tspan 93.262 - sodipodi:role="line" 93.263 - id="tspan2867" 93.264 - x="394.81305" 93.265 - y="493.11404" 93.266 - style="font-family:Courier"><tspan 93.267 - style="font-weight:bold" 93.268 - id="tspan2869">0</tspan>: REV0</tspan></text> 93.269 - <rect 93.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" 93.271 - id="rect2871" 93.272 - width="94.285713" 93.273 - height="20.714285" 93.274 - x="370.71414" 93.275 - y="432.61789" /> 93.276 - <text 93.277 - xml:space="preserve" 93.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" 93.279 - x="394.81305" 93.280 - y="446.23904" 93.281 - id="text2873"><tspan 93.282 - sodipodi:role="line" 93.283 - id="tspan2875" 93.284 - x="394.81305" 93.285 - y="446.23904" 93.286 - style="font-family:Courier"><tspan 93.287 - id="tspan2877" 93.288 - style="font-weight:bold">1</tspan>: REV1</tspan></text> 93.289 - <rect 93.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" 93.291 - id="rect2879" 93.292 - width="94.285713" 93.293 - height="20.714285" 93.294 - x="370.71414" 93.295 - y="385.74289" /> 93.296 - <text 93.297 - xml:space="preserve" 93.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" 93.299 - x="394.81305" 93.300 - y="399.36404" 93.301 - id="text2881"><tspan 93.302 - sodipodi:role="line" 93.303 - id="tspan2883" 93.304 - x="394.81305" 93.305 - y="399.36404" 93.306 - style="font-family:Courier"><tspan 93.307 - style="font-weight:bold" 93.308 - id="tspan2885">2</tspan>: REV2</tspan></text> 93.309 - <rect 93.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" 93.311 - id="rect2887" 93.312 - width="94.285713" 93.313 - height="20.714285" 93.314 - x="370.71414" 93.315 - y="338.86792" /> 93.316 - <text 93.317 - xml:space="preserve" 93.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" 93.319 - x="394.81305" 93.320 - y="352.48907" 93.321 - id="text2889"><tspan 93.322 - sodipodi:role="line" 93.323 - id="tspan2891" 93.324 - x="394.81305" 93.325 - y="352.48907" 93.326 - style="font-family:Courier"><tspan 93.327 - style="font-weight:bold" 93.328 - id="tspan2893">3</tspan>: REV3</tspan></text> 93.329 - <rect 93.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" 93.331 - id="rect2895" 93.332 - width="94.285713" 93.333 - height="20.714285" 93.334 - x="370.71414" 93.335 - y="291.99289" /> 93.336 - <text 93.337 - xml:space="preserve" 93.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" 93.339 - x="394.81305" 93.340 - y="305.61404" 93.341 - id="text2897"><tspan 93.342 - sodipodi:role="line" 93.343 - id="tspan2899" 93.344 - x="394.81305" 93.345 - y="305.61404" 93.346 - style="font-family:Courier"><tspan 93.347 - style="font-weight:bold" 93.348 - id="tspan2901">4</tspan>: REV4</tspan></text> 93.349 - <path 93.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" 93.351 - d="M 417.85701,478.4929 L 417.85701,454.33218" 93.352 - id="path2903" 93.353 - inkscape:connector-type="polyline" /> 93.354 - <path 93.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" 93.356 - d="M 417.85701,431.6179 L 417.85701,407.45718" 93.357 - id="path2905" 93.358 - inkscape:connector-type="polyline" /> 93.359 - <path 93.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" 93.361 - d="M 417.85701,384.7429 L 417.85701,360.58221" 93.362 - id="path2907" 93.363 - inkscape:connector-type="polyline" /> 93.364 - <path 93.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" 93.366 - d="M 417.85701,337.86793 L 417.85701,313.70718" 93.367 - id="path2909" 93.368 - inkscape:connector-type="polyline" /> 93.369 - <rect 93.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" 93.371 - id="rect2911" 93.372 - width="94.285995" 93.373 - height="20.714283" 93.374 - x="370.71414" 93.375 - y="245.17511" /> 93.376 - <text 93.377 - xml:space="preserve" 93.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" 93.379 - x="394.81274" 93.380 - y="258.79678" 93.381 - id="text2913" 93.382 - transform="scale(1.000002,0.999998)"><tspan 93.383 - sodipodi:role="line" 93.384 - id="tspan2915" 93.385 - x="394.81274" 93.386 - y="258.79678" 93.387 - style="font-family:Courier"><tspan 93.388 - style="font-weight:bold" 93.389 - id="tspan2917">5</tspan>: REV_my_new_hello</tspan></text> 93.390 - <path 93.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" 93.392 - d="M 417.85715,291.05004 L 417.85715,266.88929" 93.393 - id="path2919" 93.394 - inkscape:connector-type="polyline" /> 93.395 - <text 93.396 - xml:space="preserve" 93.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" 93.398 - x="369.61453" 93.399 - y="232.25546" 93.400 - id="text2925"><tspan 93.401 - sodipodi:role="line" 93.402 - id="tspan2927" 93.403 - x="369.61453" 93.404 - y="232.25546">my-new-hello</tspan></text> 93.405 - <text 93.406 - xml:space="preserve" 93.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" 93.408 - x="300.54352" 93.409 - y="252.12723" 93.410 - id="text2933"><tspan 93.411 - sodipodi:role="line" 93.412 - id="tspan2935" 93.413 - x="300.54352" 93.414 - y="252.12723" 93.415 - style="text-align:center;text-anchor:middle">newest changes</tspan><tspan 93.416 - sodipodi:role="line" 93.417 - x="300.54352" 93.418 - y="267.12723" 93.419 - style="text-align:center;text-anchor:middle" 93.420 - id="tspan3132">differ</tspan></text> 93.421 - <text 93.422 - xml:space="preserve" 93.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" 93.424 - x="262.15436" 93.425 - y="398.37112" 93.426 - id="text2929"><tspan 93.427 - sodipodi:role="line" 93.428 - x="262.15436" 93.429 - y="398.37112" 93.430 - id="tspan3013" 93.431 - style="text-align:start;text-anchor:start">common history</tspan></text> 93.432 - <g 93.433 - id="g3107" 93.434 - transform="translate(0,0.855744)"> 93.435 - <path 93.436 - id="path3101" 93.437 - d="M 300.35713,381.29075 L 300.35713,304.50504" 93.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" /> 93.439 - <path 93.440 - id="path3105" 93.441 - d="M 291.07142,301.64789 L 309.28571,301.64789" 93.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" /> 93.443 - </g> 93.444 - <path 93.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" 93.446 - d="M 300.53571,486.38926 L 300.53571,409.60355" 93.447 - id="path3113" /> 93.448 - <path 93.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" 93.450 - d="M 291.25,488.49641 L 309.46429,488.49641" 93.451 - id="path3115" /> 93.452 - <text 93.453 - xml:space="preserve" 93.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" 93.455 - x="480.71429" 93.456 - y="250.91507" 93.457 - id="text1949"><tspan 93.458 - sodipodi:role="line" 93.459 - id="tspan1951" 93.460 - x="480.71429" 93.461 - y="250.91507" 93.462 - style="text-align:start;text-anchor:start">head revision</tspan><tspan 93.463 - sodipodi:role="line" 93.464 - x="480.71429" 93.465 - y="265.91507" 93.466 - id="tspan1953" 93.467 - style="text-align:start;text-anchor:start">(has no children)</tspan></text> 93.468 - </g> 93.469 -</svg>
94.1 --- a/fr/tour-merge.tex Sun Aug 16 03:41:39 2009 +0200 94.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 94.3 @@ -1,319 +0,0 @@ 94.4 -\chapter{Un rapide tour de Mercurial: fusionner les travaux} 94.5 -\label{chap:tour-merge} 94.6 - 94.7 -Nous avons maintenant étudié comment cloner un dépôt, effectuer 94.8 -des changements dedans, et récupérer ou transférer depuis un 94.9 -autre dépôt. La prochaine étape est donc de \emph{fusionner} les 94.10 -modifications de différents dépôts. 94.11 - 94.12 -\section{Fusionner différents travaux} %%%TODO: better translation 94.13 - %%% for 'Merging streams of work' ? 94.14 -La fusion\footnote{NdT: Je garde fusion mais le jargon professionnel 94.15 -emploiera généralement le terme \textit{merge}.} est un aspect 94.16 -fondamental lorsqu'on travaille avec un gestionnaire de source 94.17 -distribué. 94.18 -\begin{itemize} 94.19 -\item Alice et Bob ont chacun une copie personnelle du dépôt d'un 94.20 - projet sur lequel ils collaborent. Alice corrige un \textit{bug} 94.21 - dans son dépôt, et Bob ajoute une nouvelle fonctionnalité dans le 94.22 - sien. Ils veulent un dépôt partagé avec à la fois le correctif du 94.23 - \textit{bug} et la nouvelle fonctionnalité. 94.24 -\item Je travaille régulièrement sur plusieurs tâches différentes sur 94.25 - un seul projet en même temps, chacun isolé dans son propre dépôt. 94.26 - Travailler ainsi signifie que je dois régulièrement fusionner une 94.27 - partie de mon code avec celui des autres. 94.28 -\end{itemize} 94.29 - 94.30 -Parce que la fusion est une opération si commune à réaliser, 94.31 -Mercurial la rend facile. Étudions ensemble le déroulement des opérations. 94.32 -Nous commencerons encore par faire un clone d'un autre dépôt (vous voyez 94.33 -que l'on fait ça tout le temps ?) puis nous ferons quelques modifications 94.34 -dessus. 94.35 -\interaction{tour.merge.clone} 94.36 -Nous devrions avoir maintenant deux copies de \filename{hello.c} avec 94.37 -des contenus différents. Les historiques de ces deux dépôts ont aussi 94.38 -divergés, comme illustré dans la figure~\ref{fig:tour-merge:sep-repos}. 94.39 - 94.40 -\interaction{tour.merge.cat} 94.41 - 94.42 -\begin{figure}[ht] 94.43 - \centering 94.44 - \grafix{tour-merge-sep-repos} 94.45 - \caption{Historiques récent divergents des dépôts \dirname{my-hello} 94.46 - et \dirname{my-new-hello}} 94.47 - \label{fig:tour-merge:sep-repos} 94.48 -\end{figure} 94.49 - 94.50 -Nous savons déjà que récupérer les modifications depuis notre dépôt 94.51 -\dirname{my-hello} n'aura aucun effet sur l'espace de travail. 94.52 - 94.53 -\interaction{tour.merge.pull} 94.54 - 94.55 -Néanmoins, la commande \hgcmd{pull} nous indique quelque chose au 94.56 -sujet des ``heads''. 94.57 - 94.58 -\subsection{\textit{Head changesets}} %%%TODO: Hard (too?) to translate 94.59 - 94.60 -Une \textit{head}\footnote{NdT: Je garde \textit{head} que j'accorde 94.61 -au féminin comme la coutume orale l'a imposé.} est un \textit{changeset} 94.62 -sans descendants, ou enfants, comme on les désigne parfois. La révision 94.63 -\textit{tip} est une \textit{head}, car la dernière révision dans un dépôt 94.64 -n'a aucun enfant, mais il est important de noter qu'un dépôt peut contenir 94.65 -plus d'une \textit{head}. 94.66 - 94.67 -\begin{figure}[ht] 94.68 - \centering 94.69 - \grafix{tour-merge-pull} 94.70 - \caption{Contenu d'un dépôt après avoir transféré le contenu du dépôt 94.71 - \dirname{my-hello} dans le dépôt \dirname{my-new-hello}} 94.72 - \label{fig:tour-merge:pull} 94.73 -\end{figure} 94.74 - 94.75 -Dans la figure~\ref{fig:tour-merge:pull}, vous pouvez constater l'effet 94.76 -d'un \textit{pull} depuis le dépôt \dirname{my-hello} dans le dépôt 94.77 -\dirname{my-new-hello}. L'historique qui était déjà présent dans le dépôt 94.78 -\dirname{my-new-hello} reste intact, mais une nouvelle révision a été 94.79 -ajoutée. En vous reportant à la figure~\ref{fig:tour-merge:sep-repos}, 94.80 -vous pouvez voir que le \textit{\emph{changeset ID}} reste le même dans 94.81 -le nouveau dépôt, mais que le \emph{numéro de révision} reste le même. 94.82 -(Ceci est un parfait exemple de pourquoi il n'est fiable d'utiliser les 94.83 -numéros de révision lorsque l'on discute d'un \textit{changeset}.) Vous 94.84 -pouvez voir les \texit{heads} présentes dans le dépôt en utilisant la 94.85 -commande \hgcmd{heads}. 94.86 -\interaction{tour.merge.heads} 94.87 - 94.88 -\subsection{Effectuer la fusion} 94.89 - 94.90 -Que se passe-t-il quand vous essayez d'utiliser la commande \hgcmd{update} 94.91 -pour mettre à jour votre espace de travail au nouveau \textit{tip}. 94.92 -\interaction{tour.merge.update} 94.93 -Mercurial nous prévient que la commande \hgcmd{update} n'effectuera pas 94.94 -la fusion, il ne veut pas mettre à jour l'espace de travail quand il 94.95 -estime que nous pourrions avoir besoin d'une fusion, à moins de lui 94.96 -forcer la main. À la place, il faut utiliser la commande \hgcmd{merge} 94.97 -pour fusionner les deux \textit{heads}. 94.98 -\interaction{tour.merge.merge} 94.99 - 94.100 -\begin{figure}[ht] 94.101 - \centering 94.102 - \grafix{tour-merge-merge} 94.103 - \caption{Espace de travail et dépôt lors d'une fusion, et dans le 94.104 - \textit{commit} qui suit.} 94.105 - \label{fig:tour-merge:merge} 94.106 -\end{figure} 94.107 - 94.108 -Ceci met à jour l'espace de travail de manière à ce qu'il contienne 94.109 -les modifications des \emph{deux} \textit{heads}, ce qui apparaît dans 94.110 -les sorties de la commande \hgcmd{parents} et le contenu de 94.111 -\filename{hello.c}. 94.112 -\interaction{tour.merge.parents} 94.113 - 94.114 -\subsection{Effectuer le \textit{commit} du résultat de la fusion} 94.115 - 94.116 -Dès l'instant où vous avez effectué une fusion, \hgcmd{parents} vous 94.117 -affichera deux parents, avant que vous n'exécutiez la commande 94.118 -\hgcmd{commit} sur le résultat de la fusion. 94.119 -\interaction{tour.merge.commit} 94.120 -Nous avons maintenant un nouveau \textit{tip}, remarquer qu'il contient 94.121 -\emph{à la fois} nos anciennes \textit{heads} et leurs parents. Ce sont 94.122 -les mêmes révisions que nous avions affichées avec la commande 94.123 -\hgcmd{parents}. 94.124 - 94.125 -\interaction{tour.merge.tip} 94.126 -Dans la figure~\ref{fig:tour-merge:merge}, vous pouvez voir une représentation 94.127 -de ce qui se passe dans l'espace de travail pendant la fusion, et comment ceci 94.128 -affecte le dépôt lors du \textit{commit}. Pendant la fusion, l'espace de travail, 94.129 -qui a deux \texit{changesets} comme parents, voit ces derniers devenir le parent 94.130 -%%% TODO: le parent ou "les parents" : plus logique mais si il reste seulement 94.131 -%%% un changeset, alors c'est effectivement un parent (le changeset est hermaphrodite) 94.132 -d'un nouveau \textit{changeset}. 94.133 - 94.134 -\section{Fusionner les modifications en conflit} 94.135 - 94.136 -La plupart des fusions sont assez simple à réaliser, mais parfois 94.137 -vous vous retrouverez à fusionner des fichiers où la modification touche 94.138 -la même portion de code, au sein d'un même fichier. À moins que ces 94.139 -modification ne soient identiques, ceci aboutira à un \emph{conflit}, 94.140 -et vous devrez décider comment réconcilier les différentes modifications 94.141 -dans un tout cohérent. 94.142 - 94.143 -\begin{figure}[ht] 94.144 - \centering 94.145 - \grafix{tour-merge-conflict} 94.146 - \caption{Modifications conflictuelles dans un document} 94.147 - \label{fig:tour-merge:conflict} 94.148 -\end{figure} 94.149 - 94.150 -La figure~\ref{fig:tour-merge:conflict} illustre un cas de modifications 94.151 -conflictuelles dans un document. Nous avons commencé avec une version simple 94.152 -de ce fichier, puis nous avons ajouté des modifications, pendant que 94.153 -quelqu'un d'autre modifiait le même texte. Notre tâche dans la résolution 94.154 -du conflit est de décider à quoi le fichier devrait ressembler. 94.155 - 94.156 -Mercurial n'a pas de mécanisme interne pour gérer les conflits. 94.157 -À la place, il exécute un programme externe appelé \command{hgmerge}. 94.158 -Il s'agit d'un script shell qui est embarqué par Mercurial, vous 94.159 -pouvez le modifier si vous le voulez. Ce qu'il fait par défaut est 94.160 -d'essayer de trouver un des différents outils de fusion qui seront 94.161 -probablement installés sur le système. Il commence par les outils 94.162 -totalement automatiques, et si ils échouent (parce que la résolution 94.163 -du conflit nécessite une intervention humaine) ou si ils sont absents, 94.164 -le script tente d'exécuter certains outils graphiques de fusion. 94.165 - 94.166 -Il est aussi possible de demander à Mercurial d'exécuter un autre 94.167 -programme ou un autre script au lieu de la commande \command{hgmerge}, 94.168 -en définissant la variable d'environnement \envar{HGMERGE} avec le nom 94.169 -du programme de votre choix. 94.170 - 94.171 -\subsection{Utiliser un outil graphique de fusion} 94.172 - 94.173 -Mon outil de fusion préféré est \command{kdiff3}, que j'utilise ici 94.174 -pour illustrer les fonctionnalités classiques des outils graphiques 94.175 -de fusion. Vous pouvez voir une capture d'écran de l'utilisation de 94.176 -\command{kdiff3} dans la figure~\ref{fig:tour-merge:kdiff3}. Cet outil 94.177 -effectue une \emph{fusion \textit{three-way}}, car il y a trois différentes 94.178 -versions du fichier qui nous intéresse. Le fichier découpe la partie 94.179 -supérieure de la fenêtre en trois panneaux: 94.180 - 94.181 -\begin{itemize} 94.182 -\item A gauche on la version de \emph{base} du fichier, soit la plus 94.183 - récente version des deux versions qu'on souhaite fusionner. 94.184 -\item Au centre, il y a ``notre'' version du fichier, avec le contenu 94.185 - que nous avons modifié. 94.186 -\item Sur la droite, on trouve ``leur'' version du fichier, celui qui 94.187 - contient le \textit{changeset} que nous souhaitons intégré. 94.188 -\end{itemize} 94.189 - 94.190 -Dans le panneau en dessous, on trouve le \emph{résultat} actuel de notre 94.191 -fusion. Notre tâche consiste donc à remplacement tous les textes en rouges, 94.192 -qui indiquent des conflits non résolus, avec une fusion manuelle et pertinente 94.193 -de ``notre'' version et de la ``leur''. 94.194 - 94.195 -Tous les quatre panneaux sont \emph{accrochés ensemble}, si nous déroulons 94.196 -les ascenseurs verticalement ou horizontalement dans chacun d'entre eux, les 94.197 -autres sont mis à jour avec la section correspondante dans leurs fichiers 94.198 -respectifs. 94.199 - 94.200 -\begin{figure}[ht] 94.201 - \centering 94.202 - \grafix{kdiff3} 94.203 - \caption{Utilisation de \command{kdiff3} pour fusionner différentes versions 94.204 - d'un fichier.} 94.205 - \label{fig:tour-merge:kdiff3} 94.206 -\end{figure} 94.207 - 94.208 -Pour chaque portion de fichier posant problème, nous pouvons choisir 94.209 -de résoudre le conflit en utilisant une combinaison 94.210 -de texte depuis la version de base, la notre, ou la leur. Nous pouvons 94.211 -aussi éditer manuellement les fichiers à tout moment, si c'est 94.212 -nécessaire. 94.213 - 94.214 -Il y a \emph{beaucoup} d'outils de fusion disponibles, bien trop pour 94.215 -en parler de tous ici. Leurs disponibilités varient selon les plate formes 94.216 -ainsi que leurs avantages et inconvénients. La plupart sont optimisé pour 94.217 -la fusion de fichier contenant un texte plat, certains sont spécialisé 94.218 -dans un format de fichier précis (généralement XML). 94.219 - 94.220 -\subsection{Un exemple concret} 94.221 - 94.222 -Dans cet exemple, nous allons reproduire la modification de l'historique 94.223 -du fichier de la figure~\ref{fig:tour-merge:conflict} ci dessus. Commençons 94.224 -par créer un dépôt avec une version de base de notre document. 94.225 - 94.226 -\interaction{tour-merge-conflict.wife} 94.227 -Créons un clone de ce dépôt et faisons une modification dans le fichier. 94.228 -\interaction{tour-merge-conflict.cousin} 94.229 -Et un autre clone, pour simuler que quelqu'un d'autre effectue une 94.230 -modification sur le fichier. (Ceci pour suggérer qu'il n'est pas rare 94.231 -de devoir effectuer des \textit{merge} avec vos propres travaux quand 94.232 -vous isolez les tâches dans des dépôts distincts. En effet, vous 94.233 -aurez alors à trouver et résoudre certains conflits). 94.234 -\interaction{tour-merge-conflict.son} 94.235 -Maintenant que ces deux versions différentes du même fichier sont 94.236 -créées, nous allons configurer l'environnement de manière appropriée pour 94.237 -exécuter notre \textit{merge}. 94.238 -\interaction{tour-merge-conflict.pull} 94.239 - 94.240 -Dans cette exemple, je n'utiliserais pas la commande Mercurial 94.241 -habituelle \command{hgmerge} pour effectuer le \textit{merge}, 94.242 -car il me faudrait abandonner ce joli petit exemple automatisé 94.243 -pour utiliser un outil graphique. À la place, je vais définir 94.244 -la variable d'environnement \envar{HGMERGE} pour indiquer à 94.245 -Mercurial d'utiliser la commande non-interactive \command{merge}. 94.246 -Cette dernière est embarquée par de nombreux systèmes ``à la Unix''. 94.247 -Si vous exécutez cet exemple depuis votre ordinateur, ne vous 94.248 -occupez pas de définir \envar{HGMERGE}. 94.249 -\interaction{tour-merge-conflict.merge} 94.250 -Parce que \command{merge} ne peut pas résoudre les modifications 94.251 -conflictuelles, il laisse des \emph{marqueurs de différences} 94.252 -\footnote{NdT: Oui, je traduis \textit{merge markers} par un sens 94.253 -inverse en Français, mais je pense vraiment que c'est plus clair 94.254 -comme ça...} à l'intérieur du fichier qui a des conflits, indiquant 94.255 -clairement quelles lignes sont en conflits, et si elles viennent de 94.256 -notre fichier ou du fichier externe. 94.257 - 94.258 -Mercurial peut distinguer, à la manière dont la commande \command{merge} 94.259 -se termine, qu'elle n'a pas été capable d'effectuer le \textit{merge}, 94.260 -alors il nous indique que nous devons effectuer de nouveau cette 94.261 -opération. Ceci peut être très utile si, par exemple, nous exécutons un 94.262 -outil graphique de fusion et que nous le quittons sans nous rendre compte 94.263 -qu'il reste des conflits ou simplement par erreur. 94.264 - 94.265 -Si le \textit{merge} automatique ou manuel échoue, il n'y a rien pour 94.266 -nous empêcher de ``corriger le tir'' en modifiant nous même les fichiers, 94.267 -et enfin effectuer le \textit{commit} du fichier: 94.268 -\interaction{tour-merge-conflict.commit} 94.269 - 94.270 -\section{Simplification de la séquence pull-merge-commit} 94.271 -\label{sec:tour-merge:fetch} 94.272 - 94.273 -La procédure pour effectuer la fusion indiquée ci-dessus est simple, 94.274 -mais requiert le lancement de trois commandes à la suite. 94.275 -\begin{codesample2} 94.276 - hg pull 94.277 - hg merge 94.278 - hg commit -m 'Merged remote changes' 94.279 -\end{codesample2} 94.280 - 94.281 -Lors du \textit{commit} final, vous devez également saisir un message, 94.282 -qui aura vraisemblablement assez peu d'intérêt. 94.283 - 94.284 -Il serait assez sympathique de pouvoir réduire le nombre d'opérations 94.285 -nécessaire, si possible. De fait Mercurial est fourni avec une 94.286 -extension appelé \hgext{fetch} qui fait justement cela. 94.287 - 94.288 -Mercurial fourni un mécanisme d'extension flexible qui permet à chacun 94.289 -d'étendre ces fonctionnalités, tout en conservant le cœur de Mercurial 94.290 -léger et facile à utiliser. Certains extensions ajoutent de nouvelles 94.291 -commandes que vous pouvez utiliser en ligne de commande, alors que 94.292 -d'autres travaillent ``en coulisse,'' par exemple en ajoutant des 94.293 -possibilités au serveur. 94.294 - 94.295 -L'extension \hgext{fetch} ajoute une nouvelle commande nommée, sans 94.296 -surprise, \hgcmd{fetch}. Cette extension résulte en une combinaison 94.297 -de \hgcmd{pull}, \hgcmd{update} and \hgcmd{merge}. Elle commence par 94.298 -récupérer les modifications d'un autre dépôt dans le dépôt courant. 94.299 -Si elle trouve que les modifications ajoutent une nouvelle \textit{head}, 94.300 -elle effectue un \textit{merge}, et ensuite \texit{commit} le résultat 94.301 -du \textit{merge} avec un message généré automatiquement. Si aucune 94.302 -\textit{head} n'ont été ajouté, elle met à jour le répertoire de travail 94.303 -au niveau du nouveau \textit{changeset} \textit{tip}. 94.304 - 94.305 - 94.306 -Activer l'extension \hgext{fetch} est facile. Modifiez votre \sfilename{.hgrc}, 94.307 -et soit allez à la section \rcsection{extensions} soit créer une 94.308 -section \rcsection{extensions}. Ensuite ajoutez une ligne qui consiste 94.309 -simplement en ``\Verb+fetch =''. 94.310 - 94.311 -\begin{codesample2} 94.312 - [extensions] 94.313 - fetch = 94.314 -\end{codesample2} 94.315 -(Normalement, sur la partie droite de ``\texttt{=}'' devrait apparaître 94.316 -le chemin de l'extension, mais étant donné que l'extension \hgext{fetch} 94.317 -fait partie de la distribution standard, Mercurial sait où la trouver.) 94.318 - 94.319 -%%% Local Variables: 94.320 -%%% mode: latex 94.321 -%%% TeX-master: "00book" 94.322 -%%% End:
95.1 --- a/fr/undo-manual-merge.dot Sun Aug 16 03:41:39 2009 +0200 95.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 95.3 @@ -1,8 +0,0 @@ 95.4 -digraph undo_manual { 95.5 - "first change" -> "second change"; 95.6 - "second change" -> "third change"; 95.7 - backout [label="back out\nsecond change", shape=box]; 95.8 - "second change" -> backout; 95.9 - "third change" -> "manual\nmerge"; 95.10 - backout -> "manual\nmerge"; 95.11 -}
96.1 --- a/fr/undo-manual.dot Sun Aug 16 03:41:39 2009 +0200 96.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 96.3 @@ -1,6 +0,0 @@ 96.4 -digraph undo_manual { 96.5 - "first change" -> "second change"; 96.6 - "second change" -> "third change"; 96.7 - backout [label="back out\nsecond change", shape=box]; 96.8 - "second change" -> backout; 96.9 -}
97.1 --- a/fr/undo-non-tip.dot Sun Aug 16 03:41:39 2009 +0200 97.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 97.3 @@ -1,9 +0,0 @@ 97.4 -digraph undo_non_tip { 97.5 - "first change" -> "second change"; 97.6 - "second change" -> "third change"; 97.7 - backout [label="back out\nsecond change", shape=box]; 97.8 - "second change" -> backout; 97.9 - merge [label="automated\nmerge", shape=box]; 97.10 - "third change" -> merge; 97.11 - backout -> merge; 97.12 -}
98.1 --- a/fr/undo-simple.dot Sun Aug 16 03:41:39 2009 +0200 98.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 98.3 @@ -1,4 +0,0 @@ 98.4 -digraph undo_simple { 98.5 - "first change" -> "second change"; 98.6 - "second change" -> "back out\nsecond change"; 98.7 -}
99.1 --- a/fr/undo.tex Sun Aug 16 03:41:39 2009 +0200 99.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 99.3 @@ -1,767 +0,0 @@ 99.4 -\chapter{Finding and fixing your mistakes} 99.5 -\label{chap:undo} 99.6 - 99.7 -To err might be human, but to really handle the consequences well 99.8 -takes a top-notch revision control system. In this chapter, we'll 99.9 -discuss some of the techniques you can use when you find that a 99.10 -problem has crept into your project. Mercurial has some highly 99.11 -capable features that will help you to isolate the sources of 99.12 -problems, and to handle them appropriately. 99.13 - 99.14 -\section{Erasing local history} 99.15 - 99.16 -\subsection{The accidental commit} 99.17 - 99.18 -I have the occasional but persistent problem of typing rather more 99.19 -quickly than I can think, which sometimes results in me committing a 99.20 -changeset that is either incomplete or plain wrong. In my case, the 99.21 -usual kind of incomplete changeset is one in which I've created a new 99.22 -source file, but forgotten to \hgcmd{add} it. A ``plain wrong'' 99.23 -changeset is not as common, but no less annoying. 99.24 - 99.25 -\subsection{Rolling back a transaction} 99.26 -\label{sec:undo:rollback} 99.27 - 99.28 -In section~\ref{sec:concepts:txn}, I mentioned that Mercurial treats 99.29 -each modification of a repository as a \emph{transaction}. Every time 99.30 -you commit a changeset or pull changes from another repository, 99.31 -Mercurial remembers what you did. You can undo, or \emph{roll back}, 99.32 -exactly one of these actions using the \hgcmd{rollback} command. (See 99.33 -section~\ref{sec:undo:rollback-after-push} for an important caveat 99.34 -about the use of this command.) 99.35 - 99.36 -Here's a mistake that I often find myself making: committing a change 99.37 -in which I've created a new file, but forgotten to \hgcmd{add} it. 99.38 -\interaction{rollback.commit} 99.39 -Looking at the output of \hgcmd{status} after the commit immediately 99.40 -confirms the error. 99.41 -\interaction{rollback.status} 99.42 -The commit captured the changes to the file \filename{a}, but not the 99.43 -new file \filename{b}. If I were to push this changeset to a 99.44 -repository that I shared with a colleague, the chances are high that 99.45 -something in \filename{a} would refer to \filename{b}, which would not 99.46 -be present in their repository when they pulled my changes. I would 99.47 -thus become the object of some indignation. 99.48 - 99.49 -However, luck is with me---I've caught my error before I pushed the 99.50 -changeset. I use the \hgcmd{rollback} command, and Mercurial makes 99.51 -that last changeset vanish. 99.52 -\interaction{rollback.rollback} 99.53 -Notice that the changeset is no longer present in the repository's 99.54 -history, and the working directory once again thinks that the file 99.55 -\filename{a} is modified. The commit and rollback have left the 99.56 -working directory exactly as it was prior to the commit; the changeset 99.57 -has been completely erased. I can now safely \hgcmd{add} the file 99.58 -\filename{b}, and rerun my commit. 99.59 -\interaction{rollback.add} 99.60 - 99.61 -\subsection{The erroneous pull} 99.62 - 99.63 -It's common practice with Mercurial to maintain separate development 99.64 -branches of a project in different repositories. Your development 99.65 -team might have one shared repository for your project's ``0.9'' 99.66 -release, and another, containing different changes, for the ``1.0'' 99.67 -release. 99.68 - 99.69 -Given this, you can imagine that the consequences could be messy if 99.70 -you had a local ``0.9'' repository, and accidentally pulled changes 99.71 -from the shared ``1.0'' repository into it. At worst, you could be 99.72 -paying insufficient attention, and push those changes into the shared 99.73 -``0.9'' tree, confusing your entire team (but don't worry, we'll 99.74 -return to this horror scenario later). However, it's more likely that 99.75 -you'll notice immediately, because Mercurial will display the URL it's 99.76 -pulling from, or you will see it pull a suspiciously large number of 99.77 -changes into the repository. 99.78 - 99.79 -The \hgcmd{rollback} command will work nicely to expunge all of the 99.80 -changesets that you just pulled. Mercurial groups all changes from 99.81 -one \hgcmd{pull} into a single transaction, so one \hgcmd{rollback} is 99.82 -all you need to undo this mistake. 99.83 - 99.84 -\subsection{Rolling back is useless once you've pushed} 99.85 -\label{sec:undo:rollback-after-push} 99.86 - 99.87 -The value of the \hgcmd{rollback} command drops to zero once you've 99.88 -pushed your changes to another repository. Rolling back a change 99.89 -makes it disappear entirely, but \emph{only} in the repository in 99.90 -which you perform the \hgcmd{rollback}. Because a rollback eliminates 99.91 -history, there's no way for the disappearance of a change to propagate 99.92 -between repositories. 99.93 - 99.94 -If you've pushed a change to another repository---particularly if it's 99.95 -a shared repository---it has essentially ``escaped into the wild,'' 99.96 -and you'll have to recover from your mistake in a different way. What 99.97 -will happen if you push a changeset somewhere, then roll it back, then 99.98 -pull from the repository you pushed to, is that the changeset will 99.99 -reappear in your repository. 99.100 - 99.101 -(If you absolutely know for sure that the change you want to roll back 99.102 -is the most recent change in the repository that you pushed to, 99.103 -\emph{and} you know that nobody else could have pulled it from that 99.104 -repository, you can roll back the changeset there, too, but you really 99.105 -should really not rely on this working reliably. If you do this, 99.106 -sooner or later a change really will make it into a repository that 99.107 -you don't directly control (or have forgotten about), and come back to 99.108 -bite you.) 99.109 - 99.110 -\subsection{You can only roll back once} 99.111 - 99.112 -Mercurial stores exactly one transaction in its transaction log; that 99.113 -transaction is the most recent one that occurred in the repository. 99.114 -This means that you can only roll back one transaction. If you expect 99.115 -to be able to roll back one transaction, then its predecessor, this is 99.116 -not the behaviour you will get. 99.117 -\interaction{rollback.twice} 99.118 -Once you've rolled back one transaction in a repository, you can't 99.119 -roll back again in that repository until you perform another commit or 99.120 -pull. 99.121 - 99.122 -\section{Reverting the mistaken change} 99.123 - 99.124 -If you make a modification to a file, and decide that you really 99.125 -didn't want to change the file at all, and you haven't yet committed 99.126 -your changes, the \hgcmd{revert} command is the one you'll need. It 99.127 -looks at the changeset that's the parent of the working directory, and 99.128 -restores the contents of the file to their state as of that changeset. 99.129 -(That's a long-winded way of saying that, in the normal case, it 99.130 -undoes your modifications.) 99.131 - 99.132 -Let's illustrate how the \hgcmd{revert} command works with yet another 99.133 -small example. We'll begin by modifying a file that Mercurial is 99.134 -already tracking. 99.135 -\interaction{daily.revert.modify} 99.136 -If we don't want that change, we can simply \hgcmd{revert} the file. 99.137 -\interaction{daily.revert.unmodify} 99.138 -The \hgcmd{revert} command provides us with an extra degree of safety 99.139 -by saving our modified file with a \filename{.orig} extension. 99.140 -\interaction{daily.revert.status} 99.141 - 99.142 -Here is a summary of the cases that the \hgcmd{revert} command can 99.143 -deal with. We will describe each of these in more detail in the 99.144 -section that follows. 99.145 -\begin{itemize} 99.146 -\item If you modify a file, it will restore the file to its unmodified 99.147 - state. 99.148 -\item If you \hgcmd{add} a file, it will undo the ``added'' state of 99.149 - the file, but leave the file itself untouched. 99.150 -\item If you delete a file without telling Mercurial, it will restore 99.151 - the file to its unmodified contents. 99.152 -\item If you use the \hgcmd{remove} command to remove a file, it will 99.153 - undo the ``removed'' state of the file, and restore the file to its 99.154 - unmodified contents. 99.155 -\end{itemize} 99.156 - 99.157 -\subsection{File management errors} 99.158 -\label{sec:undo:mgmt} 99.159 - 99.160 -The \hgcmd{revert} command is useful for more than just modified 99.161 -files. It lets you reverse the results of all of Mercurial's file 99.162 -management commands---\hgcmd{add}, \hgcmd{remove}, and so on. 99.163 - 99.164 -If you \hgcmd{add} a file, then decide that in fact you don't want 99.165 -Mercurial to track it, use \hgcmd{revert} to undo the add. Don't 99.166 -worry; Mercurial will not modify the file in any way. It will just 99.167 -``unmark'' the file. 99.168 -\interaction{daily.revert.add} 99.169 - 99.170 -Similarly, if you ask Mercurial to \hgcmd{remove} a file, you can use 99.171 -\hgcmd{revert} to restore it to the contents it had as of the parent 99.172 -of the working directory. 99.173 -\interaction{daily.revert.remove} 99.174 -This works just as well for a file that you deleted by hand, without 99.175 -telling Mercurial (recall that in Mercurial terminology, this kind of 99.176 -file is called ``missing''). 99.177 -\interaction{daily.revert.missing} 99.178 - 99.179 -If you revert a \hgcmd{copy}, the copied-to file remains in your 99.180 -working directory afterwards, untracked. Since a copy doesn't affect 99.181 -the copied-from file in any way, Mercurial doesn't do anything with 99.182 -the copied-from file. 99.183 -\interaction{daily.revert.copy} 99.184 - 99.185 -\subsubsection{A slightly special case: reverting a rename} 99.186 - 99.187 -If you \hgcmd{rename} a file, there is one small detail that 99.188 -you should remember. When you \hgcmd{revert} a rename, it's not 99.189 -enough to provide the name of the renamed-to file, as you can see 99.190 -here. 99.191 -\interaction{daily.revert.rename} 99.192 -As you can see from the output of \hgcmd{status}, the renamed-to file 99.193 -is no longer identified as added, but the renamed-\emph{from} file is 99.194 -still removed! This is counter-intuitive (at least to me), but at 99.195 -least it's easy to deal with. 99.196 -\interaction{daily.revert.rename-orig} 99.197 -So remember, to revert a \hgcmd{rename}, you must provide \emph{both} 99.198 -the source and destination names. 99.199 - 99.200 -% TODO: the output doesn't look like it will be removed! 99.201 - 99.202 -(By the way, if you rename a file, then modify the renamed-to file, 99.203 -then revert both components of the rename, when Mercurial restores the 99.204 -file that was removed as part of the rename, it will be unmodified. 99.205 -If you need the modifications in the renamed-to file to show up in the 99.206 -renamed-from file, don't forget to copy them over.) 99.207 - 99.208 -These fiddly aspects of reverting a rename arguably constitute a small 99.209 -bug in Mercurial. 99.210 - 99.211 -\section{Dealing with committed changes} 99.212 - 99.213 -Consider a case where you have committed a change $a$, and another 99.214 -change $b$ on top of it; you then realise that change $a$ was 99.215 -incorrect. Mercurial lets you ``back out'' an entire changeset 99.216 -automatically, and building blocks that let you reverse part of a 99.217 -changeset by hand. 99.218 - 99.219 -Before you read this section, here's something to keep in mind: the 99.220 -\hgcmd{backout} command undoes changes by \emph{adding} history, not 99.221 -by modifying or erasing it. It's the right tool to use if you're 99.222 -fixing bugs, but not if you're trying to undo some change that has 99.223 -catastrophic consequences. To deal with those, see 99.224 -section~\ref{sec:undo:aaaiiieee}. 99.225 - 99.226 -\subsection{Backing out a changeset} 99.227 - 99.228 -The \hgcmd{backout} command lets you ``undo'' the effects of an entire 99.229 -changeset in an automated fashion. Because Mercurial's history is 99.230 -immutable, this command \emph{does not} get rid of the changeset you 99.231 -want to undo. Instead, it creates a new changeset that 99.232 -\emph{reverses} the effect of the to-be-undone changeset. 99.233 - 99.234 -The operation of the \hgcmd{backout} command is a little intricate, so 99.235 -let's illustrate it with some examples. First, we'll create a 99.236 -repository with some simple changes. 99.237 -\interaction{backout.init} 99.238 - 99.239 -The \hgcmd{backout} command takes a single changeset ID as its 99.240 -argument; this is the changeset to back out. Normally, 99.241 -\hgcmd{backout} will drop you into a text editor to write a commit 99.242 -message, so you can record why you're backing the change out. In this 99.243 -example, we provide a commit message on the command line using the 99.244 -\hgopt{backout}{-m} option. 99.245 - 99.246 -\subsection{Backing out the tip changeset} 99.247 - 99.248 -We're going to start by backing out the last changeset we committed. 99.249 -\interaction{backout.simple} 99.250 -You can see that the second line from \filename{myfile} is no longer 99.251 -present. Taking a look at the output of \hgcmd{log} gives us an idea 99.252 -of what the \hgcmd{backout} command has done. 99.253 -\interaction{backout.simple.log} 99.254 -Notice that the new changeset that \hgcmd{backout} has created is a 99.255 -child of the changeset we backed out. It's easier to see this in 99.256 -figure~\ref{fig:undo:backout}, which presents a graphical view of the 99.257 -change history. As you can see, the history is nice and linear. 99.258 - 99.259 -\begin{figure}[htb] 99.260 - \centering 99.261 - \grafix{undo-simple} 99.262 - \caption{Backing out a change using the \hgcmd{backout} command} 99.263 - \label{fig:undo:backout} 99.264 -\end{figure} 99.265 - 99.266 -\subsection{Backing out a non-tip change} 99.267 - 99.268 -If you want to back out a change other than the last one you 99.269 -committed, pass the \hgopt{backout}{--merge} option to the 99.270 -\hgcmd{backout} command. 99.271 -\interaction{backout.non-tip.clone} 99.272 -This makes backing out any changeset a ``one-shot'' operation that's 99.273 -usually simple and fast. 99.274 -\interaction{backout.non-tip.backout} 99.275 - 99.276 -If you take a look at the contents of \filename{myfile} after the 99.277 -backout finishes, you'll see that the first and third changes are 99.278 -present, but not the second. 99.279 -\interaction{backout.non-tip.cat} 99.280 - 99.281 -As the graphical history in figure~\ref{fig:undo:backout-non-tip} 99.282 -illustrates, Mercurial actually commits \emph{two} changes in this 99.283 -kind of situation (the box-shaped nodes are the ones that Mercurial 99.284 -commits automatically). Before Mercurial begins the backout process, 99.285 -it first remembers what the current parent of the working directory 99.286 -is. It then backs out the target changeset, and commits that as a 99.287 -changeset. Finally, it merges back to the previous parent of the 99.288 -working directory, and commits the result of the merge. 99.289 - 99.290 -% TODO: to me it looks like mercurial doesn't commit the second merge automatically! 99.291 - 99.292 -\begin{figure}[htb] 99.293 - \centering 99.294 - \grafix{undo-non-tip} 99.295 - \caption{Automated backout of a non-tip change using the \hgcmd{backout} command} 99.296 - \label{fig:undo:backout-non-tip} 99.297 -\end{figure} 99.298 - 99.299 -The result is that you end up ``back where you were'', only with some 99.300 -extra history that undoes the effect of the changeset you wanted to 99.301 -back out. 99.302 - 99.303 -\subsubsection{Always use the \hgopt{backout}{--merge} option} 99.304 - 99.305 -In fact, since the \hgopt{backout}{--merge} option will do the ``right 99.306 -thing'' whether or not the changeset you're backing out is the tip 99.307 -(i.e.~it won't try to merge if it's backing out the tip, since there's 99.308 -no need), you should \emph{always} use this option when you run the 99.309 -\hgcmd{backout} command. 99.310 - 99.311 -\subsection{Gaining more control of the backout process} 99.312 - 99.313 -While I've recommended that you always use the 99.314 -\hgopt{backout}{--merge} option when backing out a change, the 99.315 -\hgcmd{backout} command lets you decide how to merge a backout 99.316 -changeset. Taking control of the backout process by hand is something 99.317 -you will rarely need to do, but it can be useful to understand what 99.318 -the \hgcmd{backout} command is doing for you automatically. To 99.319 -illustrate this, let's clone our first repository, but omit the 99.320 -backout change that it contains. 99.321 - 99.322 -\interaction{backout.manual.clone} 99.323 -As with our earlier example, We'll commit a third changeset, then back 99.324 -out its parent, and see what happens. 99.325 -\interaction{backout.manual.backout} 99.326 -Our new changeset is again a descendant of the changeset we backout 99.327 -out; it's thus a new head, \emph{not} a descendant of the changeset 99.328 -that was the tip. The \hgcmd{backout} command was quite explicit in 99.329 -telling us this. 99.330 -\interaction{backout.manual.log} 99.331 - 99.332 -Again, it's easier to see what has happened by looking at a graph of 99.333 -the revision history, in figure~\ref{fig:undo:backout-manual}. This 99.334 -makes it clear that when we use \hgcmd{backout} to back out a change 99.335 -other than the tip, Mercurial adds a new head to the repository (the 99.336 -change it committed is box-shaped). 99.337 - 99.338 -\begin{figure}[htb] 99.339 - \centering 99.340 - \grafix{undo-manual} 99.341 - \caption{Backing out a change using the \hgcmd{backout} command} 99.342 - \label{fig:undo:backout-manual} 99.343 -\end{figure} 99.344 - 99.345 -After the \hgcmd{backout} command has completed, it leaves the new 99.346 -``backout'' changeset as the parent of the working directory. 99.347 -\interaction{backout.manual.parents} 99.348 -Now we have two isolated sets of changes. 99.349 -\interaction{backout.manual.heads} 99.350 - 99.351 -Let's think about what we expect to see as the contents of 99.352 -\filename{myfile} now. The first change should be present, because 99.353 -we've never backed it out. The second change should be missing, as 99.354 -that's the change we backed out. Since the history graph shows the 99.355 -third change as a separate head, we \emph{don't} expect to see the 99.356 -third change present in \filename{myfile}. 99.357 -\interaction{backout.manual.cat} 99.358 -To get the third change back into the file, we just do a normal merge 99.359 -of our two heads. 99.360 -\interaction{backout.manual.merge} 99.361 -Afterwards, the graphical history of our repository looks like 99.362 -figure~\ref{fig:undo:backout-manual-merge}. 99.363 - 99.364 -\begin{figure}[htb] 99.365 - \centering 99.366 - \grafix{undo-manual-merge} 99.367 - \caption{Manually merging a backout change} 99.368 - \label{fig:undo:backout-manual-merge} 99.369 -\end{figure} 99.370 - 99.371 -\subsection{Why \hgcmd{backout} works as it does} 99.372 - 99.373 -Here's a brief description of how the \hgcmd{backout} command works. 99.374 -\begin{enumerate} 99.375 -\item It ensures that the working directory is ``clean'', i.e.~that 99.376 - the output of \hgcmd{status} would be empty. 99.377 -\item It remembers the current parent of the working directory. Let's 99.378 - call this changeset \texttt{orig} 99.379 -\item It does the equivalent of a \hgcmd{update} to sync the working 99.380 - directory to the changeset you want to back out. Let's call this 99.381 - changeset \texttt{backout} 99.382 -\item It finds the parent of that changeset. Let's call that 99.383 - changeset \texttt{parent}. 99.384 -\item For each file that the \texttt{backout} changeset affected, it 99.385 - does the equivalent of a \hgcmdargs{revert}{-r parent} on that file, 99.386 - to restore it to the contents it had before that changeset was 99.387 - committed. 99.388 -\item It commits the result as a new changeset. This changeset has 99.389 - \texttt{backout} as its parent. 99.390 -\item If you specify \hgopt{backout}{--merge} on the command line, it 99.391 - merges with \texttt{orig}, and commits the result of the merge. 99.392 -\end{enumerate} 99.393 - 99.394 -An alternative way to implement the \hgcmd{backout} command would be 99.395 -to \hgcmd{export} the to-be-backed-out changeset as a diff, then use 99.396 -the \cmdopt{patch}{--reverse} option to the \command{patch} command to 99.397 -reverse the effect of the change without fiddling with the working 99.398 -directory. This sounds much simpler, but it would not work nearly as 99.399 -well. 99.400 - 99.401 -The reason that \hgcmd{backout} does an update, a commit, a merge, and 99.402 -another commit is to give the merge machinery the best chance to do a 99.403 -good job when dealing with all the changes \emph{between} the change 99.404 -you're backing out and the current tip. 99.405 - 99.406 -If you're backing out a changeset that's~100 revisions back in your 99.407 -project's history, the chances that the \command{patch} command will 99.408 -be able to apply a reverse diff cleanly are not good, because 99.409 -intervening changes are likely to have ``broken the context'' that 99.410 -\command{patch} uses to determine whether it can apply a patch (if 99.411 -this sounds like gibberish, see \ref{sec:mq:patch} for a 99.412 -discussion of the \command{patch} command). Also, Mercurial's merge 99.413 -machinery will handle files and directories being renamed, permission 99.414 -changes, and modifications to binary files, none of which 99.415 -\command{patch} can deal with. 99.416 - 99.417 -\section{Changes that should never have been} 99.418 -\label{sec:undo:aaaiiieee} 99.419 - 99.420 -Most of the time, the \hgcmd{backout} command is exactly what you need 99.421 -if you want to undo the effects of a change. It leaves a permanent 99.422 -record of exactly what you did, both when committing the original 99.423 -changeset and when you cleaned up after it. 99.424 - 99.425 -On rare occasions, though, you may find that you've committed a change 99.426 -that really should not be present in the repository at all. For 99.427 -example, it would be very unusual, and usually considered a mistake, 99.428 -to commit a software project's object files as well as its source 99.429 -files. Object files have almost no intrinsic value, and they're 99.430 -\emph{big}, so they increase the size of the repository and the amount 99.431 -of time it takes to clone or pull changes. 99.432 - 99.433 -Before I discuss the options that you have if you commit a ``brown 99.434 -paper bag'' change (the kind that's so bad that you want to pull a 99.435 -brown paper bag over your head), let me first discuss some approaches 99.436 -that probably won't work. 99.437 - 99.438 -Since Mercurial treats history as accumulative---every change builds 99.439 -on top of all changes that preceded it---you generally can't just make 99.440 -disastrous changes disappear. The one exception is when you've just 99.441 -committed a change, and it hasn't been pushed or pulled into another 99.442 -repository. That's when you can safely use the \hgcmd{rollback} 99.443 -command, as I detailed in section~\ref{sec:undo:rollback}. 99.444 - 99.445 -After you've pushed a bad change to another repository, you 99.446 -\emph{could} still use \hgcmd{rollback} to make your local copy of the 99.447 -change disappear, but it won't have the consequences you want. The 99.448 -change will still be present in the remote repository, so it will 99.449 -reappear in your local repository the next time you pull. 99.450 - 99.451 -If a situation like this arises, and you know which repositories your 99.452 -bad change has propagated into, you can \emph{try} to get rid of the 99.453 -changeefrom \emph{every} one of those repositories. This is, of 99.454 -course, not a satisfactory solution: if you miss even a single 99.455 -repository while you're expunging, the change is still ``in the 99.456 -wild'', and could propagate further. 99.457 - 99.458 -If you've committed one or more changes \emph{after} the change that 99.459 -you'd like to see disappear, your options are further reduced. 99.460 -Mercurial doesn't provide a way to ``punch a hole'' in history, 99.461 -leaving changesets intact. 99.462 - 99.463 -XXX This needs filling out. The \texttt{hg-replay} script in the 99.464 -\texttt{examples} directory works, but doesn't handle merge 99.465 -changesets. Kind of an important omission. 99.466 - 99.467 -\subsection{Protect yourself from ``escaped'' changes} 99.468 - 99.469 -If you've committed some changes to your local repository and they've 99.470 -been pushed or pulled somewhere else, this isn't necessarily a 99.471 -disaster. You can protect yourself ahead of time against some classes 99.472 -of bad changeset. This is particularly easy if your team usually 99.473 -pulls changes from a central repository. 99.474 - 99.475 -By configuring some hooks on that repository to validate incoming 99.476 -changesets (see chapter~\ref{chap:hook}), you can automatically 99.477 -prevent some kinds of bad changeset from being pushed to the central 99.478 -repository at all. With such a configuration in place, some kinds of 99.479 -bad changeset will naturally tend to ``die out'' because they can't 99.480 -propagate into the central repository. Better yet, this happens 99.481 -without any need for explicit intervention. 99.482 - 99.483 -For instance, an incoming change hook that verifies that a changeset 99.484 -will actually compile can prevent people from inadvertantly ``breaking 99.485 -the build''. 99.486 - 99.487 -\section{Finding the source of a bug} 99.488 -\label{sec:undo:bisect} 99.489 - 99.490 -While it's all very well to be able to back out a changeset that 99.491 -introduced a bug, this requires that you know which changeset to back 99.492 -out. Mercurial provides an invaluable command, called 99.493 -\hgcmd{bisect}, that helps you to automate this process and accomplish 99.494 -it very efficiently. 99.495 - 99.496 -The idea behind the \hgcmd{bisect} command is that a changeset has 99.497 -introduced some change of behaviour that you can identify with a 99.498 -simple binary test. You don't know which piece of code introduced the 99.499 -change, but you know how to test for the presence of the bug. The 99.500 -\hgcmd{bisect} command uses your test to direct its search for the 99.501 -changeset that introduced the code that caused the bug. 99.502 - 99.503 -Here are a few scenarios to help you understand how you might apply 99.504 -this command. 99.505 -\begin{itemize} 99.506 -\item The most recent version of your software has a bug that you 99.507 - remember wasn't present a few weeks ago, but you don't know when it 99.508 - was introduced. Here, your binary test checks for the presence of 99.509 - that bug. 99.510 -\item You fixed a bug in a rush, and now it's time to close the entry 99.511 - in your team's bug database. The bug database requires a changeset 99.512 - ID when you close an entry, but you don't remember which changeset 99.513 - you fixed the bug in. Once again, your binary test checks for the 99.514 - presence of the bug. 99.515 -\item Your software works correctly, but runs~15\% slower than the 99.516 - last time you measured it. You want to know which changeset 99.517 - introduced the performance regression. In this case, your binary 99.518 - test measures the performance of your software, to see whether it's 99.519 - ``fast'' or ``slow''. 99.520 -\item The sizes of the components of your project that you ship 99.521 - exploded recently, and you suspect that something changed in the way 99.522 - you build your project. 99.523 -\end{itemize} 99.524 - 99.525 -From these examples, it should be clear that the \hgcmd{bisect} 99.526 -command is not useful only for finding the sources of bugs. You can 99.527 -use it to find any ``emergent property'' of a repository (anything 99.528 -that you can't find from a simple text search of the files in the 99.529 -tree) for which you can write a binary test. 99.530 - 99.531 -We'll introduce a little bit of terminology here, just to make it 99.532 -clear which parts of the search process are your responsibility, and 99.533 -which are Mercurial's. A \emph{test} is something that \emph{you} run 99.534 -when \hgcmd{bisect} chooses a changeset. A \emph{probe} is what 99.535 -\hgcmd{bisect} runs to tell whether a revision is good. Finally, 99.536 -we'll use the word ``bisect'', as both a noun and a verb, to stand in 99.537 -for the phrase ``search using the \hgcmd{bisect} command. 99.538 - 99.539 -One simple way to automate the searching process would be simply to 99.540 -probe every changeset. However, this scales poorly. If it took ten 99.541 -minutes to test a single changeset, and you had 10,000 changesets in 99.542 -your repository, the exhaustive approach would take on average~35 99.543 -\emph{days} to find the changeset that introduced a bug. Even if you 99.544 -knew that the bug was introduced by one of the last 500 changesets, 99.545 -and limited your search to those, you'd still be looking at over 40 99.546 -hours to find the changeset that introduced your bug. 99.547 - 99.548 -What the \hgcmd{bisect} command does is use its knowledge of the 99.549 -``shape'' of your project's revision history to perform a search in 99.550 -time proportional to the \emph{logarithm} of the number of changesets 99.551 -to check (the kind of search it performs is called a dichotomic 99.552 -search). With this approach, searching through 10,000 changesets will 99.553 -take less than three hours, even at ten minutes per test (the search 99.554 -will require about 14 tests). Limit your search to the last hundred 99.555 -changesets, and it will take only about an hour (roughly seven tests). 99.556 - 99.557 -The \hgcmd{bisect} command is aware of the ``branchy'' nature of a 99.558 -Mercurial project's revision history, so it has no problems dealing 99.559 -with branches, merges, or multiple heads in a repository. It can 99.560 -prune entire branches of history with a single probe, which is how it 99.561 -operates so efficiently. 99.562 - 99.563 -\subsection{Using the \hgcmd{bisect} command} 99.564 - 99.565 -Here's an example of \hgcmd{bisect} in action. 99.566 - 99.567 -\begin{note} 99.568 - In versions 0.9.5 and earlier of Mercurial, \hgcmd{bisect} was not a 99.569 - core command: it was distributed with Mercurial as an extension. 99.570 - This section describes the built-in command, not the old extension. 99.571 -\end{note} 99.572 - 99.573 -Now let's create a repository, so that we can try out the 99.574 -\hgcmd{bisect} command in isolation. 99.575 -\interaction{bisect.init} 99.576 -We'll simulate a project that has a bug in it in a simple-minded way: 99.577 -create trivial changes in a loop, and nominate one specific change 99.578 -that will have the ``bug''. This loop creates 35 changesets, each 99.579 -adding a single file to the repository. We'll represent our ``bug'' 99.580 -with a file that contains the text ``i have a gub''. 99.581 -\interaction{bisect.commits} 99.582 - 99.583 -The next thing that we'd like to do is figure out how to use the 99.584 -\hgcmd{bisect} command. We can use Mercurial's normal built-in help 99.585 -mechanism for this. 99.586 -\interaction{bisect.help} 99.587 - 99.588 -The \hgcmd{bisect} command works in steps. Each step proceeds as follows. 99.589 -\begin{enumerate} 99.590 -\item You run your binary test. 99.591 - \begin{itemize} 99.592 - \item If the test succeeded, you tell \hgcmd{bisect} by running the 99.593 - \hgcmdargs{bisect}{good} command. 99.594 - \item If it failed, run the \hgcmdargs{bisect}{--bad} command. 99.595 - \end{itemize} 99.596 -\item The command uses your information to decide which changeset to 99.597 - test next. 99.598 -\item It updates the working directory to that changeset, and the 99.599 - process begins again. 99.600 -\end{enumerate} 99.601 -The process ends when \hgcmd{bisect} identifies a unique changeset 99.602 -that marks the point where your test transitioned from ``succeeding'' 99.603 -to ``failing''. 99.604 - 99.605 -To start the search, we must run the \hgcmdargs{bisect}{--reset} command. 99.606 -\interaction{bisect.search.init} 99.607 - 99.608 -In our case, the binary test we use is simple: we check to see if any 99.609 -file in the repository contains the string ``i have a gub''. If it 99.610 -does, this changeset contains the change that ``caused the bug''. By 99.611 -convention, a changeset that has the property we're searching for is 99.612 -``bad'', while one that doesn't is ``good''. 99.613 - 99.614 -Most of the time, the revision to which the working directory is 99.615 -synced (usually the tip) already exhibits the problem introduced by 99.616 -the buggy change, so we'll mark it as ``bad''. 99.617 -\interaction{bisect.search.bad-init} 99.618 - 99.619 -Our next task is to nominate a changeset that we know \emph{doesn't} 99.620 -have the bug; the \hgcmd{bisect} command will ``bracket'' its search 99.621 -between the first pair of good and bad changesets. In our case, we 99.622 -know that revision~10 didn't have the bug. (I'll have more words 99.623 -about choosing the first ``good'' changeset later.) 99.624 -\interaction{bisect.search.good-init} 99.625 - 99.626 -Notice that this command printed some output. 99.627 -\begin{itemize} 99.628 -\item It told us how many changesets it must consider before it can 99.629 - identify the one that introduced the bug, and how many tests that 99.630 - will require. 99.631 -\item It updated the working directory to the next changeset to test, 99.632 - and told us which changeset it's testing. 99.633 -\end{itemize} 99.634 - 99.635 -We now run our test in the working directory. We use the 99.636 -\command{grep} command to see if our ``bad'' file is present in the 99.637 -working directory. If it is, this revision is bad; if not, this 99.638 -revision is good. 99.639 -\interaction{bisect.search.step1} 99.640 - 99.641 -This test looks like a perfect candidate for automation, so let's turn 99.642 -it into a shell function. 99.643 -\interaction{bisect.search.mytest} 99.644 -We can now run an entire test step with a single command, 99.645 -\texttt{mytest}. 99.646 -\interaction{bisect.search.step2} 99.647 -A few more invocations of our canned test step command, and we're 99.648 -done. 99.649 -\interaction{bisect.search.rest} 99.650 - 99.651 -Even though we had~40 changesets to search through, the \hgcmd{bisect} 99.652 -command let us find the changeset that introduced our ``bug'' with 99.653 -only five tests. Because the number of tests that the \hgcmd{bisect} 99.654 -command performs grows logarithmically with the number of changesets to 99.655 -search, the advantage that it has over the ``brute force'' search 99.656 -approach increases with every changeset you add. 99.657 - 99.658 -\subsection{Cleaning up after your search} 99.659 - 99.660 -When you're finished using the \hgcmd{bisect} command in a 99.661 -repository, you can use the \hgcmdargs{bisect}{reset} command to drop 99.662 -the information it was using to drive your search. The command 99.663 -doesn't use much space, so it doesn't matter if you forget to run this 99.664 -command. However, \hgcmd{bisect} won't let you start a new search in 99.665 -that repository until you do a \hgcmdargs{bisect}{reset}. 99.666 -\interaction{bisect.search.reset} 99.667 - 99.668 -\section{Tips for finding bugs effectively} 99.669 - 99.670 -\subsection{Give consistent input} 99.671 - 99.672 -The \hgcmd{bisect} command requires that you correctly report the 99.673 -result of every test you perform. If you tell it that a test failed 99.674 -when it really succeeded, it \emph{might} be able to detect the 99.675 -inconsistency. If it can identify an inconsistency in your reports, 99.676 -it will tell you that a particular changeset is both good and bad. 99.677 -However, it can't do this perfectly; it's about as likely to report 99.678 -the wrong changeset as the source of the bug. 99.679 - 99.680 -\subsection{Automate as much as possible} 99.681 - 99.682 -When I started using the \hgcmd{bisect} command, I tried a few times 99.683 -to run my tests by hand, on the command line. This is an approach 99.684 -that I, at least, am not suited to. After a few tries, I found that I 99.685 -was making enough mistakes that I was having to restart my searches 99.686 -several times before finally getting correct results. 99.687 - 99.688 -My initial problems with driving the \hgcmd{bisect} command by hand 99.689 -occurred even with simple searches on small repositories; if the 99.690 -problem you're looking for is more subtle, or the number of tests that 99.691 -\hgcmd{bisect} must perform increases, the likelihood of operator 99.692 -error ruining the search is much higher. Once I started automating my 99.693 -tests, I had much better results. 99.694 - 99.695 -The key to automated testing is twofold: 99.696 -\begin{itemize} 99.697 -\item always test for the same symptom, and 99.698 -\item always feed consistent input to the \hgcmd{bisect} command. 99.699 -\end{itemize} 99.700 -In my tutorial example above, the \command{grep} command tests for the 99.701 -symptom, and the \texttt{if} statement takes the result of this check 99.702 -and ensures that we always feed the same input to the \hgcmd{bisect} 99.703 -command. The \texttt{mytest} function marries these together in a 99.704 -reproducible way, so that every test is uniform and consistent. 99.705 - 99.706 -\subsection{Check your results} 99.707 - 99.708 -Because the output of a \hgcmd{bisect} search is only as good as the 99.709 -input you give it, don't take the changeset it reports as the 99.710 -absolute truth. A simple way to cross-check its report is to manually 99.711 -run your test at each of the following changesets: 99.712 -\begin{itemize} 99.713 -\item The changeset that it reports as the first bad revision. Your 99.714 - test should still report this as bad. 99.715 -\item The parent of that changeset (either parent, if it's a merge). 99.716 - Your test should report this changeset as good. 99.717 -\item A child of that changeset. Your test should report this 99.718 - changeset as bad. 99.719 -\end{itemize} 99.720 - 99.721 -\subsection{Beware interference between bugs} 99.722 - 99.723 -It's possible that your search for one bug could be disrupted by the 99.724 -presence of another. For example, let's say your software crashes at 99.725 -revision 100, and worked correctly at revision 50. Unknown to you, 99.726 -someone else introduced a different crashing bug at revision 60, and 99.727 -fixed it at revision 80. This could distort your results in one of 99.728 -several ways. 99.729 - 99.730 -It is possible that this other bug completely ``masks'' yours, which 99.731 -is to say that it occurs before your bug has a chance to manifest 99.732 -itself. If you can't avoid that other bug (for example, it prevents 99.733 -your project from building), and so can't tell whether your bug is 99.734 -present in a particular changeset, the \hgcmd{bisect} command cannot 99.735 -help you directly. Instead, you can mark a changeset as untested by 99.736 -running \hgcmdargs{bisect}{--skip}. 99.737 - 99.738 -A different problem could arise if your test for a bug's presence is 99.739 -not specific enough. If you check for ``my program crashes'', then 99.740 -both your crashing bug and an unrelated crashing bug that masks it 99.741 -will look like the same thing, and mislead \hgcmd{bisect}. 99.742 - 99.743 -Another useful situation in which to use \hgcmdargs{bisect}{--skip} is 99.744 -if you can't test a revision because your project was in a broken and 99.745 -hence untestable state at that revision, perhaps because someone 99.746 -checked in a change that prevented the project from building. 99.747 - 99.748 -\subsection{Bracket your search lazily} 99.749 - 99.750 -Choosing the first ``good'' and ``bad'' changesets that will mark the 99.751 -end points of your search is often easy, but it bears a little 99.752 -discussion nevertheless. From the perspective of \hgcmd{bisect}, the 99.753 -``newest'' changeset is conventionally ``bad'', and the older 99.754 -changeset is ``good''. 99.755 - 99.756 -If you're having trouble remembering when a suitable ``good'' change 99.757 -was, so that you can tell \hgcmd{bisect}, you could do worse than 99.758 -testing changesets at random. Just remember to eliminate contenders 99.759 -that can't possibly exhibit the bug (perhaps because the feature with 99.760 -the bug isn't present yet) and those where another problem masks the 99.761 -bug (as I discussed above). 99.762 - 99.763 -Even if you end up ``early'' by thousands of changesets or months of 99.764 -history, you will only add a handful of tests to the total number that 99.765 -\hgcmd{bisect} must perform, thanks to its logarithmic behaviour. 99.766 - 99.767 -%%% Local Variables: 99.768 -%%% mode: latex 99.769 -%%% TeX-master: "00book" 99.770 -%%% End:
100.1 --- a/fr/wdir-after-commit.svg Sun Aug 16 03:41:39 2009 +0200 100.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 100.3 @@ -1,394 +0,0 @@ 100.4 -<?xml version="1.0" encoding="UTF-8" standalone="no"?> 100.5 -<!-- Created with Inkscape (http://www.inkscape.org/) --> 100.6 -<svg 100.7 - xmlns:dc="http://purl.org/dc/elements/1.1/" 100.8 - xmlns:cc="http://web.resource.org/cc/" 100.9 - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 100.10 - xmlns:svg="http://www.w3.org/2000/svg" 100.11 - xmlns="http://www.w3.org/2000/svg" 100.12 - xmlns:xlink="http://www.w3.org/1999/xlink" 100.13 - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" 100.14 - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" 100.15 - width="744.09448819" 100.16 - height="1052.3622047" 100.17 - id="svg5971" 100.18 - sodipodi:version="0.32" 100.19 - inkscape:version="0.44.1" 100.20 - sodipodi:docbase="/home/bos/hg/hgbook/en" 100.21 - sodipodi:docname="wdir-after-commit.svg"> 100.22 - <defs 100.23 - id="defs5973"> 100.24 - <linearGradient 100.25 - inkscape:collect="always" 100.26 - xlink:href="#linearGradient6049" 100.27 - id="linearGradient6445" 100.28 - gradientUnits="userSpaceOnUse" 100.29 - gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)" 100.30 - x1="333.91171" 100.31 - y1="488.79077" 100.32 - x2="508.94543" 100.33 - y2="263.79077" /> 100.34 - <marker 100.35 - inkscape:stockid="Arrow1Mstart" 100.36 - orient="auto" 100.37 - refY="0.0" 100.38 - refX="0.0" 100.39 - id="Arrow1Mstart" 100.40 - style="overflow:visible"> 100.41 - <path 100.42 - id="path4855" 100.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 " 100.44 - style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none" 100.45 - transform="scale(0.4) translate(10,0)" /> 100.46 - </marker> 100.47 - <linearGradient 100.48 - id="linearGradient6049"> 100.49 - <stop 100.50 - style="stop-color:#686868;stop-opacity:1;" 100.51 - offset="0" 100.52 - id="stop6051" /> 100.53 - <stop 100.54 - style="stop-color:#f0f0f0;stop-opacity:1;" 100.55 - offset="1" 100.56 - id="stop6053" /> 100.57 - </linearGradient> 100.58 - <marker 100.59 - inkscape:stockid="Arrow1Mend" 100.60 - orient="auto" 100.61 - refY="0.0" 100.62 - refX="0.0" 100.63 - id="Arrow1Mend" 100.64 - style="overflow:visible;"> 100.65 - <path 100.66 - id="path4852" 100.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 " 100.68 - style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;" 100.69 - transform="scale(0.4) rotate(180) translate(10,0)" /> 100.70 - </marker> 100.71 - <linearGradient 100.72 - inkscape:collect="always" 100.73 - xlink:href="#linearGradient6049" 100.74 - id="linearGradient6083" 100.75 - gradientUnits="userSpaceOnUse" 100.76 - gradientTransform="translate(-240.0462,-8.633237e-6)" 100.77 - x1="333.91171" 100.78 - y1="488.79077" 100.79 - x2="508.94543" 100.80 - y2="263.79077" /> 100.81 - <linearGradient 100.82 - inkscape:collect="always" 100.83 - xlink:href="#linearGradient6049" 100.84 - id="linearGradient6142" 100.85 - gradientUnits="userSpaceOnUse" 100.86 - gradientTransform="translate(-42.00893,-30.49544)" 100.87 - x1="333.91171" 100.88 - y1="488.79077" 100.89 - x2="508.94543" 100.90 - y2="263.79077" /> 100.91 - <linearGradient 100.92 - inkscape:collect="always" 100.93 - xlink:href="#linearGradient6049" 100.94 - id="linearGradient6193" 100.95 - gradientUnits="userSpaceOnUse" 100.96 - gradientTransform="translate(-240.0462,-8.633237e-6)" 100.97 - x1="333.91171" 100.98 - y1="488.79077" 100.99 - x2="508.94543" 100.100 - y2="263.79077" /> 100.101 - <linearGradient 100.102 - inkscape:collect="always" 100.103 - xlink:href="#linearGradient6049" 100.104 - id="linearGradient6216" 100.105 - gradientUnits="userSpaceOnUse" 100.106 - gradientTransform="translate(-6.0462,-0.664361)" 100.107 - x1="333.91171" 100.108 - y1="488.79077" 100.109 - x2="508.94543" 100.110 - y2="263.79077" /> 100.111 - <linearGradient 100.112 - inkscape:collect="always" 100.113 - xlink:href="#linearGradient6049" 100.114 - id="linearGradient6232" 100.115 - gradientUnits="userSpaceOnUse" 100.116 - gradientTransform="matrix(1.000474,0,0,0.790947,222.8399,50.85693)" 100.117 - x1="333.91171" 100.118 - y1="488.79077" 100.119 - x2="508.94543" 100.120 - y2="263.79077" /> 100.121 - <linearGradient 100.122 - inkscape:collect="always" 100.123 - xlink:href="#linearGradient6049" 100.124 - id="linearGradient6772" 100.125 - gradientUnits="userSpaceOnUse" 100.126 - gradientTransform="matrix(1.000474,0,0,0.790947,222.8399,50.85693)" 100.127 - x1="333.91171" 100.128 - y1="488.79077" 100.129 - x2="508.94543" 100.130 - y2="263.79077" /> 100.131 - </defs> 100.132 - <sodipodi:namedview 100.133 - id="base" 100.134 - pagecolor="#ffffff" 100.135 - bordercolor="#666666" 100.136 - borderopacity="1.0" 100.137 - gridtolerance="10000" 100.138 - guidetolerance="10" 100.139 - objecttolerance="10" 100.140 - inkscape:pageopacity="0.0" 100.141 - inkscape:pageshadow="2" 100.142 - inkscape:zoom="0.90509668" 100.143 - inkscape:cx="390.0539" 100.144 - inkscape:cy="690.49342" 100.145 - inkscape:document-units="px" 100.146 - inkscape:current-layer="layer1" 100.147 - showguides="true" 100.148 - inkscape:guide-bbox="true" 100.149 - inkscape:window-width="906" 100.150 - inkscape:window-height="620" 100.151 - inkscape:window-x="0" 100.152 - inkscape:window-y="25"> 100.153 - <sodipodi:guide 100.154 - orientation="vertical" 100.155 - position="-1.4285714" 100.156 - id="guide6022" /> 100.157 - </sodipodi:namedview> 100.158 - <metadata 100.159 - id="metadata5976"> 100.160 - <rdf:RDF> 100.161 - <cc:Work 100.162 - rdf:about=""> 100.163 - <dc:format>image/svg+xml</dc:format> 100.164 - <dc:type 100.165 - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 100.166 - </cc:Work> 100.167 - </rdf:RDF> 100.168 - </metadata> 100.169 - <g 100.170 - inkscape:label="Layer 1" 100.171 - inkscape:groupmode="layer" 100.172 - id="layer1"> 100.173 - <rect 100.174 - y="245.98355" 100.175 - x="328.23956" 100.176 - height="258.57144" 100.177 - width="174.28572" 100.178 - id="rect6047" 100.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" /> 100.180 - <g 100.181 - id="g6261" 100.182 - transform="translate(234,0)"> 100.183 - <rect 100.184 - y="258.7149" 100.185 - x="114.11369" 100.186 - height="44.537449" 100.187 - width="134.53746" 100.188 - id="rect5983" 100.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" /> 100.190 - <text 100.191 - id="text5985" 100.192 - y="284.47562" 100.193 - x="138.7962" 100.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" 100.195 - xml:space="preserve"><tspan 100.196 - style="font-family:Courier" 100.197 - y="284.47562" 100.198 - x="138.7962" 100.199 - id="tspan5987" 100.200 - sodipodi:role="line">dfbbb33f3fa3</tspan></text> 100.201 - </g> 100.202 - <rect 100.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" 100.204 - id="rect5996" 100.205 - width="134.53746" 100.206 - height="44.537449" 100.207 - x="348.11371" 100.208 - y="320.38159" /> 100.209 - <text 100.210 - xml:space="preserve" 100.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" 100.212 - x="372.7962" 100.213 - y="346.1423" 100.214 - id="text5998"><tspan 100.215 - sodipodi:role="line" 100.216 - id="tspan6000" 100.217 - x="372.7962" 100.218 - y="346.1423" 100.219 - style="font-family:Courier">e7639888bb2f</tspan></text> 100.220 - <rect 100.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" 100.222 - id="rect6004" 100.223 - width="134.53746" 100.224 - height="44.537449" 100.225 - x="348.11371" 100.226 - y="382.04825" /> 100.227 - <text 100.228 - xml:space="preserve" 100.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" 100.230 - x="370.65421" 100.231 - y="407.80896" 100.232 - id="text6006"><tspan 100.233 - sodipodi:role="line" 100.234 - id="tspan6008" 100.235 - x="370.65421" 100.236 - y="407.80896" 100.237 - style="font-family:Courier">7b064d8bac5e</tspan></text> 100.238 - <path 100.239 - inkscape:connector-type="polyline" 100.240 - id="path6018" 100.241 - d="M 415.38242,303.62646 L 415.38242,320.00744" 100.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" /> 100.243 - <path 100.244 - inkscape:connection-end="#rect6004" 100.245 - inkscape:connector-type="polyline" 100.246 - id="path6020" 100.247 - d="M 415.38242,365.29315 L 415.38243,381.67412" 100.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" /> 100.249 - <rect 100.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" 100.251 - id="rect6039" 100.252 - width="134.53746" 100.253 - height="44.537449" 100.254 - x="348.11359" 100.255 - y="443.71487" /> 100.256 - <text 100.257 - xml:space="preserve" 100.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" 100.259 - x="372.79706" 100.260 - y="469.47556" 100.261 - id="text6041"><tspan 100.262 - sodipodi:role="line" 100.263 - id="tspan6043" 100.264 - x="372.79706" 100.265 - y="469.47556" 100.266 - style="fill:#979797;fill-opacity:1;font-family:Courier">000000000000</tspan></text> 100.267 - <path 100.268 - inkscape:connection-end="#rect6039" 100.269 - inkscape:connector-type="polyline" 100.270 - id="path6045" 100.271 - d="M 415.38238,426.95981 L 415.38235,443.34087" 100.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" /> 100.273 - <text 100.274 - xml:space="preserve" 100.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" 100.276 - x="327.66046" 100.277 - y="231.36218" 100.278 - id="text6102"><tspan 100.279 - sodipodi:role="line" 100.280 - id="tspan6104" 100.281 - x="327.66046" 100.282 - y="231.36218">History in repository</tspan></text> 100.283 - <rect 100.284 - y="245.94225" 100.285 - x="557.28418" 100.286 - height="204.51619" 100.287 - width="174.36833" 100.288 - id="rect6140" 100.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" /> 100.290 - <g 100.291 - id="g6130" 100.292 - transform="translate(262.3254,24.38544)"> 100.293 - <rect 100.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" 100.295 - id="rect6106" 100.296 - width="134.53746" 100.297 - height="44.537449" 100.298 - x="314.87415" 100.299 - y="257.95059" /> 100.300 - <text 100.301 - xml:space="preserve" 100.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" 100.303 - x="339.55664" 100.304 - y="283.7113" 100.305 - id="text6108"><tspan 100.306 - sodipodi:role="line" 100.307 - id="tspan6110" 100.308 - x="339.55664" 100.309 - y="283.7113" 100.310 - style="font-family:Courier">dfbbb33f3fa3</tspan></text> 100.311 - </g> 100.312 - <g 100.313 - id="g6135" 100.314 - transform="translate(263.0396,49.83106)"> 100.315 - <rect 100.316 - inkscape:transform-center-y="102.85714" 100.317 - inkscape:transform-center-x="129.28571" 100.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" 100.319 - id="rect6112" 100.320 - width="134.53746" 100.321 - height="44.537449" 100.322 - x="314.15985" 100.323 - y="326.52203" /> 100.324 - <text 100.325 - inkscape:transform-center-y="102.7311" 100.326 - inkscape:transform-center-x="128.69672" 100.327 - xml:space="preserve" 100.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" 100.329 - x="338.84335" 100.330 - y="352.28271" 100.331 - id="text6114"><tspan 100.332 - sodipodi:role="line" 100.333 - id="tspan6116" 100.334 - x="338.84335" 100.335 - y="352.28271" 100.336 - style="fill:#979797;fill-opacity:1;font-family:Courier">000000000000</tspan></text> 100.337 - </g> 100.338 - <text 100.339 - xml:space="preserve" 100.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" 100.341 - x="576.63208" 100.342 - y="270.479" 100.343 - id="text6118"><tspan 100.344 - sodipodi:role="line" 100.345 - id="tspan6120" 100.346 - x="576.63208" 100.347 - y="270.479">First parent</tspan></text> 100.348 - <text 100.349 - xml:space="preserve" 100.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" 100.351 - x="576.07544" 100.352 - y="364.49615" 100.353 - id="text6122"><tspan 100.354 - sodipodi:role="line" 100.355 - id="tspan6124" 100.356 - x="576.07544" 100.357 - y="364.49615">Second parent</tspan></text> 100.358 - <text 100.359 - xml:space="preserve" 100.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" 100.361 - x="556.61743" 100.362 - y="231.36218" 100.363 - id="text6195"><tspan 100.364 - sodipodi:role="line" 100.365 - id="tspan6197" 100.366 - x="556.61743" 100.367 - y="231.36218">Parents of working directory</tspan></text> 100.368 - <path 100.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" 100.370 - d="M 576.82542,297.63008 L 483.02528,287.95831" 100.371 - id="path6266" 100.372 - inkscape:connector-type="polyline" 100.373 - inkscape:connection-start="#g6130" 100.374 - inkscape:connection-end="#g6261" /> 100.375 - <path 100.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" 100.377 - d="M 665.12232,418.17579 L 665.12232,418.17579" 100.378 - id="path6270" 100.379 - inkscape:connector-type="polyline" /> 100.380 - <text 100.381 - xml:space="preserve" 100.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" 100.383 - x="316.86407" 100.384 - y="275.6496" 100.385 - id="text6573"><tspan 100.386 - sodipodi:role="line" 100.387 - id="tspan6575" 100.388 - x="316.86407" 100.389 - y="275.6496" 100.390 - style="text-align:end;text-anchor:end">New</tspan><tspan 100.391 - sodipodi:role="line" 100.392 - x="316.86407" 100.393 - y="290.6496" 100.394 - id="tspan6577" 100.395 - style="text-align:end;text-anchor:end">changeset</tspan></text> 100.396 - </g> 100.397 -</svg>
101.1 --- a/fr/wdir-branch.svg Sun Aug 16 03:41:39 2009 +0200 101.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 101.3 @@ -1,418 +0,0 @@ 101.4 -<?xml version="1.0" encoding="UTF-8" standalone="no"?> 101.5 -<!-- Created with Inkscape (http://www.inkscape.org/) --> 101.6 -<svg 101.7 - xmlns:dc="http://purl.org/dc/elements/1.1/" 101.8 - xmlns:cc="http://web.resource.org/cc/" 101.9 - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 101.10 - xmlns:svg="http://www.w3.org/2000/svg" 101.11 - xmlns="http://www.w3.org/2000/svg" 101.12 - xmlns:xlink="http://www.w3.org/1999/xlink" 101.13 - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" 101.14 - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" 101.15 - width="744.09448819" 101.16 - height="1052.3622047" 101.17 - id="svg5971" 101.18 - sodipodi:version="0.32" 101.19 - inkscape:version="0.44.1" 101.20 - sodipodi:docbase="/home/bos/hg/hgbook/en" 101.21 - sodipodi:docname="wdir-branch.svg"> 101.22 - <defs 101.23 - id="defs5973"> 101.24 - <marker 101.25 - inkscape:stockid="Arrow1Mstart" 101.26 - orient="auto" 101.27 - refY="0.0" 101.28 - refX="0.0" 101.29 - id="Arrow1Mstart" 101.30 - style="overflow:visible"> 101.31 - <path 101.32 - id="path4855" 101.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 " 101.34 - style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none" 101.35 - transform="scale(0.4) translate(10,0)" /> 101.36 - </marker> 101.37 - <linearGradient 101.38 - id="linearGradient6049"> 101.39 - <stop 101.40 - style="stop-color:#686868;stop-opacity:1;" 101.41 - offset="0" 101.42 - id="stop6051" /> 101.43 - <stop 101.44 - style="stop-color:#f0f0f0;stop-opacity:1;" 101.45 - offset="1" 101.46 - id="stop6053" /> 101.47 - </linearGradient> 101.48 - <marker 101.49 - inkscape:stockid="Arrow1Mend" 101.50 - orient="auto" 101.51 - refY="0.0" 101.52 - refX="0.0" 101.53 - id="Arrow1Mend" 101.54 - style="overflow:visible;"> 101.55 - <path 101.56 - id="path4852" 101.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 " 101.58 - style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;" 101.59 - transform="scale(0.4) rotate(180) translate(10,0)" /> 101.60 - </marker> 101.61 - <linearGradient 101.62 - inkscape:collect="always" 101.63 - xlink:href="#linearGradient6049" 101.64 - id="linearGradient6083" 101.65 - gradientUnits="userSpaceOnUse" 101.66 - gradientTransform="translate(-240.0462,-8.633237e-6)" 101.67 - x1="333.91171" 101.68 - y1="488.79077" 101.69 - x2="508.94543" 101.70 - y2="263.79077" /> 101.71 - <linearGradient 101.72 - inkscape:collect="always" 101.73 - xlink:href="#linearGradient6049" 101.74 - id="linearGradient6142" 101.75 - gradientUnits="userSpaceOnUse" 101.76 - gradientTransform="translate(-42.00893,-30.49544)" 101.77 - x1="333.91171" 101.78 - y1="488.79077" 101.79 - x2="508.94543" 101.80 - y2="263.79077" /> 101.81 - <linearGradient 101.82 - inkscape:collect="always" 101.83 - xlink:href="#linearGradient6049" 101.84 - id="linearGradient6193" 101.85 - gradientUnits="userSpaceOnUse" 101.86 - gradientTransform="translate(-240.0462,-8.633237e-6)" 101.87 - x1="333.91171" 101.88 - y1="488.79077" 101.89 - x2="508.94543" 101.90 - y2="263.79077" /> 101.91 - <linearGradient 101.92 - inkscape:collect="always" 101.93 - xlink:href="#linearGradient6049" 101.94 - id="linearGradient6216" 101.95 - gradientUnits="userSpaceOnUse" 101.96 - gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)" 101.97 - x1="333.91171" 101.98 - y1="488.79077" 101.99 - x2="508.94543" 101.100 - y2="263.79077" /> 101.101 - <linearGradient 101.102 - inkscape:collect="always" 101.103 - xlink:href="#linearGradient6049" 101.104 - id="linearGradient6232" 101.105 - gradientUnits="userSpaceOnUse" 101.106 - gradientTransform="matrix(1.000473,0,0,0.790947,-11.16012,50.85693)" 101.107 - x1="333.91171" 101.108 - y1="488.79077" 101.109 - x2="508.94543" 101.110 - y2="263.79077" /> 101.111 - <linearGradient 101.112 - inkscape:collect="always" 101.113 - xlink:href="#linearGradient6049" 101.114 - id="linearGradient6445" 101.115 - gradientUnits="userSpaceOnUse" 101.116 - gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)" 101.117 - x1="333.91171" 101.118 - y1="488.79077" 101.119 - x2="508.94543" 101.120 - y2="263.79077" /> 101.121 - <linearGradient 101.122 - inkscape:collect="always" 101.123 - xlink:href="#linearGradient6049" 101.124 - id="linearGradient6974" 101.125 - gradientUnits="userSpaceOnUse" 101.126 - gradientTransform="matrix(1.911882,0,0,0.789965,-574.7896,51.22599)" 101.127 - x1="333.91171" 101.128 - y1="488.79077" 101.129 - x2="508.94543" 101.130 - y2="263.79077" /> 101.131 - <linearGradient 101.132 - inkscape:collect="always" 101.133 - xlink:href="#linearGradient6049" 101.134 - id="linearGradient6996" 101.135 - gradientUnits="userSpaceOnUse" 101.136 - gradientTransform="matrix(1.000473,0,0,0.790947,112.8399,50.85693)" 101.137 - x1="333.91171" 101.138 - y1="488.79077" 101.139 - x2="508.94543" 101.140 - y2="263.79077" /> 101.141 - </defs> 101.142 - <sodipodi:namedview 101.143 - id="base" 101.144 - pagecolor="#ffffff" 101.145 - bordercolor="#666666" 101.146 - borderopacity="1.0" 101.147 - gridtolerance="10000" 101.148 - guidetolerance="10" 101.149 - objecttolerance="10" 101.150 - inkscape:pageopacity="0.0" 101.151 - inkscape:pageshadow="2" 101.152 - inkscape:zoom="0.90509668" 101.153 - inkscape:cx="345.85973" 101.154 - inkscape:cy="690.49342" 101.155 - inkscape:document-units="px" 101.156 - inkscape:current-layer="layer1" 101.157 - showguides="true" 101.158 - inkscape:guide-bbox="true" 101.159 - inkscape:window-width="906" 101.160 - inkscape:window-height="620" 101.161 - inkscape:window-x="0" 101.162 - inkscape:window-y="25"> 101.163 - <sodipodi:guide 101.164 - orientation="vertical" 101.165 - position="-1.4285714" 101.166 - id="guide6022" /> 101.167 - </sodipodi:namedview> 101.168 - <metadata 101.169 - id="metadata5976"> 101.170 - <rdf:RDF> 101.171 - <cc:Work 101.172 - rdf:about=""> 101.173 - <dc:format>image/svg+xml</dc:format> 101.174 - <dc:type 101.175 - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 101.176 - </cc:Work> 101.177 - </rdf:RDF> 101.178 - </metadata> 101.179 - <g 101.180 - inkscape:label="Layer 1" 101.181 - inkscape:groupmode="layer" 101.182 - id="layer1"> 101.183 - <rect 101.184 - y="246.06918" 101.185 - x="64.325172" 101.186 - height="204.26233" 101.187 - width="333.2135" 101.188 - id="rect6047" 101.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" /> 101.190 - <g 101.191 - id="g1935"> 101.192 - <rect 101.193 - y="266.24374" 101.194 - x="84.113708" 101.195 - height="44.537449" 101.196 - width="134.53746" 101.197 - id="rect5996" 101.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" /> 101.199 - <text 101.200 - id="text5998" 101.201 - y="292.00446" 101.202 - x="108.7962" 101.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" 101.204 - xml:space="preserve"><tspan 101.205 - style="font-family:Courier" 101.206 - y="292.00446" 101.207 - x="108.7962" 101.208 - id="tspan6000" 101.209 - sodipodi:role="line">e7639888bb2f</tspan></text> 101.210 - </g> 101.211 - <g 101.212 - id="g6976" 101.213 - transform="translate(70,0)"> 101.214 - <rect 101.215 - y="327.9104" 101.216 - x="40.113693" 101.217 - height="44.537449" 101.218 - width="134.53746" 101.219 - id="rect6004" 101.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" /> 101.221 - <text 101.222 - id="text6006" 101.223 - y="353.67111" 101.224 - x="62.654205" 101.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" 101.226 - xml:space="preserve"><tspan 101.227 - style="font-family:Courier" 101.228 - y="353.67111" 101.229 - x="62.654205" 101.230 - id="tspan6008" 101.231 - sodipodi:role="line">7b064d8bac5e</tspan></text> 101.232 - </g> 101.233 - <path 101.234 - inkscape:connector-type="polyline" 101.235 - id="path6020" 101.236 - d="M 160.92915,311.15532 L 167.83571,327.53627" 101.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" 101.238 - inkscape:connection-end="#g6976" 101.239 - inkscape:connection-start="#g1935" /> 101.240 - <rect 101.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" 101.242 - id="rect6039" 101.243 - width="134.53746" 101.244 - height="44.537449" 101.245 - x="110.11359" 101.246 - y="389.57703" /> 101.247 - <text 101.248 - xml:space="preserve" 101.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" 101.250 - x="134.79706" 101.251 - y="415.33771" 101.252 - id="text6041"><tspan 101.253 - sodipodi:role="line" 101.254 - id="tspan6043" 101.255 - x="134.79706" 101.256 - y="415.33771" 101.257 - style="fill:#979797;fill-opacity:1;font-family:Courier">000000000000</tspan></text> 101.258 - <path 101.259 - inkscape:connection-end="#rect6039" 101.260 - inkscape:connector-type="polyline" 101.261 - id="path6045" 101.262 - d="M 177.38238,372.82195 L 177.38235,389.20303" 101.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" /> 101.264 - <rect 101.265 - y="245.94225" 101.266 - x="447.28412" 101.267 - height="204.51619" 101.268 - width="174.36833" 101.269 - id="rect6140" 101.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" /> 101.271 - <g 101.272 - id="g6130" 101.273 - transform="translate(152.3254,24.38544)"> 101.274 - <rect 101.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" 101.276 - id="rect6106" 101.277 - width="134.53746" 101.278 - height="44.537449" 101.279 - x="314.87415" 101.280 - y="257.95059" /> 101.281 - <text 101.282 - xml:space="preserve" 101.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" 101.284 - x="339.55664" 101.285 - y="283.7113" 101.286 - id="text6108"><tspan 101.287 - sodipodi:role="line" 101.288 - id="tspan6110" 101.289 - x="339.55664" 101.290 - y="283.7113" 101.291 - style="font-family:Courier">ffb20e1701ea</tspan></text> 101.292 - </g> 101.293 - <g 101.294 - id="g6135" 101.295 - transform="translate(153.0396,49.83106)"> 101.296 - <rect 101.297 - inkscape:transform-center-y="102.85714" 101.298 - inkscape:transform-center-x="129.28571" 101.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" 101.300 - id="rect6112" 101.301 - width="134.53746" 101.302 - height="44.537449" 101.303 - x="314.15985" 101.304 - y="326.52203" /> 101.305 - <text 101.306 - inkscape:transform-center-y="102.7311" 101.307 - inkscape:transform-center-x="128.69672" 101.308 - xml:space="preserve" 101.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" 101.310 - x="338.84335" 101.311 - y="352.28271" 101.312 - id="text6114"><tspan 101.313 - sodipodi:role="line" 101.314 - id="tspan6116" 101.315 - x="338.84335" 101.316 - y="352.28271" 101.317 - style="fill:#979797;fill-opacity:1;font-family:Courier">000000000000</tspan></text> 101.318 - </g> 101.319 - <text 101.320 - xml:space="preserve" 101.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" 101.322 - x="466.63208" 101.323 - y="270.479" 101.324 - id="text6118"><tspan 101.325 - sodipodi:role="line" 101.326 - id="tspan6120" 101.327 - x="466.63208" 101.328 - y="270.479">First parent</tspan></text> 101.329 - <text 101.330 - xml:space="preserve" 101.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" 101.332 - x="466.07544" 101.333 - y="364.49615" 101.334 - id="text6122"><tspan 101.335 - sodipodi:role="line" 101.336 - id="tspan6124" 101.337 - x="466.07544" 101.338 - y="364.49615">Second parent</tspan></text> 101.339 - <text 101.340 - xml:space="preserve" 101.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" 101.342 - x="446.61743" 101.343 - y="231.36218" 101.344 - id="text6195"><tspan 101.345 - sodipodi:role="line" 101.346 - id="tspan6197" 101.347 - x="446.61743" 101.348 - y="231.36218">Parents of working directory</tspan></text> 101.349 - <path 101.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" 101.351 - d="M 466.82542,300.21999 L 377.00207,294.39744" 101.352 - id="path6266" 101.353 - inkscape:connector-type="polyline" 101.354 - inkscape:connection-start="#g6130" 101.355 - inkscape:connection-end="#rect1925" /> 101.356 - <path 101.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" 101.358 - d="M 665.12232,418.17579 L 665.12232,418.17579" 101.359 - id="path6270" 101.360 - inkscape:connector-type="polyline" /> 101.361 - <g 101.362 - id="g2845"> 101.363 - <rect 101.364 - y="266.24374" 101.365 - x="242.09048" 101.366 - height="44.537449" 101.367 - width="134.53746" 101.368 - id="rect1925" 101.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" /> 101.370 - <text 101.371 - id="text1927" 101.372 - y="292.00446" 101.373 - x="266.77298" 101.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" 101.375 - xml:space="preserve"><tspan 101.376 - style="font-family:Courier" 101.377 - y="292.00446" 101.378 - x="266.77298" 101.379 - id="tspan1929" 101.380 - sodipodi:role="line">ffb20e1701ea</tspan></text> 101.381 - </g> 101.382 - <path 101.383 - inkscape:connector-type="polyline" 101.384 - id="path1933" 101.385 - d="M 260.89978,311.15532 L 225.84185,327.53627" 101.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" 101.387 - inkscape:connection-end="#g6976" /> 101.388 - <text 101.389 - xml:space="preserve" 101.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" 101.391 - x="109.45568" 101.392 - y="231.4554" 101.393 - id="text2837"><tspan 101.394 - sodipodi:role="line" 101.395 - id="tspan2839" 101.396 - x="109.45568" 101.397 - y="231.4554">Pre-existing head</tspan></text> 101.398 - <text 101.399 - xml:space="preserve" 101.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" 101.401 - x="237.54184" 101.402 - y="231.4554" 101.403 - id="text2841"><tspan 101.404 - sodipodi:role="line" 101.405 - id="tspan2843" 101.406 - x="237.54184" 101.407 - y="231.4554">Newly created head (and tip)</tspan></text> 101.408 - <path 101.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)" 101.410 - d="M 148.05048,235.87482 L 149.94915,265.86962" 101.411 - id="path2850" 101.412 - inkscape:connector-type="polyline" 101.413 - inkscape:connection-end="#g1935" /> 101.414 - <path 101.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)" 101.416 - d="M 303.83495,238.08453 L 306.87874,265.86962" 101.417 - id="path2852" 101.418 - inkscape:connector-type="polyline" 101.419 - inkscape:connection-end="#g2845" /> 101.420 - </g> 101.421 -</svg>
102.1 --- a/fr/wdir-merge.svg Sun Aug 16 03:41:39 2009 +0200 102.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 102.3 @@ -1,425 +0,0 @@ 102.4 -<?xml version="1.0" encoding="UTF-8" standalone="no"?> 102.5 -<!-- Created with Inkscape (http://www.inkscape.org/) --> 102.6 -<svg 102.7 - xmlns:dc="http://purl.org/dc/elements/1.1/" 102.8 - xmlns:cc="http://web.resource.org/cc/" 102.9 - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 102.10 - xmlns:svg="http://www.w3.org/2000/svg" 102.11 - xmlns="http://www.w3.org/2000/svg" 102.12 - xmlns:xlink="http://www.w3.org/1999/xlink" 102.13 - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" 102.14 - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" 102.15 - width="744.09448819" 102.16 - height="1052.3622047" 102.17 - id="svg5971" 102.18 - sodipodi:version="0.32" 102.19 - inkscape:version="0.44.1" 102.20 - sodipodi:docbase="/home/bos/hg/hgbook/en" 102.21 - sodipodi:docname="wdir-merge.svg"> 102.22 - <defs 102.23 - id="defs5973"> 102.24 - <marker 102.25 - inkscape:stockid="Arrow1Mstart" 102.26 - orient="auto" 102.27 - refY="0.0" 102.28 - refX="0.0" 102.29 - id="Arrow1Mstart" 102.30 - style="overflow:visible"> 102.31 - <path 102.32 - id="path4855" 102.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 " 102.34 - style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none" 102.35 - transform="scale(0.4) translate(10,0)" /> 102.36 - </marker> 102.37 - <linearGradient 102.38 - id="linearGradient6049"> 102.39 - <stop 102.40 - style="stop-color:#686868;stop-opacity:1;" 102.41 - offset="0" 102.42 - id="stop6051" /> 102.43 - <stop 102.44 - style="stop-color:#f0f0f0;stop-opacity:1;" 102.45 - offset="1" 102.46 - id="stop6053" /> 102.47 - </linearGradient> 102.48 - <marker 102.49 - inkscape:stockid="Arrow1Mend" 102.50 - orient="auto" 102.51 - refY="0.0" 102.52 - refX="0.0" 102.53 - id="Arrow1Mend" 102.54 - style="overflow:visible;"> 102.55 - <path 102.56 - id="path4852" 102.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 " 102.58 - style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;" 102.59 - transform="scale(0.4) rotate(180) translate(10,0)" /> 102.60 - </marker> 102.61 - <linearGradient 102.62 - inkscape:collect="always" 102.63 - xlink:href="#linearGradient6049" 102.64 - id="linearGradient6083" 102.65 - gradientUnits="userSpaceOnUse" 102.66 - gradientTransform="translate(-240.0462,-8.633237e-6)" 102.67 - x1="333.91171" 102.68 - y1="488.79077" 102.69 - x2="508.94543" 102.70 - y2="263.79077" /> 102.71 - <linearGradient 102.72 - inkscape:collect="always" 102.73 - xlink:href="#linearGradient6049" 102.74 - id="linearGradient6142" 102.75 - gradientUnits="userSpaceOnUse" 102.76 - gradientTransform="translate(-42.00893,-30.49544)" 102.77 - x1="333.91171" 102.78 - y1="488.79077" 102.79 - x2="508.94543" 102.80 - y2="263.79077" /> 102.81 - <linearGradient 102.82 - inkscape:collect="always" 102.83 - xlink:href="#linearGradient6049" 102.84 - id="linearGradient6193" 102.85 - gradientUnits="userSpaceOnUse" 102.86 - gradientTransform="translate(-240.0462,-8.633237e-6)" 102.87 - x1="333.91171" 102.88 - y1="488.79077" 102.89 - x2="508.94543" 102.90 - y2="263.79077" /> 102.91 - <linearGradient 102.92 - inkscape:collect="always" 102.93 - xlink:href="#linearGradient6049" 102.94 - id="linearGradient6216" 102.95 - gradientUnits="userSpaceOnUse" 102.96 - gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)" 102.97 - x1="333.91171" 102.98 - y1="488.79077" 102.99 - x2="508.94543" 102.100 - y2="263.79077" /> 102.101 - <linearGradient 102.102 - inkscape:collect="always" 102.103 - xlink:href="#linearGradient6049" 102.104 - id="linearGradient6232" 102.105 - gradientUnits="userSpaceOnUse" 102.106 - gradientTransform="matrix(1.000473,0,0,0.790947,-11.16012,50.85693)" 102.107 - x1="333.91171" 102.108 - y1="488.79077" 102.109 - x2="508.94543" 102.110 - y2="263.79077" /> 102.111 - <linearGradient 102.112 - inkscape:collect="always" 102.113 - xlink:href="#linearGradient6049" 102.114 - id="linearGradient6445" 102.115 - gradientUnits="userSpaceOnUse" 102.116 - gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)" 102.117 - x1="333.91171" 102.118 - y1="488.79077" 102.119 - x2="508.94543" 102.120 - y2="263.79077" /> 102.121 - <linearGradient 102.122 - inkscape:collect="always" 102.123 - xlink:href="#linearGradient6049" 102.124 - id="linearGradient6974" 102.125 - gradientUnits="userSpaceOnUse" 102.126 - gradientTransform="matrix(1.911882,0,0,0.789965,-574.7896,51.22599)" 102.127 - x1="333.91171" 102.128 - y1="488.79077" 102.129 - x2="508.94543" 102.130 - y2="263.79077" /> 102.131 - <linearGradient 102.132 - inkscape:collect="always" 102.133 - xlink:href="#linearGradient6049" 102.134 - id="linearGradient6996" 102.135 - gradientUnits="userSpaceOnUse" 102.136 - gradientTransform="matrix(1.000473,0,0,0.790947,112.8399,50.85693)" 102.137 - x1="333.91171" 102.138 - y1="488.79077" 102.139 - x2="508.94543" 102.140 - y2="263.79077" /> 102.141 - </defs> 102.142 - <sodipodi:namedview 102.143 - id="base" 102.144 - pagecolor="#ffffff" 102.145 - bordercolor="#666666" 102.146 - borderopacity="1.0" 102.147 - gridtolerance="10000" 102.148 - guidetolerance="10" 102.149 - objecttolerance="10" 102.150 - inkscape:pageopacity="0.0" 102.151 - inkscape:pageshadow="2" 102.152 - inkscape:zoom="1.28" 102.153 - inkscape:cx="345.85973" 102.154 - inkscape:cy="690.49342" 102.155 - inkscape:document-units="px" 102.156 - inkscape:current-layer="layer1" 102.157 - showguides="true" 102.158 - inkscape:guide-bbox="true" 102.159 - inkscape:window-width="906" 102.160 - inkscape:window-height="620" 102.161 - inkscape:window-x="0" 102.162 - inkscape:window-y="25"> 102.163 - <sodipodi:guide 102.164 - orientation="vertical" 102.165 - position="-1.4285714" 102.166 - id="guide6022" /> 102.167 - </sodipodi:namedview> 102.168 - <metadata 102.169 - id="metadata5976"> 102.170 - <rdf:RDF> 102.171 - <cc:Work 102.172 - rdf:about=""> 102.173 - <dc:format>image/svg+xml</dc:format> 102.174 - <dc:type 102.175 - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 102.176 - </cc:Work> 102.177 - </rdf:RDF> 102.178 - </metadata> 102.179 - <g 102.180 - inkscape:label="Layer 1" 102.181 - inkscape:groupmode="layer" 102.182 - id="layer1"> 102.183 - <rect 102.184 - y="246.06918" 102.185 - x="64.325172" 102.186 - height="204.26233" 102.187 - width="333.2135" 102.188 - id="rect6047" 102.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" /> 102.190 - <g 102.191 - id="g6976" 102.192 - transform="translate(70,0)"> 102.193 - <rect 102.194 - y="327.9104" 102.195 - x="40.113693" 102.196 - height="44.537449" 102.197 - width="134.53746" 102.198 - id="rect6004" 102.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" /> 102.200 - <text 102.201 - id="text6006" 102.202 - y="353.67111" 102.203 - x="62.654205" 102.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" 102.205 - xml:space="preserve"><tspan 102.206 - style="font-family:Courier" 102.207 - y="353.67111" 102.208 - x="62.654205" 102.209 - id="tspan6008" 102.210 - sodipodi:role="line">7b064d8bac5e</tspan></text> 102.211 - </g> 102.212 - <path 102.213 - inkscape:connector-type="polyline" 102.214 - id="path6020" 102.215 - d="M 160.92915,311.15532 L 167.83571,327.53627" 102.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" 102.217 - inkscape:connection-end="#g6976" 102.218 - inkscape:connection-start="#g1935" /> 102.219 - <rect 102.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" 102.221 - id="rect6039" 102.222 - width="134.53746" 102.223 - height="44.537449" 102.224 - x="110.11359" 102.225 - y="389.57703" /> 102.226 - <text 102.227 - xml:space="preserve" 102.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" 102.229 - x="134.79706" 102.230 - y="415.33771" 102.231 - id="text6041"><tspan 102.232 - sodipodi:role="line" 102.233 - id="tspan6043" 102.234 - x="134.79706" 102.235 - y="415.33771" 102.236 - style="fill:#979797;fill-opacity:1;font-family:Courier">000000000000</tspan></text> 102.237 - <path 102.238 - inkscape:connection-end="#rect6039" 102.239 - inkscape:connector-type="polyline" 102.240 - id="path6045" 102.241 - d="M 177.38238,372.82195 L 177.38235,389.20303" 102.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" /> 102.243 - <rect 102.244 - y="245.94225" 102.245 - x="447.28412" 102.246 - height="204.51619" 102.247 - width="174.36833" 102.248 - id="rect6140" 102.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" /> 102.250 - <g 102.251 - id="g6130" 102.252 - transform="translate(152.3254,24.38544)"> 102.253 - <rect 102.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" 102.255 - id="rect6106" 102.256 - width="134.53746" 102.257 - height="44.537449" 102.258 - x="314.87415" 102.259 - y="257.95059" /> 102.260 - <text 102.261 - xml:space="preserve" 102.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" 102.263 - x="339.55664" 102.264 - y="283.7113" 102.265 - id="text6108"><tspan 102.266 - sodipodi:role="line" 102.267 - id="tspan6110" 102.268 - x="339.55664" 102.269 - y="283.7113" 102.270 - style="font-family:Courier">ffb20e1701ea</tspan></text> 102.271 - </g> 102.272 - <g 102.273 - id="g6135" 102.274 - transform="translate(153.0396,49.83106)"> 102.275 - <rect 102.276 - inkscape:transform-center-y="102.85714" 102.277 - inkscape:transform-center-x="129.28571" 102.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" 102.279 - id="rect6112" 102.280 - width="134.53746" 102.281 - height="44.537449" 102.282 - x="314.15985" 102.283 - y="326.52203" /> 102.284 - <text 102.285 - inkscape:transform-center-y="102.7311" 102.286 - inkscape:transform-center-x="128.69672" 102.287 - xml:space="preserve" 102.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" 102.289 - x="338.84335" 102.290 - y="352.28271" 102.291 - id="text6114"><tspan 102.292 - sodipodi:role="line" 102.293 - id="tspan6116" 102.294 - x="338.84335" 102.295 - y="352.28271" 102.296 - style="fill:black;fill-opacity:1;font-family:Courier">e7639888bb2f</tspan></text> 102.297 - </g> 102.298 - <text 102.299 - xml:space="preserve" 102.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" 102.301 - x="466.63208" 102.302 - y="270.479" 102.303 - id="text6118"><tspan 102.304 - sodipodi:role="line" 102.305 - id="tspan6120" 102.306 - x="466.63208" 102.307 - y="270.479">First parent (unchanged)</tspan></text> 102.308 - <text 102.309 - xml:space="preserve" 102.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" 102.311 - x="466.07544" 102.312 - y="364.49615" 102.313 - id="text6122"><tspan 102.314 - sodipodi:role="line" 102.315 - id="tspan6124" 102.316 - x="466.07544" 102.317 - y="364.49615">Second parent</tspan></text> 102.318 - <text 102.319 - xml:space="preserve" 102.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" 102.321 - x="446.61743" 102.322 - y="231.36218" 102.323 - id="text6195"><tspan 102.324 - sodipodi:role="line" 102.325 - id="tspan6197" 102.326 - x="446.61743" 102.327 - y="231.36218">Parents of working directory</tspan></text> 102.328 - <path 102.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" 102.330 - d="M 466.82542,300.21999 L 377.00207,294.39744" 102.331 - id="path6266" 102.332 - inkscape:connector-type="polyline" 102.333 - inkscape:connection-start="#g6130" 102.334 - inkscape:connection-end="#rect1925" /> 102.335 - <path 102.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" 102.337 - d="M 665.12232,418.17579 L 665.12232,418.17579" 102.338 - id="path6270" 102.339 - inkscape:connector-type="polyline" /> 102.340 - <g 102.341 - id="g2845"> 102.342 - <rect 102.343 - y="266.24374" 102.344 - x="242.09048" 102.345 - height="44.537449" 102.346 - width="134.53746" 102.347 - id="rect1925" 102.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" /> 102.349 - <text 102.350 - id="text1927" 102.351 - y="292.00446" 102.352 - x="266.77298" 102.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" 102.354 - xml:space="preserve"><tspan 102.355 - style="font-family:Courier" 102.356 - y="292.00446" 102.357 - x="266.77298" 102.358 - id="tspan1929" 102.359 - sodipodi:role="line">ffb20e1701ea</tspan></text> 102.360 - </g> 102.361 - <path 102.362 - inkscape:connector-type="polyline" 102.363 - id="path1933" 102.364 - d="M 260.89978,311.15532 L 225.84185,327.53627" 102.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" 102.366 - inkscape:connection-end="#g6976" /> 102.367 - <text 102.368 - xml:space="preserve" 102.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" 102.370 - x="109.45568" 102.371 - y="231.4554" 102.372 - id="text2837"><tspan 102.373 - sodipodi:role="line" 102.374 - id="tspan2839" 102.375 - x="109.45568" 102.376 - y="231.4554">Pre-existing head</tspan></text> 102.377 - <text 102.378 - xml:space="preserve" 102.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" 102.380 - x="237.54184" 102.381 - y="231.4554" 102.382 - id="text2841"><tspan 102.383 - sodipodi:role="line" 102.384 - id="tspan2843" 102.385 - x="237.54184" 102.386 - y="231.4554">Newly created head (and tip)</tspan></text> 102.387 - <path 102.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)" 102.389 - d="M 148.05048,235.87482 L 149.94915,265.86962" 102.390 - id="path2850" 102.391 - inkscape:connector-type="polyline" 102.392 - inkscape:connection-end="#g1935" /> 102.393 - <path 102.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)" 102.395 - d="M 303.83495,238.08453 L 306.87874,265.86962" 102.396 - id="path2852" 102.397 - inkscape:connector-type="polyline" 102.398 - inkscape:connection-end="#g2845" /> 102.399 - <path 102.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" 102.401 - d="M 466.82545,379.17944 L 219.0253,307.95488" 102.402 - id="path3016" 102.403 - inkscape:connector-type="polyline" 102.404 - inkscape:connection-start="#g6135" 102.405 - inkscape:connection-end="#g1935" /> 102.406 - <g 102.407 - id="g1935"> 102.408 - <rect 102.409 - y="266.24374" 102.410 - x="84.113708" 102.411 - height="44.537449" 102.412 - width="134.53746" 102.413 - id="rect5996" 102.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" /> 102.415 - <text 102.416 - id="text5998" 102.417 - y="292.00446" 102.418 - x="108.7962" 102.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" 102.420 - xml:space="preserve"><tspan 102.421 - style="font-family:Courier" 102.422 - y="292.00446" 102.423 - x="108.7962" 102.424 - id="tspan6000" 102.425 - sodipodi:role="line">e7639888bb2f</tspan></text> 102.426 - </g> 102.427 - </g> 102.428 -</svg>
103.1 --- a/fr/wdir-pre-branch.svg Sun Aug 16 03:41:39 2009 +0200 103.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 103.3 @@ -1,364 +0,0 @@ 103.4 -<?xml version="1.0" encoding="UTF-8" standalone="no"?> 103.5 -<!-- Created with Inkscape (http://www.inkscape.org/) --> 103.6 -<svg 103.7 - xmlns:dc="http://purl.org/dc/elements/1.1/" 103.8 - xmlns:cc="http://web.resource.org/cc/" 103.9 - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 103.10 - xmlns:svg="http://www.w3.org/2000/svg" 103.11 - xmlns="http://www.w3.org/2000/svg" 103.12 - xmlns:xlink="http://www.w3.org/1999/xlink" 103.13 - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" 103.14 - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" 103.15 - width="744.09448819" 103.16 - height="1052.3622047" 103.17 - id="svg5971" 103.18 - sodipodi:version="0.32" 103.19 - inkscape:version="0.44.1" 103.20 - sodipodi:docbase="/home/bos/hg/hgbook/en" 103.21 - sodipodi:docname="wdir-branch.svg"> 103.22 - <defs 103.23 - id="defs5973"> 103.24 - <marker 103.25 - inkscape:stockid="Arrow1Mstart" 103.26 - orient="auto" 103.27 - refY="0.0" 103.28 - refX="0.0" 103.29 - id="Arrow1Mstart" 103.30 - style="overflow:visible"> 103.31 - <path 103.32 - id="path4855" 103.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 " 103.34 - style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none" 103.35 - transform="scale(0.4) translate(10,0)" /> 103.36 - </marker> 103.37 - <linearGradient 103.38 - id="linearGradient6049"> 103.39 - <stop 103.40 - style="stop-color:#686868;stop-opacity:1;" 103.41 - offset="0" 103.42 - id="stop6051" /> 103.43 - <stop 103.44 - style="stop-color:#f0f0f0;stop-opacity:1;" 103.45 - offset="1" 103.46 - id="stop6053" /> 103.47 - </linearGradient> 103.48 - <marker 103.49 - inkscape:stockid="Arrow1Mend" 103.50 - orient="auto" 103.51 - refY="0.0" 103.52 - refX="0.0" 103.53 - id="Arrow1Mend" 103.54 - style="overflow:visible;"> 103.55 - <path 103.56 - id="path4852" 103.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 " 103.58 - style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;" 103.59 - transform="scale(0.4) rotate(180) translate(10,0)" /> 103.60 - </marker> 103.61 - <linearGradient 103.62 - inkscape:collect="always" 103.63 - xlink:href="#linearGradient6049" 103.64 - id="linearGradient6083" 103.65 - gradientUnits="userSpaceOnUse" 103.66 - gradientTransform="translate(-240.0462,-8.633237e-6)" 103.67 - x1="333.91171" 103.68 - y1="488.79077" 103.69 - x2="508.94543" 103.70 - y2="263.79077" /> 103.71 - <linearGradient 103.72 - inkscape:collect="always" 103.73 - xlink:href="#linearGradient6049" 103.74 - id="linearGradient6142" 103.75 - gradientUnits="userSpaceOnUse" 103.76 - gradientTransform="translate(-42.00893,-30.49544)" 103.77 - x1="333.91171" 103.78 - y1="488.79077" 103.79 - x2="508.94543" 103.80 - y2="263.79077" /> 103.81 - <linearGradient 103.82 - inkscape:collect="always" 103.83 - xlink:href="#linearGradient6049" 103.84 - id="linearGradient6193" 103.85 - gradientUnits="userSpaceOnUse" 103.86 - gradientTransform="translate(-240.0462,-8.633237e-6)" 103.87 - x1="333.91171" 103.88 - y1="488.79077" 103.89 - x2="508.94543" 103.90 - y2="263.79077" /> 103.91 - <linearGradient 103.92 - inkscape:collect="always" 103.93 - xlink:href="#linearGradient6049" 103.94 - id="linearGradient6216" 103.95 - gradientUnits="userSpaceOnUse" 103.96 - gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)" 103.97 - x1="333.91171" 103.98 - y1="488.79077" 103.99 - x2="508.94543" 103.100 - y2="263.79077" /> 103.101 - <linearGradient 103.102 - inkscape:collect="always" 103.103 - xlink:href="#linearGradient6049" 103.104 - id="linearGradient6232" 103.105 - gradientUnits="userSpaceOnUse" 103.106 - gradientTransform="matrix(1.000473,0,0,0.790947,-11.16012,50.85693)" 103.107 - x1="333.91171" 103.108 - y1="488.79077" 103.109 - x2="508.94543" 103.110 - y2="263.79077" /> 103.111 - <linearGradient 103.112 - inkscape:collect="always" 103.113 - xlink:href="#linearGradient6049" 103.114 - id="linearGradient6445" 103.115 - gradientUnits="userSpaceOnUse" 103.116 - gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)" 103.117 - x1="333.91171" 103.118 - y1="488.79077" 103.119 - x2="508.94543" 103.120 - y2="263.79077" /> 103.121 - <linearGradient 103.122 - inkscape:collect="always" 103.123 - xlink:href="#linearGradient6049" 103.124 - id="linearGradient6974" 103.125 - gradientUnits="userSpaceOnUse" 103.126 - gradientTransform="matrix(1.000474,0,0,0.790947,-314.246,50.85694)" 103.127 - x1="333.91171" 103.128 - y1="488.79077" 103.129 - x2="508.94543" 103.130 - y2="263.79077" /> 103.131 - <linearGradient 103.132 - inkscape:collect="always" 103.133 - xlink:href="#linearGradient6049" 103.134 - id="linearGradient6996" 103.135 - gradientUnits="userSpaceOnUse" 103.136 - gradientTransform="matrix(1.000473,0,0,0.790947,-85.16012,50.85693)" 103.137 - x1="333.91171" 103.138 - y1="488.79077" 103.139 - x2="508.94543" 103.140 - y2="263.79077" /> 103.141 - </defs> 103.142 - <sodipodi:namedview 103.143 - id="base" 103.144 - pagecolor="#ffffff" 103.145 - bordercolor="#666666" 103.146 - borderopacity="1.0" 103.147 - gridtolerance="10000" 103.148 - guidetolerance="10" 103.149 - objecttolerance="10" 103.150 - inkscape:pageopacity="0.0" 103.151 - inkscape:pageshadow="2" 103.152 - inkscape:zoom="0.90509668" 103.153 - inkscape:cx="390.0539" 103.154 - inkscape:cy="690.49342" 103.155 - inkscape:document-units="px" 103.156 - inkscape:current-layer="layer1" 103.157 - showguides="true" 103.158 - inkscape:guide-bbox="true" 103.159 - inkscape:window-width="906" 103.160 - inkscape:window-height="620" 103.161 - inkscape:window-x="0" 103.162 - inkscape:window-y="25"> 103.163 - <sodipodi:guide 103.164 - orientation="vertical" 103.165 - position="-1.4285714" 103.166 - id="guide6022" /> 103.167 - </sodipodi:namedview> 103.168 - <metadata 103.169 - id="metadata5976"> 103.170 - <rdf:RDF> 103.171 - <cc:Work 103.172 - rdf:about=""> 103.173 - <dc:format>image/svg+xml</dc:format> 103.174 - <dc:type 103.175 - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 103.176 - </cc:Work> 103.177 - </rdf:RDF> 103.178 - </metadata> 103.179 - <g 103.180 - inkscape:label="Layer 1" 103.181 - inkscape:groupmode="layer" 103.182 - id="layer1"> 103.183 - <rect 103.184 - y="245.94225" 103.185 - x="20.198257" 103.186 - height="204.51619" 103.187 - width="174.36833" 103.188 - id="rect6047" 103.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" /> 103.190 - <rect 103.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" 103.192 - id="rect5996" 103.193 - width="134.53746" 103.194 - height="44.537449" 103.195 - x="40.113693" 103.196 - y="266.24374" /> 103.197 - <text 103.198 - xml:space="preserve" 103.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" 103.200 - x="64.796204" 103.201 - y="292.00446" 103.202 - id="text5998"><tspan 103.203 - sodipodi:role="line" 103.204 - id="tspan6000" 103.205 - x="64.796204" 103.206 - y="292.00446" 103.207 - style="font-family:Courier">e7639888bb2f</tspan></text> 103.208 - <g 103.209 - id="g6976"> 103.210 - <rect 103.211 - y="327.9104" 103.212 - x="40.113693" 103.213 - height="44.537449" 103.214 - width="134.53746" 103.215 - id="rect6004" 103.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" /> 103.217 - <text 103.218 - id="text6006" 103.219 - y="353.67111" 103.220 - x="62.654205" 103.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" 103.222 - xml:space="preserve"><tspan 103.223 - style="font-family:Courier" 103.224 - y="353.67111" 103.225 - x="62.654205" 103.226 - id="tspan6008" 103.227 - sodipodi:role="line">7b064d8bac5e</tspan></text> 103.228 - </g> 103.229 - <path 103.230 - inkscape:connection-end="#rect6004" 103.231 - inkscape:connector-type="polyline" 103.232 - id="path6020" 103.233 - d="M 107.38242,311.15529 L 107.38242,327.53626" 103.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" /> 103.235 - <rect 103.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" 103.237 - id="rect6039" 103.238 - width="134.53746" 103.239 - height="44.537449" 103.240 - x="40.113571" 103.241 - y="389.57703" /> 103.242 - <text 103.243 - xml:space="preserve" 103.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" 103.245 - x="64.797073" 103.246 - y="415.33771" 103.247 - id="text6041"><tspan 103.248 - sodipodi:role="line" 103.249 - id="tspan6043" 103.250 - x="64.797073" 103.251 - y="415.33771" 103.252 - style="fill:#979797;fill-opacity:1;font-family:Courier">000000000000</tspan></text> 103.253 - <path 103.254 - inkscape:connection-end="#rect6039" 103.255 - inkscape:connector-type="polyline" 103.256 - id="path6045" 103.257 - d="M 107.38238,372.82195 L 107.38235,389.20301" 103.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" /> 103.259 - <text 103.260 - xml:space="preserve" 103.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" 103.262 - x="19.660461" 103.263 - y="231.36218" 103.264 - id="text6102"><tspan 103.265 - sodipodi:role="line" 103.266 - id="tspan6104" 103.267 - x="19.660461" 103.268 - y="231.36218">History in repository</tspan></text> 103.269 - <rect 103.270 - y="245.94225" 103.271 - x="249.28412" 103.272 - height="204.51619" 103.273 - width="174.36833" 103.274 - id="rect6140" 103.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" /> 103.276 - <g 103.277 - id="g6130" 103.278 - transform="translate(-45.67459,24.38544)"> 103.279 - <rect 103.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" 103.281 - id="rect6106" 103.282 - width="134.53746" 103.283 - height="44.537449" 103.284 - x="314.87415" 103.285 - y="257.95059" /> 103.286 - <text 103.287 - xml:space="preserve" 103.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" 103.289 - x="339.55664" 103.290 - y="283.7113" 103.291 - id="text6108"><tspan 103.292 - sodipodi:role="line" 103.293 - id="tspan6110" 103.294 - x="339.55664" 103.295 - y="283.7113" 103.296 - style="font-family:Courier">7b064d8bac5e</tspan></text> 103.297 - </g> 103.298 - <g 103.299 - id="g6135" 103.300 - transform="translate(-44.96042,49.83106)"> 103.301 - <rect 103.302 - inkscape:transform-center-y="102.85714" 103.303 - inkscape:transform-center-x="129.28571" 103.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" 103.305 - id="rect6112" 103.306 - width="134.53746" 103.307 - height="44.537449" 103.308 - x="314.15985" 103.309 - y="326.52203" /> 103.310 - <text 103.311 - inkscape:transform-center-y="102.7311" 103.312 - inkscape:transform-center-x="128.69672" 103.313 - xml:space="preserve" 103.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" 103.315 - x="338.84335" 103.316 - y="352.28271" 103.317 - id="text6114"><tspan 103.318 - sodipodi:role="line" 103.319 - id="tspan6116" 103.320 - x="338.84335" 103.321 - y="352.28271" 103.322 - style="fill:#979797;fill-opacity:1;font-family:Courier">000000000000</tspan></text> 103.323 - </g> 103.324 - <text 103.325 - xml:space="preserve" 103.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" 103.327 - x="268.63208" 103.328 - y="270.479" 103.329 - id="text6118"><tspan 103.330 - sodipodi:role="line" 103.331 - id="tspan6120" 103.332 - x="268.63208" 103.333 - y="270.479">First parent</tspan></text> 103.334 - <text 103.335 - xml:space="preserve" 103.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" 103.337 - x="268.07544" 103.338 - y="364.49615" 103.339 - id="text6122"><tspan 103.340 - sodipodi:role="line" 103.341 - id="tspan6124" 103.342 - x="268.07544" 103.343 - y="364.49615">Second parent</tspan></text> 103.344 - <text 103.345 - xml:space="preserve" 103.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" 103.347 - x="248.61746" 103.348 - y="231.36218" 103.349 - id="text6195"><tspan 103.350 - sodipodi:role="line" 103.351 - id="tspan6197" 103.352 - x="248.61746" 103.353 - y="231.36218">Parents of working directory</tspan></text> 103.354 - <path 103.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" 103.356 - d="M 268.82543,318.06163 L 175.02528,336.72225" 103.357 - id="path6266" 103.358 - inkscape:connector-type="polyline" 103.359 - inkscape:connection-end="#g6976" 103.360 - inkscape:connection-start="#g6130" /> 103.361 - <path 103.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" 103.363 - d="M 665.12232,418.17579 L 665.12232,418.17579" 103.364 - id="path6270" 103.365 - inkscape:connector-type="polyline" /> 103.366 - </g> 103.367 -</svg>
104.1 --- a/fr/wdir.svg Sun Aug 16 03:41:39 2009 +0200 104.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 104.3 @@ -1,348 +0,0 @@ 104.4 -<?xml version="1.0" encoding="UTF-8" standalone="no"?> 104.5 -<!-- Created with Inkscape (http://www.inkscape.org/) --> 104.6 -<svg 104.7 - xmlns:dc="http://purl.org/dc/elements/1.1/" 104.8 - xmlns:cc="http://web.resource.org/cc/" 104.9 - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 104.10 - xmlns:svg="http://www.w3.org/2000/svg" 104.11 - xmlns="http://www.w3.org/2000/svg" 104.12 - xmlns:xlink="http://www.w3.org/1999/xlink" 104.13 - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" 104.14 - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" 104.15 - width="744.09448819" 104.16 - height="1052.3622047" 104.17 - id="svg5971" 104.18 - sodipodi:version="0.32" 104.19 - inkscape:version="0.44.1" 104.20 - sodipodi:docbase="/home/bos/hg/hgbook/en" 104.21 - sodipodi:docname="wdir.svg"> 104.22 - <defs 104.23 - id="defs5973"> 104.24 - <marker 104.25 - inkscape:stockid="Arrow1Mstart" 104.26 - orient="auto" 104.27 - refY="0.0" 104.28 - refX="0.0" 104.29 - id="Arrow1Mstart" 104.30 - style="overflow:visible"> 104.31 - <path 104.32 - id="path4855" 104.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 " 104.34 - style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none" 104.35 - transform="scale(0.4) translate(10,0)" /> 104.36 - </marker> 104.37 - <linearGradient 104.38 - id="linearGradient6049"> 104.39 - <stop 104.40 - style="stop-color:#686868;stop-opacity:1;" 104.41 - offset="0" 104.42 - id="stop6051" /> 104.43 - <stop 104.44 - style="stop-color:#f0f0f0;stop-opacity:1;" 104.45 - offset="1" 104.46 - id="stop6053" /> 104.47 - </linearGradient> 104.48 - <marker 104.49 - inkscape:stockid="Arrow1Mend" 104.50 - orient="auto" 104.51 - refY="0.0" 104.52 - refX="0.0" 104.53 - id="Arrow1Mend" 104.54 - style="overflow:visible;"> 104.55 - <path 104.56 - id="path4852" 104.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 " 104.58 - style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;" 104.59 - transform="scale(0.4) rotate(180) translate(10,0)" /> 104.60 - </marker> 104.61 - <linearGradient 104.62 - inkscape:collect="always" 104.63 - xlink:href="#linearGradient6049" 104.64 - id="linearGradient6083" 104.65 - gradientUnits="userSpaceOnUse" 104.66 - gradientTransform="translate(-240.0462,-8.633237e-6)" 104.67 - x1="333.91171" 104.68 - y1="488.79077" 104.69 - x2="508.94543" 104.70 - y2="263.79077" /> 104.71 - <linearGradient 104.72 - inkscape:collect="always" 104.73 - xlink:href="#linearGradient6049" 104.74 - id="linearGradient6142" 104.75 - gradientUnits="userSpaceOnUse" 104.76 - gradientTransform="translate(-42.00893,-30.49544)" 104.77 - x1="333.91171" 104.78 - y1="488.79077" 104.79 - x2="508.94543" 104.80 - y2="263.79077" /> 104.81 - <linearGradient 104.82 - inkscape:collect="always" 104.83 - xlink:href="#linearGradient6049" 104.84 - id="linearGradient6193" 104.85 - gradientUnits="userSpaceOnUse" 104.86 - gradientTransform="translate(-240.0462,-8.633237e-6)" 104.87 - x1="333.91171" 104.88 - y1="488.79077" 104.89 - x2="508.94543" 104.90 - y2="263.79077" /> 104.91 - <linearGradient 104.92 - inkscape:collect="always" 104.93 - xlink:href="#linearGradient6049" 104.94 - id="linearGradient6216" 104.95 - gradientUnits="userSpaceOnUse" 104.96 - gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)" 104.97 - x1="333.91171" 104.98 - y1="488.79077" 104.99 - x2="508.94543" 104.100 - y2="263.79077" /> 104.101 - <linearGradient 104.102 - inkscape:collect="always" 104.103 - xlink:href="#linearGradient6049" 104.104 - id="linearGradient6232" 104.105 - gradientUnits="userSpaceOnUse" 104.106 - gradientTransform="matrix(1.000473,0,0,0.790947,-11.16012,50.85693)" 104.107 - x1="333.91171" 104.108 - y1="488.79077" 104.109 - x2="508.94543" 104.110 - y2="263.79077" /> 104.111 - <linearGradient 104.112 - inkscape:collect="always" 104.113 - xlink:href="#linearGradient6049" 104.114 - id="linearGradient6445" 104.115 - gradientUnits="userSpaceOnUse" 104.116 - gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)" 104.117 - x1="333.91171" 104.118 - y1="488.79077" 104.119 - x2="508.94543" 104.120 - y2="263.79077" /> 104.121 - </defs> 104.122 - <sodipodi:namedview 104.123 - id="base" 104.124 - pagecolor="#ffffff" 104.125 - bordercolor="#666666" 104.126 - borderopacity="1.0" 104.127 - gridtolerance="10000" 104.128 - guidetolerance="10" 104.129 - objecttolerance="10" 104.130 - inkscape:pageopacity="0.0" 104.131 - inkscape:pageshadow="2" 104.132 - inkscape:zoom="0.90509668" 104.133 - inkscape:cx="390.0539" 104.134 - inkscape:cy="690.49342" 104.135 - inkscape:document-units="px" 104.136 - inkscape:current-layer="layer1" 104.137 - showguides="true" 104.138 - inkscape:guide-bbox="true" 104.139 - inkscape:window-width="906" 104.140 - inkscape:window-height="620" 104.141 - inkscape:window-x="0" 104.142 - inkscape:window-y="25"> 104.143 - <sodipodi:guide 104.144 - orientation="vertical" 104.145 - position="-1.4285714" 104.146 - id="guide6022" /> 104.147 - </sodipodi:namedview> 104.148 - <metadata 104.149 - id="metadata5976"> 104.150 - <rdf:RDF> 104.151 - <cc:Work 104.152 - rdf:about=""> 104.153 - <dc:format>image/svg+xml</dc:format> 104.154 - <dc:type 104.155 - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 104.156 - </cc:Work> 104.157 - </rdf:RDF> 104.158 - </metadata> 104.159 - <g 104.160 - inkscape:label="Layer 1" 104.161 - inkscape:groupmode="layer" 104.162 - id="layer1"> 104.163 - <g 104.164 - id="g6431" 104.165 - transform="translate(0,-0.137863)"> 104.166 - <rect 104.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" 104.168 - id="rect6047" 104.169 - width="174.36833" 104.170 - height="204.51619" 104.171 - x="94.198257" 104.172 - y="246.08011" /> 104.173 - <rect 104.174 - y="266.38159" 104.175 - x="114.11369" 104.176 - height="44.537449" 104.177 - width="134.53746" 104.178 - id="rect5996" 104.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" /> 104.180 - <text 104.181 - id="text5998" 104.182 - y="292.1423" 104.183 - x="138.7962" 104.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" 104.185 - xml:space="preserve"><tspan 104.186 - style="font-family:Courier" 104.187 - y="292.1423" 104.188 - x="138.7962" 104.189 - id="tspan6000" 104.190 - sodipodi:role="line">e7639888bb2f</tspan></text> 104.191 - <rect 104.192 - y="328.04825" 104.193 - x="114.11369" 104.194 - height="44.537449" 104.195 - width="134.53746" 104.196 - id="rect6004" 104.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" /> 104.198 - <text 104.199 - id="text6006" 104.200 - y="353.80896" 104.201 - x="136.65421" 104.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" 104.203 - xml:space="preserve"><tspan 104.204 - style="font-family:Courier" 104.205 - y="353.80896" 104.206 - x="136.65421" 104.207 - id="tspan6008" 104.208 - sodipodi:role="line">7b064d8bac5e</tspan></text> 104.209 - <path 104.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" 104.211 - d="M 181.38242,311.29315 L 181.38242,327.67412" 104.212 - id="path6020" 104.213 - inkscape:connector-type="polyline" 104.214 - inkscape:connection-end="#rect6004" /> 104.215 - <rect 104.216 - y="389.71487" 104.217 - x="114.11357" 104.218 - height="44.537449" 104.219 - width="134.53746" 104.220 - id="rect6039" 104.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" /> 104.222 - <text 104.223 - id="text6041" 104.224 - y="415.47556" 104.225 - x="138.79707" 104.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" 104.227 - xml:space="preserve"><tspan 104.228 - style="fill:#979797;fill-opacity:1;font-family:Courier" 104.229 - y="415.47556" 104.230 - x="138.79707" 104.231 - id="tspan6043" 104.232 - sodipodi:role="line">000000000000</tspan></text> 104.233 - <path 104.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" 104.235 - d="M 181.38238,372.95981 L 181.38235,389.34087" 104.236 - id="path6045" 104.237 - inkscape:connector-type="polyline" 104.238 - inkscape:connection-end="#rect6039" /> 104.239 - </g> 104.240 - <text 104.241 - xml:space="preserve" 104.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" 104.243 - x="93.660484" 104.244 - y="231.36218" 104.245 - id="text6102"><tspan 104.246 - sodipodi:role="line" 104.247 - id="tspan6104" 104.248 - x="93.660484" 104.249 - y="231.36218">History in repository</tspan></text> 104.250 - <g 104.251 - id="g6416"> 104.252 - <rect 104.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" 104.254 - id="rect6140" 104.255 - width="174.36833" 104.256 - height="204.51619" 104.257 - x="323.28412" 104.258 - y="245.94225" /> 104.259 - <g 104.260 - transform="translate(28.32541,24.38544)" 104.261 - id="g6130"> 104.262 - <rect 104.263 - y="257.95059" 104.264 - x="314.87415" 104.265 - height="44.537449" 104.266 - width="134.53746" 104.267 - id="rect6106" 104.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" /> 104.269 - <text 104.270 - id="text6108" 104.271 - y="283.7113" 104.272 - x="339.55664" 104.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" 104.274 - xml:space="preserve"><tspan 104.275 - style="font-family:Courier" 104.276 - y="283.7113" 104.277 - x="339.55664" 104.278 - id="tspan6110" 104.279 - sodipodi:role="line">e7639888bb2f</tspan></text> 104.280 - </g> 104.281 - <g 104.282 - transform="translate(29.03958,49.83106)" 104.283 - id="g6135"> 104.284 - <rect 104.285 - y="326.52203" 104.286 - x="314.15985" 104.287 - height="44.537449" 104.288 - width="134.53746" 104.289 - id="rect6112" 104.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" 104.291 - inkscape:transform-center-x="129.28571" 104.292 - inkscape:transform-center-y="102.85714" /> 104.293 - <text 104.294 - id="text6114" 104.295 - y="352.28271" 104.296 - x="338.84335" 104.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" 104.298 - xml:space="preserve" 104.299 - inkscape:transform-center-x="128.69672" 104.300 - inkscape:transform-center-y="102.7311"><tspan 104.301 - style="fill:#979797;fill-opacity:1;font-family:Courier" 104.302 - y="352.28271" 104.303 - x="338.84335" 104.304 - id="tspan6116" 104.305 - sodipodi:role="line">000000000000</tspan></text> 104.306 - </g> 104.307 - <text 104.308 - id="text6118" 104.309 - y="270.479" 104.310 - x="342.63208" 104.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" 104.312 - xml:space="preserve"><tspan 104.313 - y="270.479" 104.314 - x="342.63208" 104.315 - id="tspan6120" 104.316 - sodipodi:role="line">First parent</tspan></text> 104.317 - <text 104.318 - id="text6122" 104.319 - y="364.49615" 104.320 - x="342.07544" 104.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" 104.322 - xml:space="preserve"><tspan 104.323 - y="364.49615" 104.324 - x="342.07544" 104.325 - id="tspan6124" 104.326 - sodipodi:role="line">Second parent</tspan></text> 104.327 - </g> 104.328 - <text 104.329 - xml:space="preserve" 104.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" 104.331 - x="322.61746" 104.332 - y="231.36218" 104.333 - id="text6195"><tspan 104.334 - sodipodi:role="line" 104.335 - id="tspan6197" 104.336 - x="322.61746" 104.337 - y="231.36218">Parents of working directory</tspan></text> 104.338 - <path 104.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" 104.340 - d="M 342.82543,299.89384 L 249.02528,293.36123" 104.341 - id="path6266" 104.342 - inkscape:connector-type="polyline" 104.343 - inkscape:connection-start="#g6130" 104.344 - inkscape:connection-end="#rect5996" /> 104.345 - <path 104.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" 104.347 - d="M 665.12232,418.17579 L 665.12232,418.17579" 104.348 - id="path6270" 104.349 - inkscape:connector-type="polyline" /> 104.350 - </g> 104.351 -</svg>