# HG changeset patch # User Dongsheng Song # Date 1238401413 -28800 # Node ID 1c13ed2130a723f0a428418da100950920ac34c2 # Parent 6b1577ef513516ae34ad123926530416573e71e9# Parent 9e8e5292acaae158e2a5019fbee018e804aae452 Merge with http://hg.serpentine.com/mercurial/book diff -r 6b1577ef5135 -r 1c13ed2130a7 .hgignore --- a/.hgignore Fri Mar 20 17:17:55 2009 +0800 +++ b/.hgignore Mon Mar 30 16:23:33 2009 +0800 @@ -1,7 +1,4 @@ -[^/]+/build/ -[^/]+/fop/ -[^/]+/hello/ -[^/]+/html/ +[^/]+/htdocs/ syntax: glob @@ -13,13 +10,17 @@ *.pyc *.rej *.run -*-tmp.svg *~ -.*.swp +.*.sw[op] .\#* .run .validated-00book.xml en/all-ids.dat web/hgbook/.database.sqlite3 web/hgbook/secrets.py +web/index-read.html.in stylesheets/system-xsl +build +en/html +en/examples/results +tools \ No newline at end of file diff -r 6b1577ef5135 -r 1c13ed2130a7 Makefile --- a/Makefile Fri Mar 20 17:17:55 2009 +0800 +++ b/Makefile Mon Mar 30 16:23:33 2009 +0800 @@ -20,26 +20,26 @@ rev_id = $(shell hg parents --template '{node|short} ({date|shortdate})') images := \ - en/images/feature-branches.png \ - en/images/filelog.png \ - en/images/metadata.png \ - en/images/mq-stack.png \ - en/images/revlog.png \ - en/images/snapshot.png \ - en/images/tour-history.png \ - en/images/tour-merge-conflict.png \ - en/images/tour-merge-merge.png \ - en/images/tour-merge-pull.png \ - en/images/tour-merge-sep-repos.png \ - en/images/undo-manual-merge.png \ - en/images/undo-manual.png \ - en/images/undo-non-tip.png \ - en/images/undo-simple.png \ - en/images/wdir-after-commit.png \ - en/images/wdir-branch.png \ - en/images/wdir-merge.png \ - en/images/wdir.png \ - en/images/wdir-pre-branch.png + en/figs/feature-branches.png \ + en/figs/filelog.png \ + en/figs/metadata.png \ + en/figs/mq-stack.png \ + en/figs/revlog.png \ + en/figs/snapshot.png \ + en/figs/tour-history.png \ + en/figs/tour-merge-conflict.png \ + en/figs/tour-merge-merge.png \ + en/figs/tour-merge-pull.png \ + en/figs/tour-merge-sep-repos.png \ + en/figs/undo-manual-merge.png \ + en/figs/undo-manual.png \ + en/figs/undo-non-tip.png \ + en/figs/undo-simple.png \ + en/figs/wdir-after-commit.png \ + en/figs/wdir-branch.png \ + en/figs/wdir-merge.png \ + en/figs/wdir.png \ + en/figs/wdir-pre-branch.png help: @echo " make html [LINGUA=en|zh|...]" @@ -53,30 +53,30 @@ @echo " make clean # Remove the build files." clean: - @rm -fr build po/*.mo hello en/hello en/html en/.validated-00book.xml \ - stylesheets/system-xsl en/images/*-tmp.svg \ - en/images/feature-branches.png \ - en/images/filelog.png \ - en/images/feature-branches.png \ - en/images/filelog.png \ - en/images/metadata.png \ - en/images/mq-stack.png \ - en/images/revlog.png \ - en/images/snapshot.png \ - en/images/tour-history.png \ - en/images/tour-merge-conflict.png \ - en/images/tour-merge-merge.png \ - en/images/tour-merge-pull.png \ - en/images/tour-merge-sep-repos.png \ - en/images/undo-manual-merge.png \ - en/images/undo-manual.png \ - en/images/undo-non-tip.png \ - en/images/undo-simple.png \ - en/images/wdir-after-commit.png \ - en/images/wdir-branch.png \ - en/images/wdir-merge.png \ - en/images/wdir-pre-branch.png \ - en/images/wdir.png + @rm -fr build po/*.mo hello en/hello en/html en/.validated-00book.xml en/examples/.run en/examples/results \ + stylesheets/system-xsl en/figs/*-tmp.svg \ + en/figs/feature-branches.png \ + en/figs/filelog.png \ + en/figs/feature-branches.png \ + en/figs/filelog.png \ + en/figs/metadata.png \ + en/figs/mq-stack.png \ + en/figs/revlog.png \ + en/figs/snapshot.png \ + en/figs/tour-history.png \ + en/figs/tour-merge-conflict.png \ + en/figs/tour-merge-merge.png \ + en/figs/tour-merge-pull.png \ + en/figs/tour-merge-sep-repos.png \ + en/figs/undo-manual-merge.png \ + en/figs/undo-manual.png \ + en/figs/undo-non-tip.png \ + en/figs/undo-simple.png \ + en/figs/wdir-after-commit.png \ + en/figs/wdir-branch.png \ + en/figs/wdir-merge.png \ + en/figs/wdir-pre-branch.png \ + en/figs/wdir.png all: ifdef LINGUA @@ -133,23 +133,24 @@ xmllint --nonet --noout --postvalid --xinclude $< ifneq "$(findstring $(LINGUA),$(DBK_LANGUAGES))" "" -build/$(LINGUA)/source/hgbook.xml: $(wildcard $(LINGUA)/*.xml) $(images) - mkdir -p build/$(LINGUA)/source - cp -r $(LINGUA)/* build/$(LINGUA)/source - xmllint --nonet --noent --xinclude --postvalid --output $@.tmp $(LINGUA)/00book.xml +$(LINGUA)/examples/.run: + (cd $(LINGUA)/examples; ./run-example -v -a) + +build/$(LINGUA)/source/hgbook.xml: $(wildcard $(LINGUA)/*.xml) $(images) $(LINGUA)/examples/.run $(images) + mkdir -p build/$(LINGUA)/source/figs + cp $(LINGUA)/figs/*.png build/$(LINGUA)/source/figs + (cd $(LINGUA); xmllint --nonet --noent --xinclude --postvalid --output ../$@.tmp 00book.xml) cat $@.tmp | sed 's/\$$rev_id\$$/${rev_id}/' > $@ else -build/$(LINGUA)/source/hgbook.xml: $(wildcard en/*.xml) po/$(LINGUA).po $(images) - mkdir -p build/$(LINGUA)/source - cp -r en/images build/$(LINGUA)/source - cp -r en/examples build/$(LINGUA)/source - cp en/book-shortcuts.xml build/$(LINGUA)/source - for f in en/*.xml; do \ - if [ $$f != "en/book-shortcuts.xml" ]; then \ - $(TRANSLATE) -m $$f -p po/$(LINGUA).po -l build/$(LINGUA)/source/`basename $$f`; \ - fi \ - done - xmllint --nonet --noent --xinclude --postvalid --output $@.tmp build/$(LINGUA)/source/00book.xml +en/examples/.run: + (cd en/examples; ./run-example -v -a) + +build/en/source/hgbook.xml: + ${MAKE} LINGUA=en $@ + +build/$(LINGUA)/source/hgbook.xml: build/en/source/hgbook.xml po/$(LINGUA).po $(images) + mkdir -p build/$(LINGUA)/source/figs + $(TRANSLATE) -m build/en/source/hgbook.xml -p po/$(LINGUA).po -l $@.tmp cat $@.tmp | sed 's/\$$rev_id\$$/${rev_id}/' > $@ endif @@ -164,8 +165,8 @@ html: build/$(LINGUA)/html/index.html build/$(LINGUA)/html/index.html: build/$(LINGUA)/source/hgbook.xml stylesheets/html.xsl stylesheets/$(LINGUA)/html.xsl - mkdir -p build/$(LINGUA)/html/images - cp en/images/*.png build/$(LINGUA)/html/images + mkdir -p build/$(LINGUA)/html/figs + cp en/figs/*.png build/$(LINGUA)/html/figs cp stylesheets/hgbook.css build/$(LINGUA)/html xsltproc --output build/$(LINGUA)/html/ \ stylesheets/$(LINGUA)/html.xsl build/$(LINGUA)/source/hgbook.xml @@ -180,8 +181,8 @@ html-single: build/$(LINGUA)/html-single/hgbook.html build/$(LINGUA)/html-single/hgbook.html: build/$(LINGUA)/source/hgbook.xml stylesheets/html-single.xsl stylesheets/$(LINGUA)/html-single.xsl - mkdir -p build/$(LINGUA)/html-single/images - cp en/images/*.png build/$(LINGUA)/html-single/images + mkdir -p build/$(LINGUA)/html-single/figs + cp en/figs/*.png build/$(LINGUA)/html-single/figs cp stylesheets/hgbook.css build/$(LINGUA)/html-single xsltproc --output build/$(LINGUA)/html-single/hgbook.html \ stylesheets/$(LINGUA)/html-single.xsl build/$(LINGUA)/source/hgbook.xml @@ -210,9 +211,9 @@ (cd build/$(LINGUA)/source && ../../../tools/fop/fop.sh hgbook.fo ../pdf/hgbook.pdf) endif -en/images/%.png: en/images/%.svg en/fixsvg +en/figs/%.png: en/figs/%.svg en/fixsvg en/fixsvg $< inkscape -D -d 120 -e $@ $<-tmp.svg -en/images/%.svg: en/images/%.dot +en/figs/%.svg: en/figs/%.dot dot -Tsvg -o $@ $< diff -r 6b1577ef5135 -r 1c13ed2130a7 en/00book.xml --- a/en/00book.xml Fri Mar 20 17:17:55 2009 +0800 +++ b/en/00book.xml Mon Mar 30 16:23:33 2009 +0800 @@ -1,7 +1,7 @@ - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/Makefile --- a/en/Makefile Fri Mar 20 17:17:55 2009 +0800 +++ b/en/Makefile Mon Mar 30 16:23:33 2009 +0800 @@ -1,28 +1,6 @@ # This makefile requires GNU make. -image-sources := \ - feature-branches.dot \ - filelog.svg \ - kdiff3.png \ - metadata.svg \ - mq-stack.svg \ - note.png \ - revlog.svg \ - snapshot.svg \ - tour-history.svg \ - tour-merge-conflict.svg \ - tour-merge-merge.svg \ - tour-merge-pull.svg \ - tour-merge-sep-repos.svg \ - undo-manual.dot \ - undo-manual-merge.dot \ - undo-non-tip.dot \ - undo-simple.dot \ - wdir.svg \ - wdir-after-commit.svg \ - wdir-branch.svg \ - wdir-merge.svg \ - wdir-pre-branch.svg +image-sources := $(wildcard figs/*.dot figs/*.gif figs/*.png figs/*.svg) xml-src-files := \ 00book.xml \ @@ -31,9 +9,16 @@ image-dot := $(filter %.dot,$(image-sources)) image-svg := $(filter %.svg,$(image-sources)) -image-png := $(filter %.png,$(image-sources)) +image-oth := $(filter %.gif %.png,$(image-sources)) -image-html := $(image-dot:%.dot=%.png) $(image-svg:%.svg=%.png) $(image-png) +obj-web := html +obj-websup := $(obj-web)/support +obj-web-read := $(obj-web)/read + +image-web := \ + $(image-dot:%.dot=$(obj-web-read)/%.png) \ + $(image-svg:%.svg=$(obj-web-read)/%.png) \ + $(image-oth:%=$(obj-web-read)/%) example-sources-by-name := \ backout \ @@ -71,9 +56,6 @@ $(example-sources-by-name:%=examples/%) \ $(wildcard examples/ch*/*) -obj-web := html -obj-websup := html/support - extras-web-base := \ $(obj-web)/index.html \ $(obj-web)/robots.txt \ @@ -130,24 +112,30 @@ all: web -../xsl/system-xsl: $(system-xsl-dir) +../stylesheets/system-xsl: $(system-xsl-dir) ln -s $< $@ -web: ../xsl/system-xsl websup html +web: ../stylesheets/system-xsl websup html + +html: $(obj-web-read)/index.html -html: ../xsl/system-xsl $(xml-src-files) valid - xsltproc $(xsltproc-opts) -o html/read/x ../xsl/chunk-stylesheet.xsl 00book.xml - for i in html/read/*.html; do \ +../web/index-read.html.in: ../web/genindex.py $(xml-src-files) + $< + +$(obj-web-read)/index.html: ../stylesheets/system-xsl .validated-00book.xml ../web/index-read.html.in + xsltproc $(xsltproc-opts) -o $(obj-web-read)/x ../stylesheets/chunk-stylesheet.xsl 00book.xml + python ../web/texpand.py ../web/index-read.html.in html/read/index.html + for i in $(obj-web-read)/*.html; do \ gzip -9 -c $$i > $$i.gz; \ done -websup: $(extras-web) - mkdir -p $(obj-websup)/figs - cp ../xsl/system-xsl/images/*.png $(obj-websup)/figs +websup: $(extras-web) $(image-web) + mkdir -p $(obj-websup)/figs $(obj-web-read)/figs + cp ../stylesheets/system-xsl/images/*.png $(obj-websup)/figs cp -f ../web/icons/*.png $(obj-websup)/figs -all-ids.dat: ../xsl/all-ids.xsl $(xml-src-files) - $(xsltproc) $(xsltproc-opts) -o $@ ../xsl/all-ids.xsl 00book.xml +all-ids.dat: ../stylesheets/all-ids.xsl $(xml-src-files) + $(xsltproc) $(xsltproc-opts) -o $@ ../stylesheets/all-ids.xsl 00book.xml web: websup @@ -159,12 +147,26 @@ # Produce 90dpi PNGs for the web. -%.png: %.svg fixsvg +$(obj-web-read)/figs/%.png: $(obj-web-read)/figs/%.svg fixsvg + mkdir -p $(dir $@) ./fixsvg $< inkscape -D -e $@ $<-tmp.svg rm $<-tmp.svg -%.svg: %.dot +$(obj-web-read)/figs/%.png: figs/%.svg fixsvg + mkdir -p $(dir $@) + ./fixsvg $< + inkscape -D -e $@ $<-tmp.svg + rm $<-tmp.svg + +$(obj-web-read)/figs/%.gif: figs/%.gif + cp $< $@ + +$(obj-web-read)/figs/%.png: figs/%.png + cp $< $@ + +$(obj-web-read)/figs/%.svg: figs/%.dot + mkdir -p $(dir $@) dot -Tsvg -o $@ $< examples: $(example-prereqs) examples/.run @@ -188,6 +190,7 @@ rsync -avz --delete dist sp.red-bean.com:public_html/hgbook vpath %.css ../web +vpath %.html.in ../web vpath %.js ../web/javascript $(obj-websup)/%.css: %.css diff -r 6b1577ef5135 -r 1c13ed2130a7 en/appA-cmdref.xml --- a/en/appA-cmdref.xml Fri Mar 20 17:17:55 2009 +0800 +++ b/en/appA-cmdref.xml Mon Mar 30 16:23:33 2009 +0800 @@ -1,6 +1,7 @@ + Command reference \cmdref{add}{add files at the next commit} @@ -12,7 +13,7 @@ Show differences between revisions for the specified files or directories, using the unified diff format. For a description of the -unified diff format, see section . +unified diff format, see . By default, this command does not print diffs for files that Mercurial considers to contain binary data. To control this behaviour, see the @@ -20,7 +21,7 @@ Options - +x \loptref{diff}{nodates} Omit date and time information when printing diff headers. @@ -158,7 +159,7 @@ Tips and tricks - + Why do the results of <command role="hg-cmd">hg diff</command> and <command role="hg-cmd">hg status</command> differ? When you run the hg status command, you'll see a list of files diff -r 6b1577ef5135 -r 1c13ed2130a7 en/appB-mq-ref.xml --- a/en/appB-mq-ref.xml Fri Mar 20 17:17:55 2009 +0800 +++ b/en/appB-mq-ref.xml Mon Mar 30 16:23:33 2009 +0800 @@ -1,10 +1,10 @@ - + Mercurial Queues reference - + MQ command reference For an overview of the commands provided by MQ, use the @@ -296,7 +296,7 @@ role="hg-ext-mq">qpop. - + <command role="hg-ext-mq">qpush</command>&emdash;push patches onto the stack diff -r 6b1577ef5135 -r 1c13ed2130a7 en/appC-srcinstall.xml --- a/en/appC-srcinstall.xml Fri Mar 20 17:17:55 2009 +0800 +++ b/en/appC-srcinstall.xml Mon Mar 30 16:23:33 2009 +0800 @@ -1,10 +1,10 @@ - + Installing Mercurial from source - + On a Unix-like system If you are using a Unix-like system that has a sufficiently diff -r 6b1577ef5135 -r 1c13ed2130a7 en/appD-license.xml --- a/en/appD-license.xml Fri Mar 20 17:17:55 2009 +0800 +++ b/en/appD-license.xml Mon Mar 30 16:23:33 2009 +0800 @@ -1,6 +1,6 @@ - + Open Publication License @@ -32,7 +32,7 @@ The reference must be immediately followed with any options elected by the author(s) and/or publisher of the document (see - section ). + ). Commercial redistribution of Open Publication-licensed material is permitted. @@ -133,7 +133,7 @@ - + License options The author(s) and/or publisher of an Open diff -r 6b1577ef5135 -r 1c13ed2130a7 en/ch00-preface.xml --- a/en/ch00-preface.xml Fri Mar 20 17:17:55 2009 +0800 +++ b/en/ch00-preface.xml Mon Mar 30 16:23:33 2009 +0800 @@ -1,6 +1,6 @@ - + Preface @@ -61,8 +61,8 @@ can revert to an earlier version of one or more files. In fact, a really good revision control tool will even help you to efficiently figure out exactly - when a problem was introduced (see section for details). + when a problem was introduced (see for details). It will help you to work simultaneously on, and manage the drift between, multiple versions of your project. @@ -167,8 +167,8 @@ As an instance of this, several consecutive commits in an example can show up as having occurred during the same second. You can see this occur in the bisect example in section , for instance. + role="hg-ext">bisect example in , for instance. So when you're reading examples, don't place too much weight on the dates or times you see in the output of commands. But diff -r 6b1577ef5135 -r 1c13ed2130a7 en/ch01-tour-basic.xml --- a/en/ch01-tour-basic.xml Fri Mar 20 17:17:55 2009 +0800 +++ b/en/ch01-tour-basic.xml Mon Mar 30 16:23:33 2009 +0800 @@ -1,27 +1,27 @@ - + A tour of Mercurial: the basics - + Installing Mercurial on your system - Prebuilt binary packages of Mercurial are available for + Prebuilt binary packages of Mercurial are available for every popular operating system. These make it easy to start using Mercurial on your computer immediately. Linux - Because each Linux distribution has its own packaging + Because each Linux distribution has its own packaging tools, policies, and rate of development, it's difficult to give a comprehensive set of instructions on how to install Mercurial binaries. The version of Mercurial that you will end up with can vary depending on how active the person is who maintains the package for your distribution. - To keep things simple, I will focus on installing + To keep things simple, I will focus on installing Mercurial from the command line under the most popular Linux distributions. Most of these distributions provide graphical package managers that will let you install Mercurial with a @@ -29,15 +29,15 @@ mercurial. - Debian: + Debian: apt-get install mercurial - Fedora Core: + Fedora Core: yum install mercurial - Gentoo: + Gentoo: emerge mercurial - OpenSUSE: + OpenSUSE: yum install mercurial - Ubuntu: Ubuntu's Mercurial package is based on + Ubuntu: Ubuntu's Mercurial package is based on Debian's. To install it, run the following command. apt-get install mercurial @@ -47,7 +47,7 @@ Solaris - SunFreeWare, at SunFreeWare, at http://www.sunfreeware.com, is a good source for a large number of pre-built Solaris packages for 32 and 64 bit Intel and Sparc architectures, @@ -57,7 +57,7 @@ Mac OS X - Lee Cantey publishes an installer of Mercurial for Mac OS + Lee Cantey publishes an installer of Mercurial for Mac OS X at http://mercurial.berkwood.com. This package works on both Intel- and Power-based Macs. Before @@ -66,7 +66,7 @@ is easy to do; simply follow the instructions on Lee's site. - It's also possible to install Mercurial using Fink or + It's also possible to install Mercurial using Fink or MacPorts, two popular free package managers for Mac OS X. If you have Fink, use sudo apt-get install mercurial-py25. If MacPorts, sudo port @@ -76,14 +76,14 @@ Windows - Lee Cantey publishes an installer of Mercurial for Windows + Lee Cantey publishes an installer of Mercurial for Windows at http://mercurial.berkwood.com. This package has no external dependencies; it just works. - The Windows version of Mercurial does not + The Windows version of Mercurial does not automatically convert line endings between Windows and Unix styles. If you want to share work with Unix users, you must do a little additional configuration work. XXX Flesh this @@ -95,7 +95,7 @@ Getting started - To begin, we'll use the hg + To begin, we'll use the hg version command to find out whether Mercurial is actually installed properly. The actual version information that it prints isn't so important; it's whether it prints @@ -106,7 +106,7 @@ Built-in help - Mercurial provides a built-in help system. This is + Mercurial provides a built-in help system. This is invaluable for those times when you find yourself stuck trying to remember how to run a command. If you are completely stuck, simply run hg @@ -117,7 +117,7 @@ &interaction.tour.help; - For a more impressive level of detail (which you won't + For a more impressive level of detail (which you won't usually need) run hg help . The option is short for @@ -130,13 +130,13 @@ Working with a repository - In Mercurial, everything happens inside a + In Mercurial, everything happens inside a repository. The repository for a project contains all of the files that belong to that project, along with a historical record of the project's files. - There's nothing particularly magical about a repository; it + There's nothing particularly magical about a repository; it is simply a directory tree in your filesystem that Mercurial treats as special. You can rename or delete a repository any time you like, using either the command line or your file @@ -145,7 +145,7 @@ Making a local copy of a repository - Copying a repository is just a little + Copying a repository is just a little bit special. While you could use a normal file copying command to make a copy of a repository, it's best to use a built-in command that Mercurial provides. This command is @@ -154,23 +154,23 @@ &interaction.tour.clone; - If our clone succeeded, we should now have a local + If our clone succeeded, we should now have a local directory called hello. This directory will contain some files. &interaction.tour.ls; - These files have the same contents and history in our + These files have the same contents and history in our repository as they do in the repository we cloned. - Every Mercurial repository is complete, self-contained, + Every Mercurial repository is complete, self-contained, and independent. It contains its own private copy of a project's files and history. A cloned repository remembers the location of the repository it was cloned from, but it does not communicate with that repository, or any other, unless you tell it to. - What this means for now is that we're free to experiment + What this means for now is that we're free to experiment with our repository, safe in the knowledge that it's a private sandbox that won't affect anyone else. @@ -178,20 +178,20 @@ What's in a repository? - When we take a more detailed look inside a repository, we + When we take a more detailed look inside a repository, we can see that it contains a directory named .hg. This is where Mercurial keeps all of its metadata for the repository. &interaction.tour.ls-a; - The contents of the The contents of the .hg directory and its subdirectories are private to Mercurial. Every other file and directory in the repository is yours to do with as you please. - To introduce a little terminology, the To introduce a little terminology, the .hg directory is the real repository, and all of the files and directories that coexist with it are said to live in the @@ -208,68 +208,66 @@ A tour through history - One of the first things we might want to do with a new, + One of the first things we might want to do with a new, unfamiliar repository is understand its history. The hg log command gives us a view of history. &interaction.tour.log; - By default, this command prints a brief paragraph of output + By default, this command prints a brief paragraph of output for each change to the project that was recorded. In Mercurial terminology, we call each of these recorded events a changeset, because it can contain a record of changes to several files. - The fields in a record of output from The fields in a record of output from hg log are as follows. - changeset: This field has the + changeset: This field has the format of a number, followed by a colon, followed by a hexadecimal string. These are identifiers for the changeset. There are two identifiers because the number is shorter and easier to type than the hex string. - user: The identity of the + user: The identity of the person who created the changeset. This is a free-form field, but it most often contains a person's name and email address. - date: The date and time on + date: The date and time on which the changeset was created, and the timezone in which it was created. (The date and time are local to that timezone; they display what time and date it was for the person who created the changeset.) - summary: The first line of + summary: The first line of the text message that the creator of the changeset entered to describe the changeset. - The default output printed by hg + The default output printed by hg log is purely a summary; it is missing a lot of detail. - Figure provides a - graphical representation of the history of the provides + a graphical representation of the history of the hello repository, to make it a little easier to see which direction history is flowing in. We'll be returning to this figure several times in this chapter and the chapter that follows. - +
+ Graphical history of the <filename + class="directory">hello</filename> repository - + XXX add text - Graphical history of - the hello repository - - +
Changesets, revisions, and talking to other people - As English is a notoriously sloppy language, and computer + As English is a notoriously sloppy language, and computer science has a hallowed history of terminological confusion (why use one term when four will do?), revision control has a variety of words and phrases that mean the same thing. If you @@ -279,7 +277,7 @@ cset, and sometimes a changeset is referred to as a revision or a rev. - While it doesn't matter what word you + While it doesn't matter what word you use to refer to the concept of a changeset, the identifier that you use to refer to a specific changeset is of @@ -288,14 +286,14 @@ log
identifies a changeset using both a number and a hexadecimal string.
- The revision number is only valid in + The revision number is only valid in that repository, - while the hex string is the + while the hex string is the permanent, unchanging identifier that will always identify that exact changeset in every copy of the repository. - This distinction is important. If you send someone an + This distinction is important. If you send someone an email talking about revision 33, there's a high likelihood that their revision 33 will not be the same as yours. The reason for this is that a @@ -305,7 +303,7 @@ repositories. Three changes $a,b,c$ can easily appear in one repository as $0,1,2$, while in another as $1,0,2$. - Mercurial uses revision numbers purely as a convenient + Mercurial uses revision numbers purely as a convenient shorthand. If you need to discuss a changeset with someone, or make a record of a changeset for some other reason (for example, in a bug report), use the hexadecimal @@ -315,7 +313,7 @@ Viewing specific revisions - To narrow the output of hg + To narrow the output of hg log down to a single revision, use the (or ) option. You can use @@ -324,7 +322,7 @@ &interaction.tour.log-r; - If you want to see the history of several revisions + If you want to see the history of several revisions without having to list each one, you can use range notation; this lets you express the idea I want all revisions between abc and @@ -332,7 +330,7 @@ &interaction.tour.log.range; - Mercurial also honours the order in which you specify + Mercurial also honours the order in which you specify revisions, so hg log -r 2:4 prints 2, 3, and 4. while hg log -r 4:2 prints 4, 3, and 2. @@ -341,7 +339,7 @@ More detailed information - While the summary information printed by While the summary information printed by hg log is useful if you already know what you're looking for, you may need to see a complete description of the change, or a list of the files changed, if @@ -353,13 +351,13 @@ &interaction.tour.log-v; - If you want to see both the description and content of a - change, add the (or - ) option. This - displays the content of a change as a unified - diff (if you've never seen a unified diff before, - see section for an - overview). + If you want to see both the description and + content of a change, add the (or ) option. This displays + the content of a change as a unified diff + (if you've never seen a unified diff before, see for an overview). &interaction.tour.log-vp; @@ -368,39 +366,39 @@ All about command options - Let's take a brief break from exploring Mercurial commands + Let's take a brief break from exploring Mercurial commands to discuss a pattern in the way that they work; you may find this useful to keep in mind as we continue our tour. - Mercurial has a consistent and straightforward approach to + Mercurial has a consistent and straightforward approach to dealing with the options that you can pass to commands. It follows the conventions for options that are common to modern Linux and Unix systems. - Every option has a long name. For example, as + Every option has a long name. For example, as we've already seen, the hg log command accepts a option. - Most options have short names, too. Instead of + Most options have short names, too. Instead of , we can use . (The reason that some options don't have short names is that the options in question are rarely used.) - Long options start with two dashes (e.g. - Option naming and usage is consistent across + Option naming and usage is consistent across commands. For example, every command that lets you specify a changeset ID or revision number accepts both and arguments. - In the examples throughout this book, I use short options + In the examples throughout this book, I use short options instead of long. This just reflects my own preference, so don't read anything significant into it. - Most commands that print output of some kind will print more + Most commands that print output of some kind will print more output when passed a (or ) option, and less when passed (or @@ -410,11 +408,11 @@ Making and reviewing changes - Now that we have a grasp of viewing history in Mercurial, + Now that we have a grasp of viewing history in Mercurial, let's take a look at making some changes and examining them. - The first thing we'll do is isolate our experiment in a + The first thing we'll do is isolate our experiment in a repository of its own. We use the hg clone command, but we don't need to clone a copy of the remote repository. Since we already have a copy of it @@ -424,7 +422,7 @@ &interaction.tour.reclone; - As an aside, it's often good practice to keep a + As an aside, it's often good practice to keep a pristine copy of a remote repository around, which you can then make temporary clones of to create sandboxes for each task you want to work on. This lets you work on @@ -433,7 +431,7 @@ local clones are so cheap, there's almost no overhead to cloning and destroying repositories whenever you want. - In our my-hello + In our my-hello repository, we have a file hello.c that contains the classic hello, world program. Let's use the ancient and venerable sed command to @@ -446,20 +444,20 @@ &interaction.tour.sed; - Mercurial's hg status + Mercurial's hg status command will tell us what Mercurial knows about the files in the repository. &interaction.tour.status; - The hg status command + The hg status command prints no output for some files, but a line starting with M for hello.c. Unless you tell it to, hg status will not print any output for files that have not been modified. - The M indicates that + The M indicates that Mercurial has noticed that we modified hello.c. We didn't need to inform Mercurial that we were going to @@ -467,7 +465,7 @@ file after we were done; it was able to figure this out itself. - It's a little bit helpful to know that we've modified + It's a little bit helpful to know that we've modified hello.c, but we might prefer to know exactly what changes we've made to it. To do this, we use the hg diff @@ -479,14 +477,14 @@ Recording changes in a new changeset - We can modify files, build and test our changes, and use + We can modify files, build and test our changes, and use hg status and hg diff to review our changes, until we're satisfied with what we've done and arrive at a natural stopping point where we want to record our work in a new changeset. - The hg commit command lets + The hg commit command lets us create a new changeset; we'll usually refer to this as making a commit or committing. @@ -494,7 +492,7 @@ Setting up a username - When you try to run hg + When you try to run hg commit for the first time, it is not guaranteed to succeed. Mercurial records your name and address with each change that you commit, so that you and others will later be @@ -503,36 +501,37 @@ change with. It will attempt each of the following methods, in order: - If you specify a - If you have set the HGUSER + If you have set the HGUSER environment variable, this is checked next. - If you create a file in your home directory - called .hgrc, with a - username entry, that will - be used next. To see what the contents of this file - should look like, refer to section + If you create a file in your home + directory called .hgrc, with a username entry, that will be + used next. To see what the contents of this file should + look like, refer to below. - If you have set the EMAIL + If you have set the EMAIL environment variable, this will be used next. - Mercurial will query your system to find out + Mercurial will query your system to find out your local user name and host name, and construct a username from these components. Since this often results in a username that is not very useful, it will print a warning if it has to do this. - If all of these mechanisms fail, Mercurial will + If all of these mechanisms fail, Mercurial will fail, printing an error message. In this case, it will not let you commit until you set up a username. - You should think of the HGUSER environment + You should think of the HGUSER environment variable and the option to the hg commit command as ways to override Mercurial's @@ -540,10 +539,10 @@ and most robust way to set a username for yourself is by creating a .hgrc file; see below for details. - + Creating a Mercurial configuration file - To set a user name, use your favourite editor + To set a user name, use your favourite editor to create a file called .hgrc in your home directory. Mercurial will use this file to look up your personalised @@ -555,7 +554,7 @@ username = Firstname Lastname <email.address@domain.net> - The [ui] line begins a + The [ui] line begins a section of the config file, so you can read the username = ... line as meaning set the value of the @@ -570,14 +569,14 @@ Choosing a user name - You can use any text you like as the value of + You can use any text you like as the value of the username config item, since this information is for reading by other people, but for interpreting by Mercurial. The convention that most people follow is to use their name and email address, as in the example above. - Mercurial's built-in web server obfuscates + Mercurial's built-in web server obfuscates email addresses, to make it more difficult for the email harvesting tools that spammers use. This reduces the likelihood that you'll start receiving more junk email @@ -589,7 +588,7 @@ Writing a commit message - When we commit a change, Mercurial drops us into + When we commit a change, Mercurial drops us into a text editor, to enter a message that will describe the modifications we've made in this changeset. This is called the commit message. It will be a @@ -599,14 +598,14 @@ &interaction.tour.commit; - The editor that the hg + The editor that the hg commit command drops us into will contain an empty line, followed by a number of lines starting with HG:. XXX fix this XXX - Mercurial ignores the lines that start with + Mercurial ignores the lines that start with HG:; it uses them only to tell us which files it's recording changes to. Modifying or deleting these lines has no effect. @@ -614,7 +613,7 @@ Writing a good commit message - Since hg log + Since hg log only prints the first line of a commit message by default, it's best to write a commit message whose first line stands alone. Here's a real example of a commit message that @@ -628,13 +627,13 @@ date: Tue Sep 26 21:37:07 2006 -0700 summary: include buildmeister/commondefs. Add exports. - As far as the remainder of the contents of the + As far as the remainder of the contents of the commit message are concerned, there are no hard-and-fast rules. Mercurial itself doesn't interpret or care about the contents of the commit message, though your project may have policies that dictate a certain kind of formatting. - My personal preference is for short, but + My personal preference is for short, but informative, commit messages that tell me something that I can't figure out with a quick glance at the output of hg log @@ -643,12 +642,12 @@ Aborting a commit - If you decide that you don't want to commit + If you decide that you don't want to commit while in the middle of editing a commit message, simply exit from your editor without saving the file that it's editing. This will cause nothing to happen to either the repository or the working directory. - If we run the hg + If we run the hg commit command without any arguments, it records all of the changes we've made, as reported by hg status and Admiring our new handiwork - Once we've finished the commit, we can use the + Once we've finished the commit, we can use the hg tip command to display the changeset we just created. This command produces output that is identical to hg @@ -666,7 +665,7 @@ &interaction.tour.tip; - We refer to + We refer to the newest revision in the repository as the tip revision, or simply the tip. @@ -675,16 +674,16 @@ Sharing changes - We mentioned earlier that repositories in + We mentioned earlier that repositories in Mercurial are self-contained. This means that the changeset we just created exists only in our my-hello repository. Let's look at a few ways that we can propagate this change into other repositories. - + Pulling changes from another repository - To get started, let's clone our original + To get started, let's clone our original hello repository, which does not contain the change we just committed. We'll call our temporary repository We'll use the hg + We'll use the hg pull command to bring changes from my-hello into hello-pull. However, blindly @@ -705,21 +704,21 @@ &interaction.tour.incoming; - (Of course, someone could + (Of course, someone could cause more changesets to appear in the repository that we ran hg incoming in, before we get a chance to hg pull the changes, so that we could end up pulling changes that we didn't expect.) - Bringing changes into a repository is a simple + Bringing changes into a repository is a simple matter of running the hg pull command, and telling it which repository to pull from. &interaction.tour.pull; - As you can see + As you can see from the before-and-after output of hg tip, we have successfully pulled changes into our repository. There remains one step @@ -729,19 +728,19 @@ Updating the working directory - We have so far glossed over the relationship between a - repository and its working directory. The We have so far glossed over the relationship + between a repository and its working directory. The hg pull command that we ran in - section brought changes - into the repository, but if we check, there's no sign of those - changes in the working directory. This is because brought changes into the + repository, but if we check, there's no sign of those changes + in the working directory. This is because hg pull does not (by default) touch the working directory. Instead, we use the hg update command to do this. &interaction.tour.update; - It might seem a bit strange that hg + It might seem a bit strange that hg pull doesn't update the working directory automatically. There's actually a good reason for this: you can use hg update to update @@ -752,29 +751,28 @@ role="hg-cmd">hg pull which automatically updated the working directory to a new revision, you might not be terribly happy. - However, since pull-then-update is such a common thing to + However, since pull-then-update is such a common thing to do, Mercurial lets you combine the two by passing the option to hg pull. - If you look back at the output of hg pull in section when we ran it without - To find out what revision the working directory is at, use + To find out what revision the working directory is at, use the hg parents command. &interaction.tour.parents; - If you look back at figure , + If you look back at , you'll see arrows connecting each changeset. The node that the arrow leads from in each case is a parent, and the node that the arrow leads @@ -782,14 +780,14 @@ has a parent in just the same way; this is the changeset that the working directory currently contains. - To update the working directory to a particular revision, + To update the working directory to a particular revision, give a revision number or changeset ID to the hg update command. &interaction.tour.older; - If you omit an explicit revision, If you omit an explicit revision, hg update will update to the tip revision, as shown by the second call to hg update in the example @@ -799,7 +797,7 @@ Pushing changes to another repository - Mercurial lets us push changes to another + Mercurial lets us push changes to another repository, from the repository we're currently visiting. As with the example of hg pull above, we'll create a temporary repository @@ -807,19 +805,19 @@ &interaction.tour.clone-push; - The hg outgoing command + The hg outgoing command tells us what changes would be pushed into another repository. &interaction.tour.outgoing; - And the + And the hg push command does the actual push. &interaction.tour.push; - As with + As with hg pull, the hg push command does not update the working directory in the repository that it's pushing @@ -828,7 +826,7 @@ does not provide a -u option that updates the other repository's working directory.) - What happens if we try to pull or push changes + What happens if we try to pull or push changes and the receiving repository already has those changes? Nothing too exciting. @@ -837,7 +835,7 @@ Sharing changes over a network - The commands we have covered in the previous few + The commands we have covered in the previous few sections are not limited to working with local repositories. Each works in exactly the same fashion over a network connection; simply pass in a URL instead of a local @@ -845,7 +843,7 @@ &interaction.tour.outgoing.net; - In this example, we + In this example, we can see what changes we could push to the remote repository, but the repository is understandably not set up to let anonymous users push to it. diff -r 6b1577ef5135 -r 1c13ed2130a7 en/ch02-tour-merge.xml --- a/en/ch02-tour-merge.xml Fri Mar 20 17:17:55 2009 +0800 +++ b/en/ch02-tour-merge.xml Mon Mar 30 16:23:33 2009 +0800 @@ -1,10 +1,10 @@ - + A tour of Mercurial: merging work - We've now covered cloning a repository, making changes in a + We've now covered cloning a repository, making changes in a repository, and pulling or pushing changes from one repository into another. Our next step is merging changes from separate repositories. @@ -12,86 +12,85 @@ Merging streams of work - Merging is a fundamental part of working with a distributed + Merging is a fundamental part of working with a distributed revision control tool. - Alice and Bob each have a personal copy of a + Alice and Bob each have a personal copy of a repository for a project they're collaborating on. Alice fixes a bug in her repository; Bob adds a new feature in his. They want the shared repository to contain both the bug fix and the new feature. - I frequently work on several different tasks for + I frequently work on several different tasks for a single project at once, each safely isolated in its own repository. Working this way means that I often need to merge one piece of my own work with another. - Because merging is such a common thing to need to do, + Because merging is such a common thing to need to do, Mercurial makes it easy. Let's walk through the process. We'll begin by cloning yet another repository (see how often they spring up?) and making a change in it. &interaction.tour.merge.clone; - We should now have two copies of + We should now have two copies of hello.c with different contents. The histories of the two repositories have also diverged, as - illustrated in figure . + illustrated in . &interaction.tour.merge.cat; - +
+ Divergent recent histories of the <filename + class="directory">my-hello</filename> and <filename + class="directory">my-new-hello</filename> + repositories - + XXX add text - Divergent recent - histories of the my-hello and my-new-hello - repositories - +
- We already know that pulling changes from our We already know that pulling changes from our my-hello repository will have no effect on the working directory. &interaction.tour.merge.pull; - However, the hg pull + However, the hg pull command says something about heads. Head changesets - A head is a change that has no descendants, or children, + A head is a change that has no descendants, or children, as they're also known. The tip revision is thus a head, because the newest revision in a repository doesn't have any children, but a repository can contain more than one head. - +
+ Repository contents after pulling from <filename + class="directory">my-hello</filename> into <filename + class="directory">my-new-hello</filename> - + + + XXX add text - Repository contents after - pulling from my-hello into - my-new-hello - +
- In figure , you can + In , you can see the effect of the pull from my-hello into my-new-hello. The history that was already present in my-new-hello is untouched, but - a new revision has been added. By referring to figure , we can see that the + a new revision has been added. By referring to , we can see that the changeset ID remains the same in the new repository, but the revision number has changed. (This, incidentally, is a fine example of why it's @@ -105,13 +104,13 @@ Performing the merge - What happens if we try to use the normal What happens if we try to use the normal hg update command to update to the new tip? &interaction.tour.merge.update; - Mercurial is telling us that the hg + Mercurial is telling us that the hg update command won't do a merge; it won't update the working directory when it thinks we might be wanting to do a merge, unless we force it to do so. Instead, we use the @@ -120,16 +119,18 @@ &interaction.tour.merge.merge; - +
+ Working directory and repository during merge, and + following commit - + + + XXX add text - Working directory and - repository during merge, and following commit - +
- This updates the working directory so that it contains + This updates the working directory so that it contains changes from both heads, which is reflected in both the output of hg parents and the contents of @@ -141,22 +142,22 @@ Committing the results of the merge - Whenever we've done a merge, hg + Whenever we've done a merge, hg parents will display two parents until we hg commit the results of the merge. &interaction.tour.merge.commit; - We now have a new tip revision; notice that it has + We now have a new tip revision; notice that it has both of our former heads as its parents. These are the same revisions that were previously displayed by hg parents. &interaction.tour.merge.tip; - In figure , you can see a + In , you can see a representation of what happens to the working directory during the merge, and how this affects the repository when the commit happens. During the merge, the working directory has two @@ -168,32 +169,29 @@ Merging conflicting changes - Most merges are simple affairs, but sometimes you'll find + Most merges are simple affairs, but sometimes you'll find yourself merging changes where each modifies the same portions of the same files. Unless both modifications are identical, this results in a conflict, where you have to decide how to reconcile the different changes into something coherent. - +
+ Conflicting changes to a document - - - XXX add text - Conflicting - changes to a document + + XXX add text - +
- Figure illustrates + illustrates an instance of two conflicting changes to a document. We started with a single version of the file; then we made some changes; while someone else made different changes to the same text. Our task in resolving the conflicting changes is to decide what the file should look like. - Mercurial doesn't have a built-in facility for handling + Mercurial doesn't have a built-in facility for handling conflicts. Instead, it runs an external program called hgmerge. This is a shell script that is bundled with Mercurial; you can change it to behave however you @@ -204,7 +202,7 @@ human guidance) or aren't present, the script tries a few different graphical merging tools. - It's also possible to get Mercurial to run another program + It's also possible to get Mercurial to run another program or script instead of hgmerge, by setting the HGMERGE environment variable to the name of your preferred program. @@ -212,59 +210,59 @@ Using a graphical merge tool - My preferred graphical merge tool is + My preferred graphical merge tool is kdiff3, which I'll use to describe the features that are common to graphical file merging tools. You can see a screenshot of kdiff3 in action in - figure . The kind of + . The kind of merge it is performing is called a three-way merge, because there are three different versions of the file of interest to us. The tool thus splits the upper portion of the window into three panes: - At the left is the base + At the left is the base version of the file, i.e. the most recent version from which the two versions we're trying to merge are descended. - In the middle is our version of + In the middle is our version of the file, with the contents that we modified. - On the right is their version + On the right is their version of the file, the one that from the changeset that we're trying to merge with. - In the pane below these is the current + In the pane below these is the current result of the merge. Our task is to replace all of the red text, which indicates unresolved conflicts, with some sensible merger of the ours and theirs versions of the file. - All four of these panes are locked + All four of these panes are locked together; if we scroll vertically or horizontally in any of them, the others are updated to display the corresponding sections of their respective files. - - - - - XXX add text - Using - kdiff3 to merge versions of a file - - - +
+ Using <command>kdiff3</command> to merge versions of a + file + + + + + XXX add text + + +
- For each conflicting portion of the file, we can choose to + For each conflicting portion of the file, we can choose to resolve the conflict using some combination of text from the base version, ours, or theirs. We can also manually edit the merged file at any time, in case we need to make further modifications. - There are many file merging tools + There are many file merging tools available, too many to cover here. They vary in which platforms they are available for, and in their particular strengths and weaknesses. Most are tuned for merging files @@ -275,20 +273,19 @@ A worked example - In this example, we will reproduce the file modification - history of figure + In this example, we will reproduce the file modification + history of above. Let's begin by creating a repository with a base version of our document. &interaction.tour-merge-conflict.wife; - We'll clone the repository and make a change to the + We'll clone the repository and make a change to the file. &interaction.tour-merge-conflict.cousin; - And another clone, to simulate someone else making a + And another clone, to simulate someone else making a change to the file. (This hints at the idea that it's not all that unusual to merge with yourself when you isolate tasks in separate repositories, and indeed to find and resolve @@ -296,13 +293,13 @@ &interaction.tour-merge-conflict.son; - Having created two + Having created two different versions of the file, we'll set up an environment suitable for running our merge. &interaction.tour-merge-conflict.pull; - In this example, I won't use Mercurial's normal + In this example, I won't use Mercurial's normal hgmerge program to do the merge, because it would drop my nice automated example-running tool into a graphical user interface. Instead, I'll set @@ -312,25 +309,25 @@ example on your computer, don't bother setting HGMERGE. - XXX FIX THIS + XXX FIX THIS EXAMPLE. &interaction.tour-merge-conflict.merge; - Because merge can't resolve the + Because merge can't resolve the conflicting changes, it leaves merge markers inside the file that has conflicts, indicating which lines have conflicts, and whether they came from our version of the file or theirs. - Mercurial can tell from the way merge + Mercurial can tell from the way merge exits that it wasn't able to merge successfully, so it tells us what commands we'll need to run if we want to redo the merging operation. This could be useful if, for example, we were running a graphical merge tool and quit because we were confused or realised we had made a mistake. - If automatic or manual merges fail, there's nothing to + If automatic or manual merges fail, there's nothing to prevent us from fixing up the affected files ourselves, and committing the results of our merge: @@ -338,32 +335,32 @@
- + Simplifying the pull-merge-commit sequence - The process of merging changes as outlined above is + The process of merging changes as outlined above is straightforward, but requires running three commands in sequence. hg pull hg merge hg commit -m 'Merged remote changes' - In the case of the final commit, you also need to enter a + In the case of the final commit, you also need to enter a commit message, which is almost always going to be a piece of uninteresting boilerplate text. - It would be nice to reduce the number of steps needed, if + It would be nice to reduce the number of steps needed, if this were possible. Indeed, Mercurial is distributed with an extension called fetch that does just this. - Mercurial provides a flexible extension mechanism that lets + Mercurial provides a flexible extension mechanism that lets people extend its functionality, while keeping the core of Mercurial small and easy to deal with. Some extensions add new commands that you can use from the command line, while others work behind the scenes, for example adding capabilities to the server. - The fetch extension adds a + The fetch extension adds a new command called, not surprisingly, hg fetch. This extension acts as a combination of hg pull, - Enabling the fetch + Enabling the fetch extension is easy. Edit your .hgrc, and either go to the extensions section or create an @@ -385,7 +382,7 @@
.
[extensions] fetch = - (Normally, on the right-hand side of the + (Normally, on the right-hand side of the = would appear the location of the extension, but since the fetch extension is in the standard diff -r 6b1577ef5135 -r 1c13ed2130a7 en/ch03-concepts.xml --- a/en/ch03-concepts.xml Fri Mar 20 17:17:55 2009 +0800 +++ b/en/ch03-concepts.xml Mon Mar 30 16:23:33 2009 +0800 @@ -1,23 +1,23 @@ - + Behind the scenes - Unlike many revision control systems, the concepts upon which + Unlike many revision control systems, the concepts upon which Mercurial is built are simple enough that it's easy to understand how the software really works. Knowing this certainly isn't necessary, but I find it useful to have a mental model of what's going on. - This understanding gives me confidence that Mercurial has been + This understanding gives me confidence that Mercurial has been carefully designed to be both safe and efficient. And just as importantly, if it's easy for me to retain a good idea of what the software is doing when I perform a revision control task, I'm less likely to be surprised by its behaviour. - In this chapter, we'll initially cover the core concepts + In this chapter, we'll initially cover the core concepts behind Mercurial's design, then continue to discuss some of the interesting details of its implementation. @@ -27,7 +27,7 @@ Tracking the history of a single file - When Mercurial tracks modifications to a file, it stores + When Mercurial tracks modifications to a file, it stores the history of that file in a metadata object called a filelog. Each entry in the filelog contains enough information to reconstruct one revision of the @@ -38,7 +38,7 @@ an index to help Mercurial to find a revision efficiently. - A file that is large, or has a lot of history, has its + A file that is large, or has a lot of history, has its filelog stored in separate data (.d suffix) and index (.i suffix) files. For @@ -46,25 +46,23 @@ are combined in a single .i file. The correspondence between a file in the working directory and the filelog that tracks its history in the - repository is illustrated in figure . + repository is illustrated in . - - - - XXX add text - Relationships between - files in working directory and filelogs in repository - - - +
+ Relationships between files in working directory and + filelogs in repository + + + XXX add text + +
Managing tracked files - Mercurial uses a structure called a + Mercurial uses a structure called a manifest to collect together information about the files that it tracks. Each entry in the manifest contains information about the files present in a single @@ -76,7 +74,7 @@ Recording changeset information - The changelog contains information + The changelog contains information about each changeset. Each revision records who committed a change, the changeset comment, other pieces of changeset-related information, and the revision of the @@ -86,32 +84,30 @@ Relationships between revisions - Within a changelog, a manifest, or a filelog, each + Within a changelog, a manifest, or a filelog, each revision stores a pointer to its immediate parent (or to its two parents, if it's a merge revision). As I mentioned above, there are also relationships between revisions across these structures, and they are hierarchical in nature. - For every changeset in a repository, there is exactly one + For every changeset in a repository, there is exactly one revision stored in the changelog. Each revision of the changelog contains a pointer to a single revision of the manifest. A revision of the manifest stores a pointer to a single revision of each filelog tracked when that changeset - was created. These relationships are illustrated in figure - . + was created. These relationships are illustrated in + . - - - - XXX add text - Metadata - relationships - - +
+ Metadata relationships + + + XXX add text + +
- As the illustration shows, there is + As the illustration shows, there is not a one to one relationship between revisions in the changelog, manifest, or filelog. If the manifest hasn't changed between two @@ -126,14 +122,14 @@ Safe, efficient storage - The underpinnings of changelogs, manifests, and filelogs are + The underpinnings of changelogs, manifests, and filelogs are provided by a single structure called the revlog. Efficient storage - The revlog provides efficient storage of revisions using a + The revlog provides efficient storage of revisions using a delta mechanism. Instead of storing a complete copy of a file for each revision, it stores the changes needed to transform an older revision into the new @@ -141,7 +137,7 @@ typically a fraction of a percent of the size of a full copy of a file. - Some obsolete revision control systems can only work with + Some obsolete revision control systems can only work with deltas of text files. They must either store binary files as complete snapshots or encoded into a text representation, both of which are wasteful approaches. Mercurial can efficiently @@ -149,16 +145,16 @@ doesn't need to treat text as special. - + Safe operation - Mercurial only ever appends data to + Mercurial only ever appends data to the end of a revlog file. It never modifies a section of a file after it has written it. This is both more robust and efficient than schemes that need to modify or rewrite data. - In addition, Mercurial treats every write as part of a + In addition, Mercurial treats every write as part of a transaction that can span a number of files. A transaction is atomic: either the entire transaction succeeds and its effects are all @@ -168,7 +164,7 @@ writing it, the reader will never see a partially written result that might confuse it. - The fact that Mercurial only appends to files makes it + The fact that Mercurial only appends to files makes it easier to provide this transactional guarantee. The easier it is to do stuff like this, the more confident you should be that it's done correctly. @@ -177,7 +173,7 @@ Fast retrieval - Mercurial cleverly avoids a pitfall common to all earlier + Mercurial cleverly avoids a pitfall common to all earlier revision control systems: the problem of inefficient retrieval. Most revision control systems store the contents of a revision as an incremental series of @@ -188,16 +184,15 @@ file accumulates, the more revisions you must read, hence the longer it takes to reconstruct a particular revision. - - - - XXX add text - Snapshot of - a revlog, with incremental deltas - - +
+ Snapshot of a revlog, with incremental deltas + + + XXX add text + +
- The innovation that Mercurial applies to this problem is + The innovation that Mercurial applies to this problem is simple but effective. Once the cumulative amount of delta information stored since the last snapshot exceeds a fixed threshold, it stores a new snapshot (compressed, of course), @@ -206,8 +201,7 @@ quickly. This approach works so well that it has since been copied by several other revision control systems. - Figure illustrates + illustrates the idea. In an entry in a revlog's index file, Mercurial stores the range of entries from the data file that it must read to reconstruct a particular revision. @@ -215,7 +209,7 @@ Aside: the influence of video compression - If you're familiar with video compression or have ever + If you're familiar with video compression or have ever watched a TV feed through a digital cable or satellite service, you may know that most video compression schemes store each frame of video as a delta against its predecessor @@ -224,7 +218,7 @@ visual errors accumulate over the course of a number of inter-frame deltas. - Because it's possible for a video stream to drop + Because it's possible for a video stream to drop out occasionally due to signal glitches, and to limit the accumulation of artefacts introduced by the lossy compression process, video encoders periodically insert a @@ -240,24 +234,24 @@ Identification and strong integrity - Along with delta or snapshot information, a revlog entry + Along with delta or snapshot information, a revlog entry contains a cryptographic hash of the data that it represents. This makes it difficult to forge the contents of a revision, and easy to detect accidental corruption. - Hashes provide more than a mere check against corruption; + Hashes provide more than a mere check against corruption; they are used as the identifiers for revisions. The changeset identification hashes that you see as an end user are from revisions of the changelog. Although filelogs and the manifest also use hashes, Mercurial only uses these behind the scenes. - Mercurial verifies that hashes are correct when it + Mercurial verifies that hashes are correct when it retrieves file revisions and when it pulls changes from another repository. If it encounters an integrity problem, it will complain and stop whatever it's doing. - In addition to the effect it has on retrieval efficiency, + In addition to the effect it has on retrieval efficiency, Mercurial's use of periodic snapshots makes it more robust against partial data corruption. If a revlog becomes partly corrupted due to a hardware error or system bug, it's often @@ -271,7 +265,7 @@ Revision history, branching, and merging - Every entry in a Mercurial revlog knows the identity of its + Every entry in a Mercurial revlog knows the identity of its immediate ancestor revision, usually referred to as its parent. In fact, a revision contains room for not one parent, but two. Mercurial uses a special hash, @@ -279,14 +273,13 @@ there is no parent here. This hash is simply a string of zeroes. - In figure , you can see + In , you can see an example of the conceptual structure of a revlog. Filelogs, manifests, and changelogs all have this same structure; they differ only in the kind of data stored in each delta or snapshot. - The first revision in a revlog (at the bottom of the image) + The first revision in a revlog (at the bottom of the image) has the null ID in both of its parent slots. For a normal revision, its first parent slot contains the ID of its parent revision, and its second contains the null @@ -295,23 +288,22 @@ revision that represents a merge between branches has two normal revision IDs in its parent slots. - +
+ The conceptual structure of a revlog - - XXX add text - Revision in revlog - + + XXX add text - +
The working directory - In the working directory, Mercurial stores a snapshot of the + In the working directory, Mercurial stores a snapshot of the files from the repository as of a particular changeset. - The working directory knows which changeset + The working directory knows which changeset it contains. When you update the working directory to contain a particular changeset, Mercurial looks up the appropriate revision of the manifest to find out which files it was tracking @@ -320,13 +312,13 @@ those files, with the same contents it had when the changeset was committed. - The dirstate contains Mercurial's + The dirstate contains Mercurial's knowledge of the working directory. This details which changeset the working directory is updated to, and all of the files that Mercurial is tracking in the working directory. - Just as a revision of a revlog has room for two parents, so + Just as a revision of a revlog has room for two parents, so that it can represent either a normal revision (with one parent) or a merge of two earlier revisions, the dirstate has slots for two parents. When you use the hg @@ -342,38 +334,35 @@ What happens when you commit - The dirstate stores parent information for more than just + The dirstate stores parent information for more than just book-keeping purposes. Mercurial uses the parents of the dirstate as the parents of a new changeset when you perform a commit. - - - - XXX add text - The working - directory can have two parents - - +
+ The working directory can have two parents + + + XXX add text + +
- Figure shows the + shows the normal state of the working directory, where it has a single changeset as parent. That changeset is the tip, the newest changeset in the repository that has no children. - - - - - XXX add text - The working - directory gains new parents after a commit - - +
+ The working directory gains new parents after a + commit + + + XXX add text + +
- It's useful to think of the working directory as + It's useful to think of the working directory as the changeset I'm about to commit. Any files that you tell Mercurial that you've added, removed, renamed, or copied will be reflected in that changeset, as will @@ -381,12 +370,11 @@ the new changeset will have the parents of the working directory as its parents. - After a commit, Mercurial will update the parents of the - working directory, so that the first parent is the ID of the - new changeset, and the second is the null ID. This is shown - in figure . - Mercurial + After a commit, Mercurial will update the + parents of the working directory, so that the first parent is + the ID of the new changeset, and the second is the null ID. + This is shown in . Mercurial doesn't touch any of the files in the working directory when you commit; it just modifies the dirstate to note its new parents. @@ -395,7 +383,7 @@ Creating a new head - It's perfectly normal to update the working directory to a + It's perfectly normal to update the working directory to a changeset other than the current tip. For example, you might want to know what your project looked like last Tuesday, or you could be looking through changesets to see which one @@ -404,43 +392,39 @@ interested in, and then examine the files in the working directory directly to see their contents as they were when you committed that changeset. The effect of this is shown in - figure . + . - - - - - XXX add text - The working - directory, updated to an older changeset - - +
+ The working directory, updated to an older + changeset + + + XXX add text + +
- Having updated the working directory to an older - changeset, what happens if you make some changes, and then - commit? Mercurial behaves in the same way as I outlined + Having updated the working directory to an + older changeset, what happens if you make some changes, and + then commit? Mercurial behaves in the same way as I outlined above. The parents of the working directory become the parents of the new changeset. This new changeset has no children, so it becomes the new tip. And the repository now contains two changesets that have no children; we call these heads. You can see the structure that - this creates in figure . + this creates in . - - - - - XXX add text - After a - commit made while synced to an older changeset - - +
+ After a commit made while synced to an older + changeset + + + XXX add text + +
- If you're new to Mercurial, you should keep in mind a + If you're new to Mercurial, you should keep in mind a common error, which is to use the hg pull command without any options. By default, the hg @@ -452,7 +436,7 @@ a new head, because your working directory isn't synced to whatever the current tip is. - I put the word error in quotes because + I put the word error in quotes because all that you need to do to rectify this situation is hg merge, then hg commit. In other words, this @@ -466,67 +450,66 @@ Merging heads - When you run the hg merge - command, Mercurial leaves the first parent of the working - directory unchanged, and sets the second parent to the - changeset you're merging with, as shown in figure . + When you run the hg + merge command, Mercurial leaves the first parent + of the working directory unchanged, and sets the second parent + to the changeset you're merging with, as shown in . - - - - - XXX add text - Merging two - heads - - +
+ Merging two heads + + + + + XXX add text + +
- Mercurial also has to modify the working directory, to + Mercurial also has to modify the working directory, to merge the files managed in the two changesets. Simplified a little, the merging process goes like this, for every file in the manifests of both changesets. - If neither changeset has modified a file, do + If neither changeset has modified a file, do nothing with that file. - If one changeset has modified a file, and the + If one changeset has modified a file, and the other hasn't, create the modified copy of the file in the working directory. - If one changeset has removed a file, and the + If one changeset has removed a file, and the other hasn't (or has also deleted it), delete the file from the working directory. - If one changeset has removed a file, but the + If one changeset has removed a file, but the other has modified the file, ask the user what to do: keep the modified file, or remove it? - If both changesets have modified a file, + If both changesets have modified a file, invoke an external merge program to choose the new contents for the merged file. This may require input from the user. - If one changeset has modified a file, and the + If one changeset has modified a file, and the other has renamed or copied the file, make sure that the changes follow the new name of the file. - There are more details&emdash;merging has plenty of corner + There are more details&emdash;merging has plenty of corner cases&emdash;but these are the most common choices that are involved in a merge. As you can see, most cases are completely automatic, and indeed most merges finish automatically, without requiring your input to resolve any conflicts. - When you're thinking about what happens when you commit + When you're thinking about what happens when you commit after a merge, once again the working directory is the changeset I'm about to commit. After the hg merge command completes, the working directory has two parents; these will become the parents of the new changeset. - Mercurial lets you perform multiple merges, but you must + Mercurial lets you perform multiple merges, but you must commit the results of each individual merge as you go. This is necessary because Mercurial only tracks two parents for both revisions and the working directory. While it would be @@ -539,7 +522,7 @@ Other interesting design features - In the sections above, I've tried to highlight some of the + In the sections above, I've tried to highlight some of the most important aspects of Mercurial's design, to illustrate that it pays careful attention to reliability and performance. However, the attention to detail doesn't stop there. There are @@ -552,13 +535,13 @@ Clever compression - When appropriate, Mercurial will store both snapshots and + When appropriate, Mercurial will store both snapshots and deltas in compressed form. It does this by always trying to compress a snapshot or delta, but only storing the compressed version if it's smaller than the uncompressed version. - This means that Mercurial does the right + This means that Mercurial does the right thing when storing a file whose native form is compressed, such as a zip archive or a JPEG image. When these types of files are compressed a second @@ -566,7 +549,7 @@ once-compressed form, and so Mercurial will store the plain zip or JPEG. - Deltas between revisions of a compressed file are usually + Deltas between revisions of a compressed file are usually larger than snapshots of the file, and Mercurial again does the right thing in these cases. It finds that such a delta exceeds the threshold at which it should store a @@ -577,7 +560,7 @@ Network recompression - When storing revisions on disk, Mercurial uses the + When storing revisions on disk, Mercurial uses the deflate compression algorithm (the same one used by the popular zip archive format), which balances good speed with a respectable compression @@ -585,7 +568,7 @@ network connection, Mercurial uncompresses the compressed revision data. - If the connection is over HTTP, Mercurial recompresses + If the connection is over HTTP, Mercurial recompresses the entire stream of data using a compression algorithm that gives a better compression ratio (the Burrows-Wheeler algorithm from the widely used bzip2 @@ -595,7 +578,7 @@ transferred, yielding better network performance over almost all kinds of network. - (If the connection is over ssh, + (If the connection is over ssh, Mercurial doesn't recompress the stream, because ssh can already do this itself.) @@ -605,20 +588,20 @@ Read/write ordering and atomicity - Appending to files isn't the whole story when it comes to - guaranteeing that a reader won't see a partial write. If you - recall figure , revisions in the - changelog point to revisions in the manifest, and revisions in - the manifest point to revisions in filelogs. This hierarchy - is deliberate. + Appending to files isn't the whole story when + it comes to guaranteeing that a reader won't see a partial + write. If you recall , + revisions in + the changelog point to revisions in the manifest, and + revisions in the manifest point to revisions in filelogs. + This hierarchy is deliberate. - A writer starts a transaction by writing filelog and + A writer starts a transaction by writing filelog and manifest data, and doesn't write any changelog data until those are finished. A reader starts by reading changelog data, then manifest data, followed by filelog data. - Since the writer has always finished writing filelog and + Since the writer has always finished writing filelog and manifest data before it writes to the changelog, a reader will never read a pointer to a partially written manifest revision from the changelog, and it will never read a pointer to a @@ -628,7 +611,7 @@ Concurrent access - The read/write ordering and atomicity guarantees mean that + The read/write ordering and atomicity guarantees mean that Mercurial never needs to lock a repository when it's reading data, even if the repository is being written to while the read is occurring. This has a big @@ -637,7 +620,7 @@ safely all at once, no matter whether it's being written to or not. - The lockless nature of reading means that if you're + The lockless nature of reading means that if you're sharing a repository on a multi-user system, you don't need to grant other local users permission to write to your repository in order for @@ -650,7 +633,7 @@ which of course makes for all kinds of nasty and annoying security and administrative problems.) - Mercurial uses locks to ensure that only one process can + Mercurial uses locks to ensure that only one process can write to a repository at a time (the locking mechanism is safe even over filesystems that are notoriously hostile to locking, such as NFS). If a repository is locked, a writer will wait @@ -664,7 +647,7 @@ Safe dirstate access - As with revision data, Mercurial doesn't take a lock to + As with revision data, Mercurial doesn't take a lock to read the dirstate file; it does acquire a lock to write it. To avoid the possibility of reading a partially written copy of the dirstate file, Mercurial writes to a file with a @@ -679,17 +662,17 @@ Avoiding seeks - Critical to Mercurial's performance is the avoidance of + Critical to Mercurial's performance is the avoidance of seeks of the disk head, since any seek is far more expensive than even a comparatively large read operation. - This is why, for example, the dirstate is stored in a + This is why, for example, the dirstate is stored in a single file. If there were a dirstate file per directory that Mercurial tracked, the disk would seek once per directory. Instead, Mercurial reads the entire single dirstate file in one step. - Mercurial also uses a copy on write scheme + Mercurial also uses a copy on write scheme when cloning a repository on local storage. Instead of copying every revlog file from the old repository into the new repository, it makes a hard link, which is a @@ -700,7 +683,7 @@ one repository is using the file, so Mercurial makes a new copy of the file that is private to this repository. - A few revision control developers have pointed out that + A few revision control developers have pointed out that this idea of making a complete private copy of a file is not very efficient in its use of storage. While this is true, storage is cheap, and this method gives the highest @@ -714,21 +697,21 @@ Other contents of the dirstate - Because Mercurial doesn't force you to tell it when you're + Because Mercurial doesn't force you to tell it when you're modifying a file, it uses the dirstate to store some extra information so it can determine efficiently whether you have modified a file. For each file in the working directory, it stores the time that it last modified the file itself, and the size of the file at that time. - When you explicitly hg + When you explicitly hg add, hg remove, hg rename or hg copy files, Mercurial updates the dirstate so that it knows what to do with those files when you commit. - When Mercurial is checking the states of files in the + When Mercurial is checking the states of files in the working directory, it first checks a file's modification time. If that has not changed, the file must not have been modified. If the file's size has changed, the file must have been diff -r 6b1577ef5135 -r 1c13ed2130a7 en/ch04-daily.xml --- a/en/ch04-daily.xml Fri Mar 20 17:17:55 2009 +0800 +++ b/en/ch04-daily.xml Mon Mar 30 16:23:33 2009 +0800 @@ -1,6 +1,6 @@ - + Mercurial in daily use @@ -274,7 +274,7 @@ &interaction.daily.copy.merge; - + Why should changes follow copies? This behaviour, of changes to a file propagating out to @@ -328,7 +328,7 @@ Unix-like systems, that's cp) to make a copy of a file, then hg add the new copy by hand. Before you do so, though, please do - reread section , and make + reread , and make an informed decision that this behaviour is not appropriate to your specific case. @@ -529,10 +529,10 @@ decide it was a mistake, you can still do something about it, though your options may be more limited. - For more information about the hg - revert command, and details about how to deal with - changes you have already committed, see chapter . + For more information about the hg revert command, and details about + how to deal with changes you have already committed, see .
diff -r 6b1577ef5135 -r 1c13ed2130a7 en/ch05-collab.xml --- a/en/ch05-collab.xml Fri Mar 20 17:17:55 2009 +0800 +++ b/en/ch05-collab.xml Mon Mar 30 16:23:33 2009 +0800 @@ -1,10 +1,10 @@ - + Collaborating with other people - As a completely decentralised tool, Mercurial doesn't impose + As a completely decentralised tool, Mercurial doesn't impose any policy on how people ought to work with each other. However, if you're new to distributed revision control, it helps to have some tools and examples in mind when you're thinking about @@ -13,15 +13,15 @@ Mercurial's web interface - Mercurial has a powerful web interface that provides several + Mercurial has a powerful web interface that provides several useful capabilities. - For interactive use, the web interface lets you browse a + For interactive use, the web interface lets you browse a single repository or a collection of repositories. You can view the history of a repository, examine each change (comments and diffs), and view the contents of each directory and file. - Also for human consumption, the web interface provides an + Also for human consumption, the web interface provides an RSS feed of the changes in a repository. This lets you subscribe to a repository using your favourite feed reader, and be automatically notified of activity in that @@ -31,35 +31,35 @@ configuration on the part of whoever is serving the repository. - The web interface also lets remote users clone a repository, + The web interface also lets remote users clone a repository, pull changes from it, and (when the server is configured to permit it) push changes back to it. Mercurial's HTTP tunneling protocol aggressively compresses data, so that it works efficiently even over low-bandwidth network connections. - The easiest way to get started with the web interface is to + The easiest way to get started with the web interface is to use your web browser to visit an existing repository, such as the master Mercurial repository at http://www.selenic.com/repo/hg?style=gitweb. - If you're interested in providing a web interface to your - own repositories, Mercurial provides two ways to do this. The - first is using the hg serve - command, which is best suited to short-term - lightweight serving. See section below for details of how to use + If you're interested in providing a web interface + to your own repositories, Mercurial provides two ways to do + this. The first is using the hg + serve command, which is best suited to short-term + lightweight serving. See below for details of how to use this command. If you have a long-lived repository that you'd like to make permanently available, Mercurial has built-in support for the CGI (Common Gateway Interface) standard, which - all common web servers support. See section for details of CGI + all common web servers support. See for details of CGI configuration. Collaboration models - With a suitably flexible tool, making decisions about + With a suitably flexible tool, making decisions about workflow is much more of a social engineering challenge than a technical one. Mercurial imposes few limitations on how you can structure the flow of work in a project, so it's up to you and @@ -69,13 +69,13 @@ Factors to keep in mind - The most important aspect of any model that you must keep + The most important aspect of any model that you must keep in mind is how well it matches the needs and capabilities of the people who will be using it. This might seem self-evident; even so, you still can't afford to forget it for a moment. - I once put together a workflow model that seemed to make + I once put together a workflow model that seemed to make perfect sense to me, but that caused a considerable amount of consternation and strife within my development team. In spite of my attempts to explain why we needed a complex set of @@ -85,7 +85,7 @@ operating under, or face the consequences of those constraints in the details of the model that I was advocating. - Don't sweep foreseeable social or technical problems under + Don't sweep foreseeable social or technical problems under the rug. Whatever scheme you put into effect, you should plan for mistakes and problem scenarios. Consider adding automated machinery to prevent, or quickly recover from, trouble that @@ -101,12 +101,12 @@ Informal anarchy - I wouldn't suggest an anything goes + I wouldn't suggest an anything goes approach as something sustainable, but it's a model that's easy to grasp, and it works perfectly well in a few unusual situations. - As one example, many projects have a loose-knit group of + As one example, many projects have a loose-knit group of collaborators who rarely physically meet each other. Some groups like to overcome the isolation of working at a distance by organising occasional sprints. In a sprint, @@ -115,21 +115,21 @@ place) and spend several days more or less locked in there, hacking intensely on a handful of projects. - A sprint is the perfect place to use the hg serve command, since hg serve does not require any fancy - server infrastructure. You can get started with hg serve in moments, by reading - section below. Then simply - tell - the person next to you that you're running a server, send the - URL to them in an instant message, and you immediately have a - quick-turnaround way to work together. They can type your URL - into their web browser and quickly review your changes; or - they can pull a bugfix from you and verify it; or they can - clone a branch containing a new feature and try it out. + A sprint is the perfect place to use the + hg serve command, since + hg serve does not require any + fancy server infrastructure. You can get started with + hg serve in moments, by + reading below. Then simply + tell the person next to you that you're running a server, send + the URL to them in an instant message, and you immediately + have a quick-turnaround way to work together. They can type + your URL into their web browser and quickly review your + changes; or they can pull a bugfix from you and verify it; or + they can clone a branch containing a new feature and try it + out. - The charm, and the problem, with doing things in an ad hoc + The charm, and the problem, with doing things in an ad hoc fashion like this is that only people who know about your changes, and where they are, can see them. Such an informal approach simply doesn't scale beyond a handful people, because @@ -140,18 +140,18 @@ A single central repository - For smaller projects migrating from a centralised revision + For smaller projects migrating from a centralised revision control tool, perhaps the easiest way to get started is to have changes flow through a single shared central repository. This is also the most common building block for more ambitious workflow schemes. - Contributors start by cloning a copy of this repository. + Contributors start by cloning a copy of this repository. They can pull changes from it whenever they need to, and some (perhaps all) developers have permission to push a change back when they're ready for other people to see it. - Under this model, it can still often make sense for people + Under this model, it can still often make sense for people to pull changes directly from each other, without going through the central repository. Consider a case in which I have a tentative bug fix, but I am worried that if I were to @@ -162,22 +162,21 @@ lets us put off publishing the potentially unsafe change until it has had a little testing. - In this kind of scenario, people usually use the - ssh protocol to securely push changes to - the central repository, as documented in section . It's also - usual to publish a read-only copy of the repository over HTTP - using CGI, as in section . - Publishing over HTTP - satisfies the needs of people who don't have push access, and - those who want to use web browsers to browse the repository's - history. + In this kind of scenario, people usually use + the ssh protocol to securely push changes + to the central repository, as documented in . It's also usual to publish a + read-only copy of the repository over HTTP using CGI, as in + . Publishing + over HTTP satisfies the needs of people who don't have push + access, and those who want to use web browsers to browse the + repository's history. Working with multiple branches - Projects of any significant size naturally tend to make + Projects of any significant size naturally tend to make progress on several fronts simultaneously. In the case of software, it's common for a project to go through periodic official releases. A release might then go into @@ -190,7 +189,7 @@ different directions in which development is proceeding. - Mercurial is particularly well suited to managing a number + Mercurial is particularly well suited to managing a number of simultaneous, but not identical, branches. Each development direction can live in its own central repository, and you can merge changes from one to @@ -199,27 +198,27 @@ branch will never affect a stable branch unless someone explicitly merges those changes in. - Here's an example of how this can work in practice. Let's + Here's an example of how this can work in practice. Let's say you have one main branch on a central server. &interaction.branching.init; - People clone it, make changes locally, test them, and push + People clone it, make changes locally, test them, and push them back. - Once the main branch reaches a release milestone, you can + Once the main branch reaches a release milestone, you can use the hg tag command to give a permanent name to the milestone revision. &interaction.branching.tag; - Let's say some ongoing + Let's say some ongoing development occurs on the main branch. &interaction.branching.main; - Using the tag that was recorded at the milestone, people + Using the tag that was recorded at the milestone, people who clone that repository at any time in the future can use hg update to get a copy of the working directory exactly as it was when that tagged @@ -227,26 +226,26 @@ &interaction.branching.update; - In addition, immediately after the main branch is tagged, + In addition, immediately after the main branch is tagged, someone can then clone the main branch on the server to a new stable branch, also on the server. &interaction.branching.clone; - Someone who needs to make a change to the stable branch + Someone who needs to make a change to the stable branch can then clone that repository, make their changes, commit, and push their changes back there. &interaction.branching.stable; - Because Mercurial repositories are independent, and + Because Mercurial repositories are independent, and Mercurial doesn't move changes around automatically, the stable and main branches are isolated from each other. The changes that you made on the main branch don't leak to the stable branch, and vice versa. - You'll often want all of your bugfixes on the stable + You'll often want all of your bugfixes on the stable branch to show up on the main branch, too. Rather than rewrite a bugfix on the main branch, you can simply pull and merge changes from the stable to the main branch, and @@ -254,7 +253,7 @@ &interaction.branching.merge; - The main branch will still contain changes that are not on + The main branch will still contain changes that are not on the stable branch, but it will also contain all of the bugfixes from the stable branch. The stable branch remains unaffected by these changes. @@ -263,24 +262,22 @@ Feature branches - For larger projects, an effective way to manage change is + For larger projects, an effective way to manage change is to break up a team into smaller groups. Each group has a shared branch of its own, cloned from a single master branch used by the entire project. People working on an individual branch are typically quite isolated from developments on other branches. - - - - - XXX add text - Feature - branches - - +
+ Feature branches + + + XXX add text + +
- When a particular feature is deemed to be in suitable + When a particular feature is deemed to be in suitable shape, someone on that feature team pulls and merges from the master branch into the feature branch, then pushes back up to the master branch. @@ -289,12 +286,12 @@ The release train - Some projects are organised on a train + Some projects are organised on a train basis: a release is scheduled to happen every few months, and whatever features are ready when the train is ready to leave are allowed in. - This model resembles working with feature branches. The + This model resembles working with feature branches. The difference is that when a feature branch misses a train, someone on the feature team pulls and merges the changes that went out on that train release into the feature branch, and @@ -305,7 +302,7 @@ The Linux kernel model - The development of the Linux kernel has a shallow + The development of the Linux kernel has a shallow hierarchical structure, surrounded by a cloud of apparent chaos. Because most Linux developers use git, a distributed revision control tool @@ -313,14 +310,14 @@ describe the way work flows in that environment; if you like the ideas, the approach translates well across tools. - At the center of the community sits Linus Torvalds, the + At the center of the community sits Linus Torvalds, the creator of Linux. He publishes a single source repository that is considered the authoritative current tree by the entire developer community. Anyone can clone Linus's tree, but he is very choosy about whose trees he pulls from. - Linus has a number of trusted lieutenants. + Linus has a number of trusted lieutenants. As a general rule, he pulls whatever changes they publish, in most cases without even reviewing those changes. Some of those lieutenants are generally agreed to be @@ -332,7 +329,7 @@ If the maintainer reviews their changes and agrees to take them, they'll pass them along to Linus in due course. - Individual lieutenants have their own approaches to + Individual lieutenants have their own approaches to reviewing, accepting, and publishing changes; and for deciding when to feed them to Linus. In addition, there are several well known branches that people use for different purposes. @@ -343,14 +340,14 @@ that they are about to feed upstream; and so on. Others just publish a single tree. - This model has two notable features. The first is that + This model has two notable features. The first is that it's pull only. You have to ask, convince, or beg another developer to take a change from you, because there are almost no trees to which more than one person can push, and there's no way to push changes into a tree that someone else controls. - The second is that it's based on reputation and acclaim. + The second is that it's based on reputation and acclaim. If you're an unknown, Linus will probably ignore changes from you without even responding. But a subsystem maintainer will probably review them, and will likely take them if they pass @@ -361,14 +358,14 @@ Linus hasn't yet accepted, people with similar interests may pull your changes regularly to keep up with your work. - Reputation and acclaim don't necessarily cross subsystem + Reputation and acclaim don't necessarily cross subsystem or people boundaries. If you're a respected but specialised storage hacker, and you try to fix a networking bug, that change will receive a level of scrutiny from a network maintainer comparable to a change from a complete stranger. - To people who come from more orderly project backgrounds, + To people who come from more orderly project backgrounds, the comparatively chaotic Linux kernel development process often seems completely insane. It's subject to the whims of individuals; people make sweeping changes whenever they deem @@ -380,13 +377,13 @@ Pull-only versus shared-push collaboration - A perpetual source of heat in the open source community is + A perpetual source of heat in the open source community is whether a development model in which people only ever pull changes from others is better than one in which multiple people can push changes to a shared repository. - Typically, the backers of the shared-push model use tools + Typically, the backers of the shared-push model use tools that actively enforce this approach. If you're using a centralised revision control tool such as Subversion, there's no way to make a choice over which model you'll use: the tool @@ -394,7 +391,7 @@ you'll have to roll your own approach on top (such as applying a patch by hand). - A good distributed revision control tool, such as + A good distributed revision control tool, such as Mercurial, will support both models. You and your collaborators can then structure how you work together based on your own needs and preferences, not on what contortions @@ -404,34 +401,34 @@ Where collaboration meets branch management - Once you and your team set up some shared repositories and - start propagating changes back and forth between local and - shared repos, you begin to face a related, but slightly - different challenge: that of managing the multiple directions - in which your team may be moving at once. Even though this - subject is intimately related to how your team collaborates, - it's dense enough to merit treatment of its own, in chapter - . + Once you and your team set up some shared + repositories and start propagating changes back and forth + between local and shared repos, you begin to face a related, + but slightly different challenge: that of managing the + multiple directions in which your team may be moving at once. + Even though this subject is intimately related to how your + team collaborates, it's dense enough to merit treatment of its + own, in .
The technical side of sharing - The remainder of this chapter is devoted to the question of + The remainder of this chapter is devoted to the question of serving data to your collaborators. - + Informal sharing with <command role="hg-cmd">hg serve</command> - Mercurial's hg serve + Mercurial's hg serve command is wonderfully suited to small, tight-knit, and fast-paced group environments. It also provides a great way to get a feel for using Mercurial commands over a network. - Run hg serve inside a + Run hg serve inside a repository, and in under a second it will bring up a specialised HTTP server; this will accept connections from any client, and serve up data for that repository until you terminate it. @@ -442,24 +439,24 @@ on a laptop is likely to look something like http://my-laptop.local:8000/. - The hg serve command is + The hg serve command is not a general-purpose web server. It can do only two things: - Allow people to browse the history of the + Allow people to browse the history of the repository it's serving, from their normal web browsers. - Speak Mercurial's wire protocol, so that people + Speak Mercurial's wire protocol, so that people can hg clone or hg pull changes from that repository. - In particular, hg serve + In particular, hg serve won't allow remote users to modify your repository. It's intended for read-only use. - If you're getting started with Mercurial, there's nothing to + If you're getting started with Mercurial, there's nothing to prevent you from using hg serve to serve up a repository on your own computer, then use commands like hg clone, A few things to keep in mind - Because it provides unauthenticated read access to all + Because it provides unauthenticated read access to all clients, you should only use hg serve in an environment where you either don't care, or have complete control over, who can access your network and pull data from your repository. - The hg serve command + The hg serve command knows nothing about any firewall software you might have installed on your system or network. It cannot detect or control your firewall software. If other people are unable to @@ -486,13 +483,13 @@ (after you make sure that they're using the correct URL) is check your firewall configuration. - By default, hg serve + By default, hg serve listens for incoming connections on port 8000. If another process is already listening on the port you want to use, you can specify a different port to listen on using the option. - Normally, when hg serve + Normally, when hg serve starts, it prints no output, which can be a bit unnerving. If you'd like to confirm that it is indeed running correctly, and find out what URL you should send to your collaborators, start @@ -501,59 +498,59 @@
- + Using the Secure Shell (ssh) protocol - You can pull and push changes securely over a network + You can pull and push changes securely over a network connection using the Secure Shell (ssh) protocol. To use this successfully, you may have to do a little bit of configuration on the client or server sides. - If you're not familiar with ssh, it's a network protocol + If you're not familiar with ssh, it's a network protocol that lets you securely communicate with another computer. To use it with Mercurial, you'll be setting up one or more user accounts on a server so that remote users can log in and execute commands. - (If you are familiar with ssh, you'll + (If you are familiar with ssh, you'll probably find some of the material that follows to be elementary in nature.) How to read and write ssh URLs - An ssh URL tends to look like this: + An ssh URL tends to look like this: ssh://bos@hg.serpentine.com:22/hg/hgbook - The ssh:// + The ssh:// part tells Mercurial to use the ssh protocol. - The bos@ + The bos@ component indicates what username to log into the server as. You can leave this out if the remote username is the same as your local username. - The + The hg.serpentine.com gives the hostname of the server to log into. - The :22 identifies the port + The :22 identifies the port number to connect to the server on. The default port is 22, so you only need to specify a colon and port number if you're not using port 22. - The remainder of the URL is the local path to + The remainder of the URL is the local path to the repository on the server. - There's plenty of scope for confusion with the path + There's plenty of scope for confusion with the path component of ssh URLs, as there is no standard way for tools to interpret it. Some programs behave differently than others when dealing with these paths. This isn't an ideal situation, but it's unlikely to change. Please read the following paragraphs carefully. - Mercurial treats the path to a repository on the server as + Mercurial treats the path to a repository on the server as relative to the remote user's home directory. For example, if user foo on the server has a home directory of /home/foo, then an @@ -562,13 +559,13 @@ refers to the directory /home/foo/bar. - If you want to specify a path relative to another user's + If you want to specify a path relative to another user's home directory, you can use a path that starts with a tilde character followed by the user's name (let's call them otheruser), like this. ssh://server/~otheruser/hg/repo - And if you really want to specify an + And if you really want to specify an absolute path on the server, begin the path component with two slashes, as in this example. ssh://server//absolute/path @@ -577,7 +574,7 @@ Finding an ssh client for your system - Almost every Unix-like system comes with OpenSSH + Almost every Unix-like system comes with OpenSSH preinstalled. If you're using such a system, run which ssh to find out if the ssh command is installed (it's usually in @@ -585,17 +582,17 @@ unlikely event that it isn't present, take a look at your system documentation to figure out how to install it. - On Windows, you'll first need to download a suitable ssh + On Windows, you'll first need to download a suitable ssh client. There are two alternatives. - Simon Tatham's excellent PuTTY package + Simon Tatham's excellent PuTTY package web:putty provides a complete suite of ssh client commands. - If you have a high tolerance for pain, you can + If you have a high tolerance for pain, you can use the Cygwin port of OpenSSH. - In either case, you'll need to edit your In either case, you'll need to edit your hg.ini file to tell Mercurial where to find the actual client command. For example, if you're using PuTTY, you'll need to use the @@ -605,7 +602,7 @@ ssh = C:/path/to/plink.exe -ssh -i "C:/path/to/my/private/key" - The path to plink shouldn't contain + The path to plink shouldn't contain any whitespace characters, or Mercurial may not be able to run it correctly (so putting it in C:\Program Files is probably @@ -616,7 +613,7 @@ Generating a key pair - To avoid the need to repetitively type a password every + To avoid the need to repetitively type a password every time you need to use your ssh client, I recommend generating a key pair. On a Unix-like system, the ssh-keygen command will do the trick. On @@ -624,13 +621,13 @@ puttygen command is what you'll need. - When you generate a key pair, it's usually + When you generate a key pair, it's usually highly advisable to protect it with a passphrase. (The only time that you might not want to do this is when you're using the ssh protocol for automated tasks on a secure network.) - Simply generating a key pair isn't enough, however. + Simply generating a key pair isn't enough, however. You'll need to add the public key to the set of authorised keys for whatever user you're logging in remotely as. For servers using OpenSSH (the vast majority), this will mean @@ -639,7 +636,7 @@ role="special" class="directory">.ssh directory. - On a Unix-like system, your public key will have a + On a Unix-like system, your public key will have a .pub extension. If you're using puttygen on Windows, you can save the public key to a file of your choosing, or paste it from the @@ -650,7 +647,7 @@ Using an authentication agent - An authentication agent is a daemon that stores + An authentication agent is a daemon that stores passphrases in memory (so it will forget passphrases if you log out and log back in again). An ssh client will notice if it's running, and query it for a passphrase. If there's no @@ -659,14 +656,14 @@ every time Mercurial tries to communicate with a server on your behalf (e.g. whenever you pull or push changes). - The downside of storing passphrases in an agent is that + The downside of storing passphrases in an agent is that it's possible for a well-prepared attacker to recover the plain text of your passphrases, in some cases even if your system has been power-cycled. You should make your own judgment as to whether this is an acceptable risk. It certainly saves a lot of repeated typing. - On Unix-like systems, the agent is called + On Unix-like systems, the agent is called ssh-agent, and it's often run automatically for you when you log in. You'll need to use the ssh-add command to add passphrases to the @@ -679,7 +676,7 @@ Configuring the server side properly - Because ssh can be fiddly to set up if you're new to it, + Because ssh can be fiddly to set up if you're new to it, there's a variety of things that can go wrong. Add Mercurial on top, and there's plenty more scope for head-scratching. Most of these potential problems occur on the server side, not @@ -687,7 +684,7 @@ configuration working, it will usually continue to work indefinitely. - Before you try using Mercurial to talk to an ssh server, + Before you try using Mercurial to talk to an ssh server, it's best to make sure that you can use the normal ssh or putty command to talk to the server first. If you run into problems with using @@ -698,29 +695,29 @@ before you worry about whether there's a problem with Mercurial. - The first thing to be sure of on the server side is that + The first thing to be sure of on the server side is that you can actually log in from another machine at all. If you can't use ssh or putty to log in, the error message you get may give you a few hints as to what's wrong. The most common problems are as follows. - If you get a connection refused + If you get a connection refused error, either there isn't an SSH daemon running on the server at all, or it's inaccessible due to firewall configuration. - If you get a no route to host + If you get a no route to host error, you either have an incorrect address for the server or a seriously locked down firewall that won't admit its existence at all. - If you get a permission denied + If you get a permission denied error, you may have mistyped the username on the server, or you could have mistyped your key's passphrase or the remote user's password. - In summary, if you're having trouble talking to the + In summary, if you're having trouble talking to the server's ssh daemon, first make sure that one is running at all. On many systems it will be installed, but disabled, by default. Once you're done with this step, you should then @@ -730,23 +727,23 @@ for misconfiguration until you've checked these two first. - If you're using an authentication agent on the client side + If you're using an authentication agent on the client side to store passphrases for your keys, you ought to be able to log into the server without being prompted for a passphrase or a password. If you're prompted for a passphrase, there are a few possible culprits. - You might have forgotten to use + You might have forgotten to use ssh-add or pageant to store the passphrase. - You might have stored the passphrase for the + You might have stored the passphrase for the wrong key. - If you're being prompted for the remote user's password, + If you're being prompted for the remote user's password, there are another few possible problems to check. - Either the user's home directory or their + Either the user's home directory or their .ssh directory might have excessively liberal permissions. As a result, the ssh daemon will not trust or read their @@ -755,19 +752,19 @@ role="special" class="directory">.ssh
directory will often cause this symptom.
- The user's The user's authorized_keys file may have a problem. If anyone other than the user owns or can write to that file, the ssh daemon will not trust or read it.
- In the ideal world, you should be able to run the + In the ideal world, you should be able to run the following command successfully, and it should print exactly one line of output, the current date and time. ssh myserver date - If, on your server, you have login scripts that print + If, on your server, you have login scripts that print banners or other junk even when running non-interactive commands like this, you should fix them before you continue, so that they only print output if they're run interactively. @@ -781,43 +778,43 @@ shell is to check the return code from the command tty -s.) - Once you've verified that plain old ssh is working with + Once you've verified that plain old ssh is working with your server, the next step is to ensure that Mercurial runs on the server. The following command should run successfully: ssh myserver hg version - If you see an error message instead of normal If you see an error message instead of normal hg version output, this is usually because you haven't installed Mercurial to /usr/bin. Don't worry if this is the case; you don't need to do that. But you should check for a few possible problems. - Is Mercurial really installed on the server at + Is Mercurial really installed on the server at all? I know this sounds trivial, but it's worth checking! - Maybe your shell's search path (usually set + Maybe your shell's search path (usually set via the PATH environment variable) is simply misconfigured. - Perhaps your PATH environment + Perhaps your PATH environment variable is only being set to point to the location of the hg executable if the login session is interactive. This can happen if you're setting the path in the wrong shell login script. See your shell's documentation for details. - The PYTHONPATH environment + The PYTHONPATH environment variable may need to contain the path to the Mercurial Python modules. It might not be set at all; it could be incorrect; or it may be set only if the login is interactive. - If you can run hg version + If you can run hg version over an ssh connection, well done! You've got the server and client sorted out. You should now be able to use Mercurial to access repositories hosted by that username on that server. @@ -829,19 +826,19 @@ Using compression with ssh - Mercurial does not compress data when it uses the ssh + Mercurial does not compress data when it uses the ssh protocol, because the ssh protocol can transparently compress data. However, the default behaviour of ssh clients is not to request compression. - Over any network other than a fast LAN (even a wireless + Over any network other than a fast LAN (even a wireless network), using compression is likely to significantly speed up Mercurial's network operations. For example, over a WAN, someone measured compression as reducing the amount of time required to clone a particularly large repository from 51 minutes to 17 minutes. - Both ssh and plink + Both ssh and plink accept a option which turns on compression. You can easily edit your ~/.hgrc to enable compression for @@ -849,7 +846,7 @@ [ui] ssh = ssh -C - If you use ssh, you can configure it to + If you use ssh, you can configure it to always use compression when talking to your server. To do this, edit your .ssh/config file (which may not @@ -857,7 +854,7 @@ Host hg Compression yes HostName hg.example.com - This defines an alias, hg. When you + This defines an alias, hg. When you use it on the ssh command line or in a Mercurial ssh-protocol URL, it will cause ssh to connect to @@ -867,20 +864,20 @@
- + Serving over HTTP using CGI - Depending on how ambitious you are, configuring Mercurial's + Depending on how ambitious you are, configuring Mercurial's CGI interface can take anything from a few moments to several hours. - We'll begin with the simplest of examples, and work our way + We'll begin with the simplest of examples, and work our way towards a more complex configuration. Even for the most basic case, you're almost certainly going to need to read and modify your web server's configuration. - Configuring a web server is a complex, fiddly, and + Configuring a web server is a complex, fiddly, and highly system-dependent activity. I can't possibly give you instructions that will cover anything like all of the cases you will encounter. Please use your discretion and judgment in @@ -892,25 +889,25 @@ Web server configuration checklist - Before you continue, do take a few moments to check a few + Before you continue, do take a few moments to check a few aspects of your system's setup. - Do you have a web server installed at all? + Do you have a web server installed at all? Mac OS X ships with Apache, but many other systems may not have a web server installed. - If you have a web server installed, is it + If you have a web server installed, is it actually running? On most systems, even if one is present, it will be disabled by default. - Is your server configured to allow you to run + Is your server configured to allow you to run CGI programs in the directory where you plan to do so? Most servers default to explicitly disabling the ability to run CGI programs. - If you don't have a web server installed, and don't have + If you don't have a web server installed, and don't have substantial experience configuring Apache, you should consider using the lighttpd web server instead of Apache. Apache has a well-deserved reputation for baroque and @@ -925,7 +922,7 @@ Basic CGI configuration - On Unix-like systems, it's common for users to have a + On Unix-like systems, it's common for users to have a subdirectory named something like public_html in their home directory, from which they can serve up web pages. A file @@ -933,19 +930,19 @@ accessible at a URL of the form http://www.example.com/username/foo. - To get started, find the To get started, find the hgweb.cgi script that should be present in your Mercurial installation. If you can't quickly find a local copy on your system, simply download one from the master Mercurial repository at http://www.selenic.com/repo/hg/raw-file/tip/hgweb.cgi. - You'll need to copy this script into your You'll need to copy this script into your public_html directory, and ensure that it's executable. cp .../hgweb.cgi ~/public_html chmod 755 ~/public_html/hgweb.cgi - The 755 argument to + The 755 argument to chmod is a little more general than just making the script executable: it ensures that the script is executable by anyone, and that group and @@ -958,11 +955,11 @@ must not be writable by others. chmod 755 ~/public_html - + What could <emphasis>possibly</emphasis> go wrong? - Once you've copied the CGI script into place, go into a + Once you've copied the CGI script into place, go into a web browser, and try to open the URL http://myhostname/ @@ -976,7 +973,7 @@ fresh installation of Apache, and a user account that I created specially to perform this exercise. - Your web server may have per-user directories disabled. + Your web server may have per-user directories disabled. If you're using Apache, search your config file for a UserDir directive. If there's none present, per-user directories will be disabled. If one @@ -987,7 +984,7 @@ directory, for example public_html. - Your file access permissions may be too restrictive. + Your file access permissions may be too restrictive. The web server must be able to traverse your home directory and directories under your public_html directory, and @@ -997,34 +994,34 @@ find ~/public_html -type d -print0 | xargs -0r chmod 755 find ~/public_html -type f -print0 | xargs -0r chmod 644 - The other possibility with permissions is that you might + The other possibility with permissions is that you might get a completely empty window when you try to load the script. In this case, it's likely that your access permissions are too permissive. Apache's suexec subsystem won't execute a script that's group- or world-writable, for example. - Your web server may be configured to disallow execution + Your web server may be configured to disallow execution of CGI programs in your per-user web directory. Here's Apache's default per-user configuration from my Fedora system. - + &ch06-apache-config.lst; - If you find a similar-looking + If you find a similar-looking Directory group in your Apache configuration, the directive to look at inside it is Options. Add ExecCGI to the end of this list if it's missing, and restart the web server. - If you find that Apache serves you the text of the CGI + If you find that Apache serves you the text of the CGI script instead of executing it, you may need to either uncomment (if already present) or add a directive like this. AddHandler cgi-script .cgi - The next possibility is that you might be served with a + The next possibility is that you might be served with a colourful Python backtrace claiming that it can't import a mercurial-related module. This is actually progress! The server is now capable of executing @@ -1038,7 +1035,7 @@ directions inside it to correctly set your PYTHONPATH environment variable. - Finally, you are certain to by + Finally, you are certain to by served with another colourful Python backtrace: this one will complain that it can't find /path/to/repository. Edit @@ -1048,7 +1045,7 @@ with the complete path to the repository you want to serve up. - At this point, when you try to reload the page, you + At this point, when you try to reload the page, you should be presented with a nice HTML view of your repository's history. Whew! @@ -1056,7 +1053,7 @@ Configuring lighttpd - To be exhaustive in my experiments, I tried configuring + To be exhaustive in my experiments, I tried configuring the increasingly popular lighttpd web server to serve the same repository as I described with Apache above. I had already overcome all of the problems I @@ -1066,7 +1063,7 @@ role="special">hgweb.cgi script was properly edited. - Once I had Apache running, getting + Once I had Apache running, getting lighttpd to serve the repository was a snap (in other words, even if you're trying to use lighttpd, you should read the Apache @@ -1078,7 +1075,7 @@ end of the config file, to configure these modules. userdir.path = "public_html" cgi.assign = (".cgi" => "" ) - With this done, lighttpd ran + With this done, lighttpd ran immediately for me. If I had configured lighttpd before Apache, I'd almost certainly have run into many of the same system-level @@ -1093,7 +1090,7 @@ Sharing multiple repositories with one CGI script - The hgweb.cgi script + The hgweb.cgi script only lets you publish a single repository, which is an annoying restriction. If you want to publish more than one without wracking yourself with multiple copies of the same @@ -1101,7 +1098,7 @@ the hgwebdir.cgi script. - The procedure to configure The procedure to configure hgwebdir.cgi is only a little more involved than for hgweb.cgi. First, you must obtain @@ -1109,21 +1106,23 @@ download a copy from the master Mercurial repository at http://www.selenic.com/repo/hg/raw-file/tip/hgwebdir.cgi. - You'll need to copy this script into your You'll need to copy this script into your public_html directory, and ensure that it's executable. + cp .../hgwebdir.cgi ~/public_html chmod 755 ~/public_html ~/public_html/hgwebdir.cgi - With basic configuration out of the way, try to visit - With basic configuration out of the way, try to + visit http://myhostname/ myuser/hgwebdir.cgi in your browser. It should display an empty list of repositories. If you get a blank window or error message, try walking through the list of - potential problems in section . + potential problems in . - The hgwebdir.cgi + The hgwebdir.cgi script relies on an external configuration file. By default, it searches for a file named hgweb.config in the same directory @@ -1133,7 +1132,7 @@ ConfigParser web:configparser module. - The easiest way to configure The easiest way to configure hgwebdir.cgi is with a section named collections. This will automatically publish every repository under the @@ -1141,7 +1140,7 @@ this: [collections] /my/root = /my/root - Mercurial interprets this by looking at the directory name + Mercurial interprets this by looking at the directory name on the right hand side of the = sign; finding repositories in that directory hierarchy; and using the text on the @@ -1150,7 +1149,7 @@ remaining component of a path after this stripping has occurred is called a virtual path. - Given the example above, if we have a repository whose + Given the example above, if we have a repository whose local path is /my/root/this/repo, the CGI script will strip the leading http://myhostname/ myuser/hgwebdir.cgi/this/repo. - If we replace If we replace /my/root on the left hand side of this example with /my, then root/this/repo instead of this/repo. - The hgwebdir.cgi + The hgwebdir.cgi script will recursively search each directory listed in the collections section of its configuration file, but it will not recurse into the repositories it finds. - The collections mechanism makes it easy + The collections mechanism makes it easy to publish many repositories in a fire and forget manner. You only need to set up the CGI script and configuration file one time. Afterwards, you can @@ -1193,7 +1192,7 @@ Explicitly specifying which repositories to publish - In addition to the collections + In addition to the collections mechanism, the hgwebdir.cgi script allows you to publish a specific list of repositories. To do so, @@ -1202,20 +1201,20 @@ [paths] repo1 = /my/path/to/some/repo repo2 = /some/path/to/another - In this case, the virtual path (the component that will + In this case, the virtual path (the component that will appear in a URL) is on the left hand side of each definition, while the path to the repository is on the right. Notice that there does not need to be any relationship between the virtual path you choose and the location of a repository in your filesystem. - If you wish, you can use both the + If you wish, you can use both the collections and paths mechanisms simultaneously in a single configuration file. - If multiple repositories have the same virtual path, + If multiple repositories have the same virtual path, hgwebdir.cgi will not report an error. Instead, it will behave unpredictably. @@ -1226,12 +1225,12 @@ Downloading source archives - Mercurial's web interface lets users download an archive + Mercurial's web interface lets users download an archive of any revision. This archive will contain a snapshot of the working directory as of that revision, but it will not contain a copy of the repository data. - By default, this feature is not enabled. To enable it, + By default, this feature is not enabled. To enable it, you'll need to add an allow_archive item to the web section of your Web configuration options - Mercurial's web interfaces (the hg + Mercurial's web interfaces (the hg serve command, and the hgweb.cgi and hgwebdir.cgi scripts) have a @@ -1249,7 +1248,7 @@ belong in a section named web. - allow_archive: Determines which (if any) archive download mechanisms Mercurial supports. If you enable this feature, users of the web @@ -1258,30 +1257,30 @@ archive feature, this item must take the form of a sequence of words drawn from the list below. - bz2: A + bz2: A tar archive, compressed using bzip2 compression. This has the best compression ratio, but uses the most CPU time on the server. - gz: A + gz: A tar archive, compressed using gzip compression. - zip: A + zip: A zip archive, compressed using LZW compression. This format has the worst compression ratio, but is widely used in the Windows world. - If you provide an empty list, or don't have an + If you provide an empty list, or don't have an allow_archive entry at all, this feature will be disabled. Here is an example of how to enable all three supported formats. [web] allow_archive = bz2 gz zip - allowpull: + allowpull: Boolean. Determines whether the web interface allows remote users to hg pull and hg clone this @@ -1290,7 +1289,7 @@ human-oriented portion of the web interface is available. - contact: + contact: String. A free-form (but preferably brief) string identifying the person or group in charge of the repository. This often contains the name and email @@ -1301,38 +1300,39 @@ role="special">~/.hgrc if every repository has a single maintainer. - maxchanges: + maxchanges: Integer. The default maximum number of changesets to display in a single page of output. - maxfiles: + maxfiles: Integer. The default maximum number of modified files to display in a single page of output. - stripes: + stripes: Integer. If the web interface displays alternating stripes to make it easier to visually align rows when you are looking at a table, this number controls the number of rows in each stripe. - style: - Controls the template Mercurial uses to display the web - interface. Mercurial ships with two web templates, named + style: Controls the template + Mercurial uses to display the web interface. Mercurial + ships with two web templates, named default and gitweb (the latter is much more visually attractive). You can - also specify a custom template of your own; see chapter - for details. - Here, you can see how to enable the - gitweb style. + also specify a custom template of your own; see + for details. Here, you can + see how to enable the gitweb + style. [web] style = gitweb - templates: + templates: Path. The directory in which to search for template files. By default, Mercurial searches in the directory in which it was installed. - If you are using If you are using hgwebdir.cgi, you can place a few configuration items in a web section of the Options specific to an individual repository - A few web configuration + A few web configuration items ought to be placed in a repository's local .hg/hgrc, rather than a user's or global ~/.hgrc. - description: String. A free-form (but preferably brief) string that describes the contents or purpose of the repository. - name: + name: String. The name to use for the repository in the web interface. This overrides the default name, which is the last component of the repository's path. @@ -1366,13 +1366,13 @@ Options specific to the <command role="hg-cmd">hg serve</command> command - Some of the items in the Some of the items in the web section of a ~/.hgrc file are only for use with the hg serve command. - accesslog: + accesslog: Path. The name of a file into which to write an access log. By default, the hg serve command writes this information to @@ -1380,22 +1380,22 @@ in the standard combined file format used by almost all web servers. - address: + address: String. The local address on which the server should listen for incoming connections. By default, the server listens on all addresses. - errorlog: + errorlog: Path. The name of a file into which to write an error log. By default, the hg serve command writes this information to standard error, not to a file. - ipv6: + ipv6: Boolean. Whether to use the IPv6 protocol. By default, IPv6 is not used. - port: + port: Integer. The TCP port number on which the server should listen. The default port number used is 8000. @@ -1406,14 +1406,14 @@ role="special">~/.hgrc file to add web items to - It is important to remember that a web server like + It is important to remember that a web server like Apache or lighttpd will run under a user ID that is different to yours. CGI scripts run by your server, such as hgweb.cgi, will usually also run under that user ID. - If you add web items to + If you add web items to your own personal ~/.hgrc file, CGI scripts won't read that ~/.hgrc file. Those settings will thus only affect the behaviour of the - + File names and pattern matching @@ -274,7 +274,7 @@ XXX. - + Case sensitivity If you're working in a mixed development environment that diff -r 6b1577ef5135 -r 1c13ed2130a7 en/ch07-branch.xml --- a/en/ch07-branch.xml Fri Mar 20 17:17:55 2009 +0800 +++ b/en/ch07-branch.xml Mon Mar 30 16:23:33 2009 +0800 @@ -1,6 +1,6 @@ - + Managing releases and branchy development diff -r 6b1577ef5135 -r 1c13ed2130a7 en/ch08-undo.xml --- a/en/ch08-undo.xml Fri Mar 20 17:17:55 2009 +0800 +++ b/en/ch08-undo.xml Mon Mar 30 16:23:33 2009 +0800 @@ -1,10 +1,10 @@ - + Finding and fixing mistakes - To err might be human, but to really handle the consequences + To err might be human, but to really handle the consequences well takes a top-notch revision control system. In this chapter, we'll discuss some of the techniques you can use when you find that a problem has crept into your project. Mercurial has some @@ -17,7 +17,7 @@ The accidental commit - I have the occasional but persistent problem of typing + I have the occasional but persistent problem of typing rather more quickly than I can think, which sometimes results in me committing a changeset that is either incomplete or plain wrong. In my case, the usual kind of incomplete @@ -27,33 +27,33 @@ less annoying. - + Rolling back a transaction - In section , I mentioned - that Mercurial treats each modification of a repository as a - transaction. Every time you commit a - changeset or pull changes from another repository, Mercurial - remembers what you did. You can undo, or roll - back, exactly one of these actions using the - hg rollback command. (See - section for an - important caveat about the use of this command.) + In , I + mentioned that Mercurial treats each modification of a + repository as a transaction. Every time + you commit a changeset or pull changes from another + repository, Mercurial remembers what you did. You can undo, + or roll back, exactly one of these + actions using the hg rollback + command. (See + for an important caveat about the use of this command.) - Here's a mistake that I often find myself making: + Here's a mistake that I often find myself making: committing a change in which I've created a new file, but forgotten to hg add it. &interaction.rollback.commit; - Looking at the output of hg + Looking at the output of hg status after the commit immediately confirms the error. &interaction.rollback.status; - The commit captured the changes to the file + The commit captured the changes to the file a, but not the new file b. If I were to push this changeset to a repository that I shared with a colleague, the chances are @@ -62,14 +62,14 @@ repository when they pulled my changes. I would thus become the object of some indignation. - However, luck is with me&emdash;I've caught my error + However, luck is with me&emdash;I've caught my error before I pushed the changeset. I use the hg rollback command, and Mercurial makes that last changeset vanish. &interaction.rollback.rollback; - Notice that the changeset is no longer present in the + Notice that the changeset is no longer present in the repository's history, and the working directory once again thinks that the file a is modified. The commit and rollback have left the working directory exactly as @@ -84,14 +84,14 @@ The erroneous pull - It's common practice with Mercurial to maintain separate + It's common practice with Mercurial to maintain separate development branches of a project in different repositories. Your development team might have one shared repository for your project's 0.9 release, and another, containing different changes, for the 1.0 release. - Given this, you can imagine that the consequences could be + Given this, you can imagine that the consequences could be messy if you had a local 0.9 repository, and accidentally pulled changes from the shared 1.0 repository into it. At worst, you could be paying @@ -103,7 +103,7 @@ see it pull a suspiciously large number of changes into the repository. - The hg rollback command + The hg rollback command will work nicely to expunge all of the changesets that you just pulled. Mercurial groups all changes from one hg pull into a single transaction, @@ -111,10 +111,10 @@ need to undo this mistake. - + Rolling back is useless once you've pushed - The value of the hg + The value of the hg rollback command drops to zero once you've pushed your changes to another repository. Rolling back a change makes it disappear entirely, but only in @@ -123,7 +123,7 @@ eliminates history, there's no way for the disappearance of a change to propagate between repositories. - If you've pushed a change to another + If you've pushed a change to another repository&emdash;particularly if it's a shared repository&emdash;it has essentially escaped into the wild, and you'll have to recover from your mistake @@ -132,7 +132,7 @@ you pushed to, is that the changeset will reappear in your repository. - (If you absolutely know for sure that the change you want + (If you absolutely know for sure that the change you want to roll back is the most recent change in the repository that you pushed to, and you know that nobody else could have pulled it from that repository, you can roll @@ -146,7 +146,7 @@ You can only roll back once - Mercurial stores exactly one transaction in its + Mercurial stores exactly one transaction in its transaction log; that transaction is the most recent one that occurred in the repository. This means that you can only roll back one transaction. If you expect to be able to roll back @@ -155,7 +155,7 @@ &interaction.rollback.twice; - Once you've rolled back one transaction in a repository, + Once you've rolled back one transaction in a repository, you can't roll back again in that repository until you perform another commit or pull. @@ -164,7 +164,7 @@ Reverting the mistaken change - If you make a modification to a file, and decide that you + If you make a modification to a file, and decide that you really didn't want to change the file at all, and you haven't yet committed your changes, the hg revert command is the one you'll need. It looks at @@ -173,57 +173,57 @@ changeset. (That's a long-winded way of saying that, in the normal case, it undoes your modifications.) - Let's illustrate how the hg + Let's illustrate how the hg revert command works with yet another small example. We'll begin by modifying a file that Mercurial is already tracking. &interaction.daily.revert.modify; - If we don't + If we don't want that change, we can simply hg revert the file. &interaction.daily.revert.unmodify; - The hg revert command + The hg revert command provides us with an extra degree of safety by saving our modified file with a .orig extension. &interaction.daily.revert.status; - Here is a summary of the cases that the Here is a summary of the cases that the hg revert command can deal with. We will describe each of these in more detail in the section that follows. - If you modify a file, it will restore the file + If you modify a file, it will restore the file to its unmodified state. - If you hg add a + If you hg add a file, it will undo the added state of the file, but leave the file itself untouched. - If you delete a file without telling Mercurial, + If you delete a file without telling Mercurial, it will restore the file to its unmodified contents. - If you use the hg + If you use the hg remove command to remove a file, it will undo the removed state of the file, and restore the file to its unmodified contents. - + File management errors - The hg revert command is + The hg revert command is useful for more than just modified files. It lets you reverse the results of all of Mercurial's file management commands&emdash;hg add, hg remove, and so on. - If you hg add a file, + If you hg add a file, then decide that in fact you don't want Mercurial to track it, use hg revert to undo the add. Don't worry; Mercurial will not modify the file in any @@ -231,7 +231,7 @@ &interaction.daily.revert.add; - Similarly, if you ask Mercurial to Similarly, if you ask Mercurial to hg remove a file, you can use hg revert to restore it to the contents it had as of the parent of the working directory. @@ -242,7 +242,7 @@ &interaction.daily.revert.missing; - If you revert a hg copy, + If you revert a hg copy, the copied-to file remains in your working directory afterwards, untracked. Since a copy doesn't affect the copied-from file in any way, Mercurial doesn't do anything @@ -253,7 +253,7 @@ A slightly special case: reverting a rename - If you hg rename a + If you hg rename a file, there is one small detail that you should remember. When you hg revert a rename, it's not enough to provide the name of the @@ -261,7 +261,7 @@ &interaction.daily.revert.rename; - As you can see from the output of As you can see from the output of hg status, the renamed-to file is no longer identified as added, but the renamed-from file is still removed! @@ -270,22 +270,22 @@ &interaction.daily.revert.rename-orig; - So remember, to revert a hg + So remember, to revert a hg rename, you must provide both the source and destination names. - % TODO: the output doesn't look like it will be + % TODO: the output doesn't look like it will be removed! - (By the way, if you rename a file, then modify the + (By the way, if you rename a file, then modify the renamed-to file, then revert both components of the rename, when Mercurial restores the file that was removed as part of the rename, it will be unmodified. If you need the modifications in the renamed-to file to show up in the renamed-from file, don't forget to copy them over.) - These fiddly aspects of reverting a rename arguably + These fiddly aspects of reverting a rename arguably constitute a small bug in Mercurial. @@ -294,24 +294,24 @@ Dealing with committed changes - Consider a case where you have committed a change $a$, and + Consider a case where you have committed a change $a$, and another change $b$ on top of it; you then realise that change $a$ was incorrect. Mercurial lets you back out an entire changeset automatically, and building blocks that let you reverse part of a changeset by hand. - Before you read this section, here's something to keep in - mind: the hg backout command - undoes changes by adding history, not by - modifying or erasing it. It's the right tool to use if you're - fixing bugs, but not if you're trying to undo some change that - has catastrophic consequences. To deal with those, see section - . + Before you read this section, here's something to + keep in mind: the hg backout + command undoes changes by adding history, + not by modifying or erasing it. It's the right tool to use if + you're fixing bugs, but not if you're trying to undo some change + that has catastrophic consequences. To deal with those, see + . Backing out a changeset - The hg backout command + The hg backout command lets you undo the effects of an entire changeset in an automated fashion. Because Mercurial's history is immutable, this command does @@ -320,14 +320,14 @@ reverses the effect of the to-be-undone changeset. - The operation of the hg + The operation of the hg backout command is a little intricate, so let's illustrate it with some examples. First, we'll create a repository with some simple changes. &interaction.backout.init; - The hg backout command + The hg backout command takes a single changeset ID as its argument; this is the changeset to back out. Normally, hg backout will drop you into a text editor to write @@ -340,12 +340,12 @@ Backing out the tip changeset - We're going to start by backing out the last changeset we + We're going to start by backing out the last changeset we committed. &interaction.backout.simple; - You can see that the second line from + You can see that the second line from myfile is no longer present. Taking a look at the output of hg log gives us an idea of what the hg @@ -353,51 +353,45 @@ &interaction.backout.simple.log; Notice that the new changeset that hg backout has created is a child of the changeset we backed out. It's easier to see - this in figure , - which presents a graphical - view of the change history. As you can see, the history is - nice and linear. + this in , which presents a + graphical view of the change history. As you can see, the + history is nice and linear. - - - - - XXX add text - Backing out - a change using the - hg backout - command - - +
+ Backing out a change using the <command + role="hg-cmd">hg backout</command> command + + + XXX add text + +
Backing out a non-tip change - If you want to back out a change other than the last one + If you want to back out a change other than the last one you committed, pass the option to the hg backout command. &interaction.backout.non-tip.clone; - This makes backing out any changeset a + This makes backing out any changeset a one-shot operation that's usually simple and fast. &interaction.backout.non-tip.backout; - If you take a look at the contents of + If you take a look at the contents of myfile after the backout finishes, you'll see that the first and third changes are present, but not the second. &interaction.backout.non-tip.cat; - As the graphical history in figure illustrates, Mercurial + As the graphical history in illustrates, Mercurial actually commits two changes in this kind of situation (the box-shaped nodes are the ones that Mercurial commits automatically). Before Mercurial begins the backout @@ -407,21 +401,19 @@ the previous parent of the working directory, and commits the result of the merge. - % TODO: to me it looks like mercurial doesn't commit the + % TODO: to me it looks like mercurial doesn't commit the second merge automatically! - - - - - XXX add text - Automated - backout of a non-tip change using the - hg backout command - - +
+ Automated backout of a non-tip change using the + <command role="hg-cmd">hg backout</command> command + + + XXX add text + +
- The result is that you end up back where you + The result is that you end up back where you were, only with some extra history that undoes the effect of the changeset you wanted to back out. @@ -429,7 +421,7 @@ Always use the <option role="hg-opt-backout">--merge</option> option - In fact, since the option will do the right thing whether or not the changeset you're backing out is the tip (i.e. it won't try to merge if @@ -442,7 +434,7 @@ Gaining more control of the backout process - While I've recommended that you always use the option when backing out a change, the hg backout command lets you decide how to merge a backout changeset. @@ -455,13 +447,13 @@ &interaction.backout.manual.clone; - As with our + As with our earlier example, We'll commit a third changeset, then back out its parent, and see what happens. &interaction.backout.manual.backout; - Our new changeset is again a descendant of the changeset + Our new changeset is again a descendant of the changeset we backout out; it's thus a new head, not a descendant of the changeset that was the tip. The hg backout command was quite @@ -469,38 +461,35 @@ &interaction.backout.manual.log; - Again, it's easier to see what has happened by looking at - a graph of the revision history, in figure . This makes it clear + Again, it's easier to see what has happened by looking at + a graph of the revision history, in . This makes it clear that when we use hg backout to back out a change other than the tip, Mercurial adds a new head to the repository (the change it committed is box-shaped). - - - - - XXX add text - Backing out a - change using the hg backout - command - - +
+ Backing out a change using the <command + role="hg-cmd">hg backout</command> command + + + XXX add text + +
- After the hg backout + After the hg backout command has completed, it leaves the new backout changeset as the parent of the working directory. &interaction.backout.manual.parents; - Now we have two isolated sets of changes. + Now we have two isolated sets of changes. &interaction.backout.manual.heads; - Let's think about what we expect to see as the contents of + Let's think about what we expect to see as the contents of myfile now. The first change should be present, because we've never backed it out. The second change should be missing, as that's the change we backed out. Since @@ -510,68 +499,65 @@ &interaction.backout.manual.cat; - To get the third change back into the file, we just do a + To get the third change back into the file, we just do a normal merge of our two heads. &interaction.backout.manual.merge; - Afterwards, the graphical history of our repository looks - like figure - . + Afterwards, the graphical history of our + repository looks like + . - - - - - XXX add text - Manually - merging a backout change - - +
+ Manually merging a backout change + + + XXX add text + +
Why <command role="hg-cmd">hg backout</command> works as it does - Here's a brief description of how the Here's a brief description of how the hg backout command works. - It ensures that the working directory is + It ensures that the working directory is clean, i.e. that the output of hg status would be empty. - It remembers the current parent of the working + It remembers the current parent of the working directory. Let's call this changeset orig - It does the equivalent of a It does the equivalent of a hg update to sync the working directory to the changeset you want to back out. Let's call this changeset backout - It finds the parent of that changeset. Let's + It finds the parent of that changeset. Let's call that changeset parent. - For each file that the + For each file that the backout changeset affected, it does the equivalent of a hg revert -r parent on that file, to restore it to the contents it had before that changeset was committed. - It commits the result as a new changeset. + It commits the result as a new changeset. This changeset has backout as its parent. - If you specify - An alternative way to implement the An alternative way to implement the hg backout command would be to hg export the to-be-backed-out changeset as a diff, then use the
- + Changes that should never have been - Most of the time, the hg + Most of the time, the hg backout command is exactly what you need if you want to undo the effects of a change. It leaves a permanent record of exactly what you did, both when committing the original changeset and when you cleaned up after it. - On rare occasions, though, you may find that you've + On rare occasions, though, you may find that you've committed a change that really should not be present in the repository at all. For example, it would be very unusual, and usually considered a mistake, to commit a software project's @@ -622,21 +608,21 @@ so they increase the size of the repository and the amount of time it takes to clone or pull changes. - Before I discuss the options that you have if you commit a + Before I discuss the options that you have if you commit a brown paper bag change (the kind that's so bad that you want to pull a brown paper bag over your head), let me first discuss some approaches that probably won't work. - Since Mercurial treats history as accumulative&emdash;every - change builds on top of all changes that preceded it&emdash;you - generally can't just make disastrous changes disappear. The one - exception is when you've just committed a change, and it hasn't - been pushed or pulled into another repository. That's when you - can safely use the hg rollback - command, as I detailed in section . + Since Mercurial treats history as + accumulative&emdash;every change builds on top of all changes + that preceded it&emdash;you generally can't just make disastrous + changes disappear. The one exception is when you've just + committed a change, and it hasn't been pushed or pulled into + another repository. That's when you can safely use the hg rollback command, as I detailed in + . - After you've pushed a bad change to another repository, you + After you've pushed a bad change to another repository, you could still use hg rollback to make your local copy of the change disappear, but it won't have the consequences you want. The @@ -644,7 +630,7 @@ will reappear in your local repository the next time you pull. - If a situation like this arises, and you know which + If a situation like this arises, and you know which repositories your bad change has propagated into, you can try to get rid of the changeefrom every one of those repositories. This is, @@ -652,13 +638,13 @@ single repository while you're expunging, the change is still in the wild, and could propagate further. - If you've committed one or more changes + If you've committed one or more changes after the change that you'd like to see disappear, your options are further reduced. Mercurial doesn't provide a way to punch a hole in history, leaving changesets intact. - XXX This needs filling out. The + XXX This needs filling out. The hg-replay script in the examples directory works, but doesn't handle merge changesets. Kind of an important omission. @@ -667,15 +653,15 @@ Protect yourself from <quote>escaped</quote> changes - If you've committed some changes to your local repository + If you've committed some changes to your local repository and they've been pushed or pulled somewhere else, this isn't necessarily a disaster. You can protect yourself ahead of time against some classes of bad changeset. This is particularly easy if your team usually pulls changes from a central repository. - By configuring some hooks on that repository to validate - incoming changesets (see chapter ), + By configuring some hooks on that repository to validate + incoming changesets (see chapter ), you can automatically prevent some kinds of bad changeset from being pushed to the central repository at all. With such a @@ -684,23 +670,23 @@ propagate into the central repository. Better yet, this happens without any need for explicit intervention. - For instance, an incoming change hook that verifies that a + For instance, an incoming change hook that verifies that a changeset will actually compile can prevent people from inadvertantly breaking the build.
- + Finding the source of a bug - While it's all very well to be able to back out a changeset + While it's all very well to be able to back out a changeset that introduced a bug, this requires that you know which changeset to back out. Mercurial provides an invaluable command, called hg bisect, that helps you to automate this process and accomplish it very efficiently. - The idea behind the hg + The idea behind the hg bisect command is that a changeset has introduced some change of behaviour that you can identify with a simple binary test. You don't know which piece of code introduced the @@ -709,41 +695,41 @@ test to direct its search for the changeset that introduced the code that caused the bug. - Here are a few scenarios to help you understand how you + Here are a few scenarios to help you understand how you might apply this command. - The most recent version of your software has a + The most recent version of your software has a bug that you remember wasn't present a few weeks ago, but you don't know when it was introduced. Here, your binary test checks for the presence of that bug. - You fixed a bug in a rush, and now it's time to + You fixed a bug in a rush, and now it's time to close the entry in your team's bug database. The bug database requires a changeset ID when you close an entry, but you don't remember which changeset you fixed the bug in. Once again, your binary test checks for the presence of the bug. - Your software works correctly, but runs 15% + Your software works correctly, but runs 15% slower than the last time you measured it. You want to know which changeset introduced the performance regression. In this case, your binary test measures the performance of your software, to see whether it's fast or slow. - The sizes of the components of your project that + The sizes of the components of your project that you ship exploded recently, and you suspect that something changed in the way you build your project. - From these examples, it should be clear that the From these examples, it should be clear that the hg bisect command is not useful only for finding the sources of bugs. You can use it to find any emergent property of a repository (anything that you can't find from a simple text search of the files in the tree) for which you can write a binary test. - We'll introduce a little bit of terminology here, just to + We'll introduce a little bit of terminology here, just to make it clear which parts of the search process are your responsibility, and which are Mercurial's. A test is something that @@ -756,7 +742,7 @@ the hg bisect command. - One simple way to automate the searching process would be + One simple way to automate the searching process would be simply to probe every changeset. However, this scales poorly. If it took ten minutes to test a single changeset, and you had 10,000 changesets in your repository, the exhaustive approach @@ -766,7 +752,7 @@ your search to those, you'd still be looking at over 40 hours to find the changeset that introduced your bug. - What the hg bisect command + What the hg bisect command does is use its knowledge of the shape of your project's revision history to perform a search in time proportional to the logarithm of the number @@ -777,7 +763,7 @@ Limit your search to the last hundred changesets, and it will take only about an hour (roughly seven tests). - The hg bisect command is + The hg bisect command is aware of the branchy nature of a Mercurial project's revision history, so it has no problems dealing with branches, merges, or multiple heads in a repository. It can @@ -788,24 +774,24 @@ Using the <command role="hg-cmd">hg bisect</command> command - Here's an example of hg + Here's an example of hg bisect in action. - In versions 0.9.5 and earlier of Mercurial, In versions 0.9.5 and earlier of Mercurial, hg bisect was not a core command: it was distributed with Mercurial as an extension. This section describes the built-in command, not the old extension. - Now let's create a repository, so that we can try out the + Now let's create a repository, so that we can try out the hg bisect command in isolation. &interaction.bisect.init; - We'll simulate a project that has a bug in it in a + We'll simulate a project that has a bug in it in a simple-minded way: create trivial changes in a loop, and nominate one specific change that will have the bug. This loop creates 35 changesets, each @@ -815,44 +801,44 @@ &interaction.bisect.commits; - The next thing that we'd like to do is figure out how to + The next thing that we'd like to do is figure out how to use the hg bisect command. We can use Mercurial's normal built-in help mechanism for this. &interaction.bisect.help; - The hg bisect command + The hg bisect command works in steps. Each step proceeds as follows. - You run your binary test. + You run your binary test. - If the test succeeded, you tell If the test succeeded, you tell hg bisect by running the hg bisect good command. - If it failed, run the If it failed, run the hg bisect bad command. - The command uses your information to decide + The command uses your information to decide which changeset to test next. - It updates the working directory to that + It updates the working directory to that changeset, and the process begins again. - The process ends when hg + The process ends when hg bisect identifies a unique changeset that marks the point where your test transitioned from succeeding to failing. - To start the search, we must run the To start the search, we must run the hg bisect --reset command. &interaction.bisect.search.init; - In our case, the binary test we use is simple: we check to + In our case, the binary test we use is simple: we check to see if any file in the repository contains the string i have a gub. If it does, this changeset contains the change that caused the bug. By convention, a @@ -860,14 +846,14 @@ bad, while one that doesn't is good. - Most of the time, the revision to which the working + Most of the time, the revision to which the working directory is synced (usually the tip) already exhibits the problem introduced by the buggy change, so we'll mark it as bad. &interaction.bisect.search.bad-init; - Our next task is to nominate a changeset that we know + Our next task is to nominate a changeset that we know doesn't have the bug; the hg bisect command will bracket its search between the first pair of @@ -877,38 +863,38 @@ &interaction.bisect.search.good-init; - Notice that this command printed some output. + Notice that this command printed some output. - It told us how many changesets it must + It told us how many changesets it must consider before it can identify the one that introduced the bug, and how many tests that will require. - It updated the working directory to the next + It updated the working directory to the next changeset to test, and told us which changeset it's testing. - We now run our test in the working directory. We use the + We now run our test in the working directory. We use the grep command to see if our bad file is present in the working directory. If it is, this revision is bad; if not, this revision is good. &interaction.bisect.search.step1; - This test looks like a perfect candidate for automation, + This test looks like a perfect candidate for automation, so let's turn it into a shell function. &interaction.bisect.search.mytest; - We can now run an entire test step with a single command, + We can now run an entire test step with a single command, mytest. &interaction.bisect.search.step2; - A few more invocations of our canned test step command, + A few more invocations of our canned test step command, and we're done. &interaction.bisect.search.rest; - Even though we had 40 changesets to search through, the + Even though we had 40 changesets to search through, the hg bisect command let us find the changeset that introduced our bug with only five tests. Because the number of tests that the Cleaning up after your search - When you're finished using the hg + When you're finished using the hg bisect command in a repository, you can use the hg bisect reset command to drop the information it was using to drive your search. The @@ -941,7 +927,7 @@ Give consistent input - The hg bisect command + The hg bisect command requires that you correctly report the result of every test you perform. If you tell it that a test failed when it really succeeded, it might be able to detect the @@ -955,7 +941,7 @@ Automate as much as possible - When I started using the hg + When I started using the hg bisect command, I tried a few times to run my tests by hand, on the command line. This is an approach that I, at least, am not suited to. After a few tries, I found @@ -963,7 +949,7 @@ my searches several times before finally getting correct results. - My initial problems with driving the My initial problems with driving the hg bisect command by hand occurred even with simple searches on small repositories; if the problem you're looking for is more subtle, or the number of @@ -972,14 +958,14 @@ the search is much higher. Once I started automating my tests, I had much better results. - The key to automated testing is twofold: + The key to automated testing is twofold: - always test for the same symptom, and + always test for the same symptom, and - always feed consistent input to the always feed consistent input to the hg bisect command. - In my tutorial example above, the grep + In my tutorial example above, the grep command tests for the symptom, and the if statement takes the result of this check and ensures that we always feed the same input to the hg @@ -991,21 +977,21 @@ Check your results - Because the output of a hg + Because the output of a hg bisect search is only as good as the input you give it, don't take the changeset it reports as the absolute truth. A simple way to cross-check its report is to manually run your test at each of the following changesets: - The changeset that it reports as the first bad + The changeset that it reports as the first bad revision. Your test should still report this as bad. - The parent of that changeset (either parent, + The parent of that changeset (either parent, if it's a merge). Your test should report this changeset as good. - A child of that changeset. Your test should + A child of that changeset. Your test should report this changeset as bad. @@ -1013,7 +999,7 @@ Beware interference between bugs - It's possible that your search for one bug could be + It's possible that your search for one bug could be disrupted by the presence of another. For example, let's say your software crashes at revision 100, and worked correctly at revision 50. Unknown to you, someone else introduced a @@ -1021,7 +1007,7 @@ revision 80. This could distort your results in one of several ways. - It is possible that this other bug completely + It is possible that this other bug completely masks yours, which is to say that it occurs before your bug has a chance to manifest itself. If you can't avoid that other bug (for example, it prevents your project @@ -1031,14 +1017,14 @@ you can mark a changeset as untested by running hg bisect --skip. - A different problem could arise if your test for a bug's + A different problem could arise if your test for a bug's presence is not specific enough. If you check for my program crashes, then both your crashing bug and an unrelated crashing bug that masks it will look like the same thing, and mislead hg bisect. - Another useful situation in which to use Another useful situation in which to use hg bisect --skip is if you can't test a revision because your project was in a broken and hence untestable state at that revision, perhaps because someone @@ -1049,7 +1035,7 @@ Bracket your search lazily - Choosing the first good and + Choosing the first good and bad changesets that will mark the end points of your search is often easy, but it bears a little discussion nevertheless. From the perspective of bad, and the older changeset is good. - If you're having trouble remembering when a suitable + If you're having trouble remembering when a suitable good change was, so that you can tell hg bisect, you could do worse than testing changesets at random. Just remember to eliminate @@ -1066,7 +1052,7 @@ where another problem masks the bug (as I discussed above). - Even if you end up early by thousands of + Even if you end up early by thousands of changesets or months of history, you will only add a handful of tests to the total number that hg bisect must perform, thanks to its logarithmic diff -r 6b1577ef5135 -r 1c13ed2130a7 en/ch09-hook.xml --- a/en/ch09-hook.xml Fri Mar 20 17:17:55 2009 +0800 +++ b/en/ch09-hook.xml Mon Mar 30 16:23:33 2009 +0800 @@ -1,15 +1,15 @@ - + Handling repository events with hooks - Mercurial offers a powerful mechanism to let you perform + Mercurial offers a powerful mechanism to let you perform automated actions in response to events that occur in a repository. In some cases, you can even control Mercurial's response to those events. - The name Mercurial uses for one of these actions is a + The name Mercurial uses for one of these actions is a hook. Hooks are called triggers in some revision control systems, but the two names refer to the same idea. @@ -17,49 +17,49 @@ An overview of hooks in Mercurial - Here is a brief list of the hooks that Mercurial supports. - We will revisit each of these hooks in more detail later, in - section . + Here is a brief list of the hooks that Mercurial + supports. We will revisit each of these hooks in more detail + later, in . - changegroup: This + changegroup: This is run after a group of changesets has been brought into the repository from elsewhere. - commit: This is + commit: This is run after a new changeset has been created in the local repository. - incoming: This is + incoming: This is run once for each new changeset that is brought into the repository from elsewhere. Notice the difference from changegroup, which is run once per group of changesets brought in. - outgoing: This is + outgoing: This is run after a group of changesets has been transmitted from this repository. - prechangegroup: + prechangegroup: This is run before starting to bring a group of changesets into the repository. - precommit: + precommit: Controlling. This is run before starting a commit. - preoutgoing: + preoutgoing: Controlling. This is run before starting to transmit a group of changesets from this repository. - pretag: + pretag: Controlling. This is run before creating a tag. - pretxnchangegroup: Controlling. This is run after a group of changesets has been brought into the local repository from another, but before the transaction @@ -67,27 +67,27 @@ repository. - pretxncommit: + pretxncommit: Controlling. This is run after a new changeset has been created in the local repository, but before the transaction completes that will make it permanent. - preupdate: + preupdate: Controlling. This is run before starting an update or merge of the working directory. - tag: This is run + tag: This is run after a tag is created. - update: This is + update: This is run after an update or merge of the working directory has finished. - Each of the hooks whose description begins with the word + Each of the hooks whose description begins with the word Controlling has the ability to determine whether an activity can proceed. If the hook succeeds, the activity may proceed; if it fails, the activity is either not permitted or @@ -101,7 +101,7 @@ Hooks are run with your privileges - When you run a Mercurial command in a repository, and the + When you run a Mercurial command in a repository, and the command causes a hook to run, that hook runs on your system, under your user account, with @@ -112,14 +112,14 @@ it does. - In some cases, you may be exposed to hooks that you did + In some cases, you may be exposed to hooks that you did not install yourself. If you work with Mercurial on an unfamiliar system, Mercurial will run hooks defined in that system's global ~/.hgrc file. - If you are working with a repository owned by another + If you are working with a repository owned by another user, Mercurial can run hooks defined in that user's repository, but it will still run them as you. For example, if you hg pull @@ -131,7 +131,7 @@ - This only applies if you are pulling from a repository + This only applies if you are pulling from a repository on a local or network filesystem. If you're pulling over http or ssh, any outgoing hook will run under whatever account is executing the server @@ -139,7 +139,7 @@ - XXX To see what hooks are defined in a repository, use the + XXX To see what hooks are defined in a repository, use the hg config hooks command. If you are working in one repository, but talking to another that you do not own (e.g. using hg @@ -152,27 +152,27 @@ Hooks do not propagate - In Mercurial, hooks are not revision controlled, and do + In Mercurial, hooks are not revision controlled, and do not propagate when you clone, or pull from, a repository. The reason for this is simple: a hook is a completely arbitrary piece of executable code. It runs under your user identity, with your privilege level, on your machine. - It would be extremely reckless for any distributed + It would be extremely reckless for any distributed revision control system to implement revision-controlled hooks, as this would offer an easily exploitable way to subvert the accounts of users of the revision control system. - Since Mercurial does not propagate hooks, if you are + Since Mercurial does not propagate hooks, if you are collaborating with other people on a common project, you should not assume that they are using the same Mercurial hooks as you are, or that theirs are correctly configured. You should document the hooks you expect people to use. - In a corporate intranet, this is somewhat easier to + In a corporate intranet, this is somewhat easier to control, as you can for example provide a standard installation of Mercurial on an NFS filesystem, and use a site-wide ~/.hgrc file to define hooks that all users will @@ -183,12 +183,12 @@ Hooks can be overridden - Mercurial allows you to override a hook definition by + Mercurial allows you to override a hook definition by redefining the hook. You can disable it by setting its value to the empty string, or change its behaviour as you wish. - If you deploy a system- or site-wide If you deploy a system- or site-wide ~/.hgrc file that defines some hooks, you should thus understand that your users can disable or override those hooks. @@ -198,7 +198,7 @@ Ensuring that critical hooks are run - Sometimes you may want to enforce a policy that you do not + Sometimes you may want to enforce a policy that you do not want others to be able to work around. For example, you may have a requirement that every changeset must pass a rigorous set of tests. Defining this requirement via a hook in a @@ -207,13 +207,13 @@ can subvert it at will by overriding the hook. - Instead, you can set up your policies for use of Mercurial + Instead, you can set up your policies for use of Mercurial so that people are expected to propagate changes through a well-known canonical server that you have locked down and configured appropriately. - One way to do this is via a combination of social + One way to do this is via a combination of social engineering and technology. Set up a restricted-access account; users can push changes over the network to repositories managed by this account, but they cannot log into @@ -222,7 +222,7 @@ they want. - When someone pushes a changeset to the server that + When someone pushes a changeset to the server that everyone pulls from, the server will test the changeset before it accepts it as permanent, and reject it if it fails to pass the test suite. If people only pull changes from this @@ -236,19 +236,19 @@ Care with <literal>pretxn</literal> hooks in a shared-access repository - If you want to use hooks to do some automated work in a + If you want to use hooks to do some automated work in a repository that a number of people have shared access to, you need to be careful in how you do this. - Mercurial only locks a repository when it is writing to the + Mercurial only locks a repository when it is writing to the repository, and only the parts of Mercurial that write to the repository pay attention to locks. Write locks are necessary to prevent multiple simultaneous writers from scribbling on each other's work, corrupting the repository. - Because Mercurial is careful with the order in which it + Because Mercurial is careful with the order in which it reads and writes data, it does not need to acquire a lock when it wants to read data from the repository. The parts of Mercurial that read from the repository never pay attention to @@ -256,14 +256,14 @@ performance and concurrency. - With great performance comes a trade-off, though, one which + With great performance comes a trade-off, though, one which has the potential to cause you trouble unless you're aware of it. To describe this requires a little detail about how Mercurial adds changesets to a repository and reads those changes. - When Mercurial writes metadata, it + When Mercurial writes metadata, it writes it straight into the destination file. It writes file data first, then manifest data (which contains pointers to the new file data), then changelog data (which contains pointers to @@ -274,13 +274,13 @@ before the transaction began. - When Mercurial reads metadata, it reads + When Mercurial reads metadata, it reads the changelog first, then everything else. Since a reader will only access parts of the manifest or file metadata that it can see in the changelog, it can never see partially written data. - Some controlling hooks (Some controlling hooks (pretxncommit and pretxnchangegroup) run when a transaction is almost complete. All of the metadata has been @@ -288,7 +288,7 @@ cause the newly-written data to disappear. - If one of these hooks runs for long, it opens a window of + If one of these hooks runs for long, it opens a window of time during which a reader can see the metadata for changesets that are not yet permanent, and should not be thought of as really there. The longer the hook runs, the @@ -298,7 +298,7 @@ The problem illustrated - In principle, a good use for the In principle, a good use for the pretxnchangegroup hook would be to automatically build and test incoming changes before they are accepted into a central repository. This could let you @@ -309,7 +309,7 @@ potentially breaking their build. - The safest technological answer to this challenge is to + The safest technological answer to this challenge is to set up such a gatekeeper repository as unidirectional. Let it take changes pushed in from the outside, but do not allow anyone to pull @@ -321,7 +321,7 @@ can pull from. - In practice, putting a centralised bottleneck like this in + In practice, putting a centralised bottleneck like this in place is not often a good idea, and transaction visibility has nothing to do with the problem. As the size of a project&emdash;and the time it takes to build and @@ -332,7 +332,7 @@ involved. - An approach that scales better is to get people to build + An approach that scales better is to get people to build and test before they push, then run automated builds and tests centrally after a push, to be sure all is well. The advantage of this approach is that it does not @@ -342,21 +342,21 @@ - + A short tutorial on using hooks - It is easy to write a Mercurial hook. Let's start with a + It is easy to write a Mercurial hook. Let's start with a hook that runs when you finish a hg commit, and simply prints the hash of the changeset you just created. The hook is called commit. - All hooks follow the pattern in this example. + All hooks follow the pattern in this example. &interaction.hook.simple.init; - You add an entry to the You add an entry to the hooks section of your ~/.hgrc. On the left is the name of the event to trigger on; on the right is the action to take. As @@ -368,12 +368,12 @@ Performing multiple actions per event - Quite often, you will want to define more than one hook + Quite often, you will want to define more than one hook for a particular kind of event, as shown below. &interaction.hook.simple.ext; - Mercurial lets you do this by adding an + Mercurial lets you do this by adding an extension to the end of a hook's name. You extend a hook's name by giving the name of the hook, followed by a full stop (the @@ -384,7 +384,7 @@ commit event occurs. - To give a well-defined order of execution when there are + To give a well-defined order of execution when there are multiple hooks defined for an event, Mercurial sorts hooks by extension, and executes the hook commands in this sorted order. In the above example, it will execute @@ -393,33 +393,33 @@ before both. - It is a good idea to use a somewhat descriptive extension - when you define a new hook. This will help you to remember - what the hook was for. If the hook fails, you'll get an error - message that contains the hook name and extension, so using a - descriptive extension could give you an immediate hint as to - why the hook failed (see section for an example). + It is a good idea to use a somewhat descriptive + extension when you define a new hook. This will help you to + remember what the hook was for. If the hook fails, you'll get + an error message that contains the hook name and extension, so + using a descriptive extension could give you an immediate hint + as to why the hook failed (see for an example). - + Controlling whether an activity can proceed - In our earlier examples, we used the In our earlier examples, we used the commit hook, which is run after a commit has completed. This is one of several Mercurial hooks that run after an activity finishes. Such hooks have no way of influencing the activity itself. - Mercurial defines a number of events that occur before an + Mercurial defines a number of events that occur before an activity starts; or after it starts, but before it finishes. Hooks that trigger on these events have the added ability to choose whether the activity can continue, or will abort. - The pretxncommit hook runs + The pretxncommit hook runs after a commit has all but completed. In other words, the metadata representing the changeset has been written out to disk, but the transaction has not yet been allowed to @@ -428,7 +428,7 @@ complete, or must be rolled back. - If the pretxncommit hook + If the pretxncommit hook exits with a status code of zero, the transaction is allowed to complete; the commit finishes; and the commit hook is run. If the The hook in the example above checks that a commit comment + The hook in the example above checks that a commit comment contains a bug ID. If it does, the commit can complete. If not, the commit is rolled back. @@ -450,7 +450,7 @@ Writing your own hooks - When you are writing a hook, you might find it useful to run + When you are writing a hook, you might find it useful to run Mercurial either with the option, or the verbose config item set to @@ -458,22 +458,22 @@ message before it calls each hook. - + Choosing how your hook should run - You can write a hook either as a normal + You can write a hook either as a normal program&emdash;typically a shell script&emdash;or as a Python function that is executed within the Mercurial process. - Writing a hook as an external program has the advantage + Writing a hook as an external program has the advantage that it requires no knowledge of Mercurial's internals. You can call normal Mercurial commands to get any added information you need. The trade-off is that external hooks are slower than in-process hooks. - An in-process Python hook has complete access to the + An in-process Python hook has complete access to the Mercurial API, and does not shell out to another process, so it is inherently faster than an external hook. It is also easier to obtain much of the information @@ -481,7 +481,7 @@ running Mercurial commands. - If you are comfortable with Python, or require high + If you are comfortable with Python, or require high performance, writing your hooks in Python may be a good choice. However, when you have a straightforward hook to write and you don't need to care about performance (probably @@ -489,16 +489,16 @@ - + Hook parameters - Mercurial calls each hook with a set of well-defined + Mercurial calls each hook with a set of well-defined parameters. In Python, a parameter is passed as a keyword argument to your hook function. For an external program, a parameter is passed as an environment variable. - Whether your hook is written in Python or as a shell + Whether your hook is written in Python or as a shell script, the hook-specific parameter names and values will be the same. A boolean parameter will be represented as a boolean value in Python, but as the number 1 (for @@ -514,7 +514,7 @@ Hook return values and activity control - A hook that executes successfully must exit with a status + A hook that executes successfully must exit with a status of zero if external, or return boolean false if in-process. Failure is indicated with a non-zero exit status from an external hook, or an in-process hook returning boolean @@ -522,7 +522,7 @@ exception, the hook is considered to have failed. - For a hook that controls whether an activity can proceed, + For a hook that controls whether an activity can proceed, zero/false means allow, while non-zero/true/exception means deny. @@ -531,23 +531,23 @@ Writing an external hook - When you define an external hook in your When you define an external hook in your ~/.hgrc and the hook is run, its value is passed to your shell, which interprets it. This means that you can use normal shell constructs in the body of the hook. - An executable hook is always run with its current + An executable hook is always run with its current directory set to a repository's root directory. - Each hook parameter is passed in as an environment + Each hook parameter is passed in as an environment variable; the name is upper-cased, and prefixed with the string HG_. - With the exception of hook parameters, Mercurial does not + With the exception of hook parameters, Mercurial does not set or modify any environment variables when running a hook. This is useful to remember if you are writing a site-wide hook that may be run by a number of different users with differing @@ -560,7 +560,7 @@ Telling Mercurial to use an in-process hook - The ~/.hgrc syntax + The ~/.hgrc syntax for defining an in-process hook is slightly different than for an executable hook. The value of the hook must start with the text python:, and continue @@ -568,19 +568,19 @@ the hook's value. - The module in which a hook lives is automatically imported + The module in which a hook lives is automatically imported when a hook is run. So long as you have the module name and PYTHONPATH right, it should just work. - The following ~/.hgrc + The following ~/.hgrc example snippet illustrates the syntax and meaning of the notions we just described. [hooks] commit.example = python:mymodule.submodule.myhook - When Mercurial runs the commit.example + When Mercurial runs the commit.example hook, it imports mymodule.submodule, looks for the callable object named myhook, and calls it. @@ -590,12 +590,12 @@ Writing an in-process hook - The simplest in-process hook does nothing, but illustrates + The simplest in-process hook does nothing, but illustrates the basic shape of the hook API: def myhook(ui, repo, **kwargs): pass - The first argument to a Python hook is always a The first argument to a Python hook is always a ui object. The second is a repository object; at the moment, it is always an instance of Writing meaningful commit messages - It's hard to imagine a useful commit message being very + It's hard to imagine a useful commit message being very short. The simple pretxncommit hook of the example below will prevent you from committing a changeset with a message that is less than ten bytes long. @@ -627,7 +627,7 @@ Checking for trailing whitespace - An interesting use of a commit-related hook is to help you + An interesting use of a commit-related hook is to help you to write cleaner code. A simple example of cleaner code is the dictum that a change should not add any new lines of text that contain trailing @@ -638,7 +638,7 @@ prefer to get rid of it. - You can use either the You can use either the precommit or pretxncommit hook to tell whether you have a trailing whitespace problem. If you use the - Should you choose the Should you choose the pretxncommit hook, the check won't occur until just before the transaction for the commit completes. This will allow you to check for problems only the @@ -667,7 +667,7 @@ &interaction.hook.ws.simple; - In this example, we introduce a simple In this example, we introduce a simple pretxncommit hook that checks for trailing whitespace. This hook is short, but not very helpful. It exits with an error status if a change adds a @@ -678,7 +678,7 @@ trailing whitespace cause problems. - The above version is much more complex, but also more + The above version is much more complex, but also more useful. It parses a unified diff to see if any lines add trailing whitespace, and prints the name of the file and the line number of each such occurrence. Even better, if the @@ -692,7 +692,7 @@ &interaction.hook.ws.better; - As a final aside, note in the example above the use of + As a final aside, note in the example above the use of perl's in-place editing feature to get rid of trailing whitespace from a file. This is concise and useful enough that I will reproduce it here. @@ -704,7 +704,7 @@ Bundled hooks - Mercurial ships with several bundled hooks. You can find + Mercurial ships with several bundled hooks. You can find them in the hgext directory of a Mercurial source tree. If you are using a Mercurial binary package, the hooks will be located in the @@ -716,7 +716,7 @@ <literal role="hg-ext">acl</literal>&emdash;access control for parts of a repository - The acl extension lets + The acl extension lets you control which remote users are allowed to push changesets to a networked server. You can protect any portion of a repository (including the entire repo), so that a specific @@ -724,7 +724,7 @@ portion. - This extension implements access control based on the + This extension implements access control based on the identity of the user performing a push, not on who committed the changesets they're pushing. It makes sense to use this hook only if you @@ -737,7 +737,7 @@ Configuring the <literal role="hook">acl</literal> hook - In order to manage incoming changesets, the In order to manage incoming changesets, the acl hook must be used as a pretxnchangegroup hook. This lets it see which files are modified by each incoming @@ -747,18 +747,18 @@ [hooks] pretxnchangegroup.acl = python:hgext.acl.hook - The acl extension is + The acl extension is configured using three sections. - The acl section has + The acl section has only one entry, sources, which lists the sources of incoming changesets that the hook should pay attention to. You don't normally need to configure this section. - serve: + serve: Control incoming changesets that are arriving from a remote repository over http or ssh. This is the default value of sources, and @@ -766,23 +766,23 @@ configuration item. - pull: + pull: Control incoming changesets that are arriving via a pull from a local repository. - push: + push: Control incoming changesets that are arriving via a push from a local repository. - bundle: + bundle: Control incoming changesets that are arriving from another repository via a bundle. - The acl.allow + The acl.allow section controls the users that are allowed to add changesets to the repository. If this section is not present, all users that are not explicitly denied are @@ -791,13 +791,13 @@ that all users are denied). - The acl.deny + The acl.deny section determines which users are denied from adding changesets to the repository. If this section is not present or is empty, no users are denied. - The syntaxes for the The syntaxes for the acl.allow and acl.deny sections are identical. On the left of each entry is a glob pattern that @@ -805,7 +805,7 @@ repository; on the right, a user name. - In the following example, the user + In the following example, the user docwriter can only push changes to the docs subtree of the repository, while intern can push changes @@ -821,7 +821,7 @@ Testing and troubleshooting - If you want to test the If you want to test the acl hook, run it with Mercurial's debugging output enabled. Since you'll probably be running it on a server where it's not convenient (or sometimes @@ -832,7 +832,7 @@ [ui] debug = true - With this enabled, the With this enabled, the acl hook will print enough information to let you figure out why it is allowing or forbidding pushes from specific users. @@ -845,14 +845,14 @@ role="hg-ext">bugzilla&emdash;integration with Bugzilla - The bugzilla extension + The bugzilla extension adds a comment to a Bugzilla bug whenever it finds a reference to that bug ID in a commit comment. You can install this hook on a shared server, so that any time a remote user pushes changes to this server, the hook gets run. - It adds a comment to the bug that looks like this (you can + It adds a comment to the bug that looks like this (you can configure the contents of the comment&emdash;see below): Changeset aad8b264143a, made by Joe User @@ -861,19 +861,19 @@ http://hg.domain.com/frobnitz?cmd=changeset;node=aad8b264143a Changeset description: Fix bug 10483 by guarding against some NULL pointers - The value of this hook is that it automates the process of + The value of this hook is that it automates the process of updating a bug any time a changeset refers to it. If you configure the hook properly, it makes it easy for people to browse straight from a Bugzilla bug to a changeset that refers to that bug. - You can use the code in this hook as a starting point for + You can use the code in this hook as a starting point for some more exotic Bugzilla integration recipes. Here are a few possibilities: - Require that every changeset pushed to the + Require that every changeset pushed to the server have a valid bug ID in its commit comment. In this case, you'd want to configure the hook as a pretxncommit hook. This would @@ -881,7 +881,7 @@ IDs. - Allow incoming changesets to automatically + Allow incoming changesets to automatically modify the state of a bug, as well as simply adding a comment. For example, the hook could recognise the string fixed bug 31337 as @@ -890,11 +890,11 @@ - + Configuring the <literal role="hook">bugzilla</literal> hook - You should configure this hook in your server's + You should configure this hook in your server's ~/.hgrc as an incoming hook, for example as follows: @@ -902,25 +902,25 @@ [hooks] incoming.bugzilla = python:hgext.bugzilla.hook - Because of the specialised nature of this hook, and + Because of the specialised nature of this hook, and because Bugzilla was not written with this kind of integration in mind, configuring this hook is a somewhat involved process. - Before you begin, you must install the MySQL bindings + Before you begin, you must install the MySQL bindings for Python on the host(s) where you'll be running the hook. If this is not available as a binary package for your system, you can download it from web:mysql-python. - Configuration information for this hook lives in the + Configuration information for this hook lives in the bugzilla section of your ~/.hgrc. - version: The version of Bugzilla installed on the server. The database schema that Bugzilla uses changes occasionally, so this @@ -929,14 +929,14 @@ 2.16. - host: + host: The hostname of the MySQL server that stores your Bugzilla data. The database must be configured to allow connections from whatever host you are running the bugzilla hook on. - user: + user: The username with which to connect to the MySQL server. The database must be configured to allow this user to connect from whatever host you are running the - password: The MySQL password for the user you configured above. This is stored as plain text, so you should make sure that @@ -956,14 +956,14 @@ store this information. - db: + db: The name of the Bugzilla database on the MySQL server. The default value of this item is bugs, which is the standard name of the MySQL database where Bugzilla stores its data. - notify: If you want Bugzilla to send out a notification email to subscribers after this hook has added a comment to a bug, you will @@ -976,7 +976,7 @@ cd /var/www/html/bugzilla && ./processmail %s nobody@nowhere.com - The Bugzilla + The Bugzilla processmail program expects to be given a bug ID (the hook replaces %s with the bug ID) @@ -993,7 +993,7 @@ Mapping committer names to Bugzilla user names - By default, the By default, the bugzilla hook tries to use the email address of a changeset's committer as the Bugzilla user name with which to update a bug. If this does not suit @@ -1002,14 +1002,14 @@ role="rc-usermap">usermap section. - Each item in the Each item in the usermap section contains an email address on the left, and a Bugzilla user name on the right. [usermap] jane.user@example.com = jane - You can either keep the You can either keep the usermap data in a normal ~/.hgrc, or tell the bugzilla hook to read the @@ -1025,7 +1025,7 @@ # regular hgrc file refers to external usermap file [bugzilla] usermap = /home/hg/repos/userdata/bugzilla-usermap.conf - While the usermap file that it + While the usermap file that it refers to might look like this: # bugzilla-usermap.conf - inside a hg repository @@ -1035,14 +1035,14 @@ Configuring the text that gets added to a bug - You can configure the text that this hook adds as a + You can configure the text that this hook adds as a comment; you specify it in the form of a Mercurial template. Several ~/.hgrc entries (still in the bugzilla section) control this behaviour. - strip: The number of + strip: The number of leading path elements to strip from a repository's path name to construct a partial path for a URL. For example, if the repositories on your server live under webroot. - template: The text of the + template: The text of the template to use. In addition to the usual changeset-related variables, this template can use hgweb (the value of the @@ -1066,7 +1066,7 @@ - In addition, you can add a In addition, you can add a baseurl item to the web section of your ~/.hgrc. The [web] baseurl = http://hg.domain.com/ - Here is an example set of Here is an example set of bugzilla hook config information. - &ch10-bugzilla-config.lst; + &ch10-bugzilla-config.lst; Testing and troubleshooting - The most common problems with configuring the The most common problems with configuring the bugzilla hook relate to running Bugzilla's processmail script and mapping committer names to user names. - Recall from section above that the user + Recall from above that the user that runs the Mercurial process on the server is also the one that will run the processmail script. The processmail script @@ -1105,19 +1105,19 @@ under. - You can cause processmail to be run + You can cause processmail to be run with the suitable user's identity using the sudo command. Here is an example entry for a sudoers file. hg_user = (httpd_user) NOPASSWD: /var/www/html/bugzilla/processmail-wrapper %s - This allows the hg_user user to run a + This allows the hg_user user to run a processmail-wrapper program under the identity of httpd_user. - This indirection through a wrapper script is necessary, + This indirection through a wrapper script is necessary, because processmail expects to be run with its current directory set to wherever you installed Bugzilla; you can't specify that kind of constraint in a @@ -1126,18 +1126,18 @@ #!/bin/sh cd `dirname $0` && ./processmail "$1" nobody@example.com - It doesn't seem to matter what email address you pass to + It doesn't seem to matter what email address you pass to processmail. - If your usermap is + If your usermap is not set up correctly, users will see an error message from the bugzilla hook when they push changes to the server. The error message will look like this: cannot find bugzilla user id for john.q.public@example.com - What this means is that the committer's address, + What this means is that the committer's address, john.q.public@example.com, is not a valid Bugzilla user name, nor does it have an entry in your usermap that maps it to @@ -1150,7 +1150,7 @@ <literal role="hg-ext">notify</literal>&emdash;send email notifications - Although Mercurial's built-in web server provides RSS + Although Mercurial's built-in web server provides RSS feeds of changes in every repository, many people prefer to receive change notifications via email. The notify hook lets you send out @@ -1158,13 +1158,13 @@ arrive that those subscribers are interested in. - As with the bugzilla + As with the bugzilla hook, the notify hook is template-driven, so you can customise the contents of the notification messages that it sends. - By default, the notify + By default, the notify hook includes a diff of every changeset that it sends out; you can limit the size of the diff, or turn this feature off entirely. It is useful for letting subscribers review changes @@ -1175,7 +1175,7 @@ Configuring the <literal role="hg-ext">notify</literal> hook - You can set up the You can set up the notify hook to send one email message per incoming changeset, or one per incoming group of changesets (all those that arrived in a single pull or @@ -1187,12 +1187,12 @@ # send one email per change incoming.notify = python:hgext.notify.hook - Configuration information for this hook lives in the + Configuration information for this hook lives in the notify section of a ~/.hgrc file. - test: + test: By default, this hook does not send out email at all; instead, it prints the message that it would send. Set this item to @@ -1204,7 +1204,7 @@ notifications while you debug your configuration. - config: + config: The path to a configuration file that contains subscription information. This is kept separate from the main ~/.hgrc so @@ -1213,7 +1213,7 @@ subscriptions, and push the changes back to your server. - strip: + strip: The number of leading path separator characters to strip from a repository's path, when deciding whether a repository has subscribers. For example, if the @@ -1230,13 +1230,13 @@ match subscribers against that. - template: The template text to use when sending messages. This specifies both the contents of the message header and its body. - maxdiff: The maximum number of lines of diff data to append to the end of a message. If a diff is longer than this, it is @@ -1245,41 +1245,40 @@ emails. - sources: A list of sources of changesets to consider. This lets you limit notify to only sending out email about changes that remote users pushed into - this repository via a server, for example. See section - for the sources you can - specify here. + this repository via a server, for example. See + for the sources you + can specify here. - If you set the baseurl + If you set the baseurl item in the web section, you can use it in a template; it will be available as webroot. - Here is an example set of Here is an example set of notify configuration information. - &ch10-notify-config.lst; + &ch10-notify-config.lst; - This will produce a message that looks like the + This will produce a message that looks like the following: - &ch10-notify-config-mail.lst; + &ch10-notify-config-mail.lst; Testing and troubleshooting - Do not forget that by default, the Do not forget that by default, the notify extension will not send any mail until you explicitly configure it to do so, by setting test to @@ -1290,17 +1289,17 @@ - + Information for writers of hooks In-process hook execution - An in-process hook is called with arguments of the + An in-process hook is called with arguments of the following form: def myhook(ui, repo, **kwargs): pass - The ui parameter is a The ui parameter is a ui object. The repo parameter is a localrepository @@ -1309,38 +1308,38 @@ being invoked, with the following common features: - If a parameter is named + If a parameter is named node or parentN, it will contain a hexadecimal changeset ID. The empty string is used to represent null changeset ID instead of a string of zeroes. - If a parameter is named + If a parameter is named url, it will contain the URL of a remote repository, if that can be determined. - Boolean-valued parameters are represented as + Boolean-valued parameters are represented as Python bool objects. - An in-process hook is called without a change to the + An in-process hook is called without a change to the process's working directory (unlike external hooks, which are run in the root of the repository). It must not change the process's working directory, or it will cause any calls it makes into the Mercurial API to fail. - If a hook returns a boolean false value, it + If a hook returns a boolean false value, it is considered to have succeeded. If it returns a boolean true value or raises an exception, it is considered to have failed. A useful way to think of the calling convention is tell me if you fail. - Note that changeset IDs are passed into Python hooks as + Note that changeset IDs are passed into Python hooks as hexadecimal strings, not the binary hashes that Mercurial's APIs normally use. To convert a hash from hex to binary, use the bin function. @@ -1350,7 +1349,7 @@ External hook execution - An external hook is passed to the shell of the user + An external hook is passed to the shell of the user running Mercurial. Features of that shell, such as variable substitution and command redirection, are available. The hook is run in the root directory of the repository (unlike @@ -1358,7 +1357,7 @@ Mercurial was run in). - Hook parameters are passed to the hook as environment + Hook parameters are passed to the hook as environment variables. Each environment variable's name is converted in upper case and prefixed with the string HG_. For example, if the @@ -1367,7 +1366,7 @@ parameter will be HG_NODE. - A boolean parameter is represented as the string + A boolean parameter is represented as the string 1 for true, 0 for false. If an environment variable is named HG_NODE, @@ -1379,7 +1378,7 @@ URL of a remote repository, if that can be determined. - If a hook exits with a status of zero, it is considered to + If a hook exits with a status of zero, it is considered to have succeeded. If it exits with a non-zero status, it is considered to have failed. @@ -1388,7 +1387,7 @@ Finding out where changesets come from - A hook that involves the transfer of changesets between a + A hook that involves the transfer of changesets between a local repository and another may be able to find out information about the far side. Mercurial knows how changes are being transferred, @@ -1396,10 +1395,10 @@ transferred to or from. - + Sources of changesets - Mercurial will tell a hook what means are, or were, used + Mercurial will tell a hook what means are, or were, used to transfer changesets between repositories. This is provided by Mercurial in a Python parameter named source, or an environment variable named @@ -1407,32 +1406,32 @@ - serve: Changesets are + serve: Changesets are transferred to or from a remote repository over http or ssh. - pull: Changesets are + pull: Changesets are being transferred via a pull from one repository into another. - push: Changesets are + push: Changesets are being transferred via a push from one repository into another. - bundle: Changesets are + bundle: Changesets are being transferred to or from a bundle. - + Where changes are going&emdash;remote repository URLs - When possible, Mercurial will tell a hook the location + When possible, Mercurial will tell a hook the location of the far side of an activity that transfers changeset data between repositories. This is provided by Mercurial in a Python parameter named @@ -1440,26 +1439,26 @@ HG_URL. - This information is not always known. If a hook is + This information is not always known. If a hook is invoked in a repository that is being served via http or ssh, Mercurial cannot tell where the remote repository is, but it may know where the client is connecting from. In such cases, the URL will take one of the following forms: - remote:ssh:1.2.3.4&emdash;remote + remote:ssh:1.2.3.4&emdash;remote ssh client, at the IP address 1.2.3.4. - remote:http:1.2.3.4&emdash;remote + remote:http:1.2.3.4&emdash;remote http client, at the IP address 1.2.3.4. If the client is using SSL, this will be of the form remote:https:1.2.3.4. - Empty&emdash;no information could be + Empty&emdash;no information could be discovered about the remote client. @@ -1470,11 +1469,11 @@ Hook reference - + <literal role="hook">changegroup</literal>&emdash;after remote changesets added - This hook is run after a group of pre-existing changesets + This hook is run after a group of pre-existing changesets has been added to the repository, for example via a hg pull or hg unbundle. This hook is run once per operation @@ -1484,16 +1483,16 @@ arrive in a group. - Some possible uses for this hook include kicking off an + Some possible uses for this hook include kicking off an automated build or test of the added changesets, updating a bug database, or notifying subscribers that a repository contains new changes. - Parameters to this hook: + Parameters to this hook: - node: A changeset ID. The + node: A changeset ID. The changeset ID of the first changeset in the group that was added. All changesets between this and tip, inclusive, were added by a single @@ -1502,130 +1501,131 @@ role="hg-cmd">hg unbundle. - source: A string. The - source of these changes. See section for details. + source: A + string. The source of these changes. See for details. - url: A URL. The location - of the remote repository, if known. See section for more - information. + url: A URL. The + location of the remote repository, if known. See for more information. - See also: incoming (section - ), prechangegroup (section ), pretxnchangegroup (section ) + See also: incoming (), prechangegroup (), pretxnchangegroup () - + <literal role="hook">commit</literal>&emdash;after a new changeset is created - This hook is run after a new changeset has been created. + This hook is run after a new changeset has been created. - Parameters to this hook: + Parameters to this hook: - node: A changeset ID. The + node: A changeset ID. The changeset ID of the newly committed changeset. - parent1: A changeset ID. + parent1: A changeset ID. The changeset ID of the first parent of the newly committed changeset. - parent2: A changeset ID. + parent2: A changeset ID. The changeset ID of the second parent of the newly committed changeset. - See also: precommit - (section ), pretxncommit (section ) + See also: precommit (), pretxncommit () - + <literal role="hook">incoming</literal>&emdash;after one remote changeset is added - This hook is run after a pre-existing changeset has been + This hook is run after a pre-existing changeset has been added to the repository, for example via a hg push. If a group of changesets was added in a single operation, this hook is called once for each added changeset. - You can use this hook for the same purposes as the - changegroup hook (section ); it's simply - more convenient sometimes to run a hook once per group of + You can use this hook for the same purposes as + the changegroup hook (); it's simply more + convenient sometimes to run a hook once per group of changesets, while other times it's handier once per changeset. - Parameters to this hook: + Parameters to this hook: - node: A changeset ID. The + node: A changeset ID. The ID of the newly added changeset. - source: A string. The - source of these changes. See section for details. + source: A + string. The source of these changes. See for details. - url: A URL. The location - of the remote repository, if known. See section for more - information. + url: A URL. The + location of the remote repository, if known. See for more information. - See also: changegroup - (section ) prechangegroup (section ), pretxnchangegroup (section ) + See also: changegroup () prechangegroup (), pretxnchangegroup () - + <literal role="hook">outgoing</literal>&emdash;after changesets are propagated - This hook is run after a group of changesets has been + This hook is run after a group of changesets has been propagated out of this repository, for example by a hg push or hg bundle command. - One possible use for this hook is to notify administrators + One possible use for this hook is to notify administrators that changes have been pulled. - Parameters to this hook: + Parameters to this hook: - node: A changeset ID. The + node: A changeset ID. The changeset ID of the first changeset of the group that was sent. - source: A string. The - source of the of the operation (see section ). If a remote + source: A string. The + source of the of the operation (see ). If a remote client pulled changes from this repository, source will be serve. If the client that obtained @@ -1636,187 +1636,187 @@ client performed. - url: A URL. The location - of the remote repository, if known. See section for more - information. + url: A URL. The + location of the remote repository, if known. See for more information. - See also: preoutgoing - (section ) + See also: preoutgoing () - + <literal role="hook">prechangegroup</literal>&emdash;before starting to add remote changesets - This controlling hook is run before Mercurial begins to + This controlling hook is run before Mercurial begins to add a group of changesets from another repository. - This hook does not have any information about the + This hook does not have any information about the changesets to be added, because it is run before transmission of those changesets is allowed to begin. If this hook fails, the changesets will not be transmitted. - One use for this hook is to prevent external changes from + One use for this hook is to prevent external changes from being added to a repository. For example, you could use this to freeze a server-hosted branch temporarily or permanently so that users cannot push to it, while still allowing a local administrator to modify the repository. - Parameters to this hook: + Parameters to this hook: - source: A string. The - source of these changes. See section for details. + source: A string. The + source of these changes. See for details. - url: A URL. The location - of the remote repository, if known. See section for more - information. + url: A URL. The + location of the remote repository, if known. See for more information. - See also: changegroup - (section ), incoming (section ), , pretxnchangegroup (section ) + See also: changegroup (), incoming (), pretxnchangegroup () - + <literal role="hook">precommit</literal>&emdash;before starting to commit a changeset - This hook is run before Mercurial begins to commit a new + This hook is run before Mercurial begins to commit a new changeset. It is run before Mercurial has any of the metadata for the commit, such as the files to be committed, the commit message, or the commit date. - One use for this hook is to disable the ability to commit + One use for this hook is to disable the ability to commit new changesets, while still allowing incoming changesets. Another is to run a build or test, and only allow the commit to begin if the build or test succeeds. - Parameters to this hook: + Parameters to this hook: - parent1: A changeset ID. + parent1: A changeset ID. The changeset ID of the first parent of the working directory. - parent2: A changeset ID. + parent2: A changeset ID. The changeset ID of the second parent of the working directory. - If the commit proceeds, the parents of the working + If the commit proceeds, the parents of the working directory will become the parents of the new changeset. - See also: commit (section - ), pretxncommit (section ) + See also: commit + (), pretxncommit () - + <literal role="hook">preoutgoing</literal>&emdash;before starting to propagate changesets - This hook is invoked before Mercurial knows the identities + This hook is invoked before Mercurial knows the identities of the changesets to be transmitted. - One use for this hook is to prevent changes from being + One use for this hook is to prevent changes from being transmitted to another repository. - Parameters to this hook: + Parameters to this hook: - source: A string. The - source of the operation that is attempting to obtain - changes from this repository (see section ). See the documentation + source: A + string. The source of the operation that is attempting to + obtain changes from this repository (see ). See the documentation for the source parameter to the - outgoing hook, in section - , for possible values - of - this parameter. + outgoing hook, in + , for possible values + of this parameter. - url: A URL. The location - of the remote repository, if known. See section for more - information. + url: A URL. The + location of the remote repository, if known. See for more information. - See also: outgoing (section - ) + See also: outgoing () - + <literal role="hook">pretag</literal>&emdash;before tagging a changeset - This controlling hook is run before a tag is created. If + This controlling hook is run before a tag is created. If the hook succeeds, creation of the tag proceeds. If the hook fails, the tag is not created. - Parameters to this hook: + Parameters to this hook: - local: A boolean. Whether + local: A boolean. Whether the tag is local to this repository instance (i.e. stored in .hg/localtags) or managed by Mercurial (stored in .hgtags). - node: A changeset ID. The + node: A changeset ID. The ID of the changeset to be tagged. - tag: A string. The name of + tag: A string. The name of the tag to be created. - If the tag to be created is revision-controlled, the - precommit and pretxncommit hooks (sections and ) will also be run. + If the tag to be created is + revision-controlled, the precommit and pretxncommit hooks ( and ) will also be run. - See also: tag (section - ) + See also: tag + () - + <literal role="hook">pretxnchangegroup</literal>&emdash;before completing addition of remote changesets - This controlling hook is run before a + This controlling hook is run before a transaction&emdash;that manages the addition of a group of new changesets from outside the repository&emdash;completes. If the hook succeeds, the transaction completes, and all of the @@ -1825,28 +1825,28 @@ the changesets is erased. - This hook can access the metadata associated with the + This hook can access the metadata associated with the almost-added changesets, but it should not do anything permanent with this data. It must also not modify the working directory. - While this hook is running, if other Mercurial processes + While this hook is running, if other Mercurial processes access this repository, they will be able to see the almost-added changesets as if they are permanent. This may lead to race conditions if you do not take steps to avoid them. - This hook can be used to automatically vet a group of + This hook can be used to automatically vet a group of changesets. If the hook fails, all of the changesets are rejected when the transaction rolls back. - Parameters to this hook: + Parameters to this hook: - node: A changeset ID. The + node: A changeset ID. The changeset ID of the first changeset in the group that was added. All changesets between this and tip, @@ -1856,32 +1856,32 @@ role="hg-cmd">hg unbundle. - source: A string. The - source of these changes. See section for details. + source: A + string. The source of these changes. See for details. - url: A URL. The location - of the remote repository, if known. See section for more - information. + url: A URL. The + location of the remote repository, if known. See for more information. - See also: changegroup - (section ), incoming (section ), prechangegroup (section ) + See also: changegroup (), incoming (), prechangegroup () - + <literal role="hook">pretxncommit</literal>&emdash;before completing commit of new changeset - This controlling hook is run before a + This controlling hook is run before a transaction&emdash;that manages a new commit&emdash;completes. If the hook succeeds, the transaction completes and the changeset becomes permanent within this repository. If the @@ -1889,84 +1889,85 @@ data is erased. - This hook can access the metadata associated with the + This hook can access the metadata associated with the almost-new changeset, but it should not do anything permanent with this data. It must also not modify the working directory. - While this hook is running, if other Mercurial processes + While this hook is running, if other Mercurial processes access this repository, they will be able to see the almost-new changeset as if it is permanent. This may lead to race conditions if you do not take steps to avoid them. - Parameters to this hook: + Parameters to this hook: - node: A changeset ID. The + node: A changeset ID. The changeset ID of the newly committed changeset. - parent1: A changeset ID. + parent1: A changeset ID. The changeset ID of the first parent of the newly committed changeset. - parent2: A changeset ID. + parent2: A changeset ID. The changeset ID of the second parent of the newly committed changeset. - See also: precommit - (section ) + See also: precommit () - + <literal role="hook">preupdate</literal>&emdash;before updating or merging working directory - This controlling hook is run before an update or merge of - the working directory begins. It is run only if Mercurial's - normal pre-update checks determine that the update or merge - can proceed. If the hook succeeds, the update or merge may - proceed; if it fails, the update or merge does not start. + This controlling hook is run before an update + or merge of the working directory begins. It is run only if + Mercurial's normal pre-update checks determine that the update + or merge can proceed. If the hook succeeds, the update or + merge may proceed; if it fails, the update or merge does not + start. - Parameters to this hook: + Parameters to this hook: - parent1: A changeset ID. - The ID of the parent that the working directory is to be - updated to. If the working directory is being merged, it - will not change this parent. + parent1: A + changeset ID. The ID of the parent that the working + directory is to be updated to. If the working directory + is being merged, it will not change this parent. - parent2: A changeset ID. - Only set if the working directory is being merged. The ID - of the revision that the working directory is being merged - with. + parent2: A + changeset ID. Only set if the working directory is being + merged. The ID of the revision that the working directory + is being merged with. - See also: update (section - ) - + See also: update + () - + <literal role="hook">tag</literal>&emdash;after tagging a changeset - This hook is run after a tag has been created. + This hook is run after a tag has been created. - Parameters to this hook: + Parameters to this hook: - local: A boolean. Whether + local: A boolean. Whether the new tag is local to this repository instance (i.e. stored in .hg/localtags) or managed by @@ -1974,30 +1975,30 @@ role="special">.hgtags). - node: A changeset ID. The + node: A changeset ID. The ID of the changeset that was tagged. - tag: A string. The name of + tag: A string. The name of the tag that was created. - If the created tag is revision-controlled, the If the created tag is revision-controlled, the commit hook (section ) is run before this hook. + linkend="sec:hook:commit"/>) is run before this hook. - See also: pretag (section - ) + See also: pretag + () - + <literal role="hook">update</literal>&emdash;after updating or merging working directory - This hook is run after an update or merge of the working + This hook is run after an update or merge of the working directory completes. Since a merge can fail (if the external hgmerge command fails to resolve conflicts in a file), this hook communicates whether the update or merge @@ -2005,25 +2006,25 @@ - error: A boolean. + error: A boolean. Indicates whether the update or merge completed successfully. - parent1: A changeset ID. + parent1: A changeset ID. The ID of the parent that the working directory was updated to. If the working directory was merged, it will not have changed this parent. - parent2: A changeset ID. + parent2: A changeset ID. Only set if the working directory was merged. The ID of the revision that the working directory was merged with. - See also: preupdate - (section ) + See also: preupdate + () diff -r 6b1577ef5135 -r 1c13ed2130a7 en/ch10-template.xml --- a/en/ch10-template.xml Fri Mar 20 17:17:55 2009 +0800 +++ b/en/ch10-template.xml Mon Mar 30 16:23:33 2009 +0800 @@ -1,6 +1,6 @@ - + Customising the output of Mercurial @@ -10,7 +10,7 @@ command, or to customise the entire appearance of the built-in web interface. - + Using precanned output styles Packaged with Mercurial are some output styles that you can @@ -107,7 +107,7 @@ escape sequence, telling Mercurial to print a newline at the end of each template item. If you omit this newline, Mercurial will run each piece of output together. See - section for more details + for more details of escape sequences. A template that prints a fixed string of text all the time @@ -121,14 +121,13 @@ been replaced in the output with the description of each changeset. Every time Mercurial finds text enclosed in curly braces ({ and - }), it will try to replace the braces - and text with the expansion of whatever is inside. To print a - literal curly brace, you must escape it, as described in section - . + }), it will try to replace the + braces and text with the expansion of whatever is inside. To + print a literal curly brace, you must escape it, as described in + . - + Common template keywords You can start writing simple templates immediately using the @@ -149,8 +148,8 @@ Date information. The date when the changeset was committed. This is not human-readable; you must pass it through a filter that will render it - appropriately. See section for more information + appropriately. See for more information on filters. The date is expressed as a pair of numbers. The first number is a Unix UTC timestamp (seconds since January 1, 1970); the second is the offset of the committer's @@ -197,13 +196,12 @@ As we noted above, the date keyword does not produce human-readable output, so we must treat it specially. This involves using a filter, about which more - in section . + in . &interaction.template.simple.datekeyword; - + Escape sequences Mercurial's templating engine recognises the most commonly @@ -245,7 +243,7 @@ it. - + Filtering keywords to change their results Some of the results of template expansion are not diff -r 6b1577ef5135 -r 1c13ed2130a7 en/ch11-mq.xml --- a/en/ch11-mq.xml Fri Mar 20 17:17:55 2009 +0800 +++ b/en/ch11-mq.xml Mon Mar 30 16:23:33 2009 +0800 @@ -1,13 +1,13 @@ - + Managing change with Mercurial Queues - + The patch management problem - Here is a common scenario: you need to install a software + Here is a common scenario: you need to install a software package from source, but you find a bug that you must fix in the source before you can start using the package. You make your changes, forget about the package for a while, and a few months @@ -17,27 +17,27 @@ the newer version. This is a tedious task, and it's easy to make mistakes. - This is a simple case of the patch management + This is a simple case of the patch management problem. You have an upstream source tree that you can't change; you need to make some local changes on top of the upstream tree; and you'd like to be able to keep those changes separate, so that you can apply them to newer versions of the upstream source. - The patch management problem arises in many situations. + The patch management problem arises in many situations. Probably the most visible is that a user of an open source software project will contribute a bug fix or new feature to the project's maintainers in the form of a patch. - Distributors of operating systems that include open source + Distributors of operating systems that include open source software often need to make changes to the packages they distribute so that they will build properly in their environments. - When you have few changes to maintain, it is easy to manage + When you have few changes to maintain, it is easy to manage a single patch using the standard diff and - patch programs (see section for a discussion of these + patch programs (see for a discussion of these tools). Once the number of changes grows, it starts to make sense to maintain patches as discrete chunks of work, so that for example a single patch will contain @@ -49,37 +49,37 @@ your fix in a subsequent release, you can simply drop that single patch when you're updating to the newer release. - Maintaining a single patch against an upstream tree is a + Maintaining a single patch against an upstream tree is a little tedious and error-prone, but not difficult. However, the complexity of the problem grows rapidly as the number of patches you have to maintain increases. With more than a tiny number of patches in hand, understanding which ones you have applied and maintaining them moves from messy to overwhelming. - Fortunately, Mercurial includes a powerful extension, + Fortunately, Mercurial includes a powerful extension, Mercurial Queues (or simply MQ), that massively simplifies the patch management problem. - + The prehistory of Mercurial Queues - During the late 1990s, several Linux kernel developers + During the late 1990s, several Linux kernel developers started to maintain patch series that modified the behaviour of the Linux kernel. Some of these series were focused on stability, some on feature coverage, and others were more speculative. - The sizes of these patch series grew rapidly. In 2002, + The sizes of these patch series grew rapidly. In 2002, Andrew Morton published some shell scripts he had been using to automate the task of managing his patch queues. Andrew was successfully using these scripts to manage hundreds (sometimes thousands) of patches on top of the Linux kernel. - + A patchwork quilt - In early 2003, Andreas Gruenbacher and Martin Quinson + In early 2003, Andreas Gruenbacher and Martin Quinson borrowed the approach of Andrew's scripts and published a tool called patchwork quilt web:quilt, or simply quilt @@ -88,7 +88,7 @@ management, it rapidly gained a large following among open source software developers. - Quilt manages a stack of patches on + Quilt manages a stack of patches on top of a directory tree. To begin, you tell quilt to manage a directory tree, and tell it which files you want to manage; it stores away the names and contents of those files. To fix a @@ -96,14 +96,14 @@ files you need to fix, then refresh the patch. - The refresh step causes quilt to scan the directory tree; + The refresh step causes quilt to scan the directory tree; it updates the patch with all of the changes you have made. You can create another patch on top of the first, which will track the changes required to modify the tree from tree with one patch applied to tree with two patches applied. - You can change which patches are + You can change which patches are applied to the tree. If you pop a patch, the changes made by that patch will vanish from the directory tree. Quilt remembers which patches you have popped, though, @@ -115,25 +115,25 @@ any time, change both which patches are applied and what modifications those patches make. - Quilt knows nothing about revision control tools, so it + Quilt knows nothing about revision control tools, so it works equally well on top of an unpacked tarball or a Subversion working copy. - + From patchwork quilt to Mercurial Queues - In mid-2005, Chris Mason took the features of quilt and + In mid-2005, Chris Mason took the features of quilt and wrote an extension that he called Mercurial Queues, which added quilt-like behaviour to Mercurial. - The key difference between quilt and MQ is that quilt + The key difference between quilt and MQ is that quilt knows nothing about revision control systems, while MQ is integrated into Mercurial. Each patch that you push is represented as a Mercurial changeset. Pop a patch, and the changeset goes away. - Because quilt does not care about revision control tools, + Because quilt does not care about revision control tools, it is still a tremendously useful piece of software to know about for situations where you cannot use Mercurial and MQ. @@ -143,16 +143,16 @@ The huge advantage of MQ - I cannot overstate the value that MQ offers through the + I cannot overstate the value that MQ offers through the unification of patches and revision control. - A major reason that patches have persisted in the free + A major reason that patches have persisted in the free software and open source world&emdash;in spite of the availability of increasingly capable revision control tools over the years&emdash;is the agility they offer. - Traditional revision control tools make a permanent, + Traditional revision control tools make a permanent, irreversible record of everything that you do. While this has great value, it's also somewhat stifling. If you want to perform a wild-eyed experiment, you have to be careful in how @@ -160,7 +160,7 @@ misleading or destabilising&emdash;traces of your missteps and errors in the permanent revision record. - By contrast, MQ's marriage of distributed revision control + By contrast, MQ's marriage of distributed revision control with patches makes it much easier to isolate your work. Your patches live on top of normal revision history, and you can make them disappear or reappear at will. If you don't like a patch, @@ -168,7 +168,7 @@ simply fix it&emdash;as many times as you need to, until you have refined it into the form you desire. - As an example, the integration of patches with revision + As an example, the integration of patches with revision control makes understanding patches and debugging their effects&emdash;and their interplay with the code they're based on&emdash;enormously easier. Since every @@ -183,14 +183,14 @@ And so on. - + Understanding patches - Because MQ doesn't hide its patch-oriented nature, it is + Because MQ doesn't hide its patch-oriented nature, it is helpful to understand what patches are, and a little about the tools that work with them. - The traditional Unix diff command + The traditional Unix diff command compares two files, and prints a list of differences between them. The patch command understands these differences as modifications to make to a @@ -199,20 +199,20 @@ &interaction.mq.dodiff.diff; - The type of file that diff generates (and + The type of file that diff generates (and patch takes as input) is called a patch or a diff; there is no difference between a patch and a diff. (We'll use the term patch, since it's more commonly used.) - A patch file can start with arbitrary text; the + A patch file can start with arbitrary text; the patch command ignores this text, but MQ uses it as the commit message when creating changesets. To find the beginning of the patch content, patch searches for the first line that starts with the string diff -. - MQ works with unified diffs + MQ works with unified diffs (patch can accept several other diff formats, but MQ doesn't). A unified diff contains two kinds of header. The file header describes the file being @@ -220,7 +220,7 @@ patch sees a new file header, it looks for a file with that name to start modifying. - After the file header comes a series of + After the file header comes a series of hunks. Each hunk starts with a header; this identifies the range of line numbers within the file that the hunk should modify. Following the header, a hunk starts and @@ -232,7 +232,7 @@ runs the hunks together, with a few lines of context between modifications. - Each line of context begins with a space character. Within + Each line of context begins with a space character. Within the hunk, a line that begins with - means remove this line, while a line that begins with @@ -240,16 +240,16 @@ line. For example, a line that is modified is represented by one deletion and one insertion. - We will return to some of the more subtle aspects of patches - later (in section ), but you + We will return to some of the more subtle aspects of patches + later (in ), but you should have enough information now to use MQ. - + Getting started with Mercurial Queues - Because MQ is implemented as an extension, you must + Because MQ is implemented as an extension, you must explicitly enable before you can use it. (You don't need to download anything; MQ ships with the standard Mercurial distribution.) To enable MQ, edit your [extensions] hgext.mq = - Once the extension is enabled, it will make a number of new + Once the extension is enabled, it will make a number of new commands available. To verify that the extension is working, you can use hg help to see if the qinit command is now @@ -267,14 +267,14 @@ &interaction.mq.qinit-help.help; - You can use MQ with any Mercurial + You can use MQ with any Mercurial repository, and its commands only operate within that repository. To get started, simply prepare the repository using the qinit command. &interaction.mq.tutorial.qinit; - This command creates an empty directory called This command creates an empty directory called .hg/patches, where MQ will keep its metadata. As with many Mercurial commands, the qinit command prints nothing @@ -283,18 +283,18 @@ Creating a new patch - To begin work on a new patch, use the To begin work on a new patch, use the qnew command. This command takes one argument, the name of the patch to create. - MQ will use this as the name of an actual file in the + MQ will use this as the name of an actual file in the .hg/patches directory, as you can see below. &interaction.mq.tutorial.qnew; - Also newly present in the Also newly present in the .hg/patches directory are two other files, series and status. The applied in this repository. - You may sometimes want to edit the You may sometimes want to edit the series file by hand; for example, to change the sequence in which some patches are applied. However, manually editing the - Once you have created your new patch, you can edit files + Once you have created your new patch, you can edit files in the working directory as you usually would. All of the normal Mercurial commands, such as hg diff and hg @@ -325,17 +325,17 @@ Refreshing a patch - When you reach a point where you want to save your work, + When you reach a point where you want to save your work, use the qrefresh command to update the patch you are working on. &interaction.mq.tutorial.qrefresh; - This command folds the changes you have made in the + This command folds the changes you have made in the working directory into your patch, and updates its corresponding changeset to contain those changes. - You can run qrefresh + You can run qrefresh as often as you like, so it's a good way to checkpoint your work. Refresh your patch at an opportune time; try an experiment; and if the experiment @@ -348,19 +348,19 @@ Stacking and tracking patches - Once you have finished working on a patch, or need to work + Once you have finished working on a patch, or need to work on another, you can use the qnew command again to create a new patch. Mercurial will apply this patch on top of your existing patch. &interaction.mq.tutorial.qnew2; - Notice that the patch contains the changes in our prior + Notice that the patch contains the changes in our prior patch as part of its context (you can see this more clearly in the output of hg annotate). - So far, with the exception of So far, with the exception of qnew and qrefresh, we've been careful to only use regular Mercurial commands. However, MQ provides @@ -370,13 +370,13 @@ &interaction.mq.tutorial.qseries; - The The qseries command lists every patch that MQ knows about in this repository, from oldest to newest (most recently created). - The The qapplied command lists every patch that MQ has applied in this repository, again from oldest to newest (most recently @@ -387,12 +387,12 @@ Manipulating the patch stack - The previous discussion implied that there must be a + The previous discussion implied that there must be a difference between known and applied patches, and there is. MQ can manage a patch without it being applied in the repository. - An applied patch has a corresponding + An applied patch has a corresponding changeset in the repository, and the effects of the patch and changeset are visible in the working directory. You can undo the application of a patch using the knows about, or manages, a popped patch, but the patch no longer has a corresponding changeset in the repository, and the working directory does not contain the - changes made by the patch. Figure illustrates + changes made by the patch. illustrates the difference between applied and tracked patches. - - - - XXX add text - Applied and unapplied patches - in the MQ patch stack - - +
+ Applied and unapplied patches in the MQ patch + stack + + + XXX add text + +
- You can reapply an unapplied, or popped, patch using the + You can reapply an unapplied, or popped, patch using the qpush command. This creates a new changeset to correspond to the patch, and the patch's changes once again become present in the working @@ -422,7 +422,7 @@ role="hg-ext-mq">qpush
in action.
&interaction.mq.tutorial.qpop; - Notice that once we have popped a patch or two patches, + Notice that once we have popped a patch or two patches, the output of qseries remains the same, while that of qapplied has changed. @@ -432,7 +432,7 @@ Pushing and popping many patches - While qpush and + While qpush and qpop each operate on a single patch at a time by default, you can push and pop many patches in one go. The option to qpop causes it to pop all applied patches. (For some more ways to push and pop many patches, - see section - below.) + see below.) &interaction.mq.tutorial.qpush-a; @@ -451,7 +450,7 @@ Safety checks, and overriding them - Several MQ commands check the working directory before + Several MQ commands check the working directory before they do anything, and fail if they find any modifications. They do this to ensure that you won't lose any changes that you have made, but not yet incorporated into a patch. The @@ -463,7 +462,7 @@ &interaction.mq.tutorial.add; - Commands that check the working directory all take an + Commands that check the working directory all take an I know what I'm doing option, which is always named . The exact meaning of depends on the command. For example, @@ -480,14 +479,14 @@ Working on several patches at once - The qrefresh command + The qrefresh command always refreshes the topmost applied patch. This means that you can suspend work on one patch (by refreshing it), pop or push to make a different patch the top, and work on that patch for a while. - Here's an example that illustrates how you can use this + Here's an example that illustrates how you can use this ability. Let's say you're developing a new feature as two patches. The first is a change to the core of your software, and the second&emdash;layered on top of the @@ -503,10 +502,10 @@
- + More about patches - MQ uses the GNU patch command to apply + MQ uses the GNU patch command to apply patches, so it's helpful to know a few more detailed aspects of how patch works, and about patches themselves. @@ -514,14 +513,14 @@ The strip count - If you look at the file headers in a patch, you will + If you look at the file headers in a patch, you will notice that the pathnames usually have an extra component on the front that isn't present in the actual path name. This is a holdover from the way that people used to generate patches (people still do this, but it's somewhat rare with modern revision control tools). - Alice would unpack a tarball, edit her files, then decide + Alice would unpack a tarball, edit her files, then decide that she wanted to create a patch. So she'd rename her working directory, unpack the tarball again (hence the need for the rename), and use the
command and MQ expect patches to have a strip count of one.
- If you receive a patch from someone that you want to add + If you receive a patch from someone that you want to add to your patch queue, and the patch needs a strip count other than one, you cannot just qimport the patch, because @@ -584,14 +583,14 @@ Strategies for applying a patch - When patch applies a hunk, it tries a + When patch applies a hunk, it tries a handful of successively less accurate strategies to try to make the hunk apply. This falling-back technique often makes it possible to take a patch that was generated against an old version of a file, and apply it against a newer version of that file. - First, patch tries an exact match, + First, patch tries an exact match, where the line numbers, the context, and the text to be modified must apply exactly. If it cannot make an exact match, it tries to find an exact match for the context, @@ -600,7 +599,7 @@ applied, but at some offset from the original line number. - If a context-only match fails, patch + If a context-only match fails, patch removes the first and last lines of the context, and tries a reduced context-only match. If the hunk with reduced context succeeds, it prints a message saying that @@ -609,7 +608,7 @@ context patch had to trim before the patch applied). - When neither of these techniques works, + When neither of these techniques works, patch prints a message saying that the hunk in question was rejected. It saves rejected hunks (also simply called rejects) to a file with the same @@ -629,36 +628,36 @@ Some quirks of patch representation - There are a few useful things to know about how + There are a few useful things to know about how patch works with files. - This should already be obvious, but + This should already be obvious, but patch cannot handle binary files. - Neither does it care about the executable bit; + Neither does it care about the executable bit; it creates new files as readable, but not executable. - patch treats the removal of + patch treats the removal of a file as a diff between the file to be removed and the empty file. So your idea of I deleted this file looks like every line of this file was deleted in a patch. - It treats the addition of a file as a diff + It treats the addition of a file as a diff between the empty file and the file to be added. So in a patch, your idea of I added this file looks like every line of this file was added. - It treats a renamed file as the removal of the + It treats a renamed file as the removal of the old name, and the addition of the new name. This means that renamed files have a big footprint in patches. (Note also that Mercurial does not currently try to infer when files have been renamed or copied in a patch.) - patch cannot represent + patch cannot represent empty files, so you cannot use a patch to represent the notion I added this empty file to the tree. @@ -667,7 +666,7 @@ Beware the fuzz - While applying a hunk at an offset, or with a fuzz factor, + While applying a hunk at an offset, or with a fuzz factor, will often be completely successful, these inexact techniques naturally leave open the possibility of corrupting the patched file. The most common cases typically involve applying a @@ -677,7 +676,7 @@ fuzz factor, you should make sure that the modified files are correct afterwards. - It's often a good idea to refresh a patch that has applied + It's often a good idea to refresh a patch that has applied with an offset or fuzz factor; refreshing the patch generates new context information that will make it apply cleanly. I say often, not always, because @@ -692,30 +691,29 @@ Handling rejection - If qpush fails to + If qpush fails to apply a patch, it will print an error message and exit. If it has left .rej files behind, it is usually best to fix up the rejected hunks before you push more patches or do any further work. - If your patch used to apply cleanly, + If your patch used to apply cleanly, and no longer does because you've changed the underlying code that your patches are based on, Mercurial Queues can help; see - section for details. + for details. - Unfortunately, there aren't any great techniques for + Unfortunately, there aren't any great techniques for dealing with rejected hunks. Most often, you'll need to view the .rej file and edit the target file, applying the rejected hunks by hand. - If you're feeling adventurous, Neil Brown, a Linux kernel + If you're feeling adventurous, Neil Brown, a Linux kernel hacker, wrote a tool called wiggle web:wiggle, which is more vigorous than patch in its attempts to make a patch apply. - Another Linux kernel hacker, Chris Mason (the author of + Another Linux kernel hacker, Chris Mason (the author of Mercurial Queues), wrote a similar tool called mpatch web:mpatch, which takes a simple approach to automating the application of @@ -724,21 +722,21 @@ reasons that a hunk may be rejected: - The context in the middle of a hunk has + The context in the middle of a hunk has changed. - A hunk is missing some context at the + A hunk is missing some context at the beginning or end. - A large hunk might apply better&emdash;either + A large hunk might apply better&emdash;either entirely or in part&emdash;if it was broken up into smaller hunks. - A hunk removes lines with slightly different + A hunk removes lines with slightly different content than those currently present in the file. - If you use wiggle or + If you use wiggle or mpatch, you should be doubly careful to check your results when you're done. In fact, mpatch enforces this method of @@ -749,10 +747,10 @@
- + Getting the best performance out of MQ - MQ is very efficient at handling a large number of patches. + MQ is very efficient at handling a large number of patches. I ran some performance experiments in mid-2006 for a talk that I gave at the 2006 EuroPython conference web:europython. I used as my data set the @@ -761,7 +759,7 @@ all 27,472 revisions between Linux 2.6.12-rc2 and Linux 2.6.17. - On my old, slow laptop, I was able to On my old, slow laptop, I was able to hg qpush all 1,738 patches in 3.5 minutes, and hg qpop @@ -772,11 +770,11 @@ (which made 22,779 lines of changes to 287 files) in 6.6 seconds. - Clearly, MQ is well suited to working in large trees, but + Clearly, MQ is well suited to working in large trees, but there are a few tricks you can use to get the best performance of it. - First of all, try to batch operations + First of all, try to batch operations together. Every time you run qpush or qpop, these commands scan the @@ -787,7 +785,7 @@ medium-sized tree (containing tens of thousands of files), it can take a second or more. - The qpush and The qpush and qpop commands allow you to push and pop multiple patches at a time. You can identify the destination patch that you want to end up at. @@ -797,17 +795,17 @@ role="hg-ext-mq">qpop to a destination, MQ will pop patches until the destination patch is at the top. - You can identify a destination patch using either the name + You can identify a destination patch using either the name of the patch, or by number. If you use numeric addressing, patches are counted from zero; this means that the first patch is zero, the second is one, and so on. - + Updating your patches when the underlying code changes - It's common to have a stack of patches on top of an + It's common to have a stack of patches on top of an underlying repository that you don't modify directly. If you're working on changes to third-party code, or on a feature that is taking longer to develop than the rate of change of the code @@ -816,7 +814,7 @@ This is called rebasing your patch series. - The simplest way to do this is to hg + The simplest way to do this is to hg qpop your patches, then hg pull changes into the underlying @@ -828,26 +826,26 @@ affected patch, and continue pushing until you have fixed your entire stack. - This approach is easy to use and works well if you don't + This approach is easy to use and works well if you don't expect changes to the underlying code to affect how well your patches apply. If your patch stack touches code that is modified frequently or invasively in the underlying repository, however, fixing up rejected hunks by hand quickly becomes tiresome. - It's possible to partially automate the rebasing process. + It's possible to partially automate the rebasing process. If your patches apply cleanly against some revision of the underlying repo, MQ can use this information to help you to resolve conflicts between your patches and a different revision. - The process is a little involved. + The process is a little involved. - To begin, hg qpush + To begin, hg qpush -a all of your patches on top of the revision where you know that they apply cleanly. - Save a backup copy of your patch directory using + Save a backup copy of your patch directory using hg qsave . @@ -861,17 +859,17 @@ states of the series and status files. - Use hg pull to + Use hg pull to bring new changes into the underlying repository. (Don't run hg pull -u; see below for why.) - Update to the new tip revision, using Update to the new tip revision, using hg update to override the patches you have pushed. - Merge all patches using hg qpush -m + Merge all patches using hg qpush -m -a. The option to qpush tells MQ to @@ -879,7 +877,7 @@ apply. - During the hg qpush - When you finish resolving the effects of a patch, MQ + When you finish resolving the effects of a patch, MQ refreshes your patch based on the result of the merge. - At the end of this process, your repository will have one + At the end of this process, your repository will have one extra head from the old patch queue, and a copy of the old patch queue will be in .hg/patches.N. You can remove the @@ -906,26 +904,26 @@ Identifying patches - MQ commands that work with patches let you refer to a patch + MQ commands that work with patches let you refer to a patch either by using its name or by a number. By name is obvious enough; pass the name foo.patch to qpush, for example, and it will push patches until foo.patch is applied. - As a shortcut, you can refer to a patch using both a name + As a shortcut, you can refer to a patch using both a name and a numeric offset; foo.patch-2 means two patches before foo.patch, while bar.patch+4 means four patches after bar.patch. - Referring to a patch by index isn't much different. The + Referring to a patch by index isn't much different. The first patch printed in the output of qseries is patch zero (yes, it's one of those start-at-zero counting systems); the second is patch one; and so on. - MQ also makes it easy to work with patches when you are + MQ also makes it easy to work with patches when you are using normal Mercurial commands. Every command that accepts a changeset ID will also accept the name of an applied patch. MQ augments the tags normally in the repository with an eponymous @@ -935,28 +933,28 @@ the bottom-most and topmost applied patches, respectively. - These additions to Mercurial's normal tagging capabilities + These additions to Mercurial's normal tagging capabilities make dealing with patches even more of a breeze. - Want to patchbomb a mailing list with your + Want to patchbomb a mailing list with your latest series of changes? hg email qbase:qtip - (Don't know what patchbombing is? See - section .) + (Don't know what patchbombing is? See + .) - Need to see all of the patches since + Need to see all of the patches since foo.patch that have touched files in a subdirectory of your tree? hg log -r foo.patch:qtip subdir - Because MQ makes the names of patches available to the rest + Because MQ makes the names of patches available to the rest of Mercurial through its normal internal tag machinery, you don't need to type in the entire name of a patch when you want to identify it by name. - Another nice consequence of representing patch names as tags + Another nice consequence of representing patch names as tags is that when you run the hg log command, it will display a patch's name as a tag, simply as part of its normal output. This makes it easy to visually @@ -971,21 +969,21 @@ Useful things to know about - There are a number of aspects of MQ usage that don't fit + There are a number of aspects of MQ usage that don't fit tidily into sections of their own, but that are good to know. Here they are, in one place. - Normally, when you Normally, when you qpop a patch and qpush it again, the changeset that represents the patch after the pop/push will have a different identity than the changeset - that represented the hash beforehand. See section for + that represented the hash beforehand. See for information as to why this is. - It's not a good idea to It's not a good idea to hg merge changes from another branch with a patch changeset, at least if you want to maintain the patchiness of that changeset and @@ -995,16 +993,16 @@ - + Managing patches in a repository - Because MQ's Because MQ's .hg/patches directory resides outside a Mercurial repository's working directory, the underlying Mercurial repository knows nothing about the management or presence of patches. - This presents the interesting possibility of managing the + This presents the interesting possibility of managing the contents of the patch directory as a Mercurial repository in its own right. This can be a useful way to work. For example, you can work on a patch for a while, roll back to that version of the patch later on. - You can then share different versions of the same patch + You can then share different versions of the same patch stack among multiple underlying repositories. I use this when I am developing a Linux kernel feature. I have a pristine copy of my kernel sources for each of several CPU architectures, and a @@ -1023,7 +1021,7 @@ associated with that kernel tree, pop and push all of my patches, and build and test that kernel. - Managing patches in a repository makes it possible for + Managing patches in a repository makes it possible for multiple developers to work on the same patch series without colliding with each other, all on top of an underlying source base that they may or may not control. @@ -1031,7 +1029,7 @@ MQ support for patch repositories - MQ helps you to work with the MQ helps you to work with the .hg/patches directory as a repository; when you prepare a repository for working with patches using qinit, you @@ -1041,7 +1039,7 @@ Mercurial repository. - If you forget to use the option, you can simply go into the .hg/patches directory at any @@ -1050,25 +1048,25 @@ role="special">status file to the .hgignore file, though - (hg qinit - As a convenience, if MQ notices that the As a convenience, if MQ notices that the .hg/patches directory is a repository, it will automatically hg add every patch that you create and import. - MQ provides a shortcut command, MQ provides a shortcut command, qcommit, that runs hg commit in the .hg/patches directory. This saves some bothersome typing. - Finally, as a convenience to manage the patch directory, + Finally, as a convenience to manage the patch directory, you can define the alias mq on Unix systems. For example, on Linux systems using the bash shell, you can include the following @@ -1077,17 +1075,17 @@ alias mq=`hg -R $(hg root)/.hg/patches' - You can then issue commands of the form mq + You can then issue commands of the form mq pull from the main repository. A few things to watch out for - MQ's support for working with a repository full of patches + MQ's support for working with a repository full of patches is limited in a few small respects. - MQ cannot automatically detect changes that you make to + MQ cannot automatically detect changes that you make to the patch directory. If you hg pull, manually edit, or hg update changes to patches or the - + Third party tools for working with patches - Once you've been working with patches for a while, you'll + Once you've been working with patches for a while, you'll find yourself hungry for tools that will help you to understand and manipulate the patches you're dealing with. - The diffstat command + The diffstat command web:diffstat generates a histogram of the modifications made to each file in a patch. It provides a good way to get a sense of a patch&emdash;which files @@ -1123,7 +1121,7 @@ &interaction.mq.tools.tools; - The patchutils package + The patchutils package web:patchutils is invaluable. It provides a set of small utilities that follow the Unix philosophy; each does one useful thing with a patch. @@ -1133,21 +1131,21 @@ hundreds of files across dozens of directories, a single invocation of filterdiff can generate a smaller patch that only touches files whose names match a - particular glob pattern. See section for another + particular glob pattern. See for another example. Good ways to work with patches - Whether you are working on a patch series to submit to a + Whether you are working on a patch series to submit to a free software or open source project, or a series that you intend to treat as a sequence of regular changesets when you're done, you can use some simple techniques to keep your work well organised. - Give your patches descriptive names. A good name for a + Give your patches descriptive names. A good name for a patch might be rework-device-alloc.patch, because it will immediately give you a hint what the purpose of the patch is. Long names shouldn't be a problem; you won't be @@ -1159,7 +1157,7 @@ to work with, or if you are juggling a number of different tasks and your patches only get a fraction of your attention. - Be aware of what patch you're working on. Use the Be aware of what patch you're working on. Use the qtop command and skim over the text of your patches frequently&emdash;for example, using hg tip Differences between quilt and MQ - If you are already familiar with quilt, MQ provides a + If you are already familiar with quilt, MQ provides a similar command set. There are a few differences in the way that it works. - You will already have noticed that most quilt commands have + You will already have noticed that most quilt commands have MQ counterparts that simply begin with a q. The exceptions are quilt's add and remove commands, diff -r 6b1577ef5135 -r 1c13ed2130a7 en/ch12-mq-collab.xml --- a/en/ch12-mq-collab.xml Fri Mar 20 17:17:55 2009 +0800 +++ b/en/ch12-mq-collab.xml Mon Mar 30 16:23:33 2009 +0800 @@ -1,6 +1,6 @@ - + Advanced uses of Mercurial Queues @@ -430,12 +430,12 @@ path separators. - + Viewing the history of a patch If you're developing a set of patches over a long time, it's a good idea to maintain them in a repository, as - discussed in section . If you do + discussed in . If you do so, you'll quickly discover that using the hg diff command to look at the history of changes to @@ -504,8 +504,8 @@ The extdiff extension is useful for more than merely improving the presentation of MQ - patches. To read more about it, go to section . + patches. To read more about it, go to . diff -r 6b1577ef5135 -r 1c13ed2130a7 en/ch13-hgext.xml --- a/en/ch13-hgext.xml Fri Mar 20 17:17:55 2009 +0800 +++ b/en/ch13-hgext.xml Mon Mar 30 16:23:33 2009 +0800 @@ -1,27 +1,27 @@ - + Adding functionality with extensions - While the core of Mercurial is quite complete from a + While the core of Mercurial is quite complete from a functionality standpoint, it's deliberately shorn of fancy features. This approach of preserving simplicity keeps the software easy to deal with for both maintainers and users. - However, Mercurial doesn't box you in with an inflexible + However, Mercurial doesn't box you in with an inflexible command set: you can add features to it as extensions (sometimes known as plugins). We've already discussed a few of these extensions in earlier chapters. - Section + covers the fetch extension; this combines pulling new changes and merging them with local changes into a single command, fetch. - In chapter , we covered + In , we covered several extensions that are useful for hook-related functionality: acl adds access control lists; notify sends notification emails on new changes. - The Mercurial Queues patch management extension is + The Mercurial Queues patch management extension is so invaluable that it merits two chapters and an appendix all - to itself. Chapter covers the - basics; chapter discusses advanced topics; - and appendix goes into detail on + to itself. covers the + basics; discusses advanced topics; + and goes into detail on each command. - In this chapter, we'll cover some of the other extensions that + In this chapter, we'll cover some of the other extensions that are available for Mercurial, and briefly touch on some of the machinery you'll need to know about if you want to write an extension of your own. - In section , + In , we'll discuss the possibility of huge performance improvements using the inotify extension. - + Improve performance with the <literal role="hg-ext">inotify</literal> extension - Are you interested in having some of the most common + Are you interested in having some of the most common Mercurial operations run as much as a hundred times faster? Read on! - Mercurial has great performance under normal circumstances. + Mercurial has great performance under normal circumstances. For example, when you run the hg status command, Mercurial has to scan almost every directory and file in your repository so that it can display @@ -69,7 +69,7 @@ machinery to avoid doing an expensive comparison operation on files that obviously haven't changed. - Because obtaining file status is crucial to good + Because obtaining file status is crucial to good performance, the authors of Mercurial have optimised this code to within an inch of its life. However, there's no avoiding the fact that when you run hg @@ -79,20 +79,20 @@ checked. For a sufficiently large repository, this can take a long time. - To put a number on the magnitude of this effect, I created a + To put a number on the magnitude of this effect, I created a repository containing 150,000 managed files. I timed hg status as taking ten seconds to run, even when none of those files had been modified. - Many modern operating systems contain a file notification + Many modern operating systems contain a file notification facility. If a program signs up to an appropriate service, the operating system will notify it every time a file of interest is created, modified, or deleted. On Linux systems, the kernel component that does this is called inotify. - Mercurial's inotify + Mercurial's inotify extension talks to the kernel's inotify component to optimise hg status commands. The extension has two components. A daemon sits in @@ -105,29 +105,29 @@ with a result instantaneously, avoiding the need to scan every directory and file in the repository. - Recall the ten seconds that I measured plain Mercurial as + Recall the ten seconds that I measured plain Mercurial as taking to run hg status on a 150,000 file repository. With the inotify extension enabled, the time dropped to 0.1 seconds, a factor of one hundred faster. - Before we continue, please pay attention to some + Before we continue, please pay attention to some caveats. - The inotify + The inotify extension is Linux-specific. Because it interfaces directly to the Linux kernel's inotify subsystem, it does not work on other operating systems. - It should work on any Linux distribution that + It should work on any Linux distribution that was released after early 2005. Older distributions are likely to have a kernel that lacks inotify, or a version of glibc that does not have the necessary interfacing support. - Not all filesystems are suitable for use with + Not all filesystems are suitable for use with the inotify extension. Network filesystems such as NFS are a non-starter, for example, particularly if you're running Mercurial on several @@ -138,40 +138,40 @@ fine. - The inotify extension is + The inotify extension is not yet shipped with Mercurial as of May 2007, so it's a little more involved to set up than other extensions. But the performance improvement is worth it! - The extension currently comes in two parts: a set of patches + The extension currently comes in two parts: a set of patches to the Mercurial source code, and a library of Python bindings to the inotify subsystem. - There are two Python + There are two Python inotify binding libraries. One of them is called pyinotify, and is packaged by some Linux distributions as python-inotify. This is not the one you'll need, as it is too buggy and inefficient to be practical. - To get going, it's best to already have a functioning copy + To get going, it's best to already have a functioning copy of Mercurial installed. - If you follow the instructions below, you'll be + If you follow the instructions below, you'll be replacing and overwriting any existing installation of Mercurial that you might already have, using the latest bleeding edge Mercurial code. Don't say you weren't warned! - Clone the Python inotify + Clone the Python inotify binding repository. Build and install it. hg clone http://hg.kublai.com/python/inotify cd inotify python setup.py build --force sudo python setup.py install --skip-build - Clone the Clone the crew Mercurial repository. Clone the inotify patch repository so that Mercurial Queues will be able to apply @@ -181,13 +181,13 @@ hg clone crew inotify hg clone http://hg.kublai.com/mercurial/patches/inotify inotify/.hg/patches - Make sure that you have the Mercurial Queues + Make sure that you have the Mercurial Queues extension, mq, enabled. If - you've never used MQ, read section to get started + you've never used MQ, read to get started quickly. - Go into the Go into the inotify repo, and apply all of the inotify patches using the - If you get an error message from If you get an error message from qpush, you should not continue. Instead, ask for help. - Build and install the patched version of + Build and install the patched version of Mercurial. python setup.py build --force sudo python setup.py install --skip-build - Once you've build a suitably patched version of Mercurial, + Once you've build a suitably patched version of Mercurial, all you need to do to enable the inotify extension is add an entry to your ~/.hgrc. [extensions] inotify = - When the inotify extension + When the inotify extension is enabled, Mercurial will automatically and transparently start the status daemon the first time you run a command that needs status in a repository. It runs one status daemon per repository. - The status daemon is started silently, and runs in the + The status daemon is started silently, and runs in the background. If you look at a list of running processes after you've enabled the inotify extension and run a few commands in different repositories, @@ -225,7 +225,7 @@ around, waiting for updates from the kernel and queries from Mercurial. - The first time you run a Mercurial command in a repository + The first time you run a Mercurial command in a repository when you have the inotify extension enabled, it will run with about the same performance as a normal Mercurial command. This is because the status @@ -239,14 +239,14 @@ status operations almost instantaneous on repositories of all sizes! - If you like, you can manually start a status daemon using + If you like, you can manually start a status daemon using the inserve command. This gives you slightly finer control over how the daemon ought to run. This command will of course only be available when the inotify extension is enabled. - When you're using the When you're using the inotify extension, you should notice no difference at all in Mercurial's behaviour, with the sole exception of status-related commands @@ -256,28 +256,28 @@ these situations occurs, please report a bug. - + Flexible diff support with the <literal role="hg-ext">extdiff</literal> extension - Mercurial's built-in hg + Mercurial's built-in hg diff command outputs plaintext unified diffs. &interaction.extdiff.diff; - If you would like to use an external tool to display + If you would like to use an external tool to display modifications, you'll want to use the extdiff extension. This will let you use, for example, a graphical diff tool. - The extdiff extension is + The extdiff extension is bundled with Mercurial, so it's easy to set up. In the extensions section of your ~/.hgrc, simply add a one-line entry to enable the extension. [extensions] extdiff = - This introduces a command named This introduces a command named extdiff, which by default uses your system's diff command to generate a unified diff in the same form as the built-in The result won't be exactly the same as with the built-in + The result won't be exactly the same as with the built-in hg diff variations, because the output of diff varies from one system to another, even when passed the same options. - As the making snapshot + As the making snapshot lines of output above imply, the extdiff command works by creating two snapshots of your source tree. The first snapshot @@ -303,7 +303,7 @@ directories and files that have changed between the two revisions. - Snapshot directory names have the same base name as your + Snapshot directory names have the same base name as your repository. If your repository path is /quux/bar/foo, then foo will be the name of each @@ -319,7 +319,7 @@ that the diff has the snapshot directory names embedded in its header. - The extdiff command + The extdiff command accepts two important options. The option lets you choose a program to view differences with, instead of @@ -336,7 +336,7 @@ and arguments to specify the revisions you want, the files you want, and so on. - As an example, here's how to run the normal system + As an example, here's how to run the normal system diff command, getting it to generate context diffs (using the option) instead of unified diffs, and five lines of context instead of @@ -345,28 +345,28 @@ &interaction.extdiff.extdiff-ctx; - Launching a visual diff tool is just as easy. Here's how to + Launching a visual diff tool is just as easy. Here's how to launch the kdiff3 viewer. hg extdiff -p kdiff3 -o - If your diff viewing command can't deal with directories, + If your diff viewing command can't deal with directories, you can easily work around this with a little scripting. For an example of such scripting in action with the mq extension and the - interdiff command, see section . + interdiff command, see . Defining command aliases - It can be cumbersome to remember the options to both the + It can be cumbersome to remember the options to both the extdiff command and the diff viewer you want to use, so the extdiff extension lets you define new commands that will invoke your diff viewer with exactly the right options. - All you need to do is edit your All you need to do is edit your ~/.hgrc, and add a section named extdiff. Inside this section, you can define multiple commands. Here's how to add @@ -376,7 +376,7 @@ will run kdiff3 for you. [extdiff] cmd.kdiff3 = - If you leave the right hand side of the definition empty, + If you leave the right hand side of the definition empty, as above, the extdiff extension uses the name of the command you defined as the name of the external program to run. But these names don't have to @@ -386,7 +386,7 @@ [extdiff] cmd.wibble = kdiff3 - You can also specify the default options that you want to + You can also specify the default options that you want to invoke your diff viewing program with. The prefix to use is opts., followed by the name of the command to which the options apply. This example @@ -399,18 +399,18 @@ - + Cherrypicking changes with the <literal role="hg-ext">transplant</literal> extension - Need to have a long chat with Brendan about this. + Need to have a long chat with Brendan about this. - + Send changes via email with the <literal role="hg-ext">patchbomb</literal> extension - Many projects have a culture of change + Many projects have a culture of change review, in which people send their modifications to a mailing list for others to read and comment on before they commit the final version to a shared repository. Some projects @@ -418,7 +418,7 @@ other people to a repository to which those others don't have access. - Mercurial makes it easy to send changes over email for + Mercurial makes it easy to send changes over email for review or application, via its patchbomb extension. The extension is so named because changes are formatted as patches, and it's usual @@ -426,17 +426,17 @@ of changes by email is thus much like bombing the recipient's inbox, hence patchbomb. - As usual, the basic configuration of the As usual, the basic configuration of the patchbomb extension takes just one or two lines in your /.hgrc. [extensions] patchbomb = - Once you've enabled the extension, you will have a new + Once you've enabled the extension, you will have a new command available, named email. - The safest and best way to invoke the The safest and best way to invoke the email command is to always run it first with the option. @@ -447,12 +447,12 @@ role="hg-ext-patchbomb-cmd-email-opt">hg -n option removed. - The email command + The email command accepts the same kind of revision syntax as every other Mercurial command. For example, this command will send every revision between 7 and tip, inclusive. hg email -n 7:tip - You can also specify a repository to + You can also specify a repository to compare with. If you provide a repository but no revisions, the email command will send all revisions in the local repository that are not present @@ -461,7 +461,7 @@ role="hg-ext-patchbomb-cmd-email-opt">hg -b option), this will constrain the revisions sent. - It's perfectly safe to run the It's perfectly safe to run the email command without the names of the people you want to send to: if you do this, it will just prompt you for those values interactively. (If you're @@ -469,12 +469,12 @@ readline-style editing capabilities when entering those headers, too, which is useful.) - When you are sending just one revision, the When you are sending just one revision, the email command will by default use the first line of the changeset description as the subject of the single email message it sends. - If you send multiple revisions, the If you send multiple revisions, the email command will usually send one message per changeset. It will preface the series with an introductory message, in which you should describe the @@ -483,39 +483,39 @@ Changing the behaviour of patchbombs - Not every project has exactly the same conventions for + Not every project has exactly the same conventions for sending changes in email; the patchbomb extension tries to accommodate a number of variations through command line options. - You can write a subject for the introductory + You can write a subject for the introductory message on the command line using the option. This takes one argument, the text of the subject to use. - To change the email address from which the + To change the email address from which the messages originate, use the option. This takes one argument, the email address to use. - The default behaviour is to send unified diffs - (see section for a + The default behaviour is to send unified diffs + (see for a description of the format), one per message. You can send a binary bundle instead with the option. - Unified diffs are normally prefaced with a + Unified diffs are normally prefaced with a metadata header. You can omit this, and send unadorned diffs, with the option. - Diffs are normally sent inline, + Diffs are normally sent inline, in the same body part as the description of a patch. This makes it easiest for the largest number of readers to quote and respond to parts of a diff, as some mail clients @@ -525,14 +525,14 @@ role="hg-ext-patchbomb-cmd-email-opt">hg -a option. - Instead of sending mail messages, you can + Instead of sending mail messages, you can write them to an mbox-format mail folder using the option. That option takes one argument, the name of the file to write to. - If you would like to add a + If you would like to add a diffstat-format summary to each patch, and one to the introductory message, use the diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/auto-snippets.xml --- a/en/examples/auto-snippets.xml Fri Mar 20 17:17:55 2009 +0800 +++ b/en/examples/auto-snippets.xml Mon Mar 30 16:23:33 2009 +0800 @@ -1,222 +1,225 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/backout.init.out --- a/en/examples/results/backout.init.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -$ hg init myrepo -$ cd myrepo -$ echo first change >> myfile -$ hg add myfile -$ hg commit -m 'first change' -$ echo second change >> myfile -$ hg commit -m 'second change' - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/backout.manual.backout.out --- a/en/examples/results/backout.manual.backout.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -$ echo third change >> myfile -$ hg commit -m 'third change' -$ hg backout -m 'back out second change' 1 -reverting myfile -created new head -changeset backs out changeset -the backout changeset is a new head - do not forget to merge -(use "backout --merge" if you want to auto-merge) - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/backout.manual.cat.out --- a/en/examples/results/backout.manual.cat.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -$ cat myfile -first change -second change -third change - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/backout.manual.clone.out --- a/en/examples/results/backout.manual.clone.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -$ cd .. -$ hg clone -r1 myrepo newrepo -requesting all changes -adding changesets -adding manifests -adding file changes -added 2 changesets with 2 changes to 1 files -updating working directory -1 files updated, 0 files merged, 0 files removed, 0 files unresolved -$ cd newrepo - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/backout.manual.heads.out --- a/en/examples/results/backout.manual.heads.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ -$ hg heads -changeset: -tag: tip -parent: -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: back out second change - -changeset: -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: third change - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/backout.manual.log.out --- a/en/examples/results/backout.manual.log.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ -$ hg log --style compact -3[tip]:1 2009-03-10 04:37 +0000 bos - back out second change - -2 2009-03-10 04:37 +0000 bos - third change - -1 2009-03-10 04:37 +0000 bos - second change - -0 2009-03-10 04:37 +0000 bos - first change - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/backout.manual.merge.out --- a/en/examples/results/backout.manual.merge.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -$ hg merge -merging myfile -0 files updated, 1 files merged, 0 files removed, 0 files unresolved -(branch merge, don't forget to commit) -$ hg commit -m 'merged backout with previous tip' -$ cat myfile -first change -third change - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/backout.manual.parents.out --- a/en/examples/results/backout.manual.parents.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,7 +0,0 @@ -$ hg parents -changeset: -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: third change - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/backout.non-tip.backout.out --- a/en/examples/results/backout.non-tip.backout.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -$ echo third change >> myfile -$ hg commit -m 'third change' -$ hg backout --merge -m 'back out second change' 1 -reverting myfile -created new head -changeset backs out changeset -merging with changeset -merging myfile -0 files updated, 1 files merged, 0 files removed, 0 files unresolved -(branch merge, don't forget to commit) - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/backout.non-tip.cat.out --- a/en/examples/results/backout.non-tip.cat.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -$ cat myfile -first change -third change - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/backout.non-tip.clone.out --- a/en/examples/results/backout.non-tip.clone.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -$ cd .. -$ hg clone -r1 myrepo non-tip-repo -requesting all changes -adding changesets -adding manifests -adding file changes -added 2 changesets with 2 changes to 1 files -updating working directory -1 files updated, 0 files merged, 0 files removed, 0 files unresolved -$ cd non-tip-repo - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/backout.simple.log.out --- a/en/examples/results/backout.simple.log.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -$ hg log --style compact -2[tip] 2009-03-10 04:37 +0000 bos - back out second change - -1 2009-03-10 04:37 +0000 bos - second change - -0 2009-03-10 04:37 +0000 bos - first change - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/backout.simple.out --- a/en/examples/results/backout.simple.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -$ hg backout -m 'back out second change' tip -reverting myfile -changeset backs out changeset -$ cat myfile -first change - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/bisect.commits.out --- a/en/examples/results/bisect.commits.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ - - - - - - - - - - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/bisect.help.out --- a/en/examples/results/bisect.help.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/bisect.init.out --- a/en/examples/results/bisect.init.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ - - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/bisect.search.bad-init.out --- a/en/examples/results/bisect.search.bad-init.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ - - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/bisect.search.good-init.out --- a/en/examples/results/bisect.search.good-init.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ - - - - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/bisect.search.init.out --- a/en/examples/results/bisect.search.init.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ - - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/bisect.search.mytest.out --- a/en/examples/results/bisect.search.mytest.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ - - - - - - - - - - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/bisect.search.reset.out --- a/en/examples/results/bisect.search.reset.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ - - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/bisect.search.rest.out --- a/en/examples/results/bisect.search.rest.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/bisect.search.step1.out --- a/en/examples/results/bisect.search.step1.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/bisect.search.step2.out --- a/en/examples/results/bisect.search.step2.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ - - - - - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/branch-named.branch.out --- a/en/examples/results/branch-named.branch.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -$ hg branch -default - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/branch-named.branches.out --- a/en/examples/results/branch-named.branches.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -$ hg tip -changeset: -tag: tip -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: Initial commit - -$ hg branches -default - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/branch-named.commit.out --- a/en/examples/results/branch-named.commit.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -$ echo 'hello again' >> myfile -$ hg commit -m 'Second commit' -$ hg tip -changeset: -branch: foo -tag: tip -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: Second commit - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/branch-named.create.out --- a/en/examples/results/branch-named.create.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -$ hg branch foo -marked working directory as branch foo -$ hg branch -foo - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/branch-named.foo-commit.out --- a/en/examples/results/branch-named.foo-commit.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,20 +0,0 @@ -$ echo something > somefile -$ hg commit -A -m 'New file' -adding somefile -created new head -$ hg heads -changeset: -branch: foo -tag: tip -parent: -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: New file - -changeset: -branch: bar -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: Third commit - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/branch-named.merge.out --- a/en/examples/results/branch-named.merge.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -$ hg branch -bar -$ hg merge foo -1 files updated, 0 files merged, 0 files removed, 0 files unresolved -(branch merge, don't forget to commit) -$ hg commit -m 'Merge' -$ hg tip -changeset: -branch: bar -tag: tip -parent: -parent: -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: Merge - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/branch-named.parents.out --- a/en/examples/results/branch-named.parents.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,13 +0,0 @@ -$ hg parents -changeset: -branch: bar -tag: tip -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: Third commit - -$ hg branches -bar -foo (inactive) -default (inactive) - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/branch-named.rebranch.out --- a/en/examples/results/branch-named.rebranch.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,16 +0,0 @@ -$ hg branch -foo -$ hg branch bar -marked working directory as branch bar -$ echo new file > newfile -$ hg commit -A -m 'Third commit' -adding newfile -$ hg tip -changeset: -branch: bar -tag: tip -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: Third commit - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/branch-named.status.out --- a/en/examples/results/branch-named.status.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -$ hg status -$ hg tip -changeset: -tag: tip -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: Initial commit - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/branch-named.update-bar.out --- a/en/examples/results/branch-named.update-bar.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -$ hg update bar -1 files updated, 0 files merged, 1 files removed, 0 files unresolved - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/branch-named.update-foo.out --- a/en/examples/results/branch-named.update-foo.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,13 +0,0 @@ -$ \textbf{hg update foo} -0 files updated, 0 files merged, 1 files removed, 0 files unresolved -$ \textbf{hg update} -0 files updated, 0 files merged, 0 files removed, 0 files unresolved -$ \textbf{hg parents} -changeset: -branch: foo -user: Bryan O'Sullivan - -summary: Second commit - -$ \textbf{hg update bar} -1 files updated, 0 files merged, 0 files removed, 0 files unresolved diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/branch-named.update-nothing.out --- a/en/examples/results/branch-named.update-nothing.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -$ hg update foo -0 files updated, 0 files merged, 1 files removed, 0 files unresolved -$ hg update -0 files updated, 0 files merged, 0 files removed, 0 files unresolved - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/branch-named.update-switchy.out --- a/en/examples/results/branch-named.update-switchy.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,20 +0,0 @@ -$ hg update foo -0 files updated, 0 files merged, 1 files removed, 0 files unresolved -$ hg parents -changeset: -branch: foo -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: Second commit - -$ hg update bar -1 files updated, 0 files merged, 0 files removed, 0 files unresolved -$ hg parents -changeset: -branch: bar -tag: tip -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: Third commit - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/branch-named.update.out --- a/en/examples/results/branch-named.update.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,13 +0,0 @@ -$ \textbf{hg update foo} -0 files updated, 0 files merged, 1 files removed, 0 files unresolved -$ \textbf{hg update} -0 files updated, 0 files merged, 0 files removed, 0 files unresolved -$ \textbf{hg parent} -changeset: -branch: foo -user: Bryan O'Sullivan - -summary: Second commit - -$ \textbf{hg update bar} -1 files updated, 0 files merged, 0 files removed, 0 files unresolved diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/branch-repo.bugfix.out --- a/en/examples/results/branch-repo.bugfix.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ -$ hg clone myproject-1.0.1 my-1.0.1-bugfix -updating working directory -2 files updated, 0 files merged, 0 files removed, 0 files unresolved -$ cd my-1.0.1-bugfix -$ echo 'I fixed a bug using only echo!' >> myfile -$ hg commit -m 'Important fix for 1.0.1' -$ hg push -pushing to -searching for changes -adding changesets -adding manifests -adding file changes -added 1 changesets with 1 changes to 1 files - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/branch-repo.clone.out --- a/en/examples/results/branch-repo.clone.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -$ cd .. -$ hg clone myproject myproject-1.0.1 -updating working directory -2 files updated, 0 files merged, 0 files removed, 0 files unresolved - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/branch-repo.merge.out --- a/en/examples/results/branch-repo.merge.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -$ hg merge -1 files updated, 0 files merged, 0 files removed, 0 files unresolved -(branch merge, don't forget to commit) -$ hg commit -m 'Merge bugfix from 1.0.1 branch' -$ hg push -pushing to -searching for changes -adding changesets -adding manifests -adding file changes -added 2 changesets with 1 changes to 1 files - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/branch-repo.new.out --- a/en/examples/results/branch-repo.new.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,16 +0,0 @@ -$ cd .. -$ hg clone myproject my-feature -updating working directory -2 files updated, 0 files merged, 0 files removed, 0 files unresolved -$ cd my-feature -$ echo 'This sure is an exciting new feature!' > mynewfile -$ hg commit -A -m 'New feature' -adding mynewfile -$ hg push -pushing to -searching for changes -adding changesets -adding manifests -adding file changes -added 1 changesets with 1 changes to 1 files - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/branch-repo.pull.out --- a/en/examples/results/branch-repo.pull.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ -$ cd .. -$ hg clone myproject myproject-merge -updating working directory -3 files updated, 0 files merged, 0 files removed, 0 files unresolved -$ cd myproject-merge -$ hg pull ../myproject-1.0.1 -pulling from ../myproject-1.0.1 -searching for changes -adding changesets -adding manifests -adding file changes -added 1 changesets with 1 changes to 1 files (+1 heads) -(run 'hg heads' to see heads, 'hg merge' to merge) - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/branch-repo.tag.out --- a/en/examples/results/branch-repo.tag.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -$ cd myproject -$ hg tag v1.0 - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/branching.clone.out --- a/en/examples/results/branching.clone.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -$ cd .. -$ hg clone -rv1.0 main stable -requesting all changes -adding changesets -adding manifests -adding file changes -added 1 changesets with 1 changes to 1 files -updating working directory -1 files updated, 0 files merged, 0 files removed, 0 files unresolved - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/branching.init.out --- a/en/examples/results/branching.init.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -$ hg init main -$ cd main -$ echo 'This is a boring feature.' > myfile -$ hg commit -A -m 'We have reached an important milestone!' -adding myfile - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/branching.main.out --- a/en/examples/results/branching.main.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,7 +0,0 @@ -$ cd ../main -$ echo 'This is exciting and new!' >> myfile -$ hg commit -m 'Add a new feature' -$ cat myfile -This is a boring feature. -This is exciting and new! - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/branching.merge.out --- a/en/examples/results/branching.merge.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,18 +0,0 @@ -$ cd ../main -$ hg pull ../stable -pulling from ../stable -searching for changes -adding changesets -adding manifests -adding file changes -added 1 changesets with 1 changes to 1 files (+1 heads) -(run 'hg heads' to see heads, 'hg merge' to merge) -$ hg merge -merging myfile -0 files updated, 1 files merged, 0 files removed, 0 files unresolved -(branch merge, don't forget to commit) -$ hg commit -m 'Bring in bugfix from stable branch' -$ cat myfile -This is a fix to a boring feature. -This is exciting and new! - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/branching.stable.out --- a/en/examples/results/branching.stable.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ -$ hg clone stable stable-fix -updating working directory -1 files updated, 0 files merged, 0 files removed, 0 files unresolved -$ cd stable-fix -$ echo 'This is a fix to a boring feature.' > myfile -$ hg commit -m 'Fix a bug' -$ hg push -pushing to -searching for changes -adding changesets -adding manifests -adding file changes -added 1 changesets with 1 changes to 1 files - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/branching.tag.out --- a/en/examples/results/branching.tag.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -$ hg tag v1.0 -$ hg tip -changeset: -tag: tip -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: Added tag v1.0 for changeset - -$ hg tags -tip -v1.0 - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/branching.update.out --- a/en/examples/results/branching.update.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -$ cd .. -$ hg clone -U main main-old -$ cd main-old -$ hg update v1.0 -1 files updated, 0 files merged, 0 files removed, 0 files unresolved -$ cat myfile -This is a boring feature. - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/cmdref.diff-p.out --- a/en/examples/results/cmdref.diff-p.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -$ echo '[diff]' >> $HGRC -$ echo 'showfunc = False' >> $HGRC -$ hg diff -diff -r myfile.c - - -@@ -1,4 +1,4 @@ - int myfunc() - { -- return 1; -+ return 10; - } -$ hg diff -p -diff -r myfile.c - - -@@ -1,4 +1,4 @@ - int myfunc() - { -- return 1; -+ return 10; - } - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/daily.copy.after.out --- a/en/examples/results/daily.copy.after.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -$ cp a z -$ hg copy --after a z - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/daily.copy.cat.out --- a/en/examples/results/daily.copy.cat.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -$ cat file -line -new contents -$ cat ../my-copy/new-file -line - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/daily.copy.clone.out --- a/en/examples/results/daily.copy.clone.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -$ cd .. -$ hg clone my-copy your-copy -updating working directory -1 files updated, 0 files merged, 0 files removed, 0 files unresolved - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/daily.copy.copy.out --- a/en/examples/results/daily.copy.copy.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -$ cd my-copy -$ hg copy file new-file - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/daily.copy.dir-dest.out --- a/en/examples/results/daily.copy.dir-dest.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -$ mkdir d -$ hg copy a b d -$ ls d -a b - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/daily.copy.dir-src-dest.out --- a/en/examples/results/daily.copy.dir-src-dest.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -$ hg copy c d -copying c/a/c to d/c/a/c - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/daily.copy.dir-src.out --- a/en/examples/results/daily.copy.dir-src.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -$ hg copy c e -copying c/a/c to e/a/c - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/daily.copy.init.out --- a/en/examples/results/daily.copy.init.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -$ hg init my-copy -$ cd my-copy -$ echo line > file -$ hg add file -$ hg commit -m 'Added a file' - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/daily.copy.merge.out --- a/en/examples/results/daily.copy.merge.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,16 +0,0 @@ -$ hg pull ../my-copy -pulling from ../my-copy -searching for changes -adding changesets -adding manifests -adding file changes -added 1 changesets with 1 changes to 1 files (+1 heads) -(run 'hg heads' to see heads, 'hg merge' to merge) -$ hg merge -merging file and new-file to new-file -0 files updated, 1 files merged, 0 files removed, 0 files unresolved -(branch merge, don't forget to commit) -$ cat new-file -line -new contents - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/daily.copy.other.out --- a/en/examples/results/daily.copy.other.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -$ cd ../your-copy -$ echo 'new contents' >> file -$ hg commit -m 'Changed file' - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/daily.copy.simple.out --- a/en/examples/results/daily.copy.simple.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -$ mkdir k -$ hg copy a k -$ ls k -a - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/daily.copy.status-copy.out --- a/en/examples/results/daily.copy.status-copy.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -$ hg status -C -A new-file - file -$ hg commit -m 'Copied file' - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/daily.copy.status.out --- a/en/examples/results/daily.copy.status.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -$ hg status -A new-file - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/daily.files.add-dir.out --- a/en/examples/results/daily.files.add-dir.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -$ mkdir b -$ echo b > b/b -$ echo c > b/c -$ mkdir b/d -$ echo d > b/d/d -$ hg add b -adding b/b -adding b/c -adding b/d/d -$ hg commit -m 'Added all files in subdirectory' - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/daily.files.add.out --- a/en/examples/results/daily.files.add.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -$ hg init add-example -$ cd add-example -$ echo a > a -$ hg status -? a -$ hg add a -$ hg status -A a -$ hg commit -m 'Added one file' -$ hg status - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/daily.files.addremove.out --- a/en/examples/results/daily.files.addremove.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -$ hg init addremove-example -$ cd addremove-example -$ echo a > a -$ echo b > b -$ hg addremove -adding a -adding b - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/daily.files.commit-addremove.out --- a/en/examples/results/daily.files.commit-addremove.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -$ echo c > c -$ hg commit -A -m 'Commit with addremove' -adding c - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/daily.files.hidden.out --- a/en/examples/results/daily.files.hidden.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -$ hg init hidden-example -$ cd hidden-example -$ mkdir empty -$ touch empty/.hidden -$ hg add empty/.hidden -$ hg commit -m 'Manage an empty-looking directory' -$ ls empty -$ cd .. -$ hg clone hidden-example tmp -updating working directory -1 files updated, 0 files merged, 0 files removed, 0 files unresolved -$ ls tmp -empty -$ ls tmp/empty - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/daily.files.missing.out --- a/en/examples/results/daily.files.missing.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -$ hg init missing-example -$ cd missing-example -$ echo a > a -$ hg add a -$ hg commit -m 'File about to be missing' -$ rm a -$ hg status -! a - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/daily.files.recover-missing.out --- a/en/examples/results/daily.files.recover-missing.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -$ hg revert a -$ cat a -a -$ hg status - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/daily.files.remove-after.out --- a/en/examples/results/daily.files.remove-after.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -$ hg remove --after a -$ hg status -R a - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/daily.files.remove.out --- a/en/examples/results/daily.files.remove.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ -$ hg init remove-example -$ cd remove-example -$ echo a > a -$ mkdir b -$ echo b > b/b -$ hg add a b -adding b/b -$ hg commit -m 'Small example for file removal' -$ hg remove a -$ hg status -R a -$ hg remove b -removing b/b - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/daily.rename.rename.out --- a/en/examples/results/daily.rename.rename.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -$ hg rename a b - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/daily.rename.status-copy.out --- a/en/examples/results/daily.rename.status-copy.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -$ hg status -C -A b - a -R a - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/daily.rename.status.out --- a/en/examples/results/daily.rename.status.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -$ hg status -A b -R a - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/daily.revert.add.out --- a/en/examples/results/daily.revert.add.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -$ echo oops > oops -$ hg add oops -$ hg status oops -A oops -$ hg revert oops -$ hg status -? oops - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/daily.revert.copy.out --- a/en/examples/results/daily.revert.copy.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -$ hg copy file new-file -$ hg revert new-file -$ hg status -? new-file - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/daily.revert.missing.out --- a/en/examples/results/daily.revert.missing.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,7 +0,0 @@ -$ rm file -$ hg status -! file -$ hg revert file -$ ls file -file - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/daily.revert.modify.out --- a/en/examples/results/daily.revert.modify.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -$ cat file -original content -$ echo unwanted change >> file -$ hg diff file -diff -r file - - -@@ -1,1 +1,2 @@ - original content -+unwanted change - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/daily.revert.remove.out --- a/en/examples/results/daily.revert.remove.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -$ hg remove file -$ hg status -R file -$ hg revert file -$ hg status -$ ls file -file - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/daily.revert.rename-orig.out --- a/en/examples/results/daily.revert.rename-orig.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -$ hg revert file -no changes needed to file -$ hg status -? new-file - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/daily.revert.rename.out --- a/en/examples/results/daily.revert.rename.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -$ hg rename file new-file -$ hg revert new-file -$ hg status -? new-file - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/daily.revert.status.out --- a/en/examples/results/daily.revert.status.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -$ hg status -? file.orig -$ cat file.orig -original content -unwanted change - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/daily.revert.unmodify.out --- a/en/examples/results/daily.revert.unmodify.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -$ hg status -M file -$ hg revert file -$ cat file -original content - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/extdiff.diff.out --- a/en/examples/results/extdiff.diff.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -$ hg diff -diff -r myfile - - -@@ -1,1 +1,2 @@ - The first line. -+The second line. - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/extdiff.extdiff-ctx.out --- a/en/examples/results/extdiff.extdiff-ctx.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -$ hg extdiff -o -NprcC5 - - -*************** -*** 1 **** - - The first line. -+ The second line. - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/extdiff.extdiff.out --- a/en/examples/results/extdiff.extdiff.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,7 +0,0 @@ -$ hg extdiff - - -@@ -1 +1,2 @@ - The first line. -+The second line. - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/filenames.dirs.out --- a/en/examples/results/filenames.dirs.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -$ hg status src -? src/main.py -? src/watcher/_watcher.c -? src/watcher/watcher.py -? src/xyzzy.txt - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/filenames.files.out --- a/en/examples/results/filenames.files.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -$ hg add COPYING README examples/simple.py - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/filenames.filter.exclude.out --- a/en/examples/results/filenames.filter.exclude.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -$ hg status -X '**.py' src -? src/watcher/_watcher.c -? src/xyzzy.txt - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/filenames.filter.include.out --- a/en/examples/results/filenames.filter.include.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -$ hg status -I '*.in' -? MANIFEST.in - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/filenames.glob.group.out --- a/en/examples/results/filenames.glob.group.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -$ hg status 'glob:*.{in,py}' -? MANIFEST.in -? setup.py - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/filenames.glob.question.out --- a/en/examples/results/filenames.glob.question.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -$ hg status 'glob:**.?' -? src/watcher/_watcher.c - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/filenames.glob.range.out --- a/en/examples/results/filenames.glob.range.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -$ hg status 'glob:**[nr-t]' -? MANIFEST.in -? src/xyzzy.txt - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/filenames.glob.star-starstar.out --- a/en/examples/results/filenames.glob.star-starstar.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -$ hg status 'glob:*.py' -? setup.py -$ hg status 'glob:**.py' -A examples/simple.py -A src/main.py -? examples/performant.py -? setup.py -? src/watcher/watcher.py - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/filenames.glob.star.out --- a/en/examples/results/filenames.glob.star.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -$ hg add 'glob:*.py' -adding main.py - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/filenames.glob.starstar.out --- a/en/examples/results/filenames.glob.starstar.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -$ cd .. -$ hg status 'glob:**.py' -A examples/simple.py -A src/main.py -? examples/performant.py -? setup.py -? src/watcher/watcher.py - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/filenames.wdir-relname.out --- a/en/examples/results/filenames.wdir-relname.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -$ hg status -A COPYING -A README -A examples/simple.py -? MANIFEST.in -? examples/performant.py -? setup.py -? src/main.py -? src/watcher/_watcher.c -? src/watcher/watcher.py -? src/xyzzy.txt -$ hg status `hg root` -A ../COPYING -A ../README -A ../examples/simple.py -? ../MANIFEST.in -? ../examples/performant.py -? ../setup.py -? main.py -? watcher/_watcher.c -? watcher/watcher.py -? xyzzy.txt - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/filenames.wdir-subdir.out --- a/en/examples/results/filenames.wdir-subdir.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -$ cd src -$ hg add -n -adding ../MANIFEST.in -adding ../examples/performant.py -adding ../setup.py -adding main.py -adding watcher/_watcher.c -adding watcher/watcher.py -adding xyzzy.txt -$ hg add -n . -adding main.py -adding watcher/_watcher.c -adding watcher/watcher.py -adding xyzzy.txt - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/hook.msglen.go.out --- a/en/examples/results/hook.msglen.go.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -$ cat .hg/hgrc -[hooks] -pretxncommit.msglen = test `hg tip --template {desc} | wc -c` -ge 10 -$ echo a > a -$ hg add a -$ hg commit -A -m 'too short' -transaction abort! -rollback completed -abort: pretxncommit.msglen hook exited with status 1 -$ hg commit -A -m 'long enough' - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/hook.msglen.run.out --- a/en/examples/results/hook.msglen.run.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -$ \textbf{cat .hg/hgrc} -[hooks] -pretxncommit.msglen = test `hg tip --template \{desc\} | wc -c` -ge 10 -$ \textbf{echo a > a} -$ \textbf{hg add a} -$ \textbf{hg commit -A -m 'too short'} -abort: pretxncommit.msglen hook exited with status 1 -transaction abort! -rollback completed -$ \textbf{hg commit -A -m 'long enough'} diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/hook.simple.ext.out --- a/en/examples/results/hook.simple.ext.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -$ echo 'commit.when = echo -n "date of commit: "; date' >> .hg/hgrc -$ echo a >> a -$ hg commit -m 'i have two hooks' -committed - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/hook.simple.init.out --- a/en/examples/results/hook.simple.init.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -$ hg init hook-test -$ cd hook-test -$ echo '[hooks]' >> .hg/hgrc -$ echo 'commit = echo committed $HG_NODE' >> .hg/hgrc -$ cat .hg/hgrc -[hooks] -commit = echo committed $HG_NODE -$ echo a > a -$ hg add a -$ hg commit -m 'testing commit hook' -committed - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/hook.simple.pretxncommit.out --- a/en/examples/results/hook.simple.pretxncommit.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ -$ cat check_bug_id -#!/bin/sh -# check that a commit comment mentions a numeric bug id -hg log -r $1 --template {desc} | grep -q "\<bug *[0-9]" -$ echo 'pretxncommit.bug_id_required = ./check_bug_id $HG_NODE' >> .hg/hgrc -$ echo a >> a -$ hg commit -m 'i am not mentioning a bug id' -transaction abort! -rollback completed -abort: pretxncommit.bug_id_required hook exited with status 1 -$ hg commit -m 'i refer you to bug 666' -committed - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/hook.ws.better.out --- a/en/examples/results/hook.ws.better.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,18 +0,0 @@ -$ cat .hg/hgrc -[hooks] -pretxncommit.whitespace = .hg/check_whitespace.py -$ echo 'a ' >> a -$ hg commit -A -m 'add new line with trailing whitespace' -a, line 2: trailing whitespace added -commit message saved to .hg/commit.save -transaction abort! -rollback completed -abort: pretxncommit.whitespace hook exited with status 1 -$ sed -i 's, *$,,' a -$ hg commit -A -m 'trimmed trailing whitespace' -a, line 2: trailing whitespace added -commit message saved to .hg/commit.save -transaction abort! -rollback completed -abort: pretxncommit.whitespace hook exited with status 1 - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/hook.ws.simple.out --- a/en/examples/results/hook.ws.simple.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -$ cat .hg/hgrc -[hooks] -pretxncommit.whitespace = hg export tip | (! egrep -q '^\+.*[ \t]$') -$ echo 'a ' > a -$ hg commit -A -m 'test with trailing whitespace' -adding a -transaction abort! -rollback completed -abort: pretxncommit.whitespace hook exited with status 1 -$ echo 'a' > a -$ hg commit -A -m 'drop trailing whitespace and try again' - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/issue29.go.out --- a/en/examples/results/issue29.go.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,18 +0,0 @@ -$ hg init issue29 -$ cd issue29 -$ echo a > a -$ hg ci -Ama -adding a -$ echo b > b -$ hg ci -Amb -adding b -$ hg up 0 -0 files updated, 0 files merged, 1 files removed, 0 files unresolved -$ mkdir b -$ echo b > b/b -$ hg ci -Amc -adding b/b -created new head -$ hg merge - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/mq.dodiff.diff.out --- a/en/examples/results/mq.dodiff.diff.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ -$ echo 'this is my original thought' > oldfile -$ echo 'i have changed my mind' > newfile -$ diff -u oldfile newfile > tiny.patch -$ cat tiny.patch - - -@@ -1 +1 @@ --this is my original thought -+i have changed my mind -$ patch < tiny.patch -patching file oldfile -$ cat oldfile -i have changed my mind - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/mq.guards.init.out --- a/en/examples/results/mq.guards.init.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -$ hg qinit -$ hg qnew hello.patch -$ echo hello > hello -$ hg add hello -$ hg qrefresh -$ hg qnew goodbye.patch -$ echo goodbye > goodbye -$ hg add goodbye -$ hg qrefresh - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/mq.guards.qguard.neg.out --- a/en/examples/results/mq.guards.qguard.neg.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -$ hg qguard hello.patch -quux -$ hg qguard hello.patch -hello.patch: -quux - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/mq.guards.qguard.out --- a/en/examples/results/mq.guards.qguard.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -$ hg qguard -goodbye.patch: unguarded - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/mq.guards.qguard.pos.out --- a/en/examples/results/mq.guards.qguard.pos.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -$ hg qguard +foo -$ hg qguard -goodbye.patch: +foo - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/mq.guards.qselect.cat.out --- a/en/examples/results/mq.guards.qselect.cat.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -$ cat .hg/patches/guards -foo - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/mq.guards.qselect.error.out --- a/en/examples/results/mq.guards.qselect.error.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -$ hg qselect +foo -abort: guard '+foo' starts with invalid character: '+' - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/mq.guards.qselect.foo.out --- a/en/examples/results/mq.guards.qselect.foo.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -$ hg qpop -a -patch queue now empty -$ hg qselect -no active guards -$ hg qselect foo -number of unguarded, unapplied patches has changed from 1 to 2 -$ hg qselect -foo - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/mq.guards.qselect.foobar.out --- a/en/examples/results/mq.guards.qselect.foobar.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -$ hg qselect foo bar -number of unguarded, unapplied patches has changed from 0 to 2 -$ hg qpop -a -no patches applied -$ hg qpush -a -applying hello.patch -applying goodbye.patch -now at: goodbye.patch - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/mq.guards.qselect.qpush.out --- a/en/examples/results/mq.guards.qselect.qpush.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -$ hg qpush -a -applying hello.patch -applying goodbye.patch -now at: goodbye.patch - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/mq.guards.qselect.quux.out --- a/en/examples/results/mq.guards.qselect.quux.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,7 +0,0 @@ -$ hg qselect quux -number of guarded, applied patches has changed from 0 to 2 -$ hg qpop -a -patch queue now empty -$ hg qpush -a -patch series already fully applied - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/mq.guards.series.out --- a/en/examples/results/mq.guards.series.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -$ cat .hg/patches/series -hello.patch #-quux -goodbye.patch #+foo - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/mq.id.out.out --- a/en/examples/results/mq.id.out.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ -$ \textbf{hg qapplied} -first.patch -second.patch -$ \textbf{hg log -r qbase:qtip} -changeset: -tag: first.patch -tag: qbase -user: Bryan O'Sullivan - -summary: patch queue: first.patch - -changeset: -tag: second.patch -tag: qtip -tag: tip -user: Bryan O'Sullivan - -summary: patch queue: second.patch - -$ \textbf{hg export second.patch} -# HG changeset patch -# User Bryan O'Sullivan - -# Node ID -# Parent -patch queue: second.patch - -diff -r -r other.c - - -@@ -0,0 +1,1 @@ -+double u; diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/mq.id.output.out --- a/en/examples/results/mq.id.output.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -$ hg qapplied -first.patch -second.patch -$ hg log -r qbase:qtip -changeset: -tag: first.patch -tag: qbase -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: [mq]: first.patch - -changeset: -tag: qtip -tag: second.patch -tag: tip -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: [mq]: second.patch - -$ hg export second.patch -# HG changeset patch -# User Bryan O'Sullivan <bos@serpentine.com> - -# Node ID -# Parent -[mq]: second.patch - -diff -r -r other.c - - -@@ -0,0 +1,1 @@ -+double u; - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/mq.qinit-help.help.out --- a/en/examples/results/mq.qinit-help.help.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -$ hg help qinit -hg qinit [-c] - -init a new queue repository - - The queue repository is unversioned by default. If -c is - specified, qinit will create a separate nested repository - for patches (qinit -c may also be run later to convert - an unversioned patch repository into a versioned one). - You can use qcommit to commit changes to this queue repository. - -options: - - -c --create-repo create queue repository - -use "hg -v help qinit" to show global options - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/mq.tarball.download.out --- a/en/examples/results/mq.tarball.download.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -$ download netplug-1.2.5.tar.bz2 -$ tar jxf netplug-1.2.5.tar.bz2 -$ cd netplug-1.2.5 -$ hg init -$ hg commit -q --addremove --message netplug-1.2.5 -$ cd .. -$ hg clone netplug-1.2.5 netplug -updating working directory -18 files updated, 0 files merged, 0 files removed, 0 files unresolved - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/mq.tarball.newsource.out --- a/en/examples/results/mq.tarball.newsource.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ -$ hg qpop -a -patch queue now empty -$ cd .. -$ download netplug-1.2.8.tar.bz2 -$ hg clone netplug-1.2.5 netplug-1.2.8 -updating working directory -18 files updated, 0 files merged, 0 files removed, 0 files unresolved -$ cd netplug-1.2.8 -$ hg locate -0 | xargs -0 rm -$ cd .. -$ tar jxf netplug-1.2.8.tar.bz2 -$ cd netplug-1.2.8 -$ hg commit --addremove --message netplug-1.2.8 - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/mq.tarball.qinit.out --- a/en/examples/results/mq.tarball.qinit.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -$ cd netplug -$ hg qinit -$ hg qnew -m 'fix build problem with gcc 4' build-fix.patch -$ perl -pi -e 's/int addr_len/socklen_t addr_len/' netlink.c -$ hg qrefresh -$ hg tip -p -changeset: -tag: qtip -tag: build-fix.patch -tag: tip -tag: qbase -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: fix build problem with gcc 4 - -diff -r -r netlink.c - - -@@ -275,7 +275,7 @@ - exit(1); - } - -- int addr_len = sizeof(addr); -+ socklen_t addr_len = sizeof(addr); - - if (getsockname(fd, (struct sockaddr *) &addr, &addr_len) == -1) { - do_log(LOG_ERR, "Could not get socket details: %m"); - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/mq.tarball.repush.out --- a/en/examples/results/mq.tarball.repush.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ -$ cd ../netplug -$ hg pull ../netplug-1.2.8 -pulling from ../netplug-1.2.8 -searching for changes -adding changesets -adding manifests -adding file changes -added 1 changesets with 12 changes to 12 files -(run 'hg update' to get a working copy) -$ hg qpush -a -(working directory not at tip) -applying build-fix.patch -now at: build-fix.patch - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/mq.tools.lsdiff.out --- a/en/examples/results/mq.tools.lsdiff.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -$ lsdiff -nvv remove-redundant-null-checks.patch -22 File #1 a/drivers/char/agp/sgi-agp.c - 24 Hunk #1 static int __devinit agp_sgi_init(void) -37 File #2 a/drivers/char/hvcs.c - 39 Hunk #1 static struct tty_operations hvcs_ops = - 53 Hunk #2 static int hvcs_alloc_index_list(int n) -69 File #3 a/drivers/message/fusion/mptfc.c - 71 Hunk #1 mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, in -85 File #4 a/drivers/message/fusion/mptsas.c - 87 Hunk #1 mptsas_probe_hba_phys(MPT_ADAPTER *ioc) -98 File #5 a/drivers/net/fs_enet/fs_enet-mii.c - 100 Hunk #1 static struct fs_enet_mii_bus *create_bu -111 File #6 a/drivers/net/wireless/ipw2200.c - 113 Hunk #1 static struct ipw_fw_error *ipw_alloc_er - 126 Hunk #2 static ssize_t clear_error(struct device - 140 Hunk #3 static void ipw_irq_tasklet(struct ipw_p - 150 Hunk #4 static void ipw_pci_remove(struct pci_de -164 File #7 a/drivers/scsi/libata-scsi.c - 166 Hunk #1 int ata_cmd_ioctl(struct scsi_device *sc -178 File #8 a/drivers/video/au1100fb.c - 180 Hunk #1 void __exit au1100fb_cleanup(void) - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/mq.tools.tools.out --- a/en/examples/results/mq.tools.tools.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -$ diffstat -p1 remove-redundant-null-checks.patch - drivers/char/agp/sgi-agp.c | 5 ++--- - drivers/char/hvcs.c | 11 +++++------ - drivers/message/fusion/mptfc.c | 6 ++---- - drivers/message/fusion/mptsas.c | 3 +-- - drivers/net/fs_enet/fs_enet-mii.c | 3 +-- - drivers/net/wireless/ipw2200.c | 22 ++++++---------------- - drivers/scsi/libata-scsi.c | 4 +--- - drivers/video/au1100fb.c | 3 +-- - 8 files changed, 19 insertions(+), 38 deletions(-) -$ filterdiff -i '*/video/*' remove-redundant-null-checks.patch - - -@@ -743,8 +743,7 @@ void __exit au1100fb_cleanup(void) - { - driver_unregister(&au1100fb_driver); - -- if (drv_info.opt_mode) -- kfree(drv_info.opt_mode); -+ kfree(drv_info.opt_mode); - } - - module_init(au1100fb_init); - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/mq.tutorial.add.out --- a/en/examples/results/mq.tutorial.add.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -$ echo 'file 3, line 1' >> file3 -$ hg qnew add-file3.patch -$ hg qnew -f add-file3.patch -abort: patch "add-file3.patch" already exists - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/mq.tutorial.qinit.out --- a/en/examples/results/mq.tutorial.qinit.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -$ hg init mq-sandbox -$ cd mq-sandbox -$ echo 'line 1' > file1 -$ echo 'another line 1' > file2 -$ hg add file1 file2 -$ hg commit -m'first change' -$ hg qinit - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/mq.tutorial.qnew.out --- a/en/examples/results/mq.tutorial.qnew.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,21 +0,0 @@ -$ hg tip -changeset: -tag: tip -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: first change - -$ hg qnew first.patch -$ hg tip -changeset: -tag: qtip -tag: first.patch -tag: tip -tag: qbase -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: [mq]: first.patch - -$ ls .hg/patches -first.patch series status - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/mq.tutorial.qnew2.out --- a/en/examples/results/mq.tutorial.qnew2.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -$ hg qnew second.patch -$ hg log --style=compact --limit=2 -2[qtip,second.patch,tip] 2009-03-10 04:38 +0000 bos - [mq]: second.patch - -1[first.patch,qbase] 2009-03-10 04:38 +0000 bos - [mq]: first.patch - -$ echo 'line 4' >> file1 -$ hg qrefresh -$ hg tip --style=compact --patch -2[qtip,second.patch,tip] 2009-03-10 04:38 +0000 bos - [mq]: second.patch - -diff -r -r file1 - - -@@ -1,3 +1,4 @@ - line 1 - line 2 - line 3 -+line 4 - -$ hg annotate file1 -0: line 1 -1: line 2 -1: line 3 -2: line 4 - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/mq.tutorial.qpop.out --- a/en/examples/results/mq.tutorial.qpop.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -$ hg qapplied -first.patch -second.patch -$ hg qpop -now at: first.patch -$ hg qseries -first.patch -second.patch -$ hg qapplied -first.patch -$ cat file1 -line 1 -line 2 -line 3 - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/mq.tutorial.qpush-a.out --- a/en/examples/results/mq.tutorial.qpush-a.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -$ hg qpush -a -applying second.patch -now at: second.patch -$ cat file1 -line 1 -line 2 -line 3 -line 4 - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/mq.tutorial.qrefresh.out --- a/en/examples/results/mq.tutorial.qrefresh.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -$ echo 'line 2' >> file1 -$ hg diff -diff -r file1 - - -@@ -1,1 +1,2 @@ - line 1 -+line 2 -$ hg qrefresh -$ hg diff -$ hg tip --style=compact --patch -1[qtip,first.patch,tip,qbase] 2009-03-10 04:38 +0000 bos - [mq]: first.patch - -diff -r -r file1 - - -@@ -1,1 +1,2 @@ - line 1 -+line 2 - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/mq.tutorial.qrefresh2.out --- a/en/examples/results/mq.tutorial.qrefresh2.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -$ echo 'line 3' >> file1 -$ hg status -M file1 -$ hg qrefresh -$ hg tip --style=compact --patch -1[qtip,first.patch,tip,qbase] 2009-03-10 04:38 +0000 bos - [mq]: first.patch - -diff -r -r file1 - - -@@ -1,1 +1,3 @@ - line 1 -+line 2 -+line 3 - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/mq.tutorial.qseries.out --- a/en/examples/results/mq.tutorial.qseries.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,7 +0,0 @@ -$ hg qseries -first.patch -second.patch -$ hg qapplied -first.patch -second.patch - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/rename.divergent.clone.out --- a/en/examples/results/rename.divergent.clone.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,7 +0,0 @@ -$ hg clone orig anne -updating working directory -1 files updated, 0 files merged, 0 files removed, 0 files unresolved -$ hg clone orig bob -updating working directory -1 files updated, 0 files merged, 0 files removed, 0 files unresolved - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/rename.divergent.merge.out --- a/en/examples/results/rename.divergent.merge.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,27 +0,0 @@ -# See http://www.selenic.com/mercurial/bts/issue455 -$ cd ../orig -$ hg pull -u ../anne -pulling from ../anne -searching for changes -adding changesets -adding manifests -adding file changes -added 1 changesets with 1 changes to 1 files -1 files updated, 0 files merged, 1 files removed, 0 files unresolved -$ hg pull ../bob -pulling from ../bob -searching for changes -adding changesets -adding manifests -adding file changes -added 1 changesets with 1 changes to 1 files (+1 heads) -(run 'hg heads' to see heads, 'hg merge' to merge) -$ hg merge -warning: detected divergent renames of foo to: - bar - quux -1 files updated, 0 files merged, 0 files removed, 0 files unresolved -(branch merge, don't forget to commit) -$ ls -bar quux - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/rename.divergent.rename.anne.out --- a/en/examples/results/rename.divergent.rename.anne.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -$ cd anne -$ hg mv foo bar -$ hg ci -m 'Rename foo to bar' - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/rename.divergent.rename.bob.out --- a/en/examples/results/rename.divergent.rename.bob.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -$ cd ../bob -$ hg mv foo quux -$ hg ci -m 'Rename foo to quux' - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/rollback.add.out --- a/en/examples/results/rollback.add.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -$ hg add b -$ hg commit -m 'Add file b, this time for real' - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/rollback.commit.out --- a/en/examples/results/rollback.commit.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -$ hg status -M a -$ echo b > b -$ hg commit -m 'Add file b' - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/rollback.rollback.out --- a/en/examples/results/rollback.rollback.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,13 +0,0 @@ -$ hg rollback -rolling back last transaction -$ hg tip -changeset: -tag: tip -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: First commit - -$ hg status -M a -? b - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/rollback.status.out --- a/en/examples/results/rollback.status.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -$ hg status -? b -$ hg tip -changeset: -tag: tip -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: Add file b - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/rollback.tip.out --- a/en/examples/results/rollback.tip.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/rollback.twice.out --- a/en/examples/results/rollback.twice.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -$ hg rollback -rolling back last transaction -$ hg rollback -no rollback information available - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tag.init.out --- a/en/examples/results/tag.init.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -$ hg init mytag -$ cd mytag -$ echo hello > myfile -$ hg commit -A -m 'Initial commit' -adding myfile - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tag.log.out --- a/en/examples/results/tag.log.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ -$ hg log -changeset: -tag: tip -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: Added tag v1.0 for changeset - -changeset: -tag: v1.0 -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: Initial commit - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tag.log.v1.0.out --- a/en/examples/results/tag.log.v1.0.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -$ echo goodbye > myfile2 -$ hg commit -A -m 'Second commit' -adding myfile2 -$ hg log -r v1.0 -changeset: -tag: v1.0 -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: Initial commit - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tag.remove.out --- a/en/examples/results/tag.remove.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -$ hg tag --remove v1.0 -$ hg tags -tip - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tag.replace.out --- a/en/examples/results/tag.replace.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -$ hg tag -r 1 v1.1 -$ hg tags -tip -v1.1 -$ hg tag -r 2 v1.1 -abort: tag 'v1.1' already exists (use -f to force) -$ hg tag -f -r 2 v1.1 -$ hg tags -tip -v1.1 - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tag.tag.out --- a/en/examples/results/tag.tag.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -$ hg tag v1.0 - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tag.tags.out --- a/en/examples/results/tag.tags.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -$ hg tags -tip -v1.0 - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tag.tip.out --- a/en/examples/results/tag.tip.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -$ hg tip -changeset: -tag: tip -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: Added tag v1.1 for changeset - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/template.simple.changelog.out --- a/en/examples/results/template.simple.changelog.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/template.simple.combine.out --- a/en/examples/results/template.simple.combine.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,7 +0,0 @@ - - - - - - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/template.simple.compact.out --- a/en/examples/results/template.simple.compact.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/template.simple.datekeyword.out --- a/en/examples/results/template.simple.datekeyword.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ - - - - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/template.simple.keywords.out --- a/en/examples/results/template.simple.keywords.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/template.simple.manyfilters.out --- a/en/examples/results/template.simple.manyfilters.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/template.simple.normal.out --- a/en/examples/results/template.simple.normal.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ - - - - - - - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/template.simple.rev.out --- a/en/examples/results/template.simple.rev.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ - - - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/template.simple.simplest.out --- a/en/examples/results/template.simple.simplest.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ - - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/template.simple.simplesub.out --- a/en/examples/results/template.simple.simplesub.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ - - - - - - - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/template.svnstyle.id.out --- a/en/examples/results/template.svnstyle.id.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -$ hg log -r0 --template '{node}' - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/template.svnstyle.result.out --- a/en/examples/results/template.svnstyle.result.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -$ hg log -r1 --style svn.style ------------------------------------------------------------------------- - -r1 | bos | - -added line to end of <<hello>> file. - -in addition, added a file with the helpful name (at least i hope that some -might consider it so) of goodbye. - ------------------------------------------------------------------------- - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/template.svnstyle.short.out --- a/en/examples/results/template.svnstyle.short.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -$ svn log -r9653 ------------------------------------------------------------------------- -r9653 | sean.hefty | 2006-09-27 14:39:55 -0700 (Wed, 27 Sep 2006) | 5 lines - -On reporting a route error, also include the status for the error, -rather than indicating a status of 0 when an error has occurred. - -Signed-off-by: Sean Hefty <sean.hefty@intel.com> - ------------------------------------------------------------------------- - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/template.svnstyle.simplest.out --- a/en/examples/results/template.svnstyle.simplest.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -$ cat svn.style -changeset = "{node|short}\n" -$ hg log -r1 --style svn.style - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/template.svnstyle.style.out --- a/en/examples/results/template.svnstyle.style.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -$ cat svn.style -header = '------------------------------------------------------------------------\n\n' -changeset = svn.template - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/template.svnstyle.syntax.error.out --- a/en/examples/results/template.svnstyle.syntax.error.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -$ hg log -r1 --style broken.style -abort: broken.style:1: parse error - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/template.svnstyle.syntax.input.out --- a/en/examples/results/template.svnstyle.syntax.input.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -$ cat broken.style -changeset = - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/template.svnstyle.template.out --- a/en/examples/results/template.svnstyle.template.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,7 +0,0 @@ -$ cat svn.template -r{rev} | {author|user} | {date|isodate} ({date|rfc822date}) - -{desc|strip|fill76} - ------------------------------------------------------------------------- - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour-merge-conflict.commit.out --- a/en/examples/results/tour-merge-conflict.commit.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -$ cat > letter.txt <<EOF -> Greetings! -> I am Bryan O'Sullivan, no relation of the former -> Nigerian dictator Sani Abacha. -> EOF -$ hg resolve -m letter.txt -$ hg commit -m 'Send me your money' -$ hg tip -changeset: -tag: tip -parent: -parent: -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: Send me your money - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour-merge-conflict.cousin.out --- a/en/examples/results/tour-merge-conflict.cousin.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -$ cd .. -$ hg clone scam scam-cousin -updating working directory -1 files updated, 0 files merged, 0 files removed, 0 files unresolved -$ cd scam-cousin -$ cat > letter.txt <<EOF -> Greetings! -> I am Shehu Musa Abacha, cousin to the former -> Nigerian dictator Sani Abacha. -> EOF -$ hg commit -m '419 scam, with cousin' - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour-merge-conflict.merge.out --- a/en/examples/results/tour-merge-conflict.merge.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,18 +0,0 @@ -$ export HGMERGE=merge -$ echo 'XXX this is broken and must be fixed' -XXX this is broken and must be fixed -$ hg merge -merging letter.txt -merge: warning: conflicts during merge -merging letter.txt failed! -0 files updated, 0 files merged, 0 files removed, 1 files unresolved -use 'hg resolve' to retry unresolved file merges -$ cat letter.txt -Greetings! -<<<<<<< /tmp/tour-merge-conflictBrdfE0/scam-merge/letter.txt -I am Shehu Musa Abacha, cousin to the former -======= -I am Alhaji Abba Abacha, son of the former ->>>>>>> /tmp/letter.txt~other.1ctEYy -Nigerian dictator Sani Abacha. - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour-merge-conflict.pull.out --- a/en/examples/results/tour-merge-conflict.pull.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -$ cd .. -$ hg clone scam-cousin scam-merge -updating working directory -1 files updated, 0 files merged, 0 files removed, 0 files unresolved -$ cd scam-merge -$ hg pull -u ../scam-son -pulling from ../scam-son -searching for changes -adding changesets -adding manifests -adding file changes -added 1 changesets with 1 changes to 1 files (+1 heads) -not updating, since new heads added -(run 'hg heads' to see heads, 'hg merge' to merge) - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour-merge-conflict.son.out --- a/en/examples/results/tour-merge-conflict.son.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -$ cd .. -$ hg clone scam scam-son -updating working directory -1 files updated, 0 files merged, 0 files removed, 0 files unresolved -$ cd scam-son -$ cat > letter.txt <<EOF -> Greetings! -> I am Alhaji Abba Abacha, son of the former -> Nigerian dictator Sani Abacha. -> EOF -$ hg commit -m '419 scam, with son' - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour-merge-conflict.wife.out --- a/en/examples/results/tour-merge-conflict.wife.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -$ cat > letter.txt <<EOF -> Greetings! -> I am Mariam Abacha, the wife of former -> Nigerian dictator Sani Abacha. -> EOF -$ hg add letter.txt -$ hg commit -m '419 scam, first draft' - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour.clone-pull.out --- a/en/examples/results/tour.clone-pull.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -$ cd .. -$ hg clone hello hello-pull -updating working directory -2 files updated, 0 files merged, 0 files removed, 0 files unresolved - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour.clone-push.out --- a/en/examples/results/tour.clone-push.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -$ cd .. -$ hg clone hello hello-push -updating working directory -2 files updated, 0 files merged, 0 files removed, 0 files unresolved - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour.clone.out --- a/en/examples/results/tour.clone.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -$ hg clone http://hg.serpentine.com/tutorial/hello -destination directory: hello -requesting all changes -adding changesets -adding manifests -adding file changes -added 5 changesets with 5 changes to 2 files -updating working directory -2 files updated, 0 files merged, 0 files removed, 0 files unresolved - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour.commit.out --- a/en/examples/results/tour.commit.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -$ hg commit - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour.diff.out --- a/en/examples/results/tour.diff.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -$ hg diff -diff -r hello.c - - -@@ -8,5 +8,6 @@ - int main(int argc, char **argv) - { - printf("hello, world!\"); -+ printf("hello again!\n"); - return 0; - } - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour.help.out --- a/en/examples/results/tour.help.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,20 +0,0 @@ -$ hg help init -hg init [-e CMD] [--remotecmd CMD] [DEST] - -create a new repository in the given directory - - Initialize a new repository in the given directory. If the given - directory does not exist, it is created. - - If no directory is given, the current directory is used. - - It is possible to specify an ssh:// URL as the destination. - See 'hg help urls' for more information. - -options: - - -e --ssh specify ssh command to use - --remotecmd specify hg command to run on the remote side - -use "hg -v help init" to show global options - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour.incoming.out --- a/en/examples/results/tour.incoming.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -$ cd hello-pull -$ hg incoming ../my-hello -comparing with ../my-hello -searching for changes -changeset: -tag: tip -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: Added an extra line of output - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour.log-r.out --- a/en/examples/results/tour.log-r.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -$ hg log -r 3 -changeset: -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: Get make to generate the final binary from a .o file. - -$ hg log -r -changeset: -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: Get make to generate the final binary from a .o file. - -$ hg log -r 1 -r 4 -changeset: -user: mpm@selenic.com - -summary: Create a makefile - -changeset: -tag: tip -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: Trim comments. - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour.log-v.out --- a/en/examples/results/tour.log-v.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -$ hg log -v -r 3 -changeset: -user: Bryan O'Sullivan <bos@serpentine.com> - -files: Makefile -description: -Get make to generate the final binary from a .o file. - - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour.log-vp.out --- a/en/examples/results/tour.log-vp.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -$ hg log -v -p -r 2 -changeset: -user: Bryan O'Sullivan <bos@serpentine.com> - -files: hello.c -description: -Introduce a typo into hello.c. - - -diff -r -r hello.c - - -@@ -11,6 +11,6 @@ - - int main(int argc, char **argv) - { -- printf("hello, world!\n"); -+ printf("hello, world!\"); - return 0; - } - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour.log.out --- a/en/examples/results/tour.log.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -$ hg log -changeset: -tag: tip -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: Trim comments. - -changeset: -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: Get make to generate the final binary from a .o file. - -changeset: -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: Introduce a typo into hello.c. - -changeset: -user: mpm@selenic.com - -summary: Create a makefile - -changeset: -user: mpm@selenic.com - -summary: Create a standard "hello, world" program - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour.log.range.out --- a/en/examples/results/tour.log.range.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,18 +0,0 @@ -$ hg log -r 2:4 -changeset: -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: Introduce a typo into hello.c. - -changeset: -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: Get make to generate the final binary from a .o file. - -changeset: -tag: tip -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: Trim comments. - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour.ls-a.out --- a/en/examples/results/tour.ls-a.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -$ cd hello -$ ls -a -. .. .hg Makefile hello.c - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour.ls.out --- a/en/examples/results/tour.ls.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -$ ls -l - - -$ ls hello -Makefile hello.c - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour.merge.cat.out --- a/en/examples/results/tour.merge.cat.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -$ cat hello.c -/* - * Placed in the public domain by Bryan O'Sullivan. This program is - * not covered by patents in the United States or other countries. - */ - -#include <stdio.h> - -int main(int argc, char **argv) -{ - printf("once more, hello.\n"); - printf("hello, world!\"); - return 0; -} -$ cat ../my-hello/hello.c -/* - * Placed in the public domain by Bryan O'Sullivan. This program is - * not covered by patents in the United States or other countries. - */ - -#include <stdio.h> - -int main(int argc, char **argv) -{ - printf("hello, world!\"); - printf("hello again!\n"); - return 0; -} - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour.merge.clone.out --- a/en/examples/results/tour.merge.clone.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -$ cd .. -$ hg clone hello my-new-hello -updating working directory -2 files updated, 0 files merged, 0 files removed, 0 files unresolved -$ cd my-new-hello -$ sed -i '/printf/i\\tprintf("once more, hello.\\n");' hello.c -$ hg commit -m 'A new hello for a new day.' - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour.merge.commit.out --- a/en/examples/results/tour.merge.commit.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -$ hg commit -m 'Merged changes' - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour.merge.heads.out --- a/en/examples/results/tour.merge.heads.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ -$ hg heads -changeset: -tag: tip -parent: -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: Added an extra line of output - -changeset: -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: A new hello for a new day. - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour.merge.merge.out --- a/en/examples/results/tour.merge.merge.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -$ hg merge -merging hello.c -0 files updated, 1 files merged, 0 files removed, 0 files unresolved -(branch merge, don't forget to commit) - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour.merge.parents.out --- a/en/examples/results/tour.merge.parents.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -$ hg parents -changeset: -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: A new hello for a new day. - -changeset: -tag: tip -parent: -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: Added an extra line of output - -$ cat hello.c -/* - * Placed in the public domain by Bryan O'Sullivan. This program is - * not covered by patents in the United States or other countries. - */ - -#include <stdio.h> - -int main(int argc, char **argv) -{ - printf("once more, hello.\n"); - printf("hello, world!\"); - printf("hello again!\n"); - return 0; -} - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour.merge.pull.out --- a/en/examples/results/tour.merge.pull.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -$ hg pull ../my-hello -pulling from ../my-hello -searching for changes -adding changesets -adding manifests -adding file changes -added 1 changesets with 1 changes to 1 files (+1 heads) -(run 'hg heads' to see heads, 'hg merge' to merge) - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour.merge.tip.out --- a/en/examples/results/tour.merge.tip.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -$ hg tip -changeset: -tag: tip -parent: -parent: -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: Merged changes - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour.merge.update.out --- a/en/examples/results/tour.merge.update.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -$ hg update -abort: crosses branches (use 'hg merge' or 'hg update -C') - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour.older.out --- a/en/examples/results/tour.older.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -$ hg update 2 -2 files updated, 0 files merged, 0 files removed, 0 files unresolved -$ hg parents -changeset: -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: Introduce a typo into hello.c. - -$ hg update -2 files updated, 0 files merged, 0 files removed, 0 files unresolved - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour.outgoing.net.out --- a/en/examples/results/tour.outgoing.net.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -$ hg outgoing http://hg.serpentine.com/tutorial/hello -comparing with http://hg.serpentine.com/tutorial/hello -searching for changes -changeset: -tag: tip -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: Added an extra line of output - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour.outgoing.out --- a/en/examples/results/tour.outgoing.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -$ cd my-hello -$ hg outgoing ../hello-push -comparing with ../hello-push -searching for changes -changeset: -tag: tip -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: Added an extra line of output - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour.parents.out --- a/en/examples/results/tour.parents.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -$ hg parents -changeset: -tag: tip -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: Added an extra line of output - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour.pull.out --- a/en/examples/results/tour.pull.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -$ hg tip -changeset: -tag: tip -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: Trim comments. - -$ hg pull ../my-hello -pulling from ../my-hello -searching for changes -adding changesets -adding manifests -adding file changes -added 1 changesets with 1 changes to 1 files -(run 'hg update' to get a working copy) -$ hg tip -changeset: -tag: tip -user: Bryan O'Sullivan <bos@serpentine.com> - -summary: Added an extra line of output - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour.push.net.out --- a/en/examples/results/tour.push.net.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -$ hg push http://hg.serpentine.com/tutorial/hello -pushing to http://hg.serpentine.com/tutorial/hello -searching for changes -ssl required - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour.push.nothing.out --- a/en/examples/results/tour.push.nothing.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -$ hg push ../hello-push -pushing to ../hello-push -searching for changes -no changes found - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour.push.out --- a/en/examples/results/tour.push.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -$ hg push ../hello-push -pushing to ../hello-push -searching for changes -adding changesets -adding manifests -adding file changes -added 1 changesets with 1 changes to 1 files - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour.reclone.out --- a/en/examples/results/tour.reclone.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -$ cd .. -$ hg clone hello my-hello -updating working directory -2 files updated, 0 files merged, 0 files removed, 0 files unresolved -$ cd my-hello - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour.sed.out --- a/en/examples/results/tour.sed.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -$ sed -i '/printf/a\\tprintf("hello again!\\n");' hello.c - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour.status.out --- a/en/examples/results/tour.status.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -$ ls -Makefile hello.c -$ hg status -M hello.c - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour.tip.out --- a/en/examples/results/tour.tip.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -$ hg tip -vp -changeset: -tag: tip -user: Bryan O'Sullivan <bos@serpentine.com> - -files: hello.c -description: -Added an extra line of output - - -diff -r -r hello.c - - -@@ -8,5 +8,6 @@ - int main(int argc, char **argv) - { - printf("hello, world!\"); -+ printf("hello again!\n"); - return 0; - } - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour.update.out --- a/en/examples/results/tour.update.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -$ grep printf hello.c - printf("hello, world!\"); -$ hg update tip -1 files updated, 0 files merged, 0 files removed, 0 files unresolved -$ grep printf hello.c - printf("hello, world!\"); - printf("hello again!\n"); - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/results/tour.version.out --- a/en/examples/results/tour.version.out Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,7 +0,0 @@ -$ hg version -Mercurial Distributed SCM (version ) - -Copyright (C) 2005-2008 Matt Mackall <mpm@selenic.com> and others -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/examples/run-example --- a/en/examples/run-example Fri Mar 20 17:17:55 2009 +0800 +++ b/en/examples/run-example Mon Mar 30 16:23:33 2009 +0800 @@ -134,7 +134,7 @@ self.rename_output(self.name) norm = self.name.replace(os.sep, '-') example.entities[ - '' % (norm, norm)] = 1 + '' % (norm, norm)] = 1 class shell_example(example): @@ -316,7 +316,7 @@ norm = os.path.normpath(ofp_basename) example.entities[ '' + 'SYSTEM "results/%s.lxo">' % (norm, norm)] = 1 read_hint = ofp_basename + ' ' ofp = wopen(result_name(ofp_basename + '.tmp')) diff -r 6b1577ef5135 -r 1c13ed2130a7 en/figs/feature-branches.dot --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/en/figs/feature-branches.dot Mon Mar 30 16:23:33 2009 +0800 @@ -0,0 +1,8 @@ +digraph feature_branches { + master -> crypto; + master -> filesystems; + master -> ipc; + master -> memory; + master -> network; + master -> security; +} diff -r 6b1577ef5135 -r 1c13ed2130a7 en/figs/filelog.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/en/figs/filelog.svg Mon Mar 30 16:23:33 2009 +0800 @@ -0,0 +1,373 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + .hg/store/data/README.i + + + + + README + + + + + + + + + .hg/store/data/src/hello.c.d + .hg/store/data/src/hello.c.i + + + + + src/hello.c + + + + Working directory + Repository + + diff -r 6b1577ef5135 -r 1c13ed2130a7 en/figs/metadata.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/en/figs/metadata.svg Mon Mar 30 16:23:33 2009 +0800 @@ -0,0 +1,328 @@ + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Changelog + Manifest + Filelogs + + diff -r 6b1577ef5135 -r 1c13ed2130a7 en/figs/mq-stack.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/en/figs/mq-stack.svg Mon Mar 30 16:23:33 2009 +0800 @@ -0,0 +1,270 @@ + + + + + + + + + image/svg+xml + + + + + + + prevent-compiler-reorder.patch + + namespace-cleanup.patch + + powerpc-port-fixes.patch + + report-devinfo-correctly.patch + { + { + present in series,but not applied + patches applied,changesets present + topmostapplied patch + 201ad3209902 + 126b84e593ae + a655daf15409 + e50d59aaea3a + + forbid-illegal-params.patch + + fix-memory-leak.patch + + diff -r 6b1577ef5135 -r 1c13ed2130a7 en/figs/revlog.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/en/figs/revlog.svg Mon Mar 30 16:23:33 2009 +0800 @@ -0,0 +1,1155 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + Second parent + 32bf9a5f22c0 + + + + Revision hash + 34b8b7a15ea1 + + + + ... + Revision data (delta or snapshot) + + + + + + + First parent + 000000000000 + + + + Second parent + 000000000000 + + + + + Revision hash + ff9dc8bc2a8b + + + + ... + Revision data (delta or snapshot) + + + + + + + First parent + 34b8b7a15ea1 + + + + Second parent + 000000000000 + + + + Revision hash + 1b67dc96f27a + + + + ... + Revision data (delta or snapshot) + + + + + + + + First parent + ff9dc8bc2a8b + + + + Second parent + 000000000000 + + + + Revision hash + 5b80c922ebdd + + + + ... + Revision data (delta or snapshot) + + + + + + + First parent + ecacb6b4c9fd + + + + Second parent + 000000000000 + + + + Revision hash + 32bf9a5f22c0 + + + + ... + Revision data (delta or snapshot) + + + + + + First parent + ff9dc8bc2a8b + + + + Second parent + 000000000000 + + + + Revision hash + ecacb6b4c9fd + + + + ... + Revision data (delta or snapshot) + + + + + + + Head revision(no children) + Merge revision(two parents) + Branches(two revisions,same parent) + + + First revision(both parents null) + + First parent + 5b80c922ebdd + + + + + diff -r 6b1577ef5135 -r 1c13ed2130a7 en/figs/snapshot.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/en/figs/snapshot.svg Mon Mar 30 16:23:33 2009 +0800 @@ -0,0 +1,202 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + Index, rev 7 + + Revlog index (.i file) + Revlog data (.d file) + + + Snapshot, rev 4 + + Delta, rev 4 to 5 + + Delta, rev 5 to 6 + + Delta, rev 6 to 7 + + Delta, rev 2 to 3 + + diff -r 6b1577ef5135 -r 1c13ed2130a7 en/figs/throbber.gif Binary file en/figs/throbber.gif has changed diff -r 6b1577ef5135 -r 1c13ed2130a7 en/figs/tour-history.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/en/figs/tour-history.svg Mon Mar 30 16:23:33 2009 +0800 @@ -0,0 +1,289 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + 0: REV0 + + 1: REV1 + + 2: REV2 + + 3: REV3 + + 4: REV4 + + + + + + (newest) + (oldest) + + 4: REV4 + + + revisionnumber + changesetidentifier + + diff -r 6b1577ef5135 -r 1c13ed2130a7 en/figs/tour-merge-conflict.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/en/figs/tour-merge-conflict.svg Mon Mar 30 16:23:33 2009 +0800 @@ -0,0 +1,210 @@ + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + Greetings!I am Mariam Abacha, the wife of former Nigerian dictator Sani Abacha. I am contacting you in confidence, and as a means of developing + + + + + + Greetings!I am Shehu Musa Abacha, cousin to the former Nigerian dictator Sani Abacha. I am contacting you in confidence, and as a means of developing + + + + + + Greetings!I am Alhaji Abba Abacha, son of the former Nigerian dictator Sani Abacha. I am contacting you in confidence, and as a means of developing + + + Base version + Our changes + Their changes + + diff -r 6b1577ef5135 -r 1c13ed2130a7 en/figs/tour-merge-merge.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/en/figs/tour-merge-merge.svg Mon Mar 30 16:23:33 2009 +0800 @@ -0,0 +1,380 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + 4: REV4 + + + 5: REV_my_new_hello + + + 6: REV6_my_new_hello + + tip (and head) + head + + + + merge + working directoryduring merge + + 4: REV4 + + + 5: REV_my_new_hello + + + 6: REV6_my_new_hello + + tip + + + 7: REV7_my_new_hello + Working directory during merge + Repository after merge committed + + diff -r 6b1577ef5135 -r 1c13ed2130a7 en/figs/tour-merge-pull.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/en/figs/tour-merge-pull.svg Mon Mar 30 16:23:33 2009 +0800 @@ -0,0 +1,288 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + 0: REV0 + + 1: REV1 + + 2: REV2 + + 3: REV3 + + 4: REV4 + + + + + + 5: REV_my_new_hello + + + 6: REV6_my_new_hello + + tip (and head) + head + + diff -r 6b1577ef5135 -r 1c13ed2130a7 en/figs/tour-merge-sep-repos.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/en/figs/tour-merge-sep-repos.svg Mon Mar 30 16:23:33 2009 +0800 @@ -0,0 +1,466 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + 0: REV0 + + 1: REV1 + + 2: REV2 + + 3: REV3 + + 4: REV4 + + + + + + 5: REV_my_hello + + my-hello + + 0: REV0 + + 1: REV1 + + 2: REV2 + + 3: REV3 + + 4: REV4 + + + + + + 5: REV_my_new_hello + + my-new-hello + newest changesdiffer + common history + + + + + + + head revision(has no children) + + diff -r 6b1577ef5135 -r 1c13ed2130a7 en/figs/undo-manual-merge.dot --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/en/figs/undo-manual-merge.dot Mon Mar 30 16:23:33 2009 +0800 @@ -0,0 +1,8 @@ +digraph undo_manual { + "first change" -> "second change"; + "second change" -> "third change"; + backout [label="back out\nsecond change", shape=box]; + "second change" -> backout; + "third change" -> "manual\nmerge"; + backout -> "manual\nmerge"; +} diff -r 6b1577ef5135 -r 1c13ed2130a7 en/figs/undo-manual.dot --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/en/figs/undo-manual.dot Mon Mar 30 16:23:33 2009 +0800 @@ -0,0 +1,6 @@ +digraph undo_manual { + "first change" -> "second change"; + "second change" -> "third change"; + backout [label="back out\nsecond change", shape=box]; + "second change" -> backout; +} diff -r 6b1577ef5135 -r 1c13ed2130a7 en/figs/undo-non-tip.dot --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/en/figs/undo-non-tip.dot Mon Mar 30 16:23:33 2009 +0800 @@ -0,0 +1,9 @@ +digraph undo_non_tip { + "first change" -> "second change"; + "second change" -> "third change"; + backout [label="back out\nsecond change", shape=box]; + "second change" -> backout; + merge [label="automated\nmerge", shape=box]; + "third change" -> merge; + backout -> merge; +} diff -r 6b1577ef5135 -r 1c13ed2130a7 en/figs/undo-simple.dot --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/en/figs/undo-simple.dot Mon Mar 30 16:23:33 2009 +0800 @@ -0,0 +1,4 @@ +digraph undo_simple { + "first change" -> "second change"; + "second change" -> "back out\nsecond change"; +} diff -r 6b1577ef5135 -r 1c13ed2130a7 en/figs/wdir-after-commit.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/en/figs/wdir-after-commit.svg Mon Mar 30 16:23:33 2009 +0800 @@ -0,0 +1,394 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + dfbbb33f3fa3 + + + e7639888bb2f + + 7b064d8bac5e + + + + 000000000000 + + History in repository + + + + dfbbb33f3fa3 + + + + 000000000000 + + First parent + Second parent + Parents of working directory + + + Newchangeset + + diff -r 6b1577ef5135 -r 1c13ed2130a7 en/figs/wdir-branch.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/en/figs/wdir-branch.svg Mon Mar 30 16:23:33 2009 +0800 @@ -0,0 +1,418 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + e7639888bb2f + + + + 7b064d8bac5e + + + + 000000000000 + + + + + ffb20e1701ea + + + + 000000000000 + + First parent + Second parent + Parents of working directory + + + + + ffb20e1701ea + + + Pre-existing head + Newly created head (and tip) + + + + diff -r 6b1577ef5135 -r 1c13ed2130a7 en/figs/wdir-merge.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/en/figs/wdir-merge.svg Mon Mar 30 16:23:33 2009 +0800 @@ -0,0 +1,425 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + 7b064d8bac5e + + + + 000000000000 + + + + + ffb20e1701ea + + + + e7639888bb2f + + First parent (unchanged) + Second parent + Parents of working directory + + + + + ffb20e1701ea + + + Pre-existing head + Newly created head (and tip) + + + + + + e7639888bb2f + + + diff -r 6b1577ef5135 -r 1c13ed2130a7 en/figs/wdir-pre-branch.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/en/figs/wdir-pre-branch.svg Mon Mar 30 16:23:33 2009 +0800 @@ -0,0 +1,364 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + e7639888bb2f + + + 7b064d8bac5e + + + + 000000000000 + + History in repository + + + + 7b064d8bac5e + + + + 000000000000 + + First parent + Second parent + Parents of working directory + + + + diff -r 6b1577ef5135 -r 1c13ed2130a7 en/figs/wdir.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/en/figs/wdir.svg Mon Mar 30 16:23:33 2009 +0800 @@ -0,0 +1,348 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + e7639888bb2f + + 7b064d8bac5e + + + 000000000000 + + + History in repository + + + + + e7639888bb2f + + + + 000000000000 + + First parent + Second parent + + Parents of working directory + + + + diff -r 6b1577ef5135 -r 1c13ed2130a7 en/images/feature-branches.dot --- a/en/images/feature-branches.dot Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -digraph feature_branches { - master -> crypto; - master -> filesystems; - master -> ipc; - master -> memory; - master -> network; - master -> security; -} diff -r 6b1577ef5135 -r 1c13ed2130a7 en/images/filelog.svg --- a/en/images/filelog.svg Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,373 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - .hg/store/data/README.i - - - - - README - - - - - - - - - .hg/store/data/src/hello.c.d - .hg/store/data/src/hello.c.i - - - - - src/hello.c - - - - Working directory - Repository - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/images/kdiff3.png Binary file en/images/kdiff3.png has changed diff -r 6b1577ef5135 -r 1c13ed2130a7 en/images/metadata.svg --- a/en/images/metadata.svg Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,328 +0,0 @@ - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Changelog - Manifest - Filelogs - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/images/mq-stack.svg --- a/en/images/mq-stack.svg Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,270 +0,0 @@ - - - - - - - - - image/svg+xml - - - - - - - prevent-compiler-reorder.patch - - namespace-cleanup.patch - - powerpc-port-fixes.patch - - report-devinfo-correctly.patch - { - { - present in series,but not applied - patches applied,changesets present - topmostapplied patch - 201ad3209902 - 126b84e593ae - a655daf15409 - e50d59aaea3a - - forbid-illegal-params.patch - - fix-memory-leak.patch - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/images/note.png Binary file en/images/note.png has changed diff -r 6b1577ef5135 -r 1c13ed2130a7 en/images/revlog.svg --- a/en/images/revlog.svg Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1155 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - Second parent - 32bf9a5f22c0 - - - - Revision hash - 34b8b7a15ea1 - - - - ... - Revision data (delta or snapshot) - - - - - - - First parent - 000000000000 - - - - Second parent - 000000000000 - - - - - Revision hash - ff9dc8bc2a8b - - - - ... - Revision data (delta or snapshot) - - - - - - - First parent - 34b8b7a15ea1 - - - - Second parent - 000000000000 - - - - Revision hash - 1b67dc96f27a - - - - ... - Revision data (delta or snapshot) - - - - - - - - First parent - ff9dc8bc2a8b - - - - Second parent - 000000000000 - - - - Revision hash - 5b80c922ebdd - - - - ... - Revision data (delta or snapshot) - - - - - - - First parent - ecacb6b4c9fd - - - - Second parent - 000000000000 - - - - Revision hash - 32bf9a5f22c0 - - - - ... - Revision data (delta or snapshot) - - - - - - First parent - ff9dc8bc2a8b - - - - Second parent - 000000000000 - - - - Revision hash - ecacb6b4c9fd - - - - ... - Revision data (delta or snapshot) - - - - - - - Head revision(no children) - Merge revision(two parents) - Branches(two revisions,same parent) - - - First revision(both parents null) - - First parent - 5b80c922ebdd - - - - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/images/snapshot.svg --- a/en/images/snapshot.svg Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,202 +0,0 @@ - - - - - - - - - image/svg+xml - - - - - - - - - - Index, rev 7 - - Revlog index (.i file) - Revlog data (.d file) - - - Snapshot, rev 4 - - Delta, rev 4 to 5 - - Delta, rev 5 to 6 - - Delta, rev 6 to 7 - - Delta, rev 2 to 3 - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/images/tour-history.svg --- a/en/images/tour-history.svg Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,289 +0,0 @@ - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - 0: REV0 - - 1: REV1 - - 2: REV2 - - 3: REV3 - - 4: REV4 - - - - - - (newest) - (oldest) - - 4: REV4 - - - revisionnumber - changesetidentifier - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/images/tour-merge-conflict.svg --- a/en/images/tour-merge-conflict.svg Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,210 +0,0 @@ - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - Greetings!I am Mariam Abacha, the wife of former Nigerian dictator Sani Abacha. I am contacting you in confidence, and as a means of developing - - - - - - Greetings!I am Shehu Musa Abacha, cousin to the former Nigerian dictator Sani Abacha. I am contacting you in confidence, and as a means of developing - - - - - - Greetings!I am Alhaji Abba Abacha, son of the former Nigerian dictator Sani Abacha. I am contacting you in confidence, and as a means of developing - - - Base version - Our changes - Their changes - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/images/tour-merge-merge.svg --- a/en/images/tour-merge-merge.svg Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,380 +0,0 @@ - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - 4: REV4 - - - 5: REV_my_new_hello - - - 6: REV6_my_new_hello - - tip (and head) - head - - - - merge - working directoryduring merge - - 4: REV4 - - - 5: REV_my_new_hello - - - 6: REV6_my_new_hello - - tip - - - 7: REV7_my_new_hello - Working directory during merge - Repository after merge committed - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/images/tour-merge-pull.svg --- a/en/images/tour-merge-pull.svg Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,288 +0,0 @@ - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - 0: REV0 - - 1: REV1 - - 2: REV2 - - 3: REV3 - - 4: REV4 - - - - - - 5: REV_my_new_hello - - - 6: REV6_my_new_hello - - tip (and head) - head - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/images/tour-merge-sep-repos.svg --- a/en/images/tour-merge-sep-repos.svg Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,466 +0,0 @@ - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - 0: REV0 - - 1: REV1 - - 2: REV2 - - 3: REV3 - - 4: REV4 - - - - - - 5: REV_my_hello - - my-hello - - 0: REV0 - - 1: REV1 - - 2: REV2 - - 3: REV3 - - 4: REV4 - - - - - - 5: REV_my_new_hello - - my-new-hello - newest changesdiffer - common history - - - - - - - head revision(has no children) - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/images/undo-manual-merge.dot --- a/en/images/undo-manual-merge.dot Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -digraph undo_manual { - "first change" -> "second change"; - "second change" -> "third change"; - backout [label="back out\nsecond change", shape=box]; - "second change" -> backout; - "third change" -> "manual\nmerge"; - backout -> "manual\nmerge"; -} diff -r 6b1577ef5135 -r 1c13ed2130a7 en/images/undo-manual.dot --- a/en/images/undo-manual.dot Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -digraph undo_manual { - "first change" -> "second change"; - "second change" -> "third change"; - backout [label="back out\nsecond change", shape=box]; - "second change" -> backout; -} diff -r 6b1577ef5135 -r 1c13ed2130a7 en/images/undo-non-tip.dot --- a/en/images/undo-non-tip.dot Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -digraph undo_non_tip { - "first change" -> "second change"; - "second change" -> "third change"; - backout [label="back out\nsecond change", shape=box]; - "second change" -> backout; - merge [label="automated\nmerge", shape=box]; - "third change" -> merge; - backout -> merge; -} diff -r 6b1577ef5135 -r 1c13ed2130a7 en/images/undo-simple.dot --- a/en/images/undo-simple.dot Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -digraph undo_simple { - "first change" -> "second change"; - "second change" -> "back out\nsecond change"; -} diff -r 6b1577ef5135 -r 1c13ed2130a7 en/images/wdir-after-commit.svg --- a/en/images/wdir-after-commit.svg Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,394 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - dfbbb33f3fa3 - - - e7639888bb2f - - 7b064d8bac5e - - - - 000000000000 - - History in repository - - - - dfbbb33f3fa3 - - - - 000000000000 - - First parent - Second parent - Parents of working directory - - - Newchangeset - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/images/wdir-branch.svg --- a/en/images/wdir-branch.svg Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,418 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - e7639888bb2f - - - - 7b064d8bac5e - - - - 000000000000 - - - - - ffb20e1701ea - - - - 000000000000 - - First parent - Second parent - Parents of working directory - - - - - ffb20e1701ea - - - Pre-existing head - Newly created head (and tip) - - - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/images/wdir-merge.svg --- a/en/images/wdir-merge.svg Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,425 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - 7b064d8bac5e - - - - 000000000000 - - - - - ffb20e1701ea - - - - e7639888bb2f - - First parent (unchanged) - Second parent - Parents of working directory - - - - - ffb20e1701ea - - - Pre-existing head - Newly created head (and tip) - - - - - - e7639888bb2f - - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/images/wdir-pre-branch.svg --- a/en/images/wdir-pre-branch.svg Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,364 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - e7639888bb2f - - - 7b064d8bac5e - - - - 000000000000 - - History in repository - - - - 7b064d8bac5e - - - - 000000000000 - - First parent - Second parent - Parents of working directory - - - - diff -r 6b1577ef5135 -r 1c13ed2130a7 en/images/wdir.svg --- a/en/images/wdir.svg Fri Mar 20 17:17:55 2009 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,348 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - e7639888bb2f - - 7b064d8bac5e - - - 000000000000 - - - History in repository - - - - - e7639888bb2f - - - - 000000000000 - - First parent - Second parent - - Parents of working directory - - - - diff -r 6b1577ef5135 -r 1c13ed2130a7 stylesheets/base-html-stylesheet.xsl --- a/stylesheets/base-html-stylesheet.xsl Fri Mar 20 17:17:55 2009 +0800 +++ b/stylesheets/base-html-stylesheet.xsl Mon Mar 30 16:23:33 2009 +0800 @@ -106,7 +106,7 @@ -
+

Want to stay up to date? Subscribe to the comment feed for this chapter, or the entire book.

Copyright 2006, 2007, 2008, 2009 Bryan O'Sullivan. Icons by Paul Davey aka Mattahan.

diff -r 6b1577ef5135 -r 1c13ed2130a7 web/README --- a/web/README Fri Mar 20 17:17:55 2009 +0800 +++ b/web/README Mon Mar 30 16:23:33 2009 +0800 @@ -1,5 +1,5 @@ This directory contains web-related files. Surprise! javascript - files used by the comment system, based on jQuery -rwh - Django app that acts as the comment back end +hgbook - Django app that acts as the comment back end styles.css - style file diff -r 6b1577ef5135 -r 1c13ed2130a7 web/genindex.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/genindex.py Mon Mar 30 16:23:33 2009 +0800 @@ -0,0 +1,60 @@ +#!/usr/bin/env python + +import glob, os, re + +chapter_re = re.compile(r'<(chapter|appendix|preface)\s+id="([^"]+)">') +filename_re = re.compile(r'<\?dbhtml filename="([^"]+)"\?>') +title_re = re.compile(r'(.*)') + +chapters = glob.glob('../en/ch*.xml') + glob.glob('../en/app*.xml') + +fp = open('index-read.html.in', 'w') + +print >> fp, ''' +{% extends "boilerplate.html" %} +{% block bodycontent %} + +
    ''' + +ch = 0 +app = 0 +ab = 0 +for c in chapters: + filename = None + title = None + chapid = None + chaptype = None + for line in open(c): + m = chapter_re.search(line) + if m: + chaptype, chapid = m.groups() + m = filename_re.search(line) + if m: + filename = m.group(1) + m = title_re.search(line) + if m: + title = m.group(1) + if filename and title and chapid: + if chaptype == 'appendix': + num = chr(ord('A') + app) + app += 1 + else: + num = ch + ch += 1 + ab += 1 + date = os.popen('hg log -l1 --template "{date|isodate}" ' + c).read().split(None, 1)[0] + args = { + 'ab': "ab"[ab % 2], + 'date': date, + 'chapid': chapid, + 'num': num, + 'filename': filename, + 'title': title, + } + print >> fp, '
  • %(date)s%(num)s. %(title)s
  • ' % args + break + +print >> fp, '''
+{% endblock %}''' + +fp.close() diff -r 6b1577ef5135 -r 1c13ed2130a7 web/hgbook.conf --- a/web/hgbook.conf Fri Mar 20 17:17:55 2009 +0800 +++ b/web/hgbook.conf Mon Mar 30 16:23:33 2009 +0800 @@ -1,7 +1,7 @@ # -*- apache -*- - ServerName www.hgbook.org + ServerName hgbook.red-bean.com ServerAdmin bos@serpentine.com ErrorLog logs/hgbook-error_log # Debian: @@ -12,10 +12,33 @@ DirectoryIndex index.html.var index.html DocumentRoot "/home/bos/hg/hgbook/en/html" + Redirect permanent /hgbook.html /index.html + Redirect permanent /hgbookch1.html /read/preface.html + Redirect permanent /hgbookch2.html /read/a-tour-of-mercurial-the-basics.html + Redirect permanent /hgbookch3.html /read/a-tour-of-mercurial-merging-work.html + Redirect permanent /hgbookch4.html /read/behind-the-scenes.html + Redirect permanent /hgbookch5.html /read/mercurial-in-daily-use.html + Redirect permanent /hgbookch6.html /read/file-names-and-pattern-matching.html + Redirect permanent /hgbookch6.html /read/managing-releases-and-branchy-development.html + Redirect permanent /hgbookch7.html /read/finding-and-fixing-mistakes.html + Redirect permanent /hgbookch8.html /read/handling-repository-events-with-hooks.html + Redirect permanent /hgbookch9.html /read/customizing-the-output-of-mercurial.html + Redirect permanent /hgbookch10.html /read/managing-change-with-mercurial-queues.html + Redirect permanent /hgbookch11.html /read/advanced-uses-of-mercurial-queues.html + Redirect permanent /hgbookch12.html /read/adding-functionality-with-extensions.html + Redirect permanent /hgbookap1.html /read/command-reference.html + Redirect permanent /hgbookap2.html /read/mercurial-queues-reference.html + Redirect permanent /hgbookap3.html /read/installing-mercurial-from-source.html + Redirect permanent /hgbookap4.html /read/open-publication-license.html + Redirect permanent /hgbookli1.html /read/index.html + Redirect permanent /hgbookli2.html /read/index.html + Redirect permanent /hgbookli3.html /read/index.html + Redirect permanent /hgbookli4.html /read/index.html + # Actively redirect requests via a ServerAlias to the canonical hostname. RewriteEngine On - RewriteCond %{HTTP_HOST} !=www.hgbook.org - RewriteRule ^(.*) http://www.hgbook.org$1 [R] + RewriteCond %{HTTP_HOST} !=hgbook.red-bean.com + RewriteRule ^(.*) http://hgbook.red-bean.com$1 [R] SetHandler python-program diff -r 6b1577ef5135 -r 1c13ed2130a7 web/hgbook/reviewers.py --- a/web/hgbook/reviewers.py Fri Mar 20 17:17:55 2009 +0800 +++ b/web/hgbook/reviewers.py Mon Mar 30 16:23:33 2009 +0800 @@ -52,7 +52,7 @@ total = 0 for r in c.fetchall(): r = r[0].decode('utf-8') - if r in ("Bryan O'Sullivan", 'John Goerzen', 'Don Stewart'): + if r in ("Bryan O'Sullivan",): continue total += 1 m = mappings.get(r.lower()) diff -r 6b1577ef5135 -r 1c13ed2130a7 web/hgbook/templates/boilerplate.html --- a/web/hgbook/templates/boilerplate.html Fri Mar 20 17:17:55 2009 +0800 +++ b/web/hgbook/templates/boilerplate.html Mon Mar 30 16:23:33 2009 +0800 @@ -1,7 +1,7 @@ - {% block pagetitle %}Real World Haskell{% endblock %} + {% block pagetitle %}Mercurial: The Definitive Guide{% endblock %} @@ -18,10 +18,8 @@ up to date? Subscribe to comment feeds for any chapter, or the entire book.

Copyright - 2007, 2008 Bryan O'Sullivan, Don Stewart, and John Goerzen. This - work is licensed under a Creative - Commons Attribution-Noncommercial 3.0 License. Icons by + 2006, 2007, 2008, 2009 Bryan O'Sullivan. + Icons by Paul Davey aka Mattahan.

diff -r 6b1577ef5135 -r 1c13ed2130a7 web/index.html diff -r 6b1577ef5135 -r 1c13ed2130a7 web/index.html.in --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/index.html.in Mon Mar 30 16:23:33 2009 +0800 @@ -0,0 +1,65 @@ + +{% extends "boilerplate.html" %} + +{% block bodycontent %} + + +
+

Welcome to Mercurial: The Definitive Guide

+ +

This is the online home of the book “Mercurial: The + Definitive Guide”. + It will be published in 2009 by O'Reilly Media.

+ +

I make the content freely available + online. If you like it, please make a note to buy a copy!

+ +

For news updates, please + visit my blog.

+ +

You can contribute!

+ +

I publish the source + code for this book as a Mercurial repository. Please feel + welcome to clone it, make modifications to your copy, and send me + changes.

+ +

The online version of the book includes a comment system + that you can use to send feedback involving errors, omissions, and + suggestions.

+ +

(If you would like to adapt the comment system for a + publishing project of your own, the source for the web application + is included with the book source at the link above.)

+ +

What is Mercurial?

+ +

Mercurial is a + fast, lightweight source control management system + designed for easy and efficient handling of very large distributed + projects.

+ +

How I help Mercurial and free software, and you can too

+ +

Mercurial is a member of the Software Freedom Conservancy, a + wonderful non-profit organisation that offers its member projects + legal and administrative advice.

+ +

I am donating my royalties from the sales of this book (once it is + published) to the Software Freedom Conservancy, and I encourage + you to support their work, too.

+ +

The SFC can + accept accept + donations (tax-free under IRS 501(c)(3), within the United + States) on behalf of its member projects. If you would like to + support Mercurial directly, please consider making a donation to + the SFC on its behalf.

+ +

If you would like to help free software developers to provide + their important public services without being impeded by legal + issues, please consider donating to the SFC's sister organisation, + the Software Freedom Law + Center.

+
+{% endblock %} diff -r 6b1577ef5135 -r 1c13ed2130a7 web/styles.css --- a/web/styles.css Fri Mar 20 17:17:55 2009 +0800 +++ b/web/styles.css Mon Mar 30 16:23:33 2009 +0800 @@ -269,7 +269,7 @@ color: darkred; } -.rwhfooter { +.hgfooter { width: 60em; margin-left: auto; margin-right: auto; @@ -279,14 +279,14 @@ color: #727272; } -.rwhfooter a { +.hgfooter a { color: #5555ff; } -.rwhfooter a:visited { +.hgfooter a:visited { opacity: 0.7; } -.rwhfooter img { +.hgfooter img { vertical-align: -45%; } diff -r 6b1577ef5135 -r 1c13ed2130a7 web/texpand.py --- a/web/texpand.py Fri Mar 20 17:17:55 2009 +0800 +++ b/web/texpand.py Mon Mar 30 16:23:33 2009 +0800 @@ -7,7 +7,7 @@ from django.template import Context, TemplateDoesNotExist from django.template.loader import get_template, get_template_from_string from django.core.management import setup_environ -import rwh.settings as settings +import hgbook.settings as settings import sys setup_environ(settings)