hgbook
changeset 135:0707489b90fd
Merge.
author | Bryan O'Sullivan <bos@serpentine.com> |
---|---|
date | Mon Mar 05 20:16:36 2007 -0800 (2007-03-05) |
parents | b727a63518d4 1e013fbe35f7 |
children | 7b5894fffc37 |
files | en/examples/mq.diff en/hook.tex |
line diff
1.1 --- a/.hgignore Fri Jul 21 22:42:19 2006 -0700 1.2 +++ b/.hgignore Mon Mar 05 20:16:36 2007 -0800 1.3 @@ -5,6 +5,7 @@ 1.4 1.5 beta/*.tex 1.6 build_id.tex 1.7 +*.4[ct][ct] 1.8 *.aux 1.9 *.bbl 1.10 *.bib 1.11 @@ -20,6 +21,8 @@ 1.12 *.out 1.13 *.pdf 1.14 *.png 1.15 +*.ps 1.16 +*.run 1.17 *.tmp 1.18 *.toc 1.19 *.xref
2.1 --- a/en/00book.tex Fri Jul 21 22:42:19 2006 -0700 2.2 +++ b/en/00book.tex Mon Mar 05 20:16:36 2007 -0800 2.3 @@ -37,15 +37,27 @@ 2.4 2.5 \include{preface} 2.6 \include{intro} 2.7 +\include{tour-basic} 2.8 +\include{tour-merge} 2.9 +\include{concepts} 2.10 +\include{daily} 2.11 +\include{filenames} 2.12 +\include{undo} 2.13 \include{hook} 2.14 +\include{template} 2.15 \include{mq} 2.16 +\include{mq-collab} 2.17 2.18 \appendix 2.19 +\include{cmdref} 2.20 +\include{mq-ref} 2.21 +\include{srcinstall} 2.22 \include{license} 2.23 \addcontentsline{toc}{chapter}{Bibliography} 2.24 \bibliographystyle{alpha} 2.25 \bibliography{99book} 2.26 2.27 +\addcontentsline{toc}{chapter}{Index} 2.28 \printindex 2.29 2.30 \end{document}
3.1 --- a/en/99book.bib Fri Jul 21 22:42:19 2006 -0700 3.2 +++ b/en/99book.bib Mon Mar 05 20:16:36 2007 -0800 3.3 @@ -36,7 +36,7 @@ 3.4 @Misc{web:rej, 3.5 author = {Chris Mason}, 3.6 title = {\texttt{rej}--help solve patch rejects}, 3.7 - note = {\url{ftp://ftp.suse.com/pub/people/mason/rej/}}, 3.8 + note = {\url{http://oss.oracle.com/mercurial}}, 3.9 } 3.10 3.11 @Misc{web:wiggle, 3.12 @@ -45,3 +45,20 @@ 3.13 note = {\url{http://cgi.cse.unsw.edu.au/~neilb/source/wiggle/}}, 3.14 } 3.15 3.16 +@Misc{web:mysql-python, 3.17 + author = {Andy Dustman}, 3.18 + title = {MySQL for Python}, 3.19 + note = {\url{http://sourceforge.net/projects/mysql-python}}, 3.20 +} 3.21 + 3.22 +@Misc{web:changelog, 3.23 + author = {Richard Stallman, GNU Project volunteers}, 3.24 + title = {GNU Coding Standards---Change Logs}, 3.25 + note = {\url{http://www.gnu.org/prep/standards/html_node/Change-Logs.html}}, 3.26 +} 3.27 + 3.28 +@Misc{web:macpython, 3.29 + author = {Bob Ippolito, Ronald Oussoren}, 3.30 + title = {Universal MacPython}, 3.31 + note = {\url{http://bob.pythonmac.org/archives/2006/04/10/python-and-universal-binaries-on-mac-os-x/}}, 3.32 +}
4.1 --- a/en/99defs.tex Fri Jul 21 22:42:19 2006 -0700 4.2 +++ b/en/99defs.tex Mon Mar 05 20:16:36 2007 -0800 4.3 @@ -29,6 +29,16 @@ 4.4 % Mercurial command, with arguments. 4.5 \newcommand{\hgcmdargs}[2]{\index{\texttt{#1} command}``\texttt{hg #1 #2}''} 4.6 4.7 +\newcommand{\tplkword}[1]{\index{\texttt{#1} template keyword}\index{template keywords!\texttt{#1}}\texttt{#1}} 4.8 + 4.9 +\newcommand{\tplkwfilt}[2]{\index{\texttt{#1} template keyword!\texttt{#2} 4.10 + filter}\index{template filters!\texttt{#2}}\index{\texttt{#2} 4.11 + template filter}\texttt{#2}} 4.12 + 4.13 +\newcommand{\tplfilter}[1]{\index{template 4.14 + filters!\texttt{#1}}\index{\texttt{#1} template 4.15 + filter}\texttt{#1}} 4.16 + 4.17 % Shell/system command. 4.18 \newcommand{\command}[1]{\index{\texttt{#1} command}\texttt{#1}} 4.19 4.20 @@ -55,7 +65,7 @@ 4.21 4.22 % Named item in a hgrc file section. 4.23 \newcommand{\rcitem}[2]{\index{\texttt{hgrc} file!\texttt{#1} 4.24 - section!\texttt{#2} entry}\texttt{#1.#2}} 4.25 + section!\texttt{#2} entry}\texttt{#2}} 4.26 4.27 % hgrc file. 4.28 \newcommand{\hgrc}{\index{\texttt{hgrc} file}\texttt{hgrc}} 4.29 @@ -74,11 +84,18 @@ 4.30 \newcommand{\pymodclass}[2]{\index{\texttt{#1} module!\texttt{#2} 4.31 class}\texttt{#1.#2}} 4.32 4.33 +% Python function in a module. 4.34 +\newcommand{\pymodfunc}[2]{\index{\texttt{#1} module!\texttt{#2} 4.35 + function}\texttt{#1.#2}} 4.36 + 4.37 % Note: blah blah. 4.38 \newsavebox{\notebox} 4.39 \newenvironment{note}% 4.40 {\begin{lrbox}{\notebox}\begin{minipage}{0.7\textwidth}\textbf{Note:}\space}% 4.41 {\end{minipage}\end{lrbox}\fbox{\usebox{\notebox}}} 4.42 +\newenvironment{caution}% 4.43 + {\begin{lrbox}{\notebox}\begin{minipage}{0.7\textwidth}\textbf{Caution:}\space}% 4.44 + {\end{minipage}\end{lrbox}\fbox{\usebox{\notebox}}} 4.45 4.46 % Code sample, eating 4 characters of leading space. 4.47 \DefineVerbatimEnvironment{codesample4}{Verbatim}{frame=single,gobble=4,numbers=left,commandchars=\\\{\}} 4.48 @@ -89,6 +106,9 @@ 4.49 % Interaction from the examples directory. 4.50 \newcommand{\interaction}[1]{\VerbatimInput[frame=single,numbers=left,commandchars=\\\{\}]{examples/#1.out}} 4.51 4.52 +% Example code from the examples directory. 4.53 +\newcommand{\excode}[1]{\VerbatimInput[frame=single,numbers=left,commandchars=\\\{\}]{../examples/#1}} 4.54 + 4.55 % Graphics inclusion. 4.56 \ifpdf 4.57 \newcommand{\grafix}[1]{\includegraphics{#1}} 4.58 @@ -96,6 +116,15 @@ 4.59 \newcommand{\grafix}[1]{\includegraphics{#1.png}} 4.60 \fi 4.61 4.62 +% Reference entry for a command. 4.63 +\newcommand{\cmdref}[2]{\section{\hgcmd{#1}---#2}\label{cmdref:#1}\index{\texttt{#1} command}} 4.64 + 4.65 +% Reference entry for a command option with long and short forms. 4.66 +\newcommand{\optref}[3]{\subsubsection{\hgopt{#1}{--#3}, also \hgopt{#1}{-#2}}} 4.67 + 4.68 +% Reference entry for a command option with only long form. 4.69 +\newcommand{\loptref}[2]{\subsubsection{\hgopt{#1}{--#2} option}} 4.70 + 4.71 %%% Local Variables: 4.72 %%% mode: latex 4.73 %%% TeX-master: "00book"
5.1 --- a/en/Makefile Fri Jul 21 22:42:19 2006 -0700 5.2 +++ b/en/Makefile Mon Mar 05 20:16:36 2007 -0800 5.3 @@ -1,28 +1,78 @@ 5.4 # This makefile requires GNU make. 5.5 5.6 -hg_id := $(shell hg parents --template '{node|short}\n' | head -1) 5.7 +hg_id := $(shell hg parents --template '{node|short}\n') 5.8 5.9 sources := \ 5.10 00book.tex \ 5.11 99book.bib \ 5.12 99defs.tex \ 5.13 build_id.tex \ 5.14 + cmdref.tex \ 5.15 + concepts.tex \ 5.16 + daily.tex \ 5.17 + filenames.tex \ 5.18 hook.tex \ 5.19 intro.tex \ 5.20 mq.tex \ 5.21 - preface.tex 5.22 + mq-collab.tex \ 5.23 + mq-ref.tex \ 5.24 + preface.tex \ 5.25 + srcinstall.tex \ 5.26 + template.tex \ 5.27 + tour-basic.tex \ 5.28 + tour-merge.tex \ 5.29 + undo.tex 5.30 5.31 image-sources := \ 5.32 - mq-stack.svg 5.33 + filelog.svg \ 5.34 + kdiff3.png \ 5.35 + metadata.svg \ 5.36 + mq-stack.svg \ 5.37 + revlog.svg \ 5.38 + snapshot.svg \ 5.39 + tour-history.svg \ 5.40 + tour-merge-conflict.svg \ 5.41 + tour-merge-merge.svg \ 5.42 + tour-merge-pull.svg \ 5.43 + tour-merge-sep-repos.svg \ 5.44 + undo-manual.dot \ 5.45 + undo-manual-merge.dot \ 5.46 + undo-non-tip.dot \ 5.47 + undo-simple.dot \ 5.48 + wdir.svg \ 5.49 + wdir-after-commit.svg \ 5.50 + wdir-branch.svg \ 5.51 + wdir-merge.svg \ 5.52 + wdir-pre-branch.svg 5.53 + 5.54 +image-dot := $(filter %.dot,$(image-sources)) 5.55 +image-svg := $(filter %.svg,$(image-sources)) 5.56 +image-png := $(filter %.png,$(image-sources)) 5.57 5.58 example-sources := \ 5.59 - examples/run-example \ 5.60 - examples/hook.simple \ 5.61 - examples/mq.qinit-help \ 5.62 - examples/mq.diff \ 5.63 - examples/mq.tarball \ 5.64 - examples/mq.tools \ 5.65 - examples/mq.tutorial 5.66 + backout \ 5.67 + bisect \ 5.68 + cmdref \ 5.69 + daily.copy \ 5.70 + daily.files \ 5.71 + daily.rename \ 5.72 + daily.revert \ 5.73 + filenames \ 5.74 + hook.msglen \ 5.75 + hook.simple \ 5.76 + hook.ws \ 5.77 + mq.guards \ 5.78 + mq.qinit-help \ 5.79 + mq.dodiff \ 5.80 + mq.id \ 5.81 + mq.tarball \ 5.82 + mq.tools \ 5.83 + mq.tutorial \ 5.84 + rollback \ 5.85 + template.simple \ 5.86 + template.svnstyle \ 5.87 + tour \ 5.88 + tour-merge-conflict 5.89 5.90 latex-options = \ 5.91 -interaction batchmode \ 5.92 @@ -44,7 +94,9 @@ 5.93 if grep 'Reference.*undefined' $(@:.pdf=.log); then exit 1; fi 5.94 endef 5.95 5.96 -pdf/hgbook.pdf: $(sources) $(image-sources:%.svg=%.pdf) examples 5.97 +image-pdf := $(image-dot:%.dot=%.pdf) $(image-svg:%.svg=%.pdf) $(image-png) 5.98 + 5.99 +pdf/hgbook.pdf: $(sources) $(image-pdf) examples 5.100 $(call pdf) 5.101 5.102 html: html/onepage/hgbook.html html/split/hgbook.html 5.103 @@ -69,11 +121,13 @@ 5.104 perl -pi -e 's/�([0-7][0-9a-f]);/chr(hex($$1))/egi' $(dir $(1))/*.html 5.105 endef 5.106 5.107 -html/onepage/hgbook.html: $(sources) $(image-sources:%.svg=%.png) examples 5.108 +image-html := $(image-dot:%.dot=%.png) $(image-svg:%.svg=%.png) $(image-png) 5.109 + 5.110 +html/onepage/hgbook.html: $(sources) $(image-html) examples 5.111 $(call htlatex,$@,$<) 5.112 cp $(image-sources:%.svg=%.png) $(dir $@) 5.113 5.114 -html/split/hgbook.html: $(sources) $(image-sources:%.svg=%.png) examples 5.115 +html/split/hgbook.html: $(sources) $(image-html) examples 5.116 $(call htlatex,$@,$<,2) 5.117 cp $(image-sources:%.svg=%.png) $(dir $@) 5.118 5.119 @@ -98,6 +152,9 @@ 5.120 %.png: %.svg 5.121 inkscape -D -e $@ $< 5.122 5.123 +%.svg: %.dot 5.124 + dot -Tsvg -o $@ $< 5.125 + 5.126 # Produce eps & pdf for the pdf 5.127 5.128 %.pdf: %.eps 5.129 @@ -106,14 +163,24 @@ 5.130 %.eps: %.svg 5.131 inkscape -E $@ $< 5.132 5.133 +%.eps: %.dot 5.134 + dot -Tps -o $@ $< 5.135 + 5.136 examples: examples/.run 5.137 5.138 -examples/.run: $(example-sources) 5.139 - cd examples && ./run-example 5.140 +examples/.run: $(example-sources:%=examples/%.run) 5.141 + touch examples/.run 5.142 + 5.143 +examples/%.run: examples/% examples/run-example 5.144 + cd examples && ./run-example $(notdir $<) 5.145 5.146 build_id.tex: $(wildcard ../.hg/00changelog.[id]) 5.147 echo -n $(hg_id) > build_id.tex 5.148 5.149 clean: 5.150 - rm -rf beta html pdf *.eps *.pdf *.png *.aux *.dvi *.log *.out \ 5.151 - examples/*.out examples/.run build_id.tex 5.152 + rm -rf beta html pdf \ 5.153 + $(image-dot:%.dot=%.pdf) \ 5.154 + $(image-dot:%.dot=%.png) \ 5.155 + $(image-svg:%.svg=%.pdf) \ 5.156 + $(image-svg:%.svg=%.png) \ 5.157 + examples/*.{out,run} examples/.run build_id.tex
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/en/cmdref.py Mon Mar 05 20:16:36 2007 -0800 6.3 @@ -0,0 +1,156 @@ 6.4 +#!/usr/bin/env python 6.5 + 6.6 +import getopt 6.7 +import itertools 6.8 +import os 6.9 +import re 6.10 +import sys 6.11 + 6.12 +def usage(exitcode): 6.13 + print >> sys.stderr, ('usage: %s [-H|--hidden] hg_repo' % 6.14 + os.path.basename(sys.argv[0])) 6.15 + sys.exit(exitcode) 6.16 + 6.17 +try: 6.18 + opts, args = getopt.getopt(sys.argv[1:], 'AHh?', ['all', 'help', 'hidden']) 6.19 + opt_all = False 6.20 + opt_hidden = False 6.21 + for o, a in opts: 6.22 + if o in ('-h', '-?', '--help'): 6.23 + usage(0) 6.24 + if o in ('-A', '--all'): 6.25 + opt_all = True 6.26 + if o in ('-H', '--hidden'): 6.27 + opt_hidden = True 6.28 +except getopt.GetoptError, err: 6.29 + print >> sys.stderr, 'error:', err 6.30 + usage(1) 6.31 + 6.32 +try: 6.33 + hg_repo, ltx_file = args 6.34 +except ValueError: 6.35 + usage(1) 6.36 + 6.37 +if not os.path.isfile(os.path.join(hg_repo, 'mercurial', 'commands.py')): 6.38 + print >> sys.stderr, ('error: %r does not contain mercurial code' % 6.39 + hg_repo) 6.40 + sys.exit(1) 6.41 + 6.42 +sys.path.insert(0, hg_repo) 6.43 + 6.44 +from mercurial import commands 6.45 + 6.46 +def get_commands(): 6.47 + seen = {} 6.48 + for name, info in sorted(commands.table.iteritems()): 6.49 + aliases = name.split('|', 1) 6.50 + name = aliases.pop(0).lstrip('^') 6.51 + function, options, synopsis = info 6.52 + seen[name] = {} 6.53 + for shortopt, longopt, arg, desc in options: 6.54 + seen[name][longopt] = shortopt 6.55 + return seen 6.56 + 6.57 +def cmd_filter((name, aliases, options)): 6.58 + if opt_all: 6.59 + return True 6.60 + if opt_hidden: 6.61 + return name.startswith('debug') 6.62 + return not name.startswith('debug') 6.63 + 6.64 +def scan(ltx_file): 6.65 + cmdref_re = re.compile(r'^\\cmdref{(?P<cmd>\w+)}') 6.66 + optref_re = re.compile(r'^\\l?optref{(?P<cmd>\w+)}' 6.67 + r'(?:{(?P<short>[^}])})?' 6.68 + r'{(?P<long>[^}]+)}') 6.69 + 6.70 + seen = {} 6.71 + locs = {} 6.72 + for lnum, line in enumerate(open(ltx_file)): 6.73 + m = cmdref_re.match(line) 6.74 + if m: 6.75 + d = m.groupdict() 6.76 + cmd = d['cmd'] 6.77 + seen[cmd] = {} 6.78 + locs[cmd] = lnum + 1 6.79 + continue 6.80 + m = optref_re.match(line) 6.81 + if m: 6.82 + d = m.groupdict() 6.83 + seen[d['cmd']][d['long']] = d['short'] 6.84 + continue 6.85 + return seen, locs 6.86 + 6.87 +documented, locs = scan(ltx_file) 6.88 +known = get_commands() 6.89 + 6.90 +doc_set = set(documented) 6.91 +known_set = set(known) 6.92 + 6.93 +errors = 0 6.94 + 6.95 +for nonexistent in sorted(doc_set.difference(known_set)): 6.96 + print >> sys.stderr, ('%s:%d: %r command does not exist' % 6.97 + (ltx_file, locs[nonexistent], nonexistent)) 6.98 + errors += 1 6.99 + 6.100 +def optcmp(a, b): 6.101 + la, sa = a 6.102 + lb, sb = b 6.103 + sc = cmp(sa, sb) 6.104 + if sc: 6.105 + return sc 6.106 + return cmp(la, lb) 6.107 + 6.108 +for cmd in doc_set.intersection(known_set): 6.109 + doc_opts = documented[cmd] 6.110 + known_opts = known[cmd] 6.111 + 6.112 + do_set = set(doc_opts) 6.113 + ko_set = set(known_opts) 6.114 + 6.115 + for nonexistent in sorted(do_set.difference(ko_set)): 6.116 + print >> sys.stderr, ('%s:%d: %r option to %r command does not exist' % 6.117 + (ltx_file, locs[cmd], nonexistent, cmd)) 6.118 + errors += 1 6.119 + 6.120 + def mycmp(la, lb): 6.121 + sa = known_opts[la] 6.122 + sb = known_opts[lb] 6.123 + return optcmp((la, sa), (lb, sb)) 6.124 + 6.125 + for undocumented in sorted(ko_set.difference(do_set), cmp=mycmp): 6.126 + print >> sys.stderr, ('%s:%d: %r option to %r command not documented' % 6.127 + (ltx_file, locs[cmd], undocumented, cmd)) 6.128 + shortopt = known_opts[undocumented] 6.129 + if shortopt: 6.130 + print '\optref{%s}{%s}{%s}' % (cmd, shortopt, undocumented) 6.131 + else: 6.132 + print '\loptref{%s}{%s}' % (cmd, undocumented) 6.133 + errors += 1 6.134 + sys.stdout.flush() 6.135 + 6.136 +if errors: 6.137 + sys.exit(1) 6.138 + 6.139 +sorted_locs = sorted(locs.iteritems(), key=lambda x:x[1]) 6.140 + 6.141 +def next_loc(cmd): 6.142 + for i, (name, loc) in enumerate(sorted_locs): 6.143 + if name >= cmd: 6.144 + return sorted_locs[i-1][1] + 1 6.145 + return loc 6.146 + 6.147 +for undocumented in sorted(known_set.difference(doc_set)): 6.148 + print >> sys.stderr, ('%s:%d: %r command not documented' % 6.149 + (ltx_file, next_loc(undocumented), undocumented)) 6.150 + print '\cmdref{%s}' % undocumented 6.151 + for longopt, shortopt in sorted(known[undocumented].items(), cmp=optcmp): 6.152 + if shortopt: 6.153 + print '\optref{%s}{%s}{%s}' % (undocumented, shortopt, longopt) 6.154 + else: 6.155 + print '\loptref{%s}{%s}' % (undocumented, longopt) 6.156 + sys.stdout.flush() 6.157 + errors += 1 6.158 + 6.159 +sys.exit(errors and 1 or 0)
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/en/cmdref.tex Mon Mar 05 20:16:36 2007 -0800 7.3 @@ -0,0 +1,176 @@ 7.4 +\chapter{Command reference} 7.5 +\label{cmdref} 7.6 + 7.7 +\cmdref{add}{add files at the next commit} 7.8 +\optref{add}{I}{include} 7.9 +\optref{add}{X}{exclude} 7.10 +\optref{add}{n}{dry-run} 7.11 + 7.12 +\cmdref{diff}{print changes in history or working directory} 7.13 + 7.14 +Show differences between revisions for the specified files or 7.15 +directories, using the unified diff format. For a description of the 7.16 +unified diff format, see section~\ref{sec:mq:patch}. 7.17 + 7.18 +By default, this command does not print diffs for files that Mercurial 7.19 +considers to contain binary data. To control this behaviour, see the 7.20 +\hgopt{diff}{-a} and \hgopt{diff}{--git} options. 7.21 + 7.22 +\subsection{Options} 7.23 + 7.24 +\loptref{diff}{nodates} 7.25 + 7.26 +Omit date and time information when printing diff headers. 7.27 + 7.28 +\optref{diff}{B}{ignore-blank-lines} 7.29 + 7.30 +Do not print changes that only insert or delete blank lines. A line 7.31 +that contains only whitespace is not considered blank. 7.32 + 7.33 +\optref{diff}{I}{include} 7.34 + 7.35 +Exclude files and directories whose names match the given patterns. 7.36 + 7.37 +\optref{diff}{X}{exclude} 7.38 + 7.39 +Include files and directories whose names match the given patterns. 7.40 + 7.41 +\optref{diff}{a}{text} 7.42 + 7.43 +If this option is not specified, \hgcmd{diff} will refuse to print 7.44 +diffs for files that it detects as binary. Specifying \hgopt{diff}{-a} 7.45 +forces \hgcmd{diff} to treat all files as text, and generate diffs for 7.46 +all of them. 7.47 + 7.48 +This option is useful for files that are ``mostly text'' but have a 7.49 +few embedded NUL characters. If you use it on files that contain a 7.50 +lot of binary data, its output will be incomprehensible. 7.51 + 7.52 +\optref{diff}{b}{ignore-space-change} 7.53 + 7.54 +Do not print a line if the only change to that line is in the amount 7.55 +of white space it contains. 7.56 + 7.57 +\optref{diff}{g}{git} 7.58 + 7.59 +Print \command{git}-compatible diffs. XXX reference a format 7.60 +description. 7.61 + 7.62 +\optref{diff}{p}{show-function} 7.63 + 7.64 +Display the name of the enclosing function in a hunk header, using a 7.65 +simple heuristic. This functionality is enabled by default, so the 7.66 +\hgopt{diff}{-p} option has no effect unless you change the value of 7.67 +the \rcitem{diff}{showfunc} config item, as in the following example. 7.68 +\interaction{cmdref.diff-p} 7.69 + 7.70 +\optref{diff}{r}{rev} 7.71 + 7.72 +Specify one or more revisions to compare. The \hgcmd{diff} command 7.73 +accepts up to two \hgopt{diff}{-r} options to specify the revisions to 7.74 +compare. 7.75 + 7.76 +\begin{enumerate} 7.77 +\setcounter{enumi}{0} 7.78 +\item Display the differences between the parent revision of the 7.79 + working directory and the working directory. 7.80 +\item Display the differences between the specified changeset and the 7.81 + working directory. 7.82 +\item Display the differences between the two specified changesets. 7.83 +\end{enumerate} 7.84 + 7.85 +You can specify two revisions using either two \hgopt{diff}{-r} 7.86 +options or revision range notation. For example, the two revision 7.87 +specifications below are equivalent. 7.88 +\begin{codesample2} 7.89 + hg diff -r 10 -r 20 7.90 + hg diff -r10:20 7.91 +\end{codesample2} 7.92 + 7.93 +When you provide two revisions, Mercurial treats the order of those 7.94 +revisions as significant. Thus, \hgcmdargs{diff}{-r10:20} will 7.95 +produce a diff that will transform files from their contents as of 7.96 +revision~10 to their contents as of revision~20, while 7.97 +\hgcmdargs{diff}{-r20:10} means the opposite: the diff that will 7.98 +transform files from their revision~20 contents to their revision~10 7.99 +contents. You cannot reverse the ordering in this way if you are 7.100 +diffing against the working directory. 7.101 + 7.102 +\optref{diff}{w}{ignore-all-space} 7.103 + 7.104 +\cmdref{version}{print version and copyright information} 7.105 + 7.106 +This command displays the version of Mercurial you are running, and 7.107 +its copyright license. There are four kinds of version string that 7.108 +you may see. 7.109 +\begin{itemize} 7.110 +\item The string ``\texttt{unknown}''. This version of Mercurial was 7.111 + not built in a Mercurial repository, and cannot determine its own 7.112 + version. 7.113 +\item A short numeric string, such as ``\texttt{1.1}''. This is a 7.114 + build of a revision of Mercurial that was identified by a specific 7.115 + tag in the repository where it was built. (This doesn't necessarily 7.116 + mean that you're running an official release; someone else could 7.117 + have added that tag to any revision in the repository where they 7.118 + built Mercurial.) 7.119 +\item A hexadecimal string, such as ``\texttt{875489e31abe}''. This 7.120 + is a build of the given revision of Mercurial. 7.121 +\item A hexadecimal string followed by a date, such as 7.122 + ``\texttt{875489e31abe+20070205}''. This is a build of the given 7.123 + revision of Mercurial, where the build repository contained some 7.124 + local changes that had not been committed. 7.125 +\end{itemize} 7.126 + 7.127 +\subsection{Tips and tricks} 7.128 + 7.129 +\subsubsection{Why do the results of \hgcmd{diff} and \hgcmd{status} 7.130 + differ?} 7.131 +\label{cmdref:diff-vs-status} 7.132 + 7.133 +When you run the \hgcmd{status} command, you'll see a list of files 7.134 +that Mercurial will record changes for the next time you perform a 7.135 +commit. If you run the \hgcmd{diff} command, you may notice that it 7.136 +prints diffs for only a \emph{subset} of the files that \hgcmd{status} 7.137 +listed. There are two possible reasons for this. 7.138 + 7.139 +The first is that \hgcmd{status} prints some kinds of modifications 7.140 +that \hgcmd{diff} doesn't normally display. The \hgcmd{diff} command 7.141 +normally outputs unified diffs, which don't have the ability to 7.142 +represent some changes that Mercurial can track. Most notably, 7.143 +traditional diffs can't represent a change in whether or not a file is 7.144 +executable, but Mercurial records this information. 7.145 + 7.146 +If you use the \hgopt{diff}{--git} option to \hgcmd{diff}, it will 7.147 +display \command{git}-compatible diffs that \emph{can} display this 7.148 +extra information. 7.149 + 7.150 +The second possible reason that \hgcmd{diff} might be printing diffs 7.151 +for a subset of the files displayed by \hgcmd{status} is that if you 7.152 +invoke it without any arguments, \hgcmd{diff} prints diffs against the 7.153 +first parent of the working directory. If you have run \hgcmd{merge} 7.154 +to merge two changesets, but you haven't yet committed the results of 7.155 +the merge, your working directory has two parents (use \hgcmd{parents} 7.156 +to see them). While \hgcmd{status} prints modifications relative to 7.157 +\emph{both} parents after an uncommitted merge, \hgcmd{diff} still 7.158 +operates relative only to the first parent. You can get it to print 7.159 +diffs relative to the second parent by specifying that parent with the 7.160 +\hgopt{diff}{-r} option. There is no way to print diffs relative to 7.161 +both parents. 7.162 + 7.163 +\subsubsection{Generating safe binary diffs} 7.164 + 7.165 +If you use the \hgopt{diff}{-a} option to force Mercurial to print 7.166 +diffs of files that are either ``mostly text'' or contain lots of 7.167 +binary data, those diffs cannot subsequently be applied by either 7.168 +Mercurial's \hgcmd{import} command or the system's \command{patch} 7.169 +command. 7.170 + 7.171 +If you want to generate a diff of a binary file that is safe to use as 7.172 +input for \hgcmd{import}, use the \hgcmd{diff}{--git} option when you 7.173 +generate the patch. The system \command{patch} command cannot handle 7.174 +binary patches at all. 7.175 + 7.176 +%%% Local Variables: 7.177 +%%% mode: latex 7.178 +%%% TeX-master: "00book" 7.179 +%%% End:
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/en/concepts.tex Mon Mar 05 20:16:36 2007 -0800 8.3 @@ -0,0 +1,577 @@ 8.4 +\chapter{Behind the scenes} 8.5 +\label{chap:concepts} 8.6 + 8.7 +Unlike many revision control systems, the concepts upon which 8.8 +Mercurial is built are simple enough that it's easy to understand how 8.9 +the software really works. Knowing this certainly isn't necessary, 8.10 +but I find it useful to have a ``mental model'' of what's going on. 8.11 + 8.12 +This understanding gives me confidence that Mercurial has been 8.13 +carefully designed to be both \emph{safe} and \emph{efficient}. And 8.14 +just as importantly, if it's easy for me to retain a good idea of what 8.15 +the software is doing when I perform a revision control task, I'm less 8.16 +likely to be surprised by its behaviour. 8.17 + 8.18 +In this chapter, we'll initially cover the core concepts behind 8.19 +Mercurial's design, then continue to discuss some of the interesting 8.20 +details of its implementation. 8.21 + 8.22 +\section{Mercurial's historical record} 8.23 + 8.24 +\subsection{Tracking the history of a single file} 8.25 + 8.26 +When Mercurial tracks modifications to a file, it stores the history 8.27 +of that file in a metadata object called a \emph{filelog}. Each entry 8.28 +in the filelog contains enough information to reconstruct one revision 8.29 +of the file that is being tracked. Filelogs are stored as files in 8.30 +the \sdirname{.hg/data} directory. A filelog contains two kinds of 8.31 +information: revision data, and an index to help Mercurial to find a 8.32 +revision efficiently. 8.33 + 8.34 +A file that is large, or has a lot of history, has its filelog stored 8.35 +in separate data (``\texttt{.d}'' suffix) and index (``\texttt{.i}'' 8.36 +suffix) files. For small files without much history, the revision 8.37 +data and index are combined in a single ``\texttt{.i}'' file. The 8.38 +correspondence between a file in the working directory and the filelog 8.39 +that tracks its history in the repository is illustrated in 8.40 +figure~\ref{fig:concepts:filelog}. 8.41 + 8.42 +\begin{figure}[ht] 8.43 + \centering 8.44 + \grafix{filelog} 8.45 + \caption{Relationships between files in working directory and 8.46 + filelogs in repository} 8.47 + \label{fig:concepts:filelog} 8.48 +\end{figure} 8.49 + 8.50 +\subsection{Managing tracked files} 8.51 + 8.52 +Mercurial uses a structure called a \emph{manifest} to collect 8.53 +together information about the files that it tracks. Each entry in 8.54 +the manifest contains information about the files present in a single 8.55 +changeset. An entry records which files are present in the changeset, 8.56 +the revision of each file, and a few other pieces of file metadata. 8.57 + 8.58 +\subsection{Recording changeset information} 8.59 + 8.60 +The \emph{changelog} contains information about each changeset. Each 8.61 +revision records who committed a change, the changeset comment, other 8.62 +pieces of changeset-related information, and the revision of the 8.63 +manifest to use. 8.64 + 8.65 +\subsection{Relationships between revisions} 8.66 + 8.67 +Within a changelog, a manifest, or a filelog, each revision stores a 8.68 +pointer to its immediate parent (or to its two parents, if it's a 8.69 +merge revision). As I mentioned above, there are also relationships 8.70 +between revisions \emph{across} these structures, and they are 8.71 +hierarchical in nature. 8.72 + 8.73 +For every changeset in a repository, there is exactly one revision 8.74 +stored in the changelog. Each revision of the changelog contains a 8.75 +pointer to a single revision of the manifest. A revision of the 8.76 +manifest stores a pointer to a single revision of each filelog tracked 8.77 +when that changeset was created. These relationships are illustrated 8.78 +in figure~\ref{fig:concepts:metadata}. 8.79 + 8.80 +\begin{figure}[ht] 8.81 + \centering 8.82 + \grafix{metadata} 8.83 + \caption{Metadata relationships} 8.84 + \label{fig:concepts:metadata} 8.85 +\end{figure} 8.86 + 8.87 +As the illustration shows, there is \emph{not} a ``one to one'' 8.88 +relationship between revisions in the changelog, manifest, or filelog. 8.89 +If the manifest hasn't changed between two changesets, the changelog 8.90 +entries for those changesets will point to the same revision of the 8.91 +manifest. If a file that Mercurial tracks hasn't changed between two 8.92 +changesets, the entry for that file in the two revisions of the 8.93 +manifest will point to the same revision of its filelog. 8.94 + 8.95 +\section{Safe, efficient storage} 8.96 + 8.97 +The underpinnings of changelogs, manifests, and filelogs are provided 8.98 +by a single structure called the \emph{revlog}. 8.99 + 8.100 +\subsection{Efficient storage} 8.101 + 8.102 +The revlog provides efficient storage of revisions using a 8.103 +\emph{delta} mechanism. Instead of storing a complete copy of a file 8.104 +for each revision, it stores the changes needed to transform an older 8.105 +revision into the new revision. For many kinds of file data, these 8.106 +deltas are typically a fraction of a percent of the size of a full 8.107 +copy of a file. 8.108 + 8.109 +Some obsolete revision control systems can only work with deltas of 8.110 +text files. They must either store binary files as complete snapshots 8.111 +or encoded into a text representation, both of which are wasteful 8.112 +approaches. Mercurial can efficiently handle deltas of files with 8.113 +arbitrary binary contents; it doesn't need to treat text as special. 8.114 + 8.115 +\subsection{Safe operation} 8.116 +\label{sec:concepts:txn} 8.117 + 8.118 +Mercurial only ever \emph{appends} data to the end of a revlog file. 8.119 +It never modifies a section of a file after it has written it. This 8.120 +is both more robust and efficient than schemes that need to modify or 8.121 +rewrite data. 8.122 + 8.123 +In addition, Mercurial treats every write as part of a 8.124 +\emph{transaction} that can span a number of files. A transaction is 8.125 +\emph{atomic}: either the entire transaction succeeds and its effects 8.126 +are all visible to readers in one go, or the whole thing is undone. 8.127 +This guarantee of atomicity means that if you're running two copies of 8.128 +Mercurial, where one is reading data and one is writing it, the reader 8.129 +will never see a partially written result that might confuse it. 8.130 + 8.131 +The fact that Mercurial only appends to files makes it easier to 8.132 +provide this transactional guarantee. The easier it is to do stuff 8.133 +like this, the more confident you should be that it's done correctly. 8.134 + 8.135 +\subsection{Fast retrieval} 8.136 + 8.137 +Mercurial cleverly avoids a pitfall common to all earlier 8.138 +revision control systems: the problem of \emph{inefficient retrieval}. 8.139 +Most revision control systems store the contents of a revision as an 8.140 +incremental series of modifications against a ``snapshot''. To 8.141 +reconstruct a specific revision, you must first read the snapshot, and 8.142 +then every one of the revisions between the snapshot and your target 8.143 +revision. The more history that a file accumulates, the more 8.144 +revisions you must read, hence the longer it takes to reconstruct a 8.145 +particular revision. 8.146 + 8.147 +\begin{figure}[ht] 8.148 + \centering 8.149 + \grafix{snapshot} 8.150 + \caption{Snapshot of a revlog, with incremental deltas} 8.151 + \label{fig:concepts:snapshot} 8.152 +\end{figure} 8.153 + 8.154 +The innovation that Mercurial applies to this problem is simple but 8.155 +effective. Once the cumulative amount of delta information stored 8.156 +since the last snapshot exceeds a fixed threshold, it stores a new 8.157 +snapshot (compressed, of course), instead of another delta. This 8.158 +makes it possible to reconstruct \emph{any} revision of a file 8.159 +quickly. This approach works so well that it has since been copied by 8.160 +several other revision control systems. 8.161 + 8.162 +Figure~\ref{fig:concepts:snapshot} illustrates the idea. In an entry 8.163 +in a revlog's index file, Mercurial stores the range of entries from 8.164 +the data file that it must read to reconstruct a particular revision. 8.165 + 8.166 +\subsubsection{Aside: the influence of video compression} 8.167 + 8.168 +If you're familiar with video compression or have ever watched a TV 8.169 +feed through a digital cable or satellite service, you may know that 8.170 +most video compression schemes store each frame of video as a delta 8.171 +against its predecessor frame. In addition, these schemes use 8.172 +``lossy'' compression techniques to increase the compression ratio, so 8.173 +visual errors accumulate over the course of a number of inter-frame 8.174 +deltas. 8.175 + 8.176 +Because it's possible for a video stream to ``drop out'' occasionally 8.177 +due to signal glitches, and to limit the accumulation of artefacts 8.178 +introduced by the lossy compression process, video encoders 8.179 +periodically insert a complete frame (called a ``key frame'') into the 8.180 +video stream; the next delta is generated against that frame. This 8.181 +means that if the video signal gets interrupted, it will resume once 8.182 +the next key frame is received. Also, the accumulation of encoding 8.183 +errors restarts anew with each key frame. 8.184 + 8.185 +\subsection{Identification and strong integrity} 8.186 + 8.187 +Along with delta or snapshot information, a revlog entry contains a 8.188 +cryptographic hash of the data that it represents. This makes it 8.189 +difficult to forge the contents of a revision, and easy to detect 8.190 +accidental corruption. 8.191 + 8.192 +Hashes provide more than a mere check against corruption; they are 8.193 +used as the identifiers for revisions. The changeset identification 8.194 +hashes that you see as an end user are from revisions of the 8.195 +changelog. Although filelogs and the manifest also use hashes, 8.196 +Mercurial only uses these behind the scenes. 8.197 + 8.198 +Mercurial verifies that hashes are correct when it retrieves file 8.199 +revisions and when it pulls changes from another repository. If it 8.200 +encounters an integrity problem, it will complain and stop whatever 8.201 +it's doing. 8.202 + 8.203 +In addition to the effect it has on retrieval efficiency, Mercurial's 8.204 +use of periodic snapshots makes it more robust against partial data 8.205 +corruption. If a revlog becomes partly corrupted due to a hardware 8.206 +error or system bug, it's often possible to reconstruct some or most 8.207 +revisions from the uncorrupted sections of the revlog, both before and 8.208 +after the corrupted section. This would not be possible with a 8.209 +delta-only storage model. 8.210 + 8.211 +\section{Revision history, branching, 8.212 + and merging} 8.213 + 8.214 +Every entry in a Mercurial revlog knows the identity of its immediate 8.215 +ancestor revision, usually referred to as its \emph{parent}. In fact, 8.216 +a revision contains room for not one parent, but two. Mercurial uses 8.217 +a special hash, called the ``null ID'', to represent the idea ``there 8.218 +is no parent here''. This hash is simply a string of zeroes. 8.219 + 8.220 +In figure~\ref{fig:concepts:revlog}, you can see an example of the 8.221 +conceptual structure of a revlog. Filelogs, manifests, and changelogs 8.222 +all have this same structure; they differ only in the kind of data 8.223 +stored in each delta or snapshot. 8.224 + 8.225 +The first revision in a revlog (at the bottom of the image) has the 8.226 +null ID in both of its parent slots. For a ``normal'' revision, its 8.227 +first parent slot contains the ID of its parent revision, and its 8.228 +second contains the null ID, indicating that the revision has only one 8.229 +real parent. Any two revisions that have the same parent ID are 8.230 +branches. A revision that represents a merge between branches has two 8.231 +normal revision IDs in its parent slots. 8.232 + 8.233 +\begin{figure}[ht] 8.234 + \centering 8.235 + \grafix{revlog} 8.236 + \caption{} 8.237 + \label{fig:concepts:revlog} 8.238 +\end{figure} 8.239 + 8.240 +\section{The working directory} 8.241 + 8.242 +In the working directory, Mercurial stores a snapshot of the files 8.243 +from the repository as of a particular changeset. 8.244 + 8.245 +The working directory ``knows'' which changeset it contains. When you 8.246 +update the working directory to contain a particular changeset, 8.247 +Mercurial looks up the appropriate revision of the manifest to find 8.248 +out which files it was tracking at the time that changeset was 8.249 +committed, and which revision of each file was then current. It then 8.250 +recreates a copy of each of those files, with the same contents it had 8.251 +when the changeset was committed. 8.252 + 8.253 +The \emph{dirstate} contains Mercurial's knowledge of the working 8.254 +directory. This details which changeset the working directory is 8.255 +updated to, and all of the files that Mercurial is tracking in the 8.256 +working directory. 8.257 + 8.258 +Just as a revision of a revlog has room for two parents, so that it 8.259 +can represent either a normal revision (with one parent) or a merge of 8.260 +two earlier revisions, the dirstate has slots for two parents. When 8.261 +you use the \hgcmd{update} command, the changeset that you update to 8.262 +is stored in the ``first parent'' slot, and the null ID in the second. 8.263 +When you \hgcmd{merge} with another changeset, the first parent 8.264 +remains unchanged, and the second parent is filled in with the 8.265 +changeset you're merging with. The \hgcmd{parents} command tells you 8.266 +what the parents of the dirstate are. 8.267 + 8.268 +\subsection{What happens when you commit} 8.269 + 8.270 +The dirstate stores parent information for more than just book-keeping 8.271 +purposes. Mercurial uses the parents of the dirstate as \emph{the 8.272 + parents of a new changeset} when you perform a commit. 8.273 + 8.274 +\begin{figure}[ht] 8.275 + \centering 8.276 + \grafix{wdir} 8.277 + \caption{The working directory can have two parents} 8.278 + \label{fig:concepts:wdir} 8.279 +\end{figure} 8.280 + 8.281 +Figure~\ref{fig:concepts:wdir} shows the normal state of the working 8.282 +directory, where it has a single changeset as parent. That changeset 8.283 +is the \emph{tip}, the newest changeset in the repository that has no 8.284 +children. 8.285 + 8.286 +\begin{figure}[ht] 8.287 + \centering 8.288 + \grafix{wdir-after-commit} 8.289 + \caption{The working directory gains new parents after a commit} 8.290 + \label{fig:concepts:wdir-after-commit} 8.291 +\end{figure} 8.292 + 8.293 +It's useful to think of the working directory as ``the changeset I'm 8.294 +about to commit''. Any files that you tell Mercurial that you've 8.295 +added, removed, renamed, or copied will be reflected in that 8.296 +changeset, as will modifications to any files that Mercurial is 8.297 +already tracking; the new changeset will have the parents of the 8.298 +working directory as its parents. 8.299 + 8.300 +After a commit, Mercurial will update the parents of the working 8.301 +directory, so that the first parent is the ID of the new changeset, 8.302 +and the second is the null ID. This is shown in 8.303 +figure~\ref{fig:concepts:wdir-after-commit}. Mercurial doesn't touch 8.304 +any of the files in the working directory when you commit; it just 8.305 +modifies the dirstate to note its new parents. 8.306 + 8.307 +\subsection{Creating a new head} 8.308 + 8.309 +It's perfectly normal to update the working directory to a changeset 8.310 +other than the current tip. For example, you might want to know what 8.311 +your project looked like last Tuesday, or you could be looking through 8.312 +changesets to see which one introduced a bug. In cases like this, the 8.313 +natural thing to do is update the working directory to the changeset 8.314 +you're interested in, and then examine the files in the working 8.315 +directory directly to see their contents as they werea when you 8.316 +committed that changeset. The effect of this is shown in 8.317 +figure~\ref{fig:concepts:wdir-pre-branch}. 8.318 + 8.319 +\begin{figure}[ht] 8.320 + \centering 8.321 + \grafix{wdir-pre-branch} 8.322 + \caption{The working directory, updated to an older changeset} 8.323 + \label{fig:concepts:wdir-pre-branch} 8.324 +\end{figure} 8.325 + 8.326 +Having updated the working directory to an older changeset, what 8.327 +happens if you make some changes, and then commit? Mercurial behaves 8.328 +in the same way as I outlined above. The parents of the working 8.329 +directory become the parents of the new changeset. This new changeset 8.330 +has no children, so it becomes the new tip. And the repository now 8.331 +contains two changesets that have no children; we call these 8.332 +\emph{heads}. You can see the structure that this creates in 8.333 +figure~\ref{fig:concepts:wdir-branch}. 8.334 + 8.335 +\begin{figure}[ht] 8.336 + \centering 8.337 + \grafix{wdir-branch} 8.338 + \caption{After a commit made while synced to an older changeset} 8.339 + \label{fig:concepts:wdir-branch} 8.340 +\end{figure} 8.341 + 8.342 +\begin{note} 8.343 + If you're new to Mercurial, you should keep in mind a common 8.344 + ``error'', which is to use the \hgcmd{pull} command without any 8.345 + options. By default, the \hgcmd{pull} command \emph{does not} 8.346 + update the working directory, so you'll bring new changesets into 8.347 + your repository, but the working directory will stay synced at the 8.348 + same changeset as before the pull. If you make some changes and 8.349 + commit afterwards, you'll thus create a new head, because your 8.350 + working directory isn't synced to whatever the current tip is. 8.351 + 8.352 + I put the word ``error'' in quotes because all that you need to do 8.353 + to rectify this situation is \hgcmd{merge}, then \hgcmd{commit}. In 8.354 + other words, this almost never has negative consequences; it just 8.355 + surprises people. I'll discuss other ways to avoid this behaviour, 8.356 + and why Mercurial behaves in this initially surprising way, later 8.357 + on. 8.358 +\end{note} 8.359 + 8.360 +\subsection{Merging heads} 8.361 + 8.362 +When you run the \hgcmd{merge} command, Mercurial leaves the first 8.363 +parent of the working directory unchanged, and sets the second parent 8.364 +to the changeset you're merging with, as shown in 8.365 +figure~\ref{fig:concepts:wdir-merge}. 8.366 + 8.367 +\begin{figure}[ht] 8.368 + \centering 8.369 + \grafix{wdir-merge} 8.370 + \caption{Merging two hehads} 8.371 + \label{fig:concepts:wdir-merge} 8.372 +\end{figure} 8.373 + 8.374 +Mercurial also has to modify the working directory, to merge the files 8.375 +managed in the two changesets. Simplified a little, the merging 8.376 +process goes like this, for every file in the manifests of both 8.377 +changesets. 8.378 +\begin{itemize} 8.379 +\item If neither changeset has modified a file, do nothing with that 8.380 + file. 8.381 +\item If one changeset has modified a file, and the other hasn't, 8.382 + create the modified copy of the file in the working directory. 8.383 +\item If one changeset has removed a file, and the other hasn't (or 8.384 + has also deleted it), delete the file from the working directory. 8.385 +\item If one changeset has removed a file, but the other has modified 8.386 + the file, ask the user what to do: keep the modified file, or remove 8.387 + it? 8.388 +\item If both changesets have modified a file, invoke an external 8.389 + merge program to choose the new contents for the merged file. This 8.390 + may require input from the user. 8.391 +\item If one changeset has modified a file, and the other has renamed 8.392 + or copied the file, make sure that the changes follow the new name 8.393 + of the file. 8.394 +\end{itemize} 8.395 +There are more details---merging has plenty of corner cases---but 8.396 +these are the most common choices that are involved in a merge. As 8.397 +you can see, most cases are completely automatic, and indeed most 8.398 +merges finish automatically, without requiring your input to resolve 8.399 +any conflicts. 8.400 + 8.401 +When you're thinking about what happens when you commit after a merge, 8.402 +once again the working directory is ``the changeset I'm about to 8.403 +commit''. After the \hgcmd{merge} command completes, the working 8.404 +directory has two parents; these will become the parents of the new 8.405 +changeset. 8.406 + 8.407 +Mercurial lets you perform multiple merges, but you must commit the 8.408 +results of each individual merge as you go. This is necessary because 8.409 +Mercurial only tracks two parents for both revisions and the working 8.410 +directory. While it would be technically possible to merge multiple 8.411 +changesets at once, the prospect of user confusion and making a 8.412 +terrible mess of a merge immediately becomes overwhelming. 8.413 + 8.414 +\section{Other interesting design features} 8.415 + 8.416 +In the sections above, I've tried to highlight some of the most 8.417 +important aspects of Mercurial's design, to illustrate that it pays 8.418 +careful attention to reliability and performance. However, the 8.419 +attention to detail doesn't stop there. There are a number of other 8.420 +aspects of Mercurial's construction that I personally find 8.421 +interesting. I'll detail a few of them here, separate from the ``big 8.422 +ticket'' items above, so that if you're interested, you can gain a 8.423 +better idea of the amount of thinking that goes into a well-designed 8.424 +system. 8.425 + 8.426 +\subsection{Clever compression} 8.427 + 8.428 +When appropriate, Mercurial will store both snapshots and deltas in 8.429 +compressed form. It does this by always \emph{trying to} compress a 8.430 +snapshot or delta, but only storing the compressed version if it's 8.431 +smaller than the uncompressed version. 8.432 + 8.433 +This means that Mercurial does ``the right thing'' when storing a file 8.434 +whose native form is compressed, such as a \texttt{zip} archive or a 8.435 +JPEG image. When these types of files are compressed a second time, 8.436 +the resulting file is usually bigger than the once-compressed form, 8.437 +and so Mercurial will store the plain \texttt{zip} or JPEG. 8.438 + 8.439 +Deltas between revisions of a compressed file are usually larger than 8.440 +snapshots of the file, and Mercurial again does ``the right thing'' in 8.441 +these cases. It finds that such a delta exceeds the threshold at 8.442 +which it should store a complete snapshot of the file, so it stores 8.443 +the snapshot, again saving space compared to a naive delta-only 8.444 +approach. 8.445 + 8.446 +\subsubsection{Network recompression} 8.447 + 8.448 +When storing revisions on disk, Mercurial uses the ``deflate'' 8.449 +compression algorithm (the same one used by the popular \texttt{zip} 8.450 +archive format), which balances good speed with a respectable 8.451 +compression ratio. However, when transmitting revision data over a 8.452 +network connection, Mercurial uncompresses the compressed revision 8.453 +data. 8.454 + 8.455 +If the connection is over HTTP, Mercurial recompresses the entire 8.456 +stream of data using a compression algorithm that gives a etter 8.457 +compression ratio (the Burrows-Wheeler algorithm from the widely used 8.458 +\texttt{bzip2} compression package). This combination of algorithm 8.459 +and compression of the entire stream (instead of a revision at a time) 8.460 +substantially reduces the number of bytes to be transferred, yielding 8.461 +better network performance over almost all kinds of network. 8.462 + 8.463 +(If the connection is over \command{ssh}, Mercurial \emph{doesn't} 8.464 +recompress the stream, because \command{ssh} can already do this 8.465 +itself.) 8.466 + 8.467 +\subsection{Read/write ordering and atomicity} 8.468 + 8.469 +Appending to files isn't the whole story when it comes to guaranteeing 8.470 +that a reader won't see a partial write. If you recall 8.471 +figure~\ref{fig:concepts:metadata}, revisions in the changelog point to 8.472 +revisions in the manifest, and revisions in the manifest point to 8.473 +revisions in filelogs. This hierarchy is deliberate. 8.474 + 8.475 +A writer starts a transaction by writing filelog and manifest data, 8.476 +and doesn't write any changelog data until those are finished. A 8.477 +reader starts by reading changelog data, then manifest data, followed 8.478 +by filelog data. 8.479 + 8.480 +Since the writer has always finished writing filelog and manifest data 8.481 +before it writes to the changelog, a reader will never read a pointer 8.482 +to a partially written manifest revision from the changelog, and it will 8.483 +never read a pointer to a partially written filelog revision from the 8.484 +manifest. 8.485 + 8.486 +\subsection{Concurrent access} 8.487 + 8.488 +The read/write ordering and atomicity guarantees mean that Mercurial 8.489 +never needs to \emph{lock} a repository when it's reading data, even 8.490 +if the repository is being written to while the read is occurring. 8.491 +This has a big effect on scalability; you can have an arbitrary number 8.492 +of Mercurial processes safely reading data from a repository safely 8.493 +all at once, no matter whether it's being written to or not. 8.494 + 8.495 +The lockless nature of reading means that if you're sharing a 8.496 +repository on a multi-user system, you don't need to grant other local 8.497 +users permission to \emph{write} to your repository in order for them 8.498 +to be able to clone it or pull changes from it; they only need 8.499 +\emph{read} permission. (This is \emph{not} a common feature among 8.500 +revision control systems, so don't take it for granted! Most require 8.501 +readers to be able to lock a repository to access it safely, and this 8.502 +requires write permission on at least one directory, which of course 8.503 +makes for all kinds of nasty and annoying security and administrative 8.504 +problems.) 8.505 + 8.506 +Mercurial uses locks to ensure that only one process can write to a 8.507 +repository at a time (the locking mechanism is safe even over 8.508 +filesystems that are notoriously hostile to locking, such as NFS). If 8.509 +a repository is locked, a writer will wait for a while to retry if the 8.510 +repository becomes unlocked, but if the repository remains locked for 8.511 +too long, the process attempting to write will time out after a while. 8.512 +This means that your daily automated scripts won't get stuck forever 8.513 +and pile up if a system crashes unnoticed, for example. (Yes, the 8.514 +timeout is configurable, from zero to infinity.) 8.515 + 8.516 +\subsubsection{Safe dirstate access} 8.517 + 8.518 +As with revision data, Mercurial doesn't take a lock to read the 8.519 +dirstate file; it does acquire a lock to write it. To avoid the 8.520 +possibility of reading a partially written copy of the dirstate file, 8.521 +Mercurial writes to a file with a unique name in the same directory as 8.522 +the dirstate file, then renames the temporary file atomically to 8.523 +\filename{dirstate}. The file named \filename{dirstate} is thus 8.524 +guaranteed to be complete, not partially written. 8.525 + 8.526 +\subsection{Avoiding seeks} 8.527 + 8.528 +Critical to Mercurial's performance is the avoidance of seeks of the 8.529 +disk head, since any seek is far more expensive than even a 8.530 +comparatively large read operation. 8.531 + 8.532 +This is why, for example, the dirstate is stored in a single file. If 8.533 +there were a dirstate file per directory that Mercurial tracked, the 8.534 +disk would seek once per directory. Instead, Mercurial reads the 8.535 +entire single dirstate file in one step. 8.536 + 8.537 +Mercurial also uses a ``copy on write'' scheme when cloning a 8.538 +repository on local storage. Instead of copying every revlog file 8.539 +from the old repository into the new repository, it makes a ``hard 8.540 +link'', which is a shorthand way to say ``these two names point to the 8.541 +same file''. When Mercurial is about to write to one of a revlog's 8.542 +files, it checks to see if the number of names pointing at the file is 8.543 +greater than one. If it is, more than one repository is using the 8.544 +file, so Mercurial makes a new copy of the file that is private to 8.545 +this repository. 8.546 + 8.547 +A few revision control developers have pointed out that this idea of 8.548 +making a complete private copy of a file is not very efficient in its 8.549 +use of storage. While this is true, storage is cheap, and this method 8.550 +gives the highest performance while deferring most book-keeping to the 8.551 +operating system. An alternative scheme would most likely reduce 8.552 +performance and increase the complexity of the software, each of which 8.553 +is much more important to the ``feel'' of day-to-day use. 8.554 + 8.555 +\subsection{Other contents of the dirstate} 8.556 + 8.557 +Because Mercurial doesn't force you to tell it when you're modifying a 8.558 +file, it uses the dirstate to store some extra information so it can 8.559 +determine efficiently whether you have modified a file. For each file 8.560 +in the working directory, it stores the time that it last modified the 8.561 +file itself, and the size of the file at that time. 8.562 + 8.563 +When you explicitly \hgcmd{add}, \hgcmd{remove}, \hgcmd{rename} or 8.564 +\hgcmd{copy} files, Mercurial updates the dirstate so that it knows 8.565 +what to do with those files when you commit. 8.566 + 8.567 +When Mercurial is checking the states of files in the working 8.568 +directory, it first checks a file's modification time. If that has 8.569 +not changed, the file must not have been modified. If the file's size 8.570 +has changed, the file must have been modified. If the modification 8.571 +time has changed, but the size has not, only then does Mercurial need 8.572 +to read the actual contents of the file to see if they've changed. 8.573 +Storing these few extra pieces of information dramatically reduces the 8.574 +amount of data that Mercurial needs to read, which yields large 8.575 +performance improvements compared to other revision control systems. 8.576 + 8.577 +%%% Local Variables: 8.578 +%%% mode: latex 8.579 +%%% TeX-master: "00book" 8.580 +%%% End:
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/en/daily.tex Mon Mar 05 20:16:36 2007 -0800 9.3 @@ -0,0 +1,322 @@ 9.4 +\chapter{Mercurial in daily use} 9.5 +\label{chap:daily} 9.6 + 9.7 +\section{Telling Mercurial which files to track} 9.8 + 9.9 +Mercurial does not work with files in your repository unless you tell 9.10 +it to manage them. The \hgcmd{status} command will tell you which 9.11 +files Mercurial doesn't know about; it uses a ``\texttt{?}'' to 9.12 +display such files. 9.13 + 9.14 +To tell Mercurial to track a file, use the \hgcmd{add} command. Once 9.15 +you have added a file, the entry in the output of \hgcmd{status} for 9.16 +that file changes from ``\texttt{?}'' to ``\texttt{A}''. 9.17 +\interaction{daily.files.add} 9.18 + 9.19 +After you run a \hgcmd{commit}, the files that you added before the 9.20 +commit will no longer be listed in the output of \hgcmd{status}. The 9.21 +reason for this is that \hgcmd{status} only tells you about 9.22 +``interesting'' files---those that you have modified or told Mercurial 9.23 +to do something with---by default. If you have a repository that 9.24 +contains thousands of files, you will rarely want to know about files 9.25 +that Mercurial is tracking, but that have not changed. (You can still 9.26 +get this information; we'll return to this later.) 9.27 + 9.28 +Once you add a file, Mercurial doesn't do anything with it 9.29 +immediately. Instead, it will take a snapshot of the file's state the 9.30 +next time you perform a commit. It will then continue to track the 9.31 +changes you make to the file every time you commit, until you remove 9.32 +the file. 9.33 + 9.34 +\subsection{Explicit versus implicit file naming} 9.35 + 9.36 +A useful behaviour that Mercurial has is that if you pass the name of 9.37 +a directory to a command, every Mercurial command will treat this as 9.38 +``I want to operate on every file in this directory and its 9.39 +subdirectories''. 9.40 +\interaction{daily.files.add-dir} 9.41 +Notice in this example that Mercurial printed the names of the files 9.42 +it added, whereas it didn't do so when we added the file named 9.43 +\filename{a} in the earlier example. 9.44 + 9.45 +What's going on is that in the former case, we explicitly named the 9.46 +file to add on the command line, so the assumption that Mercurial 9.47 +makes in such cases is that we know what you were doing, and it 9.48 +doesn't print any output. 9.49 + 9.50 +However, when we \emph{imply} the names of files by giving the name of 9.51 +a directory, Mercurial takes the extra step of printing the name of 9.52 +each file that it does something with. This makes it more clear what 9.53 +is happening, and reduces the likelihood of a silent and nasty 9.54 +surprise. This behaviour is common to most Mercurial commands. 9.55 + 9.56 +\subsection{Aside: Mercurial tracks files, not directories} 9.57 + 9.58 +Mercurial does not track directory information. Instead, it tracks 9.59 +the path to a file. Before creating a file, it first creates any 9.60 +missing directory components of the path. After it deletes a file, it 9.61 +then deletes any empty directories that were in the deleted file's 9.62 +path. This sounds like a trivial distinction, but it has one minor 9.63 +practical consequence: it is not possible to represent a completely 9.64 +empty directory in Mercurial. 9.65 + 9.66 +Empty directories are rarely useful, and there are unintrusive 9.67 +workarounds that you can use to achieve an appropriate effect. The 9.68 +developers of Mercurial thus felt that the complexity that would be 9.69 +required to manage empty directories was not worth the limited benefit 9.70 +this feature would bring. 9.71 + 9.72 +If you need an empty directory in your repository, there are a few 9.73 +ways to achieve this. One is to create a directory, then \hgcmd{add} a 9.74 +``hidden'' file to that directory. On Unix-like systems, any file 9.75 +name that begins with a period (``\texttt{.}'') is treated as hidden 9.76 +by most commands and GUI tools. This approach is illustrated in 9.77 +figure~\ref{ex:daily:hidden}. 9.78 + 9.79 +\begin{figure}[ht] 9.80 + \interaction{daily.files.hidden} 9.81 + \caption{Simulating an empty directory using a hidden file} 9.82 + \label{ex:daily:hidden} 9.83 +\end{figure} 9.84 + 9.85 +Another way to tackle a need for an empty directory is to simply 9.86 +create one in your automated build scripts before they will need it. 9.87 + 9.88 +\section{How to stop tracking a file} 9.89 + 9.90 +Once you decide that a file no longer belongs in your repository, use 9.91 +the \hgcmd{remove} command; this deletes the file, and tells Mercurial 9.92 +to stop tracking it. A removed file is represented in the output of 9.93 +\hgcmd{status} with a ``\texttt{R}''. 9.94 +\interaction{daily.files.remove} 9.95 + 9.96 +After you \hgcmd{remove} a file, Mercurial will no longer track 9.97 +changes to that file, even if you recreate a file with the same name 9.98 +in your working directory. If you do recreate a file with the same 9.99 +name and want Mercurial to track the new file, simply \hgcmd{add} it. 9.100 +Mercurial will know that the newly added file is not related to the 9.101 +old file of the same name. 9.102 + 9.103 +\subsection{Removing a file does not affect its history} 9.104 + 9.105 +It is important to understand that removing a file has only two 9.106 +effects. 9.107 +\begin{itemize} 9.108 +\item It removes the current version of the file from the working 9.109 + directory. 9.110 +\item It stops Mercurial from tracking changes to the file, from the 9.111 + time of the next commit. 9.112 +\end{itemize} 9.113 +Removing a file \emph{does not} in any way alter the \emph{history} of 9.114 +the file. 9.115 + 9.116 +If you update the working directory to a changeset in which a file 9.117 +that you have removed was still tracked, it will reappear in the 9.118 +working directory, with the contents it had when you committed that 9.119 +changeset. If you then update the working directory to a later 9.120 +changeset, in which the file had been removed, Mercurial will once 9.121 +again remove the file from the working directory. 9.122 + 9.123 +\subsection{Missing files} 9.124 + 9.125 +Mercurial considers a file that you have deleted, but not used 9.126 +\hgcmd{remove} to delete, to be \emph{missing}. A missing file is 9.127 +represented with ``\texttt{!}'' in the output of \hgcmd{status}. 9.128 +Mercurial commands will not generally do anything with missing files. 9.129 +\interaction{daily.files.missing} 9.130 + 9.131 +If your repository contains a file that \hgcmd{status} reports as 9.132 +missing, and you want the file to stay gone, you can run 9.133 +\hgcmdargs{remove}{\hgopt{remove}{--after}} at any time later on, to 9.134 +tell Mercurial that you really did mean to remove the file. 9.135 +\interaction{daily.files.remove-after} 9.136 + 9.137 +On the other hand, if you deleted the missing file by accident, use 9.138 +\hgcmdargs{revert}{\emph{filename}} to recover the file. It will 9.139 +reappear, in unmodified form. 9.140 +\interaction{daily.files.recover-missing} 9.141 + 9.142 +\subsection{Aside: why tell Mercurial explicitly to 9.143 + remove a file?} 9.144 + 9.145 +You might wonder why Mercurial requires you to explicitly tell it that 9.146 +you are deleting a file. Early during the development of Mercurial, 9.147 +it let you delete a file however you pleased; Mercurial would notice 9.148 +the absence of the file automatically when you next ran a 9.149 +\hgcmd{commit}, and stop tracking the file. In practice, this made it 9.150 +too easy to accidentally remove a file without noticing. 9.151 + 9.152 +\subsection{Useful shorthand---adding and removing files 9.153 + in one step} 9.154 + 9.155 +Mercurial offers a combination command, \hgcmd{addremove}, that adds 9.156 +untracked files and marks missing files as removed. 9.157 +\interaction{daily.files.addremove} 9.158 +The \hgcmd{commit} command also provides a \hgopt{commit}{-A} option 9.159 +that performs this same add-and-remove, immediately followed by a 9.160 +commit. 9.161 +\interaction{daily.files.commit-addremove} 9.162 + 9.163 +\section{Copying files} 9.164 + 9.165 +Mercurial provides a \hgcmd{copy} command that lets you make a new 9.166 +copy of a file. When you copy a file using this command, Mercurial 9.167 +makes a record of the fact that the new file is a copy of the original 9.168 +file. It treats these copied files specially when you merge your work 9.169 +with someone else's. 9.170 + 9.171 +\subsection{The results of copying during a merge} 9.172 + 9.173 +What happens during a merge is that changes ``follow'' a copy. To 9.174 +best illustrate what this means, let's create an example. We'll start 9.175 +with the usual tiny repository that contains a single file. 9.176 +\interaction{daily.copy.init} 9.177 +We need to do some work in parallel, so that we'll have something to 9.178 +merge. So let's clone our repository. 9.179 +\interaction{daily.copy.clone} 9.180 +Back in our initial repository, let's use the \hgcmd{copy} command to 9.181 +make a copy of the first file we created. 9.182 +\interaction{daily.copy.copy} 9.183 + 9.184 +If we look at the output of the \hgcmd{status} command afterwards, the 9.185 +copied file looks just like a normal added file. 9.186 +\interaction{daily.copy.status} 9.187 +But if we pass the \hgopt{status}{-C} option to \hgcmd{status}, it 9.188 +prints another line of output: this is the file that our newly-added 9.189 +file was copied \emph{from}. 9.190 +\interaction{daily.copy.status-copy} 9.191 + 9.192 +Now, back in the repository we cloned, let's make a change in 9.193 +parallel. We'll add a line of content to the original file that we 9.194 +created. 9.195 +\interaction{daily.copy.other} 9.196 +Now we have a modified \filename{file} in this repository. When we 9.197 +pull the changes from the first repository, and merge the two heads, 9.198 +Mercurial will propagate the changes that we made locally to 9.199 +\filename{file} into its copy, \filename{new-file}. 9.200 +\interaction{daily.copy.merge} 9.201 + 9.202 +\subsection{Why should changes follow copies?} 9.203 +\label{sec:daily:why-copy} 9.204 + 9.205 +This behaviour, of changes to a file propagating out to copies of the 9.206 +file, might seem esoteric, but in most cases it's highly desirable. 9.207 + 9.208 +First of all, remember that this propagation \emph{only} happens when 9.209 +you merge. So if you \hgcmd{copy} a file, and subsequently modify the 9.210 +original file during the normal course of your work, nothing will 9.211 +happen. 9.212 + 9.213 +The second thing to know is that modifications will only propagate 9.214 +across a copy as long as the repository that you're pulling changes 9.215 +from \emph{doesn't know} about the copy. 9.216 + 9.217 +The reason that Mercurial does this is as follows. Let's say I make 9.218 +an important bug fix in a source file, and commit my changes. 9.219 +Meanwhile, you've decided to \hgcmd{copy} the file in your repository, 9.220 +without knowing about the bug or having seen the fix, and you have 9.221 +started hacking on your copy of the file. 9.222 + 9.223 +If you pulled and merged my changes, and Mercurial \emph{didn't} 9.224 +propagate changes across copies, your source file would now contain 9.225 +the bug, and unless you remembered to propagate the bug fix by hand, 9.226 +the bug would \emph{remain} in your copy of the file. 9.227 + 9.228 +By automatically propagating the change that fixed the bug from the 9.229 +original file to the copy, Mercurial prevents this class of problem. 9.230 +To my knowledge, Mercurial is the \emph{only} revision control system 9.231 +that propagates changes across copies like this. 9.232 + 9.233 +Once your change history has a record that the copy and subsequent 9.234 +merge occurred, there's usually no further need to propagate changes 9.235 +from the original file to the copied file, and that's why Mercurial 9.236 +only propagates changes across copies until this point, and no 9.237 +further. 9.238 + 9.239 +\subsection{How to make changes \emph{not} follow a copy} 9.240 + 9.241 +If, for some reason, you decide that this business of automatically 9.242 +propagating changes across copies is not for you, simply use your 9.243 +system's normal file copy command (on Unix-like systems, that's 9.244 +\command{cp}) to make a copy of a file, then \hgcmd{add} the new copy 9.245 +by hand. Before you do so, though, please do reread 9.246 +section~\ref{sec:daily:why-copy}, and make an informed decision that 9.247 +this behaviour is not appropriate to your specific case. 9.248 + 9.249 +\subsection{Behaviour of the \hgcmd{copy} command} 9.250 + 9.251 +When you use the \hgcmd{copy} command, Mercurial makes a copy of each 9.252 +source file as it currently stands in the working directory. This 9.253 +means that if you make some modifications to a file, then copy it 9.254 +without first having committed those changes, the new copy will 9.255 +contain your modifications. 9.256 + 9.257 +The \hgcmd{copy} command acts similarly to the Unix \command{cp} 9.258 +command (you can use the \hgcmd{cp} alias if you prefer). The last 9.259 +argument is the \emph{destination}, and all prior arguments are 9.260 +\emph{sources}. If you pass it a single file as the source, and the 9.261 +destination does not exist, it creates a new file with that name. 9.262 +\interaction{daily.copy.simple} 9.263 +If the destination is a directory, Mercurial copies its sources into 9.264 +that directory. 9.265 +\interaction{daily.copy.dir-dest} 9.266 +Copying a directory is recursive, and preserves the directory 9.267 +structure of the source. 9.268 +\interaction{daily.copy.dir-src} 9.269 +If the source and destination are both directories, the source tree is 9.270 +recreated in the destination directory. 9.271 +\interaction{daily.copy.dir-src-dest} 9.272 + 9.273 +As with the \hgcmd{rename} command, if you copy a file manually and 9.274 +then want Mercurial to know that you've copied the file, simply use 9.275 +the \hgopt{--after} option to \hgcmd{copy}. 9.276 +\interaction{daily.copy.after} 9.277 + 9.278 +\section{Renaming files} 9.279 + 9.280 +It's rather more common to need to rename a file than to make a copy 9.281 +of it. The reason I discussed the \hgcmd{copy} command before talking 9.282 +about renaming files is that Mercurial treats a rename in essentially 9.283 +the same way as a copy. Therefore, knowing what Mercurial does when 9.284 +you copy a file tells you what to expect when you rename a file. 9.285 + 9.286 +When you use the \hgcmd{rename} command, Mercurial makes a copy of 9.287 +each source file, then deletes it and marks the file as removed. 9.288 +\interaction{daily.rename.rename} 9.289 +The \hgcmd{status} command shows the newly copied file as added, and 9.290 +the copied-from file as removed. 9.291 +\interaction{daily.rename.status} 9.292 +As with the results of a \hgcmd{copy}, we must use the 9.293 +\hgopt{status}{-C} option to \hgcmd{status} to see that the added file 9.294 +is really being tracked by Mercurial as a copy of the original, now 9.295 +removed, file. 9.296 +\interaction{daily.rename.status-copy} 9.297 + 9.298 +As with \hgcmd{remove} and \hgcmd{copy}, you can tell Mercurial about 9.299 +a rename after the fact using the \hgopt{rename}{--after} option. In 9.300 +most other respects, the behaviour of the \hgcmd{rename} command, and 9.301 +the options it accepts, are similar to the \hgcmd{copy} command. 9.302 + 9.303 +\subsection{Renaming files and merging changes} 9.304 + 9.305 +Since Mercurial's rename is implemented as copy-and-remove, the same 9.306 +propagation of changes happens when you merge after a rename as after 9.307 +a copy. 9.308 + 9.309 +If I modify a file, and you rename it to a new name, then we merge our 9.310 +respective changes, my modifications to the file under its original 9.311 +name will be propagated into the file under its new name. (This is 9.312 +something you might expect to ``simply work,'' but not all revision 9.313 +control systems actually do this.) 9.314 + 9.315 +Whereas having changes follow a copy is a feature where you can 9.316 +perhaps nod and say ``yes, that might be useful,'' it should be clear 9.317 +that having them follow a rename is definitely important. Without 9.318 +this facility, it would simply be too easy for changes to become 9.319 +orphaned when files are renamed. 9.320 + 9.321 + 9.322 +%%% Local Variables: 9.323 +%%% mode: latex 9.324 +%%% TeX-master: "00book" 9.325 +%%% End:
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/en/examples/backout Mon Mar 05 20:16:36 2007 -0800 10.3 @@ -0,0 +1,82 @@ 10.4 +#!/bin/bash 10.5 + 10.6 +# We have to fake the merges here, because they cause conflicts with 10.7 +# three-way command-line merge, and kdiff3 may not be available. 10.8 + 10.9 +export HGMERGE=$(mktemp) 10.10 +echo '#!/bin/sh' >> $HGMERGE 10.11 +echo 'echo first change > "$1"' >> $HGMERGE 10.12 +echo 'echo third change > "$1"' >> $HGMERGE 10.13 +chmod 700 $HGMERGE 10.14 + 10.15 +#$ name: init 10.16 + 10.17 +hg init myrepo 10.18 +cd myrepo 10.19 +echo first change >> myfile 10.20 +hg add myfile 10.21 +hg commit -m 'first change' 10.22 +echo second change >> myfile 10.23 +hg commit -m 'second change' 10.24 + 10.25 +#$ name: simple 10.26 + 10.27 +hg backout -m 'back out second change' tip 10.28 +cat myfile 10.29 + 10.30 +#$ name: simple.log 10.31 + 10.32 +hg log --style compact 10.33 + 10.34 +#$ name: non-tip.clone 10.35 + 10.36 +cd .. 10.37 +hg clone -r1 myrepo non-tip-repo 10.38 +cd non-tip-repo 10.39 + 10.40 +#$ name: non-tip.backout 10.41 + 10.42 +echo third change >> myfile 10.43 +hg commit -m 'third change' 10.44 +hg backout --merge -m 'back out second change' 1 10.45 + 10.46 +#$ name: non-tip.cat 10.47 +cat myfile 10.48 + 10.49 +#$ name: manual.clone 10.50 + 10.51 +cd .. 10.52 +hg clone -r1 myrepo newrepo 10.53 +cd newrepo 10.54 + 10.55 +#$ name: manual.backout 10.56 + 10.57 +echo third change >> myfile 10.58 +hg commit -m 'third change' 10.59 +hg backout -m 'back out second change' 1 10.60 + 10.61 +#$ name: manual.log 10.62 + 10.63 +hg log --style compact 10.64 + 10.65 +#$ name: manual.parents 10.66 + 10.67 +hg parents 10.68 + 10.69 +#$ name: manual.heads 10.70 + 10.71 +hg heads 10.72 + 10.73 +#$ name: manual.cat 10.74 + 10.75 +cat myfile 10.76 + 10.77 +#$ name: manual.merge 10.78 + 10.79 +hg merge 10.80 +hg commit -m 'merged backout with previous tip' 10.81 +cat myfile 10.82 + 10.83 +#$ name: 10.84 + 10.85 +rm $HGMERGE
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/en/examples/bisect Mon Mar 05 20:16:36 2007 -0800 11.3 @@ -0,0 +1,80 @@ 11.4 +#!/bin/bash 11.5 + 11.6 +echo '[extensions]' >> $HGRC 11.7 +echo 'hbisect =' >> $HGRC 11.8 + 11.9 +#$ name: init 11.10 + 11.11 +hg init mybug 11.12 +cd mybug 11.13 + 11.14 +#$ name: commits 11.15 + 11.16 +buggy_change=37 11.17 + 11.18 +for (( i = 0; i < 50; i++ )); do 11.19 + if [[ $i = $buggy_change ]]; then 11.20 + echo 'i have a gub' > myfile$i 11.21 + hg commit -q -A -m 'buggy changeset' 11.22 + else 11.23 + echo 'nothing to see here, move along' > myfile$i 11.24 + hg commit -q -A -m 'normal changeset' 11.25 + fi 11.26 +done 11.27 + 11.28 +#$ name: help 11.29 + 11.30 +hg help bisect 11.31 +hg bisect help 11.32 + 11.33 +#$ name: search.init 11.34 + 11.35 +hg bisect init 11.36 + 11.37 +#$ name: search.bad-init 11.38 + 11.39 +hg bisect bad 11.40 + 11.41 +#$ name: search.good-init 11.42 + 11.43 +hg bisect good 10 11.44 + 11.45 +#$ name: search.step1 11.46 + 11.47 +if grep -q 'i have a gub' * 11.48 +then 11.49 + result=bad 11.50 +else 11.51 + result=good 11.52 +fi 11.53 + 11.54 +echo this revision is $result 11.55 +hg bisect $result 11.56 + 11.57 +#$ name: search.mytest 11.58 + 11.59 +mytest() { 11.60 + if grep -q 'i have a gub' * 11.61 + then 11.62 + result=bad 11.63 + else 11.64 + result=good 11.65 + fi 11.66 + 11.67 + echo this revision is $result 11.68 + hg bisect $result 11.69 +} 11.70 + 11.71 +#$ name: search.step2 11.72 + 11.73 +mytest 11.74 + 11.75 +#$ name: search.rest 11.76 + 11.77 +mytest 11.78 +mytest 11.79 +mytest 11.80 + 11.81 +#$ name: search.reset 11.82 + 11.83 +hg bisect reset
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 12.2 +++ b/en/examples/cmdref Mon Mar 05 20:16:36 2007 -0800 12.3 @@ -0,0 +1,22 @@ 12.4 +#!/bin/bash 12.5 + 12.6 +hg init diff 12.7 +cd diff 12.8 +cat > myfile.c <<EOF 12.9 +int myfunc() 12.10 +{ 12.11 + return 1; 12.12 +} 12.13 +EOF 12.14 +hg ci -Ama 12.15 + 12.16 +sed -ie 's/return 1/return 10/' myfile.c 12.17 + 12.18 +#$ name: diff-p 12.19 + 12.20 +echo '[diff]' >> $HGRC 12.21 +echo 'showfunc = False' >> $HGRC 12.22 + 12.23 +hg diff 12.24 + 12.25 +hg diff -p
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 13.2 +++ b/en/examples/daily.copy Mon Mar 05 20:16:36 2007 -0800 13.3 @@ -0,0 +1,80 @@ 13.4 +#!/bin/bash 13.5 + 13.6 +#$ name: init 13.7 + 13.8 +hg init my-copy 13.9 +cd my-copy 13.10 +echo line > file 13.11 +hg add file 13.12 +hg commit -m 'Added a file' 13.13 + 13.14 +#$ name: clone 13.15 + 13.16 +cd .. 13.17 +hg clone my-copy your-copy 13.18 + 13.19 +#$ name: copy 13.20 + 13.21 +cd my-copy 13.22 +hg copy file new-file 13.23 + 13.24 +#$ name: status 13.25 + 13.26 +hg status 13.27 + 13.28 +#$ name: status-copy 13.29 + 13.30 +hg status -C 13.31 +hg commit -m 'Copied file' 13.32 + 13.33 +#$ name: other 13.34 + 13.35 +cd ../your-copy 13.36 +echo 'new contents' >> file 13.37 +hg commit -m 'Changed file' 13.38 + 13.39 +#$ name: cat 13.40 + 13.41 +cat file 13.42 +cat ../my-copy/new-file 13.43 + 13.44 +#$ name: merge 13.45 + 13.46 +hg pull ../my-copy 13.47 +hg merge 13.48 +cat new-file 13.49 + 13.50 +#$ name: 13.51 + 13.52 +cd .. 13.53 +hg init copy-example 13.54 +cd copy-example 13.55 +echo a > a 13.56 +echo b > b 13.57 +mkdir c 13.58 +mkdir c/a 13.59 +echo c > c/a/c 13.60 +hg ci -Ama 13.61 + 13.62 +#$ name: simple 13.63 + 13.64 +hg copy a c 13.65 + 13.66 +#$ name: dir-dest 13.67 + 13.68 +mkdir d 13.69 +hg copy a b d 13.70 +ls d 13.71 + 13.72 +#$ name: dir-src 13.73 + 13.74 +hg copy c e 13.75 + 13.76 +#$ name: dir-src-dest 13.77 + 13.78 +hg copy c d 13.79 + 13.80 +#$ name: after 13.81 + 13.82 +cp a z 13.83 +hg copy --after a z
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 14.2 +++ b/en/examples/daily.files Mon Mar 05 20:16:36 2007 -0800 14.3 @@ -0,0 +1,97 @@ 14.4 +#!/bin/bash 14.5 + 14.6 +#$ name: add 14.7 + 14.8 +hg init add-example 14.9 +cd add-example 14.10 +echo a > a 14.11 +hg status 14.12 +hg add a 14.13 +hg status 14.14 +hg commit -m 'Added one file' 14.15 +hg status 14.16 + 14.17 +#$ name: add-dir 14.18 + 14.19 +mkdir b 14.20 +echo b > b/b 14.21 +echo c > b/c 14.22 +mkdir b/d 14.23 +echo d > b/d/d 14.24 +hg add b 14.25 +hg commit -m 'Added all files in subdirectory' 14.26 + 14.27 +#$ name: 14.28 + 14.29 +cd .. 14.30 + 14.31 +#$ name: hidden 14.32 + 14.33 +hg init hidden-example 14.34 +cd hidden-example 14.35 +mkdir empty 14.36 +touch empty/.hidden 14.37 +hg add empty/.hidden 14.38 +hg commit -m 'Manage an empty-looking directory' 14.39 +ls empty 14.40 +cd .. 14.41 +hg clone hidden-example tmp 14.42 +ls tmp 14.43 +ls tmp/empty 14.44 + 14.45 +#$ name: 14.46 + 14.47 +cd .. 14.48 + 14.49 +#$ name: remove 14.50 + 14.51 +hg init remove-example 14.52 +cd remove-example 14.53 +echo a > a 14.54 +mkdir b 14.55 +echo b > b/b 14.56 +hg add a b 14.57 +hg commit -m 'Small example for file removal' 14.58 +hg remove a 14.59 +hg status 14.60 +hg remove b 14.61 + 14.62 +#$ name: 14.63 + 14.64 +cd .. 14.65 + 14.66 +#$ name: missing 14.67 +hg init missing-example 14.68 +cd missing-example 14.69 +echo a > a 14.70 +hg add a 14.71 +hg commit -m'File about to be missing' 14.72 +rm a 14.73 +hg status 14.74 + 14.75 +#$ name: remove-after 14.76 + 14.77 +hg remove --after a 14.78 +hg status 14.79 + 14.80 +#$ name: recover-missing 14.81 +hg revert a 14.82 +cat a 14.83 +hg status 14.84 + 14.85 +#$ name: 14.86 + 14.87 +cd .. 14.88 + 14.89 +#$ name: addremove 14.90 + 14.91 +hg init addremove-example 14.92 +cd addremove-example 14.93 +echo a > a 14.94 +echo b > b 14.95 +hg addremove 14.96 + 14.97 +#$ name: commit-addremove 14.98 + 14.99 +echo c > c 14.100 +hg commit -A -m 'Commit with addremove'
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 15.2 +++ b/en/examples/daily.rename Mon Mar 05 20:16:36 2007 -0800 15.3 @@ -0,0 +1,18 @@ 15.4 +#!/bin/bash 15.5 + 15.6 +hg init a 15.7 +cd a 15.8 +echo a > a 15.9 +hg ci -Ama 15.10 + 15.11 +#$ name: rename 15.12 + 15.13 +hg rename a b 15.14 + 15.15 +#$ name: status 15.16 + 15.17 +hg status 15.18 + 15.19 +#$ name: status-copy 15.20 + 15.21 +hg status -C
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 16.2 +++ b/en/examples/daily.revert Mon Mar 05 20:16:36 2007 -0800 16.3 @@ -0,0 +1,74 @@ 16.4 +#!/bin/bash 16.5 + 16.6 +hg init a 16.7 +cd a 16.8 +echo 'original content' > file 16.9 +hg ci -Ama 16.10 + 16.11 +#$ name: modify 16.12 + 16.13 +cat file 16.14 +echo unwanted change >> file 16.15 +hg diff file 16.16 + 16.17 +#$ name: unmodify 16.18 + 16.19 +hg status 16.20 +hg revert file 16.21 +cat file 16.22 + 16.23 +#$ name: status 16.24 + 16.25 +hg status 16.26 +cat file.orig 16.27 + 16.28 +#$ name: 16.29 + 16.30 +rm file.orig 16.31 + 16.32 +#$ name: add 16.33 + 16.34 +echo oops > oops 16.35 +hg add oops 16.36 +hg status oops 16.37 +hg revert oops 16.38 +hg status 16.39 + 16.40 +#$ name: 16.41 + 16.42 +rm oops 16.43 + 16.44 +#$ name: remove 16.45 + 16.46 +hg remove file 16.47 +hg status 16.48 +hg revert file 16.49 +hg status 16.50 +ls file 16.51 + 16.52 +#$ name: missing 16.53 + 16.54 +rm file 16.55 +hg status 16.56 +hg revert file 16.57 +ls file 16.58 + 16.59 +#$ name: copy 16.60 + 16.61 +hg copy file new-file 16.62 +hg revert new-file 16.63 +hg status 16.64 + 16.65 +#$ name: 16.66 + 16.67 +rm new-file 16.68 + 16.69 +#$ name: rename 16.70 + 16.71 +hg rename file new-file 16.72 +hg revert new-file 16.73 +hg status 16.74 + 16.75 +#$ name: rename-orig 16.76 +hg revert file 16.77 +hg status
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 17.2 +++ b/en/examples/data/check_whitespace.py Mon Mar 05 20:16:36 2007 -0800 17.3 @@ -0,0 +1,44 @@ 17.4 +#!/usr/bin/python 17.5 + 17.6 +import re 17.7 + 17.8 +def trailing_whitespace(difflines): 17.9 + added, linenum, header = [], 0, False 17.10 + 17.11 + for line in difflines: 17.12 + if header: 17.13 + # remember the name of the file that this diff affects 17.14 + m = re.match(r'(?:---|\+\+\+) ([^\t]+)', line) 17.15 + if m and m.group(1) != '/dev/null': 17.16 + filename = m.group(1).split('/', 1)[-1] 17.17 + if line.startswith('+++ '): 17.18 + header = False 17.19 + continue 17.20 + if line.startswith('diff '): 17.21 + header = True 17.22 + continue 17.23 + # hunk header - save the line number 17.24 + m = re.match(r'@@ -\d+,\d+ \+(\d+),', line) 17.25 + if m: 17.26 + linenum = int(m.group(1)) 17.27 + continue 17.28 + # hunk body - check for an added line with trailing whitespace 17.29 + m = re.match(r'\+.*\s$', line) 17.30 + if m: 17.31 + added.append((filename, linenum)) 17.32 + if line and line[0] in ' +': 17.33 + linenum += 1 17.34 + return added 17.35 + 17.36 +if __name__ == '__main__': 17.37 + import os, sys 17.38 + 17.39 + added = trailing_whitespace(os.popen('hg export tip')) 17.40 + if added: 17.41 + for filename, linenum in added: 17.42 + print >> sys.stderr, ('%s, line %d: trailing whitespace added' % 17.43 + (filename, linenum)) 17.44 + # save the commit message so we don't need to retype it 17.45 + os.system('hg tip --template "{desc}" > .hg/commit.save') 17.46 + print >> sys.stderr, 'commit message saved to .hg/commit.save' 17.47 + sys.exit(1)
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 18.2 +++ b/en/examples/filenames Mon Mar 05 20:16:36 2007 -0800 18.3 @@ -0,0 +1,61 @@ 18.4 +#!/bin/bash 18.5 + 18.6 +hg init a 18.7 +cd a 18.8 +mkdir -p examples src/watcher 18.9 +touch COPYING MANIFEST.in README setup.py 18.10 +touch examples/performant.py examples/simple.py 18.11 +touch src/main.py src/watcher/_watcher.c src/watcher/watcher.py src/xyzzy.txt 18.12 + 18.13 +#$ name: files 18.14 + 18.15 +hg add COPYING README examples/simple.py 18.16 + 18.17 +#$ name: dirs 18.18 + 18.19 +hg status src 18.20 + 18.21 +#$ name: wdir-subdir 18.22 + 18.23 +cd src 18.24 +hg add -n 18.25 +hg add -n . 18.26 + 18.27 +#$ name: wdir-relname 18.28 + 18.29 +hg status 18.30 +hg status `hg root` 18.31 + 18.32 +#$ name: glob.star 18.33 + 18.34 +hg add 'glob:*.py' 18.35 + 18.36 +#$ name: glob.starstar 18.37 + 18.38 +cd .. 18.39 +hg status 'glob:**.py' 18.40 + 18.41 +#$ name: glob.star-starstar 18.42 + 18.43 +hg status 'glob:*.py' 18.44 +hg status 'glob:**.py' 18.45 + 18.46 +#$ name: glob.question 18.47 + 18.48 +hg status 'glob:**.?' 18.49 + 18.50 +#$ name: glob.range 18.51 + 18.52 +hg status 'glob:**[nr-t]' 18.53 + 18.54 +#$ name: glob.group 18.55 + 18.56 +hg status 'glob:*.{in,py}' 18.57 + 18.58 +#$ name: filter.include 18.59 + 18.60 +hg status -I '*.in' 18.61 + 18.62 +#$ name: filter.exclude 18.63 + 18.64 +hg status -X '**.py' src
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 19.2 +++ b/en/examples/hook.msglen Mon Mar 05 20:16:36 2007 -0800 19.3 @@ -0,0 +1,14 @@ 19.4 +#!/bin/sh 19.5 + 19.6 +hg init a 19.7 +cd a 19.8 +echo '[hooks]' > .hg/hgrc 19.9 +echo 'pretxncommit.msglen = test `hg tip --template {desc} | wc -c` -ge 10' >> .hg/hgrc 19.10 + 19.11 +#$ name: run 19.12 + 19.13 +cat .hg/hgrc 19.14 +echo a > a 19.15 +hg add a 19.16 +hg commit -A -m 'too short' 19.17 +hg commit -A -m 'long enough'
20.1 --- a/en/examples/hook.simple Fri Jul 21 22:42:19 2006 -0700 20.2 +++ b/en/examples/hook.simple Mon Mar 05 20:16:36 2007 -0800 20.3 @@ -1,3 +1,5 @@ 20.4 +#!/bin/bash 20.5 + 20.6 #$ name: init 20.7 20.8 hg init hook-test
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 21.2 +++ b/en/examples/hook.ws Mon Mar 05 20:16:36 2007 -0800 21.3 @@ -0,0 +1,31 @@ 21.4 +#!/bin/bash 21.5 + 21.6 +hg init a 21.7 +cd a 21.8 +echo '[hooks]' > .hg/hgrc 21.9 +echo "pretxncommit.whitespace = hg export tip | (! grep -qP '^\\+.*[ \\t]$')" >> .hg/hgrc 21.10 + 21.11 +#$ name: simple 21.12 + 21.13 +cat .hg/hgrc 21.14 +echo 'a ' > a 21.15 +hg commit -A -m 'test with trailing whitespace' 21.16 +echo 'a' > a 21.17 +hg commit -A -m 'drop trailing whitespace and try again' 21.18 + 21.19 +#$ name: 21.20 + 21.21 +echo '[hooks]' > .hg/hgrc 21.22 +echo "pretxncommit.whitespace = check_whitespace.py" >> .hg/hgrc 21.23 +cp $EXAMPLE_DIR/data/check_whitespace.py . 21.24 + 21.25 +#$ name: better 21.26 + 21.27 +cat .hg/hgrc 21.28 +echo 'a ' >> a 21.29 +hg commit -A -m 'add new line with trailing whitespace' 21.30 +perl -pi -e 's,\s+$,,' a 21.31 +hg commit -A -m 'trimmed trailing whitespace' 21.32 + 21.33 +#$ name: 21.34 +exit 0
22.1 --- a/en/examples/mq.diff Fri Jul 21 22:42:19 2006 -0700 22.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 22.3 @@ -1,12 +0,0 @@ 22.4 -#$ name: diff 22.5 - 22.6 -echo 'this is my first line' > oldfile 22.7 -echo 'my first line is here' > newfile 22.8 - 22.9 -diff -u oldfile newfile > tiny.patch 22.10 - 22.11 -cat tiny.patch 22.12 - 22.13 -patch < tiny.patch 22.14 - 22.15 -cat newfile
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 23.2 +++ b/en/examples/mq.dodiff Mon Mar 05 20:16:36 2007 -0800 23.3 @@ -0,0 +1,14 @@ 23.4 +#!/bin/bash 23.5 + 23.6 +#$ name: diff 23.7 + 23.8 +echo 'this is my first line' > oldfile 23.9 +echo 'my first line is here' > newfile 23.10 + 23.11 +diff -u oldfile newfile > tiny.patch 23.12 + 23.13 +cat tiny.patch 23.14 + 23.15 +patch < tiny.patch 23.16 + 23.17 +cat newfile
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 24.2 +++ b/en/examples/mq.guards Mon Mar 05 20:16:36 2007 -0800 24.3 @@ -0,0 +1,67 @@ 24.4 +#!/bin/bash 24.5 + 24.6 +echo '[extensions]' >> $HGRC 24.7 +echo 'hgext.mq =' >> $HGRC 24.8 + 24.9 +hg init a 24.10 +cd a 24.11 + 24.12 +#$ name: init 24.13 + 24.14 +hg qinit 24.15 +hg qnew hello.patch 24.16 +echo hello > hello 24.17 +hg add hello 24.18 +hg qrefresh 24.19 +hg qnew goodbye.patch 24.20 +echo goodbye > goodbye 24.21 +hg add goodbye 24.22 +hg qrefresh 24.23 + 24.24 +#$ name: qguard 24.25 + 24.26 +hg qguard 24.27 + 24.28 +#$ name: qguard.pos 24.29 + 24.30 +hg qguard +foo 24.31 +hg qguard 24.32 + 24.33 +#$ name: qguard.neg 24.34 + 24.35 +hg qguard hello.patch -quux 24.36 +hg qguard hello.patch 24.37 + 24.38 +#$ name: series 24.39 + 24.40 +cat .hg/patches/series 24.41 + 24.42 +#$ name: qselect.foo 24.43 + 24.44 +hg qpop -a 24.45 +hg qselect 24.46 +hg qselect foo 24.47 +hg qselect 24.48 + 24.49 +#$ name: qselect.cat 24.50 + 24.51 +cat .hg/patches/guards 24.52 + 24.53 +#$ name: qselect.qpush 24.54 +hg qpush -a 24.55 + 24.56 +#$ name: qselect.error 24.57 + 24.58 +hg qselect +foo 24.59 + 24.60 +#$ name: qselect.quux 24.61 + 24.62 +hg qselect quux 24.63 +hg qpop -a 24.64 +hg qpush -a 24.65 + 24.66 +#$ name: qselect.foobar 24.67 + 24.68 +hg qselect foo bar 24.69 +hg qpop -a 24.70 +hg qpush -a
25.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 25.2 +++ b/en/examples/mq.id Mon Mar 05 20:16:36 2007 -0800 25.3 @@ -0,0 +1,28 @@ 25.4 +#!/bin/sh 25.5 + 25.6 +echo '[extensions]' >> $HGRC 25.7 +echo 'hgext.mq =' >> $HGRC 25.8 + 25.9 +hg init a 25.10 +cd a 25.11 +hg qinit 25.12 +echo 'int x;' > test.c 25.13 +hg ci -Ama 25.14 + 25.15 +hg qnew first.patch 25.16 +echo 'float c;' >> test.c 25.17 +hg qrefresh 25.18 + 25.19 +hg qnew second.patch 25.20 +echo 'double u;' > other.c 25.21 +hg add other.c 25.22 +hg qrefresh 25.23 + 25.24 +#$ name: out 25.25 + 25.26 +hg qapplied 25.27 +hg log -r qbase:qtip 25.28 +hg export second.patch 25.29 + 25.30 +#$ name: 25.31 +exit 0
26.1 --- a/en/examples/mq.qinit-help Fri Jul 21 22:42:19 2006 -0700 26.2 +++ b/en/examples/mq.qinit-help Mon Mar 05 20:16:36 2007 -0800 26.3 @@ -1,3 +1,5 @@ 26.4 +#!/bin/bash 26.5 + 26.6 echo '[extensions]' >> $HGRC 26.7 echo 'hgext.mq =' >> $HGRC 26.8
27.1 --- a/en/examples/mq.tarball Fri Jul 21 22:42:19 2006 -0700 27.2 +++ b/en/examples/mq.tarball Mon Mar 05 20:16:36 2007 -0800 27.3 @@ -1,3 +1,5 @@ 27.4 +#!/bin/bash 27.5 + 27.6 cp $EXAMPLE_DIR/data/netplug-*.tar.bz2 . 27.7 ln -s /bin/true download 27.8
28.1 --- a/en/examples/mq.tools Fri Jul 21 22:42:19 2006 -0700 28.2 +++ b/en/examples/mq.tools Mon Mar 05 20:16:36 2007 -0800 28.3 @@ -1,3 +1,5 @@ 28.4 +#!/bin/bash 28.5 + 28.6 cp $EXAMPLE_DIR/data/remove-redundant-null-checks.patch . 28.7 28.8 #$ name: tools
29.1 --- a/en/examples/mq.tutorial Fri Jul 21 22:42:19 2006 -0700 29.2 +++ b/en/examples/mq.tutorial Mon Mar 05 20:16:36 2007 -0800 29.3 @@ -1,3 +1,5 @@ 29.4 +#!/bin/bash 29.5 + 29.6 echo '[extensions]' >> $HGRC 29.7 echo 'hgext.mq =' >> $HGRC 29.8 29.9 @@ -66,3 +68,6 @@ 29.10 echo 'file 3, line 1' >> file3 29.11 hg qnew add-file3.patch 29.12 hg qnew -f add-file3.patch 29.13 + 29.14 +#$ name: 29.15 +exit 0
30.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 30.2 +++ b/en/examples/rollback Mon Mar 05 20:16:36 2007 -0800 30.3 @@ -0,0 +1,37 @@ 30.4 +#!/bin/bash 30.5 + 30.6 +hg init a 30.7 +cd a 30.8 +echo a > a 30.9 +hg ci -A -m 'First commit' 30.10 + 30.11 +echo a >> a 30.12 + 30.13 +#$ name: tip 30.14 + 30.15 +#$ name: commit 30.16 + 30.17 +hg status 30.18 +echo b > b 30.19 +hg commit -m 'Add file b' 30.20 + 30.21 +#$ name: status 30.22 + 30.23 +hg status 30.24 +hg tip 30.25 + 30.26 +#$ name: rollback 30.27 + 30.28 +hg rollback 30.29 +hg tip 30.30 +hg status 30.31 + 30.32 +#$ name: add 30.33 + 30.34 +hg add b 30.35 +hg commit -m 'Add file b, this time for real' 30.36 + 30.37 +#$ name: twice 30.38 + 30.39 +hg rollback 30.40 +hg rollback
31.1 --- a/en/examples/run-example Fri Jul 21 22:42:19 2006 -0700 31.2 +++ b/en/examples/run-example Mon Mar 05 20:16:36 2007 -0800 31.3 @@ -1,13 +1,16 @@ 31.4 -#!/usr/bin/python 31.5 +#!/usr/bin/env python 31.6 # 31.7 # This program takes something that resembles a shell script and runs 31.8 # it, spitting input (commands from the script) and output into text 31.9 # files, for use in examples. 31.10 31.11 import cStringIO 31.12 +import errno 31.13 +import getopt 31.14 import os 31.15 import pty 31.16 import re 31.17 +import select 31.18 import shutil 31.19 import signal 31.20 import stat 31.21 @@ -15,22 +18,37 @@ 31.22 import tempfile 31.23 import time 31.24 31.25 +tex_subs = { 31.26 + '\\': '\\textbackslash{}', 31.27 + '{': '\\{', 31.28 + '}': '\\}', 31.29 + } 31.30 + 31.31 +def gensubs(s): 31.32 + start = 0 31.33 + for i, c in enumerate(s): 31.34 + sub = tex_subs.get(c) 31.35 + if sub: 31.36 + yield s[start:i] 31.37 + start = i + 1 31.38 + yield sub 31.39 + yield s[start:] 31.40 + 31.41 def tex_escape(s): 31.42 - if '\\' in s: 31.43 - s = s.replace('\\', '\\\\') 31.44 - if '{' in s: 31.45 - s = s.replace('{', '\\{') 31.46 - if '}' in s: 31.47 - s = s.replace('}', '\\}') 31.48 - return s 31.49 + return ''.join(gensubs(s)) 31.50 31.51 class example: 31.52 - shell = '/bin/bash' 31.53 - prompt = '__run_example_prompt__\n' 31.54 - pi_re = re.compile('#\$\s*(name):\s*(.*)$') 31.55 + shell = '/usr/bin/env bash' 31.56 + ps1 = '__run_example_ps1__ ' 31.57 + ps2 = '__run_example_ps2__ ' 31.58 + pi_re = re.compile(r'#\$\s*(name):\s*(.*)$') 31.59 31.60 - def __init__(self, name): 31.61 + timeout = 5 31.62 + 31.63 + def __init__(self, name, verbose): 31.64 self.name = name 31.65 + self.verbose = verbose 31.66 + self.poll = select.poll() 31.67 31.68 def parse(self): 31.69 '''yield each hunk of input from the file.''' 31.70 @@ -49,35 +67,75 @@ 31.71 sys.stdout.flush() 31.72 31.73 def send(self, s): 31.74 - self.cfp.write(s) 31.75 - self.cfp.flush() 31.76 - 31.77 + if self.verbose: 31.78 + print >> sys.stderr, '>', self.debugrepr(s) 31.79 + while s: 31.80 + count = os.write(self.cfd, s) 31.81 + s = s[count:] 31.82 + 31.83 + def debugrepr(self, s): 31.84 + rs = repr(s) 31.85 + limit = 60 31.86 + if len(rs) > limit: 31.87 + return ('%s%s ... [%d bytes]' % (rs[:limit], rs[0], len(s))) 31.88 + else: 31.89 + return rs 31.90 + 31.91 + timeout = 5 31.92 + 31.93 + def read(self): 31.94 + events = self.poll.poll(self.timeout * 1000) 31.95 + if not events: 31.96 + print >> sys.stderr, '[timed out after %d seconds]' % self.timeout 31.97 + os.kill(self.pid, signal.SIGHUP) 31.98 + return '' 31.99 + return os.read(self.cfd, 1024) 31.100 + 31.101 def receive(self): 31.102 out = cStringIO.StringIO() 31.103 while True: 31.104 - s = self.cfp.readline().replace('\r\n', '\n') 31.105 - if not s or s == self.prompt: 31.106 - break 31.107 + try: 31.108 + if self.verbose: 31.109 + sys.stderr.write('< ') 31.110 + s = self.read() 31.111 + except OSError, err: 31.112 + if err.errno == errno.EIO: 31.113 + return '', '' 31.114 + raise 31.115 + if self.verbose: 31.116 + print >> sys.stderr, self.debugrepr(s) 31.117 out.write(s) 31.118 - return out.getvalue() 31.119 + s = out.getvalue() 31.120 + if s.endswith(self.ps1): 31.121 + return self.ps1, s.replace('\r\n', '\n')[:-len(self.ps1)] 31.122 + if s.endswith(self.ps2): 31.123 + return self.ps2, s.replace('\r\n', '\n')[:-len(self.ps2)] 31.124 31.125 def sendreceive(self, s): 31.126 self.send(s) 31.127 - r = self.receive() 31.128 + ps, r = self.receive() 31.129 if r.startswith(s): 31.130 r = r[len(s):] 31.131 - return r 31.132 + return ps, r 31.133 31.134 def run(self): 31.135 ofp = None 31.136 basename = os.path.basename(self.name) 31.137 self.status('running %s ' % basename) 31.138 tmpdir = tempfile.mkdtemp(prefix=basename) 31.139 + 31.140 + rcfile = os.path.join(tmpdir, '.hgrc') 31.141 + rcfp = open(rcfile, 'w') 31.142 + print >> rcfp, '[ui]' 31.143 + print >> rcfp, "username = Bryan O'Sullivan <bos@serpentine.com>" 31.144 + 31.145 rcfile = os.path.join(tmpdir, '.bashrc') 31.146 rcfp = open(rcfile, 'w') 31.147 - print >> rcfp, 'PS1="%s"' % self.prompt 31.148 + print >> rcfp, 'PS1="%s"' % self.ps1 31.149 + print >> rcfp, 'PS2="%s"' % self.ps2 31.150 print >> rcfp, 'unset HISTFILE' 31.151 print >> rcfp, 'export EXAMPLE_DIR="%s"' % os.getcwd() 31.152 + print >> rcfp, 'export HGMERGE=merge' 31.153 print >> rcfp, 'export LANG=C' 31.154 print >> rcfp, 'export LC_ALL=C' 31.155 print >> rcfp, 'export TZ=GMT' 31.156 @@ -85,69 +143,121 @@ 31.157 print >> rcfp, 'export HGRCPATH=$HGRC' 31.158 print >> rcfp, 'cd %s' % tmpdir 31.159 rcfp.close() 31.160 - pid, fd = pty.fork() 31.161 - if pid == 0: 31.162 - #os.execl(self.shell, self.shell) 31.163 - os.system('/bin/bash --noediting --noprofile --norc') 31.164 - sys.exit(0) 31.165 - self.cfp = os.fdopen(fd, 'w+') 31.166 + sys.stdout.flush() 31.167 + sys.stderr.flush() 31.168 + self.pid, self.cfd = pty.fork() 31.169 + if self.pid == 0: 31.170 + cmdline = ['/usr/bin/env', 'bash', '--noediting', '--noprofile', 31.171 + '--norc'] 31.172 + try: 31.173 + os.execv(cmdline[0], cmdline) 31.174 + except OSError, err: 31.175 + print >> sys.stderr, '%s: %s' % (cmdline[0], err.strerror) 31.176 + sys.stderr.flush() 31.177 + os._exit(0) 31.178 + self.poll.register(self.cfd, select.POLLIN | select.POLLERR | 31.179 + select.POLLHUP) 31.180 + 31.181 + prompts = { 31.182 + '': '', 31.183 + self.ps1: '$', 31.184 + self.ps2: '>', 31.185 + } 31.186 + 31.187 try: 31.188 - # setup env and prompt 31.189 - self.sendreceive('source %s\n\n' % rcfile) 31.190 - for hunk in self.parse(): 31.191 - # is this line a processing instruction? 31.192 - m = self.pi_re.match(hunk) 31.193 - if m: 31.194 - pi, rest = m.groups() 31.195 - if pi == 'name': 31.196 - self.status('.') 31.197 - out = rest 31.198 - assert os.sep not in out 31.199 - if out: 31.200 - ofp = open('%s.%s.out' % (self.name, out), 'w') 31.201 - else: 31.202 - ofp = None 31.203 - elif hunk.strip(): 31.204 - # it's something we should execute 31.205 - output = self.sendreceive(hunk) 31.206 - if not ofp: 31.207 - continue 31.208 - # first, print the command we ran 31.209 - if not hunk.startswith('#'): 31.210 - nl = hunk.endswith('\n') 31.211 - hunk = ('$ \\textbf{%s}' % 31.212 - tex_escape(hunk.rstrip('\n'))) 31.213 - if nl: hunk += '\n' 31.214 - ofp.write(hunk) 31.215 - # then its output 31.216 - ofp.write(tex_escape(output)) 31.217 - self.status('\n') 31.218 + try: 31.219 + # eat first prompt string from shell 31.220 + self.read() 31.221 + # setup env and prompt 31.222 + ps, output = self.sendreceive('source %s\n' % rcfile) 31.223 + for hunk in self.parse(): 31.224 + # is this line a processing instruction? 31.225 + m = self.pi_re.match(hunk) 31.226 + if m: 31.227 + pi, rest = m.groups() 31.228 + if pi == 'name': 31.229 + self.status('.') 31.230 + out = rest 31.231 + assert os.sep not in out 31.232 + if out: 31.233 + ofp = open('%s.%s.out' % (self.name, out), 'w') 31.234 + else: 31.235 + ofp = None 31.236 + elif hunk.strip(): 31.237 + # it's something we should execute 31.238 + newps, output = self.sendreceive(hunk) 31.239 + if not ofp: 31.240 + continue 31.241 + # first, print the command we ran 31.242 + if not hunk.startswith('#'): 31.243 + nl = hunk.endswith('\n') 31.244 + hunk = ('%s \\textbf{%s}' % 31.245 + (prompts[ps], 31.246 + tex_escape(hunk.rstrip('\n')))) 31.247 + if nl: hunk += '\n' 31.248 + ofp.write(hunk) 31.249 + # then its output 31.250 + ofp.write(tex_escape(output)) 31.251 + ps = newps 31.252 + self.status('\n') 31.253 + open(self.name + '.run', 'w') 31.254 + except: 31.255 + print >> sys.stderr, '(killed)' 31.256 + os.kill(self.pid, signal.SIGKILL) 31.257 + pid, rc = os.wait() 31.258 + raise 31.259 + else: 31.260 + try: 31.261 + ps, output = self.sendreceive('exit\n') 31.262 + if ofp: 31.263 + ofp.write(output) 31.264 + os.close(self.cfd) 31.265 + except IOError: 31.266 + pass 31.267 + os.kill(self.pid, signal.SIGTERM) 31.268 + pid, rc = os.wait() 31.269 + if rc: 31.270 + if os.WIFEXITED(rc): 31.271 + print >> sys.stderr, '(exit %s)' % os.WEXITSTATUS(rc) 31.272 + elif os.WIFSIGNALED(rc): 31.273 + print >> sys.stderr, '(signal %s)' % os.WTERMSIG(rc) 31.274 + return rc 31.275 finally: 31.276 - try: 31.277 - output = self.sendreceive('exit\n') 31.278 - if ofp: 31.279 - ofp.write(output) 31.280 - self.cfp.close() 31.281 - except IOError: 31.282 - pass 31.283 - os.kill(pid, signal.SIGTERM) 31.284 - os.wait() 31.285 shutil.rmtree(tmpdir) 31.286 31.287 def main(path='.'): 31.288 - args = sys.argv[1:] 31.289 + opts, args = getopt.getopt(sys.argv[1:], 'v', ['verbose']) 31.290 + verbose = False 31.291 + for o, a in opts: 31.292 + if o in ('-v', '--verbose'): 31.293 + verbose = True 31.294 + errs = 0 31.295 if args: 31.296 for a in args: 31.297 - example(a).run() 31.298 - return 31.299 + try: 31.300 + st = os.lstat(a) 31.301 + except OSError, err: 31.302 + print >> sys.stderr, '%s: %s' % (a, err.strerror) 31.303 + errs += 1 31.304 + continue 31.305 + if stat.S_ISREG(st.st_mode) and st.st_mode & 0111: 31.306 + if example(a, verbose).run(): 31.307 + errs += 1 31.308 + else: 31.309 + print >> sys.stderr, '%s: not a file, or not executable' % a 31.310 + errs += 1 31.311 + return errs 31.312 for name in os.listdir(path): 31.313 if name == 'run-example' or name.startswith('.'): continue 31.314 if name.endswith('.out') or name.endswith('~'): continue 31.315 + if name.endswith('.run'): continue 31.316 pathname = os.path.join(path, name) 31.317 st = os.lstat(pathname) 31.318 if stat.S_ISREG(st.st_mode) and st.st_mode & 0111: 31.319 - example(pathname).run() 31.320 + if example(pathname, verbose).run(): 31.321 + errs += 1 31.322 print >> open(os.path.join(path, '.run'), 'w'), time.asctime() 31.323 + return errs 31.324 31.325 if __name__ == '__main__': 31.326 - main() 31.327 + sys.exit(main())
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 32.2 +++ b/en/examples/svn-long.txt Mon Mar 05 20:16:36 2007 -0800 32.3 @@ -0,0 +1,11 @@ 32.4 +------------------------------------------------------------------------ 32.5 +r9653 | sean.hefty | 2006-09-27 14:39:55 -0700 (Wed, 27 Sep 2006) | 5 lines 32.6 +Changed paths: 32.7 + M /gen2/trunk/src/linux-kernel/infiniband/core/cma.c 32.8 + 32.9 +On reporting a route error, also include the status for the error, 32.10 +rather than indicating a status of 0 when an error has occurred. 32.11 + 32.12 +Signed-off-by: Sean Hefty <sean.hefty@intel.com> 32.13 + 32.14 +------------------------------------------------------------------------
33.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 33.2 +++ b/en/examples/svn-short.txt Mon Mar 05 20:16:36 2007 -0800 33.3 @@ -0,0 +1,9 @@ 33.4 +------------------------------------------------------------------------ 33.5 +r9653 | sean.hefty | 2006-09-27 14:39:55 -0700 (Wed, 27 Sep 2006) | 5 lines 33.6 + 33.7 +On reporting a route error, also include the status for the error, 33.8 +rather than indicating a status of 0 when an error has occurred. 33.9 + 33.10 +Signed-off-by: Sean Hefty <sean.hefty@intel.com> 33.11 + 33.12 +------------------------------------------------------------------------
34.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 34.2 +++ b/en/examples/svn.style Mon Mar 05 20:16:36 2007 -0800 34.3 @@ -0,0 +1,2 @@ 34.4 +header = '------------------------------------------------------------------------\n\n' 34.5 +changeset = svn.template
35.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 35.2 +++ b/en/examples/svn.template Mon Mar 05 20:16:36 2007 -0800 35.3 @@ -0,0 +1,5 @@ 35.4 +r{rev} | {author|user} | {date|isodate} ({date|rfc822date}) 35.5 + 35.6 +{desc|strip|fill76} 35.7 + 35.8 +------------------------------------------------------------------------
36.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 36.2 +++ b/en/examples/template.simple Mon Mar 05 20:16:36 2007 -0800 36.3 @@ -0,0 +1,92 @@ 36.4 +#!/bin/bash 36.5 + 36.6 +hg init myrepo 36.7 +cd myrepo 36.8 +echo hello > hello 36.9 +hg commit -Am'added hello' 36.10 + 36.11 +echo hello >> hello 36.12 +echo goodbye > goodbye 36.13 +echo ' added line to end of <<hello>> file.' > ../msg 36.14 +echo '' >> ../msg 36.15 +echo 'in addition, added a file with the helpful name (at least i hope that some might consider it so) of goodbye.' >> ../msg 36.16 + 36.17 +hg commit -Al../msg 36.18 + 36.19 +hg tag mytag 36.20 +hg tag v0.1 36.21 + 36.22 +#$ name: normal 36.23 + 36.24 +hg log -r1 36.25 + 36.26 +#$ name: compact 36.27 + 36.28 +hg log --style compact 36.29 + 36.30 +#$ name: changelog 36.31 + 36.32 +hg log --style changelog 36.33 + 36.34 +#$ name: simplest 36.35 + 36.36 +hg log -r1 --template 'i saw a changeset\n' 36.37 + 36.38 +#$ name: simplesub 36.39 + 36.40 +hg log --template 'i saw a changeset: {desc}\n' 36.41 + 36.42 +#$ name: keywords 36.43 + 36.44 +hg log -r1 --template 'author: {author}\n' 36.45 +hg log -r1 --template 'desc:\n{desc}\n' 36.46 +hg log -r1 --template 'files: {files}\n' 36.47 +hg log -r1 --template 'file_adds: {file_adds}\n' 36.48 +hg log -r1 --template 'file_dels: {file_dels}\n' 36.49 +hg log -r1 --template 'node: {node}\n' 36.50 +hg log -r1 --template 'parents: {parents}\n' 36.51 +hg log -r1 --template 'rev: {rev}\n' 36.52 +hg log -r1 --template 'tags: {tags}\n' 36.53 + 36.54 +#$ name: datekeyword 36.55 + 36.56 +hg log -r1 --template 'date: {date}\n' 36.57 +hg log -r1 --template 'date: {date|isodate}\n' 36.58 + 36.59 +#$ name: manyfilters 36.60 + 36.61 +hg log -r1 --template '{author}\n' 36.62 +hg log -r1 --template '{author|domain}\n' 36.63 +hg log -r1 --template '{author|email}\n' 36.64 +hg log -r1 --template '{author|obfuscate}\n' | cut -c-76 36.65 +hg log -r1 --template '{author|person}\n' 36.66 +hg log -r1 --template '{author|user}\n' 36.67 + 36.68 +hg log -r1 --template 'looks almost right, but actually garbage: {date}\n' 36.69 +hg log -r1 --template '{date|age}\n' 36.70 +hg log -r1 --template '{date|date}\n' 36.71 +hg log -r1 --template '{date|hgdate}\n' 36.72 +hg log -r1 --template '{date|isodate}\n' 36.73 +hg log -r1 --template '{date|rfc822date}\n' 36.74 +hg log -r1 --template '{date|shortdate}\n' 36.75 + 36.76 +hg log -r1 --template '{desc}\n' | cut -c-76 36.77 +hg log -r1 --template '{desc|addbreaks}\n' | cut -c-76 36.78 +hg log -r1 --template '{desc|escape}\n' | cut -c-76 36.79 +hg log -r1 --template '{desc|fill68}\n' 36.80 +hg log -r1 --template '{desc|fill76}\n' 36.81 +hg log -r1 --template '{desc|firstline}\n' 36.82 +hg log -r1 --template '{desc|strip}\n' | cut -c-76 36.83 +hg log -r1 --template '{desc|tabindent}\n' | expand | cut -c-76 36.84 + 36.85 +hg log -r1 --template '{node}\n' 36.86 +hg log -r1 --template '{node|short}\n' 36.87 + 36.88 +#$ name: combine 36.89 + 36.90 +hg log -r1 --template 'description:\n\t{desc|strip|fill68|tabindent}\n' 36.91 + 36.92 +#$ name: rev 36.93 + 36.94 +echo 'changeset = "rev: {rev}\n"' > rev 36.95 +hg log -l1 --style ./rev
37.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 37.2 +++ b/en/examples/template.svnstyle Mon Mar 05 20:16:36 2007 -0800 37.3 @@ -0,0 +1,69 @@ 37.4 +#!/bin/bash 37.5 + 37.6 +svn() { 37.7 + cat $EXAMPLE_DIR/svn-short.txt 37.8 +} 37.9 + 37.10 +#$ name: short 37.11 + 37.12 +svn log -r9653 37.13 + 37.14 +#$ name: 37.15 + 37.16 +hg init myrepo 37.17 +cd myrepo 37.18 + 37.19 +echo hello > hello 37.20 +hg commit -Am'added hello' 37.21 + 37.22 +echo hello >> hello 37.23 +echo goodbye > goodbye 37.24 +echo ' added line to end of <<hello>> file.' > ../msg 37.25 +echo '' >> ../msg 37.26 +echo 'in addition, added a file with the helpful name (at least i hope that some might consider it so) of goodbye.' >> ../msg 37.27 + 37.28 +hg commit -Al../msg 37.29 + 37.30 +hg tag mytag 37.31 +hg tag v0.1 37.32 + 37.33 +echo 'changeset = "{node|short}\n"' > svn.style 37.34 + 37.35 +#$ name: id 37.36 + 37.37 +hg log -r0 --template '{node}' 37.38 + 37.39 +#$ name: simplest 37.40 + 37.41 +cat svn.style 37.42 +hg log -r1 --style svn.style 37.43 + 37.44 +#$ name: 37.45 + 37.46 +echo 'changeset =' > broken.style 37.47 + 37.48 +#$ name: syntax.input 37.49 + 37.50 +cat broken.style 37.51 + 37.52 +#$ name: syntax.error 37.53 + 37.54 +hg log -r1 --style broken.style 37.55 + 37.56 +#$ name: 37.57 + 37.58 +cp $EXAMPLE_DIR/svn.style . 37.59 +cp $EXAMPLE_DIR/svn.template . 37.60 + 37.61 +#$ name: template 37.62 + 37.63 +cat svn.template 37.64 + 37.65 +#$ name: style 37.66 + 37.67 +cat svn.style 37.68 + 37.69 +#$ name: result 37.70 + 37.71 +hg log -r1 --style svn.style 37.72 +
38.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 38.2 +++ b/en/examples/tour Mon Mar 05 20:16:36 2007 -0800 38.3 @@ -0,0 +1,186 @@ 38.4 +#!/bin/bash 38.5 + 38.6 +#$ name: version 38.7 + 38.8 +hg version 38.9 + 38.10 +#$ name: help 38.11 + 38.12 +hg help init 38.13 + 38.14 +#$ name: clone 38.15 + 38.16 +hg clone http://hg.serpentine.com/tutorial/hello 38.17 + 38.18 +#$ name: ls 38.19 + 38.20 +ls -l 38.21 +ls hello 38.22 + 38.23 +#$ name: ls-a 38.24 + 38.25 +cd hello 38.26 +ls -a 38.27 + 38.28 +#$ name: log 38.29 + 38.30 +hg log 38.31 + 38.32 +#$ name: log-r 38.33 + 38.34 +hg log -r 3 38.35 +hg log -r ff5d7b70a2a9 38.36 +hg log -r 1 -r 4 38.37 + 38.38 +#$ name: log.range 38.39 + 38.40 +hg log -r 2:4 38.41 + 38.42 +#$ name: log-v 38.43 + 38.44 +hg log -v -r 3 38.45 + 38.46 +#$ name: log-vp 38.47 + 38.48 +hg log -v -p -r 2 38.49 + 38.50 +#$ name: reclone 38.51 + 38.52 +cd .. 38.53 +hg clone hello my-hello 38.54 +cd my-hello 38.55 + 38.56 +#$ name: sed 38.57 + 38.58 +sed -i '/printf/a\\tprintf("hello again!\\n");' hello.c 38.59 + 38.60 +#$ name: status 38.61 + 38.62 +ls 38.63 +hg status 38.64 + 38.65 +#$ name: diff 38.66 + 38.67 +hg diff 38.68 + 38.69 +#$ name: 38.70 + 38.71 +export HGEDITOR='echo Added an extra line of output >' 38.72 +HGRCPATH_ORIG=$HGRCPATH 38.73 +export HGRCPATH= 38.74 + 38.75 +#$ name: commit-no-user 38.76 + 38.77 +hg commit 38.78 + 38.79 +#$ name: 38.80 + 38.81 +export HGRCPATH=$HGRCPATH_ORIG 38.82 + 38.83 +#$ name: commit 38.84 + 38.85 +hg commit 38.86 + 38.87 +#$ name: tip 38.88 + 38.89 +hg tip -vp 38.90 + 38.91 +#$ name: clone-pull 38.92 + 38.93 +cd .. 38.94 +hg clone hello hello-pull 38.95 + 38.96 +#$ name: incoming 38.97 + 38.98 +cd hello-pull 38.99 +hg incoming ../my-hello 38.100 + 38.101 +#$ name: pull 38.102 + 38.103 +hg tip 38.104 +hg pull ../my-hello 38.105 +hg tip 38.106 + 38.107 +#$ name: update 38.108 + 38.109 +grep printf hello.c 38.110 +hg update tip 38.111 +grep printf hello.c 38.112 + 38.113 +#$ name: parents 38.114 + 38.115 +hg parents 38.116 + 38.117 +#$ name: older 38.118 + 38.119 +hg update 2 38.120 +hg parents 38.121 +hg update 38.122 + 38.123 +#$ name: clone-push 38.124 + 38.125 +cd .. 38.126 +hg clone hello hello-push 38.127 + 38.128 +#$ name: outgoing 38.129 + 38.130 +cd my-hello 38.131 +hg outgoing ../hello-push 38.132 + 38.133 +#$ name: push 38.134 + 38.135 +hg push ../hello-push 38.136 + 38.137 +#$ name: push.nothing 38.138 + 38.139 +hg push ../hello-push 38.140 + 38.141 +#$ name: outgoing.net 38.142 + 38.143 +hg outgoing http://hg.serpentine.com/tutorial/hello 38.144 + 38.145 +#$ name: push.net 38.146 + 38.147 +hg push http://hg.serpentine.com/tutorial/hello 38.148 + 38.149 +#$ name: merge.clone 38.150 + 38.151 +cd .. 38.152 +hg clone hello my-new-hello 38.153 +cd my-new-hello 38.154 +sed -i '/printf/i\\tprintf("once more, hello.\\n");' hello.c 38.155 +hg commit -m 'A new hello for a new day.' 38.156 + 38.157 +#$ name: merge.cat 38.158 + 38.159 +cat hello.c 38.160 +cat ../my-hello/hello.c 38.161 + 38.162 +#$ name: merge.pull 38.163 + 38.164 +hg pull ../my-hello 38.165 + 38.166 +#$ name: merge.heads 38.167 + 38.168 +hg heads 38.169 + 38.170 +#$ name: merge.update 38.171 + 38.172 +hg update 38.173 + 38.174 +#$ name: merge.merge 38.175 + 38.176 +hg merge 38.177 + 38.178 +#$ name: merge.parents 38.179 + 38.180 +hg parents 38.181 +cat hello.c 38.182 + 38.183 +#$ name: merge.commit 38.184 + 38.185 +hg commit -m 'Merged changes' 38.186 + 38.187 +#$ name: merge.tip 38.188 + 38.189 +hg tip
39.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 39.2 +++ b/en/examples/tour-merge-conflict Mon Mar 05 20:16:36 2007 -0800 39.3 @@ -0,0 +1,71 @@ 39.4 +#!/bin/bash 39.5 + 39.6 +hg init scam 39.7 +cd scam 39.8 + 39.9 +#$ name: wife 39.10 + 39.11 +cat > letter.txt <<EOF 39.12 +Greetings! 39.13 + 39.14 +I am Mariam Abacha, the wife of former 39.15 +Nigerian dictator Sani Abacha. 39.16 +EOF 39.17 + 39.18 +hg add letter.txt 39.19 +hg commit -m '419 scam, first draft' 39.20 + 39.21 +#$ name: cousin 39.22 + 39.23 +cd .. 39.24 +hg clone scam scam-cousin 39.25 +cd scam-cousin 39.26 + 39.27 +cat > letter.txt <<EOF 39.28 +Greetings! 39.29 + 39.30 +I am Shehu Musa Abacha, cousin to the former 39.31 +Nigerian dictator Sani Abacha. 39.32 +EOF 39.33 + 39.34 +hg commit -m '419 scam, with cousin' 39.35 + 39.36 +#$ name: son 39.37 + 39.38 +cd .. 39.39 +hg clone scam scam-son 39.40 +cd scam-son 39.41 + 39.42 +cat > letter.txt <<EOF 39.43 +Greetings! 39.44 + 39.45 +I am Alhaji Abba Abacha, son of the former 39.46 +Nigerian dictator Sani Abacha. 39.47 +EOF 39.48 + 39.49 +hg commit -m '419 scam, with son' 39.50 + 39.51 +#$ name: pull 39.52 + 39.53 +cd .. 39.54 +hg clone scam-cousin scam-merge 39.55 +cd scam-merge 39.56 +hg pull -u ../scam-son 39.57 + 39.58 +#$ name: merge 39.59 + 39.60 +export HGMERGE=merge 39.61 +hg merge 39.62 +cat letter.txt 39.63 + 39.64 +#$ name: commit 39.65 + 39.66 +cat > letter.txt <<EOF 39.67 +Greetings! 39.68 + 39.69 +I am Bryan O'Sullivan, no relation of the former 39.70 +Nigerian dictator Sani Abacha. 39.71 +EOF 39.72 + 39.73 +hg commit -m 'Send me your money' 39.74 +hg tip
40.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 40.2 +++ b/en/filelog.svg Mon Mar 05 20:16:36 2007 -0800 40.3 @@ -0,0 +1,371 @@ 40.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?> 40.5 +<!-- Created with Inkscape (http://www.inkscape.org/) --> 40.6 +<svg 40.7 + xmlns:dc="http://purl.org/dc/elements/1.1/" 40.8 + xmlns:cc="http://web.resource.org/cc/" 40.9 + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 40.10 + xmlns:svg="http://www.w3.org/2000/svg" 40.11 + xmlns="http://www.w3.org/2000/svg" 40.12 + xmlns:xlink="http://www.w3.org/1999/xlink" 40.13 + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" 40.14 + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" 40.15 + width="744.09448819" 40.16 + height="1052.3622047" 40.17 + id="svg2" 40.18 + sodipodi:version="0.32" 40.19 + inkscape:version="0.44.1" 40.20 + sodipodi:docname="filelog.svg"> 40.21 + <defs 40.22 + id="defs4"> 40.23 + <marker 40.24 + inkscape:stockid="Arrow1Mend" 40.25 + orient="auto" 40.26 + refY="0.0" 40.27 + refX="0.0" 40.28 + id="Arrow1Mend" 40.29 + style="overflow:visible;"> 40.30 + <path 40.31 + id="path3128" 40.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 " 40.33 + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;" 40.34 + transform="scale(0.4) rotate(180) translate(10,0)" /> 40.35 + </marker> 40.36 + <linearGradient 40.37 + id="linearGradient2887"> 40.38 + <stop 40.39 + style="stop-color:#91cfcf;stop-opacity:1;" 40.40 + offset="0" 40.41 + id="stop2889" /> 40.42 + <stop 40.43 + style="stop-color:aqua;stop-opacity:0;" 40.44 + offset="1" 40.45 + id="stop2891" /> 40.46 + </linearGradient> 40.47 + <linearGradient 40.48 + id="linearGradient2795"> 40.49 + <stop 40.50 + style="stop-color:#ccc;stop-opacity:1;" 40.51 + offset="0" 40.52 + id="stop2797" /> 40.53 + <stop 40.54 + style="stop-color:#ccc;stop-opacity:0;" 40.55 + offset="1" 40.56 + id="stop2799" /> 40.57 + </linearGradient> 40.58 + <linearGradient 40.59 + inkscape:collect="always" 40.60 + xlink:href="#linearGradient2795" 40.61 + id="linearGradient3170" 40.62 + gradientUnits="userSpaceOnUse" 40.63 + gradientTransform="translate(121.2183,94.95434)" 40.64 + x1="81.322357" 40.65 + y1="404.34424" 40.66 + x2="201.52036" 40.67 + y2="373.03967" /> 40.68 + <linearGradient 40.69 + inkscape:collect="always" 40.70 + xlink:href="#linearGradient2887" 40.71 + id="linearGradient3172" 40.72 + gradientUnits="userSpaceOnUse" 40.73 + gradientTransform="translate(0,12)" 40.74 + x1="62.634491" 40.75 + y1="503.3392" 40.76 + x2="248.49242" 40.77 + y2="462.94327" /> 40.78 + <linearGradient 40.79 + inkscape:collect="always" 40.80 + xlink:href="#linearGradient2795" 40.81 + id="linearGradient3174" 40.82 + gradientUnits="userSpaceOnUse" 40.83 + gradientTransform="matrix(1.001035,0,0,0.653159,236.7075,153.0415)" 40.84 + x1="81.322357" 40.85 + y1="404.34424" 40.86 + x2="201.52036" 40.87 + y2="373.03967" /> 40.88 + <linearGradient 40.89 + inkscape:collect="always" 40.90 + xlink:href="#linearGradient2887" 40.91 + id="linearGradient3176" 40.92 + gradientUnits="userSpaceOnUse" 40.93 + gradientTransform="translate(0,12)" 40.94 + x1="62.634491" 40.95 + y1="503.3392" 40.96 + x2="248.49242" 40.97 + y2="462.94327" /> 40.98 + <linearGradient 40.99 + inkscape:collect="always" 40.100 + xlink:href="#linearGradient2795" 40.101 + id="linearGradient3208" 40.102 + gradientUnits="userSpaceOnUse" 40.103 + gradientTransform="matrix(1.001035,0,0,0.653159,236.7075,153.0415)" 40.104 + x1="81.322357" 40.105 + y1="404.34424" 40.106 + x2="201.52036" 40.107 + y2="373.03967" /> 40.108 + <linearGradient 40.109 + inkscape:collect="always" 40.110 + xlink:href="#linearGradient2887" 40.111 + id="linearGradient3210" 40.112 + gradientUnits="userSpaceOnUse" 40.113 + gradientTransform="translate(0,12)" 40.114 + x1="62.634491" 40.115 + y1="503.3392" 40.116 + x2="248.49242" 40.117 + y2="462.94327" /> 40.118 + <linearGradient 40.119 + inkscape:collect="always" 40.120 + xlink:href="#linearGradient2795" 40.121 + id="linearGradient3212" 40.122 + gradientUnits="userSpaceOnUse" 40.123 + gradientTransform="translate(121.2183,94.95434)" 40.124 + x1="81.322357" 40.125 + y1="404.34424" 40.126 + x2="201.52036" 40.127 + y2="373.03967" /> 40.128 + <linearGradient 40.129 + inkscape:collect="always" 40.130 + xlink:href="#linearGradient2887" 40.131 + id="linearGradient3214" 40.132 + gradientUnits="userSpaceOnUse" 40.133 + gradientTransform="translate(0,12)" 40.134 + x1="62.634491" 40.135 + y1="503.3392" 40.136 + x2="248.49242" 40.137 + y2="462.94327" /> 40.138 + <linearGradient 40.139 + inkscape:collect="always" 40.140 + xlink:href="#linearGradient2795" 40.141 + id="linearGradient3256" 40.142 + gradientUnits="userSpaceOnUse" 40.143 + gradientTransform="translate(121.2183,94.95434)" 40.144 + x1="81.322357" 40.145 + y1="404.34424" 40.146 + x2="201.52036" 40.147 + y2="373.03967" /> 40.148 + <linearGradient 40.149 + inkscape:collect="always" 40.150 + xlink:href="#linearGradient2887" 40.151 + id="linearGradient3258" 40.152 + gradientUnits="userSpaceOnUse" 40.153 + gradientTransform="translate(0,12)" 40.154 + x1="62.634491" 40.155 + y1="503.3392" 40.156 + x2="248.49242" 40.157 + y2="462.94327" /> 40.158 + <linearGradient 40.159 + inkscape:collect="always" 40.160 + xlink:href="#linearGradient2795" 40.161 + id="linearGradient3260" 40.162 + gradientUnits="userSpaceOnUse" 40.163 + gradientTransform="matrix(1.001035,0,0,0.653159,236.7075,153.0415)" 40.164 + x1="81.322357" 40.165 + y1="404.34424" 40.166 + x2="201.52036" 40.167 + y2="373.03967" /> 40.168 + <linearGradient 40.169 + inkscape:collect="always" 40.170 + xlink:href="#linearGradient2887" 40.171 + id="linearGradient3262" 40.172 + gradientUnits="userSpaceOnUse" 40.173 + gradientTransform="translate(0,12)" 40.174 + x1="62.634491" 40.175 + y1="503.3392" 40.176 + x2="248.49242" 40.177 + y2="462.94327" /> 40.178 + </defs> 40.179 + <sodipodi:namedview 40.180 + id="base" 40.181 + pagecolor="#ffffff" 40.182 + bordercolor="#666666" 40.183 + borderopacity="1.0" 40.184 + gridtolerance="10000" 40.185 + guidetolerance="10" 40.186 + objecttolerance="10" 40.187 + inkscape:pageopacity="0.0" 40.188 + inkscape:pageshadow="2" 40.189 + inkscape:zoom="0.98994949" 40.190 + inkscape:cx="455.8122" 40.191 + inkscape:cy="520" 40.192 + inkscape:document-units="px" 40.193 + inkscape:current-layer="layer1" 40.194 + inkscape:window-width="906" 40.195 + inkscape:window-height="620" 40.196 + inkscape:window-x="5" 40.197 + inkscape:window-y="49" /> 40.198 + <metadata 40.199 + id="metadata7"> 40.200 + <rdf:RDF> 40.201 + <cc:Work 40.202 + rdf:about=""> 40.203 + <dc:format>image/svg+xml</dc:format> 40.204 + <dc:type 40.205 + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 40.206 + </cc:Work> 40.207 + </rdf:RDF> 40.208 + </metadata> 40.209 + <g 40.210 + inkscape:label="Layer 1" 40.211 + inkscape:groupmode="layer" 40.212 + id="layer1"> 40.213 + <rect 40.214 + style="opacity:1;fill:#abadf8;fill-opacity:1;stroke:#595959;stroke-width:0.86781615;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" 40.215 + id="rect3180" 40.216 + width="234.48758" 40.217 + height="199.13225" 40.218 + x="322.67767" 40.219 + y="351.75531" /> 40.220 + <rect 40.221 + style="opacity:1;fill:#a2f69c;fill-opacity:1;stroke:#595959;stroke-width:0.86781615;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" 40.222 + id="rect3178" 40.223 + width="234.48756" 40.224 + height="199.13223" 40.225 + x="72.664886" 40.226 + y="351.75531" /> 40.227 + <g 40.228 + id="g3144" 40.229 + transform="translate(34,0.71578)"> 40.230 + <g 40.231 + id="g2940"> 40.232 + <rect 40.233 + style="fill:url(#linearGradient3260);fill-opacity:1;stroke:black;stroke-width:0.80860078;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" 40.234 + id="rect2914" 40.235 + width="185.04932" 40.236 + height="39.587399" 40.237 + x="311.53635" 40.238 + y="395.04291" /> 40.239 + <text 40.240 + xml:space="preserve" 40.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" 40.242 + x="323.72824" 40.243 + y="416.7626" 40.244 + id="text2918"><tspan 40.245 + sodipodi:role="line" 40.246 + id="tspan2920" 40.247 + x="323.72824" 40.248 + y="416.7626" 40.249 + style="font-family:Courier">.hg/data/README.i</tspan></text> 40.250 + </g> 40.251 + <g 40.252 + transform="translate(3.79093e-5,-80.1853)" 40.253 + id="g2945"> 40.254 + <g 40.255 + id="g2955"> 40.256 + <rect 40.257 + y="475.44327" 40.258 + x="63.134491" 40.259 + height="39.395935" 40.260 + width="184.85793" 40.261 + id="rect2947" 40.262 + style="fill:url(#linearGradient3262);fill-opacity:1;stroke:black;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /> 40.263 + <text 40.264 + id="text2949" 40.265 + y="498.35123" 40.266 + x="75.230644" 40.267 + style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman" 40.268 + xml:space="preserve"><tspan 40.269 + style="font-family:Courier" 40.270 + y="498.35123" 40.271 + x="75.230644" 40.272 + id="tspan2951" 40.273 + sodipodi:role="line">README</tspan></text> 40.274 + </g> 40.275 + </g> 40.276 + <path 40.277 + inkscape:connection-end="#g2940" 40.278 + inkscape:connection-start="#g2945" 40.279 + inkscape:connector-type="polyline" 40.280 + id="path2960" 40.281 + d="M 248.49245,414.91131 L 311.13205,414.88123" 40.282 + 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" /> 40.283 + </g> 40.284 + <g 40.285 + id="g3156" 40.286 + transform="translate(34,0.71578)"> 40.287 + <g 40.288 + transform="translate(116,0)" 40.289 + id="g2831"> 40.290 + <rect 40.291 + style="fill:url(#linearGradient3256);fill-opacity:1;stroke:black;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" 40.292 + id="rect1906" 40.293 + width="184.85793" 40.294 + height="60.609138" 40.295 + x="195.96959" 40.296 + y="465.46356" /> 40.297 + <g 40.298 + id="g2803" 40.299 + transform="translate(-0.893671,1.833581)"> 40.300 + <text 40.301 + id="text1884" 40.302 + y="483.92801" 40.303 + x="208.95944" 40.304 + style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman" 40.305 + xml:space="preserve"><tspan 40.306 + style="font-family:Courier" 40.307 + y="483.92801" 40.308 + x="208.95944" 40.309 + id="tspan1886" 40.310 + sodipodi:role="line">.hg/data/src/hello.c.d</tspan></text> 40.311 + <text 40.312 + id="text1888" 40.313 + y="507.79309" 40.314 + x="208.95944" 40.315 + style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman" 40.316 + xml:space="preserve"><tspan 40.317 + style="font-family:Courier" 40.318 + y="507.79309" 40.319 + x="208.95944" 40.320 + id="tspan1890" 40.321 + sodipodi:role="line">.hg/data/src/hello.c.i</tspan></text> 40.322 + </g> 40.323 + </g> 40.324 + <g 40.325 + id="g2907"> 40.326 + <rect 40.327 + style="fill:url(#linearGradient3258);fill-opacity:1;stroke:black;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" 40.328 + id="rect2843" 40.329 + width="184.85793" 40.330 + height="39.395935" 40.331 + x="63.134491" 40.332 + y="475.44327" /> 40.333 + <text 40.334 + xml:space="preserve" 40.335 + style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman" 40.336 + x="75.230644" 40.337 + y="498.35123" 40.338 + id="text2847"><tspan 40.339 + sodipodi:role="line" 40.340 + id="tspan2849" 40.341 + x="75.230644" 40.342 + y="498.35123" 40.343 + style="font-family:Courier">src/hello.c</tspan></text> 40.344 + </g> 40.345 + <path 40.346 + inkscape:connection-end="#g2831" 40.347 + inkscape:connection-start="#g2907" 40.348 + inkscape:connector-type="polyline" 40.349 + id="path2962" 40.350 + d="M 248.49242,495.37535 L 311.46959,495.53401" 40.351 + 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" /> 40.352 + </g> 40.353 + <text 40.354 + xml:space="preserve" 40.355 + style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman" 40.356 + x="96.476799" 40.357 + y="373.96353" 40.358 + id="text3216"><tspan 40.359 + sodipodi:role="line" 40.360 + id="tspan3218" 40.361 + x="96.476799" 40.362 + y="373.96353">Working directory</tspan></text> 40.363 + <text 40.364 + xml:space="preserve" 40.365 + style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman" 40.366 + x="344.92493" 40.367 + y="373.96353" 40.368 + id="text3228"><tspan 40.369 + sodipodi:role="line" 40.370 + id="tspan3230" 40.371 + x="344.92493" 40.372 + y="373.96353">Repository</tspan></text> 40.373 + </g> 40.374 +</svg>
41.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 41.2 +++ b/en/filenames.tex Mon Mar 05 20:16:36 2007 -0800 41.3 @@ -0,0 +1,306 @@ 41.4 +\chapter{File names and pattern matching} 41.5 +\label{chap:names} 41.6 + 41.7 +Mercurial provides mechanisms that let you work with file names in a 41.8 +consistent and expressive way. 41.9 + 41.10 +\section{Simple file naming} 41.11 + 41.12 +Mercurial uses a unified piece of machinery ``under the hood'' to 41.13 +handle file names. Every command behaves uniformly with respect to 41.14 +file names. The way in which commands work with file names is as 41.15 +follows. 41.16 + 41.17 +If you explicitly name real files on the command line, Mercurial works 41.18 +with exactly those files, as you would expect. 41.19 +\interaction{filenames.files} 41.20 + 41.21 +When you provide a directory name, Mercurial will interpret this as 41.22 +``operate on every file in this directory and its subdirectories''. 41.23 +Mercurial traverses the files and subdirectories in a directory in 41.24 +alphabetical order. When it encounters a subdirectory, it will 41.25 +traverse that subdirectory before continuing with the current 41.26 +directory. 41.27 +\interaction{filenames.dirs} 41.28 + 41.29 +\section{Running commands without any file names} 41.30 + 41.31 +Mercurial's commands that work with file names have useful default 41.32 +behaviours when you invoke them without providing any file names or 41.33 +patterns. What kind of behaviour you should expect depends on what 41.34 +the command does. Here are a few rules of thumb you can use to 41.35 +predict what a command is likely to do if you don't give it any names 41.36 +to work with. 41.37 +\begin{itemize} 41.38 +\item Most commands will operate on the entire working directory. 41.39 + This is what the \hgcmd{add} command does, for example. 41.40 +\item If the command has effects that are difficult or impossible to 41.41 + reverse, it will force you to explicitly provide at least one name 41.42 + or pattern (see below). This protects you from accidentally 41.43 + deleting files by running \hgcmd{remove} with no arguments, for 41.44 + example. 41.45 +\end{itemize} 41.46 + 41.47 +It's easy to work around these default behaviours if they don't suit 41.48 +you. If a command normally operates on the whole working directory, 41.49 +you can invoke it on just the current directory and its subdirectories 41.50 +by giving it the name ``\dirname{.}''. 41.51 +\interaction{filenames.wdir-subdir} 41.52 + 41.53 +Along the same lines, some commands normally print file names relative 41.54 +to the root of the repository, even if you're invoking them from a 41.55 +subdirectory. Such a command will print file names relative to your 41.56 +subdirectory if you give it explicit names. Here, we're going to run 41.57 +\hgcmd{status} from a subdirectory, and get it to operate on the 41.58 +entire working directory while printing file names relative to our 41.59 +subdirectory, by passing it the output of the \hgcmd{root} command. 41.60 +\interaction{filenames.wdir-relname} 41.61 + 41.62 +\section{Telling you what's going on} 41.63 + 41.64 +The \hgcmd{add} example in the preceding section illustrates something 41.65 +else that's helpful about Mercurial commands. If a command operates 41.66 +on a file that you didn't name explicitly on the command line, it will 41.67 +usually print the name of the file, so that you will not be surprised 41.68 +what's going on. 41.69 + 41.70 +The principle here is of \emph{least surprise}. If you've exactly 41.71 +named a file on the command line, there's no point in repeating it 41.72 +back at you. If Mercurial is acting on a file \emph{implicitly}, 41.73 +because you provided no names, or a directory, or a pattern (see 41.74 +below), it's safest to tell you what it's doing. 41.75 + 41.76 +For commands that behave this way, you can silence them using the 41.77 +\hggopt{-q} option. You can also get them to print the name of every 41.78 +file, even those you've named explicitly, using the \hggopt{-v} 41.79 +option. 41.80 + 41.81 +\section{Using patterns to identify files} 41.82 + 41.83 +In addition to working with file and directory names, Mercurial lets 41.84 +you use \emph{patterns} to identify files. Mercurial's pattern 41.85 +handling is expressive. 41.86 + 41.87 +On Unix-like systems (Linux, MacOS, etc.), the job of matching file 41.88 +names to patterns normally falls to the shell. On these systems, you 41.89 +must explicitly tell Mercurial that a name is a pattern. On Windows, 41.90 +the shell does not expand patterns, so Mercurial will automatically 41.91 +identify names that are patterns, and expand them for you. 41.92 + 41.93 +To provide a pattern in place of a regular name on the command line, 41.94 +the mechanism is simple: 41.95 +\begin{codesample2} 41.96 + syntax:patternbody 41.97 +\end{codesample2} 41.98 +That is, a pattern is identified by a short text string that says what 41.99 +kind of pattern this is, followed by a colon, followed by the actual 41.100 +pattern. 41.101 + 41.102 +Mercurial supports two kinds of pattern syntax. The most frequently 41.103 +used is called \texttt{glob}; this is the same kind of pattern 41.104 +matching used by the Unix shell, and should be familiar to Windows 41.105 +command prompt users, too. 41.106 + 41.107 +When Mercurial does automatic pattern matching on Windows, it uses 41.108 +\texttt{glob} syntax. You can thus omit the ``\texttt{glob:}'' prefix 41.109 +on Windows, but it's safe to use it, too. 41.110 + 41.111 +The \texttt{re} syntax is more powerful; it lets you specify patterns 41.112 +using regular expressions, also known as regexps. 41.113 + 41.114 +By the way, in the examples that follow, notice that I'm careful to 41.115 +wrap all of my patterns in quote characters, so that they won't get 41.116 +expanded by the shell before Mercurial sees them. 41.117 + 41.118 +\subsection{Shell-style \texttt{glob} patterns} 41.119 + 41.120 +This is an overview of the kinds of patterns you can use when you're 41.121 +matching on glob patterns. 41.122 + 41.123 +The ``\texttt{*}'' character matches any string, within a single 41.124 +directory. 41.125 +\interaction{filenames.glob.star} 41.126 + 41.127 +The ``\texttt{**}'' pattern matches any string, and crosses directory 41.128 +boundaries. It's not a standard Unix glob token, but it's accepted by 41.129 +several popular Unix shells, and is very useful. 41.130 +\interaction{filenames.glob.starstar} 41.131 + 41.132 +The ``\texttt{?}'' pattern matches any single character. 41.133 +\interaction{filenames.glob.question} 41.134 + 41.135 +The ``\texttt{[}'' character begins a \emph{character class}. This 41.136 +matches any single character within the class. The class ends with a 41.137 +``\texttt{]}'' character. A class may contain multiple \emph{range}s 41.138 +of the form ``\texttt{a-f}'', which is shorthand for 41.139 +``\texttt{abcdef}''. 41.140 +\interaction{filenames.glob.range} 41.141 +If the first character after the ``\texttt{[}'' in a character class 41.142 +is a ``\texttt{!}'', it \emph{negates} the class, making it match any 41.143 +single character not in the class. 41.144 + 41.145 +A ``\texttt{\{}'' begins a group of subpatterns, where the whole group 41.146 +matches if any subpattern in the group matches. The ``\texttt{,}'' 41.147 +character separates subpatterns, and ``\texttt{\}}'' ends the group. 41.148 +\interaction{filenames.glob.group} 41.149 + 41.150 +\subsubsection{Watch out!} 41.151 + 41.152 +Don't forget that if you want to match a pattern in any directory, you 41.153 +should not be using the ``\texttt{*}'' match-any token, as this will 41.154 +only match within one directory. Instead, use the ``\texttt{**}'' 41.155 +token. This small example illustrates the difference between the two. 41.156 +\interaction{filenames.glob.star-starstar} 41.157 + 41.158 +\subsection{Regular expression matching with \texttt{re} patterns} 41.159 + 41.160 +Mercurial accepts the same regular expression syntax as the Python 41.161 +programming language (it uses Python's regexp engine internally). 41.162 +This is based on the Perl language's regexp syntax, which is the most 41.163 +popular dialect in use (it's also used in Java, for example). 41.164 + 41.165 +I won't discuss Mercurial's regexp dialect in any detail here, as 41.166 +regexps are not often used. Perl-style regexps are in any case 41.167 +already exhaustively documented on a multitude of web sites, and in 41.168 +many books. Instead, I will focus here on a few things you should 41.169 +know if you find yourself needing to use regexps with Mercurial. 41.170 + 41.171 +A regexp is matched against an entire file name, relative to the root 41.172 +of the repository. In other words, even if you're already in 41.173 +subbdirectory \dirname{foo}, if you want to match files under this 41.174 +directory, your pattern must start with ``\texttt{foo/}''. 41.175 + 41.176 +One thing to note, if you're familiar with Perl-style regexps, is that 41.177 +Mercurial's are \emph{rooted}. That is, a regexp starts matching 41.178 +against the beginning of a string; it doesn't look for a match 41.179 +anywhere within the string it. To match anywhere in a string, start 41.180 +your pattern with ``\texttt{.*}''. 41.181 + 41.182 +\section{Filtering files} 41.183 + 41.184 +Not only does Mercurial give you a variety of ways to specify files; 41.185 +it lets you further winnow those files using \emph{filters}. Commands 41.186 +that work with file names accept two filtering options. 41.187 +\begin{itemize} 41.188 +\item \hggopt{-I}, or \hggopt{--include}, lets you specify a pattern 41.189 + that file names must match in order to be processed. 41.190 +\item \hggopt{-X}, or \hggopt{--exclude}, gives you a way to 41.191 + \emph{avoid} processing files, if they match this pattern. 41.192 +\end{itemize} 41.193 +You can provide multiple \hggopt{-I} and \hggopt{-X} options on the 41.194 +command line, and intermix them as you please. Mercurial interprets 41.195 +the patterns you provide using glob syntax by default (but you can use 41.196 +regexps if you need to). 41.197 + 41.198 +You can read a \hggopt{-I} filter as ``process only the files that 41.199 +match this filter''. 41.200 +\interaction{filenames.filter.include} 41.201 +The \hggopt{-X} filter is best read as ``process only the files that 41.202 +don't match this pattern''. 41.203 +\interaction{filenames.filter.exclude} 41.204 + 41.205 +\section{Ignoring unwanted files and directories} 41.206 + 41.207 +XXX. 41.208 + 41.209 +\section{Case sensitivity} 41.210 +\label{sec:names:case} 41.211 + 41.212 +If you're working in a mixed development environment that contains 41.213 +both Linux (or other Unix) systems and Macs or Windows systems, you 41.214 +should keep in the back of your mind the knowledge that they treat the 41.215 +case (``N'' versus ``n'') of file names in incompatible ways. This is 41.216 +not very likely to affect you, and it's easy to deal with if it does, 41.217 +but it could surprise you if you don't know about it. 41.218 + 41.219 +Operating systems and filesystems differ in the way they handle the 41.220 +\emph{case} of characters in file and directory names. There are 41.221 +three common ways to handle case in names. 41.222 +\begin{itemize} 41.223 +\item Completely case insensitive. Uppercase and lowercase versions 41.224 + of a letter are treated as identical, both when creating a file and 41.225 + during subsequent accesses. This is common on older DOS-based 41.226 + systems. 41.227 +\item Case preserving, but insensitive. When a file or directory is 41.228 + created, the case of its name is stored, and can be retrieved and 41.229 + displayed by the operating system. When an existing file is being 41.230 + looked up, its case is ignored. This is the standard arrangement on 41.231 + Windows and MacOS. The names \filename{foo} and \filename{FoO} 41.232 + identify the same file. This treatment of uppercase and lowercase 41.233 + letters as interchangeable is also referred to as \emph{case 41.234 + folding}. 41.235 +\item Case sensitive. The case of a name is significant at all times. 41.236 + The names \filename{foo} and {FoO} identify different files. This 41.237 + is the way Linux and Unix systems normally work. 41.238 +\end{itemize} 41.239 + 41.240 +On Unix-like systems, it is possible to have any or all of the above 41.241 +ways of handling case in action at once. For example, if you use a 41.242 +USB thumb drive formatted with a FAT32 filesystem on a Linux system, 41.243 +Linux will handle names on that filesystem in a case preserving, but 41.244 +insensitive, way. 41.245 + 41.246 +\subsection{Safe, portable repository storage} 41.247 + 41.248 +Mercurial's repository storage mechanism is \emph{case safe}. It 41.249 +translates file names so that they can be safely stored on both case 41.250 +sensitive and case insensitive filesystems. This means that you can 41.251 +use normal file copying tools to transfer a Mercurial repository onto, 41.252 +for example, a USB thumb drive, and safely move that drive and 41.253 +repository back and forth between a Mac, a PC running Windows, and a 41.254 +Linux box. 41.255 + 41.256 +\subsection{Detecting case conflicts} 41.257 + 41.258 +When operating in the working directory, Mercurial honours the naming 41.259 +policy of the filesystem where the working directory is located. If 41.260 +the filesystem is case preserving, but insensitive, Mercurial will 41.261 +treat names that differ only in case as the same. 41.262 + 41.263 +An important aspect of this approach is that it is possible to commit 41.264 +a changeset on a case sensitive (typically Linux or Unix) filesystem 41.265 +that will cause trouble for users on case insensitive (usually Windows 41.266 +and MacOS) users. If a Linux user commits changes to two files, one 41.267 +named \filename{myfile.c} and the other named \filename{MyFile.C}, 41.268 +they will be stored correctly in the repository. And in the working 41.269 +directories of other Linux users, they will be correctly represented 41.270 +as separate files. 41.271 + 41.272 +If a Windows or Mac user pulls this change, they will not initially 41.273 +have a problem, because Mercurial's repository storage mechanism is 41.274 +case safe. However, once they try to \hgcmd{update} the working 41.275 +directory to that changeset, or \hgcmd{merge} with that changeset, 41.276 +Mercurial will spot the conflict between the two file names that the 41.277 +filesystem would treat as the same, and forbid the update or merge 41.278 +from occurring. 41.279 + 41.280 +\subsection{Fixing a case conflict} 41.281 + 41.282 +If you are using Windows or a Mac in a mixed environment where some of 41.283 +your collaborators are using Linux or Unix, and Mercurial reports a 41.284 +case folding conflict when you try to \hgcmd{update} or \hgcmd{merge}, 41.285 +the procedure to fix the problem is simple. 41.286 + 41.287 +Just find a nearby Linux or Unix box, clone the problem repository 41.288 +onto it, and use Mercurial's \hgcmd{rename} command to change the 41.289 +names of any offending files or directories so that they will no 41.290 +longer cause case folding conflicts. Commit this change, \hgcmd{pull} 41.291 +or \hgcmd{push} it across to your Windows or MacOS system, and 41.292 +\hgcmd{update} to the revision with the non-conflicting names. 41.293 + 41.294 +The changeset with case-conflicting names will remain in your 41.295 +project's history, and you still won't be able to \hgcmd{update} your 41.296 +working directory to that changeset on a Windows or MacOS system, but 41.297 +you can continue development unimpeded. 41.298 + 41.299 +\begin{note} 41.300 + Prior to version~0.9.3, Mercurial did not use a case safe repository 41.301 + storage mechanism, and did not detect case folding conflicts. If 41.302 + you are using an older version of Mercurial on Windows or MacOS, I 41.303 + strongly recommend that you upgrade. 41.304 +\end{note} 41.305 + 41.306 +%%% Local Variables: 41.307 +%%% mode: latex 41.308 +%%% TeX-master: "00book" 41.309 +%%% End:
42.1 --- a/en/hook.tex Fri Jul 21 22:42:19 2006 -0700 42.2 +++ b/en/hook.tex Mon Mar 05 20:16:36 2007 -0800 42.3 @@ -177,7 +177,7 @@ 42.4 (which contains pointers to the new manifest data). Before the first 42.5 write to each file, it stores a record of where the end of the file 42.6 was in its transaction log. If the transaction must be rolled back, 42.7 -Mercurial simply truncates each file back to te size it was before the 42.8 +Mercurial simply truncates each file back to the size it was before the 42.9 transaction began. 42.10 42.11 When Mercurial \emph{reads} metadata, it reads the changelog first, 42.12 @@ -358,8 +358,8 @@ 42.13 number 1 (for ``true'') or 0 (for ``false'') as an environment 42.14 variable for an external hook. If a hook parameter is named 42.15 \texttt{foo}, the keyword argument for a Python hook will also be 42.16 -named \texttt{foo} Python, while the environment variable for an 42.17 -external hook will be named \texttt{HG\_FOO}. 42.18 +named \texttt{foo}, while the environment variable for an external 42.19 +hook will be named \texttt{HG\_FOO}. 42.20 42.21 \subsection{Hook return values and activity control} 42.22 42.23 @@ -430,7 +430,532 @@ 42.24 doesn't care about by dropping them into a keyword argument dict, as 42.25 with \texttt{**kwargs} above. 42.26 42.27 -\section{Hook reference} 42.28 +\section{Some hook examples} 42.29 + 42.30 +\subsection{Writing meaningful commit messages} 42.31 + 42.32 +It's hard to imagine a useful commit message being very short. The 42.33 +simple \hook{pretxncommit} hook of figure~\ref{ex:hook:msglen.run} 42.34 +will prevent you from committing a changeset with a message that is 42.35 +less than ten bytes long. 42.36 + 42.37 +\begin{figure}[ht] 42.38 + \interaction{hook.msglen.run} 42.39 + \caption{A hook that forbids overly short commit messages} 42.40 + \label{ex:hook:msglen.run} 42.41 +\end{figure} 42.42 + 42.43 +\subsection{Checking for trailing whitespace} 42.44 + 42.45 +An interesting use of a commit-related hook is to help you to write 42.46 +cleaner code. A simple example of ``cleaner code'' is the dictum that 42.47 +a change should not add any new lines of text that contain ``trailing 42.48 +whitespace''. Trailing whitespace is a series of space and tab 42.49 +characters at the end of a line of text. In most cases, trailing 42.50 +whitespace is unnecessary, invisible noise, but it is occasionally 42.51 +problematic, and people often prefer to get rid of it. 42.52 + 42.53 +You can use either the \hook{precommit} or \hook{pretxncommit} hook to 42.54 +tell whether you have a trailing whitespace problem. If you use the 42.55 +\hook{precommit} hook, the hook will not know which files you are 42.56 +committing, so it will have to check every modified file in the 42.57 +repository for trailing white space. If you want to commit a change 42.58 +to just the file \filename{foo}, but the file \filename{bar} contains 42.59 +trailing whitespace, doing a check in the \hook{precommit} hook will 42.60 +prevent you from committing \filename{foo} due to the problem with 42.61 +\filename{bar}. This doesn't seem right. 42.62 + 42.63 +Should you choose the \hook{pretxncommit} hook, the check won't occur 42.64 +until just before the transaction for the commit completes. This will 42.65 +allow you to check for problems only the exact files that are being 42.66 +committed. However, if you entered the commit message interactively 42.67 +and the hook fails, the transaction will roll back; you'll have to 42.68 +re-enter the commit message after you fix the trailing whitespace and 42.69 +run \hgcmd{commit} again. 42.70 + 42.71 +\begin{figure}[ht] 42.72 + \interaction{hook.ws.simple} 42.73 + \caption{A simple hook that checks for trailing whitespace} 42.74 + \label{ex:hook:ws.simple} 42.75 +\end{figure} 42.76 + 42.77 +Figure~\ref{ex:hook:ws.simple} introduces a simple \hook{pretxncommit} 42.78 +hook that checks for trailing whitespace. This hook is short, but not 42.79 +very helpful. It exits with an error status if a change adds a line 42.80 +with trailing whitespace to any file, but does not print any 42.81 +information that might help us to identify the offending file or 42.82 +line. It also has the nice property of not paying attention to 42.83 +unmodified lines; only lines that introduce new trailing whitespace 42.84 +cause problems. 42.85 + 42.86 +\begin{figure}[ht] 42.87 + \interaction{hook.ws.better} 42.88 + \caption{A better trailing whitespace hook} 42.89 + \label{ex:hook:ws.better} 42.90 +\end{figure} 42.91 + 42.92 +The example of figure~\ref{ex:hook:ws.better} is much more complex, 42.93 +but also more useful. It parses a unified diff to see if any lines 42.94 +add trailing whitespace, and prints the name of the file and the line 42.95 +number of each such occurrence. Even better, if the change adds 42.96 +trailing whitespace, this hook saves the commit comment and prints the 42.97 +name of the save file before exiting and telling Mercurial to roll the 42.98 +transaction back, so you can use 42.99 +\hgcmdargs{commit}{\hgopt{commit}{-l}~\emph{filename}} to reuse the 42.100 +saved commit message once you've corrected the problem. 42.101 + 42.102 +As a final aside, note in figure~\ref{ex:hook:ws.better} the use of 42.103 +\command{perl}'s in-place editing feature to get rid of trailing 42.104 +whitespace from a file. This is concise and useful enough that I will 42.105 +reproduce it here. 42.106 +\begin{codesample2} 42.107 + perl -pi -e 's,\\s+\$,,' filename 42.108 +\end{codesample2} 42.109 + 42.110 +\section{Bundled hooks} 42.111 + 42.112 +Mercurial ships with several bundled hooks. You can find them in the 42.113 +\dirname{hgext} directory of a Mercurial source tree. If you are 42.114 +using a Mercurial binary package, the hooks will be located in the 42.115 +\dirname{hgext} directory of wherever your package installer put 42.116 +Mercurial. 42.117 + 42.118 +\subsection{\hgext{acl}---access control for parts of a repository} 42.119 + 42.120 +The \hgext{acl} extension lets you control which remote users are 42.121 +allowed to push changesets to a networked server. You can protect any 42.122 +portion of a repository (including the entire repo), so that a 42.123 +specific remote user can push changes that do not affect the protected 42.124 +portion. 42.125 + 42.126 +This extension implements access control based on the identity of the 42.127 +user performing a push, \emph{not} on who committed the changesets 42.128 +they're pushing. It makes sense to use this hook only if you have a 42.129 +locked-down server environment that authenticates remote users, and 42.130 +you want to be sure that only specific users are allowed to push 42.131 +changes to that server. 42.132 + 42.133 +\subsubsection{Configuring the \hook{acl} hook} 42.134 + 42.135 +In order to manage incoming changesets, the \hgext{acl} hook must be 42.136 +used as a \hook{pretxnchangegroup} hook. This lets it see which files 42.137 +are modified by each incoming changeset, and roll back a group of 42.138 +changesets if they modify ``forbidden'' files. Example: 42.139 +\begin{codesample2} 42.140 + [hooks] 42.141 + pretxnchangegroup.acl = python:hgext.acl.hook 42.142 +\end{codesample2} 42.143 + 42.144 +The \hgext{acl} extension is configured using three sections. 42.145 + 42.146 +The \rcsection{acl} section has only one entry, \rcitem{acl}{sources}, 42.147 +which lists the sources of incoming changesets that the hook should 42.148 +pay attention to. You don't normally need to configure this section. 42.149 +\begin{itemize} 42.150 +\item[\rcitem{acl}{serve}] Control incoming changesets that are arriving 42.151 + from a remote repository over http or ssh. This is the default 42.152 + value of \rcitem{acl}{sources}, and usually the only setting you'll 42.153 + need for this configuration item. 42.154 +\item[\rcitem{acl}{pull}] Control incoming changesets that are 42.155 + arriving via a pull from a local repository. 42.156 +\item[\rcitem{acl}{push}] Control incoming changesets that are 42.157 + arriving via a push from a local repository. 42.158 +\item[\rcitem{acl}{bundle}] Control incoming changesets that are 42.159 + arriving from another repository via a bundle. 42.160 +\end{itemize} 42.161 + 42.162 +The \rcsection{acl.allow} section controls the users that are allowed to 42.163 +add changesets to the repository. If this section is not present, all 42.164 +users that are not explicitly denied are allowed. If this section is 42.165 +present, all users that are not explicitly allowed are denied (so an 42.166 +empty section means that all users are denied). 42.167 + 42.168 +The \rcsection{acl.deny} section determines which users are denied 42.169 +from adding changesets to the repository. If this section is not 42.170 +present or is empty, no users are denied. 42.171 + 42.172 +The syntaxes for the \rcsection{acl.allow} and \rcsection{acl.deny} 42.173 +sections are identical. On the left of each entry is a glob pattern 42.174 +that matches files or directories, relative to the root of the 42.175 +repository; on the right, a user name. 42.176 + 42.177 +In the following example, the user \texttt{docwriter} can only push 42.178 +changes to the \dirname{docs} subtree of the repository, while 42.179 +\texttt{intern} can push changes to any file or directory except 42.180 +\dirname{source/sensitive}. 42.181 +\begin{codesample2} 42.182 + [acl.allow] 42.183 + docs/** = docwriter 42.184 + 42.185 + [acl.deny] 42.186 + source/sensitive/** = intern 42.187 +\end{codesample2} 42.188 + 42.189 +\subsubsection{Testing and troubleshooting} 42.190 + 42.191 +If you want to test the \hgext{acl} hook, run it with Mercurial's 42.192 +debugging output enabled. Since you'll probably be running it on a 42.193 +server where it's not convenient (or sometimes possible) to pass in 42.194 +the \hggopt{--debug} option, don't forget that you can enable 42.195 +debugging output in your \hgrc: 42.196 +\begin{codesample2} 42.197 + [ui] 42.198 + debug = true 42.199 +\end{codesample2} 42.200 +With this enabled, the \hgext{acl} hook will print enough information 42.201 +to let you figure out why it is allowing or forbidding pushes from 42.202 +specific users. 42.203 + 42.204 +\subsection{\hgext{bugzilla}---integration with Bugzilla} 42.205 + 42.206 +The \hgext{bugzilla} extension adds a comment to a Bugzilla bug 42.207 +whenever it finds a reference to that bug ID in a commit comment. You 42.208 +can install this hook on a shared server, so that any time a remote 42.209 +user pushes changes to this server, the hook gets run. 42.210 + 42.211 +It adds a comment to the bug that looks like this (you can configure 42.212 +the contents of the comment---see below): 42.213 +\begin{codesample2} 42.214 + Changeset aad8b264143a, made by Joe User <joe.user@domain.com> in 42.215 + the frobnitz repository, refers to this bug. 42.216 + 42.217 + For complete details, see 42.218 + http://hg.domain.com/frobnitz?cmd=changeset;node=aad8b264143a 42.219 + 42.220 + Changeset description: 42.221 + Fix bug 10483 by guarding against some NULL pointers 42.222 +\end{codesample2} 42.223 +The value of this hook is that it automates the process of updating a 42.224 +bug any time a changeset refers to it. If you configure the hook 42.225 +properly, it makes it easy for people to browse straight from a 42.226 +Bugzilla bug to a changeset that refers to that bug. 42.227 + 42.228 +You can use the code in this hook as a starting point for some more 42.229 +exotic Bugzilla integration recipes. Here are a few possibilities: 42.230 +\begin{itemize} 42.231 +\item Require that every changeset pushed to the server have a valid 42.232 + bug~ID in its commit comment. In this case, you'd want to configure 42.233 + the hook as a \hook{pretxncommit} hook. This would allow the hook 42.234 + to reject changes that didn't contain bug IDs. 42.235 +\item Allow incoming changesets to automatically modify the 42.236 + \emph{state} of a bug, as well as simply adding a comment. For 42.237 + example, the hook could recognise the string ``fixed bug 31337'' as 42.238 + indicating that it should update the state of bug 31337 to 42.239 + ``requires testing''. 42.240 +\end{itemize} 42.241 + 42.242 +\subsubsection{Configuring the \hook{bugzilla} hook} 42.243 +\label{sec:hook:bugzilla:config} 42.244 + 42.245 +You should configure this hook in your server's \hgrc\ as an 42.246 +\hook{incoming} hook, for example as follows: 42.247 +\begin{codesample2} 42.248 + [hooks] 42.249 + incoming.bugzilla = python:hgext.bugzilla.hook 42.250 +\end{codesample2} 42.251 + 42.252 +Because of the specialised nature of this hook, and because Bugzilla 42.253 +was not written with this kind of integration in mind, configuring 42.254 +this hook is a somewhat involved process. 42.255 + 42.256 +Before you begin, you must install the MySQL bindings for Python on 42.257 +the host(s) where you'll be running the hook. If this is not 42.258 +available as a binary package for your system, you can download it 42.259 +from~\cite{web:mysql-python}. 42.260 + 42.261 +Configuration information for this hook lives in the 42.262 +\rcsection{bugzilla} section of your \hgrc. 42.263 +\begin{itemize} 42.264 +\item[\rcitem{bugzilla}{version}] The version of Bugzilla installed on 42.265 + the server. The database schema that Bugzilla uses changes 42.266 + occasionally, so this hook has to know exactly which schema to use. 42.267 + At the moment, the only version supported is \texttt{2.16}. 42.268 +\item[\rcitem{bugzilla}{host}] The hostname of the MySQL server that 42.269 + stores your Bugzilla data. The database must be configured to allow 42.270 + connections from whatever host you are running the \hook{bugzilla} 42.271 + hook on. 42.272 +\item[\rcitem{bugzilla}{user}] The username with which to connect to 42.273 + the MySQL server. The database must be configured to allow this 42.274 + user to connect from whatever host you are running the 42.275 + \hook{bugzilla} hook on. This user must be able to access and 42.276 + modify Bugzilla tables. The default value of this item is 42.277 + \texttt{bugs}, which is the standard name of the Bugzilla user in a 42.278 + MySQL database. 42.279 +\item[\rcitem{bugzilla}{password}] The MySQL password for the user you 42.280 + configured above. This is stored as plain text, so you should make 42.281 + sure that unauthorised users cannot read the \hgrc\ file where you 42.282 + store this information. 42.283 +\item[\rcitem{bugzilla}{db}] The name of the Bugzilla database on the 42.284 + MySQL server. The default value of this item is \texttt{bugs}, 42.285 + which is the standard name of the MySQL database where Bugzilla 42.286 + stores its data. 42.287 +\item[\rcitem{bugzilla}{notify}] If you want Bugzilla to send out a 42.288 + notification email to subscribers after this hook has added a 42.289 + comment to a bug, you will need this hook to run a command whenever 42.290 + it updates the database. The command to run depends on where you 42.291 + have installed Bugzilla, but it will typically look something like 42.292 + this, if you have Bugzilla installed in 42.293 + \dirname{/var/www/html/bugzilla}: 42.294 + \begin{codesample4} 42.295 + cd /var/www/html/bugzilla && ./processmail %s nobody@nowhere.com 42.296 + \end{codesample4} 42.297 + The Bugzilla \texttt{processmail} program expects to be given a 42.298 + bug~ID (the hook replaces ``\texttt{\%s}'' with the bug~ID) and an 42.299 + email address. It also expects to be able to write to some files in 42.300 + the directory that it runs in. If Bugzilla and this hook are not 42.301 + installed on the same machine, you will need to find a way to run 42.302 + \texttt{processmail} on the server where Bugzilla is installed. 42.303 +\end{itemize} 42.304 + 42.305 +\subsubsection{Mapping committer names to Bugzilla user names} 42.306 + 42.307 +By default, the \hgext{bugzilla} hook tries to use the email address 42.308 +of a changeset's committer as the Bugzilla user name with which to 42.309 +update a bug. If this does not suit your needs, you can map committer 42.310 +email addresses to Bugzilla user names using a \rcsection{usermap} 42.311 +section. 42.312 + 42.313 +Each item in the \rcsection{usermap} section contains an email address 42.314 +on the left, and a Bugzilla user name on the right. 42.315 +\begin{codesample2} 42.316 + [usermap] 42.317 + jane.user@example.com = jane 42.318 +\end{codesample2} 42.319 +You can either keep the \rcsection{usermap} data in a normal \hgrc, or 42.320 +tell the \hgext{bugzilla} hook to read the information from an 42.321 +external \filename{usermap} file. In the latter case, you can store 42.322 +\filename{usermap} data by itself in (for example) a user-modifiable 42.323 +repository. This makes it possible to let your users maintain their 42.324 +own \rcitem{bugzilla}{usermap} entries. The main \hgrc\ file might 42.325 +look like this: 42.326 +\begin{codesample2} 42.327 + # regular hgrc file refers to external usermap file 42.328 + [bugzilla] 42.329 + usermap = /home/hg/repos/userdata/bugzilla-usermap.conf 42.330 +\end{codesample2} 42.331 +While the \filename{usermap} file that it refers to might look like 42.332 +this: 42.333 +\begin{codesample2} 42.334 + # bugzilla-usermap.conf - inside a hg repository 42.335 + [usermap] 42.336 + stephanie@example.com = steph 42.337 +\end{codesample2} 42.338 + 42.339 +\subsubsection{Configuring the text that gets added to a bug} 42.340 + 42.341 +You can configure the text that this hook adds as a comment; you 42.342 +specify it in the form of a Mercurial template. Several \hgrc\ 42.343 +entries (still in the \rcsection{bugzilla} section) control this 42.344 +behaviour. 42.345 +\begin{itemize} 42.346 +\item[\texttt{strip}] The number of leading path elements to strip 42.347 + from a repository's path name to construct a partial path for a URL. 42.348 + For example, if the repositories on your server live under 42.349 + \dirname{/home/hg/repos}, and you have a repository whose path is 42.350 + \dirname{/home/hg/repos/app/tests}, then setting \texttt{strip} to 42.351 + \texttt{4} will give a partial path of \dirname{app/tests}. The 42.352 + hook will make this partial path available when expanding a 42.353 + template, as \texttt{webroot}. 42.354 +\item[\texttt{template}] The text of the template to use. In addition 42.355 + to the usual changeset-related variables, this template can use 42.356 + \texttt{hgweb} (the value of the \texttt{hgweb} configuration item 42.357 + above) and \texttt{webroot} (the path constructed using 42.358 + \texttt{strip} above). 42.359 +\end{itemize} 42.360 + 42.361 +In addition, you can add a \rcitem{web}{baseurl} item to the 42.362 +\rcsection{web} section of your \hgrc. The \hgext{bugzilla} hook will 42.363 +make this available when expanding a template, as the base string to 42.364 +use when constructing a URL that will let users browse from a Bugzilla 42.365 +comment to view a changeset. Example: 42.366 +\begin{codesample2} 42.367 + [web] 42.368 + baseurl = http://hg.domain.com/ 42.369 +\end{codesample2} 42.370 + 42.371 +Here is an example set of \hgext{bugzilla} hook config information. 42.372 +\begin{codesample2} 42.373 + [bugzilla] 42.374 + host = bugzilla.example.com 42.375 + password = mypassword 42.376 + version = 2.16 42.377 + # server-side repos live in /home/hg/repos, so strip 4 leading 42.378 + # separators 42.379 + strip = 4 42.380 + hgweb = http://hg.example.com/ 42.381 + usermap = /home/hg/repos/notify/bugzilla.conf 42.382 + template = Changeset \{node|short\}, made by \{author\} in the \{webroot\} 42.383 + repo, refers to this bug.\\nFor complete details, see 42.384 + \{hgweb\}\{webroot\}?cmd=changeset;node=\{node|short\}\\nChangeset 42.385 + description:\\n\\t\{desc|tabindent\} 42.386 +\end{codesample2} 42.387 + 42.388 +\subsubsection{Testing and troubleshooting} 42.389 + 42.390 +The most common problems with configuring the \hgext{bugzilla} hook 42.391 +relate to running Bugzilla's \filename{processmail} script and mapping 42.392 +committer names to user names. 42.393 + 42.394 +Recall from section~\ref{sec:hook:bugzilla:config} above that the user 42.395 +that runs the Mercurial process on the server is also the one that 42.396 +will run the \filename{processmail} script. The 42.397 +\filename{processmail} script sometimes causes Bugzilla to write to 42.398 +files in its configuration directory, and Bugzilla's configuration 42.399 +files are usually owned by the user that your web server runs under. 42.400 + 42.401 +You can cause \filename{processmail} to be run with the suitable 42.402 +user's identity using the \command{sudo} command. Here is an example 42.403 +entry for a \filename{sudoers} file. 42.404 +\begin{codesample2} 42.405 + hg_user = (httpd_user) NOPASSWD: /var/www/html/bugzilla/processmail-wrapper %s 42.406 +\end{codesample2} 42.407 +This allows the \texttt{hg\_user} user to run a 42.408 +\filename{processmail-wrapper} program under the identity of 42.409 +\texttt{httpd\_user}. 42.410 + 42.411 +This indirection through a wrapper script is necessary, because 42.412 +\filename{processmail} expects to be run with its current directory 42.413 +set to wherever you installed Bugzilla; you can't specify that kind of 42.414 +constraint in a \filename{sudoers} file. The contents of the wrapper 42.415 +script are simple: 42.416 +\begin{codesample2} 42.417 + #!/bin/sh 42.418 + cd `dirname $0` && ./processmail "$1" nobody@example.com 42.419 +\end{codesample2} 42.420 +It doesn't seem to matter what email address you pass to 42.421 +\filename{processmail}. 42.422 + 42.423 +If your \rcsection{usermap} is not set up correctly, users will see an 42.424 +error message from the \hgext{bugzilla} hook when they push changes 42.425 +to the server. The error message will look like this: 42.426 +\begin{codesample2} 42.427 + cannot find bugzilla user id for john.q.public@example.com 42.428 +\end{codesample2} 42.429 +What this means is that the committer's address, 42.430 +\texttt{john.q.public@example.com}, is not a valid Bugzilla user name, 42.431 +nor does it have an entry in your \rcsection{usermap} that maps it to 42.432 +a valid Bugzilla user name. 42.433 + 42.434 +\subsection{\hgext{notify}---send email notifications} 42.435 + 42.436 +Although Mercurial's built-in web server provides RSS feeds of changes 42.437 +in every repository, many people prefer to receive change 42.438 +notifications via email. The \hgext{notify} hook lets you send out 42.439 +notifications to a set of email addresses whenever changesets arrive 42.440 +that those subscribers are interested in. 42.441 + 42.442 +As with the \hgext{bugzilla} hook, the \hgext{notify} hook is 42.443 +template-driven, so you can customise the contents of the notification 42.444 +messages that it sends. 42.445 + 42.446 +By default, the \hgext{notify} hook includes a diff of every changeset 42.447 +that it sends out; you can limit the size of the diff, or turn this 42.448 +feature off entirely. It is useful for letting subscribers review 42.449 +changes immediately, rather than clicking to follow a URL. 42.450 + 42.451 +\subsubsection{Configuring the \hgext{notify} hook} 42.452 + 42.453 +You can set up the \hgext{notify} hook to send one email message per 42.454 +incoming changeset, or one per incoming group of changesets (all those 42.455 +that arrived in a single pull or push). 42.456 +\begin{codesample2} 42.457 + [hooks] 42.458 + # send one email per group of changes 42.459 + changegroup.notify = python:hgext.notify.hook 42.460 + # send one email per change 42.461 + incoming.notify = python:hgext.notify.hook 42.462 +\end{codesample2} 42.463 + 42.464 +Configuration information for this hook lives in the 42.465 +\rcsection{notify} section of a \hgrc\ file. 42.466 +\begin{itemize} 42.467 +\item[\rcitem{notify}{test}] By default, this hook does not send out 42.468 + email at all; instead, it prints the message that it \emph{would} 42.469 + send. Set this item to \texttt{false} to allow email to be sent. 42.470 + The reason that sending of email is turned off by default is that it 42.471 + takes several tries to configure this extension exactly as you would 42.472 + like, and it would be bad form to spam subscribers with a number of 42.473 + ``broken'' notifications while you debug your configuration. 42.474 +\item[\rcitem{notify}{config}] The path to a configuration file that 42.475 + contains subscription information. This is kept separate from the 42.476 + main \hgrc\ so that you can maintain it in a repository of its own. 42.477 + People can then clone that repository, update their subscriptions, 42.478 + and push the changes back to your server. 42.479 +\item[\rcitem{notify}{strip}] The number of leading path separator 42.480 + characters to strip from a repository's path, when deciding whether 42.481 + a repository has subscribers. For example, if the repositories on 42.482 + your server live in \dirname{/home/hg/repos}, and \hgext{notify} is 42.483 + considering a repository named \dirname{/home/hg/repos/shared/test}, 42.484 + setting \rcitem{notify}{strip} to \texttt{4} will cause 42.485 + \hgext{notify} to trim the path it considers down to 42.486 + \dirname{shared/test}, and it will match subscribers against that. 42.487 +\item[\rcitem{notify}{template}] The template text to use when sending 42.488 + messages. This specifies both the contents of the message header 42.489 + and its body. 42.490 +\item[\rcitem{notify}{maxdiff}] The maximum number of lines of diff 42.491 + data to append to the end of a message. If a diff is longer than 42.492 + this, it is truncated. By default, this is set to 300. Set this to 42.493 + \texttt{0} to omit diffs from notification emails. 42.494 +\item[\rcitem{notify}{sources}] A list of sources of changesets to 42.495 + consider. This lets you limit \hgext{notify} to only sending out 42.496 + email about changes that remote users pushed into this repository 42.497 + via a server, for example. See section~\ref{sec:hook:sources} for 42.498 + the sources you can specify here. 42.499 +\end{itemize} 42.500 + 42.501 +If you set the \rcitem{web}{baseurl} item in the \rcsection{web} 42.502 +section, you can use it in a template; it will be available as 42.503 +\texttt{webroot}. 42.504 + 42.505 +Here is an example set of \hgext{notify} configuration information. 42.506 +\begin{codesample2} 42.507 + [notify] 42.508 + # really send email 42.509 + test = false 42.510 + # subscriber data lives in the notify repo 42.511 + config = /home/hg/repos/notify/notify.conf 42.512 + # repos live in /home/hg/repos on server, so strip 4 "/" chars 42.513 + strip = 4 42.514 + template = X-Hg-Repo: \{webroot\}\\n\\\\ 42.515 + Subject: \{webroot\}: \{desc|firstline|strip\}\\n\\\\ 42.516 + From: \{author\}\\n\\\\ 42.517 + \\n\\\\ 42.518 + changeset \{node|short\} in \{root\}\\n\\\\ 42.519 + details: \{baseurl\}\{webroot\}?cmd=changeset;node=\{node|short\}\\n\\\\ 42.520 + description:\\n\\\\ 42.521 + \\t\{desc|tabindent|strip\} 42.522 + 42.523 + [web] 42.524 + baseurl = http://hg.example.com/ 42.525 +\end{codesample2} 42.526 + 42.527 +This will produce a message that looks like the following: 42.528 +\begin{codesample2} 42.529 + X-Hg-Repo: tests/slave 42.530 + Subject: tests/slave: Handle error case when slave has no buffers 42.531 + Date: Wed, 2 Aug 2006 15:25:46 -0700 (PDT) 42.532 + 42.533 + changeset 3cba9bfe74b5 in /home/hg/repos/tests/slave 42.534 + details: http://hg.example.com/tests/slave?cmd=changeset;node=3cba9bfe74b5 42.535 + description: 42.536 + Handle error case when slave has no buffers 42.537 + diffs (54 lines): 42.538 + 42.539 + diff -r 9d95df7cf2ad -r 3cba9bfe74b5 include/tests.h 42.540 + --- a/include/tests.h Wed Aug 02 15:19:52 2006 -0700 42.541 + +++ b/include/tests.h Wed Aug 02 15:25:26 2006 -0700 42.542 + @@ -212,6 +212,15 @@ static __inline__ void test_headers(void *h) 42.543 + [...snip...] 42.544 +\end{codesample2} 42.545 + 42.546 +\subsubsection{Testing and troubleshooting} 42.547 + 42.548 +Do not forget that by default, the \hgext{notify} extension \emph{will 42.549 + not send any mail} until you explicitly configure it to do so, by 42.550 +setting \rcitem{notify}{test} to \texttt{false}. Until you do that, 42.551 +it simply prints the message it \emph{would} send. 42.552 + 42.553 +\section{Information for writers of hooks} 42.554 \label{sec:hook:ref} 42.555 42.556 \subsection{In-process hook execution} 42.557 @@ -450,26 +975,34 @@ 42.558 \texttt{parent\emph{N}}, it will contain a hexadecimal changeset ID. 42.559 The empty string is used to represent ``null changeset ID'' instead 42.560 of a string of zeroes. 42.561 +\item If a parameter is named \texttt{url}, it will contain the URL of 42.562 + a remote repository, if that can be determined. 42.563 \item Boolean-valued parameters are represented as Python 42.564 \texttt{bool} objects. 42.565 \end{itemize} 42.566 42.567 An in-process hook is called without a change to the process's working 42.568 directory (unlike external hooks, which are run in the root of the 42.569 -repository). It must not change the process's working directory. If 42.570 -it were to do so, it would probably cause calls to the Mercurial API, 42.571 -or operations after the hook finishes, to fail. 42.572 - 42.573 -If a hook returns a boolean ``false'' value, it is considered to 42.574 -have succeeded. If it returns a boolean ``true'' value or raises an 42.575 -exception, it is considered to have failed. 42.576 +repository). It must not change the process's working directory, or 42.577 +it will cause any calls it makes into the Mercurial API to fail. 42.578 + 42.579 +If a hook returns a boolean ``false'' value, it is considered to have 42.580 +succeeded. If it returns a boolean ``true'' value or raises an 42.581 +exception, it is considered to have failed. A useful way to think of 42.582 +the calling convention is ``tell me if you fail''. 42.583 + 42.584 +Note that changeset IDs are passed into Python hooks as hexadecimal 42.585 +strings, not the binary hashes that Mercurial's APIs normally use. To 42.586 +convert a hash from hex to binary, use the 42.587 +\pymodfunc{mercurial.node}{bin} function. 42.588 42.589 \subsection{External hook execution} 42.590 42.591 -An external hook is passed to the user's shell for execution, so 42.592 -features of that shell, such as variable substitution and command 42.593 +An external hook is passed to the shell of the user running Mercurial. 42.594 +Features of that shell, such as variable substitution and command 42.595 redirection, are available. The hook is run in the root directory of 42.596 -the repository. 42.597 +the repository (unlike in-process hooks, which are run in the same 42.598 +directory that Mercurial was run in). 42.599 42.600 Hook parameters are passed to the hook as environment variables. Each 42.601 environment variable's name is converted in upper case and prefixed 42.602 @@ -482,13 +1015,67 @@ 42.603 named \envar{HG\_NODE}, \envar{HG\_PARENT1} or \envar{HG\_PARENT2}, it 42.604 contains a changeset ID represented as a hexadecimal string. The 42.605 empty string is used to represent ``null changeset ID'' instead of a 42.606 -string of zeroes. 42.607 +string of zeroes. If an environment variable is named 42.608 +\envar{HG\_URL}, it will contain the URL of a remote repository, if 42.609 +that can be determined. 42.610 42.611 If a hook exits with a status of zero, it is considered to have 42.612 succeeded. If it exits with a non-zero status, it is considered to 42.613 have failed. 42.614 42.615 -\subsection{The \hook{changegroup} hook} 42.616 +\subsection{Finding out where changesets come from} 42.617 + 42.618 +A hook that involves the transfer of changesets between a local 42.619 +repository and another may be able to find out information about the 42.620 +``far side''. Mercurial knows \emph{how} changes are being 42.621 +transferred, and in many cases \emph{where} they are being transferred 42.622 +to or from. 42.623 + 42.624 +\subsubsection{Sources of changesets} 42.625 +\label{sec:hook:sources} 42.626 + 42.627 +Mercurial will tell a hook what means are, or were, used to transfer 42.628 +changesets between repositories. This is provided by Mercurial in a 42.629 +Python parameter named \texttt{source}, or an environment variable named 42.630 +\envar{HG\_SOURCE}. 42.631 + 42.632 +\begin{itemize} 42.633 +\item[\texttt{serve}] Changesets are transferred to or from a remote 42.634 + repository over http or ssh. 42.635 +\item[\texttt{pull}] Changesets are being transferred via a pull from 42.636 + one repository into another. 42.637 +\item[\texttt{push}] Changesets are being transferred via a push from 42.638 + one repository into another. 42.639 +\item[\texttt{bundle}] Changesets are being transferred to or from a 42.640 + bundle. 42.641 +\end{itemize} 42.642 + 42.643 +\subsubsection{Where changes are going---remote repository URLs} 42.644 +\label{sec:hook:url} 42.645 + 42.646 +When possible, Mercurial will tell a hook the location of the ``far 42.647 +side'' of an activity that transfers changeset data between 42.648 +repositories. This is provided by Mercurial in a Python parameter 42.649 +named \texttt{url}, or an environment variable named \envar{HG\_URL}. 42.650 + 42.651 +This information is not always known. If a hook is invoked in a 42.652 +repository that is being served via http or ssh, Mercurial cannot tell 42.653 +where the remote repository is, but it may know where the client is 42.654 +connecting from. In such cases, the URL will take one of the 42.655 +following forms: 42.656 +\begin{itemize} 42.657 +\item \texttt{remote:ssh:\emph{ip-address}}---remote ssh client, at 42.658 + the given IP address. 42.659 +\item \texttt{remote:http:\emph{ip-address}}---remote http client, at 42.660 + the given IP address. If the client is using SSL, this will be of 42.661 + the form \texttt{remote:https:\emph{ip-address}}. 42.662 +\item Empty---no information could be discovered about the remote 42.663 + client. 42.664 +\end{itemize} 42.665 + 42.666 +\section{Hook reference} 42.667 + 42.668 +\subsection{\hook{changegroup}---after remote changesets added} 42.669 \label{sec:hook:changegroup} 42.670 42.671 This hook is run after a group of pre-existing changesets has been 42.672 @@ -508,13 +1095,17 @@ 42.673 changeset in the group that was added. All changesets between this 42.674 and \index{tags!\texttt{tip}}\texttt{tip}, inclusive, were added by 42.675 a single \hgcmd{pull}, \hgcmd{push} or \hgcmd{unbundle}. 42.676 +\item[\texttt{source}] A string. The source of these changes. See 42.677 + section~\ref{sec:hook:sources} for details. 42.678 +\item[\texttt{url}] A URL. The location of the remote repository, if 42.679 + known. See section~\ref{sec:hook:url} for more information. 42.680 \end{itemize} 42.681 42.682 See also: \hook{incoming} (section~\ref{sec:hook:incoming}), 42.683 \hook{prechangegroup} (section~\ref{sec:hook:prechangegroup}), 42.684 \hook{pretxnchangegroup} (section~\ref{sec:hook:pretxnchangegroup}) 42.685 42.686 -\subsection{The \hook{commit} hook} 42.687 +\subsection{\hook{commit}---after a new changeset is created} 42.688 \label{sec:hook:commit} 42.689 42.690 This hook is run after a new changeset has been created. 42.691 @@ -532,7 +1123,7 @@ 42.692 See also: \hook{precommit} (section~\ref{sec:hook:precommit}), 42.693 \hook{pretxncommit} (section~\ref{sec:hook:pretxncommit}) 42.694 42.695 -\subsection{The \hook{incoming} hook} 42.696 +\subsection{\hook{incoming}---after one remote changeset is added} 42.697 \label{sec:hook:incoming} 42.698 42.699 This hook is run after a pre-existing changeset has been added to the 42.700 @@ -542,18 +1133,22 @@ 42.701 42.702 You can use this hook for the same purposes as the \hook{changegroup} 42.703 hook (section~\ref{sec:hook:changegroup}); it's simply more convenient 42.704 -sometimes to run a hook once per group of changesets, while othher 42.705 +sometimes to run a hook once per group of changesets, while other 42.706 times it's handier once per changeset. 42.707 42.708 Parameters to this hook: 42.709 \begin{itemize} 42.710 \item[\texttt{node}] A changeset ID. The ID of the newly added 42.711 changeset. 42.712 +\item[\texttt{source}] A string. The source of these changes. See 42.713 + section~\ref{sec:hook:sources} for details. 42.714 +\item[\texttt{url}] A URL. The location of the remote repository, if 42.715 + known. See section~\ref{sec:hook:url} for more information. 42.716 \end{itemize} 42.717 42.718 See also: \hook{changegroup} (section~\ref{sec:hook:changegroup}) \hook{prechangegroup} (section~\ref{sec:hook:prechangegroup}), \hook{pretxnchangegroup} (section~\ref{sec:hook:pretxnchangegroup}) 42.719 42.720 -\subsection{The \hook{outgoing} hook} 42.721 +\subsection{\hook{outgoing}---after changesets are propagated} 42.722 \label{sec:hook:outgoing} 42.723 42.724 This hook is run after a group of changesets has been propagated out 42.725 @@ -567,17 +1162,20 @@ 42.726 \begin{itemize} 42.727 \item[\texttt{node}] A changeset ID. The changeset ID of the first 42.728 changeset of the group that was sent. 42.729 -\item[\texttt{source}] A string. The source of the of the operation. 42.730 - If a remote client pulled changes from this repository, 42.731 - \texttt{source} will be \texttt{serve}. If the client that obtained 42.732 - changes from this repository was local, \texttt{source} will be 42.733 - \texttt{bundle}, \texttt{pull}, or \texttt{push}, depending on the 42.734 - operation the client performed. 42.735 +\item[\texttt{source}] A string. The source of the of the operation 42.736 + (see section~\ref{sec:hook:sources}). If a remote client pulled 42.737 + changes from this repository, \texttt{source} will be 42.738 + \texttt{serve}. If the client that obtained changes from this 42.739 + repository was local, \texttt{source} will be \texttt{bundle}, 42.740 + \texttt{pull}, or \texttt{push}, depending on the operation the 42.741 + client performed. 42.742 +\item[\texttt{url}] A URL. The location of the remote repository, if 42.743 + known. See section~\ref{sec:hook:url} for more information. 42.744 \end{itemize} 42.745 42.746 See also: \hook{preoutgoing} (section~\ref{sec:hook:preoutgoing}) 42.747 42.748 -\subsection{The \hook{prechangegroup} hook} 42.749 +\subsection{\hook{prechangegroup}---before starting to add remote changesets} 42.750 \label{sec:hook:prechangegroup} 42.751 42.752 This controlling hook is run before Mercurial begins to add a group of 42.753 @@ -589,16 +1187,24 @@ 42.754 transmitted. 42.755 42.756 One use for this hook is to prevent external changes from being added 42.757 -to a repository, for example to ``freeze'' a server-hosted branch 42.758 -temporarily or permanently. 42.759 - 42.760 -This hook is not passed any parameters. 42.761 +to a repository. For example, you could use this to ``freeze'' a 42.762 +server-hosted branch temporarily or permanently so that users cannot 42.763 +push to it, while still allowing a local administrator to modify the 42.764 +repository. 42.765 + 42.766 +Parameters to this hook: 42.767 +\begin{itemize} 42.768 +\item[\texttt{source}] A string. The source of these changes. See 42.769 + section~\ref{sec:hook:sources} for details. 42.770 +\item[\texttt{url}] A URL. The location of the remote repository, if 42.771 + known. See section~\ref{sec:hook:url} for more information. 42.772 +\end{itemize} 42.773 42.774 See also: \hook{changegroup} (section~\ref{sec:hook:changegroup}), 42.775 \hook{incoming} (section~\ref{sec:hook:incoming}), , 42.776 \hook{pretxnchangegroup} (section~\ref{sec:hook:pretxnchangegroup}) 42.777 42.778 -\subsection{The \hook{precommit} hook} 42.779 +\subsection{\hook{precommit}---before starting to commit a changeset} 42.780 \label{sec:hook:precommit} 42.781 42.782 This hook is run before Mercurial begins to commit a new changeset. 42.783 @@ -624,7 +1230,7 @@ 42.784 See also: \hook{commit} (section~\ref{sec:hook:commit}), 42.785 \hook{pretxncommit} (section~\ref{sec:hook:pretxncommit}) 42.786 42.787 -\subsection{The \hook{preoutgoing} hook} 42.788 +\subsection{\hook{preoutgoing}---before starting to propagate changesets} 42.789 \label{sec:hook:preoutgoing} 42.790 42.791 This hook is invoked before Mercurial knows the identities of the 42.792 @@ -636,15 +1242,18 @@ 42.793 Parameters to this hook: 42.794 \begin{itemize} 42.795 \item[\texttt{source}] A string. The source of the operation that is 42.796 - attempting to obtain changes from this repository. See the 42.797 - documentation for the \texttt{source} parameter to the 42.798 - \hook{outgoing} hook, in section~\ref{sec:hook:outgoing}, for 42.799 - possible values of this parameter.. 42.800 + attempting to obtain changes from this repository (see 42.801 + section~\ref{sec:hook:sources}). See the documentation for the 42.802 + \texttt{source} parameter to the \hook{outgoing} hook, in 42.803 + section~\ref{sec:hook:outgoing}, for possible values of this 42.804 + parameter. 42.805 +\item[\texttt{url}] A URL. The location of the remote repository, if 42.806 + known. See section~\ref{sec:hook:url} for more information. 42.807 \end{itemize} 42.808 42.809 See also: \hook{outgoing} (section~\ref{sec:hook:outgoing}) 42.810 42.811 -\subsection{The \hook{pretag} hook} 42.812 +\subsection{\hook{pretag}---before tagging a changeset} 42.813 \label{sec:hook:pretag} 42.814 42.815 This controlling hook is run before a tag is created. If the hook 42.816 @@ -666,7 +1275,8 @@ 42.817 42.818 See also: \hook{tag} (section~\ref{sec:hook:tag}) 42.819 42.820 -\subsection{The \hook{pretxnchangegroup} hook} 42.821 +\subsection{\hook{pretxnchangegroup}---before completing addition of 42.822 + remote changesets} 42.823 \label{sec:hook:pretxnchangegroup} 42.824 42.825 This controlling hook is run before a transaction---that manages the 42.826 @@ -689,14 +1299,23 @@ 42.827 the hook fails, all of the changesets are ``rejected'' when the 42.828 transaction rolls back. 42.829 42.830 -Parameters to this hook are the same as for the \hook{changegroup} 42.831 -hook; see section~\ref{sec:hook:changegroup} for details. 42.832 +Parameters to this hook: 42.833 +\begin{itemize} 42.834 +\item[\texttt{node}] A changeset ID. The changeset ID of the first 42.835 + changeset in the group that was added. All changesets between this 42.836 + and \index{tags!\texttt{tip}}\texttt{tip}, inclusive, were added by 42.837 + a single \hgcmd{pull}, \hgcmd{push} or \hgcmd{unbundle}. 42.838 +\item[\texttt{source}] A string. The source of these changes. See 42.839 + section~\ref{sec:hook:sources} for details. 42.840 +\item[\texttt{url}] A URL. The location of the remote repository, if 42.841 + known. See section~\ref{sec:hook:url} for more information. 42.842 +\end{itemize} 42.843 42.844 See also: \hook{changegroup} (section~\ref{sec:hook:changegroup}), 42.845 \hook{incoming} (section~\ref{sec:hook:incoming}), 42.846 \hook{prechangegroup} (section~\ref{sec:hook:prechangegroup}) 42.847 42.848 -\subsection{The \hook{pretxncommit} hook} 42.849 +\subsection{\hook{pretxncommit}---before completing commit of new changeset} 42.850 \label{sec:hook:pretxncommit} 42.851 42.852 This controlling hook is run before a transaction---that manages a new 42.853 @@ -714,12 +1333,19 @@ 42.854 is permanent. This may lead to race conditions if you do not take 42.855 steps to avoid them. 42.856 42.857 -Parameters to this hook are the same as for the \hook{commit} hook; 42.858 -see section~\ref{sec:hook:commit} for details. 42.859 +Parameters to this hook: 42.860 +\begin{itemize} 42.861 +\item[\texttt{node}] A changeset ID. The changeset ID of the newly 42.862 + committed changeset. 42.863 +\item[\texttt{parent1}] A changeset ID. The changeset ID of the first 42.864 + parent of the newly committed changeset. 42.865 +\item[\texttt{parent2}] A changeset ID. The changeset ID of the second 42.866 + parent of the newly committed changeset. 42.867 +\end{itemize} 42.868 42.869 See also: \hook{precommit} (section~\ref{sec:hook:precommit}) 42.870 42.871 -\subsection{The \hook{preupdate} hook} 42.872 +\subsection{\hook{preupdate}---before updating or merging working directory} 42.873 \label{sec:hook:preupdate} 42.874 42.875 This controlling hook is run before an update or merge of the working 42.876 @@ -740,20 +1366,27 @@ 42.877 42.878 See also: \hook{update} (section~\ref{sec:hook:update}) 42.879 42.880 -\subsection{The \hook{tag} hook} 42.881 +\subsection{\hook{tag}---after tagging a changeset} 42.882 \label{sec:hook:tag} 42.883 42.884 This hook is run after a tag has been created. 42.885 42.886 -Parameters to this hook are the same as for the \hook{pretag} hook; 42.887 -see section~\ref{sec:hook:pretag} for details. 42.888 +Parameters to this hook: 42.889 +\begin{itemize} 42.890 +\item[\texttt{local}] A boolean. Whether the new tag is local to this 42.891 + repository instance (i.e.~stored in \sfilename{.hg/tags}) or managed 42.892 + by Mercurial (stored in \sfilename{.hgtags}). 42.893 +\item[\texttt{node}] A changeset ID. The ID of the changeset that was 42.894 + tagged. 42.895 +\item[\texttt{tag}] A string. The name of the tag that was created. 42.896 +\end{itemize} 42.897 42.898 If the created tag is revision-controlled, the \hook{commit} hook 42.899 (section~\ref{sec:hook:commit}) is run before this hook. 42.900 42.901 See also: \hook{pretag} (section~\ref{sec:hook:pretag}) 42.902 42.903 -\subsection{The \hook{update} hook} 42.904 +\subsection{\hook{update}---after updating or merging working directory} 42.905 \label{sec:hook:update} 42.906 42.907 This hook is run after an update or merge of the working directory
43.1 Binary file en/kdiff3.png has changed
44.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 44.2 +++ b/en/metadata.svg Mon Mar 05 20:16:36 2007 -0800 44.3 @@ -0,0 +1,328 @@ 44.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?> 44.5 +<!-- Created with Inkscape (http://www.inkscape.org/) --> 44.6 +<svg 44.7 + xmlns:dc="http://purl.org/dc/elements/1.1/" 44.8 + xmlns:cc="http://web.resource.org/cc/" 44.9 + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 44.10 + xmlns:svg="http://www.w3.org/2000/svg" 44.11 + xmlns="http://www.w3.org/2000/svg" 44.12 + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" 44.13 + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" 44.14 + width="744.09448819" 44.15 + height="1052.3622047" 44.16 + id="svg2" 44.17 + sodipodi:version="0.32" 44.18 + inkscape:version="0.44.1" 44.19 + sodipodi:docname="metadata.svg" 44.20 + sodipodi:docbase="/home/bos/hg/hgbook/en"> 44.21 + <defs 44.22 + id="defs4"> 44.23 + <marker 44.24 + inkscape:stockid="Arrow1Mend" 44.25 + orient="auto" 44.26 + refY="0.0" 44.27 + refX="0.0" 44.28 + id="Arrow1Mend" 44.29 + style="overflow:visible;"> 44.30 + <path 44.31 + id="path2944" 44.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 " 44.33 + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;" 44.34 + transform="scale(0.4) rotate(180) translate(10,0)" /> 44.35 + </marker> 44.36 + </defs> 44.37 + <sodipodi:namedview 44.38 + id="base" 44.39 + pagecolor="#ffffff" 44.40 + bordercolor="#666666" 44.41 + borderopacity="1.0" 44.42 + gridtolerance="10000" 44.43 + guidetolerance="10" 44.44 + objecttolerance="10" 44.45 + inkscape:pageopacity="0.0" 44.46 + inkscape:pageshadow="2" 44.47 + inkscape:zoom="1.4" 44.48 + inkscape:cx="232.14286" 44.49 + inkscape:cy="490.68696" 44.50 + inkscape:document-units="px" 44.51 + inkscape:current-layer="layer1" 44.52 + inkscape:window-width="906" 44.53 + inkscape:window-height="620" 44.54 + inkscape:window-x="181" 44.55 + inkscape:window-y="58" /> 44.56 + <metadata 44.57 + id="metadata7"> 44.58 + <rdf:RDF> 44.59 + <cc:Work 44.60 + rdf:about=""> 44.61 + <dc:format>image/svg+xml</dc:format> 44.62 + <dc:type 44.63 + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 44.64 + </cc:Work> 44.65 + </rdf:RDF> 44.66 + </metadata> 44.67 + <g 44.68 + inkscape:label="Layer 1" 44.69 + inkscape:groupmode="layer" 44.70 + id="layer1"> 44.71 + <path 44.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" 44.73 + d="M 326.94646,467.18359 L 326.94646,510.98123" 44.74 + id="path1910" 44.75 + inkscape:connector-type="polyline" 44.76 + inkscape:connection-end="#rect2962" 44.77 + inkscape:connection-start="#rect2764" /> 44.78 + <path 44.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" 44.80 + d="M 326.94646,531.98123 L 326.94646,591.77887" 44.81 + id="path1912" 44.82 + inkscape:connector-type="polyline" 44.83 + inkscape:connection-start="#rect2962" 44.84 + inkscape:connection-end="#rect3000" /> 44.85 + <path 44.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" 44.87 + d="M 316.1622,531.98123 L 192.30212,652.57648" 44.88 + id="path1916" 44.89 + inkscape:connector-type="polyline" 44.90 + inkscape:connection-end="#rect3038" 44.91 + inkscape:connection-start="#rect2962" /> 44.92 + <path 44.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" 44.94 + d="M 254.23217,467.18359 L 254.23216,510.98123" 44.95 + id="path3088" 44.96 + inkscape:connector-type="polyline" 44.97 + inkscape:connection-start="#rect1872" 44.98 + inkscape:connection-end="#rect2960" /> 44.99 + <path 44.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" 44.101 + d="M 254.23215,531.98123 L 254.23215,591.77887" 44.102 + id="path3090" 44.103 + inkscape:connector-type="polyline" 44.104 + inkscape:connection-start="#rect2960" 44.105 + inkscape:connection-end="#rect2998" /> 44.106 + <path 44.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" 44.108 + d="M 248.84002,531.98123 L 186.90999,652.57648" 44.109 + id="path3092" 44.110 + inkscape:connector-type="polyline" 44.111 + inkscape:connection-start="#rect2960" 44.112 + inkscape:connection-end="#rect3038" /> 44.113 + <rect 44.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" 44.115 + id="rect1872" 44.116 + width="51.42857" 44.117 + height="20" 44.118 + x="228.51788" 44.119 + y="446.68359" /> 44.120 + <rect 44.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" 44.122 + id="rect2764" 44.123 + width="51.42857" 44.124 + height="20" 44.125 + x="301.23218" 44.126 + y="446.68359" /> 44.127 + <rect 44.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" 44.129 + id="rect2766" 44.130 + width="51.42857" 44.131 + height="20" 44.132 + x="155.80359" 44.133 + y="446.68359" /> 44.134 + <rect 44.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" 44.136 + id="rect2768" 44.137 + width="51.42857" 44.138 + height="20" 44.139 + x="83.089294" 44.140 + y="446.68359" /> 44.141 + <path 44.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" 44.143 + d="M 135.01786,456.68359 L 155.30359,456.68359" 44.144 + id="path2770" 44.145 + inkscape:connector-type="polyline" 44.146 + inkscape:connection-start="#rect2768" 44.147 + inkscape:connection-end="#rect2766" /> 44.148 + <path 44.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" 44.150 + d="M 207.73216,456.68359 L 228.01788,456.68359" 44.151 + id="path2772" 44.152 + inkscape:connector-type="polyline" 44.153 + inkscape:connection-start="#rect2766" 44.154 + inkscape:connection-end="#rect1872" /> 44.155 + <path 44.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" 44.157 + d="M 280.44645,456.68359 L 300.73218,456.68359" 44.158 + id="path2774" 44.159 + inkscape:connector-type="polyline" 44.160 + inkscape:connection-start="#rect1872" 44.161 + inkscape:connection-end="#rect2764" /> 44.162 + <path 44.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" 44.164 + d="M 62.303571,456.68359 L 82.589294,456.68359" 44.165 + id="path2778" 44.166 + inkscape:connector-type="polyline" 44.167 + inkscape:connection-end="#rect2768" /> 44.168 + <rect 44.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" 44.170 + id="rect2960" 44.171 + width="51.42857" 44.172 + height="20" 44.173 + x="228.51787" 44.174 + y="511.48123" /> 44.175 + <rect 44.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" 44.177 + id="rect2962" 44.178 + width="51.42857" 44.179 + height="20" 44.180 + x="301.23218" 44.181 + y="511.48123" /> 44.182 + <rect 44.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" 44.184 + id="rect2964" 44.185 + width="51.42857" 44.186 + height="20" 44.187 + x="155.80357" 44.188 + y="511.48123" /> 44.189 + <rect 44.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" 44.191 + id="rect2966" 44.192 + width="51.42857" 44.193 + height="20" 44.194 + x="83.089287" 44.195 + y="511.48123" /> 44.196 + <path 44.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" 44.198 + d="M 135.01786,521.48121 L 155.30359,521.48121" 44.199 + id="path2968" 44.200 + inkscape:connector-type="polyline" /> 44.201 + <path 44.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" 44.203 + d="M 207.73216,521.48121 L 228.01788,521.48121" 44.204 + id="path2970" 44.205 + inkscape:connector-type="polyline" /> 44.206 + <path 44.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" 44.208 + d="M 280.44645,521.48121 L 300.73218,521.48121" 44.209 + id="path2972" 44.210 + inkscape:connector-type="polyline" /> 44.211 + <path 44.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" 44.213 + d="M 62.30358,521.48121 L 82.5893,521.48121" 44.214 + id="path2974" 44.215 + inkscape:connector-type="polyline" /> 44.216 + <rect 44.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" 44.218 + id="rect2998" 44.219 + width="51.42857" 44.220 + height="20" 44.221 + x="228.51787" 44.222 + y="592.27887" /> 44.223 + <rect 44.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" 44.225 + id="rect3000" 44.226 + width="51.42857" 44.227 + height="20" 44.228 + x="301.23218" 44.229 + y="592.27887" /> 44.230 + <rect 44.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" 44.232 + id="rect3002" 44.233 + width="51.42857" 44.234 + height="20" 44.235 + x="155.80357" 44.236 + y="592.27887" /> 44.237 + <rect 44.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" 44.239 + id="rect3004" 44.240 + width="51.42857" 44.241 + height="20" 44.242 + x="83.089287" 44.243 + y="592.27887" /> 44.244 + <path 44.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" 44.246 + d="M 135.01786,602.27884 L 155.30359,602.27884" 44.247 + id="path3006" 44.248 + inkscape:connector-type="polyline" /> 44.249 + <path 44.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" 44.251 + d="M 207.73216,602.27884 L 228.01788,602.27884" 44.252 + id="path3008" 44.253 + inkscape:connector-type="polyline" /> 44.254 + <path 44.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" 44.256 + d="M 280.44645,602.27884 L 300.73218,602.27884" 44.257 + id="path3010" 44.258 + inkscape:connector-type="polyline" /> 44.259 + <path 44.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" 44.261 + d="M 62.30358,602.27884 L 82.5893,602.27884" 44.262 + id="path3012" 44.263 + inkscape:connector-type="polyline" /> 44.264 + <rect 44.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" 44.266 + id="rect3034" 44.267 + width="51.42857" 44.268 + height="20" 44.269 + x="228.51787" 44.270 + y="653.07648" /> 44.271 + <rect 44.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" 44.273 + id="rect3038" 44.274 + width="51.42857" 44.275 + height="20" 44.276 + x="155.80357" 44.277 + y="653.07648" /> 44.278 + <rect 44.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" 44.280 + id="rect3040" 44.281 + width="51.42857" 44.282 + height="20" 44.283 + x="83.089287" 44.284 + y="653.07648" /> 44.285 + <path 44.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" 44.287 + d="M 135.01786,663.07646 L 155.30359,663.07646" 44.288 + id="path3042" 44.289 + inkscape:connector-type="polyline" /> 44.290 + <path 44.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" 44.292 + d="M 207.73216,663.07646 L 228.01788,663.07646" 44.293 + id="path3044" 44.294 + inkscape:connector-type="polyline" /> 44.295 + <path 44.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" 44.297 + d="M 62.30358,663.07646 L 82.5893,663.07646" 44.298 + id="path3048" 44.299 + inkscape:connector-type="polyline" /> 44.300 + <text 44.301 + xml:space="preserve" 44.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" 44.303 + x="82.072548" 44.304 + y="432.64789" 44.305 + id="text3094"><tspan 44.306 + sodipodi:role="line" 44.307 + id="tspan3096" 44.308 + x="82.072548" 44.309 + y="432.64789">Changelog</tspan></text> 44.310 + <text 44.311 + xml:space="preserve" 44.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" 44.313 + x="82.306923" 44.314 + y="498.97327" 44.315 + id="text3098"><tspan 44.316 + sodipodi:role="line" 44.317 + id="tspan3100" 44.318 + x="82.306923" 44.319 + y="498.97327">Manifest</tspan></text> 44.320 + <text 44.321 + xml:space="preserve" 44.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" 44.323 + x="82.14286" 44.324 + y="580.08569" 44.325 + id="text3102"><tspan 44.326 + sodipodi:role="line" 44.327 + id="tspan3104" 44.328 + x="82.14286" 44.329 + y="580.08569">Filelogs</tspan></text> 44.330 + </g> 44.331 +</svg>
45.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 45.2 +++ b/en/mq-collab.tex Mon Mar 05 20:16:36 2007 -0800 45.3 @@ -0,0 +1,388 @@ 45.4 +\chapter{Advanced uses of Mercurial Queues} 45.5 + 45.6 +While it's easy to pick up straightforward uses of Mercurial Queues, 45.7 +use of a little discipline and some of MQ's less frequently used 45.8 +capabilities makes it possible to work in complicated development 45.9 +environments. 45.10 + 45.11 +In this chapter, I will use as an example a technique I have used to 45.12 +manage the development of an Infiniband device driver for the Linux 45.13 +kernel. The driver in question is large (at least as drivers go), 45.14 +with 25,000 lines of code spread across 35 source files. It is 45.15 +maintained by a small team of developers. 45.16 + 45.17 +While much of the material in this chapter is specific to Linux, the 45.18 +same principles apply to any code base for which you're not the 45.19 +primary owner, and upon which you need to do a lot of development. 45.20 + 45.21 +\section{The problem of many targets} 45.22 + 45.23 +The Linux kernel changes rapidly, and has never been internally 45.24 +stable; developers frequently make drastic changes between releases. 45.25 +This means that a version of the driver that works well with a 45.26 +particular released version of the kernel will not even \emph{compile} 45.27 +correctly against, typically, any other version. 45.28 + 45.29 +To maintain a driver, we have to keep a number of distinct versions of 45.30 +Linux in mind. 45.31 +\begin{itemize} 45.32 +\item One target is the main Linux kernel development tree. 45.33 + Maintenance of the code is in this case partly shared by other 45.34 + developers in the kernel community, who make ``drive-by'' 45.35 + modifications to the driver as they develop and refine kernel 45.36 + subsystems. 45.37 +\item We also maintain a number of ``backports'' to older versions of 45.38 + the Linux kernel, to support the needs of customers who are running 45.39 + older Linux distributions that do not incorporate our drivers. (To 45.40 + \emph{backport} a piece of code is to modify it to work in an older 45.41 + version of its target environment than the version it was developed 45.42 + for.) 45.43 +\item Finally, we make software releases on a schedule that is 45.44 + necessarily not aligned with those used by Linux distributors and 45.45 + kernel developers, so that we can deliver new features to customers 45.46 + without forcing them to upgrade their entire kernels or 45.47 + distributions. 45.48 +\end{itemize} 45.49 + 45.50 +\subsection{Tempting approaches that don't work well} 45.51 + 45.52 +There are two ``standard'' ways to maintain a piece of software that 45.53 +has to target many different environments. 45.54 + 45.55 +The first is to maintain a number of branches, each intended for a 45.56 +single target. The trouble with this approach is that you must 45.57 +maintain iron discipline in the flow of changes between repositories. 45.58 +A new feature or bug fix must start life in a ``pristine'' repository, 45.59 +then percolate out to every backport repository. Backport changes are 45.60 +more limited in the branches they should propagate to; a backport 45.61 +change that is applied to a branch where it doesn't belong will 45.62 +probably stop the driver from compiling. 45.63 + 45.64 +The second is to maintain a single source tree filled with conditional 45.65 +statements that turn chunks of code on or off depending on the 45.66 +intended target. Because these ``ifdefs'' are not allowed in the 45.67 +Linux kernel tree, a manual or automatic process must be followed to 45.68 +strip them out and yield a clean tree. A code base maintained in this 45.69 +fashion rapidly becomes a rat's nest of conditional blocks that are 45.70 +difficult to understand and maintain. 45.71 + 45.72 +Neither of these approaches is well suited to a situation where you 45.73 +don't ``own'' the canonical copy of a source tree. In the case of a 45.74 +Linux driver that is distributed with the standard kernel, Linus's 45.75 +tree contains the copy of the code that will be treated by the world 45.76 +as canonical. The upstream version of ``my'' driver can be modified 45.77 +by people I don't know, without me even finding out about it until 45.78 +after the changes show up in Linus's tree. 45.79 + 45.80 +These approaches have the added weakness of making it difficult to 45.81 +generate well-formed patches to submit upstream. 45.82 + 45.83 +In principle, Mercurial Queues seems like a good candidate to manage a 45.84 +development scenario such as the above. While this is indeed the 45.85 +case, MQ contains a few added features that make the job more 45.86 +pleasant. 45.87 + 45.88 +\section{Conditionally applying patches with 45.89 + guards} 45.90 + 45.91 +Perhaps the best way to maintain sanity with so many targets is to be 45.92 +able to choose specific patches to apply for a given situation. MQ 45.93 +provides a feature called ``guards'' (which originates with quilt's 45.94 +\texttt{guards} command) that does just this. To start off, let's 45.95 +create a simple repository for experimenting in. 45.96 +\interaction{mq.guards.init} 45.97 +This gives us a tiny repository that contains two patches that don't 45.98 +have any dependencies on each other, because they touch different files. 45.99 + 45.100 +The idea behind conditional application is that you can ``tag'' a 45.101 +patch with a \emph{guard}, which is simply a text string of your 45.102 +choosing, then tell MQ to select specific guards to use when applying 45.103 +patches. MQ will then either apply, or skip over, a guarded patch, 45.104 +depending on the guards that you have selected. 45.105 + 45.106 +A patch can have an arbitrary number of guards; 45.107 +each one is \emph{positive} (``apply this patch if this guard is 45.108 +selected'') or \emph{negative} (``skip this patch if this guard is 45.109 +selected''). A patch with no guards is always applied. 45.110 + 45.111 +\section{Controlling the guards on a patch} 45.112 + 45.113 +The \hgcmd{qguard} command lets you determine which guards should 45.114 +apply to a patch, or display the guards that are already in effect. 45.115 +Without any arguments, it displays the guards on the current topmost 45.116 +patch. 45.117 +\interaction{mq.guards.qguard} 45.118 +To set a positive guard on a patch, prefix the name of the guard with 45.119 +a ``\texttt{+}''. 45.120 +\interaction{mq.guards.qguard.pos} 45.121 +To set a negative guard on a patch, prefix the name of the guard with 45.122 +a ``\texttt{-}''. 45.123 +\interaction{mq.guards.qguard.neg} 45.124 + 45.125 +\begin{note} 45.126 + The \hgcmd{qguard} command \emph{sets} the guards on a patch; it 45.127 + doesn't \emph{modify} them. What this means is that if you run 45.128 + \hgcmdargs{qguard}{+a +b} on a patch, then \hgcmdargs{qguard}{+c} on 45.129 + the same patch, the \emph{only} guard that will be set on it 45.130 + afterwards is \texttt{+c}. 45.131 +\end{note} 45.132 + 45.133 +Mercurial stores guards in the \sfilename{series} file; the form in 45.134 +which they are stored is easy both to understand and to edit by hand. 45.135 +(In other words, you don't have to use the \hgcmd{qguard} command if 45.136 +you don't want to; it's okay to simply edit the \sfilename{series} 45.137 +file.) 45.138 +\interaction{mq.guards.series} 45.139 + 45.140 +\section{Selecting the guards to use} 45.141 + 45.142 +The \hgcmd{qselect} command determines which guards are active at a 45.143 +given time. The effect of this is to determine which patches MQ will 45.144 +apply the next time you run \hgcmd{qpush}. It has no other effect; in 45.145 +particular, it doesn't do anything to patches that are already 45.146 +applied. 45.147 + 45.148 +With no arguments, the \hgcmd{qselect} command lists the guards 45.149 +currently in effect, one per line of output. Each argument is treated 45.150 +as the name of a guard to apply. 45.151 +\interaction{mq.guards.qselect.foo} 45.152 +In case you're interested, the currently selected guards are stored in 45.153 +the \sfilename{guards} file. 45.154 +\interaction{mq.guards.qselect.cat} 45.155 +We can see the effect the selected guards have when we run 45.156 +\hgcmd{qpush}. 45.157 +\interaction{mq.guards.qselect.qpush} 45.158 + 45.159 +A guard cannot start with a ``\texttt{+}'' or ``\texttt{-}'' 45.160 +character. The name of a guard must not contain white space, but most 45.161 +othter characters are acceptable. If you try to use a guard with an 45.162 +invalid name, MQ will complain: 45.163 +\interaction{mq.guards.qselect.error} 45.164 +Changing the selected guards changes the patches that are applied. 45.165 +\interaction{mq.guards.qselect.quux} 45.166 +You can see in the example below that negative guards take precedence 45.167 +over positive guards. 45.168 +\interaction{mq.guards.qselect.foobar} 45.169 + 45.170 +\section{MQ's rules for applying patches} 45.171 + 45.172 +The rules that MQ uses when deciding whether to apply a patch 45.173 +are as follows. 45.174 +\begin{itemize} 45.175 +\item A patch that has no guards is always applied. 45.176 +\item If the patch has any negative guard that matches any currently 45.177 + selected guard, the patch is skipped. 45.178 +\item If the patch has any positive guard that matches any currently 45.179 + selected guard, the patch is applied. 45.180 +\item If the patch has positive or negative guards, but none matches 45.181 + any currently selected guard, the patch is skipped. 45.182 +\end{itemize} 45.183 + 45.184 +\section{Trimming the work environment} 45.185 + 45.186 +In working on the device driver I mentioned earlier, I don't apply the 45.187 +patches to a normal Linux kernel tree. Instead, I use a repository 45.188 +that contains only a snapshot of the source files and headers that are 45.189 +relevant to Infiniband development. This repository is~1\% the size 45.190 +of a kernel repository, so it's easier to work with. 45.191 + 45.192 +I then choose a ``base'' version on top of which the patches are 45.193 +applied. This is a snapshot of the Linux kernel tree as of a revision 45.194 +of my choosing. When I take the snapshot, I record the changeset ID 45.195 +from the kernel repository in the commit message. Since the snapshot 45.196 +preserves the ``shape'' and content of the relevant parts of the 45.197 +kernel tree, I can apply my patches on top of either my tiny 45.198 +repository or a normal kernel tree. 45.199 + 45.200 +Normally, the base tree atop which the patches apply should be a 45.201 +snapshot of a very recent upstream tree. This best facilitates the 45.202 +development of patches that can easily be submitted upstream with few 45.203 +or no modifications. 45.204 + 45.205 +\section{Dividing up the \sfilename{series} file} 45.206 + 45.207 +I categorise the patches in the \sfilename{series} file into a number 45.208 +of logical groups. Each section of like patches begins with a block 45.209 +of comments that describes the purpose of the patches that follow. 45.210 + 45.211 +The sequence of patch groups that I maintain follows. The ordering of 45.212 +these groups is important; I'll describe why after I introduce the 45.213 +groups. 45.214 +\begin{itemize} 45.215 +\item The ``accepted'' group. Patches that the development team has 45.216 + submitted to the maintainer of the Infiniband subsystem, and which 45.217 + he has accepted, but which are not present in the snapshot that the 45.218 + tiny repository is based on. These are ``read only'' patches, 45.219 + present only to transform the tree into a similar state as it is in 45.220 + the upstream maintainer's repository. 45.221 +\item The ``rework'' group. Patches that I have submitted, but that 45.222 + the upstream maintainer has requested modifications to before he 45.223 + will accept them. 45.224 +\item The ``pending'' group. Patches that I have not yet submitted to 45.225 + the upstream maintainer, but which we have finished working on. 45.226 + These will be ``read only'' for a while. If the upstream maintainer 45.227 + accepts them upon submission, I'll move them to the end of the 45.228 + ``accepted'' group. If he requests that I modify any, I'll move 45.229 + them to the beginning of the ``rework'' group. 45.230 +\item The ``in progress'' group. Patches that are actively being 45.231 + developed, and should not be submitted anywhere yet. 45.232 +\item The ``backport'' group. Patches that adapt the source tree to 45.233 + older versions of the kernel tree. 45.234 +\item The ``do not ship'' group. Patches that for some reason should 45.235 + never be submitted upstream. For example, one such patch might 45.236 + change embedded driver identification strings to make it easier to 45.237 + distinguish, in the field, between an out-of-tree version of the 45.238 + driver and a version shipped by a distribution vendor. 45.239 +\end{itemize} 45.240 + 45.241 +Now to return to the reasons for ordering groups of patches in this 45.242 +way. We would like the lowest patches in the stack to be as stable as 45.243 +possible, so that we will not need to rework higher patches due to 45.244 +changes in context. Putting patches that will never be changed first 45.245 +in the \sfilename{series} file serves this purpose. 45.246 + 45.247 +We would also like the patches that we know we'll need to modify to be 45.248 +applied on top of a source tree that resembles the upstream tree as 45.249 +closely as possible. This is why we keep accepted patches around for 45.250 +a while. 45.251 + 45.252 +The ``backport'' and ``do not ship'' patches float at the end of the 45.253 +\sfilename{series} file. The backport patches must be applied on top 45.254 +of all other patches, and the ``do not ship'' patches might as well 45.255 +stay out of harm's way. 45.256 + 45.257 +\section{Maintaining the patch series} 45.258 + 45.259 +In my work, I use a number of guards to control which patches are to 45.260 +be applied. 45.261 + 45.262 +\begin{itemize} 45.263 +\item ``Accepted'' patches are guarded with \texttt{accepted}. I 45.264 + enable this guard most of the time. When I'm applying the patches 45.265 + on top of a tree where the patches are already present, I can turn 45.266 + this patch off, and the paptches that follow it will apply cleanly. 45.267 +\item Patches that are ``finished'', but not yet submitted, have no 45.268 + guards. If I'm applying the patch stack to a copy of the upstream 45.269 + tree, I don't need to enable any guards in order to get a reasonably 45.270 + safe source tree. 45.271 +\item Those patches that need reworking before being resubmitted are 45.272 + guarded with \texttt{rework}. 45.273 +\item For those patches that are still under development, I use 45.274 + \texttt{devel}. 45.275 +\item A backport patch may have several guards, one for each version 45.276 + of the kernel to which it applies. For example, a patch that 45.277 + backports a piece of code to~2.6.9 will have a~\texttt{2.6.9} guard. 45.278 +\end{itemize} 45.279 +This variety of guards gives me considerable flexibility in 45.280 +qdetermining what kind of source tree I want to end up with. For most 45.281 +situations, the selection of appropriate guards is automated during 45.282 +the build process, but I can manually tune the guards to use for less 45.283 +common circumstances. 45.284 + 45.285 +\subsection{The art of writing backport patches} 45.286 + 45.287 +Using MQ, writing a backport patch is a simple process. All such a 45.288 +patch has to do is modify a piece of code that uses a kernel feature 45.289 +not present in the older version of the kernel, so that the driver 45.290 +continues to work correctly under that older version. 45.291 + 45.292 +A useful goal when writing a good backport patch is to make your code 45.293 +look as if it was written for the older version of the kernel you're 45.294 +targeting. The less obtrusive the patch, the easier it will be to 45.295 +understand and maintain. If you're writing a collection of backport 45.296 +patches to avoid the ``rat's nest'' effect of lots of 45.297 +\texttt{\#ifdef}s (hunks of source code that are only used 45.298 +conditionally) in your code, don't introduce version-dependent 45.299 +\texttt{\#ifdef}s into the patches. Instead, write several patches, 45.300 +each of which makes unconditional changes, and control their 45.301 +application using guards. 45.302 + 45.303 +There are two reasons to divide backport patches into a distinct 45.304 +group, away from the ``regular'' patches whose effects they modify. 45.305 +The first is that intermingling the two makes it more difficult to use 45.306 +a tool like the \hgext{patchbomb} extension to automate the process of 45.307 +submitting the patches to an upstream maintainer. The second is that 45.308 +a backport patch could perturb the context in which a subsequent 45.309 +regular patch is applied, making it impossible to apply the regular 45.310 +patch cleanly \emph{without} the earlier backport patch already being 45.311 +applied. 45.312 + 45.313 +\section{Useful tips for developing with MQ} 45.314 + 45.315 +\subsection{Organising patches in directories} 45.316 + 45.317 +If you're working on a substantial project with MQ, it's not difficult 45.318 +to accumulate a large number of patches. For example, I have one 45.319 +patch repository that contains over 250 patches. 45.320 + 45.321 +If you can group these patches into separate logical categories, you 45.322 +can if you like store them in different directories; MQ has no 45.323 +problems with patch names that contain path separators. 45.324 + 45.325 +\subsection{Viewing the history of a patch} 45.326 +\label{mq-collab:tips:interdiff} 45.327 + 45.328 +If you're developing a set of patches over a long time, it's a good 45.329 +idea to maintain them in a repository, as discussed in 45.330 +section~\ref{sec:mq:repo}. If you do so, you'll quickly discover that 45.331 +using the \hgcmd{diff} command to look at the history of changes to a 45.332 +patch is unworkable. This is in part because you're looking at the 45.333 +second derivative of the real code (a diff of a diff), but also 45.334 +because MQ adds noise to the process by modifying time stamps and 45.335 +directory names when it updates a patch. 45.336 + 45.337 +However, you can use the \hgext{extdiff} extension, which is bundled 45.338 +with Mercurial, to turn a diff of two versions of a patch into 45.339 +something readable. To do this, you will need a third-party package 45.340 +called \package{patchutils}~\cite{web:patchutils}. This provides a 45.341 +command named \command{interdiff}, which shows the differences between 45.342 +two diffs as a diff. Used on two versions of the same diff, it 45.343 +generates a diff that represents the diff from the first to the second 45.344 +version. 45.345 + 45.346 +You can enable the \hgext{extdiff} extension in the usual way, by 45.347 +adding a line to the \rcsection{extensions} section of your \hgrc. 45.348 +\begin{codesample2} 45.349 + [extensions] 45.350 + extdiff = 45.351 +\end{codesample2} 45.352 +The \command{interdiff} command expects to be passed the names of two 45.353 +files, but the \hgext{extdiff} extension passes the program it runs a 45.354 +pair of directories, each of which can contain an arbitrary number of 45.355 +files. We thus need a small program that will run \command{interdiff} 45.356 +on each pair of files in these two directories. This program is 45.357 +available as \sfilename{hg-interdiff} in the \dirname{examples} 45.358 +directory of the source code repository that accompanies this book. 45.359 +\excode{hg-interdiff} 45.360 + 45.361 +With the \sfilename{hg-interdiff} program in your shell's search path, 45.362 +you can run it as follows, from inside an MQ patch directory: 45.363 +\begin{codesample2} 45.364 + hg extdiff -p hg-interdiff -r A:B my-change.patch 45.365 +\end{codesample2} 45.366 +Since you'll probably want to use this long-winded command a lot, you 45.367 +can get \hgext{hgext} to make it available as a normal Mercurial 45.368 +command, again by editing your \hgrc. 45.369 +\begin{codesample2} 45.370 + [extdiff] 45.371 + cmd.interdiff = hg-interdiff 45.372 +\end{codesample2} 45.373 +This directs \hgext{hgext} to make an \texttt{interdiff} command 45.374 +available, so you can now shorten the previous invocation of 45.375 +\hgcmd{extdiff} to something a little more wieldy. 45.376 +\begin{codesample2} 45.377 + hg interdiff -r A:B my-change.patch 45.378 +\end{codesample2} 45.379 + 45.380 +\begin{note} 45.381 + The \command{interdiff} command works well only if the underlying 45.382 + files against which versions of a patch are generated remain the 45.383 + same. If you create a patch, modify the underlying files, and then 45.384 + regenerate the patch, \command{interdiff} may not produce useful 45.385 + output. 45.386 +\end{note} 45.387 + 45.388 +%%% Local Variables: 45.389 +%%% mode: latex 45.390 +%%% TeX-master: "00book" 45.391 +%%% End:
46.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 46.2 +++ b/en/mq-ref.tex Mon Mar 05 20:16:36 2007 -0800 46.3 @@ -0,0 +1,352 @@ 46.4 +\chapter{Mercurial Queues reference} 46.5 + 46.6 +\section{MQ command reference} 46.7 +\label{sec:mq:cmdref} 46.8 + 46.9 +For an overview of the commands provided by MQ, use the command 46.10 +\hgcmdargs{help}{mq}. 46.11 + 46.12 +\subsection{\hgcmd{qapplied}---print applied patches} 46.13 + 46.14 +The \hgcmd{qapplied} command prints the current stack of applied 46.15 +patches. Patches are printed in oldest-to-newest order, so the last 46.16 +patch in the list is the ``top'' patch. 46.17 + 46.18 +\subsection{\hgcmd{qcommit}---commit changes in the queue repository} 46.19 + 46.20 +The \hgcmd{qcommit} command commits any outstanding changes in the 46.21 +\sdirname{.hg/patches} repository. This command only works if the 46.22 +\sdirname{.hg/patches} directory is a repository, i.e.~you created the 46.23 +directory using \hgcmdargs{qinit}{\hgopt{qinit}{-c}} or ran 46.24 +\hgcmd{init} in the directory after running \hgcmd{qinit}. 46.25 + 46.26 +This command is shorthand for \hgcmdargs{commit}{--cwd .hg/patches}. 46.27 + 46.28 +\subsection{\hgcmd{qdelete}---delete a patch from the 46.29 + \sfilename{series} file} 46.30 + 46.31 +The \hgcmd{qdelete} command removes the entry for a patch from the 46.32 +\sfilename{series} file in the \sdirname{.hg/patches} directory. It 46.33 +does not pop the patch if the patch is already applied. By default, 46.34 +it does not delete the patch file; use the \hgopt{qdel}{-f} option to 46.35 +do that. 46.36 + 46.37 +Options: 46.38 +\begin{itemize} 46.39 +\item[\hgopt{qdel}{-f}] Delete the patch file. 46.40 +\end{itemize} 46.41 + 46.42 +\subsection{\hgcmd{qdiff}---print a diff of the topmost applied patch} 46.43 + 46.44 +The \hgcmd{qdiff} command prints a diff of the topmost applied patch. 46.45 +It is equivalent to \hgcmdargs{diff}{-r-2:-1}. 46.46 + 46.47 +\subsection{\hgcmd{qfold}---merge (``fold'') several patches into one} 46.48 + 46.49 +The \hgcmd{qfold} command merges multiple patches into the topmost 46.50 +applied patch, so that the topmost applied patch makes the union of 46.51 +all of the changes in the patches in question. 46.52 + 46.53 +The patches to fold must not be applied; \hgcmd{qfold} will exit with 46.54 +an error if any is. The order in which patches are folded is 46.55 +significant; \hgcmdargs{qfold}{a b} means ``apply the current topmost 46.56 +patch, followed by \texttt{a}, followed by \texttt{b}''. 46.57 + 46.58 +The comments from the folded patches are appended to the comments of 46.59 +the destination patch, with each block of comments separated by three 46.60 +asterisk (``\texttt{*}'') characters. Use the \hgopt{qfold}{-e} 46.61 +option to edit the commit message for the combined patch/changeset 46.62 +after the folding has completed. 46.63 + 46.64 +Options: 46.65 +\begin{itemize} 46.66 +\item[\hgopt{qfold}{-e}] Edit the commit message and patch description 46.67 + for the newly folded patch. 46.68 +\item[\hgopt{qfold}{-l}] Use the contents of the given file as the new 46.69 + commit message and patch description for the folded patch. 46.70 +\item[\hgopt{qfold}{-m}] Use the given text as the new commit message 46.71 + and patch description for the folded patch. 46.72 +\end{itemize} 46.73 + 46.74 +\subsection{\hgcmd{qheader}---display the header/description of a patch} 46.75 + 46.76 +The \hgcmd{qheader} command prints the header, or description, of a 46.77 +patch. By default, it prints the header of the topmost applied patch. 46.78 +Given an argument, it prints the header of the named patch. 46.79 + 46.80 +\subsection{\hgcmd{qimport}---import a third-party patch into the queue} 46.81 + 46.82 +The \hgcmd{qimport} command adds an entry for an external patch to the 46.83 +\sfilename{series} file, and copies the patch into the 46.84 +\sdirname{.hg/patches} directory. It adds the entry immediately after 46.85 +the topmost applied patch, but does not push the patch. 46.86 + 46.87 +If the \sdirname{.hg/patches} directory is a repository, 46.88 +\hgcmd{qimport} automatically does an \hgcmd{add} of the imported 46.89 +patch. 46.90 + 46.91 +\subsection{\hgcmd{qinit}---prepare a repository to work with MQ} 46.92 + 46.93 +The \hgcmd{qinit} command prepares a repository to work with MQ. It 46.94 +creates a directory called \sdirname{.hg/patches}. 46.95 + 46.96 +Options: 46.97 +\begin{itemize} 46.98 +\item[\hgopt{qinit}{-c}] Create \sdirname{.hg/patches} as a repository 46.99 + in its own right. Also creates a \sfilename{.hgignore} file that 46.100 + will ignore the \sfilename{status} file. 46.101 +\end{itemize} 46.102 + 46.103 +When the \sdirname{.hg/patches} directory is a repository, the 46.104 +\hgcmd{qimport} and \hgcmd{qnew} commands automatically \hgcmd{add} 46.105 +new patches. 46.106 + 46.107 +\subsection{\hgcmd{qnew}---create a new patch} 46.108 + 46.109 +The \hgcmd{qnew} command creates a new patch. It takes one mandatory 46.110 +argument, the name to use for the patch file. The newly created patch 46.111 +is created empty by default. It is added to the \sfilename{series} 46.112 +file after the current topmost applied patch, and is immediately 46.113 +pushed on top of that patch. 46.114 + 46.115 +If \hgcmd{qnew} finds modified files in the working directory, it will 46.116 +refuse to create a new patch unless the \hgopt{qnew}{-f} option is 46.117 +used (see below). This behaviour allows you to \hgcmd{qrefresh} your 46.118 +topmost applied patch before you apply a new patch on top of it. 46.119 + 46.120 +Options: 46.121 +\begin{itemize} 46.122 +\item[\hgopt{qnew}{-f}] Create a new patch if the contents of the 46.123 + working directory are modified. Any outstanding modifications are 46.124 + added to the newly created patch, so after this command completes, 46.125 + the working directory will no longer be modified. 46.126 +\item[\hgopt{qnew}{-m}] Use the given text as the commit message. 46.127 + This text will be stored at the beginning of the patch file, before 46.128 + the patch data. 46.129 +\end{itemize} 46.130 + 46.131 +\subsection{\hgcmd{qnext}---print the name of the next patch} 46.132 + 46.133 +The \hgcmd{qnext} command prints the name name of the next patch in 46.134 +the \sfilename{series} file after the topmost applied patch. This 46.135 +patch will become the topmost applied patch if you run \hgcmd{qpush}. 46.136 + 46.137 +\subsection{\hgcmd{qpop}---pop patches off the stack} 46.138 + 46.139 +The \hgcmd{qpop} command removes applied patches from the top of the 46.140 +stack of applied patches. By default, it removes only one patch. 46.141 + 46.142 +This command removes the changesets that represent the popped patches 46.143 +from the repository, and updates the working directory to undo the 46.144 +effects of the patches. 46.145 + 46.146 +This command takes an optional argument, which it uses as the name or 46.147 +index of the patch to pop to. If given a name, it will pop patches 46.148 +until the named patch is the topmost applied patch. If given a 46.149 +number, \hgcmd{qpop} treats the number as an index into the entries in 46.150 +the series file, counting from zero (empty lines and lines containing 46.151 +only comments do not count). It pops patches until the patch 46.152 +identified by the given index is the topmost applied patch. 46.153 + 46.154 +The \hgcmd{qpop} command does not read or write patches or the 46.155 +\sfilename{series} file. It is thus safe to \hgcmd{qpop} a patch that 46.156 +you have removed from the \sfilename{series} file, or a patch that you 46.157 +have renamed or deleted entirely. In the latter two cases, use the 46.158 +name of the patch as it was when you applied it. 46.159 + 46.160 +By default, the \hgcmd{qpop} command will not pop any patches if the 46.161 +working directory has been modified. You can override this behaviour 46.162 +using the \hgopt{qpop}{-f} option, which reverts all modifications in 46.163 +the working directory. 46.164 + 46.165 +Options: 46.166 +\begin{itemize} 46.167 +\item[\hgopt{qpop}{-a}] Pop all applied patches. This returns the 46.168 + repository to its state before you applied any patches. 46.169 +\item[\hgopt{qpop}{-f}] Forcibly revert any modifications to the 46.170 + working directory when popping. 46.171 +\item[\hgopt{qpop}{-n}] Pop a patch from the named queue. 46.172 +\end{itemize} 46.173 + 46.174 +The \hgcmd{qpop} command removes one line from the end of the 46.175 +\sfilename{status} file for each patch that it pops. 46.176 + 46.177 +\subsection{\hgcmd{qprev}---print the name of the previous patch} 46.178 + 46.179 +The \hgcmd{qprev} command prints the name of the patch in the 46.180 +\sfilename{series} file that comes before the topmost applied patch. 46.181 +This will become the topmost applied patch if you run \hgcmd{qpop}. 46.182 + 46.183 +\subsection{\hgcmd{qpush}---push patches onto the stack} 46.184 +\label{sec:mq:cmd:qpush} 46.185 + 46.186 +The \hgcmd{qpush} command adds patches onto the applied stack. By 46.187 +default, it adds only one patch. 46.188 + 46.189 +This command creates a new changeset to represent each applied patch, 46.190 +and updates the working directory to apply the effects of the patches. 46.191 + 46.192 +The default data used when creating a changeset are as follows: 46.193 +\begin{itemize} 46.194 +\item The commit date and time zone are the current date and time 46.195 + zone. Because these data are used to compute the identity of a 46.196 + changeset, this means that if you \hgcmd{qpop} a patch and 46.197 + \hgcmd{qpush} it again, the changeset that you push will have a 46.198 + different identity than the changeset you popped. 46.199 +\item The author is the same as the default used by the \hgcmd{commit} 46.200 + command. 46.201 +\item The commit message is any text from the patch file that comes 46.202 + before the first diff header. If there is no such text, a default 46.203 + commit message is used that identifies the name of the patch. 46.204 +\end{itemize} 46.205 +If a patch contains a Mercurial patch header (XXX add link), the 46.206 +information in the patch header overrides these defaults. 46.207 + 46.208 +Options: 46.209 +\begin{itemize} 46.210 +\item[\hgopt{qpush}{-a}] Push all unapplied patches from the 46.211 + \sfilename{series} file until there are none left to push. 46.212 +\item[\hgopt{qpush}{-l}] Add the name of the patch to the end 46.213 + of the commit message. 46.214 +\item[\hgopt{qpush}{-m}] If a patch fails to apply cleanly, use the 46.215 + entry for the patch in another saved queue to compute the parameters 46.216 + for a three-way merge, and perform a three-way merge using the 46.217 + normal Mercurial merge machinery. Use the resolution of the merge 46.218 + as the new patch content. 46.219 +\item[\hgopt{qpush}{-n}] Use the named queue if merging while pushing. 46.220 +\end{itemize} 46.221 + 46.222 +The \hgcmd{qpush} command reads, but does not modify, the 46.223 +\sfilename{series} file. It appends one line to the \hgcmd{status} 46.224 +file for each patch that it pushes. 46.225 + 46.226 +\subsection{\hgcmd{qrefresh}---update the topmost applied patch} 46.227 + 46.228 +The \hgcmd{qrefresh} command updates the topmost applied patch. It 46.229 +modifies the patch, removes the old changeset that represented the 46.230 +patch, and creates a new changeset to represent the modified patch. 46.231 + 46.232 +The \hgcmd{qrefresh} command looks for the following modifications: 46.233 +\begin{itemize} 46.234 +\item Changes to the commit message, i.e.~the text before the first 46.235 + diff header in the patch file, are reflected in the new changeset 46.236 + that represents the patch. 46.237 +\item Modifications to tracked files in the working directory are 46.238 + added to the patch. 46.239 +\item Changes to the files tracked using \hgcmd{add}, \hgcmd{copy}, 46.240 + \hgcmd{remove}, or \hgcmd{rename}. Added files and copy and rename 46.241 + destinations are added to the patch, while removed files and rename 46.242 + sources are removed. 46.243 +\end{itemize} 46.244 + 46.245 +Even if \hgcmd{qrefresh} detects no changes, it still recreates the 46.246 +changeset that represents the patch. This causes the identity of the 46.247 +changeset to differ from the previous changeset that identified the 46.248 +patch. 46.249 + 46.250 +Options: 46.251 +\begin{itemize} 46.252 +\item[\hgopt{qrefresh}{-e}] Modify the commit and patch description, 46.253 + using the preferred text editor. 46.254 +\item[\hgopt{qrefresh}{-m}] Modify the commit message and patch 46.255 + description, using the given text. 46.256 +\item[\hgopt{qrefresh}{-l}] Modify the commit message and patch 46.257 + description, using text from the given file. 46.258 +\end{itemize} 46.259 + 46.260 +\subsection{\hgcmd{qrename}---rename a patch} 46.261 + 46.262 +The \hgcmd{qrename} command renames a patch, and changes the entry for 46.263 +the patch in the \sfilename{series} file. 46.264 + 46.265 +With a single argument, \hgcmd{qrename} renames the topmost applied 46.266 +patch. With two arguments, it renames its first argument to its 46.267 +second. 46.268 + 46.269 +\subsection{\hgcmd{qrestore}---restore saved queue state} 46.270 + 46.271 +XXX No idea what this does. 46.272 + 46.273 +\subsection{\hgcmd{qsave}---save current queue state} 46.274 + 46.275 +XXX Likewise. 46.276 + 46.277 +\subsection{\hgcmd{qseries}---print the entire patch series} 46.278 + 46.279 +The \hgcmd{qseries} command prints the entire patch series from the 46.280 +\sfilename{series} file. It prints only patch names, not empty lines 46.281 +or comments. It prints in order from first to be applied to last. 46.282 + 46.283 +\subsection{\hgcmd{qtop}---print the name of the current patch} 46.284 + 46.285 +The \hgcmd{qtop} prints the name of the topmost currently applied 46.286 +patch. 46.287 + 46.288 +\subsection{\hgcmd{qunapplied}---print patches not yet applied} 46.289 + 46.290 +The \hgcmd{qunapplied} command prints the names of patches from the 46.291 +\sfilename{series} file that are not yet applied. It prints them in 46.292 +order from the next patch that will be pushed to the last. 46.293 + 46.294 +\subsection{\hgcmd{qversion}} 46.295 + 46.296 +The \hgcmd{qversion} command prints the version of MQ that is in use. 46.297 + 46.298 +\subsection{\hgcmd{strip}---remove a revision and descendants} 46.299 + 46.300 +The \hgcmd{strip} command removes a revision, and all of its 46.301 +descendants, from the repository. It undoes the effects of the 46.302 +removed revisions from the repository, and updates the working 46.303 +directory to the first parent of the removed revision. 46.304 + 46.305 +The \hgcmd{strip} command saves a backup of the removed changesets in 46.306 +a bundle, so that they can be reapplied if removed in error. 46.307 + 46.308 +Options: 46.309 +\begin{itemize} 46.310 +\item[\hgopt{strip}{-b}] Save unrelated changesets that are intermixed 46.311 + with the stripped changesets in the backup bundle. 46.312 +\item[\hgopt{strip}{-f}] If a branch has multiple heads, remove all 46.313 + heads. XXX This should be renamed, and use \texttt{-f} to strip revs 46.314 + when there are pending changes. 46.315 +\item[\hgopt{strip}{-n}] Do not save a backup bundle. 46.316 +\end{itemize} 46.317 + 46.318 +\section{MQ file reference} 46.319 + 46.320 +\subsection{The \sfilename{series} file} 46.321 + 46.322 +The \sfilename{series} file contains a list of the names of all 46.323 +patches that MQ can apply. It is represented as a list of names, with 46.324 +one name saved per line. Leading and trailing white space in each 46.325 +line are ignored. 46.326 + 46.327 +Lines may contain comments. A comment begins with the ``\texttt{\#}'' 46.328 +character, and extends to the end of the line. Empty lines, and lines 46.329 +that contain only comments, are ignored. 46.330 + 46.331 +You will often need to edit the \sfilename{series} file by hand, hence 46.332 +the support for comments and empty lines noted above. For example, 46.333 +you can comment out a patch temporarily, and \hgcmd{qpush} will skip 46.334 +over that patch when applying patches. You can also change the order 46.335 +in which patches are applied by reordering their entries in the 46.336 +\sfilename{series} file. 46.337 + 46.338 +Placing the \sfilename{series} file under revision control is also 46.339 +supported; it is a good idea to place all of the patches that it 46.340 +refers to under revision control, as well. If you create a patch 46.341 +directory using the \hgopt{qinit}{-c} option to \hgcmd{qinit}, this 46.342 +will be done for you automatically. 46.343 + 46.344 +\subsection{The \sfilename{status} file} 46.345 + 46.346 +The \sfilename{status} file contains the names and changeset hashes of 46.347 +all patches that MQ currently has applied. Unlike the 46.348 +\sfilename{series} file, this file is not intended for editing. You 46.349 +should not place this file under revision control, or modify it in any 46.350 +way. It is used by MQ strictly for internal book-keeping. 46.351 + 46.352 +%%% Local Variables: 46.353 +%%% mode: latex 46.354 +%%% TeX-master: "00book" 46.355 +%%% End:
47.1 --- a/en/mq.tex Fri Jul 21 22:42:19 2006 -0700 47.2 +++ b/en/mq.tex Mon Mar 05 20:16:36 2007 -0800 47.3 @@ -69,7 +69,6 @@ 47.4 \subsection{A patchwork quilt} 47.5 \label{sec:mq:quilt} 47.6 47.7 - 47.8 In early 2003, Andreas Gruenbacher and Martin Quinson borrowed the 47.9 approach of Andrew's scripts and published a tool called ``patchwork 47.10 quilt''~\cite{web:quilt}, or simply ``quilt'' 47.11 @@ -114,19 +113,45 @@ 47.12 Mercurial. Each patch that you push is represented as a Mercurial 47.13 changeset. Pop a patch, and the changeset goes away. 47.14 47.15 -This integration makes understanding patches and debugging their 47.16 -effects \emph{enormously} easier. Since every applied patch has an 47.17 -associated changeset, you can use \hgcmdargs{log}{\emph{filename}} to 47.18 -see which changesets and patches affected a file. You can use the 47.19 -\hgext{bisect} extension to binary-search through all changesets and 47.20 -applied patches to see where a bug got introduced or fixed. You can 47.21 -use the \hgcmd{annotate} command to see which changeset or patch 47.22 -modified a particular line of a source file. And so on. 47.23 - 47.24 Because quilt does not care about revision control tools, it is still 47.25 a tremendously useful piece of software to know about for situations 47.26 where you cannot use Mercurial and MQ. 47.27 47.28 +\section{The huge advantage of MQ} 47.29 + 47.30 +I cannot overstate the value that MQ offers through the unification of 47.31 +patches and revision control. 47.32 + 47.33 +A major reason that patches have persisted in the free software and 47.34 +open source world---in spite of the availability of increasingly 47.35 +capable revision control tools over the years---is the \emph{agility} 47.36 +they offer. 47.37 + 47.38 +Traditional revision control tools make a permanent, irreversible 47.39 +record of everything that you do. While this has great value, it's 47.40 +also somewhat stifling. If you want to perform a wild-eyed 47.41 +experiment, you have to be careful in how you go about it, or you risk 47.42 +leaving unneeded---or worse, misleading or destabilising---traces of 47.43 +your missteps and errors in the permanent revision record. 47.44 + 47.45 +By contrast, MQ's marriage of distributed revision control with 47.46 +patches makes it much easier to isolate your work. Your patches live 47.47 +on top of normal revision history, and you can make them disappear or 47.48 +reappear at will. If you don't like a patch, you can drop it. If a 47.49 +patch isn't quite as you want it to be, simply fix it---as many times 47.50 +as you need to, until you have refined it into the form you desire. 47.51 + 47.52 +As an example, the integration of patches with revision control makes 47.53 +understanding patches and debugging their effects---and their 47.54 +interplay with the code they're based on---\emph{enormously} easier. 47.55 +Since every applied patch has an associated changeset, you can use 47.56 +\hgcmdargs{log}{\emph{filename}} to see which changesets and patches 47.57 +affected a file. You can use the \hgext{bisect} extension to 47.58 +binary-search through all changesets and applied patches to see where 47.59 +a bug got introduced or fixed. You can use the \hgcmd{annotate} 47.60 +command to see which changeset or patch modified a particular line of 47.61 +a source file. And so on. 47.62 + 47.63 \section{Understanding patches} 47.64 \label{sec:mq:patch} 47.65 47.66 @@ -141,7 +166,7 @@ 47.67 these commands in action. 47.68 47.69 \begin{figure}[ht] 47.70 - \interaction{mq.diff.diff} 47.71 + \interaction{mq.dodiff.diff} 47.72 \caption{Simple uses of the \command{diff} and \command{patch} commands} 47.73 \label{ex:mq:diff} 47.74 \end{figure} 47.75 @@ -179,7 +204,7 @@ 47.76 line.'' For example, a line that is modified is represented by one 47.77 deletion and one insertion. 47.78 47.79 -We will return to ome of the more subtle aspects of patches later (in 47.80 +We will return to some of the more subtle aspects of patches later (in 47.81 section~\ref{sec:mq:adv-patch}), but you should have enough information 47.82 now to use MQ. 47.83 47.84 @@ -581,7 +606,11 @@ 47.85 \end{itemize} 47.86 47.87 If you use \command{wiggle} or \command{rej}, you should be doubly 47.88 -careful to check your results when you're done. 47.89 +careful to check your results when you're done. In fact, 47.90 +\command{rej} enforces this method of double-checking the tool's 47.91 +output, by automatically dropping you into a merge program when it has 47.92 +done its job, so that you can verify its work and finish off any 47.93 +remaining merges. 47.94 47.95 \section{Getting the best performance out of MQ} 47.96 \label{sec:mq:perf} 47.97 @@ -590,13 +619,14 @@ 47.98 some performance experiments in mid-2006 for a talk that I gave at the 47.99 2006 EuroPython conference~\cite{web:europython}. I used as my data 47.100 set the Linux 2.6.17-mm1 patch series, which consists of 1,738 47.101 -patches. I applied thes on top of a Linux kernel repository 47.102 +patches. I applied these on top of a Linux kernel repository 47.103 containing all 27,472 revisions between Linux 2.6.12-rc2 and Linux 47.104 2.6.17. 47.105 47.106 On my old, slow laptop, I was able to 47.107 \hgcmdargs{qpush}{\hgopt{qpush}{-a}} all 1,738 patches in 3.5 minutes, 47.108 -and \hgcmdargs{qpop}{\hgopt{qpop}{-a}} them all in 30 seconds. I 47.109 +and \hgcmdargs{qpop}{\hgopt{qpop}{-a}} them all in 30 seconds. (On a 47.110 +newer laptop, the time to push all patches dropped to two minutes.) I 47.111 could \hgcmd{qrefresh} one of the biggest patches (which made 22,779 47.112 lines of changes to 287 files) in 6.6 seconds. 47.113 47.114 @@ -615,8 +645,7 @@ 47.115 patch'' that you want to end up at. When you \hgcmd{qpush} with a 47.116 destination specified, it will push patches until that patch is at the 47.117 top of the applied stack. When you \hgcmd{qpop} to a destination, MQ 47.118 -will pop patches until the destination patch \emph{is no longer} 47.119 -applied. 47.120 +will pop patches until the destination patch is at the top. 47.121 47.122 You can identify a destination patch using either the name of the 47.123 patch, or by number. If you use numeric addressing, patches are 47.124 @@ -692,6 +721,65 @@ 47.125 or \hgcmd{strip}. You can delete \sdirname{.hg/patches.\emph{N}} once 47.126 you are sure that you no longer need it as a backup. 47.127 47.128 +\section{Identifying patches} 47.129 + 47.130 +MQ commands that work with patches let you refer to a patch either by 47.131 +using its name or by a number. By name is obvious enough; pass the 47.132 +name \filename{foo.patch} to \hgcmd{qpush}, for example, and it will 47.133 +push patches until \filename{foo.patch} is applied. 47.134 + 47.135 +As a shortcut, you can refer to a patch using both a name and a 47.136 +numeric offset; \texttt{foo.patch-2} means ``two patches before 47.137 +\texttt{foo.patch}'', while \texttt{bar.patch+4} means ``four patches 47.138 +after \texttt{bar.patch}''. 47.139 + 47.140 +Referring to a patch by index isn't much different. The first patch 47.141 +printed in the output of \hgcmd{qseries} is patch zero (yes, it's one 47.142 +of those start-at-zero counting systems); the second is patch one; and 47.143 +so on 47.144 + 47.145 +MQ also makes it easy to work with patches when you are using normal 47.146 +Mercurial commands. Every command that accepts a changeset ID will 47.147 +also accept the name of an applied patch. MQ augments the tags 47.148 +normally in the repository with an eponymous one for each applied 47.149 +patch. In addition, the special tags \index{tags!special tag 47.150 + names!\texttt{qbase}}\texttt{qbase} and \index{tags!special tag 47.151 + names!\texttt{qtip}}\texttt{qtip} identify the ``bottom-most'' and 47.152 +topmost applied patches, respectively. 47.153 + 47.154 +These additions to Mercurial's normal tagging capabilities make 47.155 +dealing with patches even more of a breeze. 47.156 +\begin{itemize} 47.157 +\item Want to patchbomb a mailing list with your latest series of 47.158 + changes? 47.159 + \begin{codesample4} 47.160 + hg email qbase:qtip 47.161 + \end{codesample4} 47.162 +\item Need to see all of the patches since \texttt{foo.patch} that 47.163 + have touched files in a subdirectory of your tree? 47.164 + \begin{codesample4} 47.165 + hg log -r foo.patch:qtip \emph{subdir} 47.166 + \end{codesample4} 47.167 +\end{itemize} 47.168 + 47.169 +Because MQ makes the names of patches available to the rest of 47.170 +Mercurial through its normal internal tag machinery, you don't need to 47.171 +type in the entire name of a patch when you want to identify it by 47.172 +name. 47.173 + 47.174 +\begin{figure}[ht] 47.175 + \interaction{mq.id.out} 47.176 + \caption{Using MQ's tag features to work with patches} 47.177 + \label{ex:mq:id} 47.178 +\end{figure} 47.179 + 47.180 +Another nice consequence of representing patch names as tags is that 47.181 +when you run the \hgcmd{log} command, it will display a patch's name 47.182 +as a tag, simply as part of its normal output. This makes it easy to 47.183 +visually distinguish applied patches from underlying ``normal'' 47.184 +revisions. Figure~\ref{ex:mq:id} shows a few normal Mercurial 47.185 +commands in use with applied patches. 47.186 + 47.187 \section{Useful things to know about} 47.188 47.189 There are a number of aspects of MQ usage that don't fit tidily into 47.190 @@ -710,7 +798,9 @@ 47.191 patch stack. If you try to do this, it will appear to succeed, but 47.192 MQ will become confused. 47.193 \end{itemize} 47.194 + 47.195 \section{Managing patches in a repository} 47.196 +\label{sec:mq:repo} 47.197 47.198 Because MQ's \sdirname{.hg/patches} directory resides outside a 47.199 Mercurial repository's working directory, the ``underlying'' Mercurial 47.200 @@ -749,6 +839,7 @@ 47.201 into the \sdirname{.hg/patches} directory at any time and run 47.202 \hgcmd{init}. Don't forget to add an entry for the 47.203 \sfilename{status} file to the \sfilename{.hgignore} file, though 47.204 + 47.205 (\hgcmdargs{qinit}{\hgopt{qinit}{-c}} does this for you 47.206 automatically); you \emph{really} don't want to manage the 47.207 \sfilename{status} file. 47.208 @@ -804,7 +895,8 @@ 47.209 extracts subsets from a patch file. For example, given a patch that 47.210 modifies hundreds of files across dozens of directories, a single 47.211 invocation of \command{filterdiff} can generate a smaller patch that 47.212 -only touches files whose names match a particular glob pattern. 47.213 +only touches files whose names match a particular glob pattern. See 47.214 +section~\ref{mq-collab:tips:interdiff} for another example. 47.215 47.216 \section{Good ways to work with patches} 47.217 47.218 @@ -866,23 +958,17 @@ 47.219 \subsection{Combining entire patches} 47.220 \label{sec:mq:combine} 47.221 47.222 -It's easy to combine entire patches. 47.223 - 47.224 -\begin{enumerate} 47.225 -\item \hgcmd{qpop} your applied patches until neither patch is 47.226 - applied. 47.227 -\item Concatenate the patches that you want to combine together: 47.228 - \begin{codesample4} 47.229 - cat patch-to-drop.patch >> patch-to-augment.patch 47.230 - \end{codesample4} 47.231 - The description from the first patch (if you have one) will be used 47.232 - as the commit comment when you \hgcmd{qpush} the combined patch. 47.233 - Edit the patch description if you need to. 47.234 -\item Use the \hgcmd{qdel} command to delete the patch you're dropping 47.235 - from the \sfilename{series} file. 47.236 -\item \hgcmd{qpush} the combined patch. Fix up any rejects. 47.237 -\item \hgcmd{qrefresh} the combined patch to tidy it up. 47.238 -\end{enumerate} 47.239 +MQ provides a command, \hgcmd{qfold} that lets you combine entire 47.240 +patches. This ``folds'' the patches you name, in the order you name 47.241 +them, into the topmost applied patch, and concatenates their 47.242 +descriptions onto the end of its description. The patches that you 47.243 +fold must be unapplied before you fold them. 47.244 + 47.245 +The order in which you fold patches matters. If your topmost applied 47.246 +patch is \texttt{foo}, and you \hgcmd{qfold} \texttt{bar} and 47.247 +\texttt{quux} into it, you will end up with a patch that has the same 47.248 +effect as if you applied first \texttt{foo}, then \texttt{bar}, 47.249 +followed by \texttt{quux}. 47.250 47.251 \subsection{Merging part of one patch into another} 47.252 47.253 @@ -935,291 +1021,6 @@ 47.254 counterparts for which are the normal Mercurial \hgcmd{add} and 47.255 \hgcmd{remove} commands. There is no MQ equivalent of the quilt 47.256 \texttt{edit} command. 47.257 -\section{MQ command reference} 47.258 -\label{sec:mq:cmdref} 47.259 - 47.260 -For an overview of the commands provided by MQ, use the command 47.261 -\hgcmdargs{help}{mq}. 47.262 - 47.263 -\subsection{\hgcmd{qapplied}---print applied patches} 47.264 - 47.265 -The \hgcmd{qapplied} command prints the current stack of applied 47.266 -patches. Patches are printed in oldest-to-newest order, so the last 47.267 -patch in the list is the ``top'' patch. 47.268 - 47.269 -\subsection{\hgcmd{qcommit}---commit changes in the queue repository} 47.270 - 47.271 -The \hgcmd{qcommit} command commits any outstanding changes in the 47.272 -\sdirname{.hg/patches} repository. This command only works if the 47.273 -\sdirname{.hg/patches} directory is a repository, i.e.~you created the 47.274 -directory using \hgcmdargs{qinit}{\hgopt{qinit}{-c}} or ran 47.275 -\hgcmd{init} in the directory after running \hgcmd{qinit}. 47.276 - 47.277 -This command is shorthand for \hgcmdargs{commit}{--cwd .hg/patches}. 47.278 - 47.279 -\subsection{\hgcmd{qdelete}---delete a patch from the 47.280 - \sfilename{series} file} 47.281 - 47.282 -The \hgcmd{qdelete} command removes the entry for a patch from the 47.283 -\sfilename{series} file in the \sdirname{.hg/patches} directory. It 47.284 -does not delete the patch file, nor does it pop the patch if the patch 47.285 -is already applied. 47.286 - 47.287 -\subsection{\hgcmd{qdiff}---print a diff of the topmost applied patch} 47.288 - 47.289 -The \hgcmd{qdiff} command prints a diff of the topmost applied patch. 47.290 -It is equivalent to \hgcmdargs{diff}{-r-2:-1}. 47.291 - 47.292 -\subsection{\hgcmd{qimport}---import a third-party patch into the queue} 47.293 - 47.294 -The \hgcmd{qimport} command adds an entry for an external patch to the 47.295 -\sfilename{series} file, and copies the patch into the 47.296 -\sdirname{.hg/patches} directory. It adds the entry immediately after 47.297 -the topmost applied patch, but does not push the patch. 47.298 - 47.299 -If the \sdirname{.hg/patches} directory is a repository, 47.300 -\hgcmd{qimport} automatically does an \hgcmd{add} of the imported 47.301 -patch. 47.302 - 47.303 -\subsection{\hgcmd{qinit}---prepare a repository to work with MQ} 47.304 - 47.305 -The \hgcmd{qinit} command prepares a repository to work with MQ. It 47.306 -creates a directory called \sdirname{.hg/patches}. 47.307 - 47.308 -Options: 47.309 -\begin{itemize} 47.310 -\item[\hgopt{qinit}{-c}] Create \sdirname{.hg/patches} as a repository 47.311 - in its own right. Also creates a \sfilename{.hgignore} file that 47.312 - will ignore the \sfilename{status} file. 47.313 -\end{itemize} 47.314 - 47.315 -When the \sdirname{.hg/patches} directory is a repository, the 47.316 -\hgcmd{qimport} and \hgcmd{qnew} commands automatically \hgcmd{add} 47.317 -new patches. 47.318 - 47.319 -\subsection{\hgcmd{qnew}---create a new patch} 47.320 - 47.321 -The \hgcmd{qnew} command creates a new patch. It takes one mandatory 47.322 -argument, the name to use for the patch file. The newly created patch 47.323 -is created empty by default. It is added to the \sfilename{series} 47.324 -file after the current topmost applied patch, and is immediately 47.325 -pushed on top of that patch. 47.326 - 47.327 -If \hgcmd{qnew} finds modified files in the working directory, it will 47.328 -refuse to create a new patch unless the \hgopt{qnew}{-f} option is 47.329 -used (see below). This behaviour allows you to \hgcmd{qrefresh} your 47.330 -topmost applied patch before you apply a new patch on top of it. 47.331 - 47.332 -Options: 47.333 -\begin{itemize} 47.334 -\item[\hgopt{qnew}{-f}] Create a new patch if the contents of the 47.335 - working directory are modified. Any outstanding modifications are 47.336 - added to the newly created patch, so after this command completes, 47.337 - the working directory will no longer be modified. 47.338 -\item[\hgopt{qnew}{-m}] Use the given text as the commit message. 47.339 - This text will be stored at the beginning of the patch file, before 47.340 - the patch data. 47.341 -\end{itemize} 47.342 - 47.343 -\subsection{\hgcmd{qnext}---print the name of the next patch} 47.344 - 47.345 -The \hgcmd{qnext} command prints the name name of the next patch in 47.346 -the \sfilename{series} file after the topmost applied patch. This 47.347 -patch will become the topmost applied patch if you run \hgcmd{qpush}. 47.348 - 47.349 -\subsection{\hgcmd{qpop}---pop patches off the stack} 47.350 - 47.351 -The \hgcmd{qpop} command removes applied patches from the top of the 47.352 -stack of applied patches. By default, it removes only one patch. 47.353 - 47.354 -This command removes the changesets that represent the popped patches 47.355 -from the repository, and updates the working directory to undo the 47.356 -effects of the patches. 47.357 - 47.358 -This command takes an optional argument, which it uses as the name or 47.359 -index of the patch to pop to. If given a name, it will pop patches 47.360 -until the named patch is no longer applied. If given a number, 47.361 -\hgcmd{qpop} treats the number as an index into the entries in the 47.362 -series file, counting from zero (empty lines and lines containing only 47.363 -comments do not count). It pops patches until the patch identified by 47.364 -the given index is no longer applied. 47.365 - 47.366 -The \hgcmd{qpop} command does not read or write patches or the 47.367 -\sfilename{series} file. It is thus safe to \hgcmd{qpop} a patch that 47.368 -you have removed from the \sfilename{series} file, or a patch that you 47.369 -have renamed or deleted entirely. In the latter two cases, use the 47.370 -name of the patch as it was when you applied it. 47.371 - 47.372 -By default, the \hgcmd{qpop} command will not pop any patches if the 47.373 -working directory has been modified. You can override this behaviour 47.374 -using the \hgopt{qpop}{-f} option, which reverts all modifications in 47.375 -the working directory. 47.376 - 47.377 -Options: 47.378 -\begin{itemize} 47.379 -\item[\hgopt{qpop}{-a}] Pop all applied patches. This returns the 47.380 - repository to its state before you applied any patches. 47.381 -\item[\hgopt{qpop}{-f}] Forcibly revert any modifications to the 47.382 - working directory when popping. 47.383 -\item[\hgopt{qpop}{-n}] Pop a patch from the named queue. 47.384 -\end{itemize} 47.385 - 47.386 -The \hgcmd{qpop} command removes one line from the end of the 47.387 -\sfilename{status} file for each patch that it pops. 47.388 -\subsection{\hgcmd{qprev}---print the name of the previous patch} 47.389 - 47.390 -The \hgcmd{qprev} command prints the name of the patch in the 47.391 -\sfilename{series} file that comes before the topmost applied patch. 47.392 -This will become the topmost applied patch if you run \hgcmd{qpop}. 47.393 - 47.394 -\subsection{\hgcmd{qpush}---push patches onto the stack} 47.395 -\label{sec:mq:cmd:qpush} 47.396 - 47.397 -The \hgcmd{qpush} command adds patches onto the applied stack. By 47.398 -default, it adds only one patch. 47.399 - 47.400 -This command creates a new changeset to represent each applied patch, 47.401 -and updates the working directory to apply the effects of the patches. 47.402 - 47.403 -The default data used when creating a changeset are as follows: 47.404 -\begin{itemize} 47.405 -\item The commit date and time zone are the current date and time 47.406 - zone. Because these data are used to compute the identity of a 47.407 - changeset, this means that if you \hgcmd{qpop} a patch and 47.408 - \hgcmd{qpush} it again, the changeset that you push will have a 47.409 - different identity than the changeset you popped. 47.410 -\item The author is the same as the default used by the \hgcmd{commit} 47.411 - command. 47.412 -\item The commit message is any text from the patch file that comes 47.413 - before the first diff header. If there is no such text, a default 47.414 - commit message is used that identifies the name of the patch. 47.415 -\end{itemize} 47.416 -If a patch contains a Mercurial patch header (XXX add link), the 47.417 -information in the patch header overrides these defaults. 47.418 - 47.419 -Options: 47.420 -\begin{itemize} 47.421 -\item[\hgopt{qpush}{-a}] Push all unapplied patches from the 47.422 - \sfilename{series} file until there are none left to push. 47.423 -\item[\hgopt{qpush}{-l}] Add the name of the patch to the end 47.424 - of the commit message. 47.425 -\item[\hgopt{qpush}{-m}] If a patch fails to apply cleanly, use the 47.426 - entry for the patch in another saved queue to compute the parameters 47.427 - for a three-way merge, and perform a three-way merge using the 47.428 - normal Mercurial merge machinery. Use the resolution of the merge 47.429 - as the new patch content. 47.430 -\item[\hgopt{qpush}{-n}] Use the named queue if merging while pushing. 47.431 -\end{itemize} 47.432 - 47.433 -The \hgcmd{qpush} command reads, but does not modify, the 47.434 -\sfilename{series} file. It appends one line to the \hgcmd{status} 47.435 -file for each patch that it pushes. 47.436 - 47.437 -\subsection{\hgcmd{qrefresh}---update the topmost applied patch} 47.438 - 47.439 -The \hgcmd{qrefresh} command updates the topmost applied patch. It 47.440 -modifies the patch, removes the old changeset that represented the 47.441 -patch, and creates a new changeset to represent the modified patch. 47.442 - 47.443 -The \hgcmd{qrefresh} command looks for the following modifications: 47.444 -\begin{itemize} 47.445 -\item Changes to the commit message, i.e.~the text before the first 47.446 - diff header in the patch file, are reflected in the new changeset 47.447 - that represents the patch. 47.448 -\item Modifications to tracked files in the working directory are 47.449 - added to the patch. 47.450 -\item Changes to the files tracked using \hgcmd{add}, \hgcmd{copy}, 47.451 - \hgcmd{remove}, or \hgcmd{rename}. Added files and copy and rename 47.452 - destinations are added to the patch, while removed files and rename 47.453 - sources are removed. 47.454 -\end{itemize} 47.455 - 47.456 -Even if \hgcmd{qrefresh} detects no changes, it still recreates the 47.457 -changeset that represents the patch. This causes the identity of the 47.458 -changeset to differ from the previous changeset that identified the 47.459 -patch. 47.460 - 47.461 -\subsection{\hgcmd{qrestore}---restore saved queue state} 47.462 - 47.463 -XXX No idea what this does. 47.464 - 47.465 -\subsection{\hgcmd{qsave}---save current queue state} 47.466 - 47.467 -XXX Likewise. 47.468 - 47.469 -\subsection{\hgcmd{qseries}---print the entire patch series} 47.470 - 47.471 -The \hgcmd{qseries} command prints the entire patch series from the 47.472 -\sfilename{series} file. It prints only patch names, not empty lines 47.473 -or comments. It prints in order from first to be applied to last. 47.474 - 47.475 -\subsection{\hgcmd{qtop}---print the name of the current patch} 47.476 - 47.477 -The \hgcmd{qtop} prints the name of the topmost currently applied 47.478 -patch. 47.479 - 47.480 -\subsection{\hgcmd{qunapplied}---print patches not yet applied} 47.481 - 47.482 -The \hgcmd{qunapplied} command prints the names of patches from the 47.483 -\sfilename{series} file that are not yet applied. It prints them in 47.484 -order from the next patch that will be pushed to the last. 47.485 - 47.486 -\subsection{\hgcmd{qversion}} 47.487 - 47.488 -The \hgcmd{qversion} command prints the version of MQ that is in use. 47.489 - 47.490 -\subsection{\hgcmd{strip}---remove a revision and descendants} 47.491 - 47.492 -The \hgcmd{strip} command removes a revision, and all of its 47.493 -descendants, from the repository. It undoes the effects of the 47.494 -removed revisions from the repository, and updates the working 47.495 -directory to the first parent of the removed revision. 47.496 - 47.497 -The \hgcmd{strip} command saves a backup of the removed changesets in 47.498 -a bundle, so that they can be reapplied if removed in error. 47.499 - 47.500 -Options: 47.501 -\begin{itemize} 47.502 -\item[\hgopt{strip}{-b}] Save unrelated changesets that are intermixed 47.503 - with the stripped changesets in the backup bundle. 47.504 -\item[\hgopt{strip}{-f}] If a branch has multiple heads, remove all 47.505 - heads. XXX This should be renamed, and use \texttt{-f} to strip revs 47.506 - when there are pending changes. 47.507 -\item[\hgopt{strip}{-n}] Do not save a backup bundle. 47.508 -\end{itemize} 47.509 -\section{MQ file reference} 47.510 - 47.511 - 47.512 -\subsection{The \sfilename{series} file} 47.513 - 47.514 -The \sfilename{series} file contains a list of the names of all 47.515 -patches that MQ can apply. It is represented as a list of names, with 47.516 -one name saved per line. Leading and trailing white space in each 47.517 -line are ignored. 47.518 - 47.519 -Lines may contain comments. A comment begins with the ``\texttt{\#}'' 47.520 -character, and extends to the end of the line. Empty lines, and lines 47.521 -that contain only comments, are ignored. 47.522 - 47.523 -You will often need to edit the \sfilename{series} file by hand, hence 47.524 -the support for comments and empty lines noted above. For example, 47.525 -you can comment out a patch temporarily, and \hgcmd{qpush} will skip 47.526 -over that patch when applying patches. You can also change the order 47.527 -in which patches are applied by reordering their entries in the 47.528 -\sfilename{series} file. 47.529 - 47.530 -Placing the \sfilename{series} file under revision control is also 47.531 -supported; it is a good idea to place all of the patches that it 47.532 -refers to under revision control, as well. If you create a patch 47.533 -directory using the \hgopt{qinit}{-c} option to \hgcmd{qinit}, this 47.534 -will be done for you automatically. 47.535 -\subsection{The \sfilename{status} file} 47.536 - 47.537 -The \sfilename{status} file contains the names and changeset hashes of 47.538 -all patches that MQ currently has applied. Unlike the 47.539 -\sfilename{series} file, this file is not intended for editing. You 47.540 -should not place this file under revision control, or modify it in any 47.541 -way. It is used by MQ strictly for internal book-keeping. 47.542 47.543 %%% Local Variables: 47.544 %%% mode: latex
48.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 48.2 +++ b/en/revlog.svg Mon Mar 05 20:16:36 2007 -0800 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/en/snapshot.svg Mon Mar 05 20:16:36 2007 -0800 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 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 50.2 +++ b/en/srcinstall.tex Mon Mar 05 20:16:36 2007 -0800 50.3 @@ -0,0 +1,53 @@ 50.4 +\chapter{Installing Mercurial from source} 50.5 +\label{chap:srcinstall} 50.6 + 50.7 +\section{On a Unix-like system} 50.8 +\label{sec:srcinstall:unixlike} 50.9 + 50.10 +If you are using a Unix-like system that has a sufficiently recent 50.11 +version of Python (2.3~or newer) available, it is easy to install 50.12 +Mercurial from source. 50.13 +\begin{enumerate} 50.14 +\item Download a recent source tarball from 50.15 + \url{http://www.selenic.com/mercurial/download}. 50.16 +\item Unpack the tarball: 50.17 + \begin{codesample4} 50.18 + gzip -dc mercurial-\emph{version}.tar.gz | tar xf - 50.19 + \end{codesample4} 50.20 +\item Go into the source directory and run the installer script. This 50.21 + will build Mercurial and install it in your home directory. 50.22 + \begin{codesample4} 50.23 + cd mercurial-\emph{version} 50.24 + python setup.py install --force --home=\$HOME 50.25 + \end{codesample4} 50.26 +\end{enumerate} 50.27 +Once the install finishes, Mercurial will be in the \texttt{bin} 50.28 +subdirectory of your home directory. Don't forget to make sure that 50.29 +this directory is present in your shell's search path. 50.30 + 50.31 +You will probably need to set the \envar{PYTHONPATH} environment 50.32 +variable so that the Mercurial executable can find the rest of the 50.33 +Mercurial packages. For example, on my laptop, I have set it to 50.34 +\texttt{/home/bos/lib/python}. The exact path that you will need to 50.35 +use depends on how Python was built for your system, but should be 50.36 +easy to figure out. If you're uncertain, look through the output of 50.37 +the installer script above, and see where the contents of the 50.38 +\texttt{mercurial} directory were installed to. 50.39 + 50.40 +\section{On Windows} 50.41 + 50.42 +Building and installing Mercurial on Windows requires a variety of 50.43 +tools, a fair amount of technical knowledge, and considerable 50.44 +patience. I very much \emph{do not recommend} this route if you are a 50.45 +``casual user''. Unless you intend to hack on Mercurial, I strongly 50.46 +suggest that you use a binary package instead. 50.47 + 50.48 +If you are intent on building Mercurial from source on Windows, follow 50.49 +the ``hard way'' directions on the Mercurial wiki at 50.50 +\url{http://www.selenic.com/mercurial/wiki/index.cgi/WindowsInstall}, 50.51 +and expect the process to involve a lot of fiddly work. 50.52 + 50.53 +%%% Local Variables: 50.54 +%%% mode: latex 50.55 +%%% TeX-master: "00book" 50.56 +%%% End:
51.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 51.2 +++ b/en/template.tex Mon Mar 05 20:16:36 2007 -0800 51.3 @@ -0,0 +1,472 @@ 51.4 +\chapter{Customising the output of Mercurial} 51.5 +\label{chap:template} 51.6 + 51.7 +Mercurial provides a powerful mechanism to let you control how it 51.8 +displays information. The mechanism is based on templates. You can 51.9 +use templates to generate specific output for a single command, or to 51.10 +customise the entire appearance of the built-in web interface. 51.11 + 51.12 +\section{Using precanned output styles} 51.13 +\label{sec:style} 51.14 + 51.15 +Packaged with Mercurial are some output styles that you can use 51.16 +immediately. A style is simply a precanned template that someone 51.17 +wrote and installed somewhere that Mercurial can find. 51.18 + 51.19 +Before we take a look at Mercurial's bundled styles, let's review its 51.20 +normal output. 51.21 + 51.22 +\interaction{template.simple.normal} 51.23 + 51.24 +This is somewhat informative, but it takes up a lot of space---five 51.25 +lines of output per changeset. The \texttt{compact} style reduces 51.26 +this to three lines, presented in a sparse manner. 51.27 + 51.28 +\interaction{template.simple.compact} 51.29 + 51.30 +The \texttt{changelog} style hints at the expressive power of 51.31 +Mercurial's templating engine. This style attempts to follow the GNU 51.32 +Project's changelog guidelines\cite{web:changelog}. 51.33 + 51.34 +\interaction{template.simple.changelog} 51.35 + 51.36 +You will not be shocked to learn that Mercurial's default output style 51.37 +is named \texttt{default}. 51.38 + 51.39 +\subsection{Setting a default style} 51.40 + 51.41 +You can modify the output style that Mercurial will use for every 51.42 +command by editing your \hgrc\ file, naming the style you would 51.43 +prefer to use. 51.44 + 51.45 +\begin{codesample2} 51.46 + [ui] 51.47 + style = compact 51.48 +\end{codesample2} 51.49 + 51.50 +If you write a style of your own, you can use it by either providing 51.51 +the path to your style file, or copying your style file into a 51.52 +location where Mercurial can find it (typically the \texttt{templates} 51.53 +subdirectory of your Mercurial install directory). 51.54 + 51.55 +\section{Commands that support styles and templates} 51.56 + 51.57 +All of Mercurial's ``\texttt{log}-like'' commands let you use styles 51.58 +and templates: \hgcmd{incoming}, \hgcmd{log}, \hgcmd{outgoing}, and 51.59 +\hgcmd{tip}. 51.60 + 51.61 +As I write this manual, these are so far the only commands that 51.62 +support styles and templates. Since these are the most important 51.63 +commands that need customisable output, there has been little pressure 51.64 +from the Mercurial user community to add style and template support to 51.65 +other commands. 51.66 + 51.67 +\section{The basics of templating} 51.68 + 51.69 +At its simplest, a Mercurial template is a piece of text. Some of the 51.70 +text never changes, while other parts are \emph{expanded}, or replaced 51.71 +with new text, when necessary. 51.72 + 51.73 +Before we continue, let's look again at a simple example of 51.74 +Mercurial's normal output. 51.75 + 51.76 +\interaction{template.simple.normal} 51.77 + 51.78 +Now, let's run the same command, but using a template to change its 51.79 +output. 51.80 + 51.81 +\interaction{template.simple.simplest} 51.82 + 51.83 +The example above illustrates the simplest possible template; it's 51.84 +just a piece of static text, printed once for each changeset. The 51.85 +\hgopt{log}{--template} option to the \hgcmd{log} command tells 51.86 +Mercurial to use the given text as the template when printing each 51.87 +changeset. 51.88 + 51.89 +Notice that the template string above ends with the text 51.90 +``\Verb+\n+''. This is an \emph{escape sequence}, telling Mercurial 51.91 +to print a newline at the end of each template item. If you omit this 51.92 +newline, Mercurial will run each piece of output together. See 51.93 +section~\ref{sec:template:escape} for more details of escape sequences. 51.94 + 51.95 +A template that prints a fixed string of text all the time isn't very 51.96 +useful; let's try something a bit more complex. 51.97 + 51.98 +\interaction{template.simple.simplesub} 51.99 + 51.100 +As you can see, the string ``\Verb+{desc}+'' in the template has been 51.101 +replaced in the output with the description of each changeset. Every 51.102 +time Mercurial finds text enclosed in curly braces (``\texttt{\{}'' 51.103 +and ``\texttt{\}}''), it will try to replace the braces and text with 51.104 +the expansion of whatever is inside. To print a literal curly brace, 51.105 +you must escape it, as described in section~\ref{sec:template:escape}. 51.106 + 51.107 +\section{Common template keywords} 51.108 +\label{sec:template:keyword} 51.109 + 51.110 +You can start writing simple templates immediately using the keywords 51.111 +below. 51.112 + 51.113 +\begin{itemize} 51.114 +\item[\tplkword{author}] String. The unmodified author of the changeset. 51.115 +\item[\tplkword{date}] Date information. The date when the changeset 51.116 + was committed. This is \emph{not} human-readable; you must pass it 51.117 + through a filter that will render it appropriately. See 51.118 + section~\ref{sec:template:filter} for more information on filters. 51.119 + The date is expressed as a pair of numbers. The first number is a 51.120 + Unix UTC timestamp (seconds since January 1, 1970); the second is 51.121 + the offset of the committer's timezone from UTC, in seconds. 51.122 +\item[\tplkword{desc}] String. The text of the changeset description. 51.123 +\item[\tplkword{files}] List of strings. All files modified, added, or 51.124 + removed by this changeset. 51.125 +\item[\tplkword{file\_adds}] List of strings. Files added by this 51.126 + changeset. 51.127 +\item[\tplkword{file\_dels}] List of strings. Files removed by this 51.128 + changeset. 51.129 +\item[\tplkword{node}] String. The changeset identification hash, as a 51.130 + 40-character hexadecimal string. 51.131 +\item[\tplkword{parents}] List of strings. The parents of the 51.132 + changeset. 51.133 +\item[\tplkword{rev}] Integer. The repository-local changeset revision 51.134 + number. 51.135 +\item[\tplkword{tags}] List of strings. Any tags associated with the 51.136 + changeset. 51.137 +\end{itemize} 51.138 + 51.139 +A few simple experiments will show us what to expect when we use these 51.140 +keywords; you can see the results in 51.141 +figure~\ref{fig:template:keywords}. 51.142 + 51.143 +\begin{figure} 51.144 + \interaction{template.simple.keywords} 51.145 + \caption{Template keywords in use} 51.146 + \label{fig:template:keywords} 51.147 +\end{figure} 51.148 + 51.149 +As we noted above, the date keyword does not produce human-readable 51.150 +output, so we must treat it specially. This involves using a 51.151 +\emph{filter}, about which more in section~\ref{sec:template:filter}. 51.152 + 51.153 +\interaction{template.simple.datekeyword} 51.154 + 51.155 +\section{Escape sequences} 51.156 +\label{sec:template:escape} 51.157 + 51.158 +Mercurial's templating engine recognises the most commonly used escape 51.159 +sequences in strings. When it sees a backslash (``\Verb+\+'') 51.160 +character, it looks at the following character and substitutes the two 51.161 +characters with a single replacement, as described below. 51.162 + 51.163 +\begin{itemize} 51.164 +\item[\Verb+\textbackslash\textbackslash+] Backslash, ``\Verb+\+'', 51.165 + ASCII~134. 51.166 +\item[\Verb+\textbackslash n+] Newline, ASCII~12. 51.167 +\item[\Verb+\textbackslash r+] Carriage return, ASCII~15. 51.168 +\item[\Verb+\textbackslash t+] Tab, ASCII~11. 51.169 +\item[\Verb+\textbackslash v+] Vertical tab, ASCII~13. 51.170 +\item[\Verb+\textbackslash \{+] Open curly brace, ``\Verb+{+'', ASCII~173. 51.171 +\item[\Verb+\textbackslash \}+] Close curly brace, ``\Verb+}+'', ASCII~175. 51.172 +\end{itemize} 51.173 + 51.174 +As indicated above, if you want the expansion of a template to contain 51.175 +a literal ``\Verb+\+'', ``\Verb+{+'', or ``\Verb+{+'' character, you 51.176 +must escape it. 51.177 + 51.178 +\section{Filtering keywords to change their results} 51.179 +\label{sec:template:filter} 51.180 + 51.181 +Some of the results of template expansion are not immediately easy to 51.182 +use. Mercurial lets you specify an optional chain of \emph{filters} 51.183 +to modify the result of expanding a keyword. You have already seen a 51.184 +common filter, \tplkwfilt{date}{isodate}, in action above, to make a 51.185 +date readable. 51.186 + 51.187 +Below is a list of the most commonly used filters that Mercurial 51.188 +supports. While some filters can be applied to any text, others can 51.189 +only be used in specific circumstances. The name of each filter is 51.190 +followed first by an indication of where it can be used, then a 51.191 +description of its effect. 51.192 + 51.193 +\begin{itemize} 51.194 +\item[\tplfilter{addbreaks}] Any text. Add an XHTML ``\Verb+<br/>+'' 51.195 + tag before the end of every line except the last. For example, 51.196 + ``\Verb+foo\nbar+'' becomes ``\Verb+foo<br/>\nbar+''. 51.197 +\item[\tplkwfilt{date}{age}] \tplkword{date} keyword. Render the 51.198 + age of the date, relative to the current time. Yields a string like 51.199 + ``\Verb+10 minutes+''. 51.200 +\item[\tplfilter{basename}] Any text, but most useful for the 51.201 + \tplkword{files} keyword and its relatives. Treat the text as a 51.202 + path, and return the basename. For example, ``\Verb+foo/bar/baz+'' 51.203 + becomes ``\Verb+baz+''. 51.204 +\item[\tplkwfilt{date}{date}] \tplkword{date} keyword. Render a date 51.205 + in a similar format to the Unix \tplkword{date} command, but with 51.206 + timezone included. Yields a string like 51.207 + ``\Verb+Mon Sep 04 15:13:13 2006 -0700+''. 51.208 +\item[\tplkwfilt{author}{domain}] Any text, but most useful for the 51.209 + \tplkword{author} keyword. Finds the first string that looks like 51.210 + an email address, and extract just the domain component. For 51.211 + example, ``\Verb+Bryan O'Sullivan <bos@serpentine.com>+'' becomes 51.212 + ``\Verb+serpentine.com+''. 51.213 +\item[\tplkwfilt{author}{email}] Any text, but most useful for the 51.214 + \tplkword{author} keyword. Extract the first string that looks like 51.215 + an email address. For example, 51.216 + ``\Verb+Bryan O'Sullivan <bos@serpentine.com>+'' becomes 51.217 + ``\Verb+bos@serpentine.com+''. 51.218 +\item[\tplfilter{escape}] Any text. Replace the special XML/XHTML 51.219 + characters ``\Verb+&+'', ``\Verb+<+'' and ``\Verb+>+'' with 51.220 + XML entities. 51.221 +\item[\tplfilter{fill68}] Any text. Wrap the text to fit in 68 51.222 + columns. This is useful before you pass text through the 51.223 + \tplfilter{tabindent} filter, and still want it to fit in an 51.224 + 80-column fixed-font window. 51.225 +\item[\tplfilter{fill76}] Any text. Wrap the text to fit in 76 51.226 + columns. 51.227 +\item[\tplfilter{firstline}] Any text. Yield the first line of text, 51.228 + without any trailing newlines. 51.229 +\item[\tplkwfilt{date}{hgdate}] \tplkword{date} keyword. Render the 51.230 + date as a pair of readable numbers. Yields a string like 51.231 + ``\Verb+1157407993 25200+''. 51.232 +\item[\tplkwfilt{date}{isodate}] \tplkword{date} keyword. Render the 51.233 + date as a text string in ISO~8601 format. Yields a string like 51.234 + ``\Verb+2006-09-04 15:13:13 -0700+''. 51.235 +\item[\tplfilter{obfuscate}] Any text, but most useful for the 51.236 + \tplkword{author} keyword. Yield the input text rendered as a 51.237 + sequence of XML entities. This helps to defeat some particularly 51.238 + stupid screen-scraping email harvesting spambots. 51.239 +\item[\tplkwfilt{author}{person}] Any text, but most useful for the 51.240 + \tplkword{author} keyword. Yield the text before an email address. 51.241 + For example, ``\Verb+Bryan O'Sullivan <bos@serpentine.com>+'' 51.242 + becomes ``\Verb+Bryan O'Sullivan+''. 51.243 +\item[\tplkwfilt{date}{rfc822date}] \tplkword{date} keyword. Render a 51.244 + date using the same format used in email headers. Yields a string 51.245 + like ``\Verb+Mon, 04 Sep 2006 15:13:13 -0700+''. 51.246 +\item[\tplkwfilt{node}{short}] Changeset hash. Yield the short form 51.247 + of a changeset hash, i.e.~a 12-byte hexadecimal string. 51.248 +\item[\tplkwfilt{date}{shortdate}] \tplkword{date} keyword. Render 51.249 + the year, month, and day of the date. Yields a string like 51.250 + ``\Verb+2006-09-04+''. 51.251 +\item[\tplfilter{strip}] Any text. Strip all leading and trailing 51.252 + whitespace from the string. 51.253 +\item[\tplfilter{tabindent}] Any text. Yield the text, with every line 51.254 + except the first starting with a tab character. 51.255 +\item[\tplfilter{urlescape}] Any text. Escape all characters that are 51.256 + considered ``special'' by URL parsers. For example, \Verb+foo bar+ 51.257 + becomes \Verb+foo%20bar+. 51.258 +\item[\tplkwfilt{author}{user}] Any text, but most useful for the 51.259 + \tplkword{author} keyword. Return the ``user'' portion of an email 51.260 + address. For example, 51.261 + ``\Verb+Bryan O'Sullivan <bos@serpentine.com>+'' becomes 51.262 + ``\Verb+bos+''. 51.263 +\end{itemize} 51.264 + 51.265 +\begin{figure} 51.266 + \interaction{template.simple.manyfilters} 51.267 + \caption{Template filters in action} 51.268 + \label{fig:template:filters} 51.269 +\end{figure} 51.270 + 51.271 +\begin{note} 51.272 + If you try to apply a filter to a piece of data that it cannot 51.273 + process, Mercurial will fail and print a Python exception. For 51.274 + example, trying to run the output of the \tplkword{desc} keyword 51.275 + into the \tplkwfilt{date}{isodate} filter is not a good idea. 51.276 +\end{note} 51.277 + 51.278 +\subsection{Combining filters} 51.279 + 51.280 +It is easy to combine filters to yield output in the form you would 51.281 +like. The following chain of filters tidies up a description, then 51.282 +makes sure that it fits cleanly into 68 columns, then indents it by a 51.283 +further 8~characters (at least on Unix-like systems, where a tab is 51.284 +conventionally 8~characters wide). 51.285 + 51.286 +\interaction{template.simple.combine} 51.287 + 51.288 +Note the use of ``\Verb+\t+'' (a tab character) in the template to 51.289 +force the first line to be indented; this is necessary since 51.290 +\tplkword{tabindent} indents all lines \emph{except} the first. 51.291 + 51.292 +Keep in mind that the order of filters in a chain is significant. The 51.293 +first filter is applied to the result of the keyword; the second to 51.294 +the result of the first filter; and so on. For example, using 51.295 +\Verb+fill68|tabindent+ gives very different results from 51.296 +\Verb+tabindent|fill68+. 51.297 + 51.298 + 51.299 +\section{From templates to styles} 51.300 + 51.301 +A command line template provides a quick and simple way to format some 51.302 +output. Templates can become verbose, though, and it's useful to be 51.303 +able to give a template a name. A style file is a template with a 51.304 +name, stored in a file. 51.305 + 51.306 +More than that, using a style file unlocks the power of Mercurial's 51.307 +templating engine in ways that are not possible using the command line 51.308 +\hgopt{log}{--template} option. 51.309 + 51.310 +\subsection{The simplest of style files} 51.311 + 51.312 +Our simple style file contains just one line: 51.313 + 51.314 +\interaction{template.simple.rev} 51.315 + 51.316 +This tells Mercurial, ``if you're printing a changeset, use the text 51.317 +on the right as the template''. 51.318 + 51.319 +\subsection{Style file syntax} 51.320 + 51.321 +The syntax rules for a style file are simple. 51.322 + 51.323 +\begin{itemize} 51.324 +\item The file is processed one line at a time. 51.325 + 51.326 +\item Leading and trailing white space are ignored. 51.327 + 51.328 +\item Empty lines are skipped. 51.329 + 51.330 +\item If a line starts with either of the characters ``\texttt{\#}'' or 51.331 + ``\texttt{;}'', the entire line is treated as a comment, and skipped 51.332 + as if empty. 51.333 + 51.334 +\item A line starts with a keyword. This must start with an 51.335 + alphabetic character or underscore, and can subsequently contain any 51.336 + alphanumeric character or underscore. (In regexp notation, a 51.337 + keyword must match \Verb+[A-Za-z_][A-Za-z0-9_]*+.) 51.338 + 51.339 +\item The next element must be an ``\texttt{=}'' character, which can 51.340 + be preceded or followed by an arbitrary amount of white space. 51.341 + 51.342 +\item If the rest of the line starts and ends with matching quote 51.343 + characters (either single or double quote), it is treated as a 51.344 + template body. 51.345 + 51.346 +\item If the rest of the line \emph{does not} start with a quote 51.347 + character, it is treated as the name of a file; the contents of this 51.348 + file will be read and used as a template body. 51.349 +\end{itemize} 51.350 + 51.351 +\section{Style files by example} 51.352 + 51.353 +To illustrate how to write a style file, we will construct a few by 51.354 +example. Rather than provide a complete style file and walk through 51.355 +it, we'll mirror the usual process of developing a style file by 51.356 +starting with something very simple, and walking through a series of 51.357 +successively more complete examples. 51.358 + 51.359 +\subsection{Identifying mistakes in style files} 51.360 + 51.361 +If Mercurial encounters a problem in a style file you are working on, 51.362 +it prints a terse error message that, once you figure out what it 51.363 +means, is actually quite useful. 51.364 + 51.365 +\interaction{template.svnstyle.syntax.input} 51.366 + 51.367 +Notice that \filename{broken.style} attempts to define a 51.368 +\texttt{changeset} keyword, but forgets to give any content for it. 51.369 +When instructed to use this style file, Mercurial promptly complains. 51.370 + 51.371 +\interaction{template.svnstyle.syntax.error} 51.372 + 51.373 +This error message looks intimidating, but it is not too hard to 51.374 +follow. 51.375 + 51.376 +\begin{itemize} 51.377 +\item The first component is simply Mercurial's way of saying ``I am 51.378 + giving up''. 51.379 + \begin{codesample4} 51.380 + \textbf{abort:} broken.style:1: parse error 51.381 + \end{codesample4} 51.382 + 51.383 +\item Next comes the name of the style file that contains the error. 51.384 + \begin{codesample4} 51.385 + abort: \textbf{broken.style}:1: parse error 51.386 + \end{codesample4} 51.387 + 51.388 +\item Following the file name is the line number where the error was 51.389 + encountered. 51.390 + \begin{codesample4} 51.391 + abort: broken.style:\textbf{1}: parse error 51.392 + \end{codesample4} 51.393 + 51.394 +\item Finally, a description of what went wrong. 51.395 + \begin{codesample4} 51.396 + abort: broken.style:1: \textbf{parse error} 51.397 + \end{codesample4} 51.398 + The description of the problem is not always clear (as in this 51.399 + case), but even when it is cryptic, it is almost always trivial to 51.400 + visually inspect the offending line in the style file and see what 51.401 + is wrong. 51.402 +\end{itemize} 51.403 + 51.404 +\subsection{Uniquely identifying a repository} 51.405 + 51.406 +If you would like to be able to identify a Mercurial repository 51.407 +``fairly uniquely'' using a short string as an identifier, you can 51.408 +use the first revision in the repository. 51.409 +\interaction{template.svnstyle.id} 51.410 +This is not guaranteed to be unique, but it is nevertheless useful in 51.411 +many cases. 51.412 +\begin{itemize} 51.413 +\item It will not work in a completely empty repository, because such 51.414 + a repository does not have a revision~zero. 51.415 +\item Neither will it work in the (extremely rare) case where a 51.416 + repository is a merge of two or more formerly independent 51.417 + repositories, and you still have those repositories around. 51.418 +\end{itemize} 51.419 +Here are some uses to which you could put this identifier: 51.420 +\begin{itemize} 51.421 +\item As a key into a table for a database that manages repositories 51.422 + on a server. 51.423 +\item As half of a \{\emph{repository~ID}, \emph{revision~ID}\} tuple. 51.424 + Save this information away when you run an automated build or other 51.425 + activity, so that you can ``replay'' the build later if necessary. 51.426 +\end{itemize} 51.427 + 51.428 +\subsection{Mimicking Subversion's output} 51.429 + 51.430 +Let's try to emulate the default output format used by another 51.431 +revision control tool, Subversion. 51.432 +\interaction{template.svnstyle.short} 51.433 + 51.434 +Since Subversion's output style is fairly simple, it is easy to 51.435 +copy-and-paste a hunk of its output into a file, and replace the text 51.436 +produced above by Subversion with the template values we'd like to see 51.437 +expanded. 51.438 +\interaction{template.svnstyle.template} 51.439 + 51.440 +There are a few small ways in which this template deviates from the 51.441 +output produced by Subversion. 51.442 +\begin{itemize} 51.443 +\item Subversion prints a ``readable'' date (the ``\texttt{Wed, 27 Sep 51.444 + 2006}'' in the example output above) in parentheses. Mercurial's 51.445 + templating engine does not provide a way to display a date in this 51.446 + format without also printing the time and time zone. 51.447 +\item We emulate Subversion's printing of ``separator'' lines full of 51.448 + ``\texttt{-}'' characters by ending the template with such a line. 51.449 + We use the templating engine's \tplkword{header} keyword to print a 51.450 + separator line as the first line of output (see below), thus 51.451 + achieving similar output to Subversion. 51.452 +\item Subversion's output includes a count in the header of the number 51.453 + of lines in the commit message. We cannot replicate this in 51.454 + Mercurial; the templating engine does not currently provide a filter 51.455 + that counts the number of items it is passed. 51.456 +\end{itemize} 51.457 +It took me no more than a minute or two of work to replace literal 51.458 +text from an example of Subversion's output with some keywords and 51.459 +filters to give the template above. The style file simply refers to 51.460 +the template. 51.461 +\interaction{template.svnstyle.style} 51.462 + 51.463 +We could have included the text of the template file directly in the 51.464 +style file by enclosing it in quotes and replacing the newlines with 51.465 +``\texttt{\\n}'' sequences, but it would have made the style file too 51.466 +difficult to read. Readability is a good guide when you're trying to 51.467 +decide whether some text belongs in a style file, or in a template 51.468 +file that the style file points to. If the style file will look too 51.469 +big or cluttered if you insert a literal piece of text, drop it into a 51.470 +template instead. 51.471 + 51.472 +%%% Local Variables: 51.473 +%%% mode: latex 51.474 +%%% TeX-master: "00book" 51.475 +%%% End:
52.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 52.2 +++ b/en/tour-basic.tex Mon Mar 05 20:16:36 2007 -0800 52.3 @@ -0,0 +1,593 @@ 52.4 +\chapter{A tour of Mercurial: the basics} 52.5 +\label{chap:tour-basic} 52.6 + 52.7 +\section{Installing Mercurial on your system} 52.8 +\label{sec:tour:install} 52.9 + 52.10 +Prebuilt binary packages of Mercurial are available for every popular 52.11 +operating system. These make it easy to start using Mercurial on your 52.12 +computer immediately. 52.13 + 52.14 +\subsection{Linux} 52.15 + 52.16 +Because each Linux distribution has its own packaging tools, policies, 52.17 +and rate of development, it's difficult to give a comprehensive set of 52.18 +instructions on how to install Mercurial binaries. The version of 52.19 +Mercurial that you will end up with can vary depending on how active 52.20 +the person is who maintains the package for your distribution. 52.21 + 52.22 +To keep things simple, I will focus on installing Mercurial from the 52.23 +command line under the most popular Linux distributions. Most of 52.24 +these distributions provide graphical package managers that will let 52.25 +you install Mercurial with a single click; the package name to look 52.26 +for is \texttt{mercurial}. 52.27 + 52.28 +\begin{itemize} 52.29 +\item[Debian] 52.30 + \begin{codesample4} 52.31 + apt-get install mercurial 52.32 + \end{codesample4} 52.33 + 52.34 +\item[Fedora Core] 52.35 + \begin{codesample4} 52.36 + yum install mercurial 52.37 + \end{codesample4} 52.38 + 52.39 +\item[Gentoo] 52.40 + \begin{codesample4} 52.41 + emerge mercurial 52.42 + \end{codesample4} 52.43 + 52.44 +\item[OpenSUSE] 52.45 + \begin{codesample4} 52.46 + yum install mercurial 52.47 + \end{codesample4} 52.48 + 52.49 +\item[Ubuntu] Ubuntu's Mercurial package is particularly old, and you 52.50 + should not use it. If you know how, you can rebuild and install the 52.51 + Debian package. It's probably easier to build Mercurial from source 52.52 + and simply run that; see section~\ref{sec:srcinstall:unixlike} for 52.53 + details. 52.54 +\end{itemize} 52.55 + 52.56 +\subsection{Mac OS X} 52.57 + 52.58 +Lee Cantey publishes an installer of Mercurial for Mac OS~X at 52.59 +\url{http://mercurial.berkwood.com}. This package works on both 52.60 +Intel-~and Power-based Macs. Before you can use it, you must install 52.61 +a compatible version of Universal MacPython~\cite{web:macpython}. This 52.62 +is easy to do; simply follow the instructions on Lee's site. 52.63 + 52.64 +\subsection{Solaris} 52.65 + 52.66 +XXX. 52.67 + 52.68 +\subsection{Windows} 52.69 + 52.70 +Lee Cantey publishes an installer of Mercurial for Windows at 52.71 +\url{http://mercurial.berkwood.com}. This package has no external 52.72 +dependencies; it ``just works''. 52.73 + 52.74 +\begin{note} 52.75 + The Windows version of Mercurial does not automatically convert line 52.76 + endings between Windows and Unix styles. If you want to share work 52.77 + with Unix users, you must do a little additional configuration 52.78 + work. XXX Flesh this out. 52.79 +\end{note} 52.80 + 52.81 +\section{Getting started} 52.82 + 52.83 +To begin, we'll use the \hgcmd{version} command to find out whether 52.84 +Mercurial is actually installed properly. The actual version 52.85 +information that it prints isn't so important; it's whether it prints 52.86 +anything at all that we care about. 52.87 +\interaction{tour.version} 52.88 + 52.89 +\subsection{Built-in help} 52.90 + 52.91 +Mercurial provides a built-in help system. This invaluable for those 52.92 +times when you find yourself stuck trying to remember how to run a 52.93 +command. If you are completely stuck, simply run \hgcmd{help}; it 52.94 +will print a brief list of commands, along with a description of what 52.95 +each does. If you ask for help on a specific command (as below), it 52.96 +prints more detailed information. 52.97 +\interaction{tour.help} 52.98 +For a more impressive level of detail (which you won't usually need) 52.99 +run \hgcmdargs{help}{\hggopt{-v}}. The \hggopt{-v} option is short 52.100 +for \hggopt{--verbose}, and tells Mercurial to print more information 52.101 +than it usually would. 52.102 + 52.103 +\section{Working with a repository} 52.104 + 52.105 +In Mercurial, everything happens inside a \emph{repository}. The 52.106 +repository for a project contains all of the files that ``belong to'' 52.107 +that project, along with a historical record of the project's files. 52.108 + 52.109 +There's nothing particularly magical about a repository; it is simply 52.110 +a directory tree in your filesystem that Mercurial treats as special. 52.111 +You can rename delete a repository any time you like, using either the 52.112 +command line or your file browser. 52.113 + 52.114 +\subsection{Making a local copy of a repository} 52.115 + 52.116 +\emph{Copying} a repository is just a little bit special. While you 52.117 +could use a normal file copying command to make a copy of a 52.118 +repository, it's best to use a built-in command that Mercurial 52.119 +provides. This command is called \hgcmd{clone}, because it creates an 52.120 +identical copy of an existing repository. 52.121 +\interaction{tour.clone} 52.122 +If our clone succeeded, we should now have a local directory called 52.123 +\dirname{hello}. This directory will contain some files. 52.124 +\interaction{tour.ls} 52.125 +These files have the same contents and history in our repository as 52.126 +they do in the repository we cloned. 52.127 + 52.128 +Every Mercurial repository is complete, self-contained, and 52.129 +independent. It contains its own private copy of a project's files 52.130 +and history. A cloned repository remembers the location of the 52.131 +repository it was cloned from, but it does not communicate with that 52.132 +repository, or any other, unless you tell it to. 52.133 + 52.134 +What this means for now is that we're free to experiment with our 52.135 +repository, safe in the knowledge that it's a private ``sandbox'' that 52.136 +won't affect anyone else. 52.137 + 52.138 +\subsection{What's in a repository?} 52.139 + 52.140 +When we take a more detailed look inside a repository, we can see that 52.141 +it contains a directory named \dirname{.hg}. This is where Mercurial 52.142 +keeps all of its metadata for the repository. 52.143 +\interaction{tour.ls-a} 52.144 + 52.145 +The contents of the \dirname{.hg} directory and its subdirectories are 52.146 +private to Mercurial. Every other file and directory in the 52.147 +repository is yours to do with as you please. 52.148 + 52.149 +To introduce a little terminology, the \dirname{.hg} directory is the 52.150 +``real'' repository, and all of the files and directories that coexist 52.151 +with it are said to live in the \emph{working directory}. An easy way 52.152 +to remember the distinction is that the \emph{repository} contains the 52.153 +\emph{history} of your project, while the \emph{working directory} 52.154 +contains a \emph{snapshot} of your project at a particular point in 52.155 +history. 52.156 + 52.157 +\section{A tour through history} 52.158 + 52.159 +One of the first things we might want to do with a new, unfamiliar 52.160 +repository is understand its history. The \hgcmd{log} command gives 52.161 +us a view of history. 52.162 +\interaction{tour.log} 52.163 +By default, this command prints a brief paragraph of output for each 52.164 +change to the project that was recorded. In Mercurial terminology, we 52.165 +call each of these recorded events a \emph{changeset}, because it can 52.166 +contain a record of changes to several files. 52.167 + 52.168 +The fields in a record of output from \hgcmd{log} are as follows. 52.169 +\begin{itemize} 52.170 +\item[\texttt{changeset}] This field has the format of a number, 52.171 + followed by a colon, followed by a hexadecimal string. These are 52.172 + \emph{identifiers} for the changeset. There are two identifiers 52.173 + because the number is shorter and easier to type than the hex 52.174 + string. 52.175 +\item[\texttt{user}] The identity of the person who created the 52.176 + changeset. This is a free-form field, but it most often contains a 52.177 + person's name and email address. 52.178 +\item[\texttt{date}] The date and time on which the changeset was 52.179 + created, and the timezone in which it was created. (Thef date and 52.180 + time are local to that timezone; they display what time and date it 52.181 + was for the person who created the changeset.) 52.182 +\item[\texttt{summary}] The first line of the text message that the 52.183 + creator of the changeset entered to describe the changeset. 52.184 +\end{itemize} 52.185 +The default output printed by \hgcmd{log} is purely a summary; it is 52.186 +missing a lot of detail. 52.187 + 52.188 +Figure~\ref{fig:tour-basic:history} provides a graphical representation of 52.189 +the history of the \dirname{hello} repository, to make it a little 52.190 +easier to see which direction history is ``flowing'' in. We'll be 52.191 +returning to this figure several times in this chapter and the chapter 52.192 +that follows. 52.193 + 52.194 +\begin{figure}[ht] 52.195 + \centering 52.196 + \grafix{tour-history} 52.197 + \caption{Graphical history of the \dirname{hello} repository} 52.198 + \label{fig:tour-basic:history} 52.199 +\end{figure} 52.200 + 52.201 +\subsection{Changesets, revisions, and talking to other 52.202 + people} 52.203 + 52.204 +As English is a notoriously sloppy language, and computer science has 52.205 +a hallowed history of terminological confusion (why use one term when 52.206 +four will do?), revision control has a variety of words and phrases 52.207 +that mean the same thing. If you are talking about Mercurial history 52.208 +with other people, you will find that the word ``changeset'' is often 52.209 +compressed to ``change'' or (when written) ``cset'', and sometimes a 52.210 +changeset is referred to as a ``revision'' or a ``rev''. 52.211 + 52.212 +While it doesn't matter what \emph{word} you use to refer to the 52.213 +concept of ``a~changeset'', the \emph{identifier} that you use to 52.214 +refer to ``a~\emph{specific} changeset'' is of great importance. 52.215 +Recall that the \texttt{changeset} field in the output from 52.216 +\hgcmd{log} identifies a changeset using both a number and a 52.217 +hexadecimal string. 52.218 +\begin{itemize} 52.219 +\item The revision number is \emph{only valid in that repository}, 52.220 +\item while the hex string is the \emph{permanent, unchanging 52.221 + identifier} that will always identify that exact changeset in 52.222 + \emph{every} copy of the repository. 52.223 +\end{itemize} 52.224 +This distinction is important. If you send someone an email talking 52.225 +about ``revision~33'', there's a high likelihood that their 52.226 +revision~33 will \emph{not be the same} as yours. The reason for this 52.227 +is that a revision number depends on the order in which changes 52.228 +arrived in a repository, and there is no guarantee that the same 52.229 +changes will happen in the same order in different repositories. 52.230 +Three changes $a,b,c$ can easily appear in one repository as $0,1,2$, 52.231 +while in another as $1,0,2$. 52.232 + 52.233 +Mercurial uses revision numbers purely as a convenient shorthand. If 52.234 +you need to discuss a changeset with someone, or make a record of a 52.235 +changeset for some other reason (for example, in a bug report), use 52.236 +the hexadecimal identifier. 52.237 + 52.238 +\subsection{Viewing specific revisions} 52.239 + 52.240 +To narrow the output of \hgcmd{log} down to a single revision, use the 52.241 +\hgopt{log}{-r} (or \hgopt{log}{--rev}) option. You can use either a 52.242 +revision number or a long-form changeset identifier, and you can 52.243 +provide as many revisions as you want. \interaction{tour.log-r} 52.244 + 52.245 +If you want to see the history of several revisions without having to 52.246 +list each one, you can use \emph{range notation}; this lets you 52.247 +express the idea ``I want all revisions between $a$ and $b$, 52.248 +inclusive''. 52.249 +\interaction{tour.log.range} 52.250 +Mercurial also honours the order in which you specify revisions, so 52.251 +\hgcmdargs{log}{-r 2:4} prints $2,3,4$ while \hgcmdargs{log}{-r 4:2} 52.252 +prints $4,3,2$. 52.253 + 52.254 +\subsection{More detailed information} 52.255 + 52.256 +While the summary information printed by \hgcmd{log} is useful if you 52.257 +already know what you're looking for, you may need to see a complete 52.258 +description of the change, or a list of the files changed, if you're 52.259 +trying to decide whether a changeset is the one you're looking for. 52.260 +The \hgcmd{log} command's \hggopt{-v} (or \hggopt{--verbose}) 52.261 +option gives you this extra detail. 52.262 +\interaction{tour.log-v} 52.263 + 52.264 +If you want to see both the description and content of a change, add 52.265 +the \hgopt{log}{-p} (or \hgopt{log}{--patch}) option. This displays 52.266 +the content of a change as a \emph{unified diff} (if you've never seen 52.267 +a unified diff before, see section~\ref{sec:mq:patch} for an overview). 52.268 +\interaction{tour.log-vp} 52.269 + 52.270 +\section{All about command options} 52.271 + 52.272 +Let's take a brief break from exploring Mercurial commands to discuss 52.273 +a pattern in the way that they work; you may find this useful to keep 52.274 +in mind as we continiue our tour. 52.275 + 52.276 +Mercurial has a consistent and straightforward approach to dealing 52.277 +with the options that you can pass to commands. It follows the 52.278 +conventions for options that are common to modern Linux and Unix 52.279 +systems. 52.280 +\begin{itemize} 52.281 +\item Every option has a long name. For example, as we've already 52.282 + seen, the \hgcmd{log} command accepts a \hgopt{log}{--rev} option. 52.283 +\item Most options have short names, too. Instead of 52.284 + \hgopt{log}{--rev}, we can use \hgopt{log}{-r}. (The reason that 52.285 + some options don't have short names is that the options in question 52.286 + are rarely used.) 52.287 +\item Long options start with two dashes (e.g.~\hgopt{log}{--rev}), 52.288 + while short options start with one (e.g.~\hgopt{log}{-r}). 52.289 +\item Option naming and usage is consistent across commands. For 52.290 + example, every command that lets you specify a changeset~ID or 52.291 + revision number accepts both \hgopt{log}{-r} and \hgopt{log}{--rev} 52.292 + arguments. 52.293 +\end{itemize} 52.294 +In the examples throughout this book, I use short options instead of 52.295 +long. This just reflects my own preference, so don't read anything 52.296 +significant into it. 52.297 + 52.298 +Most commands that print output of some kind will print more output 52.299 +when passed a \hggopt{-v} (or \hggopt{--verbose}) option, and less 52.300 +when passed \hggopt{-q} (or \hggopt{--quiet}). 52.301 + 52.302 +\section{Making and reviewing changes} 52.303 + 52.304 +Now that we have a grasp of viewing history in Mercurial, let's take a 52.305 +look at making some changes and examining them. 52.306 + 52.307 +The first thing we'll do is isolate our experiment in a repository of 52.308 +its own. We use the \hgcmd{clone} command, but we don't need to 52.309 +clone a copy of the remote repository. Since we already have a copy 52.310 +of it locally, we can just clone that instead. This is much faster 52.311 +than cloning over the network, and cloning a local repository uses 52.312 +less disk space in most cases, too. 52.313 +\interaction{tour.reclone} 52.314 +As an aside, it's often good practice to keep a ``pristine'' copy of a 52.315 +remote repository around, which you can then make temporary clones of 52.316 +to create sandboxes for each task you want to work on. This lets you 52.317 +work on multiple tasks in parallel, each isolated from the others 52.318 +until it's complete and you're ready to integrate it back. Because 52.319 +local clones are so cheap, there's almost no overhead to cloning and 52.320 +destroying repositories whenever you want. 52.321 + 52.322 +In our \dirname{my-hello} repository, we have a file 52.323 +\filename{hello.c} that contains the classic ``hello, world'' program. 52.324 +Let's use the ancient and venerable \command{sed} command to edit this 52.325 +file so that it prints a second line of output. (I'm only using 52.326 +\command{sed} to do this because it's easy to write a scripted example 52.327 +this way. Since you're not under the same constraint, you probably 52.328 +won't want to use \command{sed}; simply use your preferred text editor to 52.329 +do the same thing.) 52.330 +\interaction{tour.sed} 52.331 + 52.332 +Mercurial's \hgcmd{status} command will tell us what Mercurial knows 52.333 +about the files in the repository. 52.334 +\interaction{tour.status} 52.335 +The \hgcmd{status} command prints no output for some files, but a line 52.336 +starting with ``\texttt{M}'' for \filename{hello.c}. Unless you tell 52.337 +it to, \hgcmd{status} will not print any output for files that have 52.338 +not been modified. 52.339 + 52.340 +The ``\texttt{M}'' indicates that Mercurial has noticed that we 52.341 +modified \filename{hello.c}. We didn't need to \emph{inform} 52.342 +Mercurial that we were going to modify the file before we started, or 52.343 +that we had modified the file after we were done; it was able to 52.344 +figure this out itself. 52.345 + 52.346 +It's a little bit helpful to know that we've modified 52.347 +\filename{hello.c}, but we might prefer to know exactly \emph{what} 52.348 +changes we've made to it. To do this, we use the \hgcmd{diff} 52.349 +command. 52.350 +\interaction{tour.diff} 52.351 + 52.352 +\section{Recording changes in a new changeset} 52.353 + 52.354 +We can modify files, build and test our changes, and use 52.355 +\hgcmd{status} and \hgcmd{diff} to review our changes, until we're 52.356 +satisfied with what we've done and arrive at a natural stopping point 52.357 +where we want to record our work in a new changeset. 52.358 + 52.359 +The \hgcmd{commit} command lets us create a new changeset; we'll 52.360 +usually refer to this as ``making a commit'' or ``committing''. 52.361 + 52.362 +\subsection{Setting up a username} 52.363 + 52.364 +When you try to run \hgcmd{commit} for the first time, it may succeed 52.365 +immediately, or it may fail with an error message that looks like 52.366 +this. 52.367 +\interaction{tour.commit-no-user} 52.368 +If it succeeds for you, the chances are that either you already have a 52.369 +file called \sfilename{.hgrc} in your home directory, or an 52.370 +environment variable set named \envar{EMAIL}. 52.371 + 52.372 +When you commit, Mercurial wants to know what your name is, so that it 52.373 +can record it. If you have created a \sfilename{.hgrc} file, it will 52.374 +look in there. If it doesn't find something suitable, it will see if 52.375 +your \envar{EMAIL} address is set. If neither of these is present, it 52.376 +will produce the error message you can see above. 52.377 + 52.378 +\subsubsection{Creating a Mercurial configuration file} 52.379 + 52.380 +To set a user name, use your favourite editor to create a file called 52.381 +\sfilename{.hgrc} in your home directory. Mercurial will use this 52.382 +file to look up your personalised configuration settings. The initial 52.383 +contents of your \sfilename{.hgrc} should look like this. 52.384 +\begin{codesample2} 52.385 + # This is a Mercurial configuration file. 52.386 + [ui] 52.387 + username = Firstname Lastname <email.address@domain.net> 52.388 +\end{codesample2} 52.389 +The ``\texttt{[ui]}'' line begins a \emph{section} of the config file, 52.390 +so you can read the ``\texttt{username = ...}'' line as meaning ``set 52.391 +the value of the \texttt{username} item in the \texttt{ui} section''. 52.392 +A section continues until a new section begins, or the end of the 52.393 +file. Mercurial ignores empty lines and treats any text from 52.394 +``\texttt{\#}'' to the end of a line as a comment. 52.395 + 52.396 +\subsubsection{Choosing a user name} 52.397 + 52.398 +You can use any text you like as the value of the \texttt{username} 52.399 +config item, since this information is for reading by other people, 52.400 +but for interpreting by Mercurial. The convention that most people 52.401 +follow is to use their name and email address, as in the example 52.402 +above. 52.403 + 52.404 +\begin{note} 52.405 + Mercurial's built-in web server obfuscates email addresses, to make 52.406 + it more difficult for the email harvesting tools that spammers use. 52.407 + This reduces the likelihood that you'll start receiving more junk 52.408 + email if you publish a Mercurial repository on the web. 52.409 +\end{note} 52.410 + 52.411 +\subsection{Writing a commit message} 52.412 + 52.413 +When we commit a change, Mercurial drops us into a text editor, to 52.414 +enter a message that will describe the modifications we've made in 52.415 +this changeset. This is called the \emph{commit message}. It will be 52.416 +a record for readers of what we did and why, and it will be printed by 52.417 +\hgcmd{log} after we've finished committing. 52.418 +\interaction{tour.commit} 52.419 + 52.420 +The editor that the \hgcmd{commit} command drops us into will contain 52.421 +an empty line, followed by a number of lines starting with 52.422 +``\texttt{HG:}''. 52.423 +\begin{codesample2} 52.424 + \emph{empty line} 52.425 + HG: changed hello.c 52.426 +\end{codesample2} 52.427 +Mercurial ignores the lines that start with ``\texttt{HG:}''; it uses 52.428 +them only to tell us which files it's recording changes to. Modifying 52.429 +or deleting these lines has no effect. 52.430 + 52.431 +\subsection{Writing a good commit message} 52.432 + 52.433 +Since \hgcmd{log} only prints the first line of a commit message by 52.434 +default, it's best to write a commit message whose first line stands 52.435 +alone. Here's a real example of a commit message that \emph{doesn't} 52.436 +follow this guideline, and hence has a summary that is not readable. 52.437 +\begin{codesample2} 52.438 + changeset: 73:584af0e231be 52.439 + user: Censored Person <censored.person@example.org> 52.440 + date: Tue Sep 26 21:37:07 2006 -0700 52.441 + summary: include buildmeister/commondefs. Add an exports and install 52.442 +\end{codesample2} 52.443 + 52.444 +As far as the remainder of the contents of the commit message are 52.445 +concerned, there are no hard-and-fast rules. Mercurial itself doesn't 52.446 +interpret or care about the contents of the commit message, though 52.447 +your project may have policies that dictate a certain kind of 52.448 +formatting. 52.449 + 52.450 +My personal preference is for short, but informative, commit messages 52.451 +that tell me something that I can't figure out with a quick glance at 52.452 +the output of \hgcmdargs{log}{--patch}. 52.453 + 52.454 +\subsection{Aborting a commit} 52.455 + 52.456 +If you decide that you don't want to commit while in the middle of 52.457 +editing a commit message, simply exit from your editor without saving 52.458 +the file that it's editing. This will cause nothing to happen to 52.459 +either the repository or the working directory. 52.460 + 52.461 +If we run the \hgcmd{commit} command without any arguments, it records 52.462 +all of the changes we've made, as reported by \hgcmd{status} and 52.463 +\hgcmd{diff}. 52.464 + 52.465 +\subsection{Admiring our new handiwork} 52.466 + 52.467 +Once we've finished the commit, we can use the \hgcmd{tip} command to 52.468 +display the changeset we just created. This command produces output 52.469 +that is identical to \hgcmd{log}, but it only displays the newest 52.470 +revision in the repository. 52.471 +\interaction{tour.tip} 52.472 +We refer to the newest revision in the repository as the tip revision, 52.473 +or simply the tip. 52.474 + 52.475 +\section{Sharing changes} 52.476 + 52.477 +We mentioned earlier that repositories in Mercurial are 52.478 +self-contained. This means that the changeset we just created exists 52.479 +only in our \dirname{my-hello} repository. Let's look at a few ways 52.480 +that we can propagate this change into other repositories. 52.481 + 52.482 +\subsection{Pulling changes from another repository} 52.483 +\label{sec:tour:pull} 52.484 + 52.485 +To get started, let's clone our original \dirname{hello} repository, 52.486 +which does not contain the change we just committed. We'll call our 52.487 +temporary repository \dirname{hello-pull}. 52.488 +\interaction{tour.clone-pull} 52.489 + 52.490 +We'll use the \hgcmd{pull} command to bring changes from 52.491 +\dirname{my-hello} into \dirname{hello-pull}. However, blindly 52.492 +pulling unknown changes into a repository is a somewhat scary 52.493 +prospect. Mercurial provides the \hgcmd{incoming} command to tell us 52.494 +what changes the \hgcmd{pull} command \emph{would} pull into the 52.495 +repository, without actually pulling the changes in. 52.496 +\interaction{tour.incoming} 52.497 +(Of course, someone could cause more changesets to appear in the 52.498 +repository that we ran \hgcmd{incoming} in, before we get a chance to 52.499 +\hgcmd{pull} the changes, so that we could end up pulling changes that we 52.500 +didn't expect.) 52.501 + 52.502 +Bringing changes into a repository is a simple matter of running the 52.503 +\hgcmd{pull} command, and telling it which repository to pull from. 52.504 +\interaction{tour.pull} 52.505 +As you can see from the before-and-after output of \hgcmd{tip}, we 52.506 +have successfully pulled changes into our repository. There remains 52.507 +one step before we can see these changes in the working directory. 52.508 + 52.509 +\subsection{Updating the working directory} 52.510 + 52.511 +We have so far glossed over the relationship between a repository and 52.512 +its working directory. The \hgcmd{pull} command that we ran in 52.513 +section~\ref{sec:tour:pull} brought changes into the repository, but 52.514 +if we check, there's no sign of those changes in the working 52.515 +directory. This is because \hgcmd{pull} does not (by default) touch 52.516 +the working directory. Instead, we use the \hgcmd{update} command to 52.517 +do this. 52.518 +\interaction{tour.update} 52.519 + 52.520 +It might seem a bit strange that \hgcmd{pull} doesn't update the 52.521 +working directory automatically. There's actually a good reason for 52.522 +this: you can use \hgcmd{update} to update the working directory to 52.523 +the state it was in at \emph{any revision} in the history of the 52.524 +repository. If you had the working directory updated to an old 52.525 +revision---to hunt down the origin of a bug, say---and ran a 52.526 +\hgcmd{pull} which automatically updated the working directory to a 52.527 +new revision, you might not be terribly happy. 52.528 + 52.529 +However, since pull-then-update is such a common thing to do, 52.530 +Mercurial lets you combine the two by passing the \hgopt{pull}{-u} 52.531 +option to \hgcmd{pull}. 52.532 +\begin{codesample2} 52.533 + hg pull -u 52.534 +\end{codesample2} 52.535 +If you look back at the output of \hgcmd{pull} in 52.536 +section~\ref{sec:tour:pull} when we ran it without \hgopt{pull}{-u}, 52.537 +you can see that it printed a helpful reminder that we'd have to take 52.538 +an explicit step to update the working directory: 52.539 +\begin{codesample2} 52.540 + (run 'hg update' to get a working copy) 52.541 +\end{codesample2} 52.542 + 52.543 +To find out what revision the working directory is at, use the 52.544 +\hgcmd{parents} command. 52.545 +\interaction{tour.parents} 52.546 +If you look back at figure~\ref{fig:tour-basic:history}, you'll see 52.547 +arrows connecting each changeset. The node that the arrow leads 52.548 +\emph{from} in each case is a parent, and the node that the arrow 52.549 +leads \emph{to} is its child. The working directory has a parent in 52.550 +just the same way; this is the changeset that the working directory 52.551 +currently contains. 52.552 + 52.553 +To update the working directory to a particular revision, give a 52.554 +revision number or changeset~ID to the \hgcmd{update} command. 52.555 +\interaction{tour.older} 52.556 +If you omit an explicit revision, \hgcmd{update} will update to the 52.557 +tip revision, as shown by the second call to \hgcmd{update} in the 52.558 +example above. 52.559 + 52.560 +\subsection{Pushing changes to another repository} 52.561 + 52.562 +Mercurial lets us push changes to another repository, from the 52.563 +repository we're currently visiting. As with the example of 52.564 +\hgcmd{pull} above, we'll create a temporary repository to push our 52.565 +changes into. 52.566 +\interaction{tour.clone-push} 52.567 +The \hgcmd{outgoing} command tells us what changes would be pushed 52.568 +into another repository. 52.569 +\interaction{tour.outgoing} 52.570 +And the \hgcmd{push} command does the actual push. 52.571 +\interaction{tour.push} 52.572 +As with \hgcmd{pull}, the \hgcmd{push} command does not update the 52.573 +working directory in the repository that it's pushing changes into. 52.574 +(Unlike \hgcmd{pull}, \hgcmd{push} does not provide a \texttt{-u} 52.575 +option that updates the other repository's working directory.) 52.576 + 52.577 +What happens if we try to pull or push changes and the receiving 52.578 +repository already has those changes? Nothing too exciting. 52.579 +\interaction{tour.push.nothing} 52.580 + 52.581 +\subsection{Sharing changes over a network} 52.582 + 52.583 +The commands we have covered in the previous few sections are not 52.584 +limited to working with local repositories. Each works in exactly the 52.585 +same fashion over a network connection; simply pass in a URL instead 52.586 +of a local path. 52.587 +\interaction{tour.outgoing.net} 52.588 +In this example, we can see what changes we could push to the remote 52.589 +repository, but the repository is understandably not set up to let 52.590 +anonymous users push to it. 52.591 +\interaction{tour.push.net} 52.592 + 52.593 +%%% Local Variables: 52.594 +%%% mode: latex 52.595 +%%% TeX-master: "00book" 52.596 +%%% End:
53.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 53.2 +++ b/en/tour-history.svg Mon Mar 05 20:16:36 2007 -0800 53.3 @@ -0,0 +1,289 @@ 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-history.svg"> 53.20 + <defs 53.21 + id="defs4"> 53.22 + <marker 53.23 + inkscape:stockid="Arrow1Mstart" 53.24 + orient="auto" 53.25 + refY="0.0" 53.26 + refX="0.0" 53.27 + id="Arrow1Mstart" 53.28 + style="overflow:visible"> 53.29 + <path 53.30 + id="path2973" 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) translate(10,0)" /> 53.34 + </marker> 53.35 + <marker 53.36 + inkscape:stockid="Arrow1Mend" 53.37 + orient="auto" 53.38 + refY="0.0" 53.39 + refX="0.0" 53.40 + id="Arrow1Mend" 53.41 + style="overflow:visible;"> 53.42 + <path 53.43 + id="path3066" 53.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 " 53.45 + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;" 53.46 + transform="scale(0.4) rotate(180) translate(10,0)" /> 53.47 + </marker> 53.48 + </defs> 53.49 + <sodipodi:namedview 53.50 + id="base" 53.51 + pagecolor="#ffffff" 53.52 + bordercolor="#666666" 53.53 + borderopacity="1.0" 53.54 + gridtolerance="10000" 53.55 + guidetolerance="10" 53.56 + objecttolerance="10" 53.57 + inkscape:pageopacity="0.0" 53.58 + inkscape:pageshadow="2" 53.59 + inkscape:zoom="1.4" 53.60 + inkscape:cx="232.14286" 53.61 + inkscape:cy="672.75296" 53.62 + inkscape:document-units="px" 53.63 + inkscape:current-layer="layer1" 53.64 + inkscape:window-width="906" 53.65 + inkscape:window-height="620" 53.66 + inkscape:window-x="5" 53.67 + inkscape:window-y="49" /> 53.68 + <metadata 53.69 + id="metadata7"> 53.70 + <rdf:RDF> 53.71 + <cc:Work 53.72 + rdf:about=""> 53.73 + <dc:format>image/svg+xml</dc:format> 53.74 + <dc:type 53.75 + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 53.76 + </cc:Work> 53.77 + </rdf:RDF> 53.78 + </metadata> 53.79 + <g 53.80 + inkscape:label="Layer 1" 53.81 + inkscape:groupmode="layer" 53.82 + id="layer1"> 53.83 + <rect 53.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" 53.85 + id="rect1878" 53.86 + width="94.285713" 53.87 + height="20.714285" 53.88 + x="138" 53.89 + y="479.50504" /> 53.90 + <text 53.91 + xml:space="preserve" 53.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" 53.93 + x="162.09892" 53.94 + y="493.12619" 53.95 + id="text1872"><tspan 53.96 + sodipodi:role="line" 53.97 + id="tspan1874" 53.98 + x="162.09892" 53.99 + y="493.12619" 53.100 + style="font-family:Courier"><tspan 53.101 + style="font-weight:bold" 53.102 + id="tspan1876">0</tspan>: 0a04</tspan></text> 53.103 + <rect 53.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" 53.105 + id="rect2800" 53.106 + width="94.285713" 53.107 + height="20.714285" 53.108 + x="138" 53.109 + y="432.63004" /> 53.110 + <text 53.111 + xml:space="preserve" 53.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" 53.113 + x="162.09892" 53.114 + y="446.25119" 53.115 + id="text2794"><tspan 53.116 + sodipodi:role="line" 53.117 + id="tspan2796" 53.118 + x="162.09892" 53.119 + y="446.25119" 53.120 + style="font-family:Courier"><tspan 53.121 + id="tspan2868" 53.122 + style="font-weight:bold">1</tspan>: 82e5</tspan></text> 53.123 + <rect 53.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" 53.125 + id="rect2810" 53.126 + width="94.285713" 53.127 + height="20.714285" 53.128 + x="138" 53.129 + y="385.75504" /> 53.130 + <text 53.131 + xml:space="preserve" 53.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" 53.133 + x="162.09892" 53.134 + y="399.37619" 53.135 + id="text2804"><tspan 53.136 + sodipodi:role="line" 53.137 + id="tspan2806" 53.138 + x="162.09892" 53.139 + y="399.37619" 53.140 + style="font-family:Courier"><tspan 53.141 + style="font-weight:bold" 53.142 + id="tspan2866">2</tspan>: 057d</tspan></text> 53.143 + <rect 53.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" 53.145 + id="rect2820" 53.146 + width="94.285713" 53.147 + height="20.714285" 53.148 + x="138" 53.149 + y="338.88007" /> 53.150 + <text 53.151 + xml:space="preserve" 53.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" 53.153 + x="162.09892" 53.154 + y="352.50122" 53.155 + id="text2814"><tspan 53.156 + sodipodi:role="line" 53.157 + id="tspan2816" 53.158 + x="162.09892" 53.159 + y="352.50122" 53.160 + style="font-family:Courier"><tspan 53.161 + style="font-weight:bold" 53.162 + id="tspan2864">3</tspan>: ff5d</tspan></text> 53.163 + <rect 53.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" 53.165 + id="rect2830" 53.166 + width="94.285713" 53.167 + height="20.714285" 53.168 + x="138" 53.169 + y="292.00504" /> 53.170 + <text 53.171 + xml:space="preserve" 53.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" 53.173 + x="162.09892" 53.174 + y="305.62619" 53.175 + id="text2824"><tspan 53.176 + sodipodi:role="line" 53.177 + id="tspan2826" 53.178 + x="162.09892" 53.179 + y="305.62619" 53.180 + style="font-family:Courier"><tspan 53.181 + style="font-weight:bold" 53.182 + id="tspan2862">4</tspan>: b57f</tspan></text> 53.183 + <text 53.184 + xml:space="preserve" 53.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" 53.186 + x="173.57143" 53.187 + y="443.79074" 53.188 + id="text2832"><tspan 53.189 + sodipodi:role="line" 53.190 + id="tspan2834" 53.191 + x="173.57143" 53.192 + y="443.79074" /></text> 53.193 + <path 53.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)" 53.195 + d="M 185.14286,478.50504 L 185.14286,454.34432" 53.196 + id="path2894" 53.197 + inkscape:connector-type="polyline" /> 53.198 + <path 53.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)" 53.200 + d="M 185.14286,431.63004 L 185.14286,407.46932" 53.201 + id="path2896" 53.202 + inkscape:connector-type="polyline" /> 53.203 + <path 53.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)" 53.205 + d="M 185.14286,384.75504 L 185.14286,360.59435" 53.206 + id="path2898" 53.207 + inkscape:connector-type="polyline" /> 53.208 + <path 53.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)" 53.210 + d="M 185.14286,337.88007 L 185.14286,313.71932" 53.211 + id="path2900" 53.212 + inkscape:connector-type="polyline" /> 53.213 + <text 53.214 + xml:space="preserve" 53.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" 53.216 + x="244.60992" 53.217 + y="305.245" 53.218 + id="text1902"><tspan 53.219 + sodipodi:role="line" 53.220 + id="tspan1904" 53.221 + x="244.60992" 53.222 + y="305.245">(newest)</tspan></text> 53.223 + <text 53.224 + xml:space="preserve" 53.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" 53.226 + x="244.60992" 53.227 + y="492.745" 53.228 + id="text1906"><tspan 53.229 + sodipodi:role="line" 53.230 + id="tspan1908" 53.231 + x="244.60992" 53.232 + y="492.745">(oldest)</tspan></text> 53.233 + <rect 53.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" 53.235 + id="rect1907" 53.236 + width="94.285713" 53.237 + height="20.714285" 53.238 + x="309.28571" 53.239 + y="324.86218" /> 53.240 + <text 53.241 + xml:space="preserve" 53.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" 53.243 + x="333.38464" 53.244 + y="338.48334" 53.245 + id="text1909"><tspan 53.246 + sodipodi:role="line" 53.247 + id="tspan1911" 53.248 + x="333.38464" 53.249 + y="338.48334" 53.250 + style="font-family:Courier"><tspan 53.251 + style="font-weight:bold" 53.252 + id="tspan1913">4</tspan>: b57f</tspan></text> 53.253 + <path 53.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" 53.255 + d="M 332.14286,375.21932 L 335.71429,347.36218" 53.256 + id="path2802" /> 53.257 + <path 53.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" 53.259 + d="M 372.69968,375.21932 L 369.12825,347.36218" 53.260 + id="path2986" /> 53.261 + <text 53.262 + xml:space="preserve" 53.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" 53.264 + x="335.14285" 53.265 + y="387.21933" 53.266 + id="text2988"><tspan 53.267 + sodipodi:role="line" 53.268 + x="335.14285" 53.269 + y="387.21933" 53.270 + id="tspan3020" 53.271 + style="text-align:end;text-anchor:end">revision</tspan><tspan 53.272 + sodipodi:role="line" 53.273 + x="335.14285" 53.274 + y="402.21933" 53.275 + id="tspan3014" 53.276 + style="text-align:end;text-anchor:end">number</tspan></text> 53.277 + <text 53.278 + xml:space="preserve" 53.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" 53.280 + x="368.71429" 53.281 + y="387.21933" 53.282 + id="text2994"><tspan 53.283 + sodipodi:role="line" 53.284 + id="tspan2996" 53.285 + x="368.71429" 53.286 + y="387.21933">changeset</tspan><tspan 53.287 + sodipodi:role="line" 53.288 + x="368.71429" 53.289 + y="402.21933" 53.290 + id="tspan2998">identifier</tspan></text> 53.291 + </g> 53.292 +</svg>
54.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 54.2 +++ b/en/tour-merge-conflict.svg Mon Mar 05 20:16:36 2007 -0800 54.3 @@ -0,0 +1,210 @@ 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-conflict.svg"> 54.20 + <defs 54.21 + id="defs4"> 54.22 + <marker 54.23 + inkscape:stockid="Arrow1Mend" 54.24 + orient="auto" 54.25 + refY="0.0" 54.26 + refX="0.0" 54.27 + id="Arrow1Mend" 54.28 + style="overflow:visible;"> 54.29 + <path 54.30 + id="path3053" 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) rotate(180) translate(10,0)" /> 54.34 + </marker> 54.35 + </defs> 54.36 + <sodipodi:namedview 54.37 + id="base" 54.38 + pagecolor="#ffffff" 54.39 + bordercolor="#666666" 54.40 + borderopacity="1.0" 54.41 + gridtolerance="10000" 54.42 + guidetolerance="10" 54.43 + objecttolerance="10" 54.44 + inkscape:pageopacity="0.0" 54.45 + inkscape:pageshadow="2" 54.46 + inkscape:zoom="1.4" 54.47 + inkscape:cx="164.78349" 54.48 + inkscape:cy="590.07679" 54.49 + inkscape:document-units="px" 54.50 + inkscape:current-layer="layer1" 54.51 + inkscape:window-width="906" 54.52 + inkscape:window-height="620" 54.53 + inkscape:window-x="5" 54.54 + inkscape:window-y="49" /> 54.55 + <metadata 54.56 + id="metadata7"> 54.57 + <rdf:RDF> 54.58 + <cc:Work 54.59 + rdf:about=""> 54.60 + <dc:format>image/svg+xml</dc:format> 54.61 + <dc:type 54.62 + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 54.63 + </cc:Work> 54.64 + </rdf:RDF> 54.65 + </metadata> 54.66 + <g 54.67 + inkscape:label="Layer 1" 54.68 + inkscape:groupmode="layer" 54.69 + id="layer1"> 54.70 + <g 54.71 + id="g1988" 54.72 + transform="translate(84.85711,0)"> 54.73 + <g 54.74 + id="g1876"> 54.75 + <path 54.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" 54.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 " 54.78 + id="path1872" 54.79 + sodipodi:nodetypes="cccccc" /> 54.80 + <path 54.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" 54.82 + d="M 191.55484,563.36862 L 191.6923,560.98794 L 192.69126,552.44884 L 203.80416,551.31242" 54.83 + id="path1874" 54.84 + sodipodi:nodetypes="cccc" /> 54.85 + </g> 54.86 + <flowRoot 54.87 + style="font-size:8px;font-family:Times New Roman" 54.88 + id="flowRoot1898" 54.89 + xml:space="preserve"><flowRegion 54.90 + id="flowRegion1900"><rect 54.91 + style="font-size:8px;font-family:Times New Roman" 54.92 + y="464.50504" 54.93 + x="122.85714" 54.94 + height="93.571426" 54.95 + width="76.428574" 54.96 + id="rect1902" /></flowRegion><flowPara 54.97 + id="flowPara1904">Greetings!</flowPara><flowPara 54.98 + id="flowPara1906" /><flowPara 54.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> 54.100 + <g 54.101 + id="g1966" 54.102 + transform="translate(82,0.35715)"> 54.103 + <g 54.104 + transform="translate(-77.85718,-140.0714)" 54.105 + id="g1910"> 54.106 + <path 54.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" 54.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 " 54.109 + id="path1912" 54.110 + sodipodi:nodetypes="cccccc" /> 54.111 + <path 54.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" 54.113 + d="M 191.55484,563.36862 L 191.6923,560.98794 L 192.69126,552.44884 L 203.80416,551.31242" 54.114 + id="path1914" 54.115 + sodipodi:nodetypes="cccc" /> 54.116 + </g> 54.117 + <flowRoot 54.118 + transform="translate(-77.85718,-140.0714)" 54.119 + style="font-size:8px;font-family:Times New Roman" 54.120 + id="flowRoot1916" 54.121 + xml:space="preserve"><flowRegion 54.122 + id="flowRegion1918"><rect 54.123 + style="font-size:8px;font-family:Times New Roman" 54.124 + y="464.50504" 54.125 + x="122.85714" 54.126 + height="93.571426" 54.127 + width="76.428574" 54.128 + id="rect1920" /></flowRegion><flowPara 54.129 + id="flowPara1922">Greetings!</flowPara><flowPara 54.130 + id="flowPara1924" /><flowPara 54.131 + id="flowPara1926">I am <flowSpan 54.132 + style="font-style:italic;fill:red" 54.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> 54.134 + <g 54.135 + id="g1977" 54.136 + transform="translate(81.99999,-0.35715)"> 54.137 + <g 54.138 + transform="translate(83.57141,-139.3571)" 54.139 + id="g1932"> 54.140 + <path 54.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" 54.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 " 54.143 + id="path1934" 54.144 + sodipodi:nodetypes="cccccc" /> 54.145 + <path 54.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" 54.147 + d="M 191.55484,563.36862 L 191.6923,560.98794 L 192.69126,552.44884 L 203.80416,551.31242" 54.148 + id="path1936" 54.149 + sodipodi:nodetypes="cccc" /> 54.150 + </g> 54.151 + <flowRoot 54.152 + transform="translate(83.57141,-139.3571)" 54.153 + style="font-size:8px;font-family:Times New Roman" 54.154 + id="flowRoot1938" 54.155 + xml:space="preserve"><flowRegion 54.156 + id="flowRegion1940"><rect 54.157 + style="font-size:8px;font-family:Times New Roman" 54.158 + y="464.50504" 54.159 + x="122.85714" 54.160 + height="93.571426" 54.161 + width="76.428574" 54.162 + id="rect1942" /></flowRegion><flowPara 54.163 + id="flowPara1944">Greetings!</flowPara><flowPara 54.164 + id="flowPara1946" /><flowPara 54.165 + id="flowPara1948">I am <flowSpan 54.166 + style="font-style:italic;fill:red" 54.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> 54.168 + <path 54.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" 54.170 + d="M 215.502,457.71933 L 196.35507,424.5765" 54.171 + id="path1999" 54.172 + inkscape:connector-type="polyline" 54.173 + inkscape:connection-start="#g1988" 54.174 + inkscape:connection-end="#g1966" /> 54.175 + <path 54.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" 54.177 + d="M 277.06936,457.71933 L 296.21629,424.5765" 54.178 + id="path2001" 54.179 + inkscape:connector-type="polyline" 54.180 + inkscape:connection-start="#g1988" 54.181 + inkscape:connection-end="#g1977" /> 54.182 + <text 54.183 + xml:space="preserve" 54.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" 54.185 + x="302.42859" 54.186 + y="515.08905" 54.187 + id="text1905"><tspan 54.188 + sodipodi:role="line" 54.189 + id="tspan1907" 54.190 + x="302.42859" 54.191 + y="515.08905">Base version</tspan></text> 54.192 + <text 54.193 + xml:space="preserve" 54.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" 54.195 + x="45.57143" 54.196 + y="374.1619" 54.197 + id="text1917"><tspan 54.198 + sodipodi:role="line" 54.199 + id="tspan1919" 54.200 + x="45.57143" 54.201 + y="374.1619">Our changes</tspan></text> 54.202 + <text 54.203 + xml:space="preserve" 54.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" 54.205 + x="385.71429" 54.206 + y="374.1619" 54.207 + id="text1921"><tspan 54.208 + sodipodi:role="line" 54.209 + id="tspan1923" 54.210 + x="385.71429" 54.211 + y="374.1619">Their changes</tspan></text> 54.212 + </g> 54.213 +</svg>
55.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 55.2 +++ b/en/tour-merge-merge.svg Mon Mar 05 20:16:36 2007 -0800 55.3 @@ -0,0 +1,380 @@ 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-merge.svg"> 55.20 + <defs 55.21 + id="defs4"> 55.22 + <marker 55.23 + inkscape:stockid="Arrow1Mstart" 55.24 + orient="auto" 55.25 + refY="0.0" 55.26 + refX="0.0" 55.27 + id="Arrow1Mstart" 55.28 + style="overflow:visible"> 55.29 + <path 55.30 + id="path2973" 55.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 " 55.32 + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none" 55.33 + transform="scale(0.4) translate(10,0)" /> 55.34 + </marker> 55.35 + <marker 55.36 + inkscape:stockid="Arrow1Mend" 55.37 + orient="auto" 55.38 + refY="0.0" 55.39 + refX="0.0" 55.40 + id="Arrow1Mend" 55.41 + style="overflow:visible;"> 55.42 + <path 55.43 + id="path3066" 55.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 " 55.45 + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;" 55.46 + transform="scale(0.4) rotate(180) translate(10,0)" /> 55.47 + </marker> 55.48 + </defs> 55.49 + <sodipodi:namedview 55.50 + id="base" 55.51 + pagecolor="#ffffff" 55.52 + bordercolor="#666666" 55.53 + borderopacity="1.0" 55.54 + gridtolerance="10000" 55.55 + guidetolerance="10" 55.56 + objecttolerance="10" 55.57 + inkscape:pageopacity="0.0" 55.58 + inkscape:pageshadow="2" 55.59 + inkscape:zoom="1.4" 55.60 + inkscape:cx="247.53795" 55.61 + inkscape:cy="871.05738" 55.62 + inkscape:document-units="px" 55.63 + inkscape:current-layer="layer1" 55.64 + inkscape:window-width="906" 55.65 + inkscape:window-height="620" 55.66 + inkscape:window-x="38" 55.67 + inkscape:window-y="95" /> 55.68 + <metadata 55.69 + id="metadata7"> 55.70 + <rdf:RDF> 55.71 + <cc:Work 55.72 + rdf:about=""> 55.73 + <dc:format>image/svg+xml</dc:format> 55.74 + <dc:type 55.75 + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 55.76 + </cc:Work> 55.77 + </rdf:RDF> 55.78 + </metadata> 55.79 + <g 55.80 + inkscape:label="Layer 1" 55.81 + inkscape:groupmode="layer" 55.82 + id="layer1"> 55.83 + <rect 55.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" 55.85 + id="rect2995" 55.86 + width="94.285713" 55.87 + height="20.714285" 55.88 + x="532.85718" 55.89 + y="203.0479" /> 55.90 + <text 55.91 + xml:space="preserve" 55.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" 55.93 + x="173.57143" 55.94 + y="443.79074" 55.95 + id="text2832"><tspan 55.96 + sodipodi:role="line" 55.97 + id="tspan2834" 55.98 + x="173.57143" 55.99 + y="443.79074" /></text> 55.100 + <rect 55.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" 55.102 + id="rect2830" 55.103 + width="94.285713" 55.104 + height="20.714285" 55.105 + x="138" 55.106 + y="297.76227" /> 55.107 + <text 55.108 + xml:space="preserve" 55.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" 55.110 + x="162.09892" 55.111 + y="311.38342" 55.112 + id="text2824"><tspan 55.113 + sodipodi:role="line" 55.114 + id="tspan2826" 55.115 + x="162.09892" 55.116 + y="311.38342" 55.117 + style="font-family:Courier"><tspan 55.118 + style="font-weight:bold" 55.119 + id="tspan2862">4</tspan>: b57f</tspan></text> 55.120 + <path 55.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" 55.122 + d="M 185.14286,343.63731 L 185.14286,319.47656" 55.123 + id="path2900" 55.124 + inkscape:connector-type="polyline" /> 55.125 + <rect 55.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" 55.127 + id="rect2863" 55.128 + width="94.285713" 55.129 + height="20.714285" 55.130 + x="91.428574" 55.131 + y="250.47656" /> 55.132 + <text 55.133 + xml:space="preserve" 55.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" 55.135 + x="116.09886" 55.136 + y="264.56592" 55.137 + id="text1965" 55.138 + transform="scale(1.000002,0.999998)"><tspan 55.139 + sodipodi:role="line" 55.140 + id="tspan1967" 55.141 + x="116.09886" 55.142 + y="264.56592" 55.143 + style="font-family:Courier"><tspan 55.144 + style="font-weight:bold" 55.145 + id="tspan1973">5</tspan>: ae13</tspan></text> 55.146 + <path 55.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" 55.148 + d="M 173.95727,296.76228 L 149.75702,272.19085" 55.149 + id="path1971" 55.150 + inkscape:connector-type="polyline" 55.151 + inkscape:connection-end="#rect2863" 55.152 + inkscape:connection-start="#rect2830" /> 55.153 + <rect 55.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" 55.155 + id="rect2911" 55.156 + width="94.285995" 55.157 + height="20.714283" 55.158 + x="186.71414" 55.159 + y="204.40514" /> 55.160 + <text 55.161 + xml:space="preserve" 55.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" 55.163 + x="210.81311" 55.164 + y="218.02673" 55.165 + id="text2913" 55.166 + transform="scale(1.000002,0.999998)"><tspan 55.167 + sodipodi:role="line" 55.168 + id="tspan2915" 55.169 + x="210.81311" 55.170 + y="218.02673" 55.171 + style="font-family:Courier"><tspan 55.172 + id="tspan1966" 55.173 + style="font-weight:bold">6</tspan>: d2b5</tspan></text> 55.174 + <path 55.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" 55.176 + d="M 191.06908,296.76228 L 227.93092,226.11942" 55.177 + id="path2919" 55.178 + inkscape:connector-type="polyline" 55.179 + inkscape:connection-start="#rect2830" /> 55.180 + <text 55.181 + xml:space="preserve" 55.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" 55.183 + x="295.28571" 55.184 + y="217.56711" 55.185 + id="text2871"><tspan 55.186 + sodipodi:role="line" 55.187 + id="tspan2873" 55.188 + x="295.28571" 55.189 + y="217.56711">tip (and head)</tspan></text> 55.190 + <text 55.191 + xml:space="preserve" 55.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" 55.193 + x="76" 55.194 + y="264.91769" 55.195 + id="text2875"><tspan 55.196 + sodipodi:role="line" 55.197 + id="tspan2877" 55.198 + x="76" 55.199 + y="264.91769" 55.200 + style="text-align:end;text-anchor:end">head</tspan></text> 55.201 + <rect 55.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" 55.203 + id="rect1913" 55.204 + width="94.285713" 55.205 + height="20.714285" 55.206 + x="138" 55.207 + y="156.90514" /> 55.208 + <path 55.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" 55.210 + d="M 144.22399,249.47657 L 179.49029,178.61943" 55.211 + id="path1915" 55.212 + inkscape:connector-type="polyline" 55.213 + inkscape:connection-start="#rect2863" 55.214 + inkscape:connection-end="#rect1913" /> 55.215 + <path 55.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" 55.217 + d="M 222.20966,203.40514 L 196.79033,178.61943" 55.218 + id="path1917" 55.219 + inkscape:connector-type="polyline" 55.220 + inkscape:connection-start="#rect2911" 55.221 + inkscape:connection-end="#rect1913" /> 55.222 + <text 55.223 + xml:space="preserve" 55.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" 55.225 + x="166.16823" 55.226 + y="168.52228" 55.227 + id="text2806"><tspan 55.228 + sodipodi:role="line" 55.229 + id="tspan2808" 55.230 + x="166.16823" 55.231 + y="168.52228" 55.232 + style="font-family:Courier">merge</tspan></text> 55.233 + <text 55.234 + xml:space="preserve" 55.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" 55.236 + x="246" 55.237 + y="162.63338" 55.238 + id="text2810"><tspan 55.239 + sodipodi:role="line" 55.240 + id="tspan2812" 55.241 + x="246" 55.242 + y="162.63338">working directory</tspan><tspan 55.243 + sodipodi:role="line" 55.244 + x="246" 55.245 + y="177.63338" 55.246 + id="tspan2814">during merge</tspan></text> 55.247 + <rect 55.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" 55.249 + id="rect2816" 55.250 + width="94.285713" 55.251 + height="20.714285" 55.252 + x="483.14636" 55.253 + y="297.76227" /> 55.254 + <text 55.255 + xml:space="preserve" 55.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" 55.257 + x="507.24527" 55.258 + y="311.38342" 55.259 + id="text2818"><tspan 55.260 + sodipodi:role="line" 55.261 + id="tspan2820" 55.262 + x="507.24527" 55.263 + y="311.38342" 55.264 + style="font-family:Courier"><tspan 55.265 + style="font-weight:bold" 55.266 + id="tspan2822">4</tspan>: b57f</tspan></text> 55.267 + <path 55.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" 55.269 + d="M 530.28921,343.6373 L 530.28921,319.47655" 55.270 + id="path2824" 55.271 + inkscape:connector-type="polyline" /> 55.272 + <rect 55.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" 55.274 + id="rect2826" 55.275 + width="94.285713" 55.276 + height="20.714285" 55.277 + x="436.57492" 55.278 + y="250.47656" /> 55.279 + <text 55.280 + xml:space="preserve" 55.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" 55.282 + x="461.24484" 55.283 + y="264.56613" 55.284 + id="text2828" 55.285 + transform="scale(1.000002,0.999998)"><tspan 55.286 + sodipodi:role="line" 55.287 + id="tspan2830" 55.288 + x="461.24484" 55.289 + y="264.56613" 55.290 + style="font-family:Courier"><tspan 55.291 + style="font-weight:bold" 55.292 + id="tspan2832">5</tspan>: ae13</tspan></text> 55.293 + <path 55.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" 55.295 + d="M 519.10362,296.76227 L 494.90337,272.19084" 55.296 + id="path2834" 55.297 + inkscape:connector-type="polyline" /> 55.298 + <rect 55.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" 55.300 + id="rect2836" 55.301 + width="94.285995" 55.302 + height="20.714283" 55.303 + x="483.14001" 55.304 + y="156.548" /> 55.305 + <text 55.306 + xml:space="preserve" 55.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" 55.308 + x="555.95911" 55.309 + y="218.02698" 55.310 + id="text2838" 55.311 + transform="scale(1.000002,0.999998)"><tspan 55.312 + sodipodi:role="line" 55.313 + id="tspan2840" 55.314 + x="555.95911" 55.315 + y="218.02698" 55.316 + style="font-family:Courier"><tspan 55.317 + id="tspan2842" 55.318 + style="font-weight:bold">6</tspan>: d2b5</tspan></text> 55.319 + <path 55.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" 55.321 + d="M 536.21543,296.76227 L 574.03453,224.76218" 55.322 + id="path2844" 55.323 + inkscape:connector-type="polyline" /> 55.324 + <text 55.325 + xml:space="preserve" 55.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" 55.327 + x="594.43207" 55.328 + y="169.78796" 55.329 + id="text2846"><tspan 55.330 + sodipodi:role="line" 55.331 + id="tspan2848" 55.332 + x="594.43207" 55.333 + y="169.78796">tip</tspan></text> 55.334 + <path 55.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" 55.336 + d="M 489.37034,249.47656 L 524.65575,178.26229" 55.337 + id="path2856" 55.338 + inkscape:connector-type="polyline" 55.339 + inkscape:connection-end="#rect2836" /> 55.340 + <path 55.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" 55.342 + d="M 567.85714,202.0479 L 542.42591,178.26229" 55.343 + id="path2858" 55.344 + inkscape:connector-type="polyline" 55.345 + inkscape:connection-end="#rect2836" 55.346 + inkscape:connection-start="#rect2995" /> 55.347 + <text 55.348 + xml:space="preserve" 55.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" 55.350 + x="504.54507" 55.351 + y="170.39714" 55.352 + id="text2860"><tspan 55.353 + sodipodi:role="line" 55.354 + id="tspan2863" 55.355 + x="504.54507" 55.356 + y="170.39714" 55.357 + style="font-family:Courier"><tspan 55.358 + style="font-weight:bold" 55.359 + id="tspan2997">7</tspan>: dba3</tspan></text> 55.360 + <text 55.361 + xml:space="preserve" 55.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" 55.363 + x="90.323105" 55.364 + y="120.21933" 55.365 + id="text2929"><tspan 55.366 + sodipodi:role="line" 55.367 + id="tspan2931" 55.368 + x="90.323105" 55.369 + y="120.21933" 55.370 + style="font-weight:bold">Working directory during merge</tspan></text> 55.371 + <text 55.372 + xml:space="preserve" 55.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" 55.374 + x="435.35226" 55.375 + y="120.21933" 55.376 + id="text2937"><tspan 55.377 + sodipodi:role="line" 55.378 + id="tspan2939" 55.379 + x="435.35226" 55.380 + y="120.21933" 55.381 + style="font-weight:bold">Repository after merge committed</tspan></text> 55.382 + </g> 55.383 +</svg>
56.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 56.2 +++ b/en/tour-merge-pull.svg Mon Mar 05 20:16:36 2007 -0800 56.3 @@ -0,0 +1,288 @@ 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-pull.svg" 56.20 + sodipodi:docbase="/home/bos/hg/hgbook/en"> 56.21 + <defs 56.22 + id="defs4"> 56.23 + <marker 56.24 + inkscape:stockid="Arrow1Mstart" 56.25 + orient="auto" 56.26 + refY="0.0" 56.27 + refX="0.0" 56.28 + id="Arrow1Mstart" 56.29 + style="overflow:visible"> 56.30 + <path 56.31 + id="path2973" 56.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 " 56.33 + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none" 56.34 + transform="scale(0.4) translate(10,0)" /> 56.35 + </marker> 56.36 + <marker 56.37 + inkscape:stockid="Arrow1Mend" 56.38 + orient="auto" 56.39 + refY="0.0" 56.40 + refX="0.0" 56.41 + id="Arrow1Mend" 56.42 + style="overflow:visible;"> 56.43 + <path 56.44 + id="path3066" 56.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 " 56.46 + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;" 56.47 + transform="scale(0.4) rotate(180) translate(10,0)" /> 56.48 + </marker> 56.49 + </defs> 56.50 + <sodipodi:namedview 56.51 + id="base" 56.52 + pagecolor="#ffffff" 56.53 + bordercolor="#666666" 56.54 + borderopacity="1.0" 56.55 + gridtolerance="10000" 56.56 + guidetolerance="10" 56.57 + objecttolerance="10" 56.58 + inkscape:pageopacity="0.0" 56.59 + inkscape:pageshadow="2" 56.60 + inkscape:zoom="1.4" 56.61 + inkscape:cx="233.63208" 56.62 + inkscape:cy="832.54381" 56.63 + inkscape:document-units="px" 56.64 + inkscape:current-layer="layer1" 56.65 + inkscape:window-width="906" 56.66 + inkscape:window-height="620" 56.67 + inkscape:window-x="237" 56.68 + inkscape:window-y="103" /> 56.69 + <metadata 56.70 + id="metadata7"> 56.71 + <rdf:RDF> 56.72 + <cc:Work 56.73 + rdf:about=""> 56.74 + <dc:format>image/svg+xml</dc:format> 56.75 + <dc:type 56.76 + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 56.77 + </cc:Work> 56.78 + </rdf:RDF> 56.79 + </metadata> 56.80 + <g 56.81 + inkscape:label="Layer 1" 56.82 + inkscape:groupmode="layer" 56.83 + id="layer1"> 56.84 + <text 56.85 + xml:space="preserve" 56.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" 56.87 + x="173.57143" 56.88 + y="443.79074" 56.89 + id="text2832"><tspan 56.90 + sodipodi:role="line" 56.91 + id="tspan2834" 56.92 + x="173.57143" 56.93 + y="443.79074" /></text> 56.94 + <rect 56.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" 56.96 + id="rect1878" 56.97 + width="94.285713" 56.98 + height="20.714285" 56.99 + x="138" 56.100 + y="479.50504" /> 56.101 + <text 56.102 + xml:space="preserve" 56.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" 56.104 + x="162.09892" 56.105 + y="493.12619" 56.106 + id="text1872"><tspan 56.107 + sodipodi:role="line" 56.108 + id="tspan1874" 56.109 + x="162.09892" 56.110 + y="493.12619" 56.111 + style="font-family:Courier"><tspan 56.112 + style="font-weight:bold" 56.113 + id="tspan1876">0</tspan>: 0a04</tspan></text> 56.114 + <rect 56.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" 56.116 + id="rect2800" 56.117 + width="94.285713" 56.118 + height="20.714285" 56.119 + x="138" 56.120 + y="432.63004" /> 56.121 + <text 56.122 + xml:space="preserve" 56.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" 56.124 + x="162.09892" 56.125 + y="446.25119" 56.126 + id="text2794"><tspan 56.127 + sodipodi:role="line" 56.128 + id="tspan2796" 56.129 + x="162.09892" 56.130 + y="446.25119" 56.131 + style="font-family:Courier"><tspan 56.132 + id="tspan2868" 56.133 + style="font-weight:bold">1</tspan>: 82e5</tspan></text> 56.134 + <rect 56.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" 56.136 + id="rect2810" 56.137 + width="94.285713" 56.138 + height="20.714285" 56.139 + x="138" 56.140 + y="385.75504" /> 56.141 + <text 56.142 + xml:space="preserve" 56.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" 56.144 + x="162.09892" 56.145 + y="399.37619" 56.146 + id="text2804"><tspan 56.147 + sodipodi:role="line" 56.148 + id="tspan2806" 56.149 + x="162.09892" 56.150 + y="399.37619" 56.151 + style="font-family:Courier"><tspan 56.152 + style="font-weight:bold" 56.153 + id="tspan2866">2</tspan>: 057d</tspan></text> 56.154 + <rect 56.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" 56.156 + id="rect2820" 56.157 + width="94.285713" 56.158 + height="20.714285" 56.159 + x="138" 56.160 + y="338.88007" /> 56.161 + <text 56.162 + xml:space="preserve" 56.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" 56.164 + x="162.09892" 56.165 + y="352.50122" 56.166 + id="text2814"><tspan 56.167 + sodipodi:role="line" 56.168 + id="tspan2816" 56.169 + x="162.09892" 56.170 + y="352.50122" 56.171 + style="font-family:Courier"><tspan 56.172 + style="font-weight:bold" 56.173 + id="tspan2864">3</tspan>: ff5d</tspan></text> 56.174 + <rect 56.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" 56.176 + id="rect2830" 56.177 + width="94.285713" 56.178 + height="20.714285" 56.179 + x="138" 56.180 + y="292.00504" /> 56.181 + <text 56.182 + xml:space="preserve" 56.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" 56.184 + x="162.09892" 56.185 + y="305.62619" 56.186 + id="text2824"><tspan 56.187 + sodipodi:role="line" 56.188 + id="tspan2826" 56.189 + x="162.09892" 56.190 + y="305.62619" 56.191 + style="font-family:Courier"><tspan 56.192 + style="font-weight:bold" 56.193 + id="tspan2862">4</tspan>: b57f</tspan></text> 56.194 + <path 56.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" 56.196 + d="M 185.14286,478.50504 L 185.14286,454.34432" 56.197 + id="path2894" 56.198 + inkscape:connector-type="polyline" /> 56.199 + <path 56.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" 56.201 + d="M 185.14286,431.63004 L 185.14286,407.46932" 56.202 + id="path2896" 56.203 + inkscape:connector-type="polyline" /> 56.204 + <path 56.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" 56.206 + d="M 185.14286,384.75504 L 185.14286,360.59435" 56.207 + id="path2898" 56.208 + inkscape:connector-type="polyline" /> 56.209 + <path 56.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" 56.211 + d="M 185.14286,337.88007 L 185.14286,313.71932" 56.212 + id="path2900" 56.213 + inkscape:connector-type="polyline" /> 56.214 + <rect 56.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" 56.216 + id="rect2863" 56.217 + width="94.285713" 56.218 + height="20.714285" 56.219 + x="91.428574" 56.220 + y="244.71933" /> 56.221 + <text 56.222 + xml:space="preserve" 56.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" 56.224 + x="116.09886" 56.225 + y="258.80865" 56.226 + id="text1965" 56.227 + transform="scale(1.000002,0.999998)"><tspan 56.228 + sodipodi:role="line" 56.229 + id="tspan1967" 56.230 + x="116.09886" 56.231 + y="258.80865" 56.232 + style="font-family:Courier"><tspan 56.233 + style="font-weight:bold" 56.234 + id="tspan1973">5</tspan>: ae13</tspan></text> 56.235 + <path 56.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" 56.237 + d="M 173.95727,291.00504 L 149.75702,266.43361" 56.238 + id="path1971" 56.239 + inkscape:connector-type="polyline" 56.240 + inkscape:connection-end="#rect2863" 56.241 + inkscape:connection-start="#rect2830" /> 56.242 + <rect 56.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" 56.244 + id="rect2911" 56.245 + width="94.285995" 56.246 + height="20.714283" 56.247 + x="186.71414" 56.248 + y="198.6479" /> 56.249 + <text 56.250 + xml:space="preserve" 56.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" 56.252 + x="210.81311" 56.253 + y="212.26949" 56.254 + id="text2913" 56.255 + transform="scale(1.000002,0.999998)"><tspan 56.256 + sodipodi:role="line" 56.257 + id="tspan2915" 56.258 + x="210.81311" 56.259 + y="212.26949" 56.260 + style="font-family:Courier"><tspan 56.261 + id="tspan1966" 56.262 + style="font-weight:bold">6</tspan>: d2b5</tspan></text> 56.263 + <path 56.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" 56.265 + d="M 191.06908,291.00504 L 227.93092,220.36218" 56.266 + id="path2919" 56.267 + inkscape:connector-type="polyline" 56.268 + inkscape:connection-start="#rect2830" /> 56.269 + <text 56.270 + xml:space="preserve" 56.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" 56.272 + x="295.28571" 56.273 + y="211.80988" 56.274 + id="text2871"><tspan 56.275 + sodipodi:role="line" 56.276 + id="tspan2873" 56.277 + x="295.28571" 56.278 + y="211.80988">tip (and head)</tspan></text> 56.279 + <text 56.280 + xml:space="preserve" 56.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" 56.282 + x="76" 56.283 + y="259.16046" 56.284 + id="text2875"><tspan 56.285 + sodipodi:role="line" 56.286 + id="tspan2877" 56.287 + x="76" 56.288 + y="259.16046" 56.289 + style="text-align:end;text-anchor:end">head</tspan></text> 56.290 + </g> 56.291 +</svg>
57.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 57.2 +++ b/en/tour-merge-sep-repos.svg Mon Mar 05 20:16:36 2007 -0800 57.3 @@ -0,0 +1,466 @@ 57.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?> 57.5 +<!-- Created with Inkscape (http://www.inkscape.org/) --> 57.6 +<svg 57.7 + xmlns:dc="http://purl.org/dc/elements/1.1/" 57.8 + xmlns:cc="http://web.resource.org/cc/" 57.9 + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 57.10 + xmlns:svg="http://www.w3.org/2000/svg" 57.11 + xmlns="http://www.w3.org/2000/svg" 57.12 + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" 57.13 + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" 57.14 + width="744.09448819" 57.15 + height="1052.3622047" 57.16 + id="svg2" 57.17 + sodipodi:version="0.32" 57.18 + inkscape:version="0.44.1" 57.19 + sodipodi:docname="tour-merge-sep-repos.svg"> 57.20 + <defs 57.21 + id="defs4"> 57.22 + <marker 57.23 + inkscape:stockid="Arrow1Mstart" 57.24 + orient="auto" 57.25 + refY="0.0" 57.26 + refX="0.0" 57.27 + id="Arrow1Mstart" 57.28 + style="overflow:visible"> 57.29 + <path 57.30 + id="path2973" 57.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 " 57.32 + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none" 57.33 + transform="scale(0.4) translate(10,0)" /> 57.34 + </marker> 57.35 + <marker 57.36 + inkscape:stockid="Arrow1Mend" 57.37 + orient="auto" 57.38 + refY="0.0" 57.39 + refX="0.0" 57.40 + id="Arrow1Mend" 57.41 + style="overflow:visible;"> 57.42 + <path 57.43 + id="path3066" 57.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 " 57.45 + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;" 57.46 + transform="scale(0.4) rotate(180) translate(10,0)" /> 57.47 + </marker> 57.48 + </defs> 57.49 + <sodipodi:namedview 57.50 + id="base" 57.51 + pagecolor="#ffffff" 57.52 + bordercolor="#666666" 57.53 + borderopacity="1.0" 57.54 + gridtolerance="10000" 57.55 + guidetolerance="10" 57.56 + objecttolerance="10" 57.57 + inkscape:pageopacity="0.0" 57.58 + inkscape:pageshadow="2" 57.59 + inkscape:zoom="1.4" 57.60 + inkscape:cx="307.20351" 57.61 + inkscape:cy="716.87911" 57.62 + inkscape:document-units="px" 57.63 + inkscape:current-layer="layer1" 57.64 + inkscape:window-width="906" 57.65 + inkscape:window-height="620" 57.66 + inkscape:window-x="5" 57.67 + inkscape:window-y="49" /> 57.68 + <metadata 57.69 + id="metadata7"> 57.70 + <rdf:RDF> 57.71 + <cc:Work 57.72 + rdf:about=""> 57.73 + <dc:format>image/svg+xml</dc:format> 57.74 + <dc:type 57.75 + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 57.76 + </cc:Work> 57.77 + </rdf:RDF> 57.78 + </metadata> 57.79 + <g 57.80 + inkscape:label="Layer 1" 57.81 + inkscape:groupmode="layer" 57.82 + id="layer1"> 57.83 + <text 57.84 + xml:space="preserve" 57.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" 57.86 + x="173.57143" 57.87 + y="443.79074" 57.88 + id="text2832"><tspan 57.89 + sodipodi:role="line" 57.90 + id="tspan2834" 57.91 + x="173.57143" 57.92 + y="443.79074" /></text> 57.93 + <rect 57.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" 57.95 + id="rect1878" 57.96 + width="94.285713" 57.97 + height="20.714285" 57.98 + x="138" 57.99 + y="479.50504" /> 57.100 + <text 57.101 + xml:space="preserve" 57.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" 57.103 + x="162.09892" 57.104 + y="493.12619" 57.105 + id="text1872"><tspan 57.106 + sodipodi:role="line" 57.107 + id="tspan1874" 57.108 + x="162.09892" 57.109 + y="493.12619" 57.110 + style="font-family:Courier"><tspan 57.111 + style="font-weight:bold" 57.112 + id="tspan1876">0</tspan>: 0a04</tspan></text> 57.113 + <rect 57.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" 57.115 + id="rect2800" 57.116 + width="94.285713" 57.117 + height="20.714285" 57.118 + x="138" 57.119 + y="432.63004" /> 57.120 + <text 57.121 + xml:space="preserve" 57.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" 57.123 + x="162.09892" 57.124 + y="446.25119" 57.125 + id="text2794"><tspan 57.126 + sodipodi:role="line" 57.127 + id="tspan2796" 57.128 + x="162.09892" 57.129 + y="446.25119" 57.130 + style="font-family:Courier"><tspan 57.131 + id="tspan2868" 57.132 + style="font-weight:bold">1</tspan>: 82e5</tspan></text> 57.133 + <rect 57.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" 57.135 + id="rect2810" 57.136 + width="94.285713" 57.137 + height="20.714285" 57.138 + x="138" 57.139 + y="385.75504" /> 57.140 + <text 57.141 + xml:space="preserve" 57.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" 57.143 + x="162.09892" 57.144 + y="399.37619" 57.145 + id="text2804"><tspan 57.146 + sodipodi:role="line" 57.147 + id="tspan2806" 57.148 + x="162.09892" 57.149 + y="399.37619" 57.150 + style="font-family:Courier"><tspan 57.151 + style="font-weight:bold" 57.152 + id="tspan2866">2</tspan>: 057d</tspan></text> 57.153 + <rect 57.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" 57.155 + id="rect2820" 57.156 + width="94.285713" 57.157 + height="20.714285" 57.158 + x="138" 57.159 + y="338.88007" /> 57.160 + <text 57.161 + xml:space="preserve" 57.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" 57.163 + x="162.09892" 57.164 + y="352.50122" 57.165 + id="text2814"><tspan 57.166 + sodipodi:role="line" 57.167 + id="tspan2816" 57.168 + x="162.09892" 57.169 + y="352.50122" 57.170 + style="font-family:Courier"><tspan 57.171 + style="font-weight:bold" 57.172 + id="tspan2864">3</tspan>: ff5d</tspan></text> 57.173 + <rect 57.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" 57.175 + id="rect2830" 57.176 + width="94.285713" 57.177 + height="20.714285" 57.178 + x="138" 57.179 + y="292.00504" /> 57.180 + <text 57.181 + xml:space="preserve" 57.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" 57.183 + x="162.09892" 57.184 + y="305.62619" 57.185 + id="text2824"><tspan 57.186 + sodipodi:role="line" 57.187 + id="tspan2826" 57.188 + x="162.09892" 57.189 + y="305.62619" 57.190 + style="font-family:Courier"><tspan 57.191 + style="font-weight:bold" 57.192 + id="tspan2862">4</tspan>: b57f</tspan></text> 57.193 + <path 57.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" 57.195 + d="M 185.14286,478.50504 L 185.14286,454.34432" 57.196 + id="path2894" 57.197 + inkscape:connector-type="polyline" /> 57.198 + <path 57.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" 57.200 + d="M 185.14286,431.63004 L 185.14286,407.46932" 57.201 + id="path2896" 57.202 + inkscape:connector-type="polyline" /> 57.203 + <path 57.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" 57.205 + d="M 185.14286,384.75504 L 185.14286,360.59435" 57.206 + id="path2898" 57.207 + inkscape:connector-type="polyline" /> 57.208 + <path 57.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" 57.210 + d="M 185.14286,337.88007 L 185.14286,313.71932" 57.211 + id="path2900" 57.212 + inkscape:connector-type="polyline" /> 57.213 + <rect 57.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" 57.215 + id="rect1963" 57.216 + width="94.285995" 57.217 + height="20.714283" 57.218 + x="138" 57.219 + y="245.18723" /> 57.220 + <text 57.221 + xml:space="preserve" 57.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" 57.223 + x="162.09877" 57.224 + y="258.80865" 57.225 + id="text1965" 57.226 + transform="scale(1.000002,0.999998)"><tspan 57.227 + sodipodi:role="line" 57.228 + id="tspan1967" 57.229 + x="162.09877" 57.230 + y="258.80865" 57.231 + style="font-family:Courier"><tspan 57.232 + style="font-weight:bold" 57.233 + id="tspan1973">5</tspan>: ae13</tspan></text> 57.234 + <path 57.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" 57.236 + d="M 185.143,291.06218 L 185.143,266.90143" 57.237 + id="path1971" 57.238 + inkscape:connector-type="polyline" /> 57.239 + <text 57.240 + xml:space="preserve" 57.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" 57.242 + x="136.90039" 57.243 + y="232.25546" 57.244 + id="text2921"><tspan 57.245 + sodipodi:role="line" 57.246 + id="tspan2923" 57.247 + x="136.90039" 57.248 + y="232.25546">my-hello</tspan></text> 57.249 + <rect 57.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" 57.251 + id="rect2863" 57.252 + width="94.285713" 57.253 + height="20.714285" 57.254 + x="370.71414" 57.255 + y="479.49289" /> 57.256 + <text 57.257 + xml:space="preserve" 57.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" 57.259 + x="394.81305" 57.260 + y="493.11404" 57.261 + id="text2865"><tspan 57.262 + sodipodi:role="line" 57.263 + id="tspan2867" 57.264 + x="394.81305" 57.265 + y="493.11404" 57.266 + style="font-family:Courier"><tspan 57.267 + style="font-weight:bold" 57.268 + id="tspan2869">0</tspan>: 0a04</tspan></text> 57.269 + <rect 57.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" 57.271 + id="rect2871" 57.272 + width="94.285713" 57.273 + height="20.714285" 57.274 + x="370.71414" 57.275 + y="432.61789" /> 57.276 + <text 57.277 + xml:space="preserve" 57.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" 57.279 + x="394.81305" 57.280 + y="446.23904" 57.281 + id="text2873"><tspan 57.282 + sodipodi:role="line" 57.283 + id="tspan2875" 57.284 + x="394.81305" 57.285 + y="446.23904" 57.286 + style="font-family:Courier"><tspan 57.287 + id="tspan2877" 57.288 + style="font-weight:bold">1</tspan>: 82e5</tspan></text> 57.289 + <rect 57.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" 57.291 + id="rect2879" 57.292 + width="94.285713" 57.293 + height="20.714285" 57.294 + x="370.71414" 57.295 + y="385.74289" /> 57.296 + <text 57.297 + xml:space="preserve" 57.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" 57.299 + x="394.81305" 57.300 + y="399.36404" 57.301 + id="text2881"><tspan 57.302 + sodipodi:role="line" 57.303 + id="tspan2883" 57.304 + x="394.81305" 57.305 + y="399.36404" 57.306 + style="font-family:Courier"><tspan 57.307 + style="font-weight:bold" 57.308 + id="tspan2885">2</tspan>: 057d</tspan></text> 57.309 + <rect 57.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" 57.311 + id="rect2887" 57.312 + width="94.285713" 57.313 + height="20.714285" 57.314 + x="370.71414" 57.315 + y="338.86792" /> 57.316 + <text 57.317 + xml:space="preserve" 57.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" 57.319 + x="394.81305" 57.320 + y="352.48907" 57.321 + id="text2889"><tspan 57.322 + sodipodi:role="line" 57.323 + id="tspan2891" 57.324 + x="394.81305" 57.325 + y="352.48907" 57.326 + style="font-family:Courier"><tspan 57.327 + style="font-weight:bold" 57.328 + id="tspan2893">3</tspan>: ff5d</tspan></text> 57.329 + <rect 57.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" 57.331 + id="rect2895" 57.332 + width="94.285713" 57.333 + height="20.714285" 57.334 + x="370.71414" 57.335 + y="291.99289" /> 57.336 + <text 57.337 + xml:space="preserve" 57.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" 57.339 + x="394.81305" 57.340 + y="305.61404" 57.341 + id="text2897"><tspan 57.342 + sodipodi:role="line" 57.343 + id="tspan2899" 57.344 + x="394.81305" 57.345 + y="305.61404" 57.346 + style="font-family:Courier"><tspan 57.347 + style="font-weight:bold" 57.348 + id="tspan2901">4</tspan>: b57f</tspan></text> 57.349 + <path 57.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" 57.351 + d="M 417.85701,478.4929 L 417.85701,454.33218" 57.352 + id="path2903" 57.353 + inkscape:connector-type="polyline" /> 57.354 + <path 57.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" 57.356 + d="M 417.85701,431.6179 L 417.85701,407.45718" 57.357 + id="path2905" 57.358 + inkscape:connector-type="polyline" /> 57.359 + <path 57.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" 57.361 + d="M 417.85701,384.7429 L 417.85701,360.58221" 57.362 + id="path2907" 57.363 + inkscape:connector-type="polyline" /> 57.364 + <path 57.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" 57.366 + d="M 417.85701,337.86793 L 417.85701,313.70718" 57.367 + id="path2909" 57.368 + inkscape:connector-type="polyline" /> 57.369 + <rect 57.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" 57.371 + id="rect2911" 57.372 + width="94.285995" 57.373 + height="20.714283" 57.374 + x="370.71414" 57.375 + y="245.17511" /> 57.376 + <text 57.377 + xml:space="preserve" 57.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" 57.379 + x="394.81274" 57.380 + y="258.79678" 57.381 + id="text2913" 57.382 + transform="scale(1.000002,0.999998)"><tspan 57.383 + sodipodi:role="line" 57.384 + id="tspan2915" 57.385 + x="394.81274" 57.386 + y="258.79678" 57.387 + style="font-family:Courier"><tspan 57.388 + style="font-weight:bold" 57.389 + id="tspan2917">5</tspan>: d2b5</tspan></text> 57.390 + <path 57.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" 57.392 + d="M 417.85715,291.05004 L 417.85715,266.88929" 57.393 + id="path2919" 57.394 + inkscape:connector-type="polyline" /> 57.395 + <text 57.396 + xml:space="preserve" 57.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" 57.398 + x="369.61453" 57.399 + y="232.25546" 57.400 + id="text2925"><tspan 57.401 + sodipodi:role="line" 57.402 + id="tspan2927" 57.403 + x="369.61453" 57.404 + y="232.25546">my-new-hello</tspan></text> 57.405 + <text 57.406 + xml:space="preserve" 57.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" 57.408 + x="300.54352" 57.409 + y="252.12723" 57.410 + id="text2933"><tspan 57.411 + sodipodi:role="line" 57.412 + id="tspan2935" 57.413 + x="300.54352" 57.414 + y="252.12723" 57.415 + style="text-align:center;text-anchor:middle">newest changes</tspan><tspan 57.416 + sodipodi:role="line" 57.417 + x="300.54352" 57.418 + y="267.12723" 57.419 + style="text-align:center;text-anchor:middle" 57.420 + id="tspan3132">differ</tspan></text> 57.421 + <text 57.422 + xml:space="preserve" 57.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" 57.424 + x="262.15436" 57.425 + y="398.37112" 57.426 + id="text2929"><tspan 57.427 + sodipodi:role="line" 57.428 + x="262.15436" 57.429 + y="398.37112" 57.430 + id="tspan3013" 57.431 + style="text-align:start;text-anchor:start">common history</tspan></text> 57.432 + <g 57.433 + id="g3107" 57.434 + transform="translate(0,0.855744)"> 57.435 + <path 57.436 + id="path3101" 57.437 + d="M 300.35713,381.29075 L 300.35713,304.50504" 57.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" /> 57.439 + <path 57.440 + id="path3105" 57.441 + d="M 291.07142,301.64789 L 309.28571,301.64789" 57.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" /> 57.443 + </g> 57.444 + <path 57.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" 57.446 + d="M 300.53571,486.38926 L 300.53571,409.60355" 57.447 + id="path3113" /> 57.448 + <path 57.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" 57.450 + d="M 291.25,488.49641 L 309.46429,488.49641" 57.451 + id="path3115" /> 57.452 + <text 57.453 + xml:space="preserve" 57.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" 57.455 + x="480.71429" 57.456 + y="250.91507" 57.457 + id="text1949"><tspan 57.458 + sodipodi:role="line" 57.459 + id="tspan1951" 57.460 + x="480.71429" 57.461 + y="250.91507" 57.462 + style="text-align:start;text-anchor:start">head revision</tspan><tspan 57.463 + sodipodi:role="line" 57.464 + x="480.71429" 57.465 + y="265.91507" 57.466 + id="tspan1953" 57.467 + style="text-align:start;text-anchor:start">(has no children)</tspan></text> 57.468 + </g> 57.469 +</svg>
58.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 58.2 +++ b/en/tour-merge.tex Mon Mar 05 20:16:36 2007 -0800 58.3 @@ -0,0 +1,283 @@ 58.4 +\chapter{A tour of Mercurial: merging work} 58.5 +\label{chap:tour-merge} 58.6 + 58.7 +We've now covered cloning a repository, making changes in a 58.8 +repository, and pulling or pushing changes from one repository into 58.9 +another. Our next step is \emph{merging} changes from separate 58.10 +repositories. 58.11 + 58.12 +\section{Merging streams of work} 58.13 + 58.14 +Merging is a fundamental part of working with a distributed revision 58.15 +control tool. 58.16 +\begin{itemize} 58.17 +\item Alice and Bob each have a personal copy of a repository for a 58.18 + project they're collaborating on. Alice fixes a bug in her 58.19 + repository; Bob adds a new feature in his. They want the shared 58.20 + repository to contain both the bug fix and the new feature. 58.21 +\item I frequently work on several different tasks for a single 58.22 + project at once, each safely isolated in its own repository. 58.23 + Working this way means that I often need to merge one piece of my 58.24 + own work with another. 58.25 +\end{itemize} 58.26 + 58.27 +Because merging is such a common thing to need to do, Mercurial makes 58.28 +it easy. Let's walk through the process. We'll begin by cloning yet 58.29 +another repository (see how often they spring up?) and making a change 58.30 +in it. 58.31 +\interaction{tour.merge.clone} 58.32 +We should now have two copies of \filename{hello.c} with different 58.33 +contents. The histories of the two repositories have also diverged, 58.34 +as illustrated in figure~\ref{fig:tour-merge:sep-repos}. 58.35 +\interaction{tour.merge.cat} 58.36 + 58.37 +\begin{figure}[ht] 58.38 + \centering 58.39 + \grafix{tour-merge-sep-repos} 58.40 + \caption{Divergent recent histories of the \dirname{my-hello} and 58.41 + \dirname{my-new-hello} repositories} 58.42 + \label{fig:tour-merge:sep-repos} 58.43 +\end{figure} 58.44 + 58.45 +We already know that pulling changes from our \dirname{my-hello} 58.46 +repository will have no effect on the working directory. 58.47 +\interaction{tour.merge.pull} 58.48 +However, the \hgcmd{pull} command says something about ``heads''. 58.49 + 58.50 +\subsection{Head changesets} 58.51 + 58.52 +A head is a change that has no descendants, or children, as they're 58.53 +also known. The tip revision is thus a head, because the newest 58.54 +revision in a repository doesn't have any children, but a repository 58.55 +can contain more than one head. 58.56 + 58.57 +\begin{figure}[ht] 58.58 + \centering 58.59 + \grafix{tour-merge-pull} 58.60 + \caption{Repository contents after pulling from \dirname{my-hello} into 58.61 + \dirname{my-new-hello}} 58.62 + \label{fig:tour-merge:pull} 58.63 +\end{figure} 58.64 + 58.65 +In figure~\ref{fig:tour-merge:pull}, you can see the effect of the 58.66 +pull from \dirname{my-hello} into \dirname{my-new-hello}. The history 58.67 +that was already present in \dirname{my-new-hello} is untouched, but a 58.68 +new revision has been added. By referring to 58.69 +figure~\ref{fig:tour-merge:sep-repos}, we can see that the 58.70 +\emph{changeset ID} remains the same in the new repository, but the 58.71 +\emph{revision number} has changed. (This, incidentally, is a fine 58.72 +example of why it's not safe to use revision numbers when discussing 58.73 +changesets.) We can view the heads in a repository using the 58.74 +\hgcmd{heads} command. 58.75 +\interaction{tour.merge.heads} 58.76 + 58.77 +\subsection{Performing the merge} 58.78 + 58.79 +What happens if we try to use the normal \hgcmd{update} command to 58.80 +update to the new tip? 58.81 +\interaction{tour.merge.update} 58.82 +Mercurial is telling us that the \hgcmd{update} command won't do a 58.83 +merge; it won't update the working directory when it thinks we might 58.84 +be wanting to do a merge, unless we force it to do so. Instead, we 58.85 +use the \hgcmd{merge} command to merge the two heads. 58.86 +\interaction{tour.merge.merge} 58.87 + 58.88 +\begin{figure}[ht] 58.89 + \centering 58.90 + \grafix{tour-merge-merge} 58.91 + \caption{Working directory and repository during merge, and 58.92 + following commit} 58.93 + \label{fig:tour-merge:merge} 58.94 +\end{figure} 58.95 + 58.96 +This updates the working directory so that it contains changes from 58.97 +\emph{both} heads, which is reflected in both the output of 58.98 +\hgcmd{parents} and the contents of \filename{hello.c}. 58.99 +\interaction{tour.merge.parents} 58.100 + 58.101 +\subsection{Committing the results of the merge} 58.102 + 58.103 +Whenever we've done a merge, \hgcmd{parents} will display two parents 58.104 +until we \hgcmd{commit} the results of the merge. 58.105 +\interaction{tour.merge.commit} 58.106 +We now have a new tip revision; notice that it has \emph{both} of 58.107 +our former heads as its parents. These are the same revisions that 58.108 +were previously displayed by \hgcmd{parents}. 58.109 +\interaction{tour.merge.tip} 58.110 +In figure~\ref{fig:tour-merge:merge}, you can see a representation of 58.111 +what happens to the working directory during the merge, and how this 58.112 +affects the repository when the commit happens. During the merge, the 58.113 +working directory has two parent changesets, and these become the 58.114 +parents of the new changeset. 58.115 + 58.116 +\section{Merging conflicting changes} 58.117 + 58.118 +Most merges are simple affairs, but sometimes you'll find yourself 58.119 +merging changes where each modifies the same portions of the same 58.120 +files. Unless both modifications are identical, this results in a 58.121 +\emph{conflict}, where you have to decide how to reconcile the 58.122 +different changes into something coherent. 58.123 + 58.124 +\begin{figure}[ht] 58.125 + \centering 58.126 + \grafix{tour-merge-conflict} 58.127 + \caption{Conflicting changes to a document} 58.128 + \label{fig:tour-merge:conflict} 58.129 +\end{figure} 58.130 + 58.131 +Figure~\ref{fig:tour-merge:conflict} illustrates an instance of two 58.132 +conflicting changes to a document. We started with a single version 58.133 +of the file; then we made some changes; while someone else made 58.134 +different changes to the same text. Our task in resolving the 58.135 +conflicting changes is to decide what the file should look like. 58.136 + 58.137 +Mercurial doesn't have a built-in facility for handling conflicts. 58.138 +Instead, it runs an external program called \command{hgmerge}. This 58.139 +is a shell script that is bundled with Mercurial; you can change it to 58.140 +behave however you please. What it does by default is try to find one 58.141 +of several different merging tools that are likely to be installed on 58.142 +your system. It first tries a few fully automatic merging tools; if 58.143 +these don't succeed (because the resolution process requires human 58.144 +guidance) or aren't present, the script tries a few different 58.145 +graphical merging tools. 58.146 + 58.147 +It's also possible to get Mercurial to run another program or script 58.148 +instead of \command{hgmerge}, by setting the \envar{HGMERGE} 58.149 +environment variable to the name of your preferred program. 58.150 + 58.151 +\subsection{Using a graphical merge tool} 58.152 + 58.153 +My preferred graphical merge tool is \command{kdiff3}, which I'll use 58.154 +to describe the features that are common to graphical file merging 58.155 +tools. You can see a screenshot of \command{kdiff3} in action in 58.156 +figure~\ref{fig:tour-merge:kdiff3}. The kind of merge it is 58.157 +performing is called a \emph{three-way merge}, because there are three 58.158 +different versions of the file of interest to us. The tool thus 58.159 +splits the upper portion of the window into three panes: 58.160 +\begin{itemize} 58.161 +\item At the left is the \emph{base} version of the file, i.e.~the 58.162 + most recent version from which the two versions we're trying to 58.163 + merge are descended. 58.164 +\item In the middle is ``our'' version of the file, with the contents 58.165 + that we modified. 58.166 +\item On the right is ``their'' version of the file, the one that 58.167 + from the changeset that we're trying to merge with. 58.168 +\end{itemize} 58.169 +In the pane below these is the current \emph{result} of the merge. 58.170 +Our task is to replace all of the red text, which indicates unresolved 58.171 +conflicts, with some sensible merger of the ``ours'' and ``theirs'' 58.172 +versions of the file. 58.173 + 58.174 +All four of these panes are \emph{locked together}; if we scroll 58.175 +vertically or horizontally in any of them, the others are updated to 58.176 +display the corresponding sections of their respective files. 58.177 + 58.178 +\begin{figure}[ht] 58.179 + \centering 58.180 + \grafix{kdiff3} 58.181 + \caption{Using \command{kdiff3} to merge versions of a file} 58.182 + \label{fig:tour-merge:kdiff3} 58.183 +\end{figure} 58.184 + 58.185 +For each conflicting portion of the file, we can choose to resolve 58.186 +thhe conflict using some combination of text from the base version, 58.187 +ours, or theirs. We can also manually edit the merged file at any 58.188 +time, in case we need to make further modifications. 58.189 + 58.190 +There are \emph{many} file merging tools available, too many to cover 58.191 +here. They vary in which platforms they are available for, and in 58.192 +their particular strengths and weaknesses. Most are tuned for merging 58.193 +files containing plain text, while a few are aimed at specialised file 58.194 +formats (generally XML). 58.195 + 58.196 +\subsection{A worked example} 58.197 + 58.198 +In this example, we will reproduce the file modification history of 58.199 +figure~\ref{fig:tour-merge:conflict} above. Let's begin by creating a 58.200 +repository with a base version of our document. 58.201 +\interaction{tour-merge-conflict.wife} 58.202 +We'll clone the repository and make a change to the file. 58.203 +\interaction{tour-merge-conflict.cousin} 58.204 +And another clone, to simulate someone else making a change to the 58.205 +file. (This hints at the idea that it's not all that unusual to merge 58.206 +with yourself when you isolate tasks in separate repositories, and 58.207 +indeed to find and resolve conflicts while doing so.) 58.208 +\interaction{tour-merge-conflict.son} 58.209 +Having created two different versions of the file, we'll set up an 58.210 +environment suitable for running our merge. 58.211 +\interaction{tour-merge-conflict.pull} 58.212 + 58.213 +In this example, I won't use Mercurial's normal \command{hgmerge} 58.214 +program to do the merge, because it would drop my nice automated 58.215 +example-running tool into a graphical user interface. Instead, I'll 58.216 +set \envar{HGMERGE} to tell Mercurial to use the non-interactive 58.217 +\command{merge} command. This is bundled with many Unix-like systems. 58.218 +If you're following this example on your computer, don't bother 58.219 +setting \envar{HGMERGE}. 58.220 +\interaction{tour-merge-conflict.merge} 58.221 +Because \command{merge} can't resolve the conflicting changes, it 58.222 +leaves \emph{merge markers} inside the file that has conflicts, 58.223 +indicating which lines have conflicts, and whether they came from our 58.224 +version of the file or theirs. 58.225 + 58.226 +Mercurial can tell from the way \command{merge} exits that it wasn't 58.227 +able to merge successfully, so it tells us what commands we'll need to 58.228 +run if we want to redo the merging operation. This could be useful 58.229 +if, for example, we were running a graphical merge tool and quit 58.230 +because we were confused or realised we had made a mistake. 58.231 + 58.232 +If automatic or manual merges fail, there's nothing to prevent us from 58.233 +``fixing up'' the affected files ourselves, and committing the results 58.234 +of our merge: 58.235 +\interaction{tour-merge-conflict.commit} 58.236 + 58.237 +\section{Simplifying the pull-merge-commit 58.238 + sequence} 58.239 + 58.240 +The process of merging changes as outlined above is straightforward, 58.241 +but requires running three commands in sequence. 58.242 +\begin{codesample2} 58.243 + hg pull 58.244 + hg merge 58.245 + hg commit -m 'Merged remote changes' 58.246 +\end{codesample2} 58.247 +In the case of the final commit, you also need to enter a commit 58.248 +message, which is almost always going to be a piece of uninteresting 58.249 +``boilerplate'' text. 58.250 + 58.251 +It would be nice to reduce the number of steps needed, if this were 58.252 +possible. Indeed, Mercurial is distributed with an extension called 58.253 +\hgext{fetch} that does just this. 58.254 + 58.255 +Mercurial provides a flexible extension mechanism that lets people 58.256 +extend its functionality, while keeping the core of Mercurial small 58.257 +and easy to deal with. Some extensions add new commands that you can 58.258 +use from the command line, while others work ``behind the scenes,'' 58.259 +for example adding capabilities to the server. 58.260 + 58.261 +The \hgext{fetch} extension adds a new command called, not 58.262 +surprisingly, \hgcmd{fetch}. This extension acts as a combination of 58.263 +\hgcmd{pull}, \hgcmd{update} and \hgcmd{merge}. It begins by pulling 58.264 +changes from another repository into the current repository. If it 58.265 +finds that the changes added a new head to the repository, it begins a 58.266 +merge, then commits the result of the merge with an 58.267 +automatically-generated commit message. If no new heads were added, 58.268 +it updates the working directory to the new tip changeset. 58.269 + 58.270 +Enabling the \hgext{fetch} extension is easy. Edit your 58.271 +\sfilename{.hgrc}, and either go to the \rcsection{extensions} section 58.272 +or create an \rcsection{extensions} section. Then add a line that 58.273 +simply reads ``\Verb+fetch +''. 58.274 +\begin{codesample2} 58.275 + [extensions] 58.276 + fetch = 58.277 +\end{codesample2} 58.278 +(Normally, on the right-hand side of the ``\texttt{=}'' would appear 58.279 +the location of the extension, but since the \hgext{fetch} extension 58.280 +is in the standard distribution, Mercurial knows where to search for 58.281 +it.) 58.282 + 58.283 +%%% Local Variables: 58.284 +%%% mode: latex 58.285 +%%% TeX-master: "00book" 58.286 +%%% End:
59.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 59.2 +++ b/en/undo-manual-merge.dot Mon Mar 05 20:16:36 2007 -0800 59.3 @@ -0,0 +1,8 @@ 59.4 +digraph undo_manual { 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 + "third change" -> "manual\nmerge"; 59.10 + backout -> "manual\nmerge"; 59.11 +}
60.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 60.2 +++ b/en/undo-manual.dot Mon Mar 05 20:16:36 2007 -0800 60.3 @@ -0,0 +1,6 @@ 60.4 +digraph undo_manual { 60.5 + "first change" -> "second change"; 60.6 + "second change" -> "third change"; 60.7 + backout [label="back out\nsecond change", shape=box]; 60.8 + "second change" -> backout; 60.9 +}
61.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 61.2 +++ b/en/undo-non-tip.dot Mon Mar 05 20:16:36 2007 -0800 61.3 @@ -0,0 +1,9 @@ 61.4 +digraph undo_non_tip { 61.5 + "first change" -> "second change"; 61.6 + "second change" -> "third change"; 61.7 + backout [label="back out\nsecond change", shape=box]; 61.8 + "second change" -> backout; 61.9 + merge [label="automated\nmerge", shape=box]; 61.10 + "third change" -> merge; 61.11 + backout -> merge; 61.12 +}
62.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 62.2 +++ b/en/undo-simple.dot Mon Mar 05 20:16:36 2007 -0800 62.3 @@ -0,0 +1,4 @@ 62.4 +digraph undo_simple { 62.5 + "first change" -> "second change"; 62.6 + "second change" -> "back out\nsecond change"; 62.7 +}
63.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 63.2 +++ b/en/undo.tex Mon Mar 05 20:16:36 2007 -0800 63.3 @@ -0,0 +1,750 @@ 63.4 +\chapter{Finding and fixing your mistakes} 63.5 +\label{chap:undo} 63.6 + 63.7 +To err might be human, but to really handle the consequences well 63.8 +takes a top-notch revision control system. In this chapter, we'll 63.9 +discuss some of the techniques you can use when you find that a 63.10 +problem has crept into your project. Mercurial has some highly 63.11 +capable features that will help you to isolate the sources of 63.12 +problems, and to handle them appropriately. 63.13 + 63.14 +\section{Erasing local history} 63.15 + 63.16 +\subsection{The accidental commit} 63.17 + 63.18 +I have the occasional but persistent problem of typing rather more 63.19 +quickly than I can think, which sometimes results in me committing a 63.20 +changeset that is either incomplete or plain wrong. In my case, the 63.21 +usual kind of incomplete changeset is one in which I've created a new 63.22 +source file, but forgotten to \hgcmd{add} it. A ``plain wrong'' 63.23 +changeset is not as common, but no less annoying. 63.24 + 63.25 +\subsection{Rolling back a transaction} 63.26 +\label{sec:undo:rollback} 63.27 + 63.28 +In section~\ref{sec:concepts:txn}, I mentioned that Mercurial treats 63.29 +each modification of a repository as a \emph{transaction}. Every time 63.30 +you commit a changeset or pull changes from another repository, 63.31 +Mercurial remembers what you did. You can undo, or \emph{roll back}, 63.32 +exactly one of these actions using the \hgcmd{rollback} command. 63.33 + 63.34 +Here's a mistake that I often find myself making: committing a change 63.35 +in which I've created a new file, but forgotten to \hgcmd{add} it. 63.36 +\interaction{rollback.commit} 63.37 +Looking at the output of \hgcmd{status} after the commit immediately 63.38 +confirms the error. 63.39 +\interaction{rollback.status} 63.40 +The commit captured the changes to the file \filename{a}, but not the 63.41 +new file \filename{b}. If I were to push this changeset to a 63.42 +repository that I shared with a colleague, the chances are high that 63.43 +something in \filename{a} would refer to \filename{b}, which would not 63.44 +be present in their repository when they pulled my changes. I would 63.45 +thus become the object of some indignation. 63.46 + 63.47 +However, luck is with me---I've caught my error before I pushed the 63.48 +changeset. I use the \hgcmd{rollback} command, and Mercurial makes 63.49 +that last changeset vanish. 63.50 +\interaction{rollback.rollback} 63.51 +Notice that the changeset is no longer present in the repository's 63.52 +history, and the working directory once again thinks that the file 63.53 +\filename{a} is modified. The commit and rollback have left the 63.54 +working directory exactly as it was prior to the commit; the changeset 63.55 +has been completely erased. I can now safely \hgcmd{add} the file 63.56 +\filename{b}, and rerun my commit. 63.57 +\interaction{rollback.add} 63.58 + 63.59 +\subsection{The erroneous pull} 63.60 + 63.61 +It's common practice with Mercurial to maintain separate development 63.62 +branches of a project in different repositories. Your development 63.63 +team might have one shared repository for your project's ``0.9'' 63.64 +release, and another, containing different changes, for the ``1.0'' 63.65 +release. 63.66 + 63.67 +Given this, you can imagine that the consequences could be messy if 63.68 +you had a local ``0.9'' repository, and accidentally pulled changes 63.69 +from the shared ``1.0'' repository into it. At worst, you could be 63.70 +paying insufficient attention, and push those changes into the shared 63.71 +``0.9'' tree, confusing your entire team (but don't worry, we'll 63.72 +return to this horror scenario later). However, it's more likely that 63.73 +you'll notice immediately, because Mercurial will display the URL it's 63.74 +pulling from, or you will see it pull a suspiciously large number of 63.75 +changes into the repository. 63.76 + 63.77 +The \hgcmd{rollback} command will work nicely to expunge all of the 63.78 +changesets that you just pulled. Mercurial groups all changes from 63.79 +one \hgcmd{pull} into a single transaction, so one \hgcmd{rollback} is 63.80 +all you need to undo this mistake. 63.81 + 63.82 +\subsection{Rolling back is useless once you've pushed} 63.83 + 63.84 +The value of the \hgcmd{rollback} command drops to zero once you've 63.85 +pushed your changes to another repository. Rolling back a change 63.86 +makes it disappear entirely, but \emph{only} in the repository in 63.87 +which you perform the \hgcmd{rollback}. Because a rollback eliminates 63.88 +history, there's no way for the disappearance of a change to propagate 63.89 +between repositories. 63.90 + 63.91 +If you've pushed a change to another repository---particularly if it's 63.92 +a shared repository---it has essentially ``escaped into the wild,'' 63.93 +and you'll have to recover from your mistake in a different way. What 63.94 +will happen if you push a changeset somewhere, then roll it back, then 63.95 +pull from the repository you pushed to, is that the changeset will 63.96 +reappear in your repository. 63.97 + 63.98 +(If you absolutely know for sure that the change you want to roll back 63.99 +is the most recent change in the repository that you pushed to, 63.100 +\emph{and} you know that nobody else could have pulled it from that 63.101 +repository, you can roll back the changeset there, too, but you really 63.102 +should really not rely on this working reliably. If you do this, 63.103 +sooner or later a change really will make it into a repository that 63.104 +you don't directly control (or have forgotten about), and come back to 63.105 +bite you.) 63.106 + 63.107 +\subsection{You can only roll back once} 63.108 + 63.109 +Mercurial stores exactly one transaction in its transaction log; that 63.110 +transaction is the most recent one that occurred in the repository. 63.111 +This means that you can only roll back one transaction. If you expect 63.112 +to be able to roll back one transaction, then its predecessor, this is 63.113 +not the behaviour you will get. 63.114 +\interaction{rollback.twice} 63.115 +Once you've rolled back one transaction in a repository, you can't 63.116 +roll back again in that repository until you perform another commit or 63.117 +pull. 63.118 + 63.119 +\section{Reverting the mistaken change} 63.120 + 63.121 +If you make a modification to a file, and decide that you really 63.122 +didn't want to change the file at all, and you haven't yet committed 63.123 +your changes, the \hgcmd{revert} command is the one you'll need. It 63.124 +looks at the changeset that's the parent of the working directory, and 63.125 +restores the contents of the file to their state as of that changeset. 63.126 +(That's a long-winded way of saying that, in the normal case, it 63.127 +undoes your modifications.) 63.128 + 63.129 +Let's illustrate how the \hgcmd{revert} command works with yet another 63.130 +small example. We'll begin by modifying a file that Mercurial is 63.131 +already tracking. 63.132 +\interaction{daily.revert.modify} 63.133 +If we don't want that change, we can simply \hgcmd{revert} the file. 63.134 +\interaction{daily.revert.unmodify} 63.135 +The \hgcmd{revert} command provides us with an extra degree of safety 63.136 +by saving our modified file with a \filename{.orig} extension. 63.137 +\interaction{daily.revert.status} 63.138 + 63.139 +Here is a summary of the cases that the \hgcmd{revert} command can 63.140 +deal with. We will describe each of these in more detail in the 63.141 +section that follows. 63.142 +\begin{itemize} 63.143 +\item If you modify a file, it will restore the file to its unmodified 63.144 + state. 63.145 +\item If you \hgcmd{add} a file, it will undo the ``added'' state of 63.146 + the file, but leave the file itself untouched. 63.147 +\item If you delete a file without telling Mercurial, it will restore 63.148 + the file to its unmodified contents. 63.149 +\item If you use the \hgcmd{remove} command to remove a file, it will 63.150 + undo the ``removed'' state of the file, and restore the file to its 63.151 + unmodified contents. 63.152 +\end{itemize} 63.153 + 63.154 +\subsection{File management errors} 63.155 +\label{sec:undo:mgmt} 63.156 + 63.157 +The \hgcmd{revert} command is useful for more than just modified 63.158 +files. It lets you reverse the results of all of Mercurial's file 63.159 +management commands---\hgcmd{add}, \hgcmd{remove}, and so on. 63.160 + 63.161 +If you \hgcmd{add} a file, then decide that in fact you don't want 63.162 +Mercurial to track it, use \hgcmd{revert} to undo the add. Don't 63.163 +worry; Mercurial will not modify the file in any way. It will just 63.164 +``unmark'' the file. 63.165 +\interaction{daily.revert.add} 63.166 + 63.167 +Similarly, if you ask Mercurial to \hgcmd{remove} a file, you can use 63.168 +\hgcmd{revert} to restore it to the contents it had as of the parent 63.169 +of the working directory. 63.170 +\interaction{daily.revert.remove} 63.171 +This works just as well for a file that you deleted by hand, without 63.172 +telling Mercurial (recall that in Mercurial terminology, this kind of 63.173 +file is called ``missing''). 63.174 +\interaction{daily.revert.missing} 63.175 + 63.176 +If you revert a \hgcmd{copy}, the copied-to file remains in your 63.177 +working directory afterwards, untracked. Since a copy doesn't affect 63.178 +the copied-from file in any way, Mercurial doesn't do anything with 63.179 +the copied-from file. 63.180 +\interaction{daily.revert.copy} 63.181 + 63.182 +\subsubsection{A slightly special case: reverting a rename} 63.183 + 63.184 +If you \hgcmd{rename} a file, there is one small detail that 63.185 +you should remember. When you \hgcmd{revert} a rename, it's not 63.186 +enough to provide the name of the renamed-to file, as you can see 63.187 +here. 63.188 +\interaction{daily.revert.rename} 63.189 +As you can see from the output of \hgcmd{status}, the renamed-to file 63.190 +is no longer identified as added, but the renamed-\emph{from} file is 63.191 +still removed! This is counter-intuitive (at least to me), but at 63.192 +least it's easy to deal with. 63.193 +\interaction{daily.revert.rename-orig} 63.194 +So remember, to revert a \hgcmd{rename}, you must provide \emph{both} 63.195 +the source and destination names. 63.196 + 63.197 +(By the way, if you rename a file, then modify the renamed-to file, 63.198 +then revert both components of the rename, when Mercurial restores the 63.199 +file that was removed as part of the rename, it will be unmodified. 63.200 +If you need the modifications in the renamed-to file to show up in the 63.201 +renamed-from file, don't forget to copy them over.) 63.202 + 63.203 +These fiddly aspects of reverting a rename arguably constitute a small 63.204 +bug in Mercurial. 63.205 + 63.206 +\section{Dealing with committed changes} 63.207 + 63.208 +Consider a case where you have committed a change $a$, and another 63.209 +change $b$ on top of it; you then realise that change $a$ was 63.210 +incorrect. Mercurial lets you ``back out'' an entire changeset 63.211 +automatically, and building blocks that let you reverse part of a 63.212 +changeset by hand. 63.213 + 63.214 +Before you read this section, here's something to keep in mind: the 63.215 +\hgcmd{backout} command undoes changes by \emph{adding} history, not 63.216 +by modifying or erasing it. It's the right tool to use if you're 63.217 +fixing bugs, but not if you're trying to undo some change that has 63.218 +catastrophic consequences. To deal with those, see 63.219 +section~\ref{sec:undo:aaaiiieee}. 63.220 + 63.221 +\subsection{Backing out a changeset} 63.222 + 63.223 +The \hgcmd{backout} command lets you ``undo'' the effects of an entire 63.224 +changeset in an automated fashion. Because Mercurial's history is 63.225 +immutable, this command \emph{does not} get rid of the changeset you 63.226 +want to undo. Instead, it creates a new changeset that 63.227 +\emph{reverses} the effect of the to-be-undone changeset. 63.228 + 63.229 +The operation of the \hgcmd{backout} command is a little intricate, so 63.230 +let's illustrate it with some examples. First, we'll create a 63.231 +repository with some simple changes. 63.232 +\interaction{backout.init} 63.233 + 63.234 +The \hgcmd{backout} command takes a single changeset ID as its 63.235 +argument; this is the changeset to back out. Normally, 63.236 +\hgcmd{backout} will drop you into a text editor to write a commit 63.237 +message, so you can record why you're backing the change out. In this 63.238 +example, we provide a commit message on the command line using the 63.239 +\hgopt{backout}{-m} option. 63.240 + 63.241 +\subsection{Backing out the tip changeset} 63.242 + 63.243 +We're going to start by backing out the last changeset we committed. 63.244 +\interaction{backout.simple} 63.245 +You can see that the second line from \filename{myfile} is no longer 63.246 +present. Taking a look at the output of \hgcmd{log} gives us an idea 63.247 +of what the \hgcmd{backout} command has done. 63.248 +\interaction{backout.simple.log} 63.249 +Notice that the new changeset that \hgcmd{backout} has created is a 63.250 +child of the changeset we backed out. It's easier to see this in 63.251 +figure~\ref{fig:undo:backout}, which presents a graphical view of the 63.252 +change history. As you can see, the history is nice and linear. 63.253 + 63.254 +\begin{figure}[htb] 63.255 + \centering 63.256 + \grafix{undo-simple} 63.257 + \caption{Backing out a change using the \hgcmd{backout} command} 63.258 + \label{fig:undo:backout} 63.259 +\end{figure} 63.260 + 63.261 +\subsection{Backing out a non-tip change} 63.262 + 63.263 +If you want to back out a change other than the last one you 63.264 +committed, pass the \hgopt{backout}{--merge} option to the 63.265 +\hgcmd{backout} command. 63.266 +\interaction{backout.non-tip.clone} 63.267 +This makes backing out any changeset a ``one-shot'' operation that's 63.268 +usually simple and fast. 63.269 +\interaction{backout.non-tip.backout} 63.270 + 63.271 +If you take a look at the contents of \filename{myfile} after the 63.272 +backout finishes, you'll see that the first and third changes are 63.273 +present, but not the second. 63.274 +\interaction{backout.non-tip.cat} 63.275 + 63.276 +As the graphical history in figure~\ref{fig:undo:backout-non-tip} 63.277 +illustrates, Mercurial actually commits \emph{two} changes in this 63.278 +kind of situation (the box-shaped nodes are the ones that Mercurial 63.279 +commits automatically). Before Mercurial begins the backout process, 63.280 +it first remembers what the current parent of the working directory 63.281 +is. It then backs out the target changeset, and commits that as a 63.282 +changeset. Finally, it merges back to the previous parent of the 63.283 +working directory, and commits the result of the merge. 63.284 + 63.285 +\begin{figure}[htb] 63.286 + \centering 63.287 + \grafix{undo-non-tip} 63.288 + \caption{Automated backout of a non-tip change using the \hgcmd{backout} command} 63.289 + \label{fig:undo:backout-non-tip} 63.290 +\end{figure} 63.291 + 63.292 +The result is that you end up ``back where you were'', only with some 63.293 +extra history that undoes the effect of the changeset you wanted to 63.294 +back out. 63.295 + 63.296 +\subsubsection{Always use the \hgopt{backout}{--merge} option} 63.297 + 63.298 +In fact, since the \hgopt{backout}{--merge} option will do the ``right 63.299 +thing'' whether or not the changeset you're backing out is the tip 63.300 +(i.e.~it won't try to merge if it's backing out the tip, since there's 63.301 +no need), you should \emph{always} use this option when you run the 63.302 +\hgcmd{backout} command. 63.303 + 63.304 +\subsection{Gaining more control of the backout process} 63.305 + 63.306 +While I've recommended that you always use the 63.307 +\hgopt{backout}{--merge} option when backing out a change, the 63.308 +\hgcmd{backout} command lets you decide how to merge a backout 63.309 +changeset. Taking control of the backout process by hand is something 63.310 +you will rarely need to do, but it can be useful to understand what 63.311 +the \hgcmd{backout} command is doing for you automatically. To 63.312 +illustrate this, let's clone our first repository, but omit the 63.313 +backout change that it contains. 63.314 + 63.315 +\interaction{backout.manual.clone} 63.316 +As with our earlier example, We'll commit a third changeset, then back 63.317 +out its parent, and see what happens. 63.318 +\interaction{backout.manual.backout} 63.319 +Our new changeset is again a descendant of the changeset we backout 63.320 +out; it's thus a new head, \emph{not} a descendant of the changeset 63.321 +that was the tip. The \hgcmd{backout} command was quite explicit in 63.322 +telling us this. 63.323 +\interaction{backout.manual.log} 63.324 + 63.325 +Again, it's easier to see what has happened by looking at a graph of 63.326 +the revision history, in figure~\ref{fig:undo:backout-manual}. This 63.327 +makes it clear that when we use \hgcmd{backout} to back out a change 63.328 +other than the tip, Mercurial adds a new head to the repository (the 63.329 +change it committed is box-shaped). 63.330 + 63.331 +\begin{figure}[htb] 63.332 + \centering 63.333 + \grafix{undo-manual} 63.334 + \caption{Backing out a change using the \hgcmd{backout} command} 63.335 + \label{fig:undo:backout-manual} 63.336 +\end{figure} 63.337 + 63.338 +After the \hgcmd{backout} command has completed, it leaves the new 63.339 +``backout'' changeset as the parent of the working directory. 63.340 +\interaction{backout.manual.parents} 63.341 +Now we have two isolated sets of changes. 63.342 +\interaction{backout.manual.heads} 63.343 + 63.344 +Let's think about what we expect to see as the contents of 63.345 +\filename{myfile} now. The first change should be present, because 63.346 +we've never backed it out. The second change should be missing, as 63.347 +that's the change we backed out. Since the history graph shows the 63.348 +third change as a separate head, we \emph{don't} expect to see the 63.349 +third change present in \filename{myfile}. 63.350 +\interaction{backout.manual.cat} 63.351 +To get the third change back into the file, we just do a normal merge 63.352 +of our two heads. 63.353 +\interaction{backout.manual.merge} 63.354 +Afterwards, the graphical history of our repository looks like 63.355 +figure~\ref{fig:undo:backout-manual-merge}. 63.356 + 63.357 +\begin{figure}[htb] 63.358 + \centering 63.359 + \grafix{undo-manual-merge} 63.360 + \caption{Manually merging a backout change} 63.361 + \label{fig:undo:backout-manual-merge} 63.362 +\end{figure} 63.363 + 63.364 +\subsection{Why \hgcmd{backout} works as it does} 63.365 + 63.366 +Here's a brief description of how the \hgcmd{backout} command works. 63.367 +\begin{enumerate} 63.368 +\item It ensures that the working directory is ``clean'', i.e.~that 63.369 + the output of \hgcmd{status} would be empty. 63.370 +\item It remembers the current parent of the working directory. Let's 63.371 + call this changeset \texttt{orig} 63.372 +\item It does the equivalent of a \hgcmd{update} to sync the working 63.373 + directory to the changeset you want to back out. Let's call this 63.374 + changeset \texttt{backout} 63.375 +\item It finds the parent of that changeset. Let's call that 63.376 + changeset \texttt{parent}. 63.377 +\item For each file that the \texttt{backout} changeset affected, it 63.378 + does the equivalent of a \hgcmdargs{revert}{-r parent} on that file, 63.379 + to restore it to the contents it had before that changeset was 63.380 + committed. 63.381 +\item It commits the result as a new changeset. This changeset has 63.382 + \texttt{backout} as its parent. 63.383 +\item If you specify \hgopt{backout}{--merge} on the command line, it 63.384 + merges with \texttt{orig}, and commits the result of the merge. 63.385 +\end{enumerate} 63.386 + 63.387 +An alternative way to implement the \hgcmd{backout} command would be 63.388 +to \hgcmd{export} the to-be-backed-out changeset as a diff, then use 63.389 +the \cmdopt{patch}{--reverse} option to the \command{patch} command to 63.390 +reverse the effect of the change without fiddling with the working 63.391 +directory. This sounds much simpler, but it would not work nearly as 63.392 +well. 63.393 + 63.394 +The reason that \hgcmd{backout} does an update, a commit, a merge, and 63.395 +another commit is to give the merge machinery the best chance to do a 63.396 +good job when dealing with all the changes \emph{between} the change 63.397 +you're backing out and the current tip. 63.398 + 63.399 +If you're backing out a changeset that's~100 revisions back in your 63.400 +project's history, the chances that the \command{patch} command will 63.401 +be able to apply a reverse diff cleanly are not good, because 63.402 +intervening changes are likely to have ``broken the context'' that 63.403 +\command{patch} uses to determine whether it can apply a patch (if 63.404 +this sounds like gibberish, see \ref{sec:mq:patch} for a 63.405 +discussion of the \command{patch} command). Also, Mercurial's merge 63.406 +machinery will handle files and directories being renamed, permission 63.407 +changes, and modifications to binary files, none of which 63.408 +\command{patch} can deal with. 63.409 + 63.410 +\section{Changes that should never have been} 63.411 +\label{sec:undo:aaaiiieee} 63.412 + 63.413 +Most of the time, the \hgcmd{backout} command is exactly what you need 63.414 +if you want to undo the effects of a change. It leaves a permanent 63.415 +record of exactly what you did, both when committing the original 63.416 +changeset and when you cleaned up after it. 63.417 + 63.418 +On rare occasions, though, you may find that you've committed a change 63.419 +that really should not be present in the repository at all. For 63.420 +example, it would be very unusual, and usually considered a mistake, 63.421 +to commit a software project's object files as well as its source 63.422 +files. Object files have almost no intrinsic value, and they're 63.423 +\emph{big}, so they increase the size of the repository and the amount 63.424 +of time it takes to clone or pull changes. 63.425 + 63.426 +Before I discuss the options that you have if you commit a ``brown 63.427 +paper bag'' change (the kind that's so bad that you want to pull a 63.428 +brown paper bag over your head), let me first discuss some approaches 63.429 +that probably won't work. 63.430 + 63.431 +Since Mercurial treats history as accumulative---every change builds 63.432 +on top of all changes that preceded it---you generally can't just make 63.433 +disastrous changes disappear. The one exception is when you've just 63.434 +committed a change, and it hasn't been pushed or pulled into another 63.435 +repository. That's when you can safely use the \hgcmd{rollback} 63.436 +command, as I detailed in section~\ref{sec:undo:rollback}. 63.437 + 63.438 +After you've pushed a bad change to another repository, you 63.439 +\emph{could} still use \hgcmd{rollback} to make your local copy of the 63.440 +change disappear, but it won't have the consequences you want. The 63.441 +change will still be present in the remote repository, so it will 63.442 +reappear in your local repository the next time you pull. 63.443 + 63.444 +If a situation like this arises, and you know which repositories your 63.445 +bad change has propagated into, you can \emph{try} to get rid of the 63.446 +changeefrom \emph{every} one of those repositories. This is, of 63.447 +course, not a satisfactory solution: if you miss even a single 63.448 +repository while you're expunging, the change is still ``in the 63.449 +wild'', and could propagate further. 63.450 + 63.451 +If you've committed one or more changes \emph{after} the change that 63.452 +you'd like to see disappear, your options are further reduced. 63.453 +Mercurial doesn't provide a way to ``punch a hole'' in history, 63.454 +leaving changesets intact. 63.455 + 63.456 +XXX This needs filling out. The \texttt{hg-replay} script in the 63.457 +\texttt{examples} directory works, but doesn't handle merge 63.458 +changesets. Kind of an important omission. 63.459 + 63.460 +\section{Finding the source of a bug} 63.461 + 63.462 +While it's all very well to be able to back out a changeset that 63.463 +introduced a bug, this requires that you know which changeset to back 63.464 +out. Mercurial provides an invaluable extension, called 63.465 +\hgext{bisect}, that helps you to automate this process and accomplish 63.466 +it very efficiently. 63.467 + 63.468 +The idea behind the \hgext{bisect} extension is that a changeset has 63.469 +introduced some change of behaviour that you can identify with a 63.470 +simple binary test. You don't know which piece of code introduced the 63.471 +change, but you know how to test for the presence of the bug. The 63.472 +\hgext{bisect} extension uses your test to direct its search for the 63.473 +changeset that introduced the code that caused the bug. 63.474 + 63.475 +Here are a few scenarios to help you understand how you might apply this 63.476 +extension. 63.477 +\begin{itemize} 63.478 +\item The most recent version of your software has a bug that you 63.479 + remember wasn't present a few weeks ago, but you don't know when it 63.480 + was introduced. Here, your binary test checks for the presence of 63.481 + that bug. 63.482 +\item You fixed a bug in a rush, and now it's time to close the entry 63.483 + in your team's bug database. The bug database requires a changeset 63.484 + ID when you close an entry, but you don't remember which changeset 63.485 + you fixed the bug in. Once again, your binary test checks for the 63.486 + presence of the bug. 63.487 +\item Your software works correctly, but runs~15\% slower than the 63.488 + last time you measured it. You want to know which changeset 63.489 + introduced the performance regression. In this case, your binary 63.490 + test measures the performance of your software, to see whether it's 63.491 + ``fast'' or ``slow''. 63.492 +\item The sizes of the components of your project that you ship 63.493 + exploded recently, and you suspect that something changed in the way 63.494 + you build your project. 63.495 +\end{itemize} 63.496 + 63.497 +From these examples, it should be clear that the \hgext{bisect} 63.498 +extension is not useful only for finding the sources of bugs. You can 63.499 +use it to find any ``emergent property'' of a repository (anything 63.500 +that you can't find from a simple text search of the files in the 63.501 +tree) for which you can write a binary test. 63.502 + 63.503 +We'll introduce a little bit of terminology here, just to make it 63.504 +clear which parts of the search process are your responsibility, and 63.505 +which are Mercurial's. A \emph{test} is something that \emph{you} run 63.506 +when \hgext{bisect} chooses a changeset. A \emph{probe} is what 63.507 +\hgext{bisect} runs to tell whether a revision is good. Finally, 63.508 +we'll use the word ``bisect'', as both a noun and a verb, to stand in 63.509 +for the phrase ``search using the \hgext{bisect} extension''. 63.510 + 63.511 +One simple way to automate the searching process would be simply to 63.512 +probe every changeset. However, this scales poorly. If it took ten 63.513 +minutes to test a single changeset, and you had 10,000 changesets in 63.514 +your repository, the exhaustive approach would take on average~35 63.515 +\emph{days} to find the changeset that introduced a bug. Even if you 63.516 +knew that the bug was introduced by one of the last 500 changesets, 63.517 +and limited your search to those, you'd still be looking at over 40 63.518 +hours to find the changeset that introduced your bug. 63.519 + 63.520 +What the \emph{bisect} extension does is use its knowledge of the 63.521 +``shape'' of your project's revision history to perform a search in 63.522 +time proportional to the \emph{logarithm} of the number of changesets 63.523 +to check (the kind of search it performs is called a dichotomic 63.524 +search). With this approach, searching through 10,000 changesets will 63.525 +take less than two hours, even at ten minutes per test. Limit your 63.526 +search to the last 500 changesets, and it will take less than an hour. 63.527 + 63.528 +The \hgext{bisect} extension is aware of the ``branchy'' nature of a 63.529 +Mercurial project's revision history, so it has no problems dealing 63.530 +with branches, merges, or multiple heads in a repoository. It can 63.531 +prune entire branches of history with a single probe, which is how it 63.532 +operates so efficiently. 63.533 + 63.534 +\subsection{Using the \hgext{bisect} extension} 63.535 + 63.536 +Here's an example of \hgext{bisect} in action. To keep the core of 63.537 +Mercurial simple, \hgext{bisect} is packaged as an extension; this 63.538 +means that it won't be present unless you explicitly enable it. To do 63.539 +this, edit your \hgrc\ and add the following section header (if it's 63.540 +not already present): 63.541 +\begin{codesample2} 63.542 + [extensions] 63.543 +\end{codesample2} 63.544 +Then add a line to this section to enable the extension: 63.545 +\begin{codesample2} 63.546 + hbisect = 63.547 +\end{codesample2} 63.548 +\begin{note} 63.549 + That's right, there's a ``\texttt{h}'' at the front of the name of 63.550 + the \hgext{bisect} extension. The reason is that Mercurial is 63.551 + written in Python, and uses a standard Python package called 63.552 + \texttt{bisect}. If you omit the ``\texttt{h}'' from the name 63.553 + ``\texttt{hbisect}'', Mercurial will erroneously find the standard 63.554 + Python \texttt{bisect} package, and try to use it as a Mercurial 63.555 + extension. This won't work, and Mercurial will crash repeatedly 63.556 + until you fix the spelling in your \hgrc. Ugh. 63.557 +\end{note} 63.558 + 63.559 +Now let's create a repository, so that we can try out the 63.560 +\hgext{bisect} extension in isolation. 63.561 +\interaction{bisect.init} 63.562 +We'll simulate a project that has a bug in it in a simple-minded way: 63.563 +create trivial changes in a loop, and nominate one specific change 63.564 +that will have the ``bug''. This loop creates 50 changesets, each 63.565 +adding a single file to the repository. We'll represent our ``bug'' 63.566 +with a file that contains the text ``i have a gub''. 63.567 +\interaction{bisect.commits} 63.568 + 63.569 +The next thing that we'd like to do is figure out how to use the 63.570 +\hgext{bisect} extension. We can use Mercurial's normal built-in help 63.571 +mechanism for this. 63.572 +\interaction{bisect.help} 63.573 + 63.574 +The \hgext{bisect} extension works in steps. Each step proceeds as follows. 63.575 +\begin{enumerate} 63.576 +\item You run your binary test. 63.577 + \begin{itemize} 63.578 + \item If the test succeeded, you tell \hgext{bisect} by running the 63.579 + \hgcmdargs{bisect}{good} command. 63.580 + \item If it failed, use the \hgcmdargs{bisect}{bad} command to let 63.581 + the \hgext{bisect} extension know. 63.582 + \end{itemize} 63.583 +\item The extension uses your information to decide which changeset to 63.584 + test next. 63.585 +\item It updates the working directory to that changeset, and the 63.586 + process begins again. 63.587 +\end{enumerate} 63.588 +The process ends when \hgext{bisect} identifies a unique changeset 63.589 +that marks the point where your test transitioned from ``succeeding'' 63.590 +to ``failing''. 63.591 + 63.592 +To start the search, we must run the \hgcmdargs{bisect}{init} command. 63.593 +\interaction{bisect.search.init} 63.594 + 63.595 +In our case, the binary test we use is simple: we check to see if any 63.596 +file in the repository contains the string ``i have a gub''. If it 63.597 +does, this changeset contains the change that ``caused the bug''. By 63.598 +convention, a changeset that has the property we're searching for is 63.599 +``bad'', while one that doesn't is ``good''. 63.600 + 63.601 +Most of the time, the revision to which the working directory is 63.602 +synced (usually the tip) already exhibits the problem introduced by 63.603 +the buggy change, so we'll mark it as ``bad''. 63.604 +\interaction{bisect.search.bad-init} 63.605 + 63.606 +Our next task is to nominate a changeset that we know \emph{doesn't} 63.607 +have the bug; the \hgext{bisect} extension will ``bracket'' its search 63.608 +between the first pair of good and bad changesets. In our case, we 63.609 +know that revision~10 didn't have the bug. (I'll have more words 63.610 +about choosing the first ``good'' changeset later.) 63.611 +\interaction{bisect.search.good-init} 63.612 + 63.613 +Notice that this command printed some output. 63.614 +\begin{itemize} 63.615 +\item It told us how many changesets it must consider before it can 63.616 + identify the one that introduced the bug, and how many tests that 63.617 + will require. 63.618 +\item It updated the working directory to the next changeset to test, 63.619 + and told us which changeset it's testing. 63.620 +\end{itemize} 63.621 + 63.622 +We now run our test in the working directory. We use the 63.623 +\command{grep} command to see if our ``bad'' file is present in the 63.624 +working directory. If it is, this revision is bad; if not, this 63.625 +revision is good. 63.626 +\interaction{bisect.search.step1} 63.627 + 63.628 +This test looks like a perfect candidate for automation, so let's turn 63.629 +it into a shell function. 63.630 +\interaction{bisect.search.mytest} 63.631 +We can now run an entire test step with a single command, 63.632 +\texttt{mytest}. 63.633 +\interaction{bisect.search.step2} 63.634 +A few more invocations of our canned test step command, and we're 63.635 +done. 63.636 +\interaction{bisect.search.rest} 63.637 + 63.638 +Even though we had~40 changesets to search through, the \hgext{bisect} 63.639 +extension let us find the changeset that introduced our ``bug'' with 63.640 +only five tests. Because the number of tests that the \hgext{bisect} 63.641 +extension grows logarithmically with the number of changesets to 63.642 +search, the advantage that it has over the ``brute force'' search 63.643 +approach increases with every changeset you add. 63.644 + 63.645 +\subsection{Cleaning up after your search} 63.646 + 63.647 +When you're finished using the \hgext{bisect} extension in a 63.648 +repository, you can use the \hgcmdargs{bisect}{reset} command to drop 63.649 +the information it was using to drive your search. The extension 63.650 +doesn't use much space, so it doesn't matter if you forget to run this 63.651 +command. However, \hgext{bisect} won't let you start a new search in 63.652 +that repository until you do a \hgcmdargs{bisect}{reset}. 63.653 +\interaction{bisect.search.reset} 63.654 + 63.655 +\section{Tips for finding bugs effectively} 63.656 + 63.657 +\subsection{Give consistent input} 63.658 + 63.659 +The \hgext{bisect} extension requires that you correctly report the 63.660 +result of every test you perform. If you tell it that a test failed 63.661 +when it really succeeded, it \emph{might} be able to detect the 63.662 +inconsistency. If it can identify an inconsistency in your reports, 63.663 +it will tell you that a particular changeset is both good and bad. 63.664 +However, it can't do this perfectly; it's about as likely to report 63.665 +the wrong changeset as the source of the bug. 63.666 + 63.667 +\subsection{Automate as much as possible} 63.668 + 63.669 +When I started using the \hgext{bisect} extension, I tried a few times 63.670 +to run my tests by hand, on the command line. This is an approach 63.671 +that I, at least, am not suited to. After a few tries, I found that I 63.672 +was making enough mistakes that I was having to restart my searches 63.673 +several times before finally getting correct results. 63.674 + 63.675 +My initial problems with driving the \hgext{bisect} extension by hand 63.676 +occurred even with simple searches on small repositories; if the 63.677 +problem you're looking for is more subtle, or the number of tests that 63.678 +\hgext{bisect} must perform increases, the likelihood of operator 63.679 +error ruining the search is much higher. Once I started automating my 63.680 +tests, I had much better results. 63.681 + 63.682 +The key to automated testing is twofold: 63.683 +\begin{itemize} 63.684 +\item always test for the same symptom, and 63.685 +\item always feed consistent input to the \hgcmd{bisect} command. 63.686 +\end{itemize} 63.687 +In my tutorial example above, the \command{grep} command tests for the 63.688 +symptom, and the \texttt{if} statement takes the result of this check 63.689 +and ensures that we always feed the same input to the \hgcmd{bisect} 63.690 +command. The \texttt{mytest} function marries these together in a 63.691 +reproducible way, so that every test is uniform and consistent. 63.692 + 63.693 +\subsection{Check your results} 63.694 + 63.695 +Because the output of a \hgext{bisect} search is only as good as the 63.696 +input you give it, don't take the changeset it reports as the 63.697 +absolute truth. A simple way to cross-check its report is to manually 63.698 +run your test at each of the following changesets: 63.699 +\begin{itemize} 63.700 +\item The changeset that it reports as the first bad revision. Your 63.701 + test should still report this as bad. 63.702 +\item The parent of that changeset (either parent, if it's a merge). 63.703 + Your test should report this changeset as good. 63.704 +\item A child of that changeset. Your test should report this 63.705 + changeset as bad. 63.706 +\end{itemize} 63.707 + 63.708 +\subsection{Beware interference between bugs} 63.709 + 63.710 +It's possible that your search for one bug could be disrupted by the 63.711 +presence of another. For example, let's say your software crashes at 63.712 +revision 100, and worked correctly at revision 50. Unknown to you, 63.713 +someone else introduced a different crashing bug at revision 60, and 63.714 +fixed it at revision 80. This could distort your results in one of 63.715 +several ways. 63.716 + 63.717 +It is possible that this other bug completely ``masks'' yours, which 63.718 +is to say that it occurs before your bug has a chance to manifest 63.719 +itself. If you can't avoid that other bug (for example, it prevents 63.720 +your project from building), and so can't tell whether your bug is 63.721 +present in a particular changeset, the \hgext{bisect} extension cannot 63.722 +help you directly. Instead, you'll need to manually avoid the 63.723 +changesets where that bug is present, and do separate searches 63.724 +``around'' it. 63.725 + 63.726 +A different problem could arise if your test for a bug's presence is 63.727 +not specific enough. If you checks for ``my program crashes'', then 63.728 +both your crashing bug and an unrelated crashing bug that masks it 63.729 +will look like the same thing, and mislead \hgext{bisect}. 63.730 + 63.731 +\subsection{Bracket your search lazily} 63.732 + 63.733 +Choosing the first ``good'' and ``bad'' changesets that will mark the 63.734 +end points of your search is often easy, but it bears a little 63.735 +discussion neverthheless. From the perspective of \hgext{bisect}, the 63.736 +``newest'' changeset is conventionally ``bad'', and the older 63.737 +changeset is ``good''. 63.738 + 63.739 +If you're having trouble remembering when a suitable ``good'' change 63.740 +was, so that you can tell \hgext{bisect}, you could do worse than 63.741 +testing changesets at random. Just remember to eliminate contenders 63.742 +that can't possibly exhibit the bug (perhaps because the feature with 63.743 +the bug isn't present yet) and those where another problem masks the 63.744 +bug (as I discussed above). 63.745 + 63.746 +Even if you end up ``early'' by thousands of changesets or months of 63.747 +history, you will only add a handful of tests to the total number that 63.748 +\hgext{bisect} must perform, thanks to its logarithmic behaviour. 63.749 + 63.750 +%%% Local Variables: 63.751 +%%% mode: latex 63.752 +%%% TeX-master: "00book" 63.753 +%%% End:
64.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 64.2 +++ b/en/wdir-after-commit.svg Mon Mar 05 20:16:36 2007 -0800 64.3 @@ -0,0 +1,394 @@ 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-after-commit.svg"> 64.22 + <defs 64.23 + id="defs5973"> 64.24 + <linearGradient 64.25 + inkscape:collect="always" 64.26 + xlink:href="#linearGradient6049" 64.27 + id="linearGradient6445" 64.28 + gradientUnits="userSpaceOnUse" 64.29 + gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)" 64.30 + x1="333.91171" 64.31 + y1="488.79077" 64.32 + x2="508.94543" 64.33 + y2="263.79077" /> 64.34 + <marker 64.35 + inkscape:stockid="Arrow1Mstart" 64.36 + orient="auto" 64.37 + refY="0.0" 64.38 + refX="0.0" 64.39 + id="Arrow1Mstart" 64.40 + style="overflow:visible"> 64.41 + <path 64.42 + id="path4855" 64.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 " 64.44 + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none" 64.45 + transform="scale(0.4) translate(10,0)" /> 64.46 + </marker> 64.47 + <linearGradient 64.48 + id="linearGradient6049"> 64.49 + <stop 64.50 + style="stop-color:#686868;stop-opacity:1;" 64.51 + offset="0" 64.52 + id="stop6051" /> 64.53 + <stop 64.54 + style="stop-color:#f0f0f0;stop-opacity:1;" 64.55 + offset="1" 64.56 + id="stop6053" /> 64.57 + </linearGradient> 64.58 + <marker 64.59 + inkscape:stockid="Arrow1Mend" 64.60 + orient="auto" 64.61 + refY="0.0" 64.62 + refX="0.0" 64.63 + id="Arrow1Mend" 64.64 + style="overflow:visible;"> 64.65 + <path 64.66 + id="path4852" 64.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 " 64.68 + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;" 64.69 + transform="scale(0.4) rotate(180) translate(10,0)" /> 64.70 + </marker> 64.71 + <linearGradient 64.72 + inkscape:collect="always" 64.73 + xlink:href="#linearGradient6049" 64.74 + id="linearGradient6083" 64.75 + gradientUnits="userSpaceOnUse" 64.76 + gradientTransform="translate(-240.0462,-8.633237e-6)" 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="linearGradient6142" 64.85 + gradientUnits="userSpaceOnUse" 64.86 + gradientTransform="translate(-42.00893,-30.49544)" 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="linearGradient6193" 64.95 + gradientUnits="userSpaceOnUse" 64.96 + gradientTransform="translate(-240.0462,-8.633237e-6)" 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="linearGradient6216" 64.105 + gradientUnits="userSpaceOnUse" 64.106 + gradientTransform="translate(-6.0462,-0.664361)" 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="linearGradient6232" 64.115 + gradientUnits="userSpaceOnUse" 64.116 + gradientTransform="matrix(1.000474,0,0,0.790947,222.8399,50.85693)" 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="linearGradient6772" 64.125 + gradientUnits="userSpaceOnUse" 64.126 + gradientTransform="matrix(1.000474,0,0,0.790947,222.8399,50.85693)" 64.127 + x1="333.91171" 64.128 + y1="488.79077" 64.129 + x2="508.94543" 64.130 + y2="263.79077" /> 64.131 + </defs> 64.132 + <sodipodi:namedview 64.133 + id="base" 64.134 + pagecolor="#ffffff" 64.135 + bordercolor="#666666" 64.136 + borderopacity="1.0" 64.137 + gridtolerance="10000" 64.138 + guidetolerance="10" 64.139 + objecttolerance="10" 64.140 + inkscape:pageopacity="0.0" 64.141 + inkscape:pageshadow="2" 64.142 + inkscape:zoom="0.90509668" 64.143 + inkscape:cx="390.0539" 64.144 + inkscape:cy="690.49342" 64.145 + inkscape:document-units="px" 64.146 + inkscape:current-layer="layer1" 64.147 + showguides="true" 64.148 + inkscape:guide-bbox="true" 64.149 + inkscape:window-width="906" 64.150 + inkscape:window-height="620" 64.151 + inkscape:window-x="0" 64.152 + inkscape:window-y="25"> 64.153 + <sodipodi:guide 64.154 + orientation="vertical" 64.155 + position="-1.4285714" 64.156 + id="guide6022" /> 64.157 + </sodipodi:namedview> 64.158 + <metadata 64.159 + id="metadata5976"> 64.160 + <rdf:RDF> 64.161 + <cc:Work 64.162 + rdf:about=""> 64.163 + <dc:format>image/svg+xml</dc:format> 64.164 + <dc:type 64.165 + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 64.166 + </cc:Work> 64.167 + </rdf:RDF> 64.168 + </metadata> 64.169 + <g 64.170 + inkscape:label="Layer 1" 64.171 + inkscape:groupmode="layer" 64.172 + id="layer1"> 64.173 + <rect 64.174 + y="245.98355" 64.175 + x="328.23956" 64.176 + height="258.57144" 64.177 + width="174.28572" 64.178 + id="rect6047" 64.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" /> 64.180 + <g 64.181 + id="g6261" 64.182 + transform="translate(234,0)"> 64.183 + <rect 64.184 + y="258.7149" 64.185 + x="114.11369" 64.186 + height="44.537449" 64.187 + width="134.53746" 64.188 + id="rect5983" 64.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" /> 64.190 + <text 64.191 + id="text5985" 64.192 + y="284.47562" 64.193 + x="138.7962" 64.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" 64.195 + xml:space="preserve"><tspan 64.196 + style="font-family:Courier" 64.197 + y="284.47562" 64.198 + x="138.7962" 64.199 + id="tspan5987" 64.200 + sodipodi:role="line">dfbbb33f3fa3</tspan></text> 64.201 + </g> 64.202 + <rect 64.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" 64.204 + id="rect5996" 64.205 + width="134.53746" 64.206 + height="44.537449" 64.207 + x="348.11371" 64.208 + y="320.38159" /> 64.209 + <text 64.210 + xml:space="preserve" 64.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" 64.212 + x="372.7962" 64.213 + y="346.1423" 64.214 + id="text5998"><tspan 64.215 + sodipodi:role="line" 64.216 + id="tspan6000" 64.217 + x="372.7962" 64.218 + y="346.1423" 64.219 + style="font-family:Courier">e7639888bb2f</tspan></text> 64.220 + <rect 64.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" 64.222 + id="rect6004" 64.223 + width="134.53746" 64.224 + height="44.537449" 64.225 + x="348.11371" 64.226 + y="382.04825" /> 64.227 + <text 64.228 + xml:space="preserve" 64.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" 64.230 + x="370.65421" 64.231 + y="407.80896" 64.232 + id="text6006"><tspan 64.233 + sodipodi:role="line" 64.234 + id="tspan6008" 64.235 + x="370.65421" 64.236 + y="407.80896" 64.237 + style="font-family:Courier">7b064d8bac5e</tspan></text> 64.238 + <path 64.239 + inkscape:connector-type="polyline" 64.240 + id="path6018" 64.241 + d="M 415.38242,303.62646 L 415.38242,320.00744" 64.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" /> 64.243 + <path 64.244 + inkscape:connection-end="#rect6004" 64.245 + inkscape:connector-type="polyline" 64.246 + id="path6020" 64.247 + d="M 415.38242,365.29315 L 415.38243,381.67412" 64.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" /> 64.249 + <rect 64.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" 64.251 + id="rect6039" 64.252 + width="134.53746" 64.253 + height="44.537449" 64.254 + x="348.11359" 64.255 + y="443.71487" /> 64.256 + <text 64.257 + xml:space="preserve" 64.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" 64.259 + x="372.79706" 64.260 + y="469.47556" 64.261 + id="text6041"><tspan 64.262 + sodipodi:role="line" 64.263 + id="tspan6043" 64.264 + x="372.79706" 64.265 + y="469.47556" 64.266 + style="fill:#979797;fill-opacity:1;font-family:Courier">000000000000</tspan></text> 64.267 + <path 64.268 + inkscape:connection-end="#rect6039" 64.269 + inkscape:connector-type="polyline" 64.270 + id="path6045" 64.271 + d="M 415.38238,426.95981 L 415.38235,443.34087" 64.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" /> 64.273 + <text 64.274 + xml:space="preserve" 64.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" 64.276 + x="327.66046" 64.277 + y="231.36218" 64.278 + id="text6102"><tspan 64.279 + sodipodi:role="line" 64.280 + id="tspan6104" 64.281 + x="327.66046" 64.282 + y="231.36218">History in repository</tspan></text> 64.283 + <rect 64.284 + y="245.94225" 64.285 + x="557.28418" 64.286 + height="204.51619" 64.287 + width="174.36833" 64.288 + id="rect6140" 64.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" /> 64.290 + <g 64.291 + id="g6130" 64.292 + transform="translate(262.3254,24.38544)"> 64.293 + <rect 64.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" 64.295 + id="rect6106" 64.296 + width="134.53746" 64.297 + height="44.537449" 64.298 + x="314.87415" 64.299 + y="257.95059" /> 64.300 + <text 64.301 + xml:space="preserve" 64.302 + style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman" 64.303 + x="339.55664" 64.304 + y="283.7113" 64.305 + id="text6108"><tspan 64.306 + sodipodi:role="line" 64.307 + id="tspan6110" 64.308 + x="339.55664" 64.309 + y="283.7113" 64.310 + style="font-family:Courier">dfbbb33f3fa3</tspan></text> 64.311 + </g> 64.312 + <g 64.313 + id="g6135" 64.314 + transform="translate(263.0396,49.83106)"> 64.315 + <rect 64.316 + inkscape:transform-center-y="102.85714" 64.317 + inkscape:transform-center-x="129.28571" 64.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" 64.319 + id="rect6112" 64.320 + width="134.53746" 64.321 + height="44.537449" 64.322 + x="314.15985" 64.323 + y="326.52203" /> 64.324 + <text 64.325 + inkscape:transform-center-y="102.7311" 64.326 + inkscape:transform-center-x="128.69672" 64.327 + xml:space="preserve" 64.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" 64.329 + x="338.84335" 64.330 + y="352.28271" 64.331 + id="text6114"><tspan 64.332 + sodipodi:role="line" 64.333 + id="tspan6116" 64.334 + x="338.84335" 64.335 + y="352.28271" 64.336 + style="fill:#979797;fill-opacity:1;font-family:Courier">000000000000</tspan></text> 64.337 + </g> 64.338 + <text 64.339 + xml:space="preserve" 64.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" 64.341 + x="576.63208" 64.342 + y="270.479" 64.343 + id="text6118"><tspan 64.344 + sodipodi:role="line" 64.345 + id="tspan6120" 64.346 + x="576.63208" 64.347 + y="270.479">First parent</tspan></text> 64.348 + <text 64.349 + xml:space="preserve" 64.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" 64.351 + x="576.07544" 64.352 + y="364.49615" 64.353 + id="text6122"><tspan 64.354 + sodipodi:role="line" 64.355 + id="tspan6124" 64.356 + x="576.07544" 64.357 + y="364.49615">Second parent</tspan></text> 64.358 + <text 64.359 + xml:space="preserve" 64.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" 64.361 + x="556.61743" 64.362 + y="231.36218" 64.363 + id="text6195"><tspan 64.364 + sodipodi:role="line" 64.365 + id="tspan6197" 64.366 + x="556.61743" 64.367 + y="231.36218">Parents of working directory</tspan></text> 64.368 + <path 64.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" 64.370 + d="M 576.82542,297.63008 L 483.02528,287.95831" 64.371 + id="path6266" 64.372 + inkscape:connector-type="polyline" 64.373 + inkscape:connection-start="#g6130" 64.374 + inkscape:connection-end="#g6261" /> 64.375 + <path 64.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" 64.377 + d="M 665.12232,418.17579 L 665.12232,418.17579" 64.378 + id="path6270" 64.379 + inkscape:connector-type="polyline" /> 64.380 + <text 64.381 + xml:space="preserve" 64.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" 64.383 + x="316.86407" 64.384 + y="275.6496" 64.385 + id="text6573"><tspan 64.386 + sodipodi:role="line" 64.387 + id="tspan6575" 64.388 + x="316.86407" 64.389 + y="275.6496" 64.390 + style="text-align:end;text-anchor:end">New</tspan><tspan 64.391 + sodipodi:role="line" 64.392 + x="316.86407" 64.393 + y="290.6496" 64.394 + id="tspan6577" 64.395 + style="text-align:end;text-anchor:end">changeset</tspan></text> 64.396 + </g> 64.397 +</svg>
65.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 65.2 +++ b/en/wdir-branch.svg Mon Mar 05 20:16:36 2007 -0800 65.3 @@ -0,0 +1,418 @@ 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.911882,0,0,0.789965,-574.7896,51.22599)" 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,112.8399,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="345.85973" 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="246.06918" 65.185 + x="64.325172" 65.186 + height="204.26233" 65.187 + width="333.2135" 65.188 + id="rect6047" 65.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" /> 65.190 + <g 65.191 + id="g1935"> 65.192 + <rect 65.193 + y="266.24374" 65.194 + x="84.113708" 65.195 + height="44.537449" 65.196 + width="134.53746" 65.197 + id="rect5996" 65.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" /> 65.199 + <text 65.200 + id="text5998" 65.201 + y="292.00446" 65.202 + x="108.7962" 65.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" 65.204 + xml:space="preserve"><tspan 65.205 + style="font-family:Courier" 65.206 + y="292.00446" 65.207 + x="108.7962" 65.208 + id="tspan6000" 65.209 + sodipodi:role="line">e7639888bb2f</tspan></text> 65.210 + </g> 65.211 + <g 65.212 + id="g6976" 65.213 + transform="translate(70,0)"> 65.214 + <rect 65.215 + y="327.9104" 65.216 + x="40.113693" 65.217 + height="44.537449" 65.218 + width="134.53746" 65.219 + id="rect6004" 65.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" /> 65.221 + <text 65.222 + id="text6006" 65.223 + y="353.67111" 65.224 + x="62.654205" 65.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" 65.226 + xml:space="preserve"><tspan 65.227 + style="font-family:Courier" 65.228 + y="353.67111" 65.229 + x="62.654205" 65.230 + id="tspan6008" 65.231 + sodipodi:role="line">7b064d8bac5e</tspan></text> 65.232 + </g> 65.233 + <path 65.234 + inkscape:connector-type="polyline" 65.235 + id="path6020" 65.236 + d="M 160.92915,311.15532 L 167.83571,327.53627" 65.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" 65.238 + inkscape:connection-end="#g6976" 65.239 + inkscape:connection-start="#g1935" /> 65.240 + <rect 65.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" 65.242 + id="rect6039" 65.243 + width="134.53746" 65.244 + height="44.537449" 65.245 + x="110.11359" 65.246 + y="389.57703" /> 65.247 + <text 65.248 + xml:space="preserve" 65.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" 65.250 + x="134.79706" 65.251 + y="415.33771" 65.252 + id="text6041"><tspan 65.253 + sodipodi:role="line" 65.254 + id="tspan6043" 65.255 + x="134.79706" 65.256 + y="415.33771" 65.257 + style="fill:#979797;fill-opacity:1;font-family:Courier">000000000000</tspan></text> 65.258 + <path 65.259 + inkscape:connection-end="#rect6039" 65.260 + inkscape:connector-type="polyline" 65.261 + id="path6045" 65.262 + d="M 177.38238,372.82195 L 177.38235,389.20303" 65.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" /> 65.264 + <rect 65.265 + y="245.94225" 65.266 + x="447.28412" 65.267 + height="204.51619" 65.268 + width="174.36833" 65.269 + id="rect6140" 65.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" /> 65.271 + <g 65.272 + id="g6130" 65.273 + transform="translate(152.3254,24.38544)"> 65.274 + <rect 65.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" 65.276 + id="rect6106" 65.277 + width="134.53746" 65.278 + height="44.537449" 65.279 + x="314.87415" 65.280 + y="257.95059" /> 65.281 + <text 65.282 + xml:space="preserve" 65.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" 65.284 + x="339.55664" 65.285 + y="283.7113" 65.286 + id="text6108"><tspan 65.287 + sodipodi:role="line" 65.288 + id="tspan6110" 65.289 + x="339.55664" 65.290 + y="283.7113" 65.291 + style="font-family:Courier">ffb20e1701ea</tspan></text> 65.292 + </g> 65.293 + <g 65.294 + id="g6135" 65.295 + transform="translate(153.0396,49.83106)"> 65.296 + <rect 65.297 + inkscape:transform-center-y="102.85714" 65.298 + inkscape:transform-center-x="129.28571" 65.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" 65.300 + id="rect6112" 65.301 + width="134.53746" 65.302 + height="44.537449" 65.303 + x="314.15985" 65.304 + y="326.52203" /> 65.305 + <text 65.306 + inkscape:transform-center-y="102.7311" 65.307 + inkscape:transform-center-x="128.69672" 65.308 + xml:space="preserve" 65.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" 65.310 + x="338.84335" 65.311 + y="352.28271" 65.312 + id="text6114"><tspan 65.313 + sodipodi:role="line" 65.314 + id="tspan6116" 65.315 + x="338.84335" 65.316 + y="352.28271" 65.317 + style="fill:#979797;fill-opacity:1;font-family:Courier">000000000000</tspan></text> 65.318 + </g> 65.319 + <text 65.320 + xml:space="preserve" 65.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" 65.322 + x="466.63208" 65.323 + y="270.479" 65.324 + id="text6118"><tspan 65.325 + sodipodi:role="line" 65.326 + id="tspan6120" 65.327 + x="466.63208" 65.328 + y="270.479">First parent</tspan></text> 65.329 + <text 65.330 + xml:space="preserve" 65.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" 65.332 + x="466.07544" 65.333 + y="364.49615" 65.334 + id="text6122"><tspan 65.335 + sodipodi:role="line" 65.336 + id="tspan6124" 65.337 + x="466.07544" 65.338 + y="364.49615">Second parent</tspan></text> 65.339 + <text 65.340 + xml:space="preserve" 65.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" 65.342 + x="446.61743" 65.343 + y="231.36218" 65.344 + id="text6195"><tspan 65.345 + sodipodi:role="line" 65.346 + id="tspan6197" 65.347 + x="446.61743" 65.348 + y="231.36218">Parents of working directory</tspan></text> 65.349 + <path 65.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" 65.351 + d="M 466.82542,300.21999 L 377.00207,294.39744" 65.352 + id="path6266" 65.353 + inkscape:connector-type="polyline" 65.354 + inkscape:connection-start="#g6130" 65.355 + inkscape:connection-end="#rect1925" /> 65.356 + <path 65.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" 65.358 + d="M 665.12232,418.17579 L 665.12232,418.17579" 65.359 + id="path6270" 65.360 + inkscape:connector-type="polyline" /> 65.361 + <g 65.362 + id="g2845"> 65.363 + <rect 65.364 + y="266.24374" 65.365 + x="242.09048" 65.366 + height="44.537449" 65.367 + width="134.53746" 65.368 + id="rect1925" 65.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" /> 65.370 + <text 65.371 + id="text1927" 65.372 + y="292.00446" 65.373 + x="266.77298" 65.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" 65.375 + xml:space="preserve"><tspan 65.376 + style="font-family:Courier" 65.377 + y="292.00446" 65.378 + x="266.77298" 65.379 + id="tspan1929" 65.380 + sodipodi:role="line">ffb20e1701ea</tspan></text> 65.381 + </g> 65.382 + <path 65.383 + inkscape:connector-type="polyline" 65.384 + id="path1933" 65.385 + d="M 260.89978,311.15532 L 225.84185,327.53627" 65.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" 65.387 + inkscape:connection-end="#g6976" /> 65.388 + <text 65.389 + xml:space="preserve" 65.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" 65.391 + x="109.45568" 65.392 + y="231.4554" 65.393 + id="text2837"><tspan 65.394 + sodipodi:role="line" 65.395 + id="tspan2839" 65.396 + x="109.45568" 65.397 + y="231.4554">Pre-existing head</tspan></text> 65.398 + <text 65.399 + xml:space="preserve" 65.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" 65.401 + x="237.54184" 65.402 + y="231.4554" 65.403 + id="text2841"><tspan 65.404 + sodipodi:role="line" 65.405 + id="tspan2843" 65.406 + x="237.54184" 65.407 + y="231.4554">Newly created head (and tip)</tspan></text> 65.408 + <path 65.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)" 65.410 + d="M 148.05048,235.87482 L 149.94915,265.86962" 65.411 + id="path2850" 65.412 + inkscape:connector-type="polyline" 65.413 + inkscape:connection-end="#g1935" /> 65.414 + <path 65.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)" 65.416 + d="M 303.83495,238.08453 L 306.87874,265.86962" 65.417 + id="path2852" 65.418 + inkscape:connector-type="polyline" 65.419 + inkscape:connection-end="#g2845" /> 65.420 + </g> 65.421 +</svg>
66.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 66.2 +++ b/en/wdir-merge.svg Mon Mar 05 20:16:36 2007 -0800 66.3 @@ -0,0 +1,425 @@ 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-merge.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 + <linearGradient 66.122 + inkscape:collect="always" 66.123 + xlink:href="#linearGradient6049" 66.124 + id="linearGradient6974" 66.125 + gradientUnits="userSpaceOnUse" 66.126 + gradientTransform="matrix(1.911882,0,0,0.789965,-574.7896,51.22599)" 66.127 + x1="333.91171" 66.128 + y1="488.79077" 66.129 + x2="508.94543" 66.130 + y2="263.79077" /> 66.131 + <linearGradient 66.132 + inkscape:collect="always" 66.133 + xlink:href="#linearGradient6049" 66.134 + id="linearGradient6996" 66.135 + gradientUnits="userSpaceOnUse" 66.136 + gradientTransform="matrix(1.000473,0,0,0.790947,112.8399,50.85693)" 66.137 + x1="333.91171" 66.138 + y1="488.79077" 66.139 + x2="508.94543" 66.140 + y2="263.79077" /> 66.141 + </defs> 66.142 + <sodipodi:namedview 66.143 + id="base" 66.144 + pagecolor="#ffffff" 66.145 + bordercolor="#666666" 66.146 + borderopacity="1.0" 66.147 + gridtolerance="10000" 66.148 + guidetolerance="10" 66.149 + objecttolerance="10" 66.150 + inkscape:pageopacity="0.0" 66.151 + inkscape:pageshadow="2" 66.152 + inkscape:zoom="1.28" 66.153 + inkscape:cx="345.85973" 66.154 + inkscape:cy="690.49342" 66.155 + inkscape:document-units="px" 66.156 + inkscape:current-layer="layer1" 66.157 + showguides="true" 66.158 + inkscape:guide-bbox="true" 66.159 + inkscape:window-width="906" 66.160 + inkscape:window-height="620" 66.161 + inkscape:window-x="0" 66.162 + inkscape:window-y="25"> 66.163 + <sodipodi:guide 66.164 + orientation="vertical" 66.165 + position="-1.4285714" 66.166 + id="guide6022" /> 66.167 + </sodipodi:namedview> 66.168 + <metadata 66.169 + id="metadata5976"> 66.170 + <rdf:RDF> 66.171 + <cc:Work 66.172 + rdf:about=""> 66.173 + <dc:format>image/svg+xml</dc:format> 66.174 + <dc:type 66.175 + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 66.176 + </cc:Work> 66.177 + </rdf:RDF> 66.178 + </metadata> 66.179 + <g 66.180 + inkscape:label="Layer 1" 66.181 + inkscape:groupmode="layer" 66.182 + id="layer1"> 66.183 + <rect 66.184 + y="246.06918" 66.185 + x="64.325172" 66.186 + height="204.26233" 66.187 + width="333.2135" 66.188 + id="rect6047" 66.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" /> 66.190 + <g 66.191 + id="g6976" 66.192 + transform="translate(70,0)"> 66.193 + <rect 66.194 + y="327.9104" 66.195 + x="40.113693" 66.196 + height="44.537449" 66.197 + width="134.53746" 66.198 + id="rect6004" 66.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" /> 66.200 + <text 66.201 + id="text6006" 66.202 + y="353.67111" 66.203 + x="62.654205" 66.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" 66.205 + xml:space="preserve"><tspan 66.206 + style="font-family:Courier" 66.207 + y="353.67111" 66.208 + x="62.654205" 66.209 + id="tspan6008" 66.210 + sodipodi:role="line">7b064d8bac5e</tspan></text> 66.211 + </g> 66.212 + <path 66.213 + inkscape:connector-type="polyline" 66.214 + id="path6020" 66.215 + d="M 160.92915,311.15532 L 167.83571,327.53627" 66.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" 66.217 + inkscape:connection-end="#g6976" 66.218 + inkscape:connection-start="#g1935" /> 66.219 + <rect 66.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" 66.221 + id="rect6039" 66.222 + width="134.53746" 66.223 + height="44.537449" 66.224 + x="110.11359" 66.225 + y="389.57703" /> 66.226 + <text 66.227 + xml:space="preserve" 66.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" 66.229 + x="134.79706" 66.230 + y="415.33771" 66.231 + id="text6041"><tspan 66.232 + sodipodi:role="line" 66.233 + id="tspan6043" 66.234 + x="134.79706" 66.235 + y="415.33771" 66.236 + style="fill:#979797;fill-opacity:1;font-family:Courier">000000000000</tspan></text> 66.237 + <path 66.238 + inkscape:connection-end="#rect6039" 66.239 + inkscape:connector-type="polyline" 66.240 + id="path6045" 66.241 + d="M 177.38238,372.82195 L 177.38235,389.20303" 66.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" /> 66.243 + <rect 66.244 + y="245.94225" 66.245 + x="447.28412" 66.246 + height="204.51619" 66.247 + width="174.36833" 66.248 + id="rect6140" 66.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" /> 66.250 + <g 66.251 + id="g6130" 66.252 + transform="translate(152.3254,24.38544)"> 66.253 + <rect 66.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" 66.255 + id="rect6106" 66.256 + width="134.53746" 66.257 + height="44.537449" 66.258 + x="314.87415" 66.259 + y="257.95059" /> 66.260 + <text 66.261 + xml:space="preserve" 66.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" 66.263 + x="339.55664" 66.264 + y="283.7113" 66.265 + id="text6108"><tspan 66.266 + sodipodi:role="line" 66.267 + id="tspan6110" 66.268 + x="339.55664" 66.269 + y="283.7113" 66.270 + style="font-family:Courier">ffb20e1701ea</tspan></text> 66.271 + </g> 66.272 + <g 66.273 + id="g6135" 66.274 + transform="translate(153.0396,49.83106)"> 66.275 + <rect 66.276 + inkscape:transform-center-y="102.85714" 66.277 + inkscape:transform-center-x="129.28571" 66.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" 66.279 + id="rect6112" 66.280 + width="134.53746" 66.281 + height="44.537449" 66.282 + x="314.15985" 66.283 + y="326.52203" /> 66.284 + <text 66.285 + inkscape:transform-center-y="102.7311" 66.286 + inkscape:transform-center-x="128.69672" 66.287 + xml:space="preserve" 66.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" 66.289 + x="338.84335" 66.290 + y="352.28271" 66.291 + id="text6114"><tspan 66.292 + sodipodi:role="line" 66.293 + id="tspan6116" 66.294 + x="338.84335" 66.295 + y="352.28271" 66.296 + style="fill:black;fill-opacity:1;font-family:Courier">e7639888bb2f</tspan></text> 66.297 + </g> 66.298 + <text 66.299 + xml:space="preserve" 66.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" 66.301 + x="466.63208" 66.302 + y="270.479" 66.303 + id="text6118"><tspan 66.304 + sodipodi:role="line" 66.305 + id="tspan6120" 66.306 + x="466.63208" 66.307 + y="270.479">First parent (unchanged)</tspan></text> 66.308 + <text 66.309 + xml:space="preserve" 66.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" 66.311 + x="466.07544" 66.312 + y="364.49615" 66.313 + id="text6122"><tspan 66.314 + sodipodi:role="line" 66.315 + id="tspan6124" 66.316 + x="466.07544" 66.317 + y="364.49615">Second parent</tspan></text> 66.318 + <text 66.319 + xml:space="preserve" 66.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" 66.321 + x="446.61743" 66.322 + y="231.36218" 66.323 + id="text6195"><tspan 66.324 + sodipodi:role="line" 66.325 + id="tspan6197" 66.326 + x="446.61743" 66.327 + y="231.36218">Parents of working directory</tspan></text> 66.328 + <path 66.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" 66.330 + d="M 466.82542,300.21999 L 377.00207,294.39744" 66.331 + id="path6266" 66.332 + inkscape:connector-type="polyline" 66.333 + inkscape:connection-start="#g6130" 66.334 + inkscape:connection-end="#rect1925" /> 66.335 + <path 66.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" 66.337 + d="M 665.12232,418.17579 L 665.12232,418.17579" 66.338 + id="path6270" 66.339 + inkscape:connector-type="polyline" /> 66.340 + <g 66.341 + id="g2845"> 66.342 + <rect 66.343 + y="266.24374" 66.344 + x="242.09048" 66.345 + height="44.537449" 66.346 + width="134.53746" 66.347 + id="rect1925" 66.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" /> 66.349 + <text 66.350 + id="text1927" 66.351 + y="292.00446" 66.352 + x="266.77298" 66.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" 66.354 + xml:space="preserve"><tspan 66.355 + style="font-family:Courier" 66.356 + y="292.00446" 66.357 + x="266.77298" 66.358 + id="tspan1929" 66.359 + sodipodi:role="line">ffb20e1701ea</tspan></text> 66.360 + </g> 66.361 + <path 66.362 + inkscape:connector-type="polyline" 66.363 + id="path1933" 66.364 + d="M 260.89978,311.15532 L 225.84185,327.53627" 66.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" 66.366 + inkscape:connection-end="#g6976" /> 66.367 + <text 66.368 + xml:space="preserve" 66.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" 66.370 + x="109.45568" 66.371 + y="231.4554" 66.372 + id="text2837"><tspan 66.373 + sodipodi:role="line" 66.374 + id="tspan2839" 66.375 + x="109.45568" 66.376 + y="231.4554">Pre-existing head</tspan></text> 66.377 + <text 66.378 + xml:space="preserve" 66.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" 66.380 + x="237.54184" 66.381 + y="231.4554" 66.382 + id="text2841"><tspan 66.383 + sodipodi:role="line" 66.384 + id="tspan2843" 66.385 + x="237.54184" 66.386 + y="231.4554">Newly created head (and tip)</tspan></text> 66.387 + <path 66.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)" 66.389 + d="M 148.05048,235.87482 L 149.94915,265.86962" 66.390 + id="path2850" 66.391 + inkscape:connector-type="polyline" 66.392 + inkscape:connection-end="#g1935" /> 66.393 + <path 66.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)" 66.395 + d="M 303.83495,238.08453 L 306.87874,265.86962" 66.396 + id="path2852" 66.397 + inkscape:connector-type="polyline" 66.398 + inkscape:connection-end="#g2845" /> 66.399 + <path 66.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" 66.401 + d="M 466.82545,379.17944 L 219.0253,307.95488" 66.402 + id="path3016" 66.403 + inkscape:connector-type="polyline" 66.404 + inkscape:connection-start="#g6135" 66.405 + inkscape:connection-end="#g1935" /> 66.406 + <g 66.407 + id="g1935"> 66.408 + <rect 66.409 + y="266.24374" 66.410 + x="84.113708" 66.411 + height="44.537449" 66.412 + width="134.53746" 66.413 + id="rect5996" 66.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" /> 66.415 + <text 66.416 + id="text5998" 66.417 + y="292.00446" 66.418 + x="108.7962" 66.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" 66.420 + xml:space="preserve"><tspan 66.421 + style="font-family:Courier" 66.422 + y="292.00446" 66.423 + x="108.7962" 66.424 + id="tspan6000" 66.425 + sodipodi:role="line">e7639888bb2f</tspan></text> 66.426 + </g> 66.427 + </g> 66.428 +</svg>
67.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 67.2 +++ b/en/wdir-pre-branch.svg Mon Mar 05 20:16:36 2007 -0800 67.3 @@ -0,0 +1,364 @@ 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="svg5971" 67.18 + sodipodi:version="0.32" 67.19 + inkscape:version="0.44.1" 67.20 + sodipodi:docbase="/home/bos/hg/hgbook/en" 67.21 + sodipodi:docname="wdir-branch.svg"> 67.22 + <defs 67.23 + id="defs5973"> 67.24 + <marker 67.25 + inkscape:stockid="Arrow1Mstart" 67.26 + orient="auto" 67.27 + refY="0.0" 67.28 + refX="0.0" 67.29 + id="Arrow1Mstart" 67.30 + style="overflow:visible"> 67.31 + <path 67.32 + id="path4855" 67.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 " 67.34 + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none" 67.35 + transform="scale(0.4) translate(10,0)" /> 67.36 + </marker> 67.37 + <linearGradient 67.38 + id="linearGradient6049"> 67.39 + <stop 67.40 + style="stop-color:#686868;stop-opacity:1;" 67.41 + offset="0" 67.42 + id="stop6051" /> 67.43 + <stop 67.44 + style="stop-color:#f0f0f0;stop-opacity:1;" 67.45 + offset="1" 67.46 + id="stop6053" /> 67.47 + </linearGradient> 67.48 + <marker 67.49 + inkscape:stockid="Arrow1Mend" 67.50 + orient="auto" 67.51 + refY="0.0" 67.52 + refX="0.0" 67.53 + id="Arrow1Mend" 67.54 + style="overflow:visible;"> 67.55 + <path 67.56 + id="path4852" 67.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 " 67.58 + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;" 67.59 + transform="scale(0.4) rotate(180) translate(10,0)" /> 67.60 + </marker> 67.61 + <linearGradient 67.62 + inkscape:collect="always" 67.63 + xlink:href="#linearGradient6049" 67.64 + id="linearGradient6083" 67.65 + gradientUnits="userSpaceOnUse" 67.66 + gradientTransform="translate(-240.0462,-8.633237e-6)" 67.67 + x1="333.91171" 67.68 + y1="488.79077" 67.69 + x2="508.94543" 67.70 + y2="263.79077" /> 67.71 + <linearGradient 67.72 + inkscape:collect="always" 67.73 + xlink:href="#linearGradient6049" 67.74 + id="linearGradient6142" 67.75 + gradientUnits="userSpaceOnUse" 67.76 + gradientTransform="translate(-42.00893,-30.49544)" 67.77 + x1="333.91171" 67.78 + y1="488.79077" 67.79 + x2="508.94543" 67.80 + y2="263.79077" /> 67.81 + <linearGradient 67.82 + inkscape:collect="always" 67.83 + xlink:href="#linearGradient6049" 67.84 + id="linearGradient6193" 67.85 + gradientUnits="userSpaceOnUse" 67.86 + gradientTransform="translate(-240.0462,-8.633237e-6)" 67.87 + x1="333.91171" 67.88 + y1="488.79077" 67.89 + x2="508.94543" 67.90 + y2="263.79077" /> 67.91 + <linearGradient 67.92 + inkscape:collect="always" 67.93 + xlink:href="#linearGradient6049" 67.94 + id="linearGradient6216" 67.95 + gradientUnits="userSpaceOnUse" 67.96 + gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)" 67.97 + x1="333.91171" 67.98 + y1="488.79077" 67.99 + x2="508.94543" 67.100 + y2="263.79077" /> 67.101 + <linearGradient 67.102 + inkscape:collect="always" 67.103 + xlink:href="#linearGradient6049" 67.104 + id="linearGradient6232" 67.105 + gradientUnits="userSpaceOnUse" 67.106 + gradientTransform="matrix(1.000473,0,0,0.790947,-11.16012,50.85693)" 67.107 + x1="333.91171" 67.108 + y1="488.79077" 67.109 + x2="508.94543" 67.110 + y2="263.79077" /> 67.111 + <linearGradient 67.112 + inkscape:collect="always" 67.113 + xlink:href="#linearGradient6049" 67.114 + id="linearGradient6445" 67.115 + gradientUnits="userSpaceOnUse" 67.116 + gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)" 67.117 + x1="333.91171" 67.118 + y1="488.79077" 67.119 + x2="508.94543" 67.120 + y2="263.79077" /> 67.121 + <linearGradient 67.122 + inkscape:collect="always" 67.123 + xlink:href="#linearGradient6049" 67.124 + id="linearGradient6974" 67.125 + gradientUnits="userSpaceOnUse" 67.126 + gradientTransform="matrix(1.000474,0,0,0.790947,-314.246,50.85694)" 67.127 + x1="333.91171" 67.128 + y1="488.79077" 67.129 + x2="508.94543" 67.130 + y2="263.79077" /> 67.131 + <linearGradient 67.132 + inkscape:collect="always" 67.133 + xlink:href="#linearGradient6049" 67.134 + id="linearGradient6996" 67.135 + gradientUnits="userSpaceOnUse" 67.136 + gradientTransform="matrix(1.000473,0,0,0.790947,-85.16012,50.85693)" 67.137 + x1="333.91171" 67.138 + y1="488.79077" 67.139 + x2="508.94543" 67.140 + y2="263.79077" /> 67.141 + </defs> 67.142 + <sodipodi:namedview 67.143 + id="base" 67.144 + pagecolor="#ffffff" 67.145 + bordercolor="#666666" 67.146 + borderopacity="1.0" 67.147 + gridtolerance="10000" 67.148 + guidetolerance="10" 67.149 + objecttolerance="10" 67.150 + inkscape:pageopacity="0.0" 67.151 + inkscape:pageshadow="2" 67.152 + inkscape:zoom="0.90509668" 67.153 + inkscape:cx="390.0539" 67.154 + inkscape:cy="690.49342" 67.155 + inkscape:document-units="px" 67.156 + inkscape:current-layer="layer1" 67.157 + showguides="true" 67.158 + inkscape:guide-bbox="true" 67.159 + inkscape:window-width="906" 67.160 + inkscape:window-height="620" 67.161 + inkscape:window-x="0" 67.162 + inkscape:window-y="25"> 67.163 + <sodipodi:guide 67.164 + orientation="vertical" 67.165 + position="-1.4285714" 67.166 + id="guide6022" /> 67.167 + </sodipodi:namedview> 67.168 + <metadata 67.169 + id="metadata5976"> 67.170 + <rdf:RDF> 67.171 + <cc:Work 67.172 + rdf:about=""> 67.173 + <dc:format>image/svg+xml</dc:format> 67.174 + <dc:type 67.175 + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 67.176 + </cc:Work> 67.177 + </rdf:RDF> 67.178 + </metadata> 67.179 + <g 67.180 + inkscape:label="Layer 1" 67.181 + inkscape:groupmode="layer" 67.182 + id="layer1"> 67.183 + <rect 67.184 + y="245.94225" 67.185 + x="20.198257" 67.186 + height="204.51619" 67.187 + width="174.36833" 67.188 + id="rect6047" 67.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" /> 67.190 + <rect 67.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" 67.192 + id="rect5996" 67.193 + width="134.53746" 67.194 + height="44.537449" 67.195 + x="40.113693" 67.196 + y="266.24374" /> 67.197 + <text 67.198 + xml:space="preserve" 67.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" 67.200 + x="64.796204" 67.201 + y="292.00446" 67.202 + id="text5998"><tspan 67.203 + sodipodi:role="line" 67.204 + id="tspan6000" 67.205 + x="64.796204" 67.206 + y="292.00446" 67.207 + style="font-family:Courier">e7639888bb2f</tspan></text> 67.208 + <g 67.209 + id="g6976"> 67.210 + <rect 67.211 + y="327.9104" 67.212 + x="40.113693" 67.213 + height="44.537449" 67.214 + width="134.53746" 67.215 + id="rect6004" 67.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" /> 67.217 + <text 67.218 + id="text6006" 67.219 + y="353.67111" 67.220 + x="62.654205" 67.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" 67.222 + xml:space="preserve"><tspan 67.223 + style="font-family:Courier" 67.224 + y="353.67111" 67.225 + x="62.654205" 67.226 + id="tspan6008" 67.227 + sodipodi:role="line">7b064d8bac5e</tspan></text> 67.228 + </g> 67.229 + <path 67.230 + inkscape:connection-end="#rect6004" 67.231 + inkscape:connector-type="polyline" 67.232 + id="path6020" 67.233 + d="M 107.38242,311.15529 L 107.38242,327.53626" 67.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" /> 67.235 + <rect 67.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" 67.237 + id="rect6039" 67.238 + width="134.53746" 67.239 + height="44.537449" 67.240 + x="40.113571" 67.241 + y="389.57703" /> 67.242 + <text 67.243 + xml:space="preserve" 67.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" 67.245 + x="64.797073" 67.246 + y="415.33771" 67.247 + id="text6041"><tspan 67.248 + sodipodi:role="line" 67.249 + id="tspan6043" 67.250 + x="64.797073" 67.251 + y="415.33771" 67.252 + style="fill:#979797;fill-opacity:1;font-family:Courier">000000000000</tspan></text> 67.253 + <path 67.254 + inkscape:connection-end="#rect6039" 67.255 + inkscape:connector-type="polyline" 67.256 + id="path6045" 67.257 + d="M 107.38238,372.82195 L 107.38235,389.20301" 67.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" /> 67.259 + <text 67.260 + xml:space="preserve" 67.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" 67.262 + x="19.660461" 67.263 + y="231.36218" 67.264 + id="text6102"><tspan 67.265 + sodipodi:role="line" 67.266 + id="tspan6104" 67.267 + x="19.660461" 67.268 + y="231.36218">History in repository</tspan></text> 67.269 + <rect 67.270 + y="245.94225" 67.271 + x="249.28412" 67.272 + height="204.51619" 67.273 + width="174.36833" 67.274 + id="rect6140" 67.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" /> 67.276 + <g 67.277 + id="g6130" 67.278 + transform="translate(-45.67459,24.38544)"> 67.279 + <rect 67.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" 67.281 + id="rect6106" 67.282 + width="134.53746" 67.283 + height="44.537449" 67.284 + x="314.87415" 67.285 + y="257.95059" /> 67.286 + <text 67.287 + xml:space="preserve" 67.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" 67.289 + x="339.55664" 67.290 + y="283.7113" 67.291 + id="text6108"><tspan 67.292 + sodipodi:role="line" 67.293 + id="tspan6110" 67.294 + x="339.55664" 67.295 + y="283.7113" 67.296 + style="font-family:Courier">7b064d8bac5e</tspan></text> 67.297 + </g> 67.298 + <g 67.299 + id="g6135" 67.300 + transform="translate(-44.96042,49.83106)"> 67.301 + <rect 67.302 + inkscape:transform-center-y="102.85714" 67.303 + inkscape:transform-center-x="129.28571" 67.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" 67.305 + id="rect6112" 67.306 + width="134.53746" 67.307 + height="44.537449" 67.308 + x="314.15985" 67.309 + y="326.52203" /> 67.310 + <text 67.311 + inkscape:transform-center-y="102.7311" 67.312 + inkscape:transform-center-x="128.69672" 67.313 + xml:space="preserve" 67.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" 67.315 + x="338.84335" 67.316 + y="352.28271" 67.317 + id="text6114"><tspan 67.318 + sodipodi:role="line" 67.319 + id="tspan6116" 67.320 + x="338.84335" 67.321 + y="352.28271" 67.322 + style="fill:#979797;fill-opacity:1;font-family:Courier">000000000000</tspan></text> 67.323 + </g> 67.324 + <text 67.325 + xml:space="preserve" 67.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" 67.327 + x="268.63208" 67.328 + y="270.479" 67.329 + id="text6118"><tspan 67.330 + sodipodi:role="line" 67.331 + id="tspan6120" 67.332 + x="268.63208" 67.333 + y="270.479">First parent</tspan></text> 67.334 + <text 67.335 + xml:space="preserve" 67.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" 67.337 + x="268.07544" 67.338 + y="364.49615" 67.339 + id="text6122"><tspan 67.340 + sodipodi:role="line" 67.341 + id="tspan6124" 67.342 + x="268.07544" 67.343 + y="364.49615">Second parent</tspan></text> 67.344 + <text 67.345 + xml:space="preserve" 67.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" 67.347 + x="248.61746" 67.348 + y="231.36218" 67.349 + id="text6195"><tspan 67.350 + sodipodi:role="line" 67.351 + id="tspan6197" 67.352 + x="248.61746" 67.353 + y="231.36218">Parents of working directory</tspan></text> 67.354 + <path 67.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" 67.356 + d="M 268.82543,318.06163 L 175.02528,336.72225" 67.357 + id="path6266" 67.358 + inkscape:connector-type="polyline" 67.359 + inkscape:connection-end="#g6976" 67.360 + inkscape:connection-start="#g6130" /> 67.361 + <path 67.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" 67.363 + d="M 665.12232,418.17579 L 665.12232,418.17579" 67.364 + id="path6270" 67.365 + inkscape:connector-type="polyline" /> 67.366 + </g> 67.367 +</svg>
68.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 68.2 +++ b/en/wdir.svg Mon Mar 05 20:16:36 2007 -0800 68.3 @@ -0,0 +1,348 @@ 68.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?> 68.5 +<!-- Created with Inkscape (http://www.inkscape.org/) --> 68.6 +<svg 68.7 + xmlns:dc="http://purl.org/dc/elements/1.1/" 68.8 + xmlns:cc="http://web.resource.org/cc/" 68.9 + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 68.10 + xmlns:svg="http://www.w3.org/2000/svg" 68.11 + xmlns="http://www.w3.org/2000/svg" 68.12 + xmlns:xlink="http://www.w3.org/1999/xlink" 68.13 + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" 68.14 + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" 68.15 + width="744.09448819" 68.16 + height="1052.3622047" 68.17 + id="svg5971" 68.18 + sodipodi:version="0.32" 68.19 + inkscape:version="0.44.1" 68.20 + sodipodi:docbase="/home/bos/hg/hgbook/en" 68.21 + sodipodi:docname="wdir.svg"> 68.22 + <defs 68.23 + id="defs5973"> 68.24 + <marker 68.25 + inkscape:stockid="Arrow1Mstart" 68.26 + orient="auto" 68.27 + refY="0.0" 68.28 + refX="0.0" 68.29 + id="Arrow1Mstart" 68.30 + style="overflow:visible"> 68.31 + <path 68.32 + id="path4855" 68.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 " 68.34 + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none" 68.35 + transform="scale(0.4) translate(10,0)" /> 68.36 + </marker> 68.37 + <linearGradient 68.38 + id="linearGradient6049"> 68.39 + <stop 68.40 + style="stop-color:#686868;stop-opacity:1;" 68.41 + offset="0" 68.42 + id="stop6051" /> 68.43 + <stop 68.44 + style="stop-color:#f0f0f0;stop-opacity:1;" 68.45 + offset="1" 68.46 + id="stop6053" /> 68.47 + </linearGradient> 68.48 + <marker 68.49 + inkscape:stockid="Arrow1Mend" 68.50 + orient="auto" 68.51 + refY="0.0" 68.52 + refX="0.0" 68.53 + id="Arrow1Mend" 68.54 + style="overflow:visible;"> 68.55 + <path 68.56 + id="path4852" 68.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 " 68.58 + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;" 68.59 + transform="scale(0.4) rotate(180) translate(10,0)" /> 68.60 + </marker> 68.61 + <linearGradient 68.62 + inkscape:collect="always" 68.63 + xlink:href="#linearGradient6049" 68.64 + id="linearGradient6083" 68.65 + gradientUnits="userSpaceOnUse" 68.66 + gradientTransform="translate(-240.0462,-8.633237e-6)" 68.67 + x1="333.91171" 68.68 + y1="488.79077" 68.69 + x2="508.94543" 68.70 + y2="263.79077" /> 68.71 + <linearGradient 68.72 + inkscape:collect="always" 68.73 + xlink:href="#linearGradient6049" 68.74 + id="linearGradient6142" 68.75 + gradientUnits="userSpaceOnUse" 68.76 + gradientTransform="translate(-42.00893,-30.49544)" 68.77 + x1="333.91171" 68.78 + y1="488.79077" 68.79 + x2="508.94543" 68.80 + y2="263.79077" /> 68.81 + <linearGradient 68.82 + inkscape:collect="always" 68.83 + xlink:href="#linearGradient6049" 68.84 + id="linearGradient6193" 68.85 + gradientUnits="userSpaceOnUse" 68.86 + gradientTransform="translate(-240.0462,-8.633237e-6)" 68.87 + x1="333.91171" 68.88 + y1="488.79077" 68.89 + x2="508.94543" 68.90 + y2="263.79077" /> 68.91 + <linearGradient 68.92 + inkscape:collect="always" 68.93 + xlink:href="#linearGradient6049" 68.94 + id="linearGradient6216" 68.95 + gradientUnits="userSpaceOnUse" 68.96 + gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)" 68.97 + x1="333.91171" 68.98 + y1="488.79077" 68.99 + x2="508.94543" 68.100 + y2="263.79077" /> 68.101 + <linearGradient 68.102 + inkscape:collect="always" 68.103 + xlink:href="#linearGradient6049" 68.104 + id="linearGradient6232" 68.105 + gradientUnits="userSpaceOnUse" 68.106 + gradientTransform="matrix(1.000473,0,0,0.790947,-11.16012,50.85693)" 68.107 + x1="333.91171" 68.108 + y1="488.79077" 68.109 + x2="508.94543" 68.110 + y2="263.79077" /> 68.111 + <linearGradient 68.112 + inkscape:collect="always" 68.113 + xlink:href="#linearGradient6049" 68.114 + id="linearGradient6445" 68.115 + gradientUnits="userSpaceOnUse" 68.116 + gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)" 68.117 + x1="333.91171" 68.118 + y1="488.79077" 68.119 + x2="508.94543" 68.120 + y2="263.79077" /> 68.121 + </defs> 68.122 + <sodipodi:namedview 68.123 + id="base" 68.124 + pagecolor="#ffffff" 68.125 + bordercolor="#666666" 68.126 + borderopacity="1.0" 68.127 + gridtolerance="10000" 68.128 + guidetolerance="10" 68.129 + objecttolerance="10" 68.130 + inkscape:pageopacity="0.0" 68.131 + inkscape:pageshadow="2" 68.132 + inkscape:zoom="0.90509668" 68.133 + inkscape:cx="390.0539" 68.134 + inkscape:cy="690.49342" 68.135 + inkscape:document-units="px" 68.136 + inkscape:current-layer="layer1" 68.137 + showguides="true" 68.138 + inkscape:guide-bbox="true" 68.139 + inkscape:window-width="906" 68.140 + inkscape:window-height="620" 68.141 + inkscape:window-x="0" 68.142 + inkscape:window-y="25"> 68.143 + <sodipodi:guide 68.144 + orientation="vertical" 68.145 + position="-1.4285714" 68.146 + id="guide6022" /> 68.147 + </sodipodi:namedview> 68.148 + <metadata 68.149 + id="metadata5976"> 68.150 + <rdf:RDF> 68.151 + <cc:Work 68.152 + rdf:about=""> 68.153 + <dc:format>image/svg+xml</dc:format> 68.154 + <dc:type 68.155 + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 68.156 + </cc:Work> 68.157 + </rdf:RDF> 68.158 + </metadata> 68.159 + <g 68.160 + inkscape:label="Layer 1" 68.161 + inkscape:groupmode="layer" 68.162 + id="layer1"> 68.163 + <g 68.164 + id="g6431" 68.165 + transform="translate(0,-0.137863)"> 68.166 + <rect 68.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" 68.168 + id="rect6047" 68.169 + width="174.36833" 68.170 + height="204.51619" 68.171 + x="94.198257" 68.172 + y="246.08011" /> 68.173 + <rect 68.174 + y="266.38159" 68.175 + x="114.11369" 68.176 + height="44.537449" 68.177 + width="134.53746" 68.178 + id="rect5996" 68.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" /> 68.180 + <text 68.181 + id="text5998" 68.182 + y="292.1423" 68.183 + x="138.7962" 68.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" 68.185 + xml:space="preserve"><tspan 68.186 + style="font-family:Courier" 68.187 + y="292.1423" 68.188 + x="138.7962" 68.189 + id="tspan6000" 68.190 + sodipodi:role="line">e7639888bb2f</tspan></text> 68.191 + <rect 68.192 + y="328.04825" 68.193 + x="114.11369" 68.194 + height="44.537449" 68.195 + width="134.53746" 68.196 + id="rect6004" 68.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" /> 68.198 + <text 68.199 + id="text6006" 68.200 + y="353.80896" 68.201 + x="136.65421" 68.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" 68.203 + xml:space="preserve"><tspan 68.204 + style="font-family:Courier" 68.205 + y="353.80896" 68.206 + x="136.65421" 68.207 + id="tspan6008" 68.208 + sodipodi:role="line">7b064d8bac5e</tspan></text> 68.209 + <path 68.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" 68.211 + d="M 181.38242,311.29315 L 181.38242,327.67412" 68.212 + id="path6020" 68.213 + inkscape:connector-type="polyline" 68.214 + inkscape:connection-end="#rect6004" /> 68.215 + <rect 68.216 + y="389.71487" 68.217 + x="114.11357" 68.218 + height="44.537449" 68.219 + width="134.53746" 68.220 + id="rect6039" 68.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" /> 68.222 + <text 68.223 + id="text6041" 68.224 + y="415.47556" 68.225 + x="138.79707" 68.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" 68.227 + xml:space="preserve"><tspan 68.228 + style="fill:#979797;fill-opacity:1;font-family:Courier" 68.229 + y="415.47556" 68.230 + x="138.79707" 68.231 + id="tspan6043" 68.232 + sodipodi:role="line">000000000000</tspan></text> 68.233 + <path 68.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" 68.235 + d="M 181.38238,372.95981 L 181.38235,389.34087" 68.236 + id="path6045" 68.237 + inkscape:connector-type="polyline" 68.238 + inkscape:connection-end="#rect6039" /> 68.239 + </g> 68.240 + <text 68.241 + xml:space="preserve" 68.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" 68.243 + x="93.660484" 68.244 + y="231.36218" 68.245 + id="text6102"><tspan 68.246 + sodipodi:role="line" 68.247 + id="tspan6104" 68.248 + x="93.660484" 68.249 + y="231.36218">History in repository</tspan></text> 68.250 + <g 68.251 + id="g6416"> 68.252 + <rect 68.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" 68.254 + id="rect6140" 68.255 + width="174.36833" 68.256 + height="204.51619" 68.257 + x="323.28412" 68.258 + y="245.94225" /> 68.259 + <g 68.260 + transform="translate(28.32541,24.38544)" 68.261 + id="g6130"> 68.262 + <rect 68.263 + y="257.95059" 68.264 + x="314.87415" 68.265 + height="44.537449" 68.266 + width="134.53746" 68.267 + id="rect6106" 68.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" /> 68.269 + <text 68.270 + id="text6108" 68.271 + y="283.7113" 68.272 + x="339.55664" 68.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" 68.274 + xml:space="preserve"><tspan 68.275 + style="font-family:Courier" 68.276 + y="283.7113" 68.277 + x="339.55664" 68.278 + id="tspan6110" 68.279 + sodipodi:role="line">e7639888bb2f</tspan></text> 68.280 + </g> 68.281 + <g 68.282 + transform="translate(29.03958,49.83106)" 68.283 + id="g6135"> 68.284 + <rect 68.285 + y="326.52203" 68.286 + x="314.15985" 68.287 + height="44.537449" 68.288 + width="134.53746" 68.289 + id="rect6112" 68.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" 68.291 + inkscape:transform-center-x="129.28571" 68.292 + inkscape:transform-center-y="102.85714" /> 68.293 + <text 68.294 + id="text6114" 68.295 + y="352.28271" 68.296 + x="338.84335" 68.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" 68.298 + xml:space="preserve" 68.299 + inkscape:transform-center-x="128.69672" 68.300 + inkscape:transform-center-y="102.7311"><tspan 68.301 + style="fill:#979797;fill-opacity:1;font-family:Courier" 68.302 + y="352.28271" 68.303 + x="338.84335" 68.304 + id="tspan6116" 68.305 + sodipodi:role="line">000000000000</tspan></text> 68.306 + </g> 68.307 + <text 68.308 + id="text6118" 68.309 + y="270.479" 68.310 + x="342.63208" 68.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" 68.312 + xml:space="preserve"><tspan 68.313 + y="270.479" 68.314 + x="342.63208" 68.315 + id="tspan6120" 68.316 + sodipodi:role="line">First parent</tspan></text> 68.317 + <text 68.318 + id="text6122" 68.319 + y="364.49615" 68.320 + x="342.07544" 68.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" 68.322 + xml:space="preserve"><tspan 68.323 + y="364.49615" 68.324 + x="342.07544" 68.325 + id="tspan6124" 68.326 + sodipodi:role="line">Second parent</tspan></text> 68.327 + </g> 68.328 + <text 68.329 + xml:space="preserve" 68.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" 68.331 + x="322.61746" 68.332 + y="231.36218" 68.333 + id="text6195"><tspan 68.334 + sodipodi:role="line" 68.335 + id="tspan6197" 68.336 + x="322.61746" 68.337 + y="231.36218">Parents of working directory</tspan></text> 68.338 + <path 68.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" 68.340 + d="M 342.82543,299.89384 L 249.02528,293.36123" 68.341 + id="path6266" 68.342 + inkscape:connector-type="polyline" 68.343 + inkscape:connection-start="#g6130" 68.344 + inkscape:connection-end="#rect5996" /> 68.345 + <path 68.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" 68.347 + d="M 665.12232,418.17579 L 665.12232,418.17579" 68.348 + id="path6270" 68.349 + inkscape:connector-type="polyline" /> 68.350 + </g> 68.351 +</svg>
69.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 69.2 +++ b/examples/hg-interdiff Mon Mar 05 20:16:36 2007 -0800 69.3 @@ -0,0 +1,39 @@ 69.4 +#!/usr/bin/env python 69.5 +# 69.6 +# Adapter for using interdiff with mercurial's extdiff extension. 69.7 +# 69.8 +# Copyright 2006 Bryan O'Sullivan <bos@serpentine.com> 69.9 +# 69.10 +# This software may be used and distributed according to the terms of 69.11 +# the GNU General Public License, incorporated herein by reference. 69.12 + 69.13 +import os, sys 69.14 + 69.15 +def walk(base): 69.16 + # yield all non-directories below the base path. 69.17 + for root, dirs, files in os.walk(base): 69.18 + for f in files: 69.19 + path = os.path.join(root, f) 69.20 + yield path[len(base)+1:], path 69.21 + 69.22 +# create list of unique file names under both directories. 69.23 +files = dict(walk(sys.argv[1])) 69.24 +files.update(walk(sys.argv[2])) 69.25 +files = files.keys() 69.26 +files.sort() 69.27 + 69.28 +def name(base, f): 69.29 + # interdiff requires two files; use /dev/null if one is missing. 69.30 + path = os.path.join(base, f) 69.31 + if os.path.exists(path): 69.32 + return path 69.33 + return '/dev/null' 69.34 + 69.35 +ret = 0 69.36 + 69.37 +for f in files: 69.38 + if os.system('interdiff "%s" "%s"' % (name(sys.argv[1], f), 69.39 + name(sys.argv[2], f))): 69.40 + ret = 1 69.41 + 69.42 +sys.exit(ret)
70.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 70.2 +++ b/examples/hg-replay Mon Mar 05 20:16:36 2007 -0800 70.3 @@ -0,0 +1,107 @@ 70.4 +#!/usr/bin/env python 70.5 +# 70.6 +# Adapter for using interdiff with mercurial's extdiff extension. 70.7 +# 70.8 +# Copyright 2006 Bryan O'Sullivan <bos@serpentine.com> 70.9 +# 70.10 +# This software may be used and distributed according to the terms of 70.11 +# the GNU General Public License, incorporated herein by reference. 70.12 + 70.13 +import os 70.14 +import shutil 70.15 +import sys 70.16 +import tempfile 70.17 + 70.18 +if len(sys.argv) < 4: 70.19 + print >> sys.stderr, ('usage: %s srcrepo destrepo cset-to-omit [...]' % 70.20 + os.path.basename(sys.argv[0])) 70.21 + sys.exit(1) 70.22 + 70.23 +srcrepo, destrepo = sys.argv[1], sys.argv[2] 70.24 +omit = sys.argv[3:] 70.25 + 70.26 +changemap = {} 70.27 +revs = [] 70.28 + 70.29 +parent = None 70.30 + 70.31 +sys.stdout.write('gathering history...') 70.32 +sys.stdout.flush() 70.33 + 70.34 +for line in os.popen("hg --cwd %r log -r0:tip --template '{rev}:{node} {parents}\n'" % srcrepo): 70.35 + changes = line.split() 70.36 + cset = changes[0].split(':')[1] 70.37 + rev = len(revs) 70.38 + changemap[cset] = rev 70.39 + if len(changes) >= 2: 70.40 + p1 = int(changes[1].split(':', 1)[0]) 70.41 + if len(changes) == 3: 70.42 + p2 = int(changes[2].split(':', 1)[0]) 70.43 + else: 70.44 + p2 = None 70.45 + if len(changes) == 1: 70.46 + p1 = parent 70.47 + revs.append((cset, p1, p2)) 70.48 + parent = rev 70.49 + 70.50 +sys.stdout.write(' %d revs\n' % len(revs)) 70.51 + 70.52 +def findrev(r): 70.53 + try: 70.54 + i = int(r) 70.55 + if str(i) == r: 70.56 + rev = i 70.57 + if rev < 0: 70.58 + rev += len(revs) 70.59 + if rev < 0 or rev > len(revs): 70.60 + print >> sys.stderr, 'bad changeset: %r' % r 70.61 + sys.exit(1) 70.62 + cset = revs[rev][0] 70.63 + except ValueError: 70.64 + cset = r 70.65 + matches = [changemap[c] for c in changemap if c.startswith(cset)] 70.66 + if len(matches) != 1: 70.67 + print >> sys.stderr, 'bad changeset: %r' % r 70.68 + sys.exit(1) 70.69 + rev = matches[0] 70.70 + return rev 70.71 + 70.72 +def run(cmd): 70.73 + print cmd 70.74 + ret = os.system(cmd) 70.75 + if ret: 70.76 + print >> sys.stderr, 'failure:', cmd 70.77 + sys.exit(1) 70.78 + 70.79 +omit = map(findrev, omit) 70.80 +omit.sort() 70.81 +newrevs = revs[:omit[0]] 70.82 +tip = len(newrevs) - 1 70.83 +run('hg clone -q -r%s %r %r' % (tip, srcrepo, destrepo)) 70.84 + 70.85 +os.environ['HGMERGE'] = 'true' 70.86 + 70.87 +patchdir = tempfile.mkdtemp(prefix='replay.') 70.88 +try: 70.89 + run('hg --cwd %r export --git -o %r%s%%R %d:tip' % 70.90 + (srcrepo, patchdir, os.sep, omit[0]+1)) 70.91 + for rev in xrange(omit[0], len(revs)): 70.92 + if rev in omit: 70.93 + print 'omit', rev 70.94 + newrevs.append((None, revs[rev][1], None)) 70.95 + continue 70.96 + _, p1, p2 = revs[rev] 70.97 + np1 = newrevs[p1][1] 70.98 + if tip != np1: 70.99 + run('hg --cwd %r update -q -C %s' % (destrepo, np1)) 70.100 + np2 = None 70.101 + if p2: 70.102 + np2 = newrevs[p2][1] 70.103 + run('hg --cwd %r merge -q %s' % (destrepo, np2)) 70.104 + print >> sys.stderr, 'XXX - cannot handle merges properly yet' 70.105 + run('hg --cwd %r import -q -f %r%s%d' % (destrepo, patchdir, os.sep, rev)) 70.106 + tip = len(newrevs) - 1 70.107 + newrevs.append((None, tip, np2)) 70.108 +finally: 70.109 + print 'cleaning up ...' 70.110 + #shutil.rmtree(patchdir)