changeset 8103:2a4a71b15e95

Merge with crew
author Matt Mackall <mpm@selenic.com>
date Tue, 21 Apr 2009 12:58:05 -0500
parents fc78313cba53 (current diff) 18710802cd49 (diff)
children 9269b66fc7e7
files hgext/convert/subversion.py
diffstat 25 files changed, 400 insertions(+), 313 deletions(-) [+]
line wrap: on
line diff
--- a/hgext/bookmarks.py	Sat Apr 04 20:19:51 2009 -0500
+++ b/hgext/bookmarks.py	Tue Apr 21 12:58:05 2009 -0500
@@ -93,7 +93,7 @@
     '''Set the name of the bookmark that we are currently on
 
     Set the name of the bookmark that we are on (hg update <bookmark>).
-    The name is recoreded in .hg/bookmarks.current
+    The name is recorded in .hg/bookmarks.current
     '''
     if current(repo) == mark:
         return
--- a/hgext/children.py	Sat Apr 04 20:19:51 2009 -0500
+++ b/hgext/children.py	Tue Apr 21 12:58:05 2009 -0500
@@ -16,9 +16,9 @@
     """show the children of the given or working directory revision
 
     Print the children of the working directory's revisions. If a
-    revision is given via --rev, the children of that revision will be
-    printed. If a file argument is given, revision in which the file
-    was last changed (after the working directory revision or the
+    revision is given via --rev/-r, the children of that revision will
+    be printed. If a file argument is given, revision in which the
+    file was last changed (after the working directory revision or the
     argument to --rev if given) is printed.
     """
     rev = opts.get('rev')
--- a/hgext/churn.py	Sat Apr 04 20:19:51 2009 -0500
+++ b/hgext/churn.py	Tue Apr 21 12:58:05 2009 -0500
@@ -80,7 +80,7 @@
             newpct = int(100.0 * count / max(len(repo), 1))
             if pct < newpct:
                 pct = newpct
-                ui.write(_("\rgenerating stats: %d%%") % pct)
+                ui.write("\r" + _("generating stats: %d%%") % pct)
                 sys.stdout.flush()
 
     if opts.get('progress'):
--- a/hgext/convert/cvsps.py	Sat Apr 04 20:19:51 2009 -0500
+++ b/hgext/convert/cvsps.py	Tue Apr 21 12:58:05 2009 -0500
@@ -39,6 +39,12 @@
     def __init__(self, **entries):
         self.__dict__.update(entries)
 
+    def __repr__(self):
+        return "<%s at 0x%x: %s %s>" % (self.__class__.__name__,
+                                        id(self),
+                                        self.file,
+                                        ".".join(map(str, self.revision)))
+
 class logerror(Exception):
     pass
 
