hgbook
changeset 57:fa8bafe467cb
Merge with upstream
author | Josef "Jeff" Sipek <jeffpc@josefsipek.net> |
---|---|
date | Tue Jul 25 00:02:24 2006 -0400 (2006-07-25) |
parents | b8539d91c84d 6f37e6a7d8cd |
children | 3649ee841264 |
files | en/00book.tex en/99defs.tex en/Makefile en/examples/mq.diff |
line diff
1.1 --- a/en/00book.tex Mon Jul 24 23:57:52 2006 -0400 1.2 +++ b/en/00book.tex Tue Jul 25 00:02:24 2006 -0400 1.3 @@ -1,57 +1,58 @@ 1.4 -% The use of oneside here is a temporary hack; \marginpar entries 1.5 -% don't show up on odd pages of PDF output without it. Sigh. 1.6 -\documentclass[oneside]{book} 1.7 -\usepackage{enumerate} 1.8 -\usepackage{fullpage} 1.9 -\usepackage{makeidx} 1.10 -\usepackage{ifpdf} 1.11 -\usepackage{graphicx} 1.12 -\usepackage{pslatex} 1.13 -\usepackage{fancyvrb} 1.14 -% leave hyperref until last 1.15 -\usepackage[colorlinks=true,bookmarks=true]{hyperref} 1.16 - 1.17 -\include{99defs} 1.18 - 1.19 -\title{Distributed revision control with Mercurial} 1.20 -\author{Bryan O'Sullivan} 1.21 -\date{Copyright \copyright\ 2006 Bryan O'Sullivan.\\ 1.22 - This material may be distributed only subject to the terms and 1.23 - conditions set forth in version 1.0 of the Open Publication License. 1.24 - Please refer to Appendix~\ref{cha:opl} for the license text.\\ 1.25 - This book was prepared from revision \input{build_id}.} 1.26 - 1.27 -\makeindex 1.28 - 1.29 -\begin{document} 1.30 - 1.31 -\maketitle 1.32 - 1.33 -\addcontentsline{toc}{chapter}{Contents} 1.34 -\pagenumbering{roman} 1.35 -\tableofcontents 1.36 -\listoffigures 1.37 -%\listoftables 1.38 - 1.39 -\pagenumbering{arabic} 1.40 - 1.41 -\include{preface} 1.42 -\include{intro} 1.43 -\include{concepts} 1.44 -\include{hook} 1.45 -\include{mq} 1.46 - 1.47 -\appendix 1.48 -\include{license} 1.49 -\addcontentsline{toc}{chapter}{Bibliography} 1.50 -\bibliographystyle{alpha} 1.51 -\bibliography{99book} 1.52 - 1.53 -\printindex 1.54 - 1.55 -\end{document} 1.56 - 1.57 -%%% Local Variables: 1.58 -%%% mode: latex 1.59 -%%% TeX-master: t 1.60 -%%% End: 1.61 +% The use of oneside here is a temporary hack; \marginpar entries 1.62 +% don't show up on odd pages of PDF output without it. Sigh. 1.63 +\documentclass[oneside]{book} 1.64 +\usepackage{enumerate} 1.65 +\usepackage{fullpage} 1.66 +\usepackage{makeidx} 1.67 +\usepackage{ifpdf} 1.68 +\usepackage{graphicx} 1.69 +\usepackage{pslatex} 1.70 +\usepackage{fancyvrb} 1.71 +% leave hyperref until last 1.72 +\usepackage[colorlinks=true,bookmarks=true]{hyperref} 1.73 + 1.74 +\include{99defs} 1.75 + 1.76 +\title{Distributed revision control with Mercurial} 1.77 +\author{Bryan O'Sullivan} 1.78 +\date{Copyright \copyright\ 2006 Bryan O'Sullivan.\\ 1.79 + This material may be distributed only subject to the terms and 1.80 + conditions set forth in version 1.0 of the Open Publication License. 1.81 + Please refer to Appendix~\ref{cha:opl} for the license text.\\ 1.82 + This book was prepared from revision \input{build_id}.} 1.83 + 1.84 +\makeindex 1.85 + 1.86 +\begin{document} 1.87 + 1.88 +\maketitle 1.89 + 1.90 +\addcontentsline{toc}{chapter}{Contents} 1.91 +\pagenumbering{roman} 1.92 +\tableofcontents 1.93 +\listoffigures 1.94 +%\listoftables 1.95 + 1.96 +\pagenumbering{arabic} 1.97 + 1.98 +\include{preface} 1.99 +\include{intro} 1.100 +\include{concepts} 1.101 +\include{daily} 1.102 +\include{hook} 1.103 +\include{mq} 1.104 + 1.105 +\appendix 1.106 +\include{license} 1.107 +\addcontentsline{toc}{chapter}{Bibliography} 1.108 +\bibliographystyle{alpha} 1.109 +\bibliography{99book} 1.110 + 1.111 +\printindex 1.112 + 1.113 +\end{document} 1.114 + 1.115 +%%% Local Variables: 1.116 +%%% mode: latex 1.117 +%%% TeX-master: t 1.118 +%%% End:
2.1 --- a/en/99defs.tex Mon Jul 24 23:57:52 2006 -0400 2.2 +++ b/en/99defs.tex Tue Jul 25 00:02:24 2006 -0400 2.3 @@ -1,26 +1,80 @@ 2.4 -\newcommand{\bug}[1]{\index{Mercurial issue!no.~#1}\href{http://www.selenic.com/mercurial/bts/issue#1}{Mercurial issue no.~#1}} 2.5 +% Bug ID. 2.6 +\newcommand{\bug}[1]{\index{Mercurial bug 2.7 + database!\href{http://www.selenic.com/mercurial/bts/issue#1}{bug 2.8 + ~#1}}\href{http://www.selenic.com/mercurial/bts/issue#1}{Mercurial 2.9 + bug no.~#1}} 2.10 + 2.11 +% File name in the user's home directory. 2.12 \newcommand{\tildefile}[1]{\texttt{\~{}/#1}} 2.13 + 2.14 +% File name. 2.15 \newcommand{\filename}[1]{\texttt{#1}} 2.16 + 2.17 +% Directory name. 2.18 \newcommand{\dirname}[1]{\texttt{#1}} 2.19 + 2.20 +% File name, with index entry. 2.21 +% The ``s'' prefix comes from ``special''. 2.22 \newcommand{\sfilename}[1]{\index{\texttt{#1} file}\texttt{#1}} 2.23 + 2.24 +% Directory name, with index entry. 2.25 \newcommand{\sdirname}[1]{\index{\texttt{#1} directory}\texttt{#1}} 2.26 + 2.27 +% Mercurial extension. 2.28 \newcommand{\hgext}[1]{\index{\texttt{#1} extension}\texttt{#1}} 2.29 + 2.30 +% Mercurial command. 2.31 \newcommand{\hgcmd}[1]{\index{\texttt{#1} command}``\texttt{hg #1}''} 2.32 + 2.33 +% Mercurial command, with arguments. 2.34 +\newcommand{\hgcmdargs}[2]{\index{\texttt{#1} command}``\texttt{hg #1 #2}''} 2.35 + 2.36 +% Shell/system command. 2.37 \newcommand{\command}[1]{\index{\texttt{#1} command}\texttt{#1}} 2.38 + 2.39 +% Shell/system command, with arguments. 2.40 \newcommand{\cmdargs}[2]{\index{\texttt{#1} command}``\texttt{#1 #2}''} 2.41 -\newcommand{\hgcmdargs}[2]{\index{\texttt{#1} command}``\texttt{hg #1 #2}''} 2.42 + 2.43 +% Mercurial command option. 2.44 \newcommand{\hgopt}[2]{\index{\texttt{#1} command!\texttt{#2} option}\texttt{#2}} 2.45 + 2.46 +% Mercurial global option. 2.47 +\newcommand{\hggopt}[1]{\index{global options!\texttt{#1} option}\texttt{#1}} 2.48 + 2.49 +% Shell/system command option. 2.50 \newcommand{\cmdopt}[2]{\index{\texttt{#1} command!\texttt{#2} option}\texttt{#2}} 2.51 + 2.52 +% Command option. 2.53 \newcommand{\option}[1]{\texttt{#1}} 2.54 + 2.55 +% Software package. 2.56 \newcommand{\package}[1]{\index{\texttt{#1} package}\texttt{#1}} 2.57 + 2.58 +% Section name from a hgrc file. 2.59 \newcommand{\rcsection}[1]{\index{\texttt{hgrc} file!\texttt{#1} section}\texttt{[#1]}} 2.60 + 2.61 +% Named item in a hgrc file section. 2.62 \newcommand{\rcitem}[2]{\index{\texttt{hgrc} file!\texttt{#1} 2.63 section!\texttt{#2} entry}\texttt{#1.#2}} 2.64 + 2.65 +% hgrc file. 2.66 \newcommand{\hgrc}{\index{\texttt{hgrc} file}\texttt{hgrc}} 2.67 + 2.68 +% Hook name. 2.69 \newcommand{\hook}[1]{\index{\texttt{#1} hook}\index{hooks!\texttt{#1}}\texttt{#1}} 2.70 + 2.71 +% Environment variable. 2.72 \newcommand{\envar}[1]{\index{\texttt{#1} environment 2.73 variable}\index{environment variables!\texttt{#1}}\texttt{#1}} 2.74 2.75 +% Python module. 2.76 +\newcommand{\pymod}[1]{\index{\texttt{#1} module}\texttt{#1}} 2.77 + 2.78 +% Python class in a module. 2.79 +\newcommand{\pymodclass}[2]{\index{\texttt{#1} module!\texttt{#2} 2.80 + class}\texttt{#1.#2}} 2.81 + 2.82 +% Note: blah blah. 2.83 \newsavebox{\notebox} 2.84 \newenvironment{note}% 2.85 {\begin{lrbox}{\notebox}\begin{minipage}{0.7\textwidth}\textbf{Note:}\space}% 2.86 @@ -29,11 +83,18 @@ 2.87 {\begin{lrbox}{\notebox}\begin{minipage}{0.7\textwidth}\textbf{Caution:}\space}% 2.88 {\end{minipage}\end{lrbox}\fbox{\usebox{\notebox}}} 2.89 2.90 +% Code sample, eating 4 characters of leading space. 2.91 \DefineVerbatimEnvironment{codesample4}{Verbatim}{frame=single,gobble=4,numbers=left,commandchars=\\\{\}} 2.92 + 2.93 +% Code sample, eating 2 characters of leading space. 2.94 +\DefineVerbatimEnvironment{codesample2}{Verbatim}{frame=single,gobble=2,numbers=left,commandchars=\\\{\}} 2.95 + 2.96 +% Interaction from the examples directory. 2.97 \newcommand{\interaction}[1]{\VerbatimInput[frame=single,numbers=left,commandchars=\\\{\}]{examples/#1.out}} 2.98 2.99 +% Graphics inclusion. 2.100 \ifpdf 2.101 - \newcommand{\grafix}[1]{\includegraphics[scale=0.2]{#1_pdf.png}} 2.102 + \newcommand{\grafix}[1]{\includegraphics{#1}} 2.103 \else 2.104 \newcommand{\grafix}[1]{\includegraphics{#1.png}} 2.105 \fi
3.1 --- a/en/Makefile Mon Jul 24 23:57:52 2006 -0400 3.2 +++ b/en/Makefile Tue Jul 25 00:02:24 2006 -0400 3.3 @@ -1,121 +1,126 @@ 3.4 -# This makefile requires GNU make. 3.5 - 3.6 -hg_id := $(shell hg parents --template '{node|short}\n' | head -1) 3.7 - 3.8 -sources := \ 3.9 - 00book.tex \ 3.10 - 99book.bib \ 3.11 - 99defs.tex \ 3.12 - build_id.tex \ 3.13 - concepts.tex \ 3.14 - hook.tex \ 3.15 - intro.tex \ 3.16 - mq.tex \ 3.17 - preface.tex 3.18 - 3.19 -image-sources := \ 3.20 - mq-stack.svg 3.21 - 3.22 -example-sources := \ 3.23 - examples/run-example \ 3.24 - examples/hook.simple \ 3.25 - examples/concepts \ 3.26 - examples/mq.qinit-help \ 3.27 - examples/mq.diff \ 3.28 - examples/mq.tarball \ 3.29 - examples/mq.tools \ 3.30 - examples/mq.tutorial 3.31 - 3.32 -latex-options = \ 3.33 - -interaction batchmode \ 3.34 - -output-directory $(dir $(1)) \ 3.35 - -jobname $(basename $(notdir $(1))) 3.36 - 3.37 -all: pdf html 3.38 - 3.39 -pdf: pdf/hgbook.pdf 3.40 - 3.41 -define pdf 3.42 - mkdir -p $(dir $@) 3.43 - TEXINPUTS=$(dir $<): pdflatex $(call latex-options,$@) $< || (rm -f $@; exit 1) 3.44 - cp 99book.bib $(dir $@) 3.45 - cd $(dir $@) && bibtex $(basename $(notdir $@)) 3.46 - cd $(dir $@) && makeindex $(basename $(notdir $@)) 3.47 - TEXINPUTS=$(dir $<): pdflatex $(call latex-options,$@) $< || (rm -f $@; exit 1) 3.48 - TEXINPUTS=$(dir $<): pdflatex $(call latex-options,$@) $< || (rm -f $@; exit 1) 3.49 - if grep 'Reference.*undefined' $(@:.pdf=.log); then exit 1; fi 3.50 -endef 3.51 - 3.52 -pdf/hgbook.pdf: $(sources) $(image-sources:%.svg=%.pdf) examples 3.53 - $(call pdf) 3.54 - 3.55 -html: html/onepage/hgbook.html html/split/hgbook.html 3.56 - 3.57 -# This is a horrible hack to work around the fact that the htlatex 3.58 -# command in tex4ht is itself a horrible hack. I really don't want to 3.59 -# include verbatim the big wad of TeX that is repeated in that script, 3.60 -# so instead I mangle the script itself. 3.61 - 3.62 -define htlatex 3.63 - mkdir -p $(dir $(1)) 3.64 - head -2 $(shell which htlatex) > $(dir $(1))/htlatex.book 3.65 - cp 99book.bib $(dir $@) 3.66 - echo '(cd $(dir $@) && bibtex $(basename $(notdir $@)))' >> $(dir $(1))/htlatex.book 3.67 - echo '(cd $(dir $@) && makeindex $(basename $(notdir $@)))' >> $(dir $(1))/htlatex.book 3.68 - head -3 $(shell which htlatex) >> $(dir $(1))/htlatex.book 3.69 - echo 'echo status $$$$' >> $(dir $(1))/htlatex.book 3.70 - chmod 755 $(dir $(1))/htlatex.book 3.71 - TEXINPUTS=$(dir $(2)): $(dir $(1))/htlatex.book $(2) "xhtml,html4-uni,$(3)" " -cunihtf -utf8" "" "$(call latex-options,$(1))" || (rm -f $(1); exit 1) 3.72 - cd $(dir $(1)) && tex4ht -f/$(basename $(notdir $(1))) -cvalidate -cunihtf 3.73 - cd $(dir $(1)) && t4ht -f/$(basename $(notdir $(1))) 3.74 - perl -pi -e 's/�([0-7][0-9a-f]);/chr(hex($$1))/egi' $(dir $(1))/*.html 3.75 -endef 3.76 - 3.77 -html/onepage/hgbook.html: $(sources) $(image-sources:%.svg=%.png) examples 3.78 - $(call htlatex,$@,$<) 3.79 - cp $(image-sources:%.svg=%.png) $(dir $@) 3.80 - 3.81 -html/split/hgbook.html: $(sources) $(image-sources:%.svg=%.png) examples 3.82 - $(call htlatex,$@,$<,2) 3.83 - cp $(image-sources:%.svg=%.png) $(dir $@) 3.84 - 3.85 -beta: beta/pdf/hgbook.pdf beta/html/onepage/hgbook.html beta/html/split/hgbook.html 3.86 - 3.87 -beta/%.tex: %.tex 3.88 - ./fblinks $(hg_id) $(dir $@) $< 3.89 - 3.90 -beta/pdf/hgbook.pdf: $(sources:%.tex=beta/%.tex) $(image-sources:%.svg=%.pdf) examples fblinks 3.91 - $(call pdf) 3.92 - 3.93 -beta/html/onepage/hgbook.html: $(sources:%.tex=beta/%.tex) $(image-sources:%.svg=%.png) examples 3.94 - $(call htlatex,$@,$<) 3.95 - cp $(image-sources:%.svg=%.png) $(dir $@) 3.96 - 3.97 -beta/html/split/hgbook.html: $(sources:%.tex=beta/%.tex) $(image-sources:%.svg=%.png) examples 3.98 - $(call htlatex,$@,$<,2) 3.99 - cp $(image-sources:%.svg=%.png) $(dir $@) 3.100 - 3.101 -# Produce 90dpi PNGs for the web. 3.102 - 3.103 -%.png: %.svg 3.104 - inkscape -D -e $@ $< 3.105 - 3.106 -# Produce eps & pdf for the pdf 3.107 - 3.108 -%.pdf: %.eps 3.109 - epstopdf $< 3.110 - 3.111 -%.eps: %.svg 3.112 - inkscape -E $@ $< 3.113 - 3.114 -examples: examples/.run 3.115 - 3.116 -examples/.run: $(example-sources) 3.117 - cd examples && ./run-example 3.118 - 3.119 -build_id.tex: $(wildcard ../.hg/00changelog.[id]) 3.120 - echo -n $(hg_id) > build_id.tex 3.121 - 3.122 -clean: 3.123 - rm -rf beta html pdf *.eps *.pdf *.png *.aux *.dvi *.log *.out \ 3.124 - examples/*.out examples/.run build_id.tex 3.125 +# This makefile requires GNU make. 3.126 + 3.127 +hg_id := $(shell hg parents --template '{node|short}\n' | head -1) 3.128 + 3.129 +sources := \ 3.130 + 00book.tex \ 3.131 + 99book.bib \ 3.132 + 99defs.tex \ 3.133 + build_id.tex \ 3.134 + concepts.tex \ 3.135 + daily.tex \ 3.136 + hook.tex \ 3.137 + intro.tex \ 3.138 + mq.tex \ 3.139 + preface.tex 3.140 + 3.141 +image-sources := \ 3.142 + mq-stack.svg 3.143 + 3.144 +example-sources := \ 3.145 + examples/daily.files \ 3.146 + examples/hook.simple \ 3.147 + examples/hook.ws \ 3.148 + examples/concepts \ 3.149 + examples/mq.qinit-help \ 3.150 + examples/mq.dodiff \ 3.151 + examples/mq.tarball \ 3.152 + examples/mq.tools \ 3.153 + examples/mq.tutorial 3.154 + 3.155 +latex-options = \ 3.156 + -interaction batchmode \ 3.157 + -output-directory $(dir $(1)) \ 3.158 + -jobname $(basename $(notdir $(1))) 3.159 + 3.160 +all: pdf html 3.161 + 3.162 +pdf: pdf/hgbook.pdf 3.163 + 3.164 +define pdf 3.165 + mkdir -p $(dir $@) 3.166 + TEXINPUTS=$(dir $<): pdflatex $(call latex-options,$@) $< || (rm -f $@; exit 1) 3.167 + cp 99book.bib $(dir $@) 3.168 + cd $(dir $@) && bibtex $(basename $(notdir $@)) 3.169 + cd $(dir $@) && makeindex $(basename $(notdir $@)) 3.170 + TEXINPUTS=$(dir $<): pdflatex $(call latex-options,$@) $< || (rm -f $@; exit 1) 3.171 + TEXINPUTS=$(dir $<): pdflatex $(call latex-options,$@) $< || (rm -f $@; exit 1) 3.172 + if grep 'Reference.*undefined' $(@:.pdf=.log); then exit 1; fi 3.173 +endef 3.174 + 3.175 +pdf/hgbook.pdf: $(sources) $(image-sources:%.svg=%.pdf) examples 3.176 + $(call pdf) 3.177 + 3.178 +html: html/onepage/hgbook.html html/split/hgbook.html 3.179 + 3.180 +# This is a horrible hack to work around the fact that the htlatex 3.181 +# command in tex4ht is itself a horrible hack. I really don't want to 3.182 +# include verbatim the big wad of TeX that is repeated in that script, 3.183 +# so instead I mangle the script itself. 3.184 + 3.185 +define htlatex 3.186 + mkdir -p $(dir $(1)) 3.187 + head -2 $(shell which htlatex) > $(dir $(1))/htlatex.book 3.188 + cp 99book.bib $(dir $@) 3.189 + echo '(cd $(dir $@) && bibtex $(basename $(notdir $@)))' >> $(dir $(1))/htlatex.book 3.190 + echo '(cd $(dir $@) && makeindex $(basename $(notdir $@)))' >> $(dir $(1))/htlatex.book 3.191 + head -3 $(shell which htlatex) >> $(dir $(1))/htlatex.book 3.192 + echo 'echo status $$$$' >> $(dir $(1))/htlatex.book 3.193 + chmod 755 $(dir $(1))/htlatex.book 3.194 + TEXINPUTS=$(dir $(2)): $(dir $(1))/htlatex.book $(2) "xhtml,html4-uni,$(3)" " -cunihtf -utf8" "" "$(call latex-options,$(1))" || (rm -f $(1); exit 1) 3.195 + cd $(dir $(1)) && tex4ht -f/$(basename $(notdir $(1))) -cvalidate -cunihtf 3.196 + cd $(dir $(1)) && t4ht -f/$(basename $(notdir $(1))) 3.197 + perl -pi -e 's/�([0-7][0-9a-f]);/chr(hex($$1))/egi' $(dir $(1))/*.html 3.198 +endef 3.199 + 3.200 +html/onepage/hgbook.html: $(sources) $(image-sources:%.svg=%.png) examples 3.201 + $(call htlatex,$@,$<) 3.202 + cp $(image-sources:%.svg=%.png) $(dir $@) 3.203 + 3.204 +html/split/hgbook.html: $(sources) $(image-sources:%.svg=%.png) examples 3.205 + $(call htlatex,$@,$<,2) 3.206 + cp $(image-sources:%.svg=%.png) $(dir $@) 3.207 + 3.208 +beta: beta/pdf/hgbook.pdf beta/html/onepage/hgbook.html beta/html/split/hgbook.html 3.209 + 3.210 +beta/%.tex: %.tex 3.211 + ./fblinks $(hg_id) $(dir $@) $< 3.212 + 3.213 +beta/pdf/hgbook.pdf: $(sources:%.tex=beta/%.tex) $(image-sources:%.svg=%.pdf) examples fblinks 3.214 + $(call pdf) 3.215 + 3.216 +beta/html/onepage/hgbook.html: $(sources:%.tex=beta/%.tex) $(image-sources:%.svg=%.png) examples 3.217 + $(call htlatex,$@,$<) 3.218 + cp $(image-sources:%.svg=%.png) $(dir $@) 3.219 + 3.220 +beta/html/split/hgbook.html: $(sources:%.tex=beta/%.tex) $(image-sources:%.svg=%.png) examples 3.221 + $(call htlatex,$@,$<,2) 3.222 + cp $(image-sources:%.svg=%.png) $(dir $@) 3.223 + 3.224 +# Produce 90dpi PNGs for the web. 3.225 + 3.226 +%.png: %.svg 3.227 + inkscape -D -e $@ $< 3.228 + 3.229 +# Produce eps & pdf for the pdf 3.230 + 3.231 +%.pdf: %.eps 3.232 + epstopdf $< 3.233 + 3.234 +%.eps: %.svg 3.235 + inkscape -E $@ $< 3.236 + 3.237 +examples: examples/.run 3.238 + 3.239 +examples/.run: $(example-sources:%=%.run) 3.240 + touch examples/.run 3.241 + 3.242 +examples/%.run: examples/% examples/run-example 3.243 + cd examples && ./run-example $(notdir $<) 3.244 + 3.245 +build_id.tex: $(wildcard ../.hg/00changelog.[id]) 3.246 + echo -n $(hg_id) > build_id.tex 3.247 + 3.248 +clean: 3.249 + rm -rf beta html pdf *.eps *.pdf *.png *.aux *.dvi *.log *.out \ 3.250 + examples/*.{out,run} examples/.run build_id.tex
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/en/daily.tex Tue Jul 25 00:02:24 2006 -0400 4.3 @@ -0,0 +1,129 @@ 4.4 +\chapter{Mercurial in daily use} 4.5 +\label{chap:daily} 4.6 + 4.7 +\section{Routine file management tasks} 4.8 + 4.9 +\subsection{Telling Mercurial which files to track} 4.10 + 4.11 +Mercurial does not work with files in your repository unless you tell 4.12 +it to manage them. The \hgcmd{status} command will tell you which 4.13 +files Mercurial doesn't know about; it uses a ``\texttt{?}'' to 4.14 +display such files. 4.15 + 4.16 +To tell Mercurial to track a file, use the \hgcmd{add} command. Once 4.17 +you have added a file, the entry in the output of \hgcmd{status} for 4.18 +that file changes from ``\texttt{?}'' to ``\texttt{A}''. 4.19 + 4.20 +After you run a \hgcmd{commit}, the files that you added before the 4.21 +commit will no longer be listed in the output of \hgcmd{status}. The 4.22 +reason for this is that \hgcmd{status} only tells you about 4.23 +``interesting'' files by default. If you have a repository that 4.24 +contains thousands of files, you will rarely want to know about files 4.25 +that Mercurial is tracking, but that have not changed. (You can still 4.26 +get this information; we'll return to this later.) 4.27 + 4.28 +\begin{figure}[ht] 4.29 + \interaction{daily.files.add} 4.30 + \caption{Telling Mercurial to track a file} 4.31 + \label{ex:daily:add} 4.32 +\end{figure} 4.33 + 4.34 +Once you add a file, Mercurial will track every change you make to it 4.35 +until you either remove or rename the file. 4.36 + 4.37 +\subsubsection{Aside: Mercurial tracks files, not directories} 4.38 + 4.39 +Mercurial does not track directory information. Instead, it tracks 4.40 +the path to a file, and creates directories along a path when it needs 4.41 +to. This sounds like a trivial distinction, but it has one minor 4.42 +practical consequence: it is not possible to represent a completely 4.43 +empty directory in Mercurial. 4.44 + 4.45 +Empty directories are rarely useful, and there are unintrusive 4.46 +workarounds that you can use to achieve an appropriate effect. The 4.47 +developers of Mercurial thus felt that the complexity that would be 4.48 +required to manage empty directories was not worth the limited benefit 4.49 +this feature would bring. 4.50 + 4.51 +If you need an empty directory in your repository, there are a few 4.52 +ways to achieve this. One is to create a directory, then \hgcmd{add} a 4.53 +``hidden'' file to that directory. On Unix-like systems, any file 4.54 +name that begins with a period (``\texttt{.}'') is treated as hidden 4.55 +by most commands and GUI tools. This approach is illustrated in 4.56 +figure~\ref{ex:daily:hidden}. 4.57 + 4.58 +\begin{figure}[ht] 4.59 + \interaction{daily.files.hidden} 4.60 + \caption{Simulating an empty directory using a hidden file} 4.61 + \label{ex:daily:hidden} 4.62 +\end{figure} 4.63 + 4.64 +Another way to tackle a need for an empty directory is to simply 4.65 +create one in your automated build scripts before they will need it. 4.66 + 4.67 +\subsection{How to stop tracking a file} 4.68 + 4.69 +If you decide that a file no longer belongs in your repository, use 4.70 +the \hgcmd{remove} command; this deletes the file, and tells Mercurial 4.71 +to stop tracking it. A removed file is represented in the output of 4.72 +\hgcmd{status} with a ``\texttt{R}''. 4.73 + 4.74 +You might wonder why Mercurial requires you to explicitly tell it that 4.75 +you are deleting a file. Earlier during the development of Mercurial, 4.76 +you could simply delete a file however you pleased; Mercurial would 4.77 +notice automatically when you next ran a \hgcmd{commit}, and stop 4.78 +tracking the file. In practice, this made it too easy to accidentally 4.79 +stop Mercurial from tracking a file. 4.80 + 4.81 +Mercurial considers a file that you have deleted, but not used 4.82 +\hgcmd{remove} to delete, to be \emph{missing}. A missing file is 4.83 +represented with ``\texttt{!}'' in the output of \hgcmd{status}. 4.84 +Other Mercurial commands will not do anything with missing files. 4.85 + 4.86 +If you have a missing file in your repository, you can run 4.87 +\hgcmdargs{remove}{\hgopt{remove}{--after}} later on, to tell 4.88 +Mercurial that you deleted the file. If you deleted the file by 4.89 +accident, use \hgcmdargs{revert}{\emph{filename}} to restore the file 4.90 +to its last committed state. 4.91 + 4.92 +\subsection{Useful shorthand---adding and removing files in one step} 4.93 + 4.94 +Mercurial offers a combination command, \hgcmd{addremove}, that adds 4.95 +untracked files and marks missing files as removed. The 4.96 +\hgcmd{commit} command also provides a \hgopt{commit}{-A} option that 4.97 +performs an add-and-remove, immediately followed by a commit. This 4.98 +lets you replace the following command sequence: 4.99 +\begin{codesample2} 4.100 + hg add 4.101 + hg remove --after 4.102 + hg commit 4.103 +\end{codesample2} 4.104 +with a single command, \hgcmdargs{commit}{\hgopt{commit}{-A}}. 4.105 + 4.106 +\subsection{Renaming files} 4.107 + 4.108 +To rename a file that is tracked by Mercurial, use the \hgcmd{rename} 4.109 +command. This command behaves similarly to the Unix \command{mv} 4.110 +command. If the last argument is a directory, it moves all prior 4.111 +arguments into that directory. Otherwise, it renames a single file or 4.112 +directory to the name given in the last argument. 4.113 + 4.114 +As with \hgcmd{remove}, you can tell Mercurial about a rename after 4.115 +the fact using the \hgopt{remove}{--after} option. 4.116 + 4.117 +The na\"{i}ve way to ``rename'' a file is simply to rename the file 4.118 +yourself, \hgcmd{remove} the old name, and \hgcmd{add} the new name. 4.119 +However, if you do this, Mercurial will not know that there was any 4.120 +relationship between the files in question, and it will not be able to 4.121 +merge 4.122 + 4.123 +\subsection{Copying files} 4.124 + 4.125 +You can copy a file in two ways using mercurial. If you simply copy a 4.126 +file and then \hgcmd{add} the new file, Mercurial will not know that 4.127 +there was any relationship between the two files. However, if you 4.128 + 4.129 +%%% Local Variables: 4.130 +%%% mode: latex 4.131 +%%% TeX-master: "00book" 4.132 +%%% End:
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/en/examples/daily.files Tue Jul 25 00:02:24 2006 -0400 5.3 @@ -0,0 +1,22 @@ 5.4 +#!/bin/bash 5.5 + 5.6 +#$ name: add 5.7 + 5.8 +hg init a 5.9 +cd a 5.10 +echo content > filename 5.11 +mkdir subdir 5.12 +echo something > subdir/otherfile 5.13 +hg status 5.14 + 5.15 +#$ name: hidden 5.16 + 5.17 +mkdir empty 5.18 +touch empty/.hidden 5.19 +hg add empty/.hidden 5.20 +hg commit -m 'Manage an empty-looking directory' 5.21 +ls empty 5.22 +cd .. 5.23 +hg clone a b 5.24 +ls b 5.25 +ls b/empty
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/en/examples/data/check_whitespace.py Tue Jul 25 00:02:24 2006 -0400 6.3 @@ -0,0 +1,31 @@ 6.4 +#!/usr/bin/python 6.5 + 6.6 +import os, re, sys 6.7 + 6.8 +count = 0 6.9 + 6.10 +for line in os.popen('hg export tip'): 6.11 + # remember the name of the file that this diff affects 6.12 + m = re.match(r'^--- [^/]/([^\t])', line) 6.13 + if m: 6.14 + filename = m.group(1) 6.15 + continue 6.16 + # remember the line number 6.17 + m = re.match(r'^@@ -(\d+),') 6.18 + if m: 6.19 + linenum = m.group(1) 6.20 + continue 6.21 + linenum += 1 6.22 + # check for an added line with trailing whitespace 6.23 + m = re.match(r'^\+.*\s$', line) 6.24 + if m: 6.25 + print >> sys.stderr, ('%s:%d: trailing whitespace introduced' % 6.26 + (filename, linenum)) 6.27 + count += 1 6.28 + 6.29 +if count: 6.30 + # save the commit message so we don't need to retype it 6.31 + os.system('hg tip --template "{desc}" > .hg/commit.save') 6.32 + print >> sys.stderr, 'commit message saved to .hg/commit.save' 6.33 + 6.34 +sys.exit(count)
7.1 --- a/en/examples/hook.simple Mon Jul 24 23:57:52 2006 -0400 7.2 +++ b/en/examples/hook.simple Tue Jul 25 00:02:24 2006 -0400 7.3 @@ -1,3 +1,5 @@ 7.4 +#!/bin/bash 7.5 + 7.6 #$ name: init 7.7 7.8 hg init hook-test
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/en/examples/hook.ws Tue Jul 25 00:02:24 2006 -0400 8.3 @@ -0,0 +1,14 @@ 8.4 +#!/bin/bash 8.5 + 8.6 +cp $EXAMPLE_DIR/data/check_whitespace.py . 8.7 + 8.8 +hg init a 8.9 +cd a 8.10 +echo '[hooks]' > .hg/hgrc 8.11 +echo "pretxncommit.whitespace = hg export tip | (! grep -qP '^\\+.*[ \\t]$')" >> .hg/hgrc 8.12 + 8.13 +#$ name: simple 8.14 + 8.15 +cat .hg/hgrc 8.16 +echo 'a ' > a 8.17 +hg commit -A -m 'test with trailing whitespace'
9.1 --- a/en/examples/mq.diff Mon Jul 24 23:57:52 2006 -0400 9.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 9.3 @@ -1,12 +0,0 @@ 9.4 -#$ name: diff 9.5 - 9.6 -echo 'this is my first line' > oldfile 9.7 -echo 'my first line is here' > newfile 9.8 - 9.9 -diff -u oldfile newfile > tiny.patch 9.10 - 9.11 -cat tiny.patch 9.12 - 9.13 -patch < tiny.patch 9.14 - 9.15 -cat newfile
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/en/examples/mq.dodiff Tue Jul 25 00:02:24 2006 -0400 10.3 @@ -0,0 +1,14 @@ 10.4 +#!/bin/bash 10.5 + 10.6 +#$ name: diff 10.7 + 10.8 +echo 'this is my first line' > oldfile 10.9 +echo 'my first line is here' > newfile 10.10 + 10.11 +diff -u oldfile newfile > tiny.patch 10.12 + 10.13 +cat tiny.patch 10.14 + 10.15 +patch < tiny.patch 10.16 + 10.17 +cat newfile
11.1 --- a/en/examples/mq.qinit-help Mon Jul 24 23:57:52 2006 -0400 11.2 +++ b/en/examples/mq.qinit-help Tue Jul 25 00:02:24 2006 -0400 11.3 @@ -1,3 +1,5 @@ 11.4 +#!/bin/bash 11.5 + 11.6 echo '[extensions]' >> $HGRC 11.7 echo 'hgext.mq =' >> $HGRC 11.8
12.1 --- a/en/examples/mq.tarball Mon Jul 24 23:57:52 2006 -0400 12.2 +++ b/en/examples/mq.tarball Tue Jul 25 00:02:24 2006 -0400 12.3 @@ -1,3 +1,5 @@ 12.4 +#!/bin/bash 12.5 + 12.6 cp $EXAMPLE_DIR/data/netplug-*.tar.bz2 . 12.7 ln -s /bin/true download 12.8
13.1 --- a/en/examples/mq.tools Mon Jul 24 23:57:52 2006 -0400 13.2 +++ b/en/examples/mq.tools Tue Jul 25 00:02:24 2006 -0400 13.3 @@ -1,3 +1,5 @@ 13.4 +#!/bin/bash 13.5 + 13.6 cp $EXAMPLE_DIR/data/remove-redundant-null-checks.patch . 13.7 13.8 #$ name: tools
14.1 --- a/en/examples/mq.tutorial Mon Jul 24 23:57:52 2006 -0400 14.2 +++ b/en/examples/mq.tutorial Tue Jul 25 00:02:24 2006 -0400 14.3 @@ -1,3 +1,5 @@ 14.4 +#!/bin/bash 14.5 + 14.6 echo '[extensions]' >> $HGRC 14.7 echo 'hgext.mq =' >> $HGRC 14.8
15.1 --- a/en/examples/run-example Mon Jul 24 23:57:52 2006 -0400 15.2 +++ b/en/examples/run-example Tue Jul 25 00:02:24 2006 -0400 15.3 @@ -10,6 +10,7 @@ 15.4 import re 15.5 import shutil 15.6 import signal 15.7 +import stat 15.8 import sys 15.9 import tempfile 15.10 import time 15.11 @@ -121,6 +122,7 @@ 15.12 # then its output 15.13 ofp.write(tex_escape(output)) 15.14 self.status('\n') 15.15 + open(self.name + '.run', 'w') 15.16 finally: 15.17 try: 15.18 output = self.sendreceive('exit\n') 15.19 @@ -142,8 +144,10 @@ 15.20 for name in os.listdir(path): 15.21 if name == 'run-example' or name.startswith('.'): continue 15.22 if name.endswith('.out') or name.endswith('~'): continue 15.23 + if name.endswith('.run'): continue 15.24 pathname = os.path.join(path, name) 15.25 - if os.path.isfile(pathname): 15.26 + st = os.lstat(pathname) 15.27 + if stat.S_ISREG(st.st_mode) and st.st_mode & 0111: 15.28 example(pathname).run() 15.29 print >> open(os.path.join(path, '.run'), 'w'), time.asctime() 15.30
16.1 --- a/en/hook.tex Mon Jul 24 23:57:52 2006 -0400 16.2 +++ b/en/hook.tex Tue Jul 25 00:02:24 2006 -0400 16.3 @@ -9,6 +9,207 @@ 16.4 Hooks are called ``triggers'' in some revision control systems, but 16.5 the two names refer to the same idea. 16.6 16.7 +\section{An overview of hooks in Mercurial} 16.8 + 16.9 +Here is a brief list of the hooks that Mercurial supports. We will 16.10 +revisit each of these hooks in more detail later, in 16.11 +section~\ref{sec:hook:ref}. 16.12 + 16.13 +\begin{itemize} 16.14 +\item[\small\hook{changegroup}] This is run after a group of 16.15 + changesets has been brought into the repository from elsewhere. 16.16 +\item[\small\hook{commit}] This is run after a new changeset has been 16.17 + created in the local repository. 16.18 +\item[\small\hook{incoming}] This is run once for each new changeset 16.19 + that is brought into the repository from elsewhere. Notice the 16.20 + difference from \hook{changegroup}, which is run once per 16.21 + \emph{group} of changesets brought in. 16.22 +\item[\small\hook{outgoing}] This is run after a group of changesets 16.23 + has been transmitted from this repository. 16.24 +\item[\small\hook{prechangegroup}] This is run before starting to 16.25 + bring a group of changesets into the repository. 16.26 +\item[\small\hook{precommit}] Controlling. This is run before starting 16.27 + a commit. 16.28 +\item[\small\hook{preoutgoing}] Controlling. This is run before 16.29 + starting to transmit a group of changesets from this repository. 16.30 +\item[\small\hook{pretag}] Controlling. This is run before creating a tag. 16.31 +\item[\small\hook{pretxnchangegroup}] Controlling. This is run after a 16.32 + group of changesets has been brought into the local repository from 16.33 + another, but before the transaction completes that will make the 16.34 + changes permanent in the repository. 16.35 +\item[\small\hook{pretxncommit}] Controlling. This is run after a new 16.36 + changeset has been created in the local repository, but before the 16.37 + transaction completes that will make it permanent. 16.38 +\item[\small\hook{preupdate}] Controlling. This is run before starting 16.39 + an update or merge of the working directory. 16.40 +\item[\small\hook{tag}] This is run after a tag is created. 16.41 +\item[\small\hook{update}] This is run after an update or merge of the 16.42 + working directory has finished. 16.43 +\end{itemize} 16.44 +Each of the hooks whose description begins with the word 16.45 +``Controlling'' has the ability to determine whether an activity can 16.46 +proceed. If the hook succeeds, the activity may proceed; if it fails, 16.47 +the activity is either not permitted or undone, depending on the hook. 16.48 + 16.49 +\section{Hooks and security} 16.50 + 16.51 +\subsection{Hooks are run with your privileges} 16.52 + 16.53 +When you run a Mercurial command in a repository, and the command 16.54 +causes a hook to run, that hook runs on \emph{your} system, under 16.55 +\emph{your} user account, with \emph{your} privilege level. Since 16.56 +hooks are arbitrary pieces of executable code, you should treat them 16.57 +with an appropriate level of suspicion. Do not install a hook unless 16.58 +you are confident that you know who created it and what it does. 16.59 + 16.60 +In some cases, you may be exposed to hooks that you did not install 16.61 +yourself. If you work with Mercurial on an unfamiliar system, 16.62 +Mercurial will run hooks defined in that system's global \hgrc\ file. 16.63 + 16.64 +If you are working with a repository owned by another user, Mercurial 16.65 +can run hooks defined in that user's repository, but it will still run 16.66 +them as ``you''. For example, if you \hgcmd{pull} from that 16.67 +repository, and its \sfilename{.hg/hgrc} defines a local 16.68 +\hook{outgoing} hook, that hook will run under your user account, even 16.69 +though you don't own that repository. 16.70 + 16.71 +\begin{note} 16.72 + This only applies if you are pulling from a repository on a local or 16.73 + network filesystem. If you're pulling over http or ssh, any 16.74 + \hook{outgoing} hook will run under whatever account is executing 16.75 + the server process, on the server. 16.76 +\end{note} 16.77 + 16.78 +XXX To see what hooks are defined in a repository, use the 16.79 +\hgcmdargs{config}{hooks} command. If you are working in one 16.80 +repository, but talking to another that you do not own (e.g.~using 16.81 +\hgcmd{pull} or \hgcmd{incoming}), remember that it is the other 16.82 +repository's hooks you should be checking, not your own. 16.83 + 16.84 +\subsection{Hooks do not propagate} 16.85 + 16.86 +In Mercurial, hooks are not revision controlled, and do not propagate 16.87 +when you clone, or pull from, a repository. The reason for this is 16.88 +simple: a hook is a completely arbitrary piece of executable code. It 16.89 +runs under your user identity, with your privilege level, on your 16.90 +machine. 16.91 + 16.92 +It would be extremely reckless for any distributed revision control 16.93 +system to implement revision-controlled hooks, as this would offer an 16.94 +easily exploitable way to subvert the accounts of users of the 16.95 +revision control system. 16.96 + 16.97 +Since Mercurial does not propagate hooks, if you are collaborating 16.98 +with other people on a common project, you should not assume that they 16.99 +are using the same Mercurial hooks as you are, or that theirs are 16.100 +correctly configured. You should document the hooks you expect people 16.101 +to use. 16.102 + 16.103 +In a corporate intranet, this is somewhat easier to control, as you 16.104 +can for example provide a ``standard'' installation of Mercurial on an 16.105 +NFS filesystem, and use a site-wide \hgrc\ file to define hooks that 16.106 +all users will see. However, this too has its limits; see below. 16.107 + 16.108 +\subsection{Hooks can be overridden} 16.109 + 16.110 +Mercurial allows you to override a hook definition by redefining the 16.111 +hook. You can disable it by setting its value to the empty string, or 16.112 +change its behaviour as you wish. 16.113 + 16.114 +If you deploy a system-~or site-wide \hgrc\ file that defines some 16.115 +hooks, you should thus understand that your users can disable or 16.116 +override those hooks. 16.117 + 16.118 +\subsection{Ensuring that critical hooks are run} 16.119 + 16.120 +Sometimes you may want to enforce a policy that you do not want others 16.121 +to be able to work around. For example, you may have a requirement 16.122 +that every changeset must pass a rigorous set of tests. Defining this 16.123 +requirement via a hook in a site-wide \hgrc\ won't work for remote 16.124 +users on laptops, and of course local users can subvert it at will by 16.125 +overriding the hook. 16.126 + 16.127 +Instead, you can set up your policies for use of Mercurial so that 16.128 +people are expected to propagate changes through a well-known 16.129 +``canonical'' server that you have locked down and configured 16.130 +appropriately. 16.131 + 16.132 +One way to do this is via a combination of social engineering and 16.133 +technology. Set up a restricted-access account; users can push 16.134 +changes over the network to repositories managed by this account, but 16.135 +they cannot log into the account and run normal shell commands. In 16.136 +this scenario, a user can commit a changeset that contains any old 16.137 +garbage they want. 16.138 + 16.139 +When someone pushes a changeset to the server that everyone pulls 16.140 +from, the server will test the changeset before it accepts it as 16.141 +permanent, and reject it if it fails to pass the test suite. If 16.142 +people only pull changes from this filtering server, it will serve to 16.143 +ensure that all changes that people pull have been automatically 16.144 +vetted. 16.145 + 16.146 +\section{Using hooks with shared access to a repository} 16.147 + 16.148 +If you want to use hooks to so some automated work in a repository 16.149 +that a number of people have ahred access to, you need to be careful 16.150 +in how you do this. 16.151 + 16.152 +Mercurial only locks a repository when it is writing to the 16.153 +repository, and only the parts of Mercurial that write to the 16.154 +repository pay attention to locks. Write locks are necessary to 16.155 +prevent multiple simultaneous writers from scribbling on each other's 16.156 +work, corrupting the repository. 16.157 + 16.158 +Because Mercurial is careful with the order in which it reads and 16.159 +writes data, it does not need to acquire a lock when it wants to read 16.160 +data from the repository. The parts of Mercurial that read from the 16.161 +repository never pay attention to locks. This lockless reading scheme 16.162 +greatly increases performance and concurrency. 16.163 + 16.164 +With great performance comes a trade-off, though, one which has the 16.165 +potential to cause you trouble unless you're aware of it. To describe 16.166 +this requires a little detail about how Mercurial adds changesets to a 16.167 +repository and reads those changes. 16.168 + 16.169 +When Mercurial \emph{writes} metadata, it writes it straight into the 16.170 +destination file. It writes file data first, then manifest data 16.171 +(which contains pointers to the new file data), then changelog data 16.172 +(which contains pointers to the new manifest data). Before the first 16.173 +write to each file, it stores a record of where the end of the file 16.174 +was in its transaction log. If the transaction must be rolled back, 16.175 +Mercurial simply truncates each file back to te size it was before the 16.176 +transaction began. 16.177 + 16.178 +When Mercurial \emph{reads} metadata, it reads the changelog first, 16.179 +then everything else. Since a reader will only access parts of the 16.180 +manifest or file metadata that it can see in the changelog, it can 16.181 +never see partially written data. 16.182 + 16.183 +Some controlling hooks (\hook{pretxncommit} and 16.184 +\hook{pretxnchangegroup}) run when a transaction is almost complete. 16.185 +All of the metadata has been written, but Mercurial can still roll the 16.186 +transaction back and cause the newly-written data to disappear. 16.187 + 16.188 +If one of these hooks runs for long, it opens a window in which a 16.189 +reader can see the metadata for changesets that are, strictly 16.190 +speaking, not yet permanent. The longer the hook runs, the bigger the 16.191 +window. 16.192 + 16.193 +A good use for the \hook{pretxnchangegroup} hook would be to 16.194 +automatically build and test incoming changes before they are accepted 16.195 +into the repository, so that you can guarantee that nobody can push 16.196 +changes to this repository that ``break the build''. But if a client 16.197 +can pull changes while they're being tested, the usefulness of the 16.198 +test is zero; someone can pull untested changes. 16.199 + 16.200 +The safest answer to this challenge is to set up such a ``gatekeeper'' 16.201 +repository as \emph{unidirectional}. It can take changes pushed in 16.202 +from the outside, but nobody can pull changes from it. Use the 16.203 +\hook{preoutgoing} hook to lock it down. Configure a 16.204 +\hook{changegroup} hook so that if a build or test succeeds, the hook 16.205 +will push the new changes out to another repository that people 16.206 +\emph{can} pull from. 16.207 + 16.208 \section{A short tutorial on using hooks} 16.209 \label{sec:hook:simple} 16.210 16.211 @@ -95,11 +296,18 @@ 16.212 comment contains a bug ID. If it does, the commit can complete. If 16.213 not, the commit is rolled back. 16.214 16.215 -\section{Choosing how to write a hook} 16.216 -\label{sec:hook:impl} 16.217 +\section{Writing your own hooks} 16.218 + 16.219 +When you are writing a hook, you might find it useful to run Mercurial 16.220 +either with the \hggopt{-v} option, or the \rcitem{ui}{verbose} config 16.221 +item set to ``true''. When you do so, Mercurial will print a message 16.222 +before it calls each hook. 16.223 + 16.224 +\subsection{Choosing how your hook should run} 16.225 +\label{sec:hook:lang} 16.226 16.227 You can write a hook either as a normal program---typically a shell 16.228 -script---or as a Python function that is called within the Mercurial 16.229 +script---or as a Python function that is executed within the Mercurial 16.230 process. 16.231 16.232 Writing a hook as an external program has the advantage that it 16.233 @@ -119,7 +327,7 @@ 16.234 performance (probably the majority of hooks), a shell script is 16.235 perfectly fine. 16.236 16.237 -\section{Hook parameters} 16.238 +\subsection{Hook parameters} 16.239 \label{sec:hook:param} 16.240 16.241 Mercurial calls each hook with a set of well-defined parameters. In 16.242 @@ -128,10 +336,468 @@ 16.243 environment variable. 16.244 16.245 Whether your hook is written in Python or as a shell script, the 16.246 -parameter names and values will be the same. A boolean parameter will 16.247 -be represented as a boolean value in Python, but as the number 1 (for 16.248 -``true'') or 0 (for ``false'') 16.249 - 16.250 +hook-specific parameter names and values will be the same. A boolean 16.251 +parameter will be represented as a boolean value in Python, but as the 16.252 +number 1 (for ``true'') or 0 (for ``false'') as an environment 16.253 +variable for an external hook. If a hook parameter is named 16.254 +\texttt{foo}, the keyword argument for a Python hook will also be 16.255 +named \texttt{foo} Python, while the environment variable for an 16.256 +external hook will be named \texttt{HG\_FOO}. 16.257 + 16.258 +\subsection{Hook return values and activity control} 16.259 + 16.260 +A hook that executes successfully must exit with a status of zero if 16.261 +external, or return boolean ``false'' if in-process. Failure is 16.262 +indicated with a non-zero exit status from an external hook, or an 16.263 +in-process hook returning boolean ``true''. If an in-process hook 16.264 +raises an exception, the hook is considered to have failed. 16.265 + 16.266 +For a hook that controls whether an activity can proceed, zero/false 16.267 +means ``allow'', while non-zero/true/exception means ``deny''. 16.268 + 16.269 +\subsection{Writing an external hook} 16.270 + 16.271 +When you define an external hook in your \hgrc\ and the hook is run, 16.272 +its value is passed to your shell, which interprets it. This means 16.273 +that you can use normal shell constructs in the body of the hook. 16.274 + 16.275 +An executable hook is always run with its current directory set to a 16.276 +repository's root directory. 16.277 + 16.278 +Each hook parameter is passed in as an environment variable; the name 16.279 +is upper-cased, and prefixed with the string ``\texttt{HG\_}''. 16.280 + 16.281 +With the exception of hook parameters, Mercurial does not set or 16.282 +modify any environment variables when running a hook. This is useful 16.283 +to remember if you are writing a site-wide hook that may be run by a 16.284 +number of different users with differing environment variables set. 16.285 +In multi-user situations, you should not rely on environment variables 16.286 +being set to the values you have in your environment when testing the 16.287 +hook. 16.288 + 16.289 +\subsection{Telling Mercurial to use an in-process hook} 16.290 + 16.291 +The \hgrc\ syntax for defining an in-process hook is slightly 16.292 +different than for an executable hook. The value of the hook must 16.293 +start with the text ``\texttt{python:}'', and continue with the 16.294 +fully-qualified name of a callable object to use as the hook's value. 16.295 + 16.296 +The module in which a hook lives is automatically imported when a hook 16.297 +is run. So long as you have the module name and \envar{PYTHONPATH} 16.298 +right, it should ``just work''. 16.299 + 16.300 +The following \hgrc\ example snippet illustrates the syntax and 16.301 +meaning of the notions we just described. 16.302 +\begin{codesample2} 16.303 + [hooks] 16.304 + commit.example = python:mymodule.submodule.myhook 16.305 +\end{codesample2} 16.306 +When Mercurial runs the \texttt{commit.example} hook, it imports 16.307 +\texttt{mymodule.submodule}, looks for the callable object named 16.308 +\texttt{myhook}, and calls it. 16.309 + 16.310 +\subsection{Writing an in-process hook} 16.311 + 16.312 +The simplest in-process hook does nothing, but illustrates the basic 16.313 +shape of the hook API: 16.314 +\begin{codesample2} 16.315 + def myhook(ui, repo, **kwargs): 16.316 + pass 16.317 +\end{codesample2} 16.318 +The first argument to a Python hook is always a 16.319 +\pymodclass{mercurial.ui}{ui} object. The second is a repository object; 16.320 +at the moment, it is always an instance of 16.321 +\pymodclass{mercurial.localrepo}{localrepository}. Following these two 16.322 +arguments are other keyword arguments. Which ones are passed in 16.323 +depends on the hook being called, but a hook can ignore arguments it 16.324 +doesn't care about by dropping them into a keyword argument dict, as 16.325 +with \texttt{**kwargs} above. 16.326 + 16.327 +\section{Some hook examples} 16.328 + 16.329 +\subsection{Enforcing coding guidelines in your own repository} 16.330 + 16.331 +An interesting use of a commit-related hook is to help you to write 16.332 +cleaner code. A simple example of ``cleaner code'' is the dictum that 16.333 +a change should not add any new lines of text that contain ``trailing 16.334 +whitespace''. Trailing whitespace is a series of space and tab 16.335 +characters at the end of a line of text. In most cases, trailing 16.336 +whitespace is unnecessary, invisible noise, but it is occasionally 16.337 +problematic, and people tend to prefer to get rid of it. 16.338 + 16.339 +You can use either the \hook{precommit} or \hook{pretxncommit} hook to 16.340 +tell whether you have a trailing whitespace problem. If you use the 16.341 +\hook{precommit} hook, the hook will not know which files you are 16.342 +committing, so it will have to check every modified file in the 16.343 +repository for trailing white space. If you want to commit a change 16.344 +to just the file \filename{foo}, but the file \filename{bar} contains 16.345 +trailing whitespace, doing a check in the \hook{precommit} hook will 16.346 +prevent you from committing \filename{foo} due to the problem with 16.347 +\filename{bar}. This doesn't seem right. 16.348 + 16.349 +Should you choose the \hook{pretxncommit} hook, the check won't occur 16.350 +until just before the transaction for the commit completes. This will 16.351 +allow you to check for problems only the exact files that are being 16.352 +committed. However, if you entered the commit message interactively 16.353 +and the hook fails, the transaction will roll back; you'll have to 16.354 +re-enter the commit message after you fix the trailing whitespace and 16.355 +run \hgcmd{commit} again. 16.356 + 16.357 +\begin{figure}[ht] 16.358 + \interaction{hook.ws.simple} 16.359 + \caption{A simple hook that checks for trailing whitespace} 16.360 + \label{ex:hook:ws.simple} 16.361 +\end{figure} 16.362 + 16.363 +Figure~\ref{ex:hook:ws.simple} introduces a simple \hook{pretxncommit} 16.364 +hook that checks for trailing whitespace. This hook is short, but not 16.365 +very helpful. It exits with an error status if a change adds a line 16.366 +with trailing whitespace to any file, but does not print any 16.367 +information that might help us to identify the offending file or line. 16.368 + 16.369 +\section{Hook reference} 16.370 +\label{sec:hook:ref} 16.371 + 16.372 +\subsection{In-process hook execution} 16.373 + 16.374 +An in-process hook is called with arguments of the following form: 16.375 +\begin{codesample2} 16.376 + def myhook(ui, repo, **kwargs): 16.377 + pass 16.378 +\end{codesample2} 16.379 +The \texttt{ui} parameter is a \pymodclass{mercurial.ui}{ui} object. 16.380 +The \texttt{repo} parameter is a 16.381 +\pymodclass{mercurial.localrepo}{localrepository} object. The 16.382 +names and values of the \texttt{**kwargs} parameters depend on the 16.383 +hook being invoked, with the following common features: 16.384 +\begin{itemize} 16.385 +\item If a parameter is named \texttt{node} or 16.386 + \texttt{parent\emph{N}}, it will contain a hexadecimal changeset ID. 16.387 + The empty string is used to represent ``null changeset ID'' instead 16.388 + of a string of zeroes. 16.389 +\item Boolean-valued parameters are represented as Python 16.390 + \texttt{bool} objects. 16.391 +\end{itemize} 16.392 + 16.393 +An in-process hook is called without a change to the process's working 16.394 +directory (unlike external hooks, which are run in the root of the 16.395 +repository). It must not change the process's working directory. If 16.396 +it were to do so, it would probably cause calls to the Mercurial API, 16.397 +or operations after the hook finishes, to fail. 16.398 + 16.399 +If a hook returns a boolean ``false'' value, it is considered to 16.400 +have succeeded. If it returns a boolean ``true'' value or raises an 16.401 +exception, it is considered to have failed. 16.402 + 16.403 +\subsection{External hook execution} 16.404 + 16.405 +An external hook is passed to the user's shell for execution, so 16.406 +features of that shell, such as variable substitution and command 16.407 +redirection, are available. The hook is run in the root directory of 16.408 +the repository. 16.409 + 16.410 +Hook parameters are passed to the hook as environment variables. Each 16.411 +environment variable's name is converted in upper case and prefixed 16.412 +with the string ``\texttt{HG\_}''. For example, if the name of a 16.413 +parameter is ``\texttt{node}'', the name of the environment variable 16.414 +representing that parameter will be ``\texttt{HG\_NODE}''. 16.415 + 16.416 +A boolean parameter is represented as the string ``\texttt{1}'' for 16.417 +``true'', ``\texttt{0}'' for ``false''. If an environment variable is 16.418 +named \envar{HG\_NODE}, \envar{HG\_PARENT1} or \envar{HG\_PARENT2}, it 16.419 +contains a changeset ID represented as a hexadecimal string. The 16.420 +empty string is used to represent ``null changeset ID'' instead of a 16.421 +string of zeroes. 16.422 + 16.423 +If a hook exits with a status of zero, it is considered to have 16.424 +succeeded. If it exits with a non-zero status, it is considered to 16.425 +have failed. 16.426 + 16.427 +\subsection{The \hook{changegroup} hook} 16.428 +\label{sec:hook:changegroup} 16.429 + 16.430 +This hook is run after a group of pre-existing changesets has been 16.431 +added to the repository, for example via a \hgcmd{pull} or 16.432 +\hgcmd{unbundle}. This hook is run once per operation that added one 16.433 +or more changesets. This is in contrast to the \hook{incoming} hook, 16.434 +which is run once per changeset, regardless of whether the changesets 16.435 +arrive in a group. 16.436 + 16.437 +Some possible uses for this hook include kicking off an automated 16.438 +build or test of the added changesets, updating a bug database, or 16.439 +notifying subscribers that a repository contains new changes. 16.440 + 16.441 +Parameters to this hook: 16.442 +\begin{itemize} 16.443 +\item[\texttt{node}] A changeset ID. The changeset ID of the first 16.444 + changeset in the group that was added. All changesets between this 16.445 + and \index{tags!\texttt{tip}}\texttt{tip}, inclusive, were added by 16.446 + a single \hgcmd{pull}, \hgcmd{push} or \hgcmd{unbundle}. 16.447 +\end{itemize} 16.448 + 16.449 +See also: \hook{incoming} (section~\ref{sec:hook:incoming}), 16.450 +\hook{prechangegroup} (section~\ref{sec:hook:prechangegroup}), 16.451 +\hook{pretxnchangegroup} (section~\ref{sec:hook:pretxnchangegroup}) 16.452 + 16.453 +\subsection{The \hook{commit} hook} 16.454 +\label{sec:hook:commit} 16.455 + 16.456 +This hook is run after a new changeset has been created. 16.457 + 16.458 +Parameters to this hook: 16.459 +\begin{itemize} 16.460 +\item[\texttt{node}] A changeset ID. The changeset ID of the newly 16.461 + committed changeset. 16.462 +\item[\texttt{parent1}] A changeset ID. The changeset ID of the first 16.463 + parent of the newly committed changeset. 16.464 +\item[\texttt{parent2}] A changeset ID. The changeset ID of the second 16.465 + parent of the newly committed changeset. 16.466 +\end{itemize} 16.467 + 16.468 +See also: \hook{precommit} (section~\ref{sec:hook:precommit}), 16.469 +\hook{pretxncommit} (section~\ref{sec:hook:pretxncommit}) 16.470 + 16.471 +\subsection{The \hook{incoming} hook} 16.472 +\label{sec:hook:incoming} 16.473 + 16.474 +This hook is run after a pre-existing changeset has been added to the 16.475 +repository, for example via a \hgcmd{push}. If a group of changesets 16.476 +was added in a single operation, this hook is called once for each 16.477 +added changeset. 16.478 + 16.479 +You can use this hook for the same purposes as the \hook{changegroup} 16.480 +hook (section~\ref{sec:hook:changegroup}); it's simply more convenient 16.481 +sometimes to run a hook once per group of changesets, while othher 16.482 +times it's handier once per changeset. 16.483 + 16.484 +Parameters to this hook: 16.485 +\begin{itemize} 16.486 +\item[\texttt{node}] A changeset ID. The ID of the newly added 16.487 + changeset. 16.488 +\end{itemize} 16.489 + 16.490 +See also: \hook{changegroup} (section~\ref{sec:hook:changegroup}) \hook{prechangegroup} (section~\ref{sec:hook:prechangegroup}), \hook{pretxnchangegroup} (section~\ref{sec:hook:pretxnchangegroup}) 16.491 + 16.492 +\subsection{The \hook{outgoing} hook} 16.493 +\label{sec:hook:outgoing} 16.494 + 16.495 +This hook is run after a group of changesets has been propagated out 16.496 +of this repository, for example by a \hgcmd{push} or \hgcmd{bundle} 16.497 +command. 16.498 + 16.499 +One possible use for this hook is to notify administrators that 16.500 +changes have been pulled. 16.501 + 16.502 +Parameters to this hook: 16.503 +\begin{itemize} 16.504 +\item[\texttt{node}] A changeset ID. The changeset ID of the first 16.505 + changeset of the group that was sent. 16.506 +\item[\texttt{source}] A string. The source of the of the operation. 16.507 + If a remote client pulled changes from this repository, 16.508 + \texttt{source} will be \texttt{serve}. If the client that obtained 16.509 + changes from this repository was local, \texttt{source} will be 16.510 + \texttt{bundle}, \texttt{pull}, or \texttt{push}, depending on the 16.511 + operation the client performed. 16.512 +\end{itemize} 16.513 + 16.514 +See also: \hook{preoutgoing} (section~\ref{sec:hook:preoutgoing}) 16.515 + 16.516 +\subsection{The \hook{prechangegroup} hook} 16.517 +\label{sec:hook:prechangegroup} 16.518 + 16.519 +This controlling hook is run before Mercurial begins to add a group of 16.520 +changesets from another repository. 16.521 + 16.522 +This hook does not have any information about the changesets to be 16.523 +added, because it is run before transmission of those changesets is 16.524 +allowed to begin. If this hook fails, the changesets will not be 16.525 +transmitted. 16.526 + 16.527 +One use for this hook is to prevent external changes from being added 16.528 +to a repository, for example to ``freeze'' a server-hosted branch 16.529 +temporarily or permanently. 16.530 + 16.531 +This hook is not passed any parameters. 16.532 + 16.533 +See also: \hook{changegroup} (section~\ref{sec:hook:changegroup}), 16.534 +\hook{incoming} (section~\ref{sec:hook:incoming}), , 16.535 +\hook{pretxnchangegroup} (section~\ref{sec:hook:pretxnchangegroup}) 16.536 + 16.537 +\subsection{The \hook{precommit} hook} 16.538 +\label{sec:hook:precommit} 16.539 + 16.540 +This hook is run before Mercurial begins to commit a new changeset. 16.541 +It is run before Mercurial has any of the metadata for the commit, 16.542 +such as the files to be committed, the commit message, or the commit 16.543 +date. 16.544 + 16.545 +One use for this hook is to disable the ability to commit new 16.546 +changesets, while still allowing incoming changesets. Another is to 16.547 +run a build or test, and only allow the commit to begin if the build 16.548 +or test succeeds. 16.549 + 16.550 +Parameters to this hook: 16.551 +\begin{itemize} 16.552 +\item[\texttt{parent1}] A changeset ID. The changeset ID of the first 16.553 + parent of the working directory. 16.554 +\item[\texttt{parent2}] A changeset ID. The changeset ID of the second 16.555 + parent of the working directory. 16.556 +\end{itemize} 16.557 +If the commit proceeds, the parents of the working directory will 16.558 +become the parents of the new changeset. 16.559 + 16.560 +See also: \hook{commit} (section~\ref{sec:hook:commit}), 16.561 +\hook{pretxncommit} (section~\ref{sec:hook:pretxncommit}) 16.562 + 16.563 +\subsection{The \hook{preoutgoing} hook} 16.564 +\label{sec:hook:preoutgoing} 16.565 + 16.566 +This hook is invoked before Mercurial knows the identities of the 16.567 +changesets to be transmitted. 16.568 + 16.569 +One use for this hook is to prevent changes from being transmitted to 16.570 +another repository. 16.571 + 16.572 +Parameters to this hook: 16.573 +\begin{itemize} 16.574 +\item[\texttt{source}] A string. The source of the operation that is 16.575 + attempting to obtain changes from this repository. See the 16.576 + documentation for the \texttt{source} parameter to the 16.577 + \hook{outgoing} hook, in section~\ref{sec:hook:outgoing}, for 16.578 + possible values of this parameter.. 16.579 +\end{itemize} 16.580 + 16.581 +See also: \hook{outgoing} (section~\ref{sec:hook:outgoing}) 16.582 + 16.583 +\subsection{The \hook{pretag} hook} 16.584 +\label{sec:hook:pretag} 16.585 + 16.586 +This controlling hook is run before a tag is created. If the hook 16.587 +succeeds, creation of the tag proceeds. If the hook fails, the tag is 16.588 +not created. 16.589 + 16.590 +Parameters to this hook: 16.591 +\begin{itemize} 16.592 +\item[\texttt{local}] A boolean. Whether the tag is local to this 16.593 + repository instance (i.e.~stored in \sfilename{.hg/tags}) or managed 16.594 + by Mercurial (stored in \sfilename{.hgtags}). 16.595 +\item[\texttt{node}] A changeset ID. The ID of the changeset to be tagged. 16.596 +\item[\texttt{tag}] A string. The name of the tag to be created. 16.597 +\end{itemize} 16.598 + 16.599 +If the tag to be created is revision-controlled, the \hook{precommit} 16.600 +and \hook{pretxncommit} hooks (sections~\ref{sec:hook:commit} 16.601 +and~\ref{sec:hook:pretxncommit}) will also be run. 16.602 + 16.603 +See also: \hook{tag} (section~\ref{sec:hook:tag}) 16.604 + 16.605 +\subsection{The \hook{pretxnchangegroup} hook} 16.606 +\label{sec:hook:pretxnchangegroup} 16.607 + 16.608 +This controlling hook is run before a transaction---that manages the 16.609 +addition of a group of new changesets from outside the 16.610 +repository---completes. If the hook succeeds, the transaction 16.611 +completes, and all of the changesets become permanent within this 16.612 +repository. If the hook fails, the transaction is rolled back, and 16.613 +the data for the changesets is erased. 16.614 + 16.615 +This hook can access the metadata associated with the almost-added 16.616 +changesets, but it should not do anything permanent with this data. 16.617 +It must also not modify the working directory. 16.618 + 16.619 +While this hook is running, if other Mercurial processes access this 16.620 +repository, they will be able to see the almost-added changesets as if 16.621 +they are permanent. This may lead to race conditions if you do not 16.622 +take steps to avoid them. 16.623 + 16.624 +This hook can be used to automatically vet a group of changesets. If 16.625 +the hook fails, all of the changesets are ``rejected'' when the 16.626 +transaction rolls back. 16.627 + 16.628 +Parameters to this hook are the same as for the \hook{changegroup} 16.629 +hook; see section~\ref{sec:hook:changegroup} for details. 16.630 + 16.631 +See also: \hook{changegroup} (section~\ref{sec:hook:changegroup}), 16.632 +\hook{incoming} (section~\ref{sec:hook:incoming}), 16.633 +\hook{prechangegroup} (section~\ref{sec:hook:prechangegroup}) 16.634 + 16.635 +\subsection{The \hook{pretxncommit} hook} 16.636 +\label{sec:hook:pretxncommit} 16.637 + 16.638 +This controlling hook is run before a transaction---that manages a new 16.639 +commit---completes. If the hook succeeds, the transaction completes 16.640 +and the changeset becomes permanent within this repository. If the 16.641 +hook fails, the transaction is rolled back, and the commit data is 16.642 +erased. 16.643 + 16.644 +This hook can access the metadata associated with the almost-new 16.645 +changeset, but it should not do anything permanent with this data. It 16.646 +must also not modify the working directory. 16.647 + 16.648 +While this hook is running, if other Mercurial processes access this 16.649 +repository, they will be able to see the almost-new changeset as if it 16.650 +is permanent. This may lead to race conditions if you do not take 16.651 +steps to avoid them. 16.652 + 16.653 +Parameters to this hook are the same as for the \hook{commit} hook; 16.654 +see section~\ref{sec:hook:commit} for details. 16.655 + 16.656 +See also: \hook{precommit} (section~\ref{sec:hook:precommit}) 16.657 + 16.658 +\subsection{The \hook{preupdate} hook} 16.659 +\label{sec:hook:preupdate} 16.660 + 16.661 +This controlling hook is run before an update or merge of the working 16.662 +directory begins. It is run only if Mercurial's normal pre-update 16.663 +checks determine that the update or merge can proceed. If the hook 16.664 +succeeds, the update or merge may proceed; if it fails, the update or 16.665 +merge does not start. 16.666 + 16.667 +Parameters to this hook: 16.668 +\begin{itemize} 16.669 +\item[\texttt{parent1}] A changeset ID. The ID of the parent that the 16.670 + working directory is to be updated to. If the working directory is 16.671 + being merged, it will not change this parent. 16.672 +\item[\texttt{parent2}] A changeset ID. Only set if the working 16.673 + directory is being merged. The ID of the revision that the working 16.674 + directory is being merged with. 16.675 +\end{itemize} 16.676 + 16.677 +See also: \hook{update} (section~\ref{sec:hook:update}) 16.678 + 16.679 +\subsection{The \hook{tag} hook} 16.680 +\label{sec:hook:tag} 16.681 + 16.682 +This hook is run after a tag has been created. 16.683 + 16.684 +Parameters to this hook are the same as for the \hook{pretag} hook; 16.685 +see section~\ref{sec:hook:pretag} for details. 16.686 + 16.687 +If the created tag is revision-controlled, the \hook{commit} hook 16.688 +(section~\ref{sec:hook:commit}) is run before this hook. 16.689 + 16.690 +See also: \hook{pretag} (section~\ref{sec:hook:pretag}) 16.691 + 16.692 +\subsection{The \hook{update} hook} 16.693 +\label{sec:hook:update} 16.694 + 16.695 +This hook is run after an update or merge of the working directory 16.696 +completes. Since a merge can fail (if the external \command{hgmerge} 16.697 +command fails to resolve conflicts in a file), this hook communicates 16.698 +whether the update or merge completed cleanly. 16.699 + 16.700 +\begin{itemize} 16.701 +\item[\texttt{error}] A boolean. Indicates whether the update or 16.702 + merge completed successfully. 16.703 +\item[\texttt{parent1}] A changeset ID. The ID of the parent that the 16.704 + working directory was updated to. If the working directory was 16.705 + merged, it will not have changed this parent. 16.706 +\item[\texttt{parent2}] A changeset ID. Only set if the working 16.707 + directory was merged. The ID of the revision that the working 16.708 + directory was merged with. 16.709 +\end{itemize} 16.710 + 16.711 +See also: \hook{preupdate} (section~\ref{sec:hook:preupdate}) 16.712 16.713 %%% Local Variables: 16.714 %%% mode: latex
17.1 --- a/en/mq.tex Mon Jul 24 23:57:52 2006 -0400 17.2 +++ b/en/mq.tex Tue Jul 25 00:02:24 2006 -0400 17.3 @@ -141,7 +141,7 @@ 17.4 these commands in action. 17.5 17.6 \begin{figure}[ht] 17.7 - \interaction{mq.diff.diff} 17.8 + \interaction{mq.dodiff.diff} 17.9 \caption{Simple uses of the \command{diff} and \command{patch} commands} 17.10 \label{ex:mq:diff} 17.11 \end{figure} 17.12 @@ -336,7 +336,7 @@ 17.13 17.14 \begin{figure}[ht] 17.15 \centering 17.16 - \includegraphics{mq-stack} 17.17 + \grafix{mq-stack} 17.18 \caption{Applied and unapplied patches in the MQ patch stack} 17.19 \label{fig:mq:stack} 17.20 \end{figure}