changeset 18569:11bcab177d22

merge with stable
author Kevin Bullock <kbullock@ringworld.org>
date Fri, 08 Feb 2013 14:26:00 +0000
parents 194e63c1ccb9 (diff) cd403d6d96ef (current diff)
children dcf2d6fdf630
files
diffstat 36 files changed, 335 insertions(+), 295 deletions(-) [+]
line wrap: on
line diff
--- a/hgext/largefiles/basestore.py	Wed Feb 06 07:55:29 2013 +0000
+++ b/hgext/largefiles/basestore.py	Fri Feb 08 14:26:00 2013 +0000
@@ -96,10 +96,10 @@
         '''Verify the existence (and, optionally, contents) of every big
         file revision referenced by every changeset in revs.
         Return 0 if all is well, non-zero on any errors.'''
-        write = self.ui.write
         failed = False
 
-        write(_('searching %d changesets for largefiles\n') % len(revs))
+        self.ui.status(_('searching %d changesets for largefiles\n') %
+                       len(revs))
         verified = set()                # set of (filename, filenode) tuples
 
         for rev in revs:
@@ -113,12 +113,13 @@
         numrevs = len(verified)
         numlfiles = len(set([fname for (fname, fnode) in verified]))
         if contents:
-            write(_('verified contents of %d revisions of %d largefiles\n')
-                  % (numrevs, numlfiles))
+            self.ui.status(
+                _('verified contents of %d revisions of %d largefiles\n')
+                % (numrevs, numlfiles))
         else:
-            write(_('verified existence of %d revisions of %d largefiles\n')
-                  % (numrevs, numlfiles))
-
+            self.ui.status(
+                _('verified existence of %d revisions of %d largefiles\n')
+                % (numrevs, numlfiles))
         return int(failed)
 
     def _getfile(self, tmpfile, filename, hash):
--- a/hgext/largefiles/localstore.py	Wed Feb 06 07:55:29 2013 +0000
+++ b/hgext/largefiles/localstore.py	Fri Feb 08 14:26:00 2013 +0000
@@ -63,23 +63,19 @@
             return False
 
         expecthash = fctx.data()[0:40]
+        storepath = lfutil.storepath(self.remote, expecthash)
         verified.add(key)
         if not lfutil.instore(self.remote, expecthash):
             self.ui.warn(
-                _('changeset %s: %s missing\n'
-                  '  (looked for hash %s)\n')
-                % (cset, filename, expecthash))
+                _('changeset %s: %s references missing %s\n')
+                % (cset, filename, storepath))
             return True                 # failed
 
         if contents:
-            storepath = lfutil.storepath(self.remote, expecthash)
             actualhash = lfutil.hashfile(storepath)
             if actualhash != expecthash:
                 self.ui.warn(
-                    _('changeset %s: %s: contents differ\n'
-                      '  (%s:\n'
-                      '  expected hash %s,\n'
-                      '  but got %s)\n')
-                    % (cset, filename, storepath, expecthash, actualhash))
+                    _('changeset %s: %s references corrupted %s\n')
+                    % (cset, filename, storepath))
                 return True             # failed
         return False
--- a/hgext/largefiles/overrides.py	Wed Feb 06 07:55:29 2013 +0000
+++ b/hgext/largefiles/overrides.py	Fri Feb 08 14:26:00 2013 +0000
@@ -274,7 +274,7 @@
     contents = opts.pop('lfc', False)
 
     result = orig(ui, repo, *pats, **opts)
-    if large:
+    if large or all or contents:
         result = result or lfcommands.verifylfiles(ui, repo, all, contents)
     return result
 
@@ -368,7 +368,7 @@
         if overwrite:
             processed.append(action)
             continue
-        f, m = action[:2]
+        f, m, args, msg = action
 
         choices = (_('&Largefile'), _('&Normal file'))
         if m == "g" and lfutil.splitstandin(f) in p1 and f in p2:
@@ -379,10 +379,10 @@
             msg = _('%s has been turned into a largefile\n'
                     'use (l)argefile or keep as (n)ormal file?') % lfile
             if repo.ui.promptchoice(msg, choices, 0) == 0:
-                processed.append((lfile, "r"))
-                processed.append((standin, "g", p2.flags(standin)))
+                processed.append((lfile, "r", None, msg))
+                processed.append((standin, "g", (p2.flags(standin),), msg))
             else:
-                processed.append((standin, "r"))
+                processed.append((standin, "r", None, msg))
         elif m == "g" and lfutil.standin(f) in p1 and f in p2:
             # Case 2: largefile in the working copy, normal file in
             # the second parent
@@ -391,10 +391,10 @@
             msg = _('%s has been turned into a normal file\n'
                     'keep as (l)argefile or use (n)ormal file?') % lfile
             if repo.ui.promptchoice(msg, choices, 0) == 0:
-                processed.append((lfile, "r"))
+                processed.append((lfile, "r", None, msg))
             else:
-                processed.append((standin, "r"))
-                processed.append((lfile, "g", p2.flags(lfile)))
+                processed.append((standin, "r", None, msg))
+                processed.append((lfile, "g", (p2.flags(lfile),), msg))
         else:
             processed.append(action)
 
--- a/hgext/largefiles/uisetup.py	Wed Feb 06 07:55:29 2013 +0000
+++ b/hgext/largefiles/uisetup.py	Fri Feb 08 14:26:00 2013 +0000
@@ -52,11 +52,12 @@
     entry = extensions.wrapcommand(commands.table, 'verify',
                                    overrides.overrideverify)
 