@@ -428,6 +434,7 @@
 
 class changeset(object):
     '''Class changeset has the following attributes:
+        .id        - integer identifying this changeset (list index)
         .author    - author name as CVS knows it
         .branch    - name of branch this changeset is on, or None
         .comment   - commit message
@@ -441,6 +448,11 @@
     def __init__(self, **entries):
         self.__dict__.update(entries)
 
+    def __repr__(self):
+        return "<%s at 0x%x: %s>" % (self.__class__.__name__,
+                                     id(self),
+                                     getattr(self, 'id', "(no id)"))
+
 def createchangeset(ui, log, fuzz=60, mergefrom=None, mergeto=None):
     '''Convert log into changesets.'''
 
--- a/hgext/convert/monotone.py	Sat Apr 04 20:19:51 2009 -0500
+++ b/hgext/convert/monotone.py	Tue Apr 21 12:58:05 2009 -0500
@@ -112,15 +112,10 @@
                 value = value.replace(r'\"', '"')
                 value = value.replace(r'\\', '\\')
                 certs[name] = value
+        # Monotone may have subsecond dates: 2005-02-05T09:39:12.364306
+        certs["date"] = certs["date"].split('.')[0]
         return certs
 
-    def mtnrenamefiles(self, files, fromdir, todir):
-        renamed = {}
-        for tofile in files:
-            if tofile.startswith(todir + '/'):
-                renamed[tofile] = fromdir + tofile[len(todir):]
-        return renamed
-
     # implement the converter_source interface:
 
     def getheads(self):
@@ -133,15 +128,17 @@
         #revision = self.mtncmd("get_revision %s" % rev).split("\n\n")
         revision = self.mtnrun("get_revision", rev).split("\n\n")
         files = {}
+        addedfiles = {}
+        renameddirs = []
         copies = {}
         for e in revision:
             m = self.add_file_re.match(e)
             if m:
                 files[m.group(1)] = rev
+                addedfiles[m.group(1)] = rev
             m = self.patch_re.match(e)
             if m:
                 files[m.group(1)] = rev
-
             # Delete/rename is handled later when the convert engine
             # discovers an IOError exception from getfile,
             # but only if we add the "from" file to the list of changes.
@@ -156,16 +153,27 @@
                     copies[toname] = fromname
                     files[toname] = rev
                     files[fromname] = rev
-                if self.mtnisdir(toname, rev):
-                    renamed = self.mtnrenamefiles(self.files, fromname, toname)
-                    for tofile, fromfile in renamed.items():
-                        self.ui.debug (_("copying file in renamed directory "
-                                         "from '%s' to '%s'")
-                                       % (fromfile, tofile), '\n')
-                        files[tofile] = rev
-                        copies[tofile] = fromfile
-                    for fromfile in renamed.values():
-                        files[fromfile] = rev
+                elif self.mtnisdir(toname, rev):
+                    renameddirs.append((fromname, toname))
+
+        # Directory renames can be handled only once we have recorded
+        # all new files
+        for fromdir, todir in renameddirs:
+            renamed = {}
+            for tofile in self.files:
+                if tofile in addedfiles:
+                    continue
+                if tofile.startswith(todir + '/'):
+                    renamed[tofile] = fromdir + tofile[len(todir):]
+            for tofile, fromfile in renamed.items():
+                self.ui.debug (_("copying file in renamed directory "
+                                 "from '%s' to '%s'")
+                               % (fromfile, tofile), '\n')
+                files[tofile] = rev
+                copies[tofile] = fromfile
+            for fromfile in renamed.values():
+                files[fromfile] = rev
+
         return (files.items(), copies)
 
     def getmode(self, name, rev):
--- a/hgext/convert/subversion.py	Sat Apr 04 20:19:51 2009 -0500
+++ b/hgext/convert/subversion.py	Tue Apr 21 12:58:05 2009 -0500
@@ -347,7 +347,7 @@
 
         if self.startrev and self.heads:
             if len(self.heads) > 1:
-                raise util.Abort(_('svn: start revision is not supported with '
+                raise util.Abort(_('svn: start revision is not supported '
                                    'with more than one branch'))
             revnum = self.revnum(self.heads[0])
             if revnum < self.startrev:
--- a/hgext/extdiff.py	Sat Apr 04 20:19:51 2009 -0500
+++ b/hgext/extdiff.py	Tue Apr 21 12:58:05 2009 -0500
@@ -167,10 +167,10 @@
     an external program. The default program used is diff, with
     default options "-Npru".
 
-    To select a different program, use the -p option. The program will
-    be passed the names of two directories to compare. To pass
-    additional options to the program, use the -o option. These will
-    be passed before the names of the directories to compare.
+    To select a different program, use the -p/--program option. The
+    program will be passed the names of two directories to compare. To
+    pass additional options to the program, use -o/--option. These
+    will be passed before the names of the directories to compare.
 
     When two revision arguments are given, then changes are shown
     between those revisions. If only one revision is specified then
--- a/hgext/keyword.py	Sat Apr 04 20:19:51 2009 -0500
+++ b/hgext/keyword.py	Tue Apr 21 12:58:05 2009 -0500
@@ -177,7 +177,8 @@
         candidates = [f for f in files if self.iskwfile(f, ctx.flags)]
         if candidates:
             self.restrict = True # do not expand when reading
-            action = expand and 'expanding' or 'shrinking'
+            msg = (expand and _('overwriting %s expanding keywords\n')
+                   or _('overwriting %s shrinking keywords\n'))
             for f in candidates:
                 fp = self.repo.file(f)
                 data = fp.read(mf[f])
@@ -191,7 +192,7 @@
                 else:
                     found = self.re_kw.search(data)
                 if found:
-                    notify(_('overwriting %s %s keywords\n') % (f, action))
+                    notify(msg % f)
                     self.repo.wwrite(f, data, mf.flags(f))
                     self.repo.dirstate.normal(f)
             self.restrict = False
--- a/hgext/mq.py	Sat Apr 04 20:19:51 2009 -0500
+++ b/hgext/mq.py	Tue Apr 21 12:58:05 2009 -0500
@@ -1625,14 +1625,14 @@
     """remove patches from queue
 
     The patches must not be applied, unless they are arguments to the
-    --rev parameter. At least one patch or revision is required.
+    -r/--rev parameter. At least one patch or revision is required.
 
     With --rev, mq will stop managing the named revisions (converting
     them to regular mercurial changesets). The qfinish command should
-    be used as an alternative for qdel -r, as the latter option is
+    be used as an alternative for qdelete -r, as the latter option is
     deprecated.
 
-    With --keep, the patch files are preserved in the patch
+    With -k/--keep, the patch files are preserved in the patch
     directory."""
     q = repo.mq
     q.delete(repo, patches, opts)
@@ -1669,20 +1669,24 @@
     to the series.
 
     The patch will have the same name as its source file unless you
-    give it a new one with --name.
+    give it a new one with -n/--name.
 
     You can register an existing patch inside the patch directory with
-    the --existing flag.
+    the -e/--existing flag.
 
-    With --force, an existing patch of the same name will be
+    With -f/--force, an existing patch of the same name will be
     overwritten.
 
-    An existing changeset may be placed under mq control with --rev
+    An existing changeset may be placed under mq control with -r/--rev
     (e.g. qimport --rev tip -n patch will place tip under mq control).
-    With --git, patches imported with --rev will use the git diff
+    With -g/--git, patches imported with --rev will use the git diff
     format. See the diffs help topic for information on why this is
     important for preserving rename/copy information and permission
     changes.
+
+    To import a patch from standard input, pass - as the patch file.
+    When importing from standard input, a patch name must be specified
+    using the --name flag.
     """
     q = repo.mq
     q.qimport(repo, filename, patchname=opts['name'],
@@ -1694,11 +1698,11 @@
 def init(ui, repo, **opts):
     """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."""
+    The queue repository is unversioned by default. If
+    -c/--create-repo 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."""
     q = repo.mq
     r = q.init(repo, create=opts['create_repo'])
     q.save_dirty()
@@ -1841,19 +1845,21 @@
 
     qnew creates a new patch on top of the currently-applied patch (if
     any). It will refuse to run if there are any outstanding changes
-    unless -f is specified, in which case the patch will be
-    initialized with them. You may also use -I, -X, and/or a list of
-    files after the patch name to add only changes to matching files
-    to the new patch, leaving the rest as uncommitted modifications.
+    unless -f/--force is specified, in which case the patch will be
+    initialized with them. You may also use -I/--include,
+    -X/--exclude, and/or a list of files after the patch name to add
+    only changes to matching files to the new patch, leaving the rest
+    as uncommitted modifications.
 
-    -u and -d can be used to set the (given) user and date, respectively.
-    -U and -D set user to current user and date to current date.
+    -u/--user and -d/--date can be used to set the (given) user and
+    date, respectively. -U/--currentuser and -D/--currentdate set user
+    to current user and date to current date.
 
-    -e, -m or -l set the patch header as well as the commit message.
-    If none is specified, the header is empty and the commit message
-    is '[mq]: PATCH'.
+    -e/--edit, -m/--message or -l/--logfile set the patch header as
+    well as the commit message. If none is specified, the header is
+    empty and the commit message is '[mq]: PATCH'.
 
-    Use the --git option to keep the patch in the git extended diff
+    Use the -g/--git option to keep the patch in the git extended diff
     format. Read the diffs help topic for more information on why this
     is important for preserving permission changes and copy/rename
     information.
@@ -1878,13 +1884,13 @@
     contain only the modifications that match those patterns; the
     remaining modifications will remain in the working directory.
 
-    If --short is specified, files currently included in the patch
+    If -s/--short is specified, files currently included in the patch
     will be refreshed just like matched files and remain in the patch.
 
     hg add/remove/copy/rename work as usual, though you might want to
-    use git-style patches (--git or [diff] git=1) to track copies and
-    renames. See the diffs help topic for more information on the git
-    diff format.
+    use git-style patches (-g/--git or [diff] git=1) to track copies
+    and renames. See the diffs help topic for more information on the
+    git diff format.
     """
     q = repo.mq
     message = cmdutil.logmessage(opts)
@@ -2078,8 +2084,8 @@
 def push(ui, repo, patch=None, **opts):
     """push the next patch onto the stack
 
-    When --force is applied, all local changes in patched files will
-    be lost.
+    When -f/--force is applied, all local changes in patched files
+    will be lost.
     """
     q = repo.mq
     mergeq = None
@@ -2353,10 +2359,10 @@
     patches) by moving them out of mq control into regular repository
     history.
 
-    Accepts a revision range or the --applied option. If --applied is
-    specified, all applied mq revisions are removed from mq control.
-    Otherwise, the given revisions must be at the base of the stack of
-    applied patches.
+    Accepts a revision range or the -a/--applied option. If --applied
+    is specified, all applied mq revisions are removed from mq
+    control. Otherwise, the given revisions must be at the base of the
+    stack of applied patches.
 
     This can be especially useful if your changes have been applied to
     an upstream repository, or if you are about to push your changes
--- a/hgext/patchbomb.py	Sat Apr 04 20:19:51 2009 -0500
+++ b/hgext/patchbomb.py	Tue Apr 21 12:58:05 2009 -0500
@@ -46,7 +46,7 @@
 is set, your pager will be fired up once for each patchbomb message,
 so you can verify everything is alright.
 
-The "-m" (mbox) option is also very useful. Instead of previewing each
+The -m/--mbox option is also very useful. Instead of previewing each
 patchbomb message in a pager or sending the messages directly, it will
 create a UNIX mailbox file with the patch emails. This mailbox file
 can be previewed with any mail user agent which supports UNIX mbox
@@ -185,11 +185,11 @@
     program is installed, the result of running diffstat on the patch.
     Finally, the patch itself, as generated by "hg export".
 
-    With --outgoing, emails will be generated for patches not found in
-    the destination repository (or only those which are ancestors of
-    the specified revisions if any are provided)
+    With -o/--outgoing, emails will be generated for patches not found
+    in the destination repository (or only those which are ancestors
+    of the specified revisions if any are provided)
 
-    With --bundle, changesets are selected as for --outgoing, but a
+    With -b/--bundle, changesets are selected as for --outgoing, but a
     single email containing a binary Mercurial bundle as an attachment
     will be sent.
 
@@ -477,9 +477,11 @@
            _('file name of the bundle attachment')),
           ('r', 'rev', [], _('a revision to send')),
           ('', 'force', None,
-           _('run even when remote repository is unrelated (with -b)')),
+           _('run even when remote repository is unrelated '
+             '(with -b/--bundle)')),
           ('', 'base', [],
-           _('a base changeset to specify instead of a destination (with -b)')),
+           _('a base changeset to specify instead of a destination '
+             '(with -b/--bundle)')),
           ('', 'intro', None,
            _('send an introduction email for a single patch')),
          ] + emailopts + commands.remoteopts,
--- a/hgext/purge.py	Sat Apr 04 20:19:51 2009 -0500
+++ b/hgext/purge.py	Tue Apr 21 12:58:05 2009 -0500
@@ -104,7 +104,7 @@
           ('',  'all', None, _('purge ignored files too')),
           ('p', 'print', None, _('print the file names instead of deleting them')),
           ('0', 'print0', None, _('end filenames with NUL, for use with xargs'
-                                  ' (implies -p)')),
+                                  ' (implies -p/--print)')),
          ] + commands.walkopts,
          _('hg purge [OPTION]... [DIR]...'))
 }
--- a/hgext/rebase.py	Sat Apr 04 20:19:51 2009 -0500
+++ b/hgext/rebase.py	Tue Apr 21 12:58:05 2009 -0500
@@ -46,7 +46,7 @@
     changes relative to a master development tree.
 
     If a rebase is interrupted to manually resolve a merge, it can be
-    continued with --continue or aborted with --abort.
+    continued with --continue/-c or aborted with --abort/-a.
     """
     originalwd = target = None
     external = nullrev
--- a/hgext/transplant.py	Sat Apr 04 20:19:51 2009 -0500
+++ b/hgext/transplant.py	Tue Apr 21 12:58:05 2009 -0500
@@ -442,11 +442,12 @@
     Its argument will be invoked with the current changelog message as
     $1 and the patch as $2.
 
-    If --source is specified, selects changesets from the named
-    repository. If --branch is specified, selects changesets from the
-    branch holding the named revision, up to that revision. If --all
-    is specified, all changesets on the branch will be transplanted,
-    otherwise you will be prompted to select the changesets you want.
+    If --source/-s is specified, selects changesets from the named
+    repository. If --branch/-b is specified, selects changesets from
+    the branch holding the named revision, up to that revision. If
+    --all/-a is specified, all changesets on the branch will be
+    transplanted, otherwise you will be prompted to select the
+    changesets you want.
 
     hg transplant --branch REVISION --all will rebase the selected
     branch (up to the named revision) onto your current working
@@ -462,7 +463,7 @@
 
     If a changeset application fails, you can fix the merge by hand
     and then resume where you left off by calling hg transplant
-    --continue.
+    --continue/-c.
     '''
     def getremotechanges(repo, url):
         sourcerepo = ui.expandpath(url)
