Commits

Romain Pelisse committed 1dd00ab Merge

merge with bryan - it's been a while but everything seems ok

Comments (0)

Files changed (756)

-[^/]+/auto/
-[^/]+/dist/
-[^/]+/html/
+[^/]+/htdocs/
 
 syntax: glob
 
-beta/*.tex
-build_id.tex
-hg_id.tex
-*.4[ct][ct]
-*.aux
-*.bbl
-*.bib
-*.blg
-*.dvi
-*.eps
+*-tmp.*
 *.err
-*.idx
-*.ilg
-*.ind
-*.lg
-*.lo[fgt]
 *.lxo
+*.mo
 *.orig
 *.out
-*.pdf
+*.bb
 *.png
-*.ps
+*.pyc
 *.rej
 *.run
-*.tmp
-*.toc
-*.xref
 *~
-.*.swp
+.*.sw[op]
 .\#*
 .run
+.validated-00book.xml
+Makefile.vars
+build
+en/all-ids.dat
+en/complete.xml
+en/examples/results
+en/html
+en/svn
+stylesheets/system-xsl
+tools
+web/hgbook/.database.sqlite3
+web/hgbook/secrets.py
+web/index-read.html.in
+xsl/system-xsl
+18131160f7ee3b81bf39ce2c58f762b8d671cef3 submitted
+#
+# Makefile for the hgbook, top-level
+#
+include Makefile.vars
+
+FORMATS=html html-single pdf epub
+
+PO_LANGUAGES := zh
+DBK_LANGUAGES := en
+LANGUAGES := $(DBK_LANGUAGES) $(PO_LANGUAGES)
+
+UPDATEPO = PERLLIB=$(PO4A_LIB) $(PO4A_HOME)/po4a-updatepo -M UTF-8 \
+	   -f docbook -o doctype=docbook -o includeexternal \
+	   -o nodefault="<programlisting> <screen>" \
+	   -o untranslated="<programlisting> <screen>"
+TRANSLATE = PERLLIB=$(PO4A_LIB) $(PO4A_HOME)/po4a-translate -M UTF-8 \
+	   -f docbook -o doctype=docbook -o includeexternal \
+	   -o nodefault="<programlisting> <screen>" \
+	   -o untranslated="<programlisting> <screen>" \
+	   -k 0
+
+#rev_id = $(shell hg parents --template '{node|short} ({date|isodate})')
+rev_id = $(shell hg parents --template '{node|short} ({date|shortdate})')
+
+images := \
+	en/figs/bad-merge-1.png \
+	en/figs/bad-merge-2.png \
+	en/figs/bad-merge-3.png \
+	en/figs/bad-merge-4.png \
+	en/figs/bad-merge-5.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 epub         [LINGUA=en|zh|...]"
+	@echo "  make html         [LINGUA=en|zh|...]"
+	@echo "  make html-single  [LINGUA=en|zh|...]"
+	@echo "  make pdf          [LINGUA=en|zh|...]"
+	@echo "  make validate     [LINGUA=en|zh|...] # always before commit!"
+	@echo "  make tidypo       [LINGUA=zh|...]    # always before commit!"
+	@echo "  make updatepo     [LINGUA=zh|...]    # update po files."
+	@echo "  make all          [LINGUA=en|zh|...]"
+	@echo "  make stat         # print statistics about po files."
+	@echo "  make clean        # Remove the build files."
+
+clean:
+	@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 \
+          web/index-read.html.in \
+          en/figs/bad-merge-1.png \
+          en/figs/bad-merge-2.png \
+          en/figs/bad-merge-3.png \
+          en/figs/bad-merge-4.png \
+          en/figs/bad-merge-5.png \
+          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
+	for f in $(FORMATS); do \
+	  $(MAKE) LINGUA=$(LINGUA) $$f; \
+	done
+else
+	for l in $(LANGUAGES); do \
+	    for f in $(FORMATS); do \
+		$(MAKE) LINGUA=$$l $$f; \
+	    done; \
+	done
+endif
+
+stat:
+	@( \
+	LANG=C; export LANG; cd po; \
+	for f in *.po; do \
+	    printf "%s\t" $$f; \
+	    msgfmt --statistics -c $$f; \
+	done; \
+	)
+
+tidypo:
+ifdef LINGUA
+	msgcat --sort-by-file --width=80 po/$(LINGUA).po > po/$(LINGUA).tmp && \
+	    mv po/$(LINGUA).tmp po/$(LINGUA).po;
+else
+	for po in $(wildcard po/*.po); do \
+	    msgcat --sort-by-file --width=80 $$po > $$po.tmp && mv $$po.tmp $$po; \
+	done
+endif
+
+ifndef LINGUA
+updatepo:
+	for l in $(PO_LANGUAGES); do \
+	    $(MAKE) $@ LINGUA=$$l; \
+	done
+else
+updatepo:
+ifneq "$(findstring $(LINGUA),$(PO_LANGUAGES))" ""
+	(cd po; \
+	$(UPDATEPO) -m ../en/00book.xml -p $(LINGUA).po; \
+	)
+	$(MAKE) tidypo LINGUA=$(LINGUA)
+endif
+endif
+
+ifndef LINGUA
+validate:
+	for l in $(LANGUAGES); do \
+	    $(MAKE) $@ LINGUA=$$l; \
+	done
+else
+validate: build/$(LINGUA)/source/hgbook.xml
+	xmllint --nonet --noout --postvalid --xinclude $<
+
+ifneq "$(findstring $(LINGUA),$(DBK_LANGUAGES))" ""
+$(LINGUA)/examples/.run:
+	(cd $(LINGUA)/examples; ./run-example -v -a)
+
+build/$(LINGUA)/source/hgbook.xml: $(wildcard $(LINGUA)/*.xml) $(images) $(LINGUA)/examples/.run
+	mkdir -p build/$(LINGUA)/source/figs
+	cp $(LINGUA)/figs/*.png build/$(LINGUA)/source/figs
+	cp stylesheets/hgbook.css build/$(LINGUA)/source
+	(cd $(LINGUA); xmllint --nonet --noent --xinclude --postvalid --output ../$@.tmp 00book.xml)
+	cat $@.tmp | sed 's/\$$rev_id\$$/${rev_id}/' > $@
+else
+en/examples/.run:
+	(cd en/examples; ./run-example -v -a)
+
+build/en/source/hgbook.xml:
+	${MAKE} LINGUA=en $@
+
+build/$(LINGUA)/source/hgbook.xml: $(wildcard en/*.xml) po/$(LINGUA).po $(images)
+	mkdir -p build/$(LINGUA)/source/figs
+	cp en/figs/*.png build/$(LINGUA)/source/figs
+	cp stylesheets/hgbook.css build/$(LINGUA)/source
+	$(TRANSLATE) -m en/00book.xml -p po/$(LINGUA).po -l en/hgbook.xml.$(LINGUA)
+	xmllint --nonet --noent --xinclude --postvalid --output $@.tmp en/hgbook.xml.$(LINGUA)
+	cat $@.tmp | sed 's/\$$rev_id\$$/${rev_id}/' > $@
+	mv en/hgbook.xml.$(LINGUA) build/$(LINGUA)/source
+endif
+
+endif
+
+ifndef LINGUA
+epub:
+	for l in $(LANGUAGES); do \
+	    $(MAKE) $@ LINGUA=$$l; \
+	done
+else
+epub: build/$(LINGUA)/epub/hgbook.epub
+
+build/$(LINGUA)/epub/hgbook.epub: build/$(LINGUA)/source/hgbook.xml
+	mkdir -p build/$(LINGUA)/epub
+	(cd build/$(LINGUA)/source; $(DB2EPUB) -c hgbook.css -v hgbook.xml; mv hgbook.epub ../epub)
+endif
+
+ifndef LINGUA
+html:
+	for l in $(LANGUAGES); do \
+	    $(MAKE) $@ LINGUA=$$l; \
+	done
+else
+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/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
+endif
+
+ifndef LINGUA
+html-single:
+	for l in $(LANGUAGES); do \
+	    $(MAKE) $@ LINGUA=$$l; \
+	done
+else
+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/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
+endif
+
+ifndef LINGUA
+pdf:
+	for l in $(LANGUAGES); do \
+	    $(MAKE) $@ LINGUA=$$l; \
+	done
+else
+pdf: build/$(LINGUA)/pdf/hgbook.pdf
+
+build/$(LINGUA)/pdf/hgbook.pdf: build/$(LINGUA)/source/hgbook.xml stylesheets/fo.xsl stylesheets/$(LINGUA)/fo.xsl
+	mkdir -p build/$(LINGUA)/pdf
+	java -classpath $(JAVA_LIB)/saxon65.jar:$(JAVA_LIB)/saxon65-dbxsl.jar:$(JAVA_LIB)/xml-commons-resolver-1.2.jar:$(JAVA_LIB) \
+	    com.icl.saxon.StyleSheet \
+	    -x org.apache.xml.resolver.tools.ResolvingXMLReader \
+	    -y org.apache.xml.resolver.tools.ResolvingXMLReader \
+	    -r org.apache.xml.resolver.tools.CatalogResolver \
+	    -o build/$(LINGUA)/source/hgbook.fo \
+	    build/$(LINGUA)/source/hgbook.xml \
+	    stylesheets/$(LINGUA)/fo.xsl \
+	    fop1.extensions=1
+
+	(cd build/$(LINGUA)/source && $(FOP_HOME)/fop.sh -c $(FOP_HOME)/conf/userconfig.xml hgbook.fo ../pdf/hgbook.pdf)
+endif
+
+en/figs/%.png: en/figs/%.svg en/fixsvg
+	en/fixsvg $<
+	inkscape -D -d 120 -e $@ $<-tmp.svg
+
+en/figs/%.svg: en/figs/%.dot
+	dot -Tsvg -o $@ $<

Makefile.vars.tmpl

+#
+# Please create your Makefile.vars file from this template file.
+#
+# Please use absolute path, DO NOT use relative path !
+#
+
+# po4a (>= 0.36.1): Only for PO based Makefile !
+# po4A_HOME=/usr/bin
+# PO4A_LIB=/usr/share/perl5
+PO4A_HOME=/home/dongsheng/var/svn/i18n-zh/trunk/lib/po4a
+PO4A_LIB=$(PO4A_HOME)/lib
+
+# saxon65.jar, saxon65-dbxsl.jar, xml-commons-resolver-1.2.jar: Only for pdf format !
+JAVA_LIB=/home/dongsheng/var/svn/i18n-zh/trunk/lib/share/java
+
+# fop (>= 0.9.6): Only for pdf format !
+FOP_HOME=/home/dongsheng/var/svn/i18n-zh/trunk/lib/fop
+
+# docbook-xsl (>= 1.74.3): Only for ePub format !
+DB2EPUB=/home/dongsheng/var/svn/i18n-zh/trunk/lib/docbook/docbook-xsl/epub/bin/dbtoepub
+Mercurial: The Definitive Guide
+-------------------------------
+
+Welcome to the source code for the book.  You can clone the definitive
+copy of the source tree using Mercurial as follows:
+
+  hg clone http://hg.serpentine.com/mercurial/book
+
+Here's a top-level tour of interesting directories:
+
+en        English-language content
+es        Spanish-language content
+examples  Miscellaneous example scripts
+tools     Old, largely unused conversion scripts
+web       Content and comment system for http://hgbook.red-bean.com/
+xsl       XSLT scripts for generating HTML
+HOW-TO:  Compiling the Mercurial Book
+======================================
+
+This Mercurial Book is written in DocBook 4.5.
+
+The goal of this document is to give simple instructions to anyone who
+wants to compile this book into a useful format, like HTML or PDF.  It
+should state *exactly* which tools to use, and how to invoke them, in
+simplest terms.
+
+Table of Contents:
+
+  I. PRIMER
+ II. COMPILING THE DOCS
+III. HACKING ON THE DOCS
+
+I. PRIMER
+
+  DocBook has a tortured, confusing history.  Before you do anything,
+  take a look at Eric Raymond's excellent "DocBook Demystification HOWTO":
+
+      http://tldp.org/HOWTO/DocBook-Demystification-HOWTO/
+
+  It's very short and clears up many things.
+
+
+II. COMPILING THE DOCS
+
+
+1. Install XML DTD and XSL stylesheets for DocBook
+
+      % sudo apt-get install docbook-xml docbook-xsl
+
+2. Install libxml2-utils
+
+      % sudo apt-get install libxml2-utils
+
+3. Install graph drawing tools
+
+      % sudo apt-get install graphviz inkscape
+
+4. Install pdf support
+
+      % sudo apt-get install openjdk-6-jdk docbook-xsl-saxon libsaxon-java fop
+
+  The Makefile will actually invoke tools/fop/fop.sh, you should do
+  some trick, let fop's CLASSPATH include saxon.jar and docbook-xsl-saxon.jar .
+
+5. Make
+  Run 'make' for more details, for example:
+
+  * make all document(pdf, html and html-single for all languages)
+      % make all
+
+  * make english document(pdf, html and html-single for all languages)
+      % make LINGUA=en all
+
+  * make Chinese document(pdf, html and html-single for all languages)
+      % make LINGUA=zh all
+
+  * make Chinese pdf document
+      % make LINGUA=zh pdf
+
+III. HACKING ON THE DOCS
+
+In addition to everything in section II:
+
+
+1. Get a nice editing environment for SGML/XML.
+
+  This isn't strictly required, but it's nice when your editor
+  colorizes things, understands the DTD, tells you what tags you can
+  insert, etc.
+
+  If you use emacs, we recommend the PSGML major-mode.  Most free
+  operating systems package it, or its home page is here:
+
+      http://www.lysator.liu.se/projects/about_psgml.html
+
+  If you use vim, you might check out xmledit, at:
+
+      http://www.vim.org/scripts/script.php?script_id=301
+
+
+2. Get a validating parser.
+
+  Actually, if you have what you need to compile the documentation,
+  then you almost certainly have an XML validator installed already -
+  it is called xmllint, and comes as part of libxml2.
+
+  The makefile is preconfigured with a suitable invocation of it,
+  so simply run:
+
+      $ make validate
+
+3. Read about DocBook.
+
+  You'll want to get real intimate with a DocBook reference, such as
+  can be found at:  http://www.docbook.org/tdg/en/html/

contrib/hg-interdiff

+#!/usr/bin/env python
+#
+# Adapter for using interdiff with mercurial's extdiff extension.
+#
+# Copyright 2006 Bryan O'Sullivan <bos@serpentine.com>
+#
+# This software may be used and distributed according to the terms of
+# the GNU General Public License, incorporated herein by reference.
+
+import os, sys
+
+def walk(base):
+    # yield all non-directories below the base path.
+    for root, dirs, files in os.walk(base):
+        for f in files:
+            path = os.path.join(root, f)
+            yield path[len(base)+1:], path
+    else:
+        if os.path.isfile(base):
+            yield '', base
+
+# create list of unique file names under both directories.
+files = dict(walk(sys.argv[1]))
+files.update(walk(sys.argv[2]))
+files = files.keys()
+files.sort()
+
+def name(base, f):
+    if f:
+        path = os.path.join(base, f)
+    else:
+        path = base
+    # interdiff requires two files; use /dev/null if one is missing.
+    if os.path.exists(path):
+        return path
+    return '/dev/null'
+
+ret = 0
+
+for f in files:
+    if os.system('interdiff "%s" "%s"' % (name(sys.argv[1], f),
+                                          name(sys.argv[2], f))):
+        ret = 1
+
+sys.exit(ret)

contrib/hg-package

+#!/bin/sh
+
+build_dir=`dirname "$0"`/../build
+rev_id=`hg parents --template '{date|shortdate}' | sed 's/-//g'`
+
+for l in en zh; do
+  (
+  if [ ! -d "${build_dir}/${l}" ] ; then
+    continue
+  fi
+
+  cd ${build_dir}/${l};
+
+  f='html'
+  if [ -f "${f}/index.html" ] ; then
+     d=hgbook-${l}-${f}
+     rm -fr ${d} && cp -r ${f} ${d} && tar czf ../${d}-${rev_id}.tar.gz ${d}
+  fi
+
+  f='html-single'
+  if [ -f "${f}/hgbook.html" ] ; then
+     d=hgbook-${l}-${f}
+     rm -fr ${d} && cp -r ${f} ${d} && tar czf ../${d}-${rev_id}.tar.gz ${d}
+  fi
+
+  if [ -f "pdf/hgbook.pdf" ] ; then
+     cp pdf/hgbook.pdf ../hgbook-${l}-${rev_id}.pdf
+     gzip -f9 ../hgbook-${l}-${rev_id}.pdf
+  fi
+
+  if [ -f "epub/hgbook.epub" ] ; then
+     cp epub/hgbook.epub ../hgbook-${l}-${rev_id}.epub
+  fi
+  )
+done
+
+upload_pass=$1
+upload_user=$2
+
+# echo "upload_pass: ${upload_pass}"
+# echo "upload_user: ${upload_user}"
+
+if [ "${upload_user}x" == "x" ]; then
+  upload_user="dongsheng.song"
+fi
+
+if [ "${upload_pass}x" != "x" ]; then
+  (
+  cd ${build_dir}
+  curl -s -O http://support.googlecode.com/svn/trunk/scripts/googlecode_upload.py
+  if [[ "0" != $? ]]; then
+    exit 1
+  fi
+
+  for l in en zh; do
+    if [ -f "hgbook-${l}-${rev_id}.epub" ] ; then
+      python googlecode_upload.py --user="${upload_user}" --password="${upload_pass}" \
+          -p "i18n-zh" -l "Type-Docs,book,hgbook,hg,mercurial,ebook" \
+          -s "Distributed revision control with Mercurial - ${l} - ePub" \
+          hgbook-${l}-${rev_id}.epub
+    fi
+
+    if [ -f "hgbook-${l}-${rev_id}.pdf.gz" ] ; then
+      python googlecode_upload.py --user="${upload_user}" --password="${upload_pass}" \
+          -p "i18n-zh" -l "Type-Docs,book,hgbook,hg,mercurial" \
+          -s "Distributed revision control with Mercurial - ${l} - pdf" \
+          hgbook-${l}-${rev_id}.pdf.gz
+    fi
+
+    for f in html html-single; do
+      if [ -f "hgbook-${l}-${f}-${rev_id}.tar.gz" ] ; then
+        python googlecode_upload.py --user="${upload_user}" --password="${upload_pass}" \
+            -p "i18n-zh" -l "Type-Docs,book,hgbook,hg,mercurial" \
+            -s "Distributed revision control with Mercurial - ${l} - ${f}" \
+            hgbook-${l}-${f}-${rev_id}.tar.gz
+      fi
+    done
+  done
+  )
+fi

contrib/hg-replay

+#!/usr/bin/env python
+#
+# Adapter for using interdiff with mercurial's extdiff extension.
+#
+# Copyright 2006 Bryan O'Sullivan <bos@serpentine.com>
+#
+# This software may be used and distributed according to the terms of
+# the GNU General Public License, incorporated herein by reference.
+
+import os
+import shutil
+import sys
+import tempfile
+
+if len(sys.argv) < 4:
+    print >> sys.stderr, ('usage: %s srcrepo destrepo cset-to-omit [...]' %
+                          os.path.basename(sys.argv[0]))
+    sys.exit(1)
+
+srcrepo, destrepo = sys.argv[1], sys.argv[2]
+omit = sys.argv[3:]
+    
+changemap = {}
+revs = []
+
+parent = None
+
+sys.stdout.write('gathering history...')
+sys.stdout.flush()
+
+for line in os.popen("hg --cwd %r log -r0:tip --template '{rev}:{node} {parents}\n'" % srcrepo):
+    changes = line.split()
+    cset = changes[0].split(':')[1]
+    rev = len(revs)
+    changemap[cset] = rev
+    if len(changes) >= 2:
+        p1 = int(changes[1].split(':', 1)[0])
+    if len(changes) == 3:
+        p2 = int(changes[2].split(':', 1)[0])
+    else:
+        p2 = None
+    if len(changes) == 1:
+        p1 = parent
+    revs.append((cset, p1, p2))
+    parent = rev
+
+sys.stdout.write(' %d revs\n' % len(revs))
+
+def findrev(r):
+    try:
+        i = int(r)
+        if str(i) == r:
+            rev = i
+        if rev < 0:
+            rev += len(revs)
+        if rev < 0 or rev > len(revs):
+            print >> sys.stderr, 'bad changeset: %r' % r
+            sys.exit(1)
+        cset = revs[rev][0]
+    except ValueError:
+        cset = r
+        matches = [changemap[c] for c in changemap if c.startswith(cset)]
+        if len(matches) != 1:
+            print >> sys.stderr, 'bad changeset: %r' % r
+            sys.exit(1)
+        rev = matches[0]
+    return rev
+
+def run(cmd):
+    print cmd
+    ret = os.system(cmd)
+    if ret:
+        print >> sys.stderr, 'failure:', cmd
+        sys.exit(1)
+
+omit = map(findrev, omit)
+omit.sort()
+newrevs = revs[:omit[0]]
+tip = len(newrevs) - 1
+run('hg clone -q -r%s %r %r' % (tip, srcrepo, destrepo))
+    
+os.environ['HGMERGE'] = 'true'
+
+patchdir = tempfile.mkdtemp(prefix='replay.')
+try:
+    run('hg --cwd %r export --git -o %r%s%%R %d:tip' %
+        (srcrepo, patchdir, os.sep, omit[0]+1))
+    for rev in xrange(omit[0], len(revs)):
+        if rev in omit:
+            print 'omit', rev
+            newrevs.append((None, revs[rev][1], None))
+            continue
+        _, p1, p2 = revs[rev]
+        np1 = newrevs[p1][1]
+        if tip != np1:
+            run('hg --cwd %r update -q -C %s' % (destrepo, np1))
+        np2 = None
+        if p2:
+            np2 = newrevs[p2][1]
+            run('hg --cwd %r merge -q %s' % (destrepo, np2))
+            print >> sys.stderr, 'XXX - cannot handle merges properly yet'
+        run('hg --cwd %r import -q -f %r%s%d' % (destrepo, patchdir, os.sep, rev))
+        tip = len(newrevs) - 1
+        newrevs.append((None, tip, np2))
+finally:
+    print 'cleaning up ...'
+    #shutil.rmtree(patchdir)

contrib/latex-to-docbook

+#!/usr/bin/python
+#
+# This is the most horrible of hacks. Pretend you're not looking.</para>
+
+import cStringIO as StringIO
+import re, sys
+
+sections = {
+    'chapter': 'chapter',
+    'section': 'sect1',
+    'subsection': 'sect2',
+    'subsubsection': 'sect3',
+    }
+
+envs = {
+    'codesample2': 'programlisting',
+    'codesample4': 'programlisting',
+    'enumerate': 'orderedlist',
+    'figure': 'informalfigure',
+    'itemize': 'itemizedlist',
+    'note': 'note',
+    'quote': 'blockquote',
+    }
+
+def process(ifp, ofp):
+    print >> ofp, '<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->\n'
+    stack = []
+    para = True
+    inlist = 0
+    for line in ifp:
+        if line.startswith('%%% Local Variables:'):
+            break
+        line = (line.rstrip()
+                .replace('~', ' ')
+                .replace('&', '&amp;')
+                .replace('---', '&emdash;')
+                .replace('\_', '_')
+                .replace('\{', '{')
+                .replace('\}', '}')
+                .replace('\$', '$')
+                .replace('\%', '%')
+                .replace('\#', '#')
+                .replace('<', '&lt;')
+                .replace('>', '&gt;')
+                .replace('``', '<quote>')
+                .replace("''", '</quote>')
+                .replace('\\', '\\'))
+        line = re.sub(r'\s*\\(?:centering|small)\b\s*', '', line)
+        line = re.sub(r'\\(?:hgrc\\|hgrc)\b',
+                      r'<filename role="special"> /.hgrc</filename>', line)
+        line = re.sub(r'\\item\[(?P<key>[^]]+)\]', r'\item \g<key>:', line)
+        line = re.sub(r'\\bug{(?P<id>\d+)}',
+                      r'<ulink role="hg-bug" url="http://www.selenic.com/mercurial/bts/issue\g<id>">issue \g<id></ulink>', line)
+        line = re.sub(r'\\cite{([^}]+)}', r'<citation>\1</citation>', line)
+        line = re.sub(r'\\hggopt{(?P<opt>[^}]+)}',
+                      r'<option role="hg-opt-global">\g<opt></option>', line)
+        line = re.sub(r'\\hgxopt{(?P<ext>[^}]+)}{(?P<cmd>[^}]+)}{(?P<opt>[^}]+)}',
+                      r'<option role="hg-ext-\g<ext>-cmd-\g<cmd>-opt">\g<opt></option>', line)
+        line = re.sub(r'\\hgxcmd{(?P<ext>[^}]+)}{(?P<cmd>[^}]+)}',
+                      r'<command role="hg-ext-\g<ext>">\g<cmd></command>', line)
+        line = re.sub(r'\\hgext{(?P<ext>[^}]+)}',
+                      r'<literal role="hg-ext">\g<ext></literal>', line)
+        line = re.sub(r'\\hgopt{(?P<cmd>[^}]+)}{(?P<opt>[^}]+)}',
+                      r'<option role="hg-opt-\g<cmd>">\g<opt></option>',
+                      line)
+        line = re.sub(r'\\cmdopt{(?P<cmd>[^}]+)}{(?P<opt>[^}]+)}',
+                      r'<option role="cmd-opt-\g<cmd>">\g<opt></option>',
+                      line)
+        line = re.sub(r'\\hgcmd{(?P<cmd>[^}]+)}',
+                      r'<command role="hg-cmd">hg \g<cmd></command>', line)
+        line = re.sub(r'\\caption{(?P<text>[^}]+?)}',
+                      r'<caption><para>\g<text></para></caption>', line)
+        line = re.sub(r'\\grafix{(?P<name>[^}]+)}',
+                      r'<mediaobject><imageobject><imagedata fileref="\g<name>"/></imageobject><textobject><phrase>XXX add text</phrase></textobject></mediaobject>', line)
+        line = re.sub(r'\\envar{(?P<name>[^}]+)}',
+                      r'<envar>\g<name></envar>', line)
+        line = re.sub(r'\\rcsection{(?P<sect>[^}]+)}',
+                      r'<literal role="rc-\g<sect>">\g<sect></literal>', line)
+        line = re.sub(r'\\rcitem{(?P<sect>[^}]+)}{(?P<name>[^}]+)}',
+                      r'<envar role="rc-item-\g<sect>">\g<name></envar>', line)
+        line = re.sub(r'\\dirname{(?P<dir>[^}]+?)}',
+                      r'<filename class="directory">\g<dir></filename>', line)
+        line = re.sub(r'\\filename{(?P<file>[^}]+?)}',
+                      r'<filename>\g<file></filename>', line)
+        line = re.sub(r'\\tildefile{(?P<file>[^}]+)}',
+                      r'<filename role="home">~/\g<file></filename>', line)
+        line = re.sub(r'\\sfilename{(?P<file>[^}]+)}',
+                      r'<filename role="special">\g<file></filename>', line)
+        line = re.sub(r'\\sdirname{(?P<dir>[^}]+)}',
+                      r'<filename role="special" class="directory">\g<dir></filename>', line)
+        line = re.sub(r'\\interaction{(?P<id>[^}]+)}',
+                      r'<!-- &interaction.\g<id>; -->', line)
+        line = re.sub(r'\\excode{(?P<id>[^}]+)}',
+                      r'<!-- &example.\g<id>; -->', line)
+        line = re.sub(r'\\pymod{(?P<mod>[^}]+)}',
+                      r'<literal role="py-mod">\g<mod></literal>', line)
+        line = re.sub(r'\\pymodclass{(?P<mod>[^}]+)}{(?P<class>[^}]+)}',
+                      r'<literal role="py-mod-\g<mod>">\g<class></literal>', line)
+        line = re.sub(r'\\url{(?P<url>[^}]+)}',
+                      r'<ulink url="\g<url>">\g<url></ulink>', line)
+        line = re.sub(r'\\href{(?P<url>[^}]+)}{(?P<text>[^}]+)}',
+                      r'<ulink url="\g<url>">\g<text></ulink>', line)
+        line = re.sub(r'\\command{(?P<cmd>[^}]+)}',
+                      r'<command>\g<cmd></command>', line)
+        line = re.sub(r'\\option{(?P<opt>[^}]+)}',
+                      r'<option>\g<opt></option>', line)
+        line = re.sub(r'\\ref{(?P<id>[^}]+)}', r'<xref linkend="\g<id>"/>', line)
+        line = re.sub(r'\\emph{(?P<txt>[^}]+)}',
+                      r'<emphasis>\g<txt></emphasis>', line)
+        line = re.sub(r'\\texttt{(?P<txt>[^}]+)}',
+                      r'<literal>\g<txt></literal>', line)
+        line = re.sub(r'\\textbf{(?P<txt>[^}]+)}',
+                      r'<emphasis role="bold">\g<txt></emphasis>', line)
+        line = re.sub(r'\\hook{(?P<name>[^}]+)}',
+                      r'<literal role="hook">\g<name></literal>', line)
+        line = re.sub(r'\\tplfilter{(?P<name>[^}]+)}',
+                      r'<literal role="template-filter">\g<name></literal>', line)
+        line = re.sub(r'\\tplkword{(?P<name>[^}]+)}',
+                      r'<literal role="template-keyword">\g<name></literal>', line)
+        line = re.sub(r'\\tplkwfilt{(?P<tpl>[^}]+)}{(?P<name>[^}]+)}',
+                      r'<literal role="template-kw-filt-\g<tpl>">\g<name></literal>', line)
+        line = re.sub(r'\\[vV]erb(.)(?P<txt>[^\1]+?)\1',
+                      r'<literal>\g<txt></literal>', line)
+        line = re.sub(r'\\package{(?P<name>[^}]+)}',
+                      r'<literal role="package">\g<name></literal>', line)
+        line = re.sub(r'\\hgcmdargs{(?P<cmd>[^}]+)}{(?P<args>[^}]+)}',
+                      r'<command role="hg-cmd">hg \g<cmd> \g<args></command>',
+                      line)
+        line = re.sub(r'\\cmdargs{(?P<cmd>[^}]+)}{(?P<args>[^}]+)}',
+                      r'<command>\g<cmd> \g<args></command>',
+                      line)
+        m = re.match(r'\\(chapter|section|subsection|subsubsection){(.*)}', line)
+        if m:
+            kind, content = m.groups()
+            sec = sections[kind]
+            while stack and stack[-1] >= sec:
+                close = stack.pop()
+                print >> ofp, '</%s>' % close
+            stack.append(sec)
+            print >> ofp, '<%s>\n<title>%s</title>' % (sec, content)
+        else:
+            m = re.match(r'\s*\\(begin|end){(?P<sect>[^}]+)}', line)
+            if m:
+                if not para:
+                    print >> ofp, '</para>'
+                    if inlist:
+                        ofp.write('</listitem>')
+                    para = True
+                state, env = m.groups()
+                env = envs[env]
+                if state == 'begin':
+                    ofp.write('<')
+                    if env in ('itemizedlist', 'orderedlist'):
+                        inlist = 1
+                else:
+                    ofp.write('</')
+                    if env in ('itemizedlist', 'orderedlist'):
+                        inlist = 0
+                print >> ofp, env + '>'
+            else:
+                if line.startswith('\\item '):
+                    if inlist > 1:
+                        print >> ofp, '</para>'
+                        print >> ofp, '</listitem>'
+                    else:
+                        inlist = 2
+                    para = True
+                    line = line[6:]
+                if line and para:
+                    if inlist:
+                        ofp.write('<listitem>')
+                    ofp.write('<para>')
+                    para = False
+                if not line and not para:
+                    print >> ofp, '</para>'
+                    if inlist:
+                        ofp.write('</listitem>')
+                    para = True
+                print >> ofp, line
+    while stack:
+        print >> ofp, '</%s>' % stack.pop()
+    ofp.write('\n'.join(['\n<!--',
+                         'local variables: ',
+                         'sgml-parent-document: ("00book.xml" "book" "chapter")',
+                         'end:',
+                         '-->']))
+
+
+if __name__ == '__main__':
+    for name in sys.argv[1:]:
+        if not name.endswith('.tex'):
+            continue
+        newname = name[:-3] + 'xml'
+        ofp = StringIO.StringIO()
+        process(open(name), ofp)
+        s = ofp.getvalue()
+        s = re.sub('\n+</para>', '</para>', s, re.M)
+        open(newname, 'w').write(s)

contrib/sillybench.py

+#!/usr/bin/python
+#
+# Silly benchmarking program, to give a vague idea of how fast a few
+# tools are on a handful of common operations.
+#
+# Use a fairly big and real source tarball to test with: Firefox
+# 2.0.0.3 (37622 files, 5374 directories, 343MB unpacked onto
+# 4KB-blocksize ext3).
+
+import csv
+import os
+import shutil
+import sys
+import tempfile
+import time
+import urllib2
+
+url = 'ftp://ftp.mozilla.org/pub/mozilla.org/firefox/releases/2.0.0.3/source/firefox-2.0.0.3-source.tar.bz2'
+
+class CommandFailure(Exception):
+    pass
+
+class rcs(object):
+    def __init__(self):
+        self.logfp = open(self.__class__.__name__ + '.csv', 'w')
+        self.csv = csv.writer(self.logfp)
+
+    def download(self):
+        name = url[url.rfind('/')+1:]
+        path = os.path.join(os.environ['HOME'], name)
+        if not os.path.isfile(path):
+            ofp = open(path + '.part', 'wb')
+            try:
+                ifp = urllib2.urlopen(url)
+                nbytes = ifp.info()['content-length']
+                sys.stdout.write('%s: %s bytes ' % (name, nbytes))
+                sys.stdout.flush()
+                while True:
+                    data = ifp.read(131072)
+                    if not data: break
+                    sys.stdout.write('.')
+                    sys.stdout.flush()
+                    ofp.write(data)
+                del ofp
+                os.rename(path + '.part', path)
+            except:
+                if os.path.exists(path + '.part'):
+                    os.unlink(path + '.part')
+                if os.path.exists(path):
+                    os.unlink(path)
+                raise
+        return path
+
+    def run(self, args, mustsucceed=True):
+        ret = os.spawnvp(os.P_WAIT, args[0], args)
+        if ret < 0:
+            msg = 'killed by signal %d' % (-ret)
+        if ret > 0:
+            msg = 'exited with status %d' % (ret)
+        if ret:
+            if mustsucceed:
+                raise CommandFailure('%s: %s' % (msg, ' '.join(args)))
+            print >> sys.stderr, 'WARNING: %s: %s' % (msg, ' '.join(args))
+
+    def time(self, *args, **kwargs):
+        start = time.time()
+        self.run(*args, **kwargs)
+        end = time.time()
+        return end - start
+        
+    def logtime(self, name, elapsed, rest=[]):
+        self.log('time:' + name, '%.3f' % elapsed, rest)
+
+    def log(self, name, value, rest=[]):
+        item = (name, value, repr(rest))
+        print ' '.join(item)
+        self.csv.writerow(item)
+        self.logfp.flush()
+
+    def unpack(self):
+        tarball = self.download()
+        t = self.time(['tar', '-C', self.wdir, '-jxf', tarball])
+        self.logtime('internal:untar', t)
+        for name in os.listdir(os.path.join(self.wdir, 'mozilla')):
+            os.rename(os.path.join(self.wdir, 'mozilla', name),
+                      os.path.join(self.wdir, name))
+
+    def cleanup(self):
+        pass
+
+    def add(self, paths):
+        pass
+
+    def commit(self, msg, paths):
+        pass
+
+    def status(self, path):
+        pass
+
+    def remove(self, path):
+        pass
+
+
+class subversion(rcs):
+    def __init__(self, root):
+        rcs.__init__(self)
+        self.repo = os.path.join(root, 'repo')
+        self.wdir = os.path.join(root, 'wc')
+        create = self.time(['svnadmin', 'create', '--fs-type=fsfs', self.repo])
+        self.logtime('svn:create', create)
+        co = self.time(['svn', 'co', 'file://' + self.repo, self.wdir])
+        self.logtime('svn:co', co)
+        self.logtime('init', create + co)
+        os.chdir(self.wdir)
+
+    def dropmeta(self, names):
+        return [n for n in names if os.path.basename(n) != '.svn']
+
+    def add(self, paths):
+        t = self.time(['svn', 'add', '-q'] + paths)
+        self.logtime('add %r' % paths, t)
+
+    def commit(self, msg, paths=[]):
+        if paths:
+            t = self.time(['svn', 'ci', '-q', '-m', msg] + paths)
+        else:
+            t = self.time(['svn', 'ci', '-q', '-m', msg])
+        self.logtime('commit %r' % paths, t)
+
+
+class mercurial(rcs):
+    def __init__(self, root):
+        rcs.__init__(self)
+        self.repo = os.path.join(root, 'repo')
+        self.wdir = self.repo
+        init = self.time(['hg', 'init', self.repo])
+        self.logtime('init', init)
+        os.chdir(self.wdir)
+
+    def dropmeta(self, names):
+        return [n for n in names if os.path.basename(n) != '.hg']
+
+    def add(self, paths):
+        t = self.time(['hg', 'add', '-q'] + paths)
+        self.logtime('add %r' % paths, t)
+
+    def commit(self, msg, paths=[]):
+        if paths:
+            t = self.time(['hg', 'ci', '-q', '-m', msg] + paths)
+        else:
+            t = self.time(['hg', 'ci', '-q', '-m', msg])
+        self.logtime('commit %r' % paths, t)
+
+def benchmark(cls):
+    oldcwd = os.getcwd()
+    root = tempfile.mkdtemp(prefix='sillybench.')
+    try:
+        print 'root', root
+        inst = cls(root)
+        inst.unpack()
+        names = inst.dropmeta(os.listdir('.'))
+        dirs = [n for n in names if os.path.isdir(n)]
+        nondirs = [n for n in names if not os.path.isdir(n)]
+        dirs.sort(key=hash)
+        names.sort(key=hash)
+        for d in dirs[:len(dirs)/2]:
+            inst.add([d])
+            inst.commit('Add %r' % d, [d])
+        inst.add(dirs[len(dirs)/2:] + names)
+        inst.commit('Add remaining dirs and files')
+    finally:
+        print >> sys.stderr, '[cleaning up...]'
+        shutil.rmtree(root)
+        os.chdir(oldcwd)
+
+benchmark(mercurial)
+#benchmark(subversion)

en/00book.tex

-% The use of oneside here is a temporary hack; \marginpar entries
-% don't show up on odd pages of PDF output without it.  Sigh.
-\documentclass[oneside]{book}
-\usepackage{enumerate}
-\usepackage{fullpage}
-\usepackage{makeidx}
-\usepackage{ifpdf}
-\usepackage{graphicx}
-\usepackage{pslatex}
-\usepackage{fancyvrb}
-% leave hyperref until last
-\usepackage[colorlinks=true,bookmarks=true,pdftitle={Distributed
-  revision control with Mercurial},pdfsubject={Revision
-  control},pdfkeywords={Mercurial, Revision control, Distributed
-  revision control},pdfauthor={Bryan O'Sullivan}]{hyperref}
-
-\include{99defs}
-
-\title{Distributed revision control with Mercurial} \author{Bryan
-  O'Sullivan}
-\date{Copyright \copyright\ 2006, 2007 Bryan O'Sullivan.\\
-  This material may be distributed only subject to the terms and
-  conditions set forth in version 1.0 of the Open Publication License.
-  Please refer to Appendix~\ref{cha:opl} for the license text.\\
-  This book was prepared from
-  \href{http://hg.serpentine.com/mercurial/book/}{rev~\input{build_id}}
-  using \href{http://www.selenic.com/hg/}{rev~\input{hg_id}} of Mercurial.}
-
-\makeindex
-
-\begin{document}
-
-\maketitle
-
-\addcontentsline{toc}{chapter}{Contents}
-\pagenumbering{roman}
-\tableofcontents
-\listoffigures
-%\listoftables
-
-\pagenumbering{arabic}
-
-\include{preface}
-\include{intro}
-\include{tour-basic}
-\include{tour-merge}
-\include{concepts}
-\include{daily}
-\include{collab}
-\include{filenames}
-\include{branch}
-\include{undo}
-\include{hook}
-\include{template}
-\include{mq}
-\include{mq-collab}
-\include{hgext}
-
-\appendix
-\include{cmdref}
-\include{mq-ref}
-\include{srcinstall}
-\include{license}
-\addcontentsline{toc}{chapter}{Bibliography}
-\bibliographystyle{alpha}
-\bibliography{99book}
-
-\addcontentsline{toc}{chapter}{Index}
-\printindex
-
-\end{document}
-
-%%% Local Variables: 
-%%% mode: latex