-    verifyopt = [('', 'large', None, _('verify largefiles')),
+    verifyopt = [('', 'large', None,
+                  _('verify that all largefiles in current revision exists')),
                  ('', 'lfa', None,
-                     _('verify all revisions of largefiles not just current')),
+                  _('verify largefiles in all revisions, not just current')),
                  ('', 'lfc', None,
-                     _('verify largefile contents not just existence'))]
+                  _('verify local largefile contents, not just existence'))]
     entry[1].extend(verifyopt)
 
     entry = extensions.wrapcommand(commands.table, 'debugstate',
--- a/mercurial/bdiff.c	Wed Feb 06 07:55:29 2013 +0000
+++ b/mercurial/bdiff.c	Fri Feb 08 14:26:00 2013 +0000
@@ -347,6 +347,11 @@
 	if (!PyArg_ParseTuple(args, "s#s#:bdiff", &sa, &la, &sb, &lb))
 		return NULL;
 
+	if (la > UINT_MAX || lb > UINT_MAX) {
+		PyErr_SetString(PyExc_ValueError, "bdiff inputs too large");
+		return NULL;
+	}
+
 	_save = PyEval_SaveThread();
 	an = splitlines(sa, la, &al);
 	bn = splitlines(sb, lb, &bl);
@@ -381,18 +386,9 @@
 	for (h = l.next; h; h = h->next) {
 		if (h->a1 != la || h->b1 != lb) {
 			len = bl[h->b1].l - bl[lb].l;
-
-#define checkputbe32(__x, __c) \
-	if (__x > UINT_MAX) { \
-		PyErr_SetString(PyExc_ValueError, \
-		                "bdiff: value too large for putbe32"); \
-		goto nomem; \
-	} \
-	putbe32((uint32_t)(__x), __c);
-
-			checkputbe32(al[la].l - al->l, rb);
-			checkputbe32(al[h->a1].l - al->l, rb + 4);
-			checkputbe32(len, rb + 8);
+			putbe32((uint32_t)(al[la].l - al->l), rb);
+			putbe32((uint32_t)(al[h->a1].l - al->l), rb + 4);
+			putbe32((uint32_t)len, rb + 8);
 			memcpy(rb + 12, bl[lb].l, len);
 			rb += 12 + len;
 		}
--- a/mercurial/cmdutil.py	Wed Feb 06 07:55:29 2013 +0000
+++ b/mercurial/cmdutil.py	Fri Feb 08 14:26:00 2013 +0000
@@ -12,6 +12,7 @@
 import match as matchmod
 import subrepo, context, repair, graphmod, revset, phases, obsolete
 import changelog
+import bookmarks
 import lock as lockmod
 
 def parsealiases(cmd):
@@ -1793,6 +1794,8 @@
         edittext.append(_("HG: branch merge"))
     if ctx.branch():
         edittext.append(_("HG: branch '%s'") % ctx.branch())
+    if bookmarks.iscurrent(repo):
+        edittext.append(_("HG: bookmark '%s'") % repo._bookmarkcurrent)
     edittext.extend([_("HG: subrepo %s") % s for s in subs])
     edittext.extend([_("HG: added %s") % f for f in added])
     edittext.extend([_("HG: changed %s") % f for f in modified])
--- a/mercurial/dirstate.py	Wed Feb 06 07:55:29 2013 +0000
+++ b/mercurial/dirstate.py	Fri Feb 08 14:26:00 2013 +0000
@@ -9,10 +9,8 @@
 from node import nullid
 from i18n import _
 import scmutil, util, ignore, osutil, parsers, encoding
-import struct, os, stat, errno
-import cStringIO
+import os, stat, errno
 
-_format = ">cllll"
 propertycache = util.propertycache
 filecache = scmutil.filecache
 _rangemask = 0x7fffffff
@@ -508,38 +506,7 @@
         # use the modification time of the newly created temporary file as the
         # filesystem's notion of 'now'
         now = util.fstat(st).st_mtime
-        copymap = self._copymap
-        try:
-            finish(parsers.pack_dirstate(self._map, copymap, self._pl, now))
-            return
-        except AttributeError:
-            pass
-
-        now = int(now)
-        cs = cStringIO.StringIO()
-        pack = struct.pack
-        write = cs.write
-        write("".join(self._pl))
-        for f, e in self._map.iteritems():
-            if e[0] == 'n' and e[3] == now:
-                # The file was last modified "simultaneously" with the current
-                # write to dirstate (i.e. within the same second for file-
-                # systems with a granularity of 1 sec). This commonly happens
-                # for at least a couple of files on 'update'.
-                # The user could change the file without changing its size
-                # within the same second. Invalidate the file's stat data in
-                # dirstate, forcing future 'status' calls to compare the
-                # contents of the file. This prevents mistakenly treating such
-                # files as clean.
-                e = (e[0], 0, -1, -1)   # mark entry as 'unset'
-                self._map[f] = e
-
-            if f in copymap:
-                f = "%s\0%s" % (f, copymap[f])
-            e = pack(_format, e[0], e[1], e[2], e[3], len(f))
-            write(e)
-            write(f)
-        finish(cs.getvalue())
+        finish(parsers.pack_dirstate(self._map, self._copymap, self._pl, now))
 
     def _dirignore(self, f):
         if f == '.':
--- a/mercurial/dispatch.py	Wed Feb 06 07:55:29 2013 +0000
+++ b/mercurial/dispatch.py	Fri Feb 08 14:26:00 2013 +0000
@@ -748,6 +748,7 @@
 def lsprofile(ui, func, fp):
     format = ui.config('profiling', 'format', default='text')
     field = ui.config('profiling', 'sort', default='inlinetime')
+    limit = ui.configint('profiling', 'limit', default=30)
     climit = ui.configint('profiling', 'nested', default=5)
 
     if format not in ['text', 'kcachegrind']:
@@ -776,7 +777,7 @@
             # format == 'text'
             stats = lsprof.Stats(p.getstats())
             stats.sort(field)
-            stats.pprint(limit=30, file=fp, climit=climit)
+            stats.pprint(limit=limit, file=fp, climit=climit)
 
 def statprofile(ui, func, fp):
     try:
--- a/mercurial/help/config.txt	Wed Feb 06 07:55:29 2013 +0000
+++ b/mercurial/help/config.txt	Fri Feb 08 14:26:00 2013 +0000
@@ -996,6 +996,10 @@
     ``inlinetime``.
     Default: inlinetime.
 
+``limit``
+    Number of lines to show. Specific to the ``ls`` instrumenting profiler.
+    Default: 30.
+
 ``nested``
     Show at most this number of lines of drill-down info in a tree structure
     after each main entry. This can help explain the difference between Total
--- a/mercurial/help/dates.txt	Wed Feb 06 07:55:29 2013 +0000
+++ b/mercurial/help/dates.txt	Fri Feb 08 14:26:00 2013 +0000
@@ -18,6 +18,8 @@
 - ``12-6``
 - ``12/6``
 - ``12/6/6`` (Dec 6 2006)
+- ``today`` (midnight)
+- ``yesterday`` (midnight)
 
 Lastly, there is Mercurial's internal format:
 
--- a/mercurial/merge.py	Wed Feb 06 07:55:29 2013 +0000
+++ b/mercurial/merge.py	Fri Feb 08 14:26:00 2013 +0000
@@ -176,12 +176,12 @@
     state = branchmerge and 'r' or 'f'
     for f in wctx.deleted():
         if f not in mctx:
-            actions.append((f, state))
+            actions.append((f, state, None, "forget deleted"))
 
     if not branchmerge:
         for f in wctx.removed():
             if f not in mctx:
-                actions.append((f, "f"))
+                actions.append((f, "f", None, "forget removed"))
 
     return actions
 
@@ -193,10 +193,6 @@
     partial = function to filter file lists
     """
 
-    def act(msg, m, f, *args):
-        repo.ui.debug(" %s: %s -> %s\n" % (f, msg, m))
-        actions.append((f, m) + args)
-
     actions, copy, movewithdir = [], {}, {}
 
     if overwrite:
@@ -207,9 +203,9 @@
         ret = copies.mergecopies(repo, p1, p2, pa)
         copy, movewithdir, diverge, renamedelete = ret
         for of, fl in diverge.iteritems():
-            act("divergent renames", "dr", of, fl)
+            actions.append((of, "dr", (fl,), "divergent renames"))
         for of, fl in renamedelete.iteritems():
-            act("rename and delete", "rd", of, fl)
+            actions.append((of, "rd", (fl,), "rename and delete"))
 
     repo.ui.note(_("resolving manifests\n"))
     repo.ui.debug(" overwrite: %s, partial: %s\n"
@@ -227,11 +223,9 @@
                 m1['.hgsubstate'] += "+"
                 break
 
+    prompts = []
     # Compare manifests
-    visit = m1.iteritems()
-    if repo.ui.debugflag:
-        visit = sorted(visit)
-    for f, n in visit:
+    for f, n in m1.iteritems():
         if partial and not partial(f):
             continue
         if f in m2:
@@ -245,72 +239,76 @@
                 pass # remote unchanged - keep local
             elif n == a and fl1 == fla: # local unchanged - use remote
                 if n == n2: # optimization: keep local content
-                    act("update permissions", "e", f, fl2)
+                    actions.append((f, "e", (fl2,), "update permissions"))
                 else:
-                    act("remote is newer", "g", f, fl2)
+                    actions.append((f, "g", (fl2,), "remote is newer"))
             elif nol and n2 == a: # remote only changed 'x'
-                act("update permissions", "e", f, fl2)
+                actions.append((f, "e", (fl2,), "update permissions"))
             elif nol and n == a: # local only changed 'x'
-                act("remote is newer", "g", f, fl1)
+                actions.append((f, "g", (fl1,), "remote is newer"))
             else: # both changed something
-                act("versions differ", "m", f, f, f, False)
+                actions.append((f, "m", (f, f, False), "versions differ"))
         elif f in copied: # files we'll deal with on m2 side
             pass
         elif f in movewithdir: # directory rename
             f2 = movewithdir[f]
-            act("remote renamed directory to " + f2, "d", f, None, f2,
-                m1.flags(f))
+            actions.append((f, "d", (None, f2, m1.flags(f)),
+                            "remote renamed directory to " + f2))
         elif f in copy:
             f2 = copy[f]
-            act("local copied/moved to " + f2, "m", f, f2, f, False)
+            actions.append((f, "m", (f2, f, False),
+                            "local copied/moved to " + f2))
         elif f in ma: # clean, a different, no remote
             if n != ma[f]:
-                if repo.ui.promptchoice(
-                    _(" local changed %s which remote deleted\n"
-                      "use (c)hanged version or (d)elete?") % f,
-                    (_("&Changed"), _("&Delete")), 0):
-                    act("prompt delete", "r", f)
-                else:
-                    act("prompt keep", "a", f)
+                prompts.append((f, "cd")) # prompt changed/deleted
             elif n[20:] == "a": # added, no remote
-                act("remote deleted", "f", f)
+                actions.append((f, "f", None, "remote deleted"))
             else:
-                act("other deleted", "r", f)
+                actions.append((f, "r", None, "other deleted"))
 
-    visit = m2.iteritems()
-    if repo.ui.debugflag:
-        visit = sorted(visit)
-    for f, n in visit:
+    for f, n in m2.iteritems():
         if partial and not partial(f):
             continue
         if f in m1 or f in copied: # files already visited
             continue
         if f in movewithdir:
             f2 = movewithdir[f]
-            act("local renamed directory to " + f2, "d", None, f, f2,
-                m2.flags(f))
+            actions.append((None, "d", (f, f2, m2.flags(f)),
+                            "local renamed directory to " + f2))
         elif f in copy:
             f2 = copy[f]
             if f2 in m2:
-                act("remote copied to " + f, "m",
-                    f2, f, f, False)
+                actions.append((f2, "m", (f, f, False),
+                                "remote copied to " + f))
             else:
-                act("remote moved to " + f, "m",
-                    f2, f, f, True)
+                actions.append((f2, "m", (f, f, True),
+                                "remote moved to " + f))
         elif f not in ma:
             if (not overwrite
                 and _checkunknownfile(repo, p1, p2, f)):
-                act("remote differs from untracked local",
-                    "m", f, f, f, False)
+                actions.append((f, "m", (f, f, False),
+                                "remote differs from untracked local"))
             else:
-                act("remote created", "g", f, m2.flags(f))
+                actions.append((f, "g", (m2.flags(f),), "remote created"))
         elif n != ma[f]:
+            prompts.append((f, "dc")) # prompt deleted/changed
+
+    for f, m in sorted(prompts):
+        if m == "cd":
+            if repo.ui.promptchoice(
+                _("local changed %s which remote deleted\n"
+                  "use (c)hanged version or (d)elete?") % f,
+                (_("&Changed"), _("&Delete")), 0):
+                actions.append((f, "r", None, "prompt delete"))
+            else:
+                actions.append((f, "a", None, "prompt keep"))
+        elif m == "dc":
             if repo.ui.promptchoice(
                 _("remote changed %s which local deleted\n"
                   "use (c)hanged version or leave (d)eleted?") % f,
                 (_("&Changed"), _("&Deleted")), 0) == 0:
-                act("prompt recreating", "g", f, m2.flags(f))
-
+                actions.append((f, "g", (m2.flags(f),), "prompt recreating"))
+        else: assert False, m
     return actions
 
 def actionkey(a):
@@ -335,12 +333,13 @@
 
     # prescan for merges
     for a in actions:
-        f, m = a[:2]
+        f, m, args, msg = a
+        repo.ui.debug(" %s: %s -> %s\n" % (f, msg, m))
         if m == "m": # merge
-            f2, fd, move = a[2:]
+            f2, fd, move = args
             if fd == '.hgsubstate': # merged internally
                 continue
-            repo.ui.debug("preserving %s for resolve of %s\n" % (f, fd))
+            repo.ui.debug("  preserving %s for resolve of %s\n" % (f, fd))
             fcl = wctx[f]
             fco = mctx[f2]
             if mctx == actx: # backwards, use working dir parent as ancestor
@@ -367,7 +366,7 @@
 
     numupdates = len(actions)
     for i, a in enumerate(actions):
-        f, m = a[:2]
+        f, m, args, msg = a
         repo.ui.progress(_('updating'), i + 1, item=f, total=numupdates,
                          unit=_('files'))
         if m == "r": # remove
@@ -386,7 +385,7 @@
                 subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx),
                                  overwrite)
                 continue
-            f2, fd, move = a[2:]
+            f2, fd, move = args
             audit(fd)
             r = ms.resolve(fd, wctx, mctx)
             if r is not None and r > 0:
@@ -397,14 +396,14 @@
                 else:
                     merged += 1
         elif m == "g": # get
-            flags = a[2]
+            flags, = args
             repo.ui.note(_("getting %s\n") % f)
             repo.wwrite(f, mctx.filectx(f).data(), flags)
             updated += 1
             if f == '.hgsubstate': # subrepo states need updating
                 subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
         elif m == "d": # directory rename
-            f2, fd, flags = a[2:]
+            f2, fd, flags = args
             if f:
                 repo.ui.note(_("moving %s to %s\n") % (f, fd))
                 audit(f)
@@ -415,19 +414,19 @@
                 repo.wwrite(fd, mctx.filectx(f2).data(), flags)
             updated += 1
         elif m == "dr": # divergent renames
-            fl = a[2]
+            fl, = args
             repo.ui.warn(_("note: possible conflict - %s was renamed "
                            "multiple times to:\n") % f)
             for nf in fl:
                 repo.ui.warn(" %s\n" % nf)
         elif m == "rd": # rename and delete
-            fl = a[2]
+            fl, = args
             repo.ui.warn(_("note: possible conflict - %s was deleted "
                            "and renamed to:\n") % f)
             for nf in fl:
                 repo.ui.warn(" %s\n" % nf)
         elif m == "e": # exec
-            flags = a[2]
+            flags, = args
             audit(f)
             util.setflags(repo.wjoin(f), 'l' in flags, 'x' in flags)
             updated += 1
@@ -461,7 +460,7 @@
     "record merge actions to the dirstate"
 
     for a in actions:
-        f, m = a[:2]
+        f, m, args, msg = a
         if m == "r": # remove
             if branchmerge:
                 repo.dirstate.remove(f)
@@ -480,7 +479,7 @@
             else:
                 repo.dirstate.normal(f)
         elif m == "m": # merge
-            f2, fd, move = a[2:]
+            f2, fd, move = args
             if branchmerge:
                 # We've done a branch merge, mark this file as merged
                 # so that we properly record the merger later
@@ -503,7 +502,7 @@
                 if move:
                     repo.dirstate.drop(f)
         elif m == "d": # directory rename
-            f2, fd, flag = a[2:]
+            f2, fd, flag = args
             if not f2 and f not in repo.dirstate:
                 # untracked file moved
                 continue
--- a/mercurial/parsers.c	Wed Feb 06 07:55:29 2013 +0000
+++ b/mercurial/parsers.c	Fri Feb 08 14:26:00 2013 +0000
@@ -326,7 +326,8 @@
 		if (getintat(v, 3, &mtime) == -1)
 			goto bail;
 		if (*s == 'n' && mtime == (uint32_t)now) {
-			/* See dirstate.py:write for why we do this. */
+			/* See pure/parsers.py:pack_dirstate for why we do
+			 * this. */
 			if (PyDict_SetItem(map, k, dirstate_unset) == -1)
 				goto bail;
 			mode = 0, size = -1, mtime = -1;
--- a/mercurial/pure/parsers.py	Wed Feb 06 07:55:29 2013 +0000
+++ b/mercurial/pure/parsers.py	Fri Feb 08 14:26:00 2013 +0000
@@ -7,7 +7,7 @@
 
 from mercurial.node import bin, nullid
 from mercurial import util
-import struct, zlib
+import struct, zlib, cStringIO
 
 _pack = struct.pack
 _unpack = struct.unpack
@@ -87,3 +87,29 @@
             copymap[f] = c
         dmap[f] = e[:4]
     return parents
+
+def pack_dirstate(dmap, copymap, pl, now):
+    now = int(now)
+    cs = cStringIO.StringIO()
+    write = cs.write
+    write("".join(pl))
+    for f, e in dmap.iteritems():
+        if e[0] == 'n' and e[3] == now:
+            # The file was last modified "simultaneously" with the current
+            # write to dirstate (i.e. within the same second for file-
+            # systems with a granularity of 1 sec). This commonly happens
+            # for at least a couple of files on 'update'.
+            # The user could change the file without changing its size
+            # within the same second. Invalidate the file's stat data in
+            # dirstate, forcing future 'status' calls to compare the
+            # contents of the file. This prevents mistakenly treating such
+            # files as clean.
+            e = (e[0], 0, -1, -1)   # mark entry as 'unset'
+            dmap[f] = e
+
+        if f in copymap:
+            f = "%s\0%s" % (f, copymap[f])
+        e = _pack(">cllll", e[0], e[1], e[2], e[3], len(f))
+        write(e)
+        write(f)
+    return cs.getvalue()
--- a/mercurial/revset.py	Wed Feb 06 07:55:29 2013 +0000
+++ b/mercurial/revset.py	Fri Feb 08 14:26:00 2013 +0000
@@ -277,20 +277,32 @@
     return checkstatus(repo, subset, pat, 1)
 
 def ancestor(repo, subset, x):
-    """``ancestor(single, single)``
-    Greatest common ancestor of the two changesets.
+    """``ancestor(*changeset)``
+    Greatest common ancestor of the changesets.
+
+    Accepts 0 or more changesets.
+    Will return empty list when passed no args.
+    Greatest common ancestor of a single changeset is that changeset.
     """
     # i18n: "ancestor" is a keyword
-    l = getargs(x, 2, 2, _("ancestor requires two arguments"))
-    r = list(repo)
-    a = getset(repo, r, l[0])
-    b = getset(repo, r, l[1])
-    if len(a) != 1 or len(b) != 1:
-        # i18n: "ancestor" is a keyword
-        raise error.ParseError(_("ancestor arguments must be single revisions"))
-    an = [repo[a[0]].ancestor(repo[b[0]]).rev()]
+    l = getlist(x)
+    rl = list(repo)
+    anc = None
 
-    return [r for r in an if r in subset]
+    # (getset(repo, rl, i) for i in l) generates a list of lists
+    rev = repo.changelog.rev
+    ancestor = repo.changelog.ancestor
+    node = repo.changelog.node
+    for revs in (getset(repo, rl, i) for i in l):
+        for r in revs:
+            if anc is None:
+                anc = r
+            else:
+                anc = rev(ancestor(node(anc), node(r)))
+
+    if anc is not None and anc in subset:
+        return [anc]
+    return []
 
 def _ancestors(repo, subset, x, followfirst=False):
     args = getset(repo, list(repo), x)
--- a/mercurial/scmutil.py	Wed Feb 06 07:55:29 2013 +0000
+++ b/mercurial/scmutil.py	Fri Feb 08 14:26:00 2013 +0000
@@ -34,6 +34,11 @@
     for c in (':', '\0', '\n', '\r'):
         if c in lbl:
             raise util.Abort(_("%r cannot be used in a name") % c)
+    try:
+        int(lbl)
+        raise util.Abort(_("a %s cannot have an integer as its name") % kind)
+    except ValueError:
+        pass
 
 def checkfilename(f):
     '''Check that the filename f is an acceptable filename for a tracked file'''
@@ -733,29 +738,33 @@
     rejected = []
     m.bad = lambda x, y: rejected.append(x)
 
-    for abs in repo.walk(m):
-        target = repo.wjoin(abs)
+    ctx = repo[None]
+    walkresults = repo.dirstate.walk(m, sorted(ctx.substate), True, False)
+    for abs in sorted(walkresults):
         good = True
         try:
             audit_path(abs)
         except (OSError, util.Abort):
             good = False
-        rel = m.rel(abs)
-        exact = m.exact(abs)
-        if good and abs not in repo.dirstate:
+
+        st = walkresults[abs]
+        dstate = repo.dirstate[abs]
+        if good and dstate == '?':
             unknown.append(abs)
-            if repo.ui.verbose or not exact:
+            if repo.ui.verbose or not m.exact(abs):
+                rel = m.rel(abs)
                 repo.ui.status(_('adding %s\n') % ((pats and rel) or abs))
-        elif (repo.dirstate[abs] != 'r' and
-              (not good or not os.path.lexists(target) or
-               (os.path.isdir(target) and not os.path.islink(target)))):
+        elif (dstate != 'r' and
+              (not good or not st or
+               (stat.S_ISDIR(st.st_mode) and not stat.S_ISLNK(st.st_mode)))):
             deleted.append(abs)
-            if repo.ui.verbose or not exact:
+            if repo.ui.verbose or not m.exact(abs):
+                rel = m.rel(abs)
                 repo.ui.status(_('removing %s\n') % ((pats and rel) or abs))
         # for finding renames
-        elif repo.dirstate[abs] == 'r':
+        elif dstate == 'r':
             removed.append(abs)
-        elif repo.dirstate[abs] == 'a':
+        elif dstate == 'a':
             added.append(abs)
     copies = {}
     if similarity > 0:
--- a/mercurial/util.py	Wed Feb 06 07:55:29 2013 +0000
+++ b/mercurial/util.py	Fri Feb 08 14:26:00 2013 +0000
@@ -1027,6 +1027,14 @@
 
     The date may be a "unixtime offset" string or in one of the specified
     formats. If the date already is a (unixtime, offset) tuple, it is returned.
+
+    >>> parsedate(' today ') == parsedate(\
+                                  datetime.date.today().strftime('%b %d'))
+    True
+    >>> parsedate( 'yesterday ') == parsedate((datetime.date.today() -\
+                                               datetime.timedelta(days=1)\
+                                              ).strftime('%b %d'))
+    True
     """
     if not date:
         return 0, 0
@@ -1035,6 +1043,13 @@
     if not formats:
         formats = defaultdateformats
     date = date.strip()
+
+    if date == _('today'):
+        date = datetime.date.today().strftime('%b %d')
+    elif date == _('yesterday'):
+        date = (datetime.date.today() -
+                datetime.timedelta(days=1)).strftime('%b %d')
+
     try:
         when, offset = map(int, date.split(' '))
     except ValueError:
--- a/tests/run-tests.py	Wed Feb 06 07:55:29 2013 +0000
+++ b/tests/run-tests.py	Fri Feb 08 14:26:00 2013 +0000
@@ -622,6 +622,7 @@
         script.append('set -x\n')
     if os.getenv('MSYSTEM'):
         script.append('alias pwd="pwd -W"\n')
+    n = 0
     for n, l in enumerate(t):
         if not l.endswith('\n'):
             l += '\n'
--- a/tests/test-bookmarks.t	Wed Feb 06 07:55:29 2013 +0000
+++ b/tests/test-bookmarks.t	Fri Feb 08 14:26:00 2013 +0000
@@ -257,6 +257,12 @@
   abort: a bookmark cannot have the name of an existing branch
   [255]
 
+bookmark with integer name
+
+  $ hg bookmark 10
+  abort: a bookmark cannot have an integer as its name
+  [255]
+
 incompatible options
 
   $ hg bookmark -m Y -d Z
--- a/tests/test-commit.t	Wed Feb 06 07:55:29 2013 +0000
+++ b/tests/test-commit.t	Fri Feb 08 14:26:00 2013 +0000
@@ -263,6 +263,7 @@
   $ cd commitmsg
   $ echo changed > changed
   $ echo removed > removed
+  $ hg book currentbookmark
   $ hg ci -qAm init
 
   $ hg rm removed
@@ -277,6 +278,7 @@
   HG: --
   HG: user: test
   HG: branch 'default'
+  HG: bookmark 'currentbookmark'
   HG: added added
   HG: changed changed
   HG: removed removed
--- a/tests/test-copy-move-merge.t	Wed Feb 06 07:55:29 2013 +0000
+++ b/tests/test-copy-move-merge.t	Fri Feb 08 14:26:00 2013 +0000
@@ -32,9 +32,9 @@
    overwrite: False, partial: False
    ancestor: b8bf91eeebbc, local: add3f11052fa+, remote: 17c05bb7fcb6
    a: remote moved to b -> m
+    preserving a for resolve of b
    a: remote moved to c -> m
-  preserving a for resolve of b
-  preserving a for resolve of c
+    preserving a for resolve of c
   removing a
   updating: a 1/2 files (50.00%)
   picked tool 'internal:merge' for b (binary False symlink False)
--- a/tests/test-double-merge.t	Wed Feb 06 07:55:29 2013 +0000
+++ b/tests/test-double-merge.t	Fri Feb 08 14:26:00 2013 +0000
@@ -35,10 +35,10 @@
   resolving manifests
    overwrite: False, partial: False
    ancestor: e6dc8efe11cc, local: 6a0df1dad128+, remote: 484bf6903104
+   foo: remote copied to bar -> m
+    preserving foo for resolve of bar
    foo: versions differ -> m
-   foo: remote copied to bar -> m
-  preserving foo for resolve of bar
-  preserving foo for resolve of foo
+    preserving foo for resolve of foo
   updating: foo 1/2 files (50.00%)
   picked tool 'internal:merge' for bar (binary False symlink False)
   merging foo and bar to bar
--- a/tests/test-graft.t	Wed Feb 06 07:55:29 2013 +0000
+++ b/tests/test-graft.t	Fri Feb 08 14:26:00 2013 +0000
@@ -137,7 +137,7 @@
    overwrite: False, partial: False
    ancestor: 68795b066622, local: ef0ef43d49e7+, remote: 5d205f8b35b6
    b: local copied/moved to a -> m
-  preserving b for resolve of b
+    preserving b for resolve of b
   updating: b 1/1 files (100.00%)
   picked tool 'internal:merge' for b (binary False symlink False)
   merging b and a to b
@@ -160,7 +160,7 @@
    ancestor: 4c60f11aa304, local: 1905859650ec+, remote: 9c233e8e184d
    d: remote is newer -> g
    e: versions differ -> m
-  preserving e for resolve of e
+    preserving e for resolve of e
   updating: d 1/2 files (50.00%)
   getting d
   updating: e 2/2 files (100.00%)
--- a/tests/test-issue672.t	Wed Feb 06 07:55:29 2013 +0000
+++ b/tests/test-issue672.t	Fri Feb 08 14:26:00 2013 +0000
@@ -66,7 +66,7 @@
    overwrite: False, partial: False
    ancestor: c64f439569a9, local: e327dca35ac8+, remote: 746e9549ea96
    1a: local copied/moved to 1 -> m
-  preserving 1a for resolve of 1a
+    preserving 1a for resolve of 1a
   updating: 1a 1/1 files (100.00%)
   picked tool 'internal:merge' for 1a (binary False symlink False)
   merging 1a and 1 to 1a
@@ -89,7 +89,7 @@
    overwrite: False, partial: False
    ancestor: c64f439569a9, local: 746e9549ea96+, remote: e327dca35ac8
    1: remote moved to 1a -> m
-  preserving 1 for resolve of 1a
+    preserving 1 for resolve of 1a
   removing 1
   updating: 1 1/1 files (100.00%)
   picked tool 'internal:merge' for 1a (binary False symlink False)
--- a/tests/test-largefiles.t	Wed Feb 06 07:55:29 2013 +0000
+++ b/tests/test-largefiles.t	Fri Feb 08 14:26:00 2013 +0000
@@ -1210,20 +1210,14 @@
   checking files
   10 files, 10 changesets, 28 total revisions
   searching 1 changesets for largefiles
-  changeset 9:598410d3eb9a: sub/large4 missing
-    (looked for hash e166e74c7303192238d60af5a9c4ce9bef0b7928)
+  changeset 9:598410d3eb9a: sub/large4 references missing $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 (glob)
   verified existence of 3 revisions of 3 largefiles
   [1]
 
 - introduce corruption and make sure that it is caught when checking content:
   $ echo '5 cents' > $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928
   $ hg verify -q --large --lfc
-  searching 1 changesets for largefiles
-  changeset 9:598410d3eb9a: sub/large4: contents differ
-    ($TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928: (glob)
-    expected hash e166e74c7303192238d60af5a9c4ce9bef0b7928,
-    but got 1f19b76d5b3cad1472c87efb42b582c97e040060)
-  verified contents of 3 revisions of 3 largefiles
+  changeset 9:598410d3eb9a: sub/large4 references corrupted $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 (glob)
   [1]
 
 - cleanup
@@ -1231,31 +1225,14 @@
 
 - verifying all revisions will fail because we didn't clone all largefiles to d:
   $ echo 'T-shirt' > $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
-  $ hg verify -q --large --lfa --lfc
-  searching 10 changesets for largefiles
-  changeset 0:30d30fe6a5be: large1 missing
-    (looked for hash 4669e532d5b2c093a78eca010077e708a071bb64)
-  changeset 0:30d30fe6a5be: sub/large2 missing
-    (looked for hash 1deebade43c8c498a3c8daddac0244dc55d1331d)
-  changeset 1:ce8896473775: large1 missing
-    (looked for hash 5f78770c0e77ba4287ad6ef3071c9bf9c379742f)
-  changeset 1:ce8896473775: sub/large2: contents differ
-    ($TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4: (glob)
-    expected hash eb7338044dc27f9bc59b8dd5a246b065ead7a9c4,
-    but got cfef678f24d3e339944138ecdd8fd85ca21d820f)
-  changeset 3:9e8fbc4bce62: large1: contents differ
-    ($TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4: (glob)
-    expected hash eb7338044dc27f9bc59b8dd5a246b065ead7a9c4,
-    but got cfef678f24d3e339944138ecdd8fd85ca21d820f)
-  changeset 4:74c02385b94c: large3: contents differ
-    ($TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4: (glob)
-    expected hash eb7338044dc27f9bc59b8dd5a246b065ead7a9c4,
-    but got cfef678f24d3e339944138ecdd8fd85ca21d820f)
-  changeset 4:74c02385b94c: sub/large4: contents differ
-    ($TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4: (glob)
-    expected hash eb7338044dc27f9bc59b8dd5a246b065ead7a9c4,
-    but got cfef678f24d3e339944138ecdd8fd85ca21d820f)
-  verified contents of 15 revisions of 6 largefiles
+  $ hg verify -q --lfa --lfc
+  changeset 0:30d30fe6a5be: large1 references missing $TESTTMP/d/.hg/largefiles/4669e532d5b2c093a78eca010077e708a071bb64 (glob)
+  changeset 0:30d30fe6a5be: sub/large2 references missing $TESTTMP/d/.hg/largefiles/1deebade43c8c498a3c8daddac0244dc55d1331d (glob)
+  changeset 1:ce8896473775: large1 references missing $TESTTMP/d/.hg/largefiles/5f78770c0e77ba4287ad6ef3071c9bf9c379742f (glob)
+  changeset 1:ce8896473775: sub/large2 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob)
+  changeset 3:9e8fbc4bce62: large1 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob)
+  changeset 4:74c02385b94c: large3 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob)
+  changeset 4:74c02385b94c: sub/large4 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob)
   [1]
 
 - cleanup
@@ -1664,8 +1641,6 @@
   [1]
   $ mv 02a439e5c31c526465ab1a0ca1f431f76b827b90 empty/.hg/largefiles/
   $ hg -R http-clone -q verify --large --lfa
-  searching 1 changesets for largefiles
-  verified existence of 1 revisions of 1 largefiles
 
 largefiles pulled on update - a largefile missing on the server:
   $ mv empty/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90 .
--- a/tests/test-lfconvert.t	Wed Feb 06 07:55:29 2013 +0000
+++ b/tests/test-lfconvert.t	Fri Feb 08 14:26:00 2013 +0000
@@ -317,18 +317,12 @@
   checking files
   8 files, 7 changesets, 12 total revisions
   searching 7 changesets for largefiles
-  changeset 0:d4892ec57ce2: large missing
-    (looked for hash 2e000fa7e85759c7f4c254d4d9c33ef481e459a7)
-  changeset 1:334e5237836d: sub/maybelarge.dat missing
-    (looked for hash 34e163be8e43c5631d8b92e9c43ab0bf0fa62b9c)
-  changeset 2:261ad3f3f037: stuff/maybelarge.dat missing
-    (looked for hash 34e163be8e43c5631d8b92e9c43ab0bf0fa62b9c)
-  changeset 3:55759520c76f: sub/maybelarge.dat missing
-    (looked for hash 76236b6a2c6102826c61af4297dd738fb3b1de38)
-  changeset 5:9cc5aa7204f0: stuff/maybelarge.dat missing
-    (looked for hash 76236b6a2c6102826c61af4297dd738fb3b1de38)
-  changeset 6:17126745edfd: anotherlarge missing
-    (looked for hash 3b71f43ff30f4b15b5cd85dd9e95ebc7e84eb5a3)
+  changeset 0:d4892ec57ce2: large references missing $TESTTMP/largefiles-repo-hg/.hg/largefiles/2e000fa7e85759c7f4c254d4d9c33ef481e459a7 (glob)
+  changeset 1:334e5237836d: sub/maybelarge.dat references missing $TESTTMP/largefiles-repo-hg/.hg/largefiles/34e163be8e43c5631d8b92e9c43ab0bf0fa62b9c (glob)
+  changeset 2:261ad3f3f037: stuff/maybelarge.dat references missing $TESTTMP/largefiles-repo-hg/.hg/largefiles/34e163be8e43c5631d8b92e9c43ab0bf0fa62b9c (glob)
+  changeset 3:55759520c76f: sub/maybelarge.dat references missing $TESTTMP/largefiles-repo-hg/.hg/largefiles/76236b6a2c6102826c61af4297dd738fb3b1de38 (glob)
+  changeset 5:9cc5aa7204f0: stuff/maybelarge.dat references missing $TESTTMP/largefiles-repo-hg/.hg/largefiles/76236b6a2c6102826c61af4297dd738fb3b1de38 (glob)
+  changeset 6:17126745edfd: anotherlarge references missing $TESTTMP/largefiles-repo-hg/.hg/largefiles/3b71f43ff30f4b15b5cd85dd9e95ebc7e84eb5a3 (glob)
   verified existence of 6 revisions of 4 largefiles
   [1]
   $ hg -R largefiles-repo-hg showconfig paths
--- a/tests/test-merge-commit.t	Wed Feb 06 07:55:29 2013 +0000
+++ b/tests/test-merge-commit.t	Fri Feb 08 14:26:00 2013 +0000
@@ -72,7 +72,7 @@
    overwrite: False, partial: False
    ancestor: 0f2ff26688b9, local: 2263c1be0967+, remote: 0555950ead28
    bar: versions differ -> m
-  preserving bar for resolve of bar
+    preserving bar for resolve of bar
   updating: bar 1/1 files (100.00%)
   picked tool 'internal:merge' for bar (binary False symlink False)
   merging bar
@@ -159,7 +159,7 @@
    overwrite: False, partial: False
    ancestor: 0f2ff26688b9, local: 2263c1be0967+, remote: 3ffa6b9e35f0
    bar: versions differ -> m
-  preserving bar for resolve of bar
+    preserving bar for resolve of bar
   updating: bar 1/1 files (100.00%)
   picked tool 'internal:merge' for bar (binary False symlink False)
   merging bar
--- a/tests/test-merge-prompt.t	Wed Feb 06 07:55:29 2013 +0000
+++ b/tests/test-merge-prompt.t	Fri Feb 08 14:26:00 2013 +0000
@@ -42,7 +42,7 @@
 Non-interactive merge:
 
   $ hg merge -y
-   local changed file1 which remote deleted
+  local changed file1 which remote deleted
   use (c)hanged version or (d)elete? c
   remote changed file2 which local deleted
   use (c)hanged version or leave (d)eleted? c
@@ -70,7 +70,7 @@
   > c
   > d
   > EOF
-   local changed file1 which remote deleted
+  local changed file1 which remote deleted
   use (c)hanged version or (d)elete? remote changed file2 which local deleted
   use (c)hanged version or leave (d)eleted? 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   (branch merge, don't forget to commit)
@@ -97,11 +97,11 @@
   > baz
   > c
   > EOF
-   local changed file1 which remote deleted
+  local changed file1 which remote deleted
   use (c)hanged version or (d)elete? unrecognized response
-   local changed file1 which remote deleted
+  local changed file1 which remote deleted
   use (c)hanged version or (d)elete? unrecognized response
-   local changed file1 which remote deleted
+  local changed file1 which remote deleted
   use (c)hanged version or (d)elete? remote changed file2 which local deleted
   use (c)hanged version or leave (d)eleted? unrecognized response
   remote changed file2 which local deleted
@@ -126,7 +126,7 @@
   $ hg merge --config ui.interactive=true <<EOF
   > d
   > EOF
-   local changed file1 which remote deleted
+  local changed file1 which remote deleted
   use (c)hanged version or (d)elete? remote changed file2 which local deleted
   use (c)hanged version or leave (d)eleted? abort: response expected
   [255]
--- a/tests/test-merge-types.t	Wed Feb 06 07:55:29 2013 +0000
+++ b/tests/test-merge-types.t	Fri Feb 08 14:26:00 2013 +0000
@@ -35,7 +35,7 @@
    overwrite: False, partial: False
    ancestor: c334dc3be0da, local: 521a1e40188f+, remote: 3574f3e69b1c
    a: versions differ -> m
-  preserving a for resolve of a
+    preserving a for resolve of a
   updating: a 1/1 files (100.00%)
   picked tool 'internal:merge' for a (binary False symlink True)
   merging a
@@ -68,7 +68,7 @@
    overwrite: False, partial: False
    ancestor: c334dc3be0da, local: 3574f3e69b1c+, remote: 521a1e40188f
    a: versions differ -> m
-  preserving a for resolve of a
+    preserving a for resolve of a
   updating: a 1/1 files (100.00%)
   picked tool 'internal:merge' for a (binary False symlink True)
   merging a
@@ -102,7 +102,7 @@
    overwrite: False, partial: False
    ancestor: c334dc3be0da, local: c334dc3be0da+, remote: 521a1e40188f
    a: versions differ -> m
-  preserving a for resolve of a
+    preserving a for resolve of a
   updating: a 1/1 files (100.00%)
   (couldn't find merge tool hgmerge|tool hgmerge can't handle symlinks) (re)
   picked tool 'internal:prompt' for a (binary False symlink True)
--- a/tests/test-merge7.t	Wed Feb 06 07:55:29 2013 +0000
+++ b/tests/test-merge7.t	Fri Feb 08 14:26:00 2013 +0000
@@ -84,7 +84,7 @@
    overwrite: False, partial: False
    ancestor: 96b70246a118, local: 50c3a7e29886+, remote: 40d11a4173a8
    test.txt: versions differ -> m
-  preserving test.txt for resolve of test.txt
+    preserving test.txt for resolve of test.txt
   updating: test.txt 1/1 files (100.00%)
   picked tool 'internal:merge' for test.txt (binary False symlink False)
   merging test.txt
--- a/tests/test-parse-date.t	Wed Feb 06 07:55:29 2013 +0000
+++ b/tests/test-parse-date.t	Fri Feb 08 14:26:00 2013 +0000
@@ -234,3 +234,20 @@
   Sat Apr 15 13:30:00 2006 +0000
   Wed Feb 01 13:00:30 2006 -0500
   Wed Feb 01 13:00:30 2006 +0000
+
+Test issue 3764 (interpreting 'today' and 'yesterday')
+  $ echo "hello" >> a
+  >>> import datetime
+  >>> today = datetime.date.today().strftime("%b %d")
+  >>> yesterday = (datetime.date.today() - datetime.timedelta(days=1)).strftime("%b %d")
+  >>> dates = open('dates', 'w')
+  >>> dates.write(today + '\n')
+  >>> dates.write(yesterday)
+  >>> dates.close()
+  $ hg ci -d "`sed -n '1p' dates`" -m "today is a good day to code"
+  $ hg log -d today --template '{desc}\n'
+  today is a good day to code
+  $ echo "goodbye" >> a
+  $ hg ci -d "`sed -n '2p' dates`" -m "the time traveler's code"
+  $ hg log -d yesterday --template '{desc}\n'
+  the time traveler's code
--- a/tests/test-rebase-collapse.t	Wed Feb 06 07:55:29 2013 +0000
+++ b/tests/test-rebase-collapse.t	Fri Feb 08 14:26:00 2013 +0000
@@ -496,15 +496,15 @@
   $ hg ci -Am 'A'
   adding a
 
-  $ hg branch '1'
-  marked working directory as branch 1
+  $ hg branch 'one'
+  marked working directory as branch one
   (branches are permanent and global, did you want a bookmark?)
   $ echo 'b' > b
   $ hg ci -Am 'B'
   adding b
 
-  $ hg branch '2'
-  marked working directory as branch 2
+  $ hg branch 'two'
+  marked working directory as branch two
   (branches are permanent and global, did you want a bookmark?)
   $ echo 'c' > c
   $ hg ci -Am 'C'
@@ -518,9 +518,9 @@
   $ hg tglog
   @  3: 'D'
   |
-  | o  2: 'C' 2
+  | o  2: 'C' two
   | |
-  | o  1: 'B' 1
+  | o  1: 'B' one
   |/
   o  0: 'A'
   
@@ -546,9 +546,9 @@
   |/
   o  3: 'D'
   |
-  | o  2: 'C' 2
+  | o  2: 'C' two
   | |
-  | o  1: 'B' 1
+  | o  1: 'B' one
   |/
   o  0: 'A'
   
@@ -559,9 +559,9 @@
   |
   o  3: 'D'
   |
-  | o  2: 'C' 2
+  | o  2: 'C' two
   | |
-  | o  1: 'B' 1
+  | o  1: 'B' one
   |/
   o  0: 'A'
   
--- a/tests/test-rename-merge1.t	Wed Feb 06 07:55:29 2013 +0000
+++ b/tests/test-rename-merge1.t	Fri Feb 08 14:26:00 2013 +0000
@@ -33,13 +33,13 @@
      src: 'a2' -> dst: 'b2' !
      src: 'a2' -> dst: 'c2' !
     checking for directory renames
-   a2: divergent renames -> dr
   resolving manifests
    overwrite: False, partial: False
    ancestor: af1939970a1c, local: 044f8520aeeb+, remote: 85c198ef2f6c
    a: remote moved to b -> m
+    preserving a for resolve of b
+   a2: divergent renames -> dr
    b2: remote created -> g
-  preserving a for resolve of b
   removing a
   updating: a 1/3 files (33.33%)
   picked tool 'internal:merge' for b (binary False symlink False)
@@ -178,10 +178,10 @@
     all copies found (* = to merge, ! = divergent, % = renamed and deleted):
      src: 'file' -> dst: 'newfile' %
     checking for directory renames
-   file: rename and delete -> rd
   resolving manifests
    overwrite: False, partial: False
    ancestor: 19d7f95df299, local: 0084274f6b67+, remote: 5d32493049f0
+   file: rename and delete -> rd
    newfile: remote created -> g
   updating: file 1/2 files (50.00%)
   note: possible conflict - file was deleted and renamed to:
--- a/tests/test-rename-merge2.t	Wed Feb 06 07:55:29 2013 +0000
+++ b/tests/test-rename-merge2.t	Fri Feb 08 14:26:00 2013 +0000
@@ -86,10 +86,10 @@
   resolving manifests
    overwrite: False, partial: False
    ancestor: 924404dff337, local: e300d1c794ec+, remote: 4ce40f5aca24
+   a: remote copied to b -> m
+    preserving a for resolve of b
    rev: versions differ -> m
-   a: remote copied to b -> m
-  preserving a for resolve of b
-  preserving rev for resolve of rev
+    preserving rev for resolve of rev
   updating: a 1/2 files (50.00%)
   picked tool 'python ../merge' for b (binary False symlink False)
   merging a and b to b
@@ -123,9 +123,9 @@
    ancestor: 924404dff337, local: 86a2aa42fc76+, remote: f4db7e329e71
    a: remote is newer -> g
    b: local copied/moved to a -> m
+    preserving b for resolve of b
    rev: versions differ -> m
-  preserving b for resolve of b
-  preserving rev for resolve of rev
+    preserving rev for resolve of rev
   updating: a 1/3 files (33.33%)
   getting a
   updating: b 2/3 files (66.67%)
@@ -159,10 +159,10 @@
   resolving manifests
    overwrite: False, partial: False
    ancestor: 924404dff337, local: e300d1c794ec+, remote: bdb19105162a
+   a: remote moved to b -> m
+    preserving a for resolve of b
    rev: versions differ -> m
-   a: remote moved to b -> m
-  preserving a for resolve of b
-  preserving rev for resolve of rev
+    preserving rev for resolve of rev
   removing a
   updating: a 1/2 files (50.00%)
   picked tool 'python ../merge' for b (binary False symlink False)
@@ -195,9 +195,9 @@
    overwrite: False, partial: False
    ancestor: 924404dff337, local: 02963e448370+, remote: f4db7e329e71
    b: local copied/moved to a -> m
+    preserving b for resolve of b
    rev: versions differ -> m
-  preserving b for resolve of b
-  preserving rev for resolve of rev
+    preserving rev for resolve of rev
   updating: b 1/2 files (50.00%)
   picked tool 'python ../merge' for b (binary False symlink False)
   merging b and a to b
@@ -228,9 +228,9 @@
   resolving manifests
    overwrite: False, partial: False
    ancestor: 924404dff337, local: 94b33a1b7f2d+, remote: 4ce40f5aca24
+   b: remote created -> g
    rev: versions differ -> m
-   b: remote created -> g
-  preserving rev for resolve of rev
+    preserving rev for resolve of rev
   updating: b 1/2 files (50.00%)
   getting b
   updating: rev 2/2 files (100.00%)
@@ -259,7 +259,7 @@
    overwrite: False, partial: False
    ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 97c705ade336
    rev: versions differ -> m
-  preserving rev for resolve of rev
+    preserving rev for resolve of rev
   updating: rev 1/1 files (100.00%)
   picked tool 'python ../merge' for rev (binary False symlink False)
   merging rev
@@ -286,9 +286,9 @@
    overwrite: False, partial: False
    ancestor: 924404dff337, local: 94b33a1b7f2d+, remote: bdb19105162a
    a: other deleted -> r
+   b: remote created -> g
    rev: versions differ -> m
-   b: remote created -> g
-  preserving rev for resolve of rev
+    preserving rev for resolve of rev
   updating: a 1/3 files (33.33%)
   removing a
   updating: b 2/3 files (66.67%)
@@ -318,7 +318,7 @@
    overwrite: False, partial: False
    ancestor: 924404dff337, local: 02963e448370+, remote: 97c705ade336
    rev: versions differ -> m
-  preserving rev for resolve of rev
+    preserving rev for resolve of rev
   updating: rev 1/1 files (100.00%)
   picked tool 'python ../merge' for rev (binary False symlink False)
   merging rev
@@ -339,9 +339,9 @@
    overwrite: False, partial: False
    ancestor: 924404dff337, local: 62e7bf090eba+, remote: 49b6d8032493
    b: versions differ -> m
+    preserving b for resolve of b
    rev: versions differ -> m
-  preserving b for resolve of b
-  preserving rev for resolve of rev
+    preserving rev for resolve of rev
   updating: b 1/2 files (50.00%)
   picked tool 'python ../merge' for b (binary False symlink False)
   merging b
@@ -373,13 +373,13 @@
      src: 'a' -> dst: 'b' !
      src: 'a' -> dst: 'c' !
     checking for directory renames
-   a: divergent renames -> dr
   resolving manifests
    overwrite: False, partial: False
    ancestor: 924404dff337, local: 02963e448370+, remote: fe905ef2c33e
-   rev: versions differ -> m
+   a: divergent renames -> dr
    c: remote created -> g
-  preserving rev for resolve of rev
+   rev: versions differ -> m
+    preserving rev for resolve of rev
   updating: a 1/3 files (33.33%)
   note: possible conflict - a was renamed multiple times to:
    b
@@ -407,9 +407,9 @@
    overwrite: False, partial: False
    ancestor: 924404dff337, local: 86a2aa42fc76+, remote: af30c7647fc7
    b: versions differ -> m
+    preserving b for resolve of b
    rev: versions differ -> m
-  preserving b for resolve of b
-  preserving rev for resolve of rev
+    preserving rev for resolve of rev
   updating: b 1/2 files (50.00%)
   picked tool 'python ../merge' for b (binary False symlink False)
   merging b
@@ -436,9 +436,9 @@
    ancestor: 924404dff337, local: 59318016310c+, remote: bdb19105162a
    a: other deleted -> r
    b: versions differ -> m
+    preserving b for resolve of b
    rev: versions differ -> m
-  preserving b for resolve of b
-  preserving rev for resolve of rev
+    preserving rev for resolve of rev
   updating: a 1/3 files (33.33%)
   removing a
   updating: b 2/3 files (66.67%)
@@ -466,9 +466,9 @@
    ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 8dbce441892a
    a: remote is newer -> g
    b: versions differ -> m
+    preserving b for resolve of b
    rev: versions differ -> m
-  preserving b for resolve of b
-  preserving rev for resolve of rev
+    preserving rev for resolve of rev
   updating: a 1/3 files (33.33%)
   getting a
   updating: b 2/3 files (66.67%)
@@ -497,9 +497,9 @@
    ancestor: 924404dff337, local: 59318016310c+, remote: bdb19105162a
    a: other deleted -> r
    b: versions differ -> m
+    preserving b for resolve of b
    rev: versions differ -> m
-  preserving b for resolve of b
-  preserving rev for resolve of rev
+    preserving rev for resolve of rev
   updating: a 1/3 files (33.33%)
   removing a
   updating: b 2/3 files (66.67%)
@@ -527,9 +527,9 @@
    ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 8dbce441892a
    a: remote is newer -> g
    b: versions differ -> m
+    preserving b for resolve of b
    rev: versions differ -> m
-  preserving b for resolve of b
-  preserving rev for resolve of rev
+    preserving rev for resolve of rev
   updating: a 1/3 files (33.33%)
   getting a
   updating: b 2/3 files (66.67%)
@@ -557,9 +557,9 @@
    overwrite: False, partial: False
    ancestor: 924404dff337, local: 0b76e65c8289+, remote: 4ce40f5aca24
    b: versions differ -> m
+    preserving b for resolve of b
    rev: versions differ -> m
-  preserving b for resolve of b
-  preserving rev for resolve of rev
+    preserving rev for resolve of rev
   updating: b 1/2 files (50.00%)
   picked tool 'python ../merge' for b (binary False symlink False)
   merging b
@@ -584,13 +584,13 @@
   resolving manifests
    overwrite: False, partial: False
    ancestor: 924404dff337, local: 02963e448370+, remote: 8dbce441892a
-   b: versions differ -> m
-   rev: versions differ -> m
   remote changed a which local deleted
   use (c)hanged version or leave (d)eleted? c
    a: prompt recreating -> g
-  preserving b for resolve of b
-  preserving rev for resolve of rev
+   b: versions differ -> m
+    preserving b for resolve of b
+   rev: versions differ -> m
+    preserving rev for resolve of rev
   updating: a 1/3 files (33.33%)
   getting a
   updating: b 2/3 files (66.67%)
@@ -617,13 +617,13 @@
   resolving manifests
    overwrite: False, partial: False
    ancestor: 924404dff337, local: 0b76e65c8289+, remote: bdb19105162a
-   local changed a which remote deleted
+  local changed a which remote deleted
   use (c)hanged version or (d)elete? c
    a: prompt keep -> a
    b: versions differ -> m
+    preserving b for resolve of b
    rev: versions differ -> m
-  preserving b for resolve of b
-  preserving rev for resolve of rev
+    preserving rev for resolve of rev
   updating: a 1/3 files (33.33%)
   updating: b 2/3 files (66.67%)
   picked tool 'python ../merge' for b (binary False symlink False)
@@ -654,10 +654,10 @@
   resolving manifests
    overwrite: False, partial: False
    ancestor: 924404dff337, local: e300d1c794ec+, remote: 49b6d8032493
+   a: remote moved to b -> m
+    preserving a for resolve of b
    rev: versions differ -> m
-   a: remote moved to b -> m
-  preserving a for resolve of b
-  preserving rev for resolve of rev
+    preserving rev for resolve of rev
   removing a
   updating: a 1/2 files (50.00%)
   picked tool 'python ../merge' for b (binary False symlink False)
@@ -689,9 +689,9 @@
    overwrite: False, partial: False
    ancestor: 924404dff337, local: 62e7bf090eba+, remote: f4db7e329e71
    b: local copied/moved to a -> m
+    preserving b for resolve of b
    rev: versions differ -> m
-  preserving b for resolve of b
-  preserving rev for resolve of rev
+    preserving rev for resolve of rev
   updating: b 1/2 files (50.00%)
   picked tool 'python ../merge' for b (binary False symlink False)
   merging b and a to b
@@ -727,10 +727,10 @@
    overwrite: False, partial: False
    ancestor: 924404dff337, local: 02963e448370+, remote: 2b958612230f
    b: local copied/moved to a -> m
-   rev: versions differ -> m
+    preserving b for resolve of b
    c: remote created -> g
-  preserving b for resolve of b
-  preserving rev for resolve of rev
+   rev: versions differ -> m
+    preserving rev for resolve of rev
   updating: b 1/3 files (33.33%)
   picked tool 'python ../merge' for b (binary False symlink False)
   merging b and a to b
--- a/tests/test-revset.t	Wed Feb 06 07:55:29 2013 +0000
+++ b/tests/test-revset.t	Fri Feb 08 14:26:00 2013 +0000
@@ -218,17 +218,29 @@
   $ log 'date(2005) and 1::'
   4
 
+ancestor can accept 0 or more arguments
+
+  $ log 'ancestor()'
   $ log 'ancestor(1)'
-  hg: parse error: ancestor requires two arguments
-  [255]
+  1
   $ log 'ancestor(4,5)'
   1
   $ log 'ancestor(4,5) and 4'
+  $ log 'ancestor(0,0,1,3)'
+  0
+  $ log 'ancestor(3,1,5,3,5,1)'
+  1
+  $ log 'ancestor(0,1,3,5)'
+  0
+  $ log 'ancestor(1,2,3,4,5)'
+  1
   $ log 'ancestors(5)'
   0
   1
   3
   5
+  $ log 'ancestor(ancestors(5))'
+  0
   $ log 'author(bob)'
   2
   $ log 'author("re:bob|test")'
--- a/tests/test-subrepo.t	Wed Feb 06 07:55:29 2013 +0000
+++ b/tests/test-subrepo.t	Fri Feb 08 14:26:00 2013 +0000
@@ -244,7 +244,7 @@
    overwrite: False, partial: False
    ancestor: 6747d179aa9a, local: 20a0db6fbf6c+, remote: 7af322bc1198
    t: versions differ -> m
-  preserving t for resolve of t
+    preserving t for resolve of t
   updating: t 1/1 files (100.00%)
   picked tool 'internal:merge' for t (binary False symlink False)
   merging t
--- a/tests/test-up-local-change.t	Wed Feb 06 07:55:29 2013 +0000
+++ b/tests/test-up-local-change.t	Fri Feb 08 14:26:00 2013 +0000
@@ -47,8 +47,8 @@
    overwrite: False, partial: False
    ancestor: c19d34741b0a, local: c19d34741b0a+, remote: 1e71731e6fbb
    a: versions differ -> m
+    preserving a for resolve of a
    b: remote created -> g
-  preserving a for resolve of a
   updating: a 1/2 files (50.00%)
   picked tool 'true' for a (binary False symlink False)
   merging a
@@ -67,9 +67,9 @@
   resolving manifests
    overwrite: False, partial: False
    ancestor: 1e71731e6fbb, local: 1e71731e6fbb+, remote: c19d34741b0a
+   b: other deleted -> r
    a: versions differ -> m
-   b: other deleted -> r
-  preserving a for resolve of a
+    preserving a for resolve of a
   updating: b 1/2 files (50.00%)
   removing b
   updating: a 2/2 files (100.00%)
@@ -101,8 +101,8 @@
    overwrite: False, partial: False
    ancestor: c19d34741b0a, local: c19d34741b0a+, remote: 1e71731e6fbb
    a: versions differ -> m
+    preserving a for resolve of a
    b: remote created -> g
-  preserving a for resolve of a
   updating: a 1/2 files (50.00%)
   picked tool 'true' for a (binary False symlink False)
   merging a
@@ -179,9 +179,9 @@
    overwrite: False, partial: False
    ancestor: c19d34741b0a, local: 1e71731e6fbb+, remote: 83c51d0caff4
    a: versions differ -> m
+    preserving a for resolve of a
    b: versions differ -> m
-  preserving a for resolve of a
-  preserving b for resolve of b
+    preserving b for resolve of b
   updating: a 1/2 files (50.00%)
   picked tool 'true' for a (binary False symlink False)
   merging a