--- a/mercurial/commands.py	Sat Apr 04 20:19:51 2009 -0500
+++ b/mercurial/commands.py	Tue Apr 21 12:58:05 2009 -0500
@@ -287,15 +287,21 @@
     """
     def print_result(nodes, good):
         displayer = cmdutil.show_changeset(ui, repo, {})
-        transition = (good and "good" or "bad")
         if len(nodes) == 1:
             # narrowed it down to a single revision
-            ui.write(_("The first %s revision is:\n") % transition)
+            if good:
+                ui.write(_("The first good revision is:\n"))
+            else:
+                ui.write(_("The first bad revision is:\n"))
             displayer.show(repo[nodes[0]])
         else:
             # multiple possible revisions
-            ui.write(_("Due to skipped revisions, the first "
-                       "%s revision could be any of:\n") % transition)
+            if good:
+                ui.write(_("Due to skipped revisions, the first "
+                        "good revision could be any of:\n"))
+            else:
+                ui.write(_("Due to skipped revisions, the first "
+                        "bad revision could be any of:\n"))
             for n in nodes:
                 displayer.show(repo[n])
 
--- a/mercurial/manifest.py	Sat Apr 04 20:19:51 2009 -0500
+++ b/mercurial/manifest.py	Tue Apr 21 12:58:05 2009 -0500
@@ -125,7 +125,7 @@
             for f in l:
                 if '\n' in f or '\r' in f:
                     raise error.RevlogError(
-                        _("'\\n' and '\\r' disallowed in filenames"))
+                        _("'\\n' and '\\r' disallowed in filenames: %r") % f)
 
         # if we're using the listcache, make sure it is valid and
         # parented by the same node we're diffing against
--- a/mercurial/patch.py	Sat Apr 04 20:19:51 2009 -0500
+++ b/mercurial/patch.py	Tue Apr 21 12:58:05 2009 -0500
@@ -421,11 +421,12 @@
                             f = self.ui.note
                         offset = l - orig_start - fuzzlen
                         if offset == 1:
-                            linestr = "line"
+                            msg = _("Hunk #%d succeeded at %d %s"
+                                    "(offset %d line).\n")
                         else:
-                            linestr = "lines"
-                        f(_("Hunk #%d succeeded at %d %s(offset %d %s).\n") %
-                          (h.number, l+1, fuzzstr, offset, linestr))
+                            msg = _("Hunk #%d succeeded at %d %s"
+                                    "(offset %d lines).\n")
+                        f(msg % (h.number, l+1, fuzzstr, offset))
                         return fuzzlen
         self.printfile(True)
         self.ui.warn(_("Hunk #%d FAILED at %d\n") % (h.number, orig_start))
--- a/tests/run-tests.py	Sat Apr 04 20:19:51 2009 -0500
+++ b/tests/run-tests.py	Tue Apr 21 12:58:05 2009 -0500
@@ -37,8 +37,9 @@
 SKIPPED_STATUS = 80
 SKIPPED_PREFIX = 'skipped: '
 FAILED_PREFIX  = 'hghave check failed: '
+PYTHON = sys.executable
 
-required_tools = ["python", "diff", "grep", "unzip", "gunzip", "bunzip2", "sed"]
+requiredtools = ["python", "diff", "grep", "unzip", "gunzip", "bunzip2", "sed"]
 
 defaults = {
     'jobs': ('HGTEST_JOBS', 1),
@@ -46,61 +47,73 @@
     'port': ('HGTEST_PORT', 20059),
 }
 
-parser = optparse.OptionParser("%prog [options] [tests]")
-parser.add_option("-C", "--annotate", action="store_true",
-    help="output files annotated with coverage")
-parser.add_option("--child", type="int",
-    help="run as child process, summary to given fd")
-parser.add_option("-c", "--cover", action="store_true",
-    help="print a test coverage report")
-parser.add_option("-f", "--first", action="store_true",
-    help="exit on the first test failure")
-parser.add_option("-i", "--interactive", action="store_true",
-    help="prompt to accept changed output")
-parser.add_option("-j", "--jobs", type="int",
-    help="number of jobs to run in parallel"
-         " (default: $%s or %d)" % defaults['jobs'])
-parser.add_option("--keep-tmpdir", action="store_true",
-    help="keep temporary directory after running tests"
-         " (best used with --tmpdir)")
-parser.add_option("-R", "--restart", action="store_true",
-    help="restart at last error")
-parser.add_option("-p", "--port", type="int",
-    help="port on which servers should listen"
-         " (default: $%s or %d)" % defaults['port'])
-parser.add_option("-r", "--retest", action="store_true",
-    help="retest failed tests")
-parser.add_option("-s", "--cover_stdlib", action="store_true",
-    help="print a test coverage report inc. standard libraries")
-parser.add_option("-t", "--timeout", type="int",
-    help="kill errant tests after TIMEOUT seconds"
-         " (default: $%s or %d)" % defaults['timeout'])
-parser.add_option("--tmpdir", type="string",
-    help="run tests in the given temporary directory")
-parser.add_option("-v", "--verbose", action="store_true",
-    help="output verbose messages")
-parser.add_option("-n", "--nodiff", action="store_true",
-    help="skip showing test changes")
-parser.add_option("--with-hg", type="string",
-    help="test existing install at given location")
-parser.add_option("--pure", action="store_true",
-    help="use pure Python code instead of C extensions")
+def parseargs():
+    parser = optparse.OptionParser("%prog [options] [tests]")
+    parser.add_option("-C", "--annotate", action="store_true",
+        help="output files annotated with coverage")
+    parser.add_option("--child", type="int",
+        help="run as child process, summary to given fd")
+    parser.add_option("-c", "--cover", action="store_true",
+        help="print a test coverage report")
+    parser.add_option("-f", "--first", action="store_true",
+        help="exit on the first test failure")
+    parser.add_option("-i", "--interactive", action="store_true",
+        help="prompt to accept changed output")
+    parser.add_option("-j", "--jobs", type="int",
+        help="number of jobs to run in parallel"
+             " (default: $%s or %d)" % defaults['jobs'])
+    parser.add_option("--keep-tmpdir", action="store_true",
+        help="keep temporary directory after running tests"
+             " (best used with --tmpdir)")
+    parser.add_option("-R", "--restart", action="store_true",
+        help="restart at last error")
+    parser.add_option("-p", "--port", type="int",
+        help="port on which servers should listen"
+             " (default: $%s or %d)" % defaults['port'])
+    parser.add_option("-r", "--retest", action="store_true",
+        help="retest failed tests")
+    parser.add_option("-s", "--cover_stdlib", action="store_true",
+        help="print a test coverage report inc. standard libraries")
+    parser.add_option("-t", "--timeout", type="int",
+        help="kill errant tests after TIMEOUT seconds"
+             " (default: $%s or %d)" % defaults['timeout'])
+    parser.add_option("--tmpdir", type="string",
+        help="run tests in the given temporary directory")
+    parser.add_option("-v", "--verbose", action="store_true",
+        help="output verbose messages")
+    parser.add_option("-n", "--nodiff", action="store_true",
+        help="skip showing test changes")
+    parser.add_option("--with-hg", type="string",
+        help="test existing install at given location")
+    parser.add_option("--pure", action="store_true",
+        help="use pure Python code instead of C extensions")
 
-for option, default in defaults.items():
-    defaults[option] = int(os.environ.get(*default))
-parser.set_defaults(**defaults)
-(options, args) = parser.parse_args()
-verbose = options.verbose
-nodiff = options.nodiff
-coverage = options.cover or options.cover_stdlib or options.annotate
-python = sys.executable
+    for option, default in defaults.items():
+        defaults[option] = int(os.environ.get(*default))
+    parser.set_defaults(**defaults)
+    (options, args) = parser.parse_args()
+
+    global vlog
+    options.anycoverage = (options.cover or
+                           options.cover_stdlib or
+                           options.annotate)
 
-if options.jobs < 1:
-    print >> sys.stderr, 'ERROR: -j/--jobs must be positive'
-    sys.exit(1)
-if options.interactive and options.jobs > 1:
-    print '(--interactive overrides --jobs)'
-    options.jobs = 1
+    if options.verbose:
+        def vlog(*msg):
+            for m in msg:
+                print m,
+            print
+    else:
+        vlog = lambda *msg: None
+
+    if options.jobs < 1:
+        print >> sys.stderr, 'ERROR: -j/--jobs must be positive'
+        sys.exit(1)
+    if options.interactive and options.jobs > 1:
+        print '(--interactive overrides --jobs)'
+        options.jobs = 1
+
+    return (options, args)
 
 def rename(src, dst):
     """Like os.rename(), trade atomicity and opened files friendliness
@@ -109,12 +122,6 @@
     shutil.copy(src, dst)
     os.remove(src)
 
-def vlog(*msg):
-    if verbose:
-        for m in msg:
-            print m,
-        print
-
 def splitnewlines(text):
     '''like str.splitlines, but only split on newlines.
     keep line endings.'''
@@ -130,7 +137,7 @@
         lines.append(text[i:n+1])
         i = n + 1
 
-def parse_hghave_output(lines):
+def parsehghaveoutput(lines):
     '''Parse hghave log lines.
     Return tuple of lists (missing, failed):
       * the missing/unknown features
@@ -147,12 +154,12 @@
 
     return missing, failed
 
-def show_diff(expected, output):
+def showdiff(expected, output):
     for line in difflib.unified_diff(expected, output,
             "Expected output", "Test output"):
         sys.stdout.write(line)
 
-def find_program(program):
+def findprogram(program):
     """Search PATH for a executable program"""
     for p in os.environ.get('PATH', os.defpath).split(os.pathsep):
         name = os.path.join(p, program)
@@ -160,43 +167,43 @@
             return name
     return None
 
-def check_required_tools():
+def checktools():
     # Before we go any further, check for pre-requisite tools
     # stuff from coreutils (cat, rm, etc) are not tested
-    for p in required_tools:
+    for p in requiredtools:
         if os.name == 'nt':
             p += '.exe'
-        found = find_program(p)
+        found = findprogram(p)
         if found:
             vlog("# Found prerequisite", p, "at", found)
         else:
             print "WARNING: Did not find prerequisite tool: "+p
 
-def cleanup_exit():
+def cleanup(options):
     if not options.keep_tmpdir:
-        if verbose:
+        if options.verbose:
             print "# Cleaning up HGTMP", HGTMP
         shutil.rmtree(HGTMP, True)
 
-def use_correct_python():
+def usecorrectpython():
     # some tests run python interpreter. they must use same
     # interpreter we use or bad things will happen.
     exedir, exename = os.path.split(sys.executable)
     if exename == 'python':
-        path = find_program('python')
+        path = findprogram('python')
         if os.path.dirname(path) == exedir:
             return
     vlog('# Making python executable in test path use correct Python')
-    my_python = os.path.join(BINDIR, 'python')
+    mypython = os.path.join(BINDIR, 'python')
     try:
-        os.symlink(sys.executable, my_python)
+        os.symlink(sys.executable, mypython)
     except AttributeError:
         # windows fallback
-        shutil.copyfile(sys.executable, my_python)
-        shutil.copymode(sys.executable, my_python)
+        shutil.copyfile(sys.executable, mypython)
+        shutil.copymode(sys.executable, mypython)
 
-def install_hg():
-    global python
+def installhg(options):
+    global PYTHON
     vlog("# Performing temporary installation of HG")
     installerrs = os.path.join("tests", "install.err")
     pure = options.pure and "--pure" or ""
@@ -209,7 +216,7 @@
            % (sys.executable, pure, INST, PYTHONDIR, BINDIR, installerrs))
     vlog("# Running", cmd)
     if os.system(cmd) == 0:
-        if not verbose:
+        if not options.verbose:
             os.remove(installerrs)
     else:
         f = open(installerrs)
@@ -229,7 +236,7 @@
         pythonpath = pydir
     os.environ["PYTHONPATH"] = pythonpath
 
-    use_correct_python()
+    usecorrectpython()
     global hgpkg
     hgpkg = _hgpath()
 
@@ -245,7 +252,7 @@
     f.close()
     os.chmod(os.path.join(BINDIR, 'diffstat'), 0700)
 
-    if coverage:
+    if options.anycoverage:
         vlog("# Installing coverage wrapper")
         os.environ['COVERAGE_FILE'] = COVERAGE_FILE
         if os.path.exists(COVERAGE_FILE):
@@ -260,10 +267,17 @@
                  os.path.join(BINDIR, '_hg.py')))
         f.close()
         os.chmod(os.path.join(BINDIR, 'hg'), 0700)
-        python = '"%s" "%s" -x' % (sys.executable,
+        PYTHON = '"%s" "%s" -x' % (sys.executable,
                                    os.path.join(TESTDIR,'coverage.py'))
 
-def output_coverage():
+def _hgpath():
+    cmd = '%s -c "import mercurial; print mercurial.__path__[0]"'
+    hgpath = os.popen(cmd % PYTHON)
+    path = hgpath.read().strip()
+    hgpath.close()
+    return path
+
+def outputcoverage(options):
     vlog("# Producing coverage report")
     omit = [BINDIR, TESTDIR, PYTHONDIR]
     if not options.cover_stdlib:
@@ -321,14 +335,14 @@
                        % options.timeout)
     return ret, splitnewlines(output)
 
-def run_one(test, skips, fails):
+def runone(options, test, skips, fails):
     '''tristate output:
     None -> skipped
     True -> passed
     False -> failed'''
 
     def skip(msg):
-        if not verbose:
+        if not options.verbose:
             skips.append((test, msg))
         else:
             print "\nSkipping %s: %s" % (test, msg)
@@ -336,7 +350,7 @@
 
     def fail(msg):
         fails.append((test, msg))
-        if not nodiff:
+        if not options.nodiff:
             print "\nERROR: %s %s" % (test, msg)
         return None
 
@@ -374,7 +388,7 @@
     lctest = test.lower()
 
     if lctest.endswith('.py') or firstline == '#!/usr/bin/env python':
-        cmd = '%s "%s"' % (python, testpath)
+        cmd = '%s "%s"' % (PYTHON, testpath)
     elif lctest.endswith('.bat'):
         # do not run batch scripts on non-windows
         if os.name != 'nt':
@@ -409,13 +423,13 @@
     # If reference output file exists, check test output against it
     if os.path.exists(ref):
         f = open(ref, "r")
-        ref_out = splitnewlines(f.read())
+        refout = splitnewlines(f.read())
         f.close()
     else:
-        ref_out = []
+        refout = []
     if skipped:
         mark = 's'
-        missing, failed = parse_hghave_output(out)
+        missing, failed = parsehghaveoutput(out)
         if not missing:
             missing = ['irrelevant']
         if failed:
@@ -423,20 +437,20 @@
             skipped = False
         else:
             skip(missing[-1])
-    elif out != ref_out:
+    elif out != refout:
         mark = '!'
         if ret:
             fail("output changed and returned error code %d" % ret)
         else:
             fail("output changed")
-        if not nodiff:
-            show_diff(ref_out, out)
+        if not options.nodiff:
+            showdiff(refout, out)
         ret = 1
     elif ret:
         mark = '!'
         fail("returned error code %d" % ret)
 
-    if not verbose:
+    if not options.verbose:
         sys.stdout.write(mark)
         sys.stdout.flush()
 
@@ -478,54 +492,9 @@
         return None
     return ret == 0
 
-if not options.child:
-    os.umask(022)
-
-    check_required_tools()
-
-# Reset some environment variables to well-known values so that
-# the tests produce repeatable output.
-os.environ['LANG'] = os.environ['LC_ALL'] = 'C'
-os.environ['TZ'] = 'GMT'
-os.environ["EMAIL"] = "Foo Bar <foo.bar@example.com>"
-os.environ['CDPATH'] = ''
-
-TESTDIR = os.environ["TESTDIR"] = os.getcwd()
-HGTMP = os.environ['HGTMP'] = os.path.realpath(tempfile.mkdtemp('', 'hgtests.',
-                                               options.tmpdir))
-DAEMON_PIDS = None
-HGRCPATH = None
-
-os.environ["HGEDITOR"] = sys.executable + ' -c "import sys; sys.exit(0)"'
-os.environ["HGMERGE"] = "internal:merge"
-os.environ["HGUSER"]   = "test"
-os.environ["HGENCODING"] = "ascii"
-os.environ["HGENCODINGMODE"] = "strict"
-os.environ["HGPORT"] = str(options.port)
-os.environ["HGPORT1"] = str(options.port + 1)
-os.environ["HGPORT2"] = str(options.port + 2)
-
-if options.with_hg:
-    INST = options.with_hg
-else:
-    INST = os.path.join(HGTMP, "install")
-BINDIR = os.environ["BINDIR"] = os.path.join(INST, "bin")
-PYTHONDIR = os.path.join(INST, "lib", "python")
-COVERAGE_FILE = os.path.join(TESTDIR, ".coverage")
-
-def _hgpath():
-    cmd = '%s -c "import mercurial; print mercurial.__path__[0]"'
-    hgpath = os.popen(cmd % python)
-    path = hgpath.read().strip()
-    hgpath.close()
-    return path
-
-expecthg = os.path.join(HGTMP, 'install', 'lib', 'python', 'mercurial')
-hgpkg = None
-
-def run_children(tests):
+def runchildren(options, expecthg, tests):
     if not options.with_hg:
-        install_hg()
+        installhg()
         if hgpkg != expecthg:
             print '# Testing unexpected mercurial: %s' % hgpkg
 
@@ -553,7 +522,7 @@
             continue
         rfd, wfd = os.pipe()
         childopts = ['--child=%d' % wfd, '--port=%d' % (options.port + j * 3)]
-        cmdline = [python, sys.argv[0]] + opts + childopts + job
+        cmdline = [PYTHON, sys.argv[0]] + opts + childopts + job
         vlog(' '.join(cmdline))
         fps[os.spawnvp(os.P_NOWAIT, cmdline[0], cmdline)] = os.fdopen(rfd, 'r')
         os.close(wfd)
@@ -588,14 +557,14 @@
         tested, skipped, failed)
     sys.exit(failures != 0)
 
-def run_tests(tests):
+def runtests(options, expecthg, tests):
     global DAEMON_PIDS, HGRCPATH
     DAEMON_PIDS = os.environ["DAEMON_PIDS"] = os.path.join(HGTMP, 'daemon.pids')
     HGRCPATH = os.environ["HGRCPATH"] = os.path.join(HGTMP, '.hgrc')
 
     try:
         if not options.with_hg:
-            install_hg()
+            installhg(options)
 
             if hgpkg != expecthg:
                 print '# Testing unexpected mercurial: %s' % hgpkg
@@ -629,7 +598,7 @@
             if options.retest and not os.path.exists(test + ".err"):
                 skipped += 1
                 continue
-            ret = run_one(test, skips, fails)
+            ret = runone(options, test, skips, fails)
             if ret is None:
                 skipped += 1
             elif not ret:
@@ -665,8 +634,8 @@
             print "# Ran %d tests, %d skipped, %d failed." % (
                 tested, skipped, failed)
 
-        if coverage:
-            output_coverage()
+        if options.anycoverage:
+            outputcoverage(options)
     except KeyboardInterrupt:
         failed = True
         print "\ninterrupted!"
@@ -674,24 +643,67 @@
     if failed:
         sys.exit(1)
 
-if len(args) == 0:
-    args = os.listdir(".")
-    args.sort()
+def main():
+    (options, args) = parseargs()
+    if not options.child:
+        os.umask(022)
+
+        checktools()
+
+    # Reset some environment variables to well-known values so that
+    # the tests produce repeatable output.
+    os.environ['LANG'] = os.environ['LC_ALL'] = 'C'
+    os.environ['TZ'] = 'GMT'
+    os.environ["EMAIL"] = "Foo Bar <foo.bar@example.com>"
+    os.environ['CDPATH'] = ''
 
-tests = []
-for test in args:
-    if (test.startswith("test-") and '~' not in test and
-        ('.' not in test or test.endswith('.py') or
-         test.endswith('.bat'))):
-        tests.append(test)
+    global TESTDIR, HGTMP, INST, BINDIR, PYTHONDIR, COVERAGE_FILE
+    TESTDIR = os.environ["TESTDIR"] = os.getcwd()
+    HGTMP = os.environ['HGTMP'] = os.path.realpath(tempfile.mkdtemp('', 'hgtests.',
+                                                   options.tmpdir))
+    DAEMON_PIDS = None
+    HGRCPATH = None
+
+    os.environ["HGEDITOR"] = sys.executable + ' -c "import sys; sys.exit(0)"'
+    os.environ["HGMERGE"] = "internal:merge"
+    os.environ["HGUSER"]   = "test"
+    os.environ["HGENCODING"] = "ascii"
+    os.environ["HGENCODINGMODE"] = "strict"
+    os.environ["HGPORT"] = str(options.port)
+    os.environ["HGPORT1"] = str(options.port + 1)
+    os.environ["HGPORT2"] = str(options.port + 2)
 
-vlog("# Using TESTDIR", TESTDIR)
-vlog("# Using HGTMP", HGTMP)
+    if options.with_hg:
+        INST = options.with_hg
+    else:
+        INST = os.path.join(HGTMP, "install")
+    BINDIR = os.environ["BINDIR"] = os.path.join(INST, "bin")
+    PYTHONDIR = os.path.join(INST, "lib", "python")
+    COVERAGE_FILE = os.path.join(TESTDIR, ".coverage")
+
+    expecthg = os.path.join(HGTMP, 'install', 'lib', 'python', 'mercurial')
+    hgpkg = None
+
+    if len(args) == 0:
+        args = os.listdir(".")
+        args.sort()
 
-try:
-    if len(tests) > 1 and options.jobs > 1:
-        run_children(tests)
-    else:
-        run_tests(tests)
-finally:
-    cleanup_exit()
+    tests = []
+    for test in args:
+        if (test.startswith("test-") and '~' not in test and
+            ('.' not in test or test.endswith('.py') or
+             test.endswith('.bat'))):
+            tests.append(test)
+
+    vlog("# Using TESTDIR", TESTDIR)
+    vlog("# Using HGTMP", HGTMP)
+
+    try:
+        if len(tests) > 1 and options.jobs > 1:
+            runchildren(options, expecthg, tests)
+        else:
+            runtests(options, expecthg, tests)
+    finally:
+        cleanup(options)
+
+main()
--- a/tests/test-convert-bzr-merges	Sat Apr 04 20:19:51 2009 -0500
+++ b/tests/test-convert-bzr-merges	Tue Apr 21 12:58:05 2009 -0500
@@ -1,5 +1,9 @@
 #!/bin/sh
 
+# N.B. bzr 1.13 has a bug that breaks this test.  If you see this
+# test fail, check your bzr version.  Upgrading to bzr 1.13.1
+# should fix it.
+
 . "$TESTDIR/bzr-definitions"
 
 echo % test multiple merges at once
--- a/tests/test-convert-cvs-synthetic	Sat Apr 04 20:19:51 2009 -0500
+++ b/tests/test-convert-cvs-synthetic	Tue Apr 21 12:58:05 2009 -0500
@@ -3,8 +3,6 @@
 # This feature requires use of builtin cvsps!
 "$TESTDIR/hghave" cvs || exit 80
 
-# XXX lots of duplication with other test-convert-cvs* scripts
-
 set -e
 
 echo "[extensions]" >> $HGRCPATH
@@ -19,47 +17,62 @@
 export CVS_OPTIONS=-f
 cd ..
 
-filter='sed "s:$CVSROOT:*REPO*:g"'
+filterpath()
+{
+    eval "$@" | sed "s:$CVSROOT:*REPO*:g"
+}
+
 cvscall()
 {
-    cvs -f "$@" | eval $filter
+    echo cvs -f "$@"
+    cvs -f "$@" 2>&1
 }
 
-cvscall -q -d "$CVSROOT" init
+# output of 'cvs ci' varies unpredictably, so just discard it
+cvsci()
+{
+    echo cvs -f ci "$@"
+    cvs -f ci "$@" >/dev/null 2>&1
+}
+
+filterpath cvscall -d "$CVSROOT" init
 mkdir cvsrepo/proj
 
-cvscall co proj
+cvscall -q co proj
 
 echo % create file1 on the trunk
 cd proj
 touch file1
-cvscall add file1
-cvscall ci -m"add file1 on trunk" file1
+cvscall -Q add file1
+cvsci -m"add file1 on trunk" file1
 
 echo % create two branches
-cvscall tag -b v1_0
-cvscall tag -b v1_1
+cvscall -q tag -b v1_0
+cvscall -q tag -b v1_1
 
 echo % create file2 on branch v1_0
-cvs up -rv1_0
+cvscall -q up -rv1_0
 touch file2
-cvscall add file2
-cvscall ci -m"add file2 on branch v1_0" file2
+cvscall -Q add file2
+cvsci -m"add file2 on branch v1_0" file2
 
 echo % create file3, file4 on branch v1_1
-cvs up -rv1_1
+cvscall -Q up -rv1_1
 touch file3
 touch file4
-cvscall add file3 file4
-cvscall ci -m"add file3, file4 on branch v1_1" file3 file4
+cvscall -Q add file3 file4
+cvsci -m"add file3, file4 on branch v1_1" file3 file4
 
 echo % merge file2 from v1_0 to v1_1
-cvscall up -jv1_0
-cvscall ci -m"merge file2 from v1_0 to v1_1"
+cvscall -q up -jv1_0
+cvsci -m"merge file2 from v1_0 to v1_1"
+
+echo % cvs rlog output
+filterpath cvscall -q rlog proj | egrep '^(RCS file|revision)'
 
 echo % convert to hg
 cd ..
-hg convert proj proj.hg | eval $filter
+filterpath hg convert proj proj.hg
 
 echo % hg log output
 hg -R proj.hg log --template "{rev} {desc}\n"
--- a/tests/test-convert-cvs-synthetic.out	Sat Apr 04 20:19:51 2009 -0500
+++ b/tests/test-convert-cvs-synthetic.out	Tue Apr 21 12:58:05 2009 -0500
@@ -1,37 +1,40 @@
 % create cvs repository with one project
-cvs checkout: Updating proj
+cvs -f -d *REPO* init
+cvs -f -q co proj
 % create file1 on the trunk
-cvs add: scheduling file `file1' for addition
-cvs add: use `cvs commit' to add this file permanently
-*REPO*/proj/file1,v  <--  file1
-initial revision: 1.1
+cvs -f -Q add file1
+cvs -f ci -madd file1 on trunk file1
 % create two branches
-cvs tag: Tagging .
+cvs -f -q tag -b v1_0
 T file1
-cvs tag: Tagging .
+cvs -f -q tag -b v1_1
 T file1
 % create file2 on branch v1_0
-cvs update: Updating .
-cvs add: scheduling file `file2' for addition on branch `v1_0'
-cvs add: use `cvs commit' to add this file permanently
-*REPO*/proj/Attic/file2,v  <--  file2
-new revision: 1.1.2.1; previous revision: 1.1
+cvs -f -q up -rv1_0
+cvs -f -Q add file2
+cvs -f ci -madd file2 on branch v1_0 file2
 % create file3, file4 on branch v1_1
-cvs update: Updating .
-cvs update: `file2' is no longer in the repository
-cvs add: scheduling file `file3' for addition on branch `v1_1'
-cvs add: scheduling file `file4' for addition on branch `v1_1'
-cvs add: use `cvs commit' to add these files permanently
-*REPO*/proj/Attic/file3,v  <--  file3
-new revision: 1.1.2.1; previous revision: 1.1
-*REPO*/proj/Attic/file4,v  <--  file4
-new revision: 1.1.2.1; previous revision: 1.1
+cvs -f -Q up -rv1_1
+cvs -f -Q add file3 file4
+cvs -f ci -madd file3, file4 on branch v1_1 file3 file4
 % merge file2 from v1_0 to v1_1
-cvs update: Updating .
+cvs -f -q up -jv1_0
 U file2
-cvs commit: Examining .
-*REPO*/proj/Attic/file2,v  <--  file2
-new revision: 1.1.4.2; previous revision: 1.1.4.1
+cvs -f ci -mmerge file2 from v1_0 to v1_1
+% cvs rlog output
+RCS file: *REPO*/proj/file1,v
+revision 1.1
+RCS file: *REPO*/proj/Attic/file2,v
+revision 1.1
+revision 1.1.4.2
+revision 1.1.4.1
+revision 1.1.2.1
+RCS file: *REPO*/proj/Attic/file3,v
+revision 1.1
+revision 1.1.2.1
+RCS file: *REPO*/proj/Attic/file4,v
+revision 1.1
+revision 1.1.2.1
 % convert to hg
 initializing destination proj.hg repository
 connecting to *REPO*
--- a/tests/test-convert-mtn	Sat Apr 04 20:19:51 2009 -0500
+++ b/tests/test-convert-mtn	Tue Apr 21 12:58:05 2009 -0500
@@ -33,9 +33,10 @@
 echo a > a
 mkdir dir
 echo b > dir/b
+echo d > dir/d
 python -c 'file("bin", "wb").write("a\\x00b")'
 echo c > c
-mtn add a dir/b c bin
+mtn add a dir/b dir/d c bin
 mtn ci -m initialize
 echo % update monotone working directory
 mtn mv a dir/a
@@ -66,6 +67,9 @@
 mtn ci -m movedir1
 echo '% test subdirectory move'
 mtn mv dir dir2
+echo newfile > dir2/newfile
+mtn drop dir2/d
+mtn add dir2/newfile
 mtn ci -m movedir
 # Test directory removal with empty directory
 mkdir dir2/dir
@@ -102,5 +106,7 @@
 test -d dir1/subdir2 || echo 'new dir1/subdir2 does not exist!'
 test -d dir1/subdir1 && echo 'renamed dir1/subdir1 is still there!'
 hg log -v -C -r 4 | grep copies
+echo % check file remove with directory move
+hg manifest -r 5
 exit 0
 
--- a/tests/test-convert-mtn.out	Sat Apr 04 20:19:51 2009 -0500
+++ b/tests/test-convert-mtn.out	Tue Apr 21 12:58:05 2009 -0500
@@ -5,14 +5,15 @@
 mtn: adding c to workspace manifest
 mtn: adding dir to workspace manifest
 mtn: adding dir/b to workspace manifest
+mtn: adding dir/d to workspace manifest
 mtn: beginning commit on branch 'com.selenic.test'
-mtn: committed revision 803ef0bf815e35b951dbd4310acd1e45e675016e
+mtn: committed revision 0f6e5e4f2e7d2a8ef312408f57618abf026afd90
 % update monotone working directory
 mtn: skipping dir, already accounted for in workspace
 mtn: renaming a to dir/a in workspace manifest
 mtn: dropping c from workspace manifest
 mtn: beginning commit on branch 'com.selenic.test'
-mtn: committed revision 4daf60753d6fe21a06ce5f716303fe55fd6d3a56
+mtn: committed revision 51d0a982464573a2a2cf5ee2c9219c652aaebeff
 % convert once
 assuming destination repo.mtn-hg
 initializing destination repo.mtn-hg repository
@@ -25,7 +26,7 @@
 mtn: dropping dir/b from workspace manifest
 mtn: renaming bin to bin2 in workspace manifest
 mtn: beginning commit on branch 'com.selenic.test'
-mtn: committed revision 6c6977a6ef609ec80e40779f89dbd2772c96de62
+mtn: committed revision ebe58335d85d8cb176b6d0a12be04f5314b998da
 % test directory move
 mtn: adding dir1 to workspace manifest
 mtn: adding dir1/subdir1 to workspace manifest
@@ -33,23 +34,25 @@
 mtn: adding dir1/subdir2_other to workspace manifest
 mtn: adding dir1/subdir2_other/file1 to workspace manifest
 mtn: beginning commit on branch 'com.selenic.test'
-mtn: committed revision e066b1feb2b7a7110450c2c18b5b4462011427d1
+mtn: committed revision a8d62bc04fee4d2936d28e98bbcc81686dd74306
 mtn: skipping dir1, already accounted for in workspace
 mtn: renaming dir1/subdir1 to dir1/subdir2 in workspace manifest
 mtn: beginning commit on branch 'com.selenic.test'
-mtn: committed revision 2ad2409d25bb8d2583b57a3d4c0fa1df62aa1f79
+mtn: committed revision 2c3d241bbbfe538b1b51d910f5676407e3f4d3a6
 % test subdirectory move
 mtn: renaming dir to dir2 in workspace manifest
+mtn: dropping dir2/d from workspace manifest
+mtn: adding dir2/newfile to workspace manifest
 mtn: beginning commit on branch 'com.selenic.test'
-mtn: committed revision a85290b81fc4a8fbce4dc4d956404109842b406e
+mtn: committed revision fdb5a02dae8bfce3a79b3393680af471016e1b4c
 mtn: beginning commit on branch 'com.selenic.test'
-mtn: committed revision 7e3c8746060117104f16ff2d9212cf0f810cbff0
+mtn: committed revision 8bbf76d717001d24964e4604739fdcd0f539fc88
 mtn: dropping dir2/dir/subdir/f from workspace manifest
 mtn: dropping dir2/dir/subdir from workspace manifest
 mtn: dropping dir2/dir/emptydir from workspace manifest
 mtn: dropping dir2/dir from workspace manifest
 mtn: beginning commit on branch 'com.selenic.test'
-mtn: committed revision a97e0433d041a6d253c5dc27e080d544e55d9c19
+mtn: committed revision 2323d4bc324e6c82628dc04d47a9fd32ad24e322
 % convert incrementally
 assuming destination repo.mtn-hg
 scanning source...
@@ -61,12 +64,12 @@
 2 movedir
 1 emptydir
 0 dropdirectory
-5 files updated, 0 files merged, 0 files removed, 0 files unresolved
+6 files updated, 0 files merged, 0 files removed, 0 files unresolved
 @  7 "dropdirectory" files: dir2/dir/subdir/f
 |
 o  6 "emptydir" files: dir2/dir/subdir/f
 |
-o  5 "movedir" files: dir/a dir2/a
+o  5 "movedir" files: dir/a dir/d dir2/a dir2/newfile
 |
 o  4 "movedir1" files: dir1/subdir1/file1 dir1/subdir2/file1
 |
@@ -76,13 +79,14 @@
 |
 o  1 "update1" files: a bin c dir/a dir/b
 |
-o  0 "initialize" files: a bin c dir/b
+o  0 "initialize" files: a bin c dir/b dir/d
 
 % manifest
 bin2
 dir1/subdir2/file1
 dir1/subdir2_other/file1
 dir2/a
+dir2/newfile
 e
 % contents
 a
@@ -92,7 +96,15 @@
 % check directory move
 bin2
 dir/a
+dir/d
 dir1/subdir2/file1
 dir1/subdir2_other/file1
 e
 copies:      dir1/subdir2/file1 (dir1/subdir1/file1)
+% check file remove with directory move
+bin2
+dir1/subdir2/file1
+dir1/subdir2_other/file1
+dir2/a
+dir2/newfile
+e
--- a/tests/test-highlight	Sat Apr 04 20:19:51 2009 -0500
+++ b/tests/test-highlight	Tue Apr 21 12:58:05 2009 -0500
@@ -24,7 +24,7 @@
 
 echo % hgweb filerevision, html
 ("$TESTDIR/get-with-headers.py" localhost:$HGPORT '/file/tip/get-with-headers.py') \
-    | sed "s/class=\"k\"/class=\"kn\"/g"
+    | sed "s/class=\"k\"/class=\"kn\"/g" | sed "s/class=\"mf\"/class=\"mi\"/g"
 
 echo % hgweb filerevision, html
 ("$TESTDIR/get-with-headers.py" localhost:$HGPORT '/file/tip/isolatin.txt') \
@@ -32,7 +32,7 @@
 
 echo % hgweb fileannotate, html
 ("$TESTDIR/get-with-headers.py" localhost:$HGPORT '/annotate/tip/get-with-headers.py') \
-    | sed "s/class=\"k\"/class=\"kn\"/g"
+    | sed "s/class=\"k\"/class=\"kn\"/g" | sed "s/class=\"mi\"/class=\"mf\"/g"
 
 echo % hgweb fileannotate, raw
 ("$TESTDIR/get-with-headers.py" localhost:$HGPORT '/annotate/tip/get-with-headers.py?style=raw') \
--- a/tests/test-highlight.out	Sat Apr 04 20:19:51 2009 -0500
+++ b/tests/test-highlight.out	Tue Apr 21 12:58:05 2009 -0500
@@ -75,7 +75,7 @@
 
 <div class="overflow">
 <div class="sourcefirst"> line source</div>
-<div class="parity0 source"><a href="#l1" id="l1">     1</a> <span class="c">#!/usr/bin/env python</span></div><div class="parity1 source"><a href="#l2" id="l2">     2</a> </div><div class="parity0 source"><a href="#l3" id="l3">     3</a> <span class="n">__doc__</span> <span class="o">=</span> <span class="s">&quot;&quot;&quot;This does HTTP get requests given a host:port and path and returns</span></div><div class="parity1 source"><a href="#l4" id="l4">     4</a> <span class="s">a subset of the headers plus the body of the result.&quot;&quot;&quot;</span></div><div class="parity0 source"><a href="#l5" id="l5">     5</a> </div><div class="parity1 source"><a href="#l6" id="l6">     6</a> <span class="kn">import</span> <span class="nn">httplib</span><span class="o">,</span> <span class="nn">sys</span><span class="o">,</span> <span class="nn">re</span></div><div class="parity0 source"><a href="#l7" id="l7">     7</a> </div><div class="parity1 source"><a href="#l8" id="l8">     8</a> <span class="kn">try</span><span class="p">:</span></div><div class="parity0 source"><a href="#l9" id="l9">     9</a>     <span class="kn">import</span> <span class="nn">msvcrt</span><span class="o">,</span> <span class="nn">os</span></div><div class="parity1 source"><a href="#l10" id="l10">    10</a>     <span class="n">msvcrt</span><span class="o">.</span><span class="n">setmode</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">fileno</span><span class="p">(),</span> <span class="n">os</span><span class="o">.</span><span class="n">O_BINARY</span><span class="p">)</span></div><div class="parity0 source"><a href="#l11" id="l11">    11</a>     <span class="n">msvcrt</span><span class="o">.</span><span class="n">setmode</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="o">.</span><span class="n">fileno</span><span class="p">(),</span> <span class="n">os</span><span class="o">.</span><span class="n">O_BINARY</span><span class="p">)</span></div><div class="parity1 source"><a href="#l12" id="l12">    12</a> <span class="kn">except</span> <span class="ne">ImportError</span><span class="p">:</span></div><div class="parity0 source"><a href="#l13" id="l13">    13</a>     <span class="kn">pass</span></div><div class="parity1 source"><a href="#l14" id="l14">    14</a> </div><div class="parity0 source"><a href="#l15" id="l15">    15</a> <span class="n">headers</span> <span class="o">=</span> <span class="p">[</span><span class="n">h</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="kn">for</span> <span class="n">h</span> <span class="ow">in</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mf">3</span><span class="p">:]]</span></div><div class="parity1 source"><a href="#l16" id="l16">    16</a> <span class="n">conn</span> <span class="o">=</span> <span class="n">httplib</span><span class="o">.</span><span class="n">HTTPConnection</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mf">1</span><span class="p">])</span></div><div class="parity0 source"><a href="#l17" id="l17">    17</a> <span class="n">conn</span><span class="o">.</span><span class="n">request</span><span class="p">(</span><span class="s">&quot;GET&quot;</span><span class="p">,</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mf">2</span><span class="p">])</span></div><div class="parity1 source"><a href="#l18" id="l18">    18</a> <span class="n">response</span> <span class="o">=</span> <span class="n">conn</span><span class="o">.</span><span class="n">getresponse</span><span class="p">()</span></div><div class="parity0 source"><a href="#l19" id="l19">    19</a> <span class="kn">print</span> <span class="n">response</span><span class="o">.</span><span class="n">status</span><span class="p">,</span> <span class="n">response</span><span class="o">.</span><span class="n">reason</span></div><div class="parity1 source"><a href="#l20" id="l20">    20</a> <span class="kn">for</span> <span class="n">h</span> <span class="ow">in</span> <span class="n">headers</span><span class="p">:</span></div><div class="parity0 source"><a href="#l21" id="l21">    21</a>     <span class="kn">if</span> <span class="n">response</span><span class="o">.</span><span class="n">getheader</span><span class="p">(</span><span class="n">h</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span></div><div class="parity1 source"><a href="#l22" id="l22">    22</a>         <span class="kn">print</span> <span class="s">&quot;</span><span class="si">%s</span><span class="s">: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">h</span><span class="p">,</span> <span class="n">response</span><span class="o">.</span><span class="n">getheader</span><span class="p">(</span><span class="n">h</span><span class="p">))</span></div><div class="parity0 source"><a href="#l23" id="l23">    23</a> <span class="kn">print</span></div><div class="parity1 source"><a href="#l24" id="l24">    24</a> <span class="n">data</span> <span class="o">=</span> <span class="n">response</span><span class="o">.</span><span class="n">read</span><span class="p">()</span></div><div class="parity0 source"><a href="#l25" id="l25">    25</a> <span class="n">data</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">sub</span><span class="p">(</span><span class="s">&#39;\d+ years&#39;</span><span class="p">,</span> <span class="s">&#39;many years&#39;</span><span class="p">,</span> <span class="n">data</span><span class="p">)</span></div><div class="parity1 source"><a href="#l26" id="l26">    26</a> <span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">data</span><span class="p">)</span></div><div class="parity0 source"><a href="#l27" id="l27">    27</a> </div><div class="parity1 source"><a href="#l28" id="l28">    28</a> <span class="kn">if</span> <span class="mf">200</span> <span class="o">&lt;=</span> <span class="n">response</span><span class="o">.</span><span class="n">status</span> <span class="o">&lt;=</span> <span class="mf">299</span><span class="p">:</span></div><div class="parity0 source"><a href="#l29" id="l29">    29</a>     <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mf">0</span><span class="p">)</span></div><div class="parity1 source"><a href="#l30" id="l30">    30</a> <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mf">1</span><span class="p">)</span></div>
+<div class="parity0 source"><a href="#l1" id="l1">     1</a> <span class="c">#!/usr/bin/env python</span></div><div class="parity1 source"><a href="#l2" id="l2">     2</a> </div><div class="parity0 source"><a href="#l3" id="l3">     3</a> <span class="n">__doc__</span> <span class="o">=</span> <span class="s">&quot;&quot;&quot;This does HTTP get requests given a host:port and path and returns</span></div><div class="parity1 source"><a href="#l4" id="l4">     4</a> <span class="s">a subset of the headers plus the body of the result.&quot;&quot;&quot;</span></div><div class="parity0 source"><a href="#l5" id="l5">     5</a> </div><div class="parity1 source"><a href="#l6" id="l6">     6</a> <span class="kn">import</span> <span class="nn">httplib</span><span class="o">,</span> <span class="nn">sys</span><span class="o">,</span> <span class="nn">re</span></div><div class="parity0 source"><a href="#l7" id="l7">     7</a> </div><div class="parity1 source"><a href="#l8" id="l8">     8</a> <span class="kn">try</span><span class="p">:</span></div><div class="parity0 source"><a href="#l9" id="l9">     9</a>     <span class="kn">import</span> <span class="nn">msvcrt</span><span class="o">,</span> <span class="nn">os</span></div><div class="parity1 source"><a href="#l10" id="l10">    10</a>     <span class="n">msvcrt</span><span class="o">.</span><span class="n">setmode</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">fileno</span><span class="p">(),</span> <span class="n">os</span><span class="o">.</span><span class="n">O_BINARY</span><span class="p">)</span></div><div class="parity0 source"><a href="#l11" id="l11">    11</a>     <span class="n">msvcrt</span><span class="o">.</span><span class="n">setmode</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="o">.</span><span class="n">fileno</span><span class="p">(),</span> <span class="n">os</span><span class="o">.</span><span class="n">O_BINARY</span><span class="p">)</span></div><div class="parity1 source"><a href="#l12" id="l12">    12</a> <span class="kn">except</span> <span class="ne">ImportError</span><span class="p">:</span></div><div class="parity0 source"><a href="#l13" id="l13">    13</a>     <span class="kn">pass</span></div><div class="parity1 source"><a href="#l14" id="l14">    14</a> </div><div class="parity0 source"><a href="#l15" id="l15">    15</a> <span class="n">headers</span> <span class="o">=</span> <span class="p">[</span><span class="n">h</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="kn">for</span> <span class="n">h</span> <span class="ow">in</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">3</span><span class="p">:]]</span></div><div class="parity1 source"><a href="#l16" id="l16">    16</a> <span class="n">conn</span> <span class="o">=</span> <span class="n">httplib</span><span class="o">.</span><span class="n">HTTPConnection</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span></div><div class="parity0 source"><a href="#l17" id="l17">    17</a> <span class="n">conn</span><span class="o">.</span><span class="n">request</span><span class="p">(</span><span class="s">&quot;GET&quot;</span><span class="p">,</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span></div><div class="parity1 source"><a href="#l18" id="l18">    18</a> <span class="n">response</span> <span class="o">=</span> <span class="n">conn</span><span class="o">.</span><span class="n">getresponse</span><span class="p">()</span></div><div class="parity0 source"><a href="#l19" id="l19">    19</a> <span class="kn">print</span> <span class="n">response</span><span class="o">.</span><span class="n">status</span><span class="p">,</span> <span class="n">response</span><span class="o">.</span><span class="n">reason</span></div><div class="parity1 source"><a href="#l20" id="l20">    20</a> <span class="kn">for</span> <span class="n">h</span> <span class="ow">in</span> <span class="n">headers</span><span class="p">:</span></div><div class="parity0 source"><a href="#l21" id="l21">    21</a>     <span class="kn">if</span> <span class="n">response</span><span class="o">.</span><span class="n">getheader</span><span class="p">(</span><span class="n">h</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span></div><div class="parity1 source"><a href="#l22" id="l22">    22</a>         <span class="kn">print</span> <span class="s">&quot;</span><span class="si">%s</span><span class="s">: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">h</span><span class="p">,</span> <span class="n">response</span><span class="o">.</span><span class="n">getheader</span><span class="p">(</span><span class="n">h</span><span class="p">))</span></div><div class="parity0 source"><a href="#l23" id="l23">    23</a> <span class="kn">print</span></div><div class="parity1 source"><a href="#l24" id="l24">    24</a> <span class="n">data</span> <span class="o">=</span> <span class="n">response</span><span class="o">.</span><span class="n">read</span><span class="p">()</span></div><div class="parity0 source"><a href="#l25" id="l25">    25</a> <span class="n">data</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">sub</span><span class="p">(</span><span class="s">&#39;\d+ years&#39;</span><span class="p">,</span> <span class="s">&#39;many years&#39;</span><span class="p">,</span> <span class="n">data</span><span class="p">)</span></div><div class="parity1 source"><a href="#l26" id="l26">    26</a> <span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">data</span><span class="p">)</span></div><div class="parity0 source"><a href="#l27" id="l27">    27</a> </div><div class="parity1 source"><a href="#l28" id="l28">    28</a> <span class="kn">if</span> <span class="mi">200</span> <span class="o">&lt;=</span> <span class="n">response</span><span class="o">.</span><span class="n">status</span> <span class="o">&lt;=</span> <span class="mi">299</span><span class="p">:</span></div><div class="parity0 source"><a href="#l29" id="l29">    29</a>     <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span></div><div class="parity1 source"><a href="#l30" id="l30">    30</a> <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span></div>
 <div class="sourcelast"></div>
 </div>
 </div>
--- a/tests/test-rebase-parameters.out	Sat Apr 04 20:19:51 2009 -0500
+++ b/tests/test-rebase-parameters.out	Tue Apr 21 12:58:05 2009 -0500
@@ -11,7 +11,7 @@
     changes relative to a master development tree.
 
     If a rebase is interrupted to manually resolve a merge, it can be
-    continued with --continue or aborted with --abort.
+    continued with --continue/-c or aborted with --abort/-a.
 
 options:
 
@@ -39,7 +39,7 @@
     changes relative to a master development tree.
 
     If a rebase is interrupted to manually resolve a merge, it can be
-    continued with --continue or aborted with --abort.
+    continued with --continue/-c or aborted with --abort/-a.
 
 options:
 
@@ -67,7 +67,7 @@
     changes relative to a master development tree.
 
     If a rebase is interrupted to manually resolve a merge, it can be
-    continued with --continue or aborted with --abort.
+    continued with --continue/-c or aborted with --abort/-a.
 
 options:
 
@@ -95,7 +95,7 @@
     changes relative to a master development tree.
 
     If a rebase is interrupted to manually resolve a merge, it can be
-    continued with --continue or aborted with --abort.
+    continued with --continue/-c or aborted with --abort/-a.
 
 options: