changeset 16192:a4413624d014

merge with stable
author Matt Mackall <mpm@selenic.com>
date Tue, 28 Feb 2012 21:17:53 -0600
parents af3e67354beb (diff) 7c75924a6926 (current diff)
children 0196c437ca9f
files hgext/mq.py mercurial/commands.py tests/test-check-code-hg.t tests/test-mq.t
diffstat 55 files changed, 2446 insertions(+), 1136 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Tue Feb 28 23:47:46 2012 +0200
+++ b/Makefile	Tue Feb 28 21:17:53 2012 -0600
@@ -91,8 +91,10 @@
 
 i18n/hg.pot: $(PYFILES) $(DOCFILES)
 	$(PYTHON) i18n/hggettext mercurial/commands.py \
-	  hgext/*.py hgext/*/__init__.py mercurial/fileset.py mercurial/revset.py \
+	  hgext/*.py hgext/*/__init__.py \
+	  mercurial/fileset.py mercurial/revset.py \
 	  mercurial/templatefilters.py mercurial/templatekw.py \
+	  mercurial/filemerge.py \
 	  $(DOCFILES) > i18n/hg.pot
         # All strings marked for translation in Mercurial contain
         # ASCII characters only. But some files contain string
--- a/hgext/convert/bzr.py	Tue Feb 28 23:47:46 2012 +0200
+++ b/hgext/convert/bzr.py	Tue Feb 28 21:17:53 2012 -0600
@@ -23,7 +23,7 @@
 
 try:
     # bazaar imports
-    from bzrlib import branch, revision, errors
+    from bzrlib import bzrdir, revision, errors
     from bzrlib.revisionspec import RevisionSpec
 except ImportError:
     pass
@@ -42,14 +42,17 @@
 
         try:
             # access bzrlib stuff
-            branch
+            bzrdir
         except NameError:
             raise NoRepo(_('Bazaar modules could not be loaded'))
 
         path = os.path.abspath(path)
         self._checkrepotype(path)
-        self.branch = branch.Branch.open(path)
-        self.sourcerepo = self.branch.repository
+        try:
+            self.sourcerepo = bzrdir.BzrDir.open(path).open_repository()
+        except errors.NoRepositoryPresent:
+            raise NoRepo(_('%s does not look like a Bazaar repository')
+                         % path)
         self._parentids = {}
 
     def _checkrepotype(self, path):
@@ -88,16 +91,28 @@
     def after(self):
         self.sourcerepo.unlock()
 
+    def _bzrbranches(self):
+        return self.sourcerepo.find_branches(using=True)
+
     def getheads(self):
         if not self.rev:
-            return [self.branch.last_revision()]
-        try:
-            r = RevisionSpec.from_string(self.rev)
-            info = r.in_history(self.branch)
-        except errors.BzrError:
-            raise util.Abort(_('%s is not a valid revision in current branch')
-                             % self.rev)
-        return [info.rev_id]
+            # Set using=True to avoid nested repositories (see issue3254)
+            heads = sorted([b.last_revision() for b in self._bzrbranches()])
+        else:
+            revid = None
+            for branch in self._bzrbranches():
+                try:
+                    r = RevisionSpec.from_string(self.rev)
+                    info = r.in_history(branch)
+                except errors.BzrError:
+                    pass
+                revid = info.rev_id
+            if revid is None:
+                raise util.Abort(_('%s is not a valid revision') % self.rev)
+            heads = [revid]
+        # Empty repositories return 'null:', which cannot be retrieved
+        heads = [h for h in heads if h != 'null:']
+        return heads
 
     def getfile(self, name, rev):
         revtree = self.sourcerepo.revision_tree(rev)
@@ -140,20 +155,24 @@
             parents = self._filterghosts(rev.parent_ids)
             self._parentids[version] = parents
 
+        branch = self.recode(rev.properties.get('branch-nick', u'default'))
+        if branch == 'trunk':
+            branch = 'default'
         return commit(parents=parents,
                 date='%d %d' % (rev.timestamp, -rev.timezone),
                 author=self.recode(rev.committer),
-                # bzr returns bytestrings or unicode, depending on the content
                 desc=self.recode(rev.message),
+                branch=branch,
                 rev=version)
 
     def gettags(self):
-        if not self.branch.supports_tags():
-            return {}
-        tagdict = self.branch.tags.get_tag_dict()
         bytetags = {}
-        for name, rev in tagdict.iteritems():
-            bytetags[self.recode(name)] = rev
+        for branch in self._bzrbranches():
+            if not branch.supports_tags():
+                return {}
+            tagdict = branch.tags.get_tag_dict()
+            for name, rev in tagdict.iteritems():
+                bytetags[self.recode(name)] = rev
         return bytetags
 
     def getchangedfiles(self, rev, i):
@@ -231,7 +250,11 @@
                 continue
 
             # we got unicode paths, need to convert them
-            path, topath = [self.recode(part) for part in paths]
+            path, topath = paths
+            if path is not None:
+                path = self.recode(path)
+            if topath is not None:
+                topath = self.recode(topath)
             seen.add(path or topath)
 
             if topath is None:
@@ -260,19 +283,3 @@
         parentmap = self.sourcerepo.get_parent_map(ids)
         parents = tuple([parent for parent in ids if parent in parentmap])
         return parents
-
-    def recode(self, s, encoding=None):
-        """This version of recode tries to encode unicode to bytecode,
-        and preferably using the UTF-8 codec.
-        Other types than Unicode are silently returned, this is by
-        intention, e.g. the None-type is not going to be encoded but instead
-        just passed through
-        """
-        if not encoding:
-            encoding = self.encoding or 'utf-8'
-
-        if isinstance(s, unicode):
-            return s.encode(encoding)
-        else:
-            # leave it alone
-            return s
--- a/hgext/graphlog.py	Tue Feb 28 23:47:46 2012 +0200
+++ b/hgext/graphlog.py	Tue Feb 28 21:17:53 2012 -0600
@@ -17,7 +17,7 @@
 from mercurial.i18n import _
 from mercurial.node import nullrev
 from mercurial import cmdutil, commands, extensions, scmutil
-from mercurial import hg, util, graphmod
+from mercurial import hg, util, graphmod, templatekw
 
 cmdtable = {}
 command = cmdutil.command(cmdtable)
@@ -237,69 +237,175 @@
         return (len(repo) - 1, 0)
 
 def check_unsupported_flags(pats, opts):
-    for op in ["follow_first", "copies", "newest_first"]:
+    for op in ["newest_first"]:
         if op in opts and opts[op]:
             raise util.Abort(_("-G/--graph option is incompatible with --%s")
                              % op.replace("_", "-"))
-    if pats and opts.get('follow'):
-        raise util.Abort(_("-G/--graph option is incompatible with --follow "
-                           "with file argument"))
+
+def makefilematcher(repo, pats, followfirst):
+    # When displaying a revision with --patch --follow FILE, we have
+    # to know which file of the revision must be diffed. With
+    # --follow, we want the names of the ancestors of FILE in the
+    # revision, stored in "fcache". "fcache" is populated by
+    # reproducing the graph traversal already done by --follow revset
+    # and relating linkrevs to file names (which is not "correct" but
+    # good enough).
+    fcache = {}
+    fcacheready = [False]
+    pctx = repo['.']
+    wctx = repo[None]
 
-def revset(pats, opts):
-    """Return revset str built of revisions, log options and file patterns.
+    def populate():
+        for fn in pats:
+            for i in ((pctx[fn],), pctx[fn].ancestors(followfirst=followfirst)):
+                for c in i:
+                    fcache.setdefault(c.linkrev(), set()).add(c.path())
+
+    def filematcher(rev):
+        if not fcacheready[0]:
+            # Lazy initialization
+            fcacheready[0] = True
+            populate()
+        return scmutil.match(wctx, fcache.get(rev, []), default='path')
+
+    return filematcher
+
+def revset(repo, pats, opts):
+    """Return (expr, filematcher) where expr is a revset string built
+    of revisions, log options and file patterns. If --stat or --patch
+    are not passed filematcher is None. Otherwise it a a callable
+    taking a revision number and returning a match objects filtering
+    the files to be detailed when displaying the revision.
     """
     opt2revset = {
-        'follow': (0, 'follow()'),
-        'no_merges': (0, 'not merge()'),
-        'only_merges': (0, 'merge()'),
-        'removed': (0, 'removes("*")'),
-        'date': (1, 'date($)'),
-        'branch': (2, 'branch($)'),
-        'exclude': (2, 'not file($)'),
-        'include': (2, 'file($)'),
-        'keyword': (2, 'keyword($)'),
-        'only_branch': (2, 'branch($)'),
-        'prune': (2, 'not ($ or ancestors($))'),
-        'user': (2, 'user($)'),
+        'follow':           ('follow()', None),
+        'follow_first':     ('_followfirst()', None),
+        'no_merges':        ('not merge()', None),
+        'only_merges':      ('merge()', None),
+        'date':             ('date(%(val)r)', None),
+        'branch':           ('branch(%(val)r)', ' or '),
+        '_patslog':         ('filelog(%(val)r)', ' or '),
+        '_patsfollow':      ('follow(%(val)r)', ' or '),
+        '_patsfollowfirst': ('_followfirst(%(val)r)', ' or '),
+        'keyword':          ('keyword(%(val)r)', ' or '),
+        'prune':            ('not (%(val)r or ancestors(%(val)r))', ' and '),
+        'user':             ('user(%(val)r)', ' or '),
+        'rev':              ('%(val)s', ' or '),
         }
-    optrevset = []
+
+    opts = dict(opts)
+    # branch and only_branch are really aliases and must be handled at
+    # the same time
+    if 'branch' in opts and 'only_branch' in opts:
+        opts['branch'] = opts['branch'] + opts.pop('only_branch')
+
+    follow = opts.get('follow') or opts.get('follow_first')
+    followfirst = opts.get('follow_first')
+    if 'follow' in opts:
+        del opts['follow']
+    if 'follow_first' in opts:
+        del opts['follow_first']
+    # pats/include/exclude are passed to match.match() directly in
+    # _matchfile() revset but walkchangerevs() builds its matcher with
+    # scmutil.match(). The difference is input pats are globbed on
+    # platforms without shell expansion (windows).
+    pctx = repo[None]
+    match, pats = scmutil.matchandpats(pctx, pats, opts)
+    slowpath = match.anypats() or (match.files() and opts.get('removed'))
+    if not slowpath:
+        for f in match.files():
+            if follow and f not in pctx:
+                raise util.Abort(_('cannot follow file not in parent '
+                                   'revision: "%s"') % f)
+            filelog = repo.file(f)
+            if not len(filelog):
+                # A zero count may be a directory or deleted file, so
+                # try to find matching entries on the slow path.
+                if follow:
+                    raise util.Abort(
+                        _('cannot follow nonexistent file: "%s"') % f)
+                slowpath = True
+    if slowpath:
+        # See cmdutil.walkchangerevs() slow path.
+        #
+        if follow:
+            raise util.Abort(_('can only follow copies/renames for explicit '
+                               'filenames'))
+        # pats/include/exclude cannot be represented as separate
+        # revset expressions as their filtering logic applies at file
+        # level. For instance "-I a -X a" matches a revision touching
+        # "a" and "b" while "file(a) and not file(b)" does
+        # not. Besides, filesets are evaluated against the working
+        # directory.
+        matchargs = ['r:']
+        for p in pats:
+            matchargs.append('p:' + p)
+        for p in opts.get('include', []):
+            matchargs.append('i:' + p)
+        for p in opts.get('exclude', []):
+            matchargs.append('x:' + p)
+        matchargs = ','.join(('%r' % p) for p in matchargs)
+        opts['rev'] = opts.get('rev', []) + ['_matchfiles(%s)' % matchargs]
+    else:
+        if follow:
+            if followfirst:
+                if pats:
+                    opts['_patsfollowfirst'] = list(pats)
+                else:
+                    opts['follow_first'] = True
+            else:
+                if pats:
+                    opts['_patsfollow'] = list(pats)
+                else:
+                    opts['follow'] = True
+        else:
+            opts['_patslog'] = list(pats)
+
+    filematcher = None
+    if opts.get('patch') or opts.get('stat'):
+        if follow:
+            filematcher = makefilematcher(repo, pats, followfirst)
+        else:
+            filematcher = lambda rev: match
+
     revset = []
     for op, val in opts.iteritems():
         if not val:
             continue
-        if op == 'rev':
-            # Already a revset
-            revset.extend(val)
         if op not in opt2revset:
             continue
-        arity, revop = opt2revset[op]
-        revop = revop.replace('$', '%(val)r')
-        if arity == 0:
-            optrevset.append(revop)
-        elif arity == 1:
-            optrevset.append(revop % {'val': val})
+        revop, andor = opt2revset[op]
+        if '%(val)' not in revop:
+            revset.append(revop)
         else:
-            for f in val:
-                optrevset.append(revop % {'val': f})
+            if not isinstance(val, list):
+                expr = revop % {'val': val}
+            else:
+                expr = '(' + andor.join((revop % {'val': v}) for v in val) + ')'
+            revset.append(expr)
 
-    for path in pats:
-        optrevset.append('file(%r)' % path)
-
-    if revset or optrevset:
-        if revset:
-            revset = ['(' + ' or '.join(revset) + ')']
-        if optrevset:
-            revset.append('(' + ' and '.join(optrevset) + ')')
-        revset = ' and '.join(revset)
+    if revset:
+        revset = '(' + ' and '.join(revset) + ')'
     else:
         revset = 'all()'
-    return revset
+    return revset, filematcher
 
-def generate(ui, dag, displayer, showparents, edgefn):
+def generate(ui, dag, displayer, showparents, edgefn, getrenamed=None,
+             filematcher=None):
     seen, state = [], asciistate()
     for rev, type, ctx, parents in dag:
         char = ctx.node() in showparents and '@' or 'o'
-        displayer.show(ctx)
+        copies = None
+        if getrenamed and ctx.rev():
+            copies = []
+            for fn in ctx.files():
+                rename = getrenamed(fn, ctx.rev())
+                if rename:
+                    copies.append((fn, rename[0]))
+        revmatchfn = None
+        if filematcher is not None:
+            revmatchfn = filematcher(ctx.rev())
+        displayer.show(ctx, copies=copies, matchfn=revmatchfn)
         lines = displayer.hunk.pop(rev).split('\n')[:-1]
         displayer.flush(rev)
         edges = edgefn(type, char, lines, seen, rev, parents)
@@ -326,15 +432,23 @@
 
     check_unsupported_flags(pats, opts)
 
-    revs = sorted(scmutil.revrange(repo, [revset(pats, opts)]), reverse=1)
+    expr, filematcher = revset(repo, pats, opts)
+    revs = sorted(scmutil.revrange(repo, [expr]), reverse=1)
     limit = cmdutil.loglimit(opts)
     if limit is not None:
         revs = revs[:limit]
     revdag = graphmod.dagwalker(repo, revs)
 
+    getrenamed = None
+    if opts.get('copies'):
+        endrev = None
+        if opts.get('rev'):
+            endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
+        getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
     displayer = show_changeset(ui, repo, opts, buffered=True)
     showparents = [ctx.node() for ctx in repo[None].parents()]
-    generate(ui, revdag, displayer, showparents, asciiedges)
+    generate(ui, revdag, displayer, showparents, asciiedges, getrenamed,
+             filematcher)
 
 def graphrevs(repo, nodes, opts):
     limit = cmdutil.loglimit(opts)
--- a/hgext/largefiles/lfutil.py	Tue Feb 28 23:47:46 2012 +0200
+++ b/hgext/largefiles/lfutil.py	Tue Feb 28 21:17:53 2012 -0600
@@ -449,3 +449,11 @@
         newheads = repo.branchheads(branch)
         heads = heads + newheads
     return heads
+
+def getstandinsstate(repo):
+    standins = []
+    matcher = getstandinmatcher(repo)
+    for standin in dirstate_walk(repo.dirstate, matcher):
+        lfile = splitstandin(standin)
+        standins.append((lfile, readstandin(repo, lfile)))
+    return standins
--- a/hgext/largefiles/overrides.py	Tue Feb 28 23:47:46 2012 +0200
+++ b/hgext/largefiles/overrides.py	Tue Feb 28 21:17:53 2012 -0600
@@ -265,13 +265,10 @@
 # The overridden function filters the unknown files by removing any
 # largefiles. This makes the merge proceed and we can then handle this
 # case further in the overridden manifestmerge function below.
-def override_checkunknown(origfn, wctx, mctx, folding):
-    origunknown = wctx.unknown()
-    wctx._unknown = filter(lambda f: lfutil.standin(f) not in wctx, origunknown)
-    try:
-        return origfn(wctx, mctx, folding)
-    finally:
-        wctx._unknown = origunknown
+def override_checkunknownfile(origfn, repo, wctx, mctx, f):
+    if lfutil.standin(f) in wctx:
+        return False
+    return origfn(repo, wctx, mctx, f)
 
 # The manifest merge handles conflicts on the manifest level. We want
 # to handle changes in largefile-ness of files at this level too.
@@ -322,7 +319,7 @@
                 processed.append((standin, "g", p2.flags(standin)))
             else:
                 processed.append((standin, "r"))
-        elif m == "m" and lfutil.standin(f) in p1 and f in p2:
+        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
             standin = lfutil.standin(f)
@@ -454,7 +451,7 @@
                 m._fmap = set(m._files)
                 orig_matchfn = m.matchfn
                 m.matchfn = lambda f: (lfutil.isstandin(f) and
-                                    lfile(lfutil.splitstandin(f)) and
+                                    (f in manifest) and
                                     orig_matchfn(lfutil.splitstandin(f)) or
                                     None)
                 return m
@@ -546,7 +543,7 @@
                 match = oldmatch(ctx, pats, opts, globbed, default)
                 m = copy.copy(match)
                 def tostandin(f):
-                    if lfutil.standin(f) in ctx or lfutil.standin(f) in ctx:
+                    if lfutil.standin(f) in ctx:
                         return lfutil.standin(f)
                     elif lfutil.standin(f) in repo[None]:
                         return None
@@ -605,8 +602,20 @@
         wlock.release()
 
 def hg_update(orig, repo, node):
+    # In order to not waste a lot of extra time during the update largefiles
+    # step, we keep track of the state of the standins before and after we
+    # call the original update function, and only update the standins that
+    # have changed in the hg.update() call
+    oldstandins = lfutil.getstandinsstate(repo)
     result = orig(repo, node)
-    lfcommands.updatelfiles(repo.ui, repo)
+    newstandins = lfutil.getstandinsstate(repo)
+    tobeupdated = set(oldstandins).symmetric_difference(set(newstandins))
+    filelist = []
+    for f in tobeupdated:
+        if f[0] not in filelist:
+            filelist.append(f[0])
+
+    lfcommands.updatelfiles(repo.ui, repo, filelist=filelist, printmessage=True)
     return result
 
 def hg_clean(orig, repo, node, show_stats=True):
--- a/hgext/largefiles/uisetup.py	Tue Feb 28 23:47:46 2012 +0200
+++ b/hgext/largefiles/uisetup.py	Tue Feb 28 21:17:53 2012 -0600
@@ -64,8 +64,8 @@
                                    overrides.override_update)
     entry = extensions.wrapcommand(commands.table, 'pull',
                                    overrides.override_pull)
-    entry = extensions.wrapfunction(merge, '_checkunknown',
-                                    overrides.override_checkunknown)
+    entry = extensions.wrapfunction(merge, '_checkunknownfile',
+                                    overrides.override_checkunknownfile)
     entry = extensions.wrapfunction(merge, 'manifestmerge',
                                     overrides.override_manifestmerge)
     entry = extensions.wrapfunction(filemerge, 'filemerge',
--- a/hgext/mq.py	Tue Feb 28 23:47:46 2012 +0200
+++ b/hgext/mq.py	Tue Feb 28 21:17:53 2012 -0600
@@ -257,10 +257,11 @@
                 ci += 1
             del self.comments[ci]
 
-def secretcommit(repo, phase, *args, **kwargs):
-    """helper dedicated to ensure a commit are secret
-
-    It should be used instead of repo.commit inside the mq source
+def newcommit(repo, phase, *args, **kwargs):
+    """helper dedicated to ensure a commit respect mq.secret setting
+
+    It should be used instead of repo.commit inside the mq source for operation
+    creating new changeset.
     """
     if phase is None:
         if repo.ui.configbool('mq', 'secret', False):
@@ -581,7 +582,7 @@
         ret = hg.merge(repo, rev)
         if ret:
             raise util.Abort(_("update returned %d") % ret)
-        n = secretcommit(repo, None, ctx.description(), ctx.user(), force=True)
+        n = newcommit(repo, None, ctx.description(), ctx.user(), force=True)
         if n is None:
             raise util.Abort(_("repo commit failed"))
         try:
@@ -621,7 +622,7 @@
             # the first patch in the queue is never a merge patch
             #
             pname = ".hg.patches.merge.marker"
-            n = secretcommit(repo, None, '[mq]: merge marker', force=True)
+            n = newcommit(repo, None, '[mq]: merge marker', force=True)
             self.removeundo(repo)
             self.applied.append(statusentry(n, pname))
             self.applieddirty = True
@@ -752,8 +753,8 @@
 
             match = scmutil.matchfiles(repo, files or [])
             oldtip = repo['tip']
-            n = secretcommit(repo, None, message, ph.user, ph.date, match=match,
-                             force=True)
+            n = newcommit(repo, None, message, ph.user, ph.date, match=match,
+                          force=True)
             if repo['tip'] == oldtip:
                 raise util.Abort(_("qpush exactly duplicates child changeset"))
             if n is None:
@@ -993,8 +994,8 @@
                 if util.safehasattr(msg, '__call__'):
                     msg = msg()
                 commitmsg = msg and msg or ("[mq]: %s" % patchfn)
-                n = secretcommit(repo, None, commitmsg, user, date, match=match,
-                                 force=True)
+                n = newcommit(repo, None, commitmsg, user, date, match=match,
+                              force=True)
                 if n is None:
                     raise util.Abort(_("repo commit failed"))
                 try:
@@ -1548,8 +1549,8 @@
 
                 # Ensure we create a new changeset in the same phase than
                 # the old one.
-                n = secretcommit(repo, oldphase, message, user, ph.date,
-                                 match=match, force=True)
+                n = newcommit(repo, oldphase, message, user, ph.date,
+                              match=match, force=True)
                 # only write patch after a successful commit
                 patchf.close()
                 self.applied.append(statusentry(n, patchfn))
@@ -1997,7 +1998,7 @@
           ('P', 'push', None, _('qpush after importing'))],
          _('hg qimport [-e] [-n NAME] [-f] [-g] [-P] [-r REV]... FILE...'))
 def qimport(ui, repo, *filename, **opts):
-    """import a patch
+    """import a patch or existing changeset
 
     The patch is inserted into the series after the last applied
     patch. If no patches have been applied, qimport prepends the patch
--- a/i18n/de.po	Tue Feb 28 23:47:46 2012 +0200
+++ b/i18n/de.po	Tue Feb 28 21:17:53 2012 -0600
@@ -43,7 +43,7 @@
 #
 # Schlecht:
 #   Mergen Sie zunächst die Branche.
-#   Falls der Tag im Filelog zu finden ist...
+#   Falls der Tag im Filelog nicht gecheckt werden kann...
 #
 # Ãœbersetzungen:
 #  backup        Sicherheitskopie (gewinnt in google-fight gegen Sicherungsk.)
@@ -54,9 +54,12 @@
 #  changeset     Änderungssatz
 #  commit        Commit/Ãœbernahme
 #  commit (v)    übernehmen
+#  comm. message Versionsmeldung
 #  committer     Autor
+#  corrupt       beschädigt (nicht korrumpiert)
 #  deprecated    veraltet
 #  force (v)     erzwingen
+#  history       Historie
 #  merge         zusammenführen
 #  notation      Schreibweise
 #  queue         Reihe
@@ -64,24 +67,25 @@
 #  manage/track  versionieren
 #  pull          abrufen
 #  push          übertragen
-#  rebase        Pfropfung/Verschiebung
+#  rebase        Verschiebung (Pfropfung)
 #  section       Abschnitt (nicht Sektion)
 #  tag           Etikett    (svn verwendet "Marke")
 #
 # Nicht übersetzt bleiben
-#  hook     mangels guter Übersetzung (Einhängeaktion?)
-#  token    Fachbegriff auch im Deutschen
-#  parser   Fachbegriff auch im Deutschen
-#  patch    Bezieht sich auf ein sehr altes Programm mit demselben Namen und
+#  Hook  (m) mangels guter Übersetzung (Einhängeaktion?)
+#  Token (n) Fachbegriff auch im Deutschen
+#  Parser(m) Fachbegriff auch im Deutschen
+#  Patch (m) Bezieht sich auf ein sehr altes Programm mit demselben Namen und
 #           Dateien in dessen Syntax/Format
 #           Die ursprüngliche Bedeutung des englischen Wortes (Flicken) trifft
 #           heute eh nicht mehr zu.
-#  diff     Siehe patch, ausserdem Abkürzung eines auch deutschen Worts
-#  glob
+#  Diff  (n) Siehe patch, ausserdem Abkürzung eines auch deutschen Worts
+#  glob  (n)
 #  dirstate Nur für Entwickler interessant. Im sonstigen Handbuch umschreiben!
 #  .. note:: Dies ist spezielle reStructured-Syntax und darf nicht geändert
 #           werden
-# 
+#  Pager (m) mangels guter Ãœbersetzung (Theoretisch "Verseitener" :)
+#
 # Weiteres:
 #  graft/transplant: Da graft eine Reimplementierung von transplant als
 #         Kernfunktion ist, kann in beiden Fällen "Transplantation" als
@@ -92,12 +96,14 @@
 #         kann die Ãœbersetzung "Revision" lauten.
 #  largefile: Binärriese (neues Wort, vielleicht fällt jemandem ein besseres
 #             ein. Dies ist zur Zeit konsequent verwendet)
+#  default: Sollte dies nicht lieber eine Voreinstellung statt des Standards
+#           sein?
 #
 msgid ""
 msgstr ""
 "Project-Id-Version: Mercurial\n"
 "Report-Msgid-Bugs-To: <mercurial-devel@selenic.com>\n"
-"POT-Creation-Date: 2011-12-04 13:42+0200\n"
+"POT-Creation-Date: 2012-01-21 14:20+0200\n"
 "PO-Revision-Date: 2010-12-24 15:09+0100\n"
 "Last-Translator: Fabian Kreutz <fabian.kreutz@qvantel.com>\n"
 "Language-Team: \n"
@@ -470,8 +476,7 @@
 
 #, python-format
 msgid "acl: user \"%s\" denied on \"%s\" (changeset \"%s\")"
-msgstr ""
-"acl: Zugriff für \"%s\" auf \"%s\" abgelehnt (Änderungssatz \"%s\")"
+msgstr "acl: Zugriff für \"%s\" auf \"%s\" abgelehnt (Änderungssatz \"%s\")"
 
 #, python-format
 msgid "acl: user \"%s\" not allowed on \"%s\" (changeset \"%s\")"
@@ -529,7 +534,8 @@
 msgstr ""
 "Direktes Schreiben in die Datenbank führt leicht zu Problemen bei Schema-\n"
 "veränderungen. Ausserdem wird ein externes Bugzilla Script benötigt, um\n"
-"Benachrichtigungsemails zu versenden. Dieses Script wird mit den Rechten des\n"
+"Benachrichtigungsemails zu versenden. Dieses Script wird mit den Rechten "
+"des\n"
 "Mercurial-Benutzers ausgeführt, benötigt eine lokale Bugzilla-Installation\n"
 "sowie Leserechte an der Bugzilla Konfigurationsdatei und MySQL Benutzername\n"
 "und Passwort, um vollen Zugriff auf die Bugzilla Datenbank zu haben. Aus\n"
@@ -650,7 +656,8 @@
 msgstr ""
 "bugzilla.strip\n"
 "  Die Anzahl von Verzeichnisebenen, die vom Anfang des Archivpfads\n"
-"  (``{root}`` in Vorlagen) abgeschnitten wird, um ``{webroot}`` zu erhalten.\n"
+"  (``{root}`` in Vorlagen) abgeschnitten wird, um ``{webroot}`` zu "
+"erhalten.\n"
 "  Zum Beispiel mit ``{root}`` als ``/var/local/mein-projekt`` und einem\n"
 "  Wert 2, wird ``{webroot}`` auf ``mein-projekt`` gesetzt. Standard 0."
 
@@ -721,8 +728,7 @@
 msgid ""
 "XMLRPC+email access mode uses the XMLRPC access mode configuration items,\n"
 "and also:"
-msgstr ""
-"XMLRPC+email nutzt die gleichen Zugriffskonfiguration wie XMLRPC plus:"
+msgstr "XMLRPC+email nutzt die gleichen Zugriffskonfiguration wie XMLRPC plus:"
 
 msgid ""
 "bugzilla.bzemail\n"
@@ -928,7 +934,8 @@
 "with a collection of Mercurial repositories in ``/var/local/hg/repos/``,\n"
 "with a web interface at ``http://my-project.org/hg``. ::"
 msgstr ""
-"MySQL Beispielkonfiguration. Bugzilla 3.2 ist lokal in ``/opt/bugzilla-3.2``\n"
+"MySQL Beispielkonfiguration. Bugzilla 3.2 ist lokal in ``/opt/"
+"bugzilla-3.2``\n"
 "installiert. Die MySQL Datenbank wird per ``localhost`` angesprochen,\n"
 "der Name der Bugzilla Datenbank ist ``bugs`` und der MySQL Zugriff ist für\n"
 "enutzer ``bugs`` mit Password ``XYZZY`` erlaubt. Die Archive, deren\n"
@@ -1341,7 +1348,8 @@
 "(fettgeschrieben), 'dim' (gedämmt), 'inverse' (Vorder- und Hintergrund\n"
 "getauscht), 'italic' (Schrägschrift), 'standout' (hervorstehend) und\n"
 "'underline' (unterstrichen); im ECMA-48 Modus nur 'bold', 'inverse',\n"
-"'italic' und 'underline'. Wie dies tatsächlich aussieht, hängt vom Terminal-\n"
+"'italic' und 'underline'. Wie dies tatsächlich aussieht, hängt vom "
+"Terminal-\n"
 "emulator ab. Effekte, die nicht realisiert werden können, werden ohne\n"
 "Warnung ignoriert."
 
@@ -1415,13 +1423,11 @@
 "deaktivieren.\n"
 
 msgid "no terminfo entry for setab/setaf: reverting to ECMA-48 color\n"
-msgstr ""
-"Kein terminfo-Eintrag für setab/setaf: Falle auf ECMA-48 zurück\n"
+msgstr "Kein terminfo-Eintrag für setab/setaf: Falle auf ECMA-48 zurück\n"
 
 #, python-format
 msgid "warning: failed to set color mode to %s\n"
-msgstr ""
-"Warnung: Konnte Farbmodus nicht auf %s setzen\n"
+msgstr "Warnung: Konnte Farbmodus nicht auf %s setzen\n"
 
 #, python-format
 msgid "ignoring unknown color/effect %r (configured in color.%s)\n"
@@ -1569,8 +1575,7 @@
 msgstr "      Quellautor = Zielautor"
 
 msgid "    Empty lines and lines starting with a ``#`` are ignored."
-msgstr ""
-"    Leere Zeilen und Zeilen, die mit ``#`` beginnen, werden ignoriert."
+msgstr "    Leere Zeilen und Zeilen, die mit ``#`` beginnen, werden ignoriert."
 
 msgid ""
 "    The filemap is a file that allows filtering and remapping of files\n"
@@ -2476,7 +2481,7 @@
 msgstr ""
 
 msgid "failed to reach end of mtn automate stdio headers"
-msgstr ""
+msgstr "Konnte den Endpunkt der mtn automate-Schnittstelle nicht erreichen"
 
 #, python-format
 msgid "%s does not look like a P4 repository"
@@ -2493,6 +2498,10 @@
 "Mercurial konnte sich selbst nicht ausführen, prüfe, ob die Programmdatei\n"
 "in PATH enthalten ist."
 
+#, python-format
+msgid "log stream exception '%s'"
+msgstr ""
+
 msgid ""
 "svn: cannot probe remote repository, assume it could be a subversion "
 "repository. Use --source-type if you know better.\n"
@@ -3331,10 +3340,10 @@
 "  project = foo\n"
 "  # das Modul (Unterprojekt) (optional)\n"
 "  #module = foo\n"
-"  # Hänge eine Statistik über die Änderungen an die Commit-Nachricht an\n"
+"  # Hänge eine Statistik über Änderungen an die Versionsmeldung an\n"
 "  # (optional)\n"
 "  #diffstat = False\n"
-"  # Vorlage für die Commit-Nachrichten (optional)\n"
+"  # Vorlage für die Versionsmeldungen (optional)\n"
 "  #template = {desc}\\n{baseurl}{webroot}/rev/{node}-- {diffstat}\n"
 "  # zu verwendender Stil (optional)\n"
 "  #style = foo\n"
@@ -4160,9 +4169,10 @@
 "enabled for this to work."
 msgstr ""
 "Wird ein Änderungssatz, welcher einen Binärriesen ändert oder hinzufügt,\n"
-"in ein entferntes Archiv übertragen, so werden auch die Revisionen der\n"
-"Binärdatei übertragen. Das entfernte Mercurial muss hierfür die\n"
-"largefiles-Erweiterung unterstützen."
+"in ein entferntes Archiv übertragen, so werden gleichzeitig (asymmetrisch\n"
+"zum Abrufen per pull) auch die (neuen) Revisionen der Binärdatei "
+"übertragen.\n"
+"Das entfernte Mercurial muss hierfür die largefiles-Erweiterung unterstützen."
 
 msgid ""
 "When you pull a changeset that affects largefiles from a remote\n"
@@ -4242,10 +4252,18 @@
 
 msgid ""
 "Files that match one of these patterns will be added as largefiles\n"
-"regardless of their size.\n"
+"regardless of their size."
 msgstr ""
 "Dateien, die auf ein solches Muster passen, werden unabhängig von ihrer\n"
-"Größe als Binärriesen hinzugefügt.\n"
+"Größe als Binärriesen hinzugefügt."
+
+msgid ""
+"The ``largefiles.minsize`` and ``largefiles.patterns`` config options\n"
+"will be ignored for any repositories not already containing a\n"
+"largefile. To add the first largefile to a repository, you must\n"
+"explicitly do so with the --large flag passed to the :hg:`add`\n"
+"command.\n"
+msgstr ""
 
 msgid "convert a normal repository to a largefiles repository"
 msgstr "Konvertiert ein normales Archiv in ein Archiv mit Binärriesen"
@@ -4335,6 +4353,18 @@
 msgid "largefile %s becomes symlink"
 msgstr "Binärriese %s wird ein symbolischer Verweis"
 
+#, python-format
+msgid "skipping incorrectly formatted tag %s\n"
+msgstr "Ãœberspringe fehlerhaft formatiertes Etikett: %s\n"
+
+#, python-format
+msgid "skipping incorrectly formatted id %s\n"
+msgstr "Ãœberspringe fehlerhaft formatierte ID: %s\n"
+
+#, python-format
+msgid "no mapping for id %s\n"
+msgstr "Keine Abbildung für ID %s\n"
+
 msgid "uploading largefiles"
 msgstr "Lade Binärriesen hoch"
 
@@ -4378,10 +4408,6 @@
 msgid "Found %s in system cache\n"
 msgstr "%s im Zwischenspeicher gefunden\n"
 
-#, python-format
-msgid "bad hash in '%s' (only %d bytes long)"
-msgstr "Prüfsummenfehler in '%s' (nur %d Bytes lang)"
-
 msgid "Can't get file locally"
 msgstr "Kann Datei nicht lokal abrufen"
 
@@ -4417,8 +4443,8 @@
 msgstr "Keine Dateien angegeben"
 
 #, python-format
-msgid "not removing %s: %s (use -f to force removal)\n"
-msgstr "Entferne nicht %s: %s (Nutze -f um Entfernung zu erzwingen)\n"
+msgid "not removing %s: %s (use forget to undo)\n"
+msgstr "Entferne nicht %s: %s (Nutze ``forget`` um rückgängig zu machen)\n"
 
 msgid "file still exists"
 msgstr "Datei existiert noch"
@@ -4436,6 +4462,28 @@
 msgid "uncommitted local changes"
 msgstr "Ausstehende nicht versionierte Änderungen"
 
+msgid "&Largefile"
+msgstr "&Binärriese"
+
+msgid "&Normal file"
+msgstr "&Normale Datei"
+
+#, python-format
+msgid ""
+"%s has been turned into a largefile\n"
+"use (l)argefile or keep as (n)ormal file?"
+msgstr ""
+"%s wurde in einen Binärriesen umgewandelt.\n"
+"Nutze als (B)inärriese oder als (n)ormale Datei?"
+
+#, python-format
+msgid ""
+"%s has been turned into a normal file\n"
+"keep as (l)argefile or use (n)ormal file?"
+msgstr ""
+"%s wurde in eine normale Datei umgewandelt.\n"
+"Nutze als (B)inärriese oder als (n)ormale Datei?"
+
 #, python-format
 msgid "merging %s and %s to %s\n"
 msgstr "Führe %s und %s zusammen zu %s\n"
@@ -4464,6 +4512,13 @@
 msgid "no files to copy"
 msgstr "Keine Dateien zu kopieren"
 
+msgid "caching new largefiles\n"
+msgstr "Lade neue Binärriesen in den Zwischenspeicher\n"
+
+#, python-format
+msgid "%d largefiles cached\n"
+msgstr "%d Binärriesen in den Zwischenspeicher geladen\n"
+
 #, python-format
 msgid "unknown archive type '%s'"
 msgstr "Unbekannter Archivtyp '%s'"
@@ -4472,6 +4527,10 @@
 msgstr "Bei Archivierung in Dateien kann kein Präfix angegeben werden"
 
 #, python-format
+msgid "largefile %s not found in repo store or system cache"
+msgstr "Binärriese %s weder im Archivlager noch Zwischenspeicher gefunden"
+
+#, python-format
 msgid "not removing %s: file is already untracked\n"
 msgstr "Entferne %s nicht: Datei ist nicht versioniert\n"
 
@@ -4485,18 +4544,24 @@
 msgid "largefiles: %d to upload\n"
 msgstr "largefiles: %d hochzuladen\n"
 
-msgid "addremove cannot be run on a repo with largefiles"
-msgstr ""
-"'addremove' kann nicht auf ein Archiv mit Binärriesen angewendet werden"
-
-#, python-format
-msgid "largefiles: failed to put %s (%s) into store: %s"
-msgstr "largefiles: Konnte %s (%s) nicht in einlagern: %s"
+msgid "largefile contents do not match hash"
+msgstr "Inhalt des Binärriesen passt nicht auf Prüfsumme"
+
+#, python-format
+msgid "largefiles: failed to put %s into store: %s"
+msgstr "largefiles: Konnte %s nicht in einlagern: %s"
 
 #, python-format
 msgid "requested largefile %s not present in cache"
 msgstr "Angeforderer Binärriese %s ist nicht im Zwischenspeicher"
 
+msgid "remote: "
+msgstr "Entfernt: "
+
+#, python-format
+msgid "unexpected putlfile response: %s"
+msgstr "Unerwartete Antwort von putlfile: %s"
+
 msgid "putlfile failed:"
 msgstr "putlfile fehlgeschlagen:"
 
@@ -4539,7 +4604,8 @@
 "largefiles: repo method %r appears to have already been wrapped by another "
 "extension: largefiles may behave incorrectly\n"
 msgstr ""
-"largefiles: Aktion %r scheint bereits von einer anderen Erweiterung verändert zu sein. Dadurch kann es zu Fehlern in largefiles kommen\n"
+"largefiles: Aktion %r scheint bereits von einer anderen Erweiterung "
+"verändert zu sein. Dadurch kann es zu Fehlern in largefiles kommen\n"
 
 #, python-format
 msgid "file \"%s\" is a largefile standin"
@@ -5011,6 +5077,13 @@
 msgstr "Nachfahren der Revision %d werden nicht verwaltet"
 
 #, python-format
+msgid "revision %d is not mutable"
+msgstr "Revision %d ist unveränderbar"
+
+msgid "see \"hg help phases\" for details"
+msgstr "siehe \"hg help phases\" für Details"
+
+#, python-format
 msgid "cannot import merge revision %d"
 msgstr "Kann Zusammenführung %d nicht importieren"
 
@@ -5030,7 +5103,8 @@
 msgstr "Benenne %s in %s um\n"
 
 msgid "need --name to import a patch from -"
-msgstr "Beim Import von der Standardeingabe muss die Option --name angegeben werden"
+msgstr ""
+"Beim Import von der Standardeingabe muss die Option --name angegeben werden"
 
 #, python-format
 msgid "unable to read file %s"
@@ -5054,11 +5128,13 @@
 
 msgid ""
 "    The patches must not be applied, and at least one patch is required. "
-"With\n"
-"    -k/--keep, the patch files are preserved in the patch directory."
+"Exact\n"
+"    patch identifiers must be given. With -k/--keep, the patch files are\n"
+"    preserved in the patch directory."
 msgstr ""
 "    Die Patches dürfen nicht angewendet sein und mindestens einer muss\n"
-"    angegeben sein. Mit -k/--keep werden die Patchdateien erhalten."
+"    angegeben sein. Exakte Patch-IDs müssen verwendet werden. Mit -k/--keep\n"
+"    werden die Patchdateien erhalten."
 
 msgid ""
 "    To stop managing a patch and move it into permanent history,\n"
@@ -5896,12 +5972,12 @@
 "    Beispiel::"
 
 msgid ""
-"        qguard foo.patch -stable    (negative guard)\n"
-"        qguard bar.patch +stable    (positive guard)\n"
+"        qguard foo.patch -- -stable    (negative guard)\n"
+"        qguard bar.patch    +stable    (positive guard)\n"
 "        qselect stable"
 msgstr ""
-"        qguard foo.patch -stable    (negativer Wächter)\n"
-"        qguard bar.patch +stable    (positiver Wächter)\n"
+"        qguard foo.patch -- -stable    (negativer Wächter)\n"
+"        qguard bar.patch    +stable    (positiver Wächter)\n"
 "        qselect stable"
 
 msgid ""
@@ -6005,7 +6081,7 @@
 msgstr ""
 "    Schließt die angegebenen Revisionen ab (entspricht den angewandten\n"
 "    Patches), indem sie aus der Kontrolle von mq entfernt und in die\n"
-"    reguläre Projektgeschichte übernommen werden."
+"    reguläre Projekthistorie übernommen werden."
 
 msgid ""
 "    Accepts a revision range or the -a/--applied option. If --applied\n"
@@ -6025,8 +6101,7 @@
 msgstr ""
 "    Dies kann insbes. nützlich sein, wenn Ihre Änderungen in einem\n"
 "    vorgelagerten Projektarchiv angewandt wurden, oder wenn Sie Ihre\n"
-"    Änderungen in ein vorgelagertes Archiv übertragen wollen.\n"
-"    "
+"    Änderungen in ein vorgelagertes Archiv übertragen wollen."
 
 msgid "no revisions specified"
 msgstr "Keine Revisionen angegeben"
@@ -6062,9 +6137,8 @@
 "    Supports switching between different patch queues, as well as creating\n"
 "    new patch queues and deleting existing ones."
 msgstr ""
-"    Unterstützt das Wechseln zwischen verschiedener Patch-Reihen, ebenso "
-"wie\n"
-"    das erstellen neuer Reihen und das Löschen bereits bestehender."
+"    Unterstützt das Wechseln zwischen verschiedener Patch-Reihen, sowie\n"
+"    das Erstellen neuer Reihen und das Löschen bereits bestehender."
 
 msgid ""
 "    Omitting a queue name or specifying -l/--list will show you the "
@@ -6130,7 +6204,7 @@
 
 #, python-format
 msgid "non-queue directory \"%s\" already exists"
-msgstr "Nicht-Reihen-Verzeichnis \"%s\" existiert bereits"
+msgstr "Verzeichnis \"%s\" existiert bereits, ist aber keine Reihe"
 
 msgid "use --create to create a new queue"
 msgstr "Verwenden Sie --create, um eine neue Reihe zu erzeugen"
@@ -6192,6 +6266,9 @@
 "This extension let you run hooks sending email notifications when\n"
 "changesets are being pushed, from the sending or receiving side."
 msgstr ""
+"Diese Erweiterung ermöglicht das Senden von Benachrichtigungsemails,\n"
+"wannimmer Änderungssätze übertragen werden. Dies kann von der über-\n"
+"tragenden oder der empfangenden Seite aus geschehen."
 
 msgid ""
 "First, enable the extension as explained in :hg:`help extensions`, and\n"
@@ -6199,6 +6276,10 @@
 "are run by the changesets receiver while the ``outgoing`` one is for\n"
 "the sender::"
 msgstr ""
+"Zunächst muss die Erweiterung (wie in :hg:`help extensions` beschrieben)\n"
+"aktiviert werden und dann als Hook registriert werden. Für den Empfänger\n"
+"sind dies die ``incoming`` und ``outgoing`` Hooks, für den Sender der\n"
+"``outgoing`` Hook::"
 
 msgid ""
 "  [hooks]\n"
@@ -6217,6 +6298,8 @@
 "  # one email for all outgoing changesets\n"
 "  outgoing.notify = python:hgext.notify.hook"
 msgstr ""
+"  # eine E-Mail für jeden übertragenen Änderungssatz\n"
+"  outgoing.notify = python:hgext.notify.hook"
 
 msgid ""
 "Now the hooks are running, subscribers must be assigned to\n"
@@ -6224,6 +6307,9 @@
 "given email or the ``[reposubs]`` section to map emails to a single\n"
 "repository::"
 msgstr ""
+"Schliesslich müssen noch die Abonnements für die Projektarchive definiert\n"
+"werden. Im Abschnitt ``[usersubs]`` kann man mehrere Archive einer Email\n"
+"zuweisen, in ``[reposubs]`` umgekehrt mehrere Emails für ein Archiv angeben."
 
 msgid ""
 "  [usersubs]\n"
@@ -6252,6 +6338,9 @@
 "root. The subscriptions can be defined in their own file and\n"
 "referenced with::"
 msgstr ""
+"Die glob-Muster müssen auf den absoluten Pfad zum Archiv passen. Alle\n"
+"Abonnements können in einer eigenen Datei gesammelt werden und folgender-\n"
+"maßen in der Konfiguration eingebunden werden::"
 
 msgid ""
 "  [notify]\n"
@@ -6264,23 +6353,33 @@
 "Alternatively, they can be added to Mercurial configuration files by\n"
 "setting the previous entry to an empty value."
 msgstr ""
+"Alternativ (mit leerem Wert für ``notify.config``) können die Abonnements\n"
+"in der Mercurial Konfigurationsdatei angegeben werden."
 
 msgid ""
 "At this point, notifications should be generated but will not be sent until "
 "you\n"
 "set the ``notify.test`` entry to ``False``."
 msgstr ""
+"Nach dieser Konfiguration werden die Benachrichtigungen nun generiert, aber\n"
+"noch nicht gesendet, bis der Wert von ``notify.test`` auf ``False`` gesetzt\n"
+"wird."
 
 msgid ""
 "Notifications content can be tweaked with the following configuration "
 "entries:"
 msgstr ""
+"Der Inhalt der Benachrichtigungen kann mit der folgenden Konfiguration\n"
+"angepasst werden:"
 
 msgid ""
 "notify.test\n"
 "  If ``True``, print messages to stdout instead of sending them. Default: "
 "True."
 msgstr ""
+"notify.test\n"
+"  Falls ``True`` werden die Nachrichten auf die Standardausgabe und nicht\n"
+"  als Email versendet. Standard: True."
 
 msgid ""
 "notify.sources\n"
@@ -6292,6 +6391,14 @@
 "  locally. Outgoing sources are the same except for ``unbundle`` which\n"
 "  is replaced by ``bundle``. Default: serve."
 msgstr ""
+"notify.sources\n"
+"  Kommaseparierte Liste von Quellaktionen. Benachrichtigungen werden nur\n"
+"  gesendet, wenn die Änderungen von einer solchen Aktion ausgelöst wurden.\n"
+"  Quellen für ankommende Änderungen sind ``serve`` (Änderungen via http\n"
+"  oder ssh), ``pull`` (aktiv abgerufen), ``unbundle`` (per :hg:`unbundle`\n"
+"  eingefügt) oder ``push`` (lokal übertragen). Für ausgehende Änderungen\n"
+"  gibt es die gleichen, nur mit ``unbundle`` gegen ``bundle`` getauscht.\n"
+"  Standard: serve."
 
 msgid ""
 "notify.strip\n"
@@ -6303,12 +6410,21 @@
 "change\n"
 "  ``/long/path/repository`` into ``repository``. Default: 0."
 msgstr ""
+"notify.strip\n"
+"  Anzahl der Schrägstriche, die vom URL-Pfad abgeschnitten werden sollen.\n"
+"  Standardmäßig werden Archive mit ihrem absoluten Pfad benannt.\n"
+"  Mit ``notify.strip`` lässt sich das in relative Pfade abwandeln. Zum\n"
+"  Beispiel wird ``/langer/pfad/zum/archiv`` mit ``strip=4`` zu ``archiv``.\n"
+"  Standard: 0."
 
 msgid ""
 "notify.domain\n"
 "  If subscribers emails or the from email have no domain set, complete them\n"
 "  with this value."
 msgstr ""
+"notify.domain\n"
+"  Falls eine Abonnementen- oder die Sender-Adresse keine Domäne haben,\n"
+"  wird dieser Wert eingefügt."
 
 msgid ""
 "notify.style\n"
@@ -6328,62 +6444,103 @@
 "notify.incoming\n"
 "  Template to use when run as incoming hook, override ``notify.template``."
 msgstr ""
+"notify.incoming\n"
+"  Vorlage (mit höherer Priorität als ``notify.template``), falls die Aktion\n"
+"  durch einen 'incoming'-Hook ausgelöst wurde."
 
 msgid ""
 "notify.outgoing\n"
 "  Template to use when run as outgoing hook, override ``notify.template``."
 msgstr ""
+"notify.outcoming\n"
+"  Vorlage (mit höherer Priorität als ``notify.template``), falls die Aktion\n"
+"  durch einen 'outcoming'-Hook ausgelöst wurde."
 
 msgid ""
 "notify.changegroup\n"
 "  Template to use when running as changegroup hook, override\n"
 "  ``notify.template``."
 msgstr ""
+"notify.changegroup\n"
+"  Vorlage (mit höherer Priorität als ``notify.template``), falls die Aktion\n"
+"  durch einen 'changegroup'-Hook ausgelöst wurde."
 
 msgid ""
 "notify.maxdiff\n"
 "  Maximum number of diff lines to include in notification email. Set to 0\n"
 "  to disable the diff, -1 to include all of it. Default: 300."
 msgstr ""
+"notify.maxdiff\n"
+"  Maximale Zeilenanzahl des Diffs in der Benachrichtigungsemail. Der Wert\n"
+"  0 unterbindet die Anzeige des Diffs, -1 wird das gesamte Diff ausgeben.\n"
+"  Standard: 300."
 
 msgid ""
 "notify.maxsubject\n"
 "  Maximum number of characters in emails subject line. Default: 67."
 msgstr ""
+"notify.maxsubject\n"
+"  Maximale Länge der Betreffszeile. Standard: 67."
 
 msgid ""
 "notify.diffstat\n"
 "  Set to True to include a diffstat before diff content. Default: True."
 msgstr ""
+"notify.diffstat\n"
+"  Zeige eine Diff-Statistik vor dem eigentlich Diff an. Standard: True."
 
 msgid ""
 "notify.merge\n"
 "  If True, send notifications for merge changesets. Default: True."
 msgstr ""
+"notify.merge\n"
+"  Sende Nachrichten auch für Zusammenführungen. Standard: True."
 
 msgid ""
 "notify.mbox\n"
 "  If set, append mails to this mbox file instead of sending. Default: None."
 msgstr ""
 "notify.mbox\n"
-"  Schreibe Nachrichten in mbox Datei, anstatt sie zu versenden. Standard: None"
+"  Schreibe Nachrichten in mbox Datei, anstatt sie zu versenden. Standard: "
+"None"
+
+msgid ""
+"notify.fromauthor\n"
+"  If set, use the first committer of the changegroup for the \"From\" field "
+"of\n"
+"  the notification mail. If not set, take the user from the pushing repo.\n"
+"  Default: False."
+msgstr ""
+"notify.fromauthor\n"
+"  Verwende den Autoren der ersten Änderungsgruppe als Absender der\n"
+"  Benachrichtigungsemail. Falls nicht gesetzt, verwende den Nutzer im\n"
+"  übertragenden Archiv. Standard: False."
+
 
 msgid ""
 "If set, the following entries will also be used to customize the "
 "notifications:"
 msgstr ""
+"Durch Setzen der folgenden Einträge können die Benachrichtigungen weiter\n"
+"angepasst werden:"
 
 msgid ""
 "email.from\n"
 "  Email ``From`` address to use if none can be found in generated email "
 "content."
 msgstr ""
+"email.from\n"
+"  Die zu verwendende Senderadresse (``From``), falls die Vorlage keinen\n"
+"  Wert setzt."
 
 msgid ""
 "web.baseurl\n"
 "  Root repository browsing URL to combine with repository paths when making\n"
 "  references. See also ``notify.strip``."
 msgstr ""
+"web.baseurl\n"
+"  Die Basis-URL für alle Archive, die mit dem abgeschnittenen (siehe\n"
+"  ``notify.strip``) Archivpfad für Referenzen verwendet wird."
 
 #, python-format
 msgid "%s: %d new changesets"
@@ -6487,7 +6644,7 @@
 "Befehle den Pager benutzen."
 
 msgid "If pager.attend is present, pager.ignore will be ignored."
-msgstr "Wenn pager.attend vorhanden ist, wird pager.ignore ignoriert."
+msgstr "Wenn pager.attend vorhanden ist, ist pager.ignore wirkungslos."
 
 msgid ""
 "To ignore global commands like :hg:`version` or :hg:`help`, you have\n"
@@ -6550,7 +6707,7 @@
 "configuration file::"
 msgstr ""
 "Andere Standardwerte können beispielsweise durch den folgenden Abschnitt\n"
-"in der hgrc konfiguriert werden::"
+"in der Konfigurationsdatei gesetzt werden::"
 
 msgid ""
 "  [email]\n"
@@ -6571,8 +6728,8 @@
 "Use ``[patchbomb]`` as configuration section name if you need to\n"
 "override global ``[email]`` address settings."
 msgstr ""
-"Benutzen Sie [patchbomb] als Abschnittsnamen, falls Sie globale\n"
-"[email]-Einstellungen überschreiben müssen."
+"Benutzen Sie ``[patchbomb]`` als Abschnittsnamen, falls Sie globale\n"
+"``[email]``-Einstellungen überschreiben müssen."
 
 msgid ""
 "Then you can use the :hg:`email` command to mail a series of\n"
@@ -6709,9 +6866,9 @@
 "    with a final summary of all messages and asked for confirmation before\n"
 "    the messages are sent."
 msgstr ""
-"Bei der Angabe der Optionen -d/--diffstat oder -c/--confirm wird eine\n"
-"abschließende Zusammenfassung aller Nachrichten angezeigt und um\n"
-"Bestätigung gebeten, bevor die Nachrichten versendet werden."
+"    Bei der Angabe der Optionen -d/--diffstat oder -c/--confirm wird eine\n"
+"    abschließende Zusammenfassung aller Nachrichten angezeigt und um\n"
+"    Bestätigung gebeten, bevor die Nachrichten versendet werden."
 
 msgid ""
 "    By default the patch is included as text in the email body for\n"
@@ -6747,9 +6904,9 @@
 "    previewed with any mail user agent which supports UNIX mbox\n"
 "    files."
 msgstr ""
-"Alternativ werden die Nachrichten mit der Option -m/--mbox in eine Datei\n"
-"geschrieben, die von jedem Emailprogramm, welches das UNIX-mbox-Format\n"
-"unterstützt, geprüft werden, zum Beispiel mit mutt::"
+"    Alternativ werden die Nachrichten mit der Option -m/--mbox in eine\n"
+"    Datei geschrieben, die von jedem Emailprogramm, welches das UNIX-mbox-\n"
+"    Format unterstützt, geprüft werden, zum Beispiel mit mutt::"
 
 msgid ""
 "    With -n/--test, all steps will run, but mail will not be sent.\n"
@@ -6759,13 +6916,13 @@
 "    PAGER environment variable is set, your pager will be fired up once\n"
 "    for each patchbomb message, so you can verify everything is alright."
 msgstr ""
-"Um das Versenden verfrühter Patches zu verhindern, sollte man :hg:`email`\n"
-"mit der Option \"-n\" (Testmodus) aufrufen. Sie werden nach einer\n"
-"Empfängeradresse, einem Betreff und einer einleitenden Nachricht gefragt,\n"
-"die die Patches Ihrer Patchbombe beschreibt. Danach werden die\n"
-"Patchbombennachrichten angezeigt. Wenn die PAGER-Umgebungsvariable gesetzt\n"
-"ist, wird Ihr Pager für jede Patchbombe einzeln aufgerufen, so dass alles\n"
-"überprüft werden kann."
+"    Mit der Option -n/--test werden alle Schritte ausgeführt und das\n"
+"    Ergebnis angezeigt, aber keine Email versendet. Sie werden also nach\n"
+"    einer Empfängeradresse, einem Betreff und einer einleitenden Nachricht,\n"
+"    die die Patches Ihrer Patchbombe beschreibt, gefragt. Dann werden alle\n"
+"    Patchbombennachrichten angezeigt. Wenn die PAGER-Umgebungsvariable\n"
+"    gesetzt ist, wird Ihr Pager für jede Patchbombe einzeln aufgerufen, so\n"
+"    dass alles überprüft werden kann."
 
 msgid ""
 "    In case email sending fails, you will find a backup of your series\n"
@@ -6828,7 +6985,7 @@
 "    hgrc. See the [email] section in hgrc(5) for details.\n"
 "    "
 msgstr ""
-"    Um dieses Kommando zu benutzen muss das Email-Versenden im Abschnitt\n"
+"    Um dieses Kommando zu benutzen muss der Emailversand im Abschnitt\n"
 "    [email] der Konfiguration aktiviert sein. Siehe hgrc(5) für Details.\n"
 "    "
 
@@ -6863,23 +7020,23 @@
 msgstr "Diese Patch-Serie besteht aus %d Patches."
 
 msgid "no recipient addresses provided"
-msgstr ""
+msgstr "Keine Empfängeradresse angegeben"
 
 msgid ""
 "\n"
 "Final summary:"
 msgstr ""
 "\n"
-"Zusammenfassung:"
+"Engültige Zusammenfassung:"
 
 msgid "are you sure you want to send (yn)?"
-msgstr "Sicher, dass Sie jetzt senden möchten (y/n)?"
+msgstr "Sicher, dass Sie jetzt senden möchten (j/n)?"
 
 msgid "&No"
 msgstr "&Nein"
 
 msgid "&Yes"
-msgstr "Ja (&y)"
+msgstr "&Ja"
 
 msgid "patchbomb canceled"
 msgstr "patchbomb abgebrochen"
@@ -6957,36 +7114,36 @@
 #. i18n: format XX seconds as "XXs"
 #, python-format
 msgid "%02ds"
-msgstr ""
+msgstr "%02dsek"
 
 #. i18n: format X minutes and YY seconds as "XmYYs"
 #, python-format
 msgid "%dm%02ds"
-msgstr ""
+msgstr "%d:%02d"
 
 #. i18n: format X hours and YY minutes as "XhYYm"
 #, python-format
 msgid "%dh%02dm"
-msgstr ""
+msgstr "%d:%02d"
 
 #. i18n: format X days and YY hours as "XdYYh"
 #, python-format
 msgid "%dd%02dh"
-msgstr ""
+msgstr "%dd%02dh"
 
 #. i18n: format X weeks and YY days as "XwYYd"
 #, python-format
 msgid "%dw%02dd"
-msgstr ""
+msgstr "%dw%02dd"
 
 #. i18n: format X years and YY weeks as "XyYYw"
 #, python-format
 msgid "%dy%02dw"
-msgstr ""
+msgstr "%dy%02dw"
 
 #, python-format
 msgid "%d %s/sec"
-msgstr ""
+msgstr "%d %s/Sek"
 
 msgid "command to delete untracked files from the working directory"
 msgstr "Löscht nicht versionierte Dateien aus dem Arbeitsverzeichnis"
@@ -7056,7 +7213,7 @@
 "    option.\n"
 "    "
 msgstr ""
-"    Seien Sie mit purge vorsichtig, da Sie Dateien unwiderbringlich\n"
+"    Seien Sie mit purge vorsichtig, da Sie Dateien unwiederbringlich\n"
 "    löschen könnten, die Sie nicht zum Projektarchiv hinzugefügt\n"
 "    haben. Wenn Sie nur die Liste der Dateien sehen wollen, die dieses\n"
 "    Programm entfernen würde, nutzen Sie die Option --print.\n"
@@ -7112,16 +7269,16 @@
 msgstr "Verschiebe auf den gegebenen Änderungssatz"
 
 msgid "collapse the rebased changesets"
-msgstr "Faltet die erzeugten Änderungssätze nach dem Rebase zusammen"
+msgstr "Fügt die verschobenen Änderungssätze zu einem einzelnen zusammen"
 
 msgid "use text as collapse commit message"
-msgstr "Nimm Text als gefaltete Commit-Nachricht"
+msgstr "Setzt die Versionsmeldung des zusammengefügten Änderungssatzes"
 
 msgid "invoke editor on commit messages"
-msgstr "Ruft Editor zum setzen der Versionsmeldung auf"
+msgstr "Ruft Editor zum Setzen der Versionsmeldung auf"
 
 msgid "read collapse commit message from file"
-msgstr "Liest gefaltete Commit-Nachricht aus Datei"
+msgstr "Liest Versionsmeldung für den zusammengefügten Änderungssatz aus Datei"
 
 msgid "keep original changesets"
 msgstr "Behält die ursprünglichen Änderungssätze bei"
@@ -7136,15 +7293,17 @@
 msgstr "Methode für das Zusammenführen"
 
 msgid "continue an interrupted rebase"
-msgstr "Führt einen unterbrochenen Rebase fort"
+msgstr "Führt eine unterbrochene Pfropfung fort"
 
 msgid "abort an interrupted rebase"
-msgstr "Bricht einen unterbrochenen Rebase ab"
+msgstr "Bricht eine unterbrochene Pfropfung ab"
 
 msgid ""
 "hg rebase [-s REV | -b REV] [-d REV] [options]\n"
 "hg rebase {-a|-c}"
 msgstr ""
+"hg rebase [-s REV | -b REV] [-d REV] [Optionen]\n"
+"hg rebase {-a|-c}"
 
 msgid "move changeset (and descendants) to a different branch"
 msgstr ""
@@ -7170,7 +7329,7 @@
 "    Sie sollten keine Änderungssätze umpfropfen, die auch andere bereits\n"
 "    haben, ansonsten zwingen Sie jeden anderen die gleiche rebase-\n"
 "    Operation durchzuführen, um die verschobenen Versionen nicht\n"
-"    doppelt zu haben, wenn sie Ihre Änderungen ziehen."
+"    doppelt zu haben, sobald sie Ihre Änderungen abrufen."
 
 msgid ""
 "    If you don't specify a destination changeset (``-d/--dest``),\n"
@@ -7178,10 +7337,10 @@
 "    destination. (The destination changeset is not modified by\n"
 "    rebasing, but new changesets are added as its descendants.)"
 msgstr ""
-"    Wenn Sie keine Zielversion spezifizieren (``-d/--dest``),\n"
-"    verwendet rebase den head des aktuellen named branch, der am \n"
-"    nächsten an tip ist als Ziel (die Zielversion wird durch rebase\n"
-"    nicht verändert. Sie erhält nur neue changesets als Kinder)."
+"    Wenn Sie keine Zielversion spezifizieren (``-d/--dest``), verwendet\n"
+"    rebase als Ziel den Kopf des aktuellen benannten Zweigs, der\n"
+"    der Projektspitze (tip) am nächsten ist. (Die Zielversion wird durch\n"
+"    die Verschiebung nicht verändert, aber erhält neue Kinder.)"
 
 msgid ""
 "    You can specify which changesets to rebase in two ways: as a\n"
@@ -7196,19 +7355,17 @@
 "    the whole branch. If you specify neither ``-s`` nor ``-b``, rebase\n"
 "    uses the parent of the working directory as the base."
 msgstr ""
-"    Sie können auf zwei Arten angeben, welche Changesets rebased werden\n"
-"    sollen: als \"source\" oder als \"base\" Changesets. Beide sind\n"
-"    Abkürzungen für ein Menge von Changesets, die topologisch\n"
-"    zusammenhängen (die \"source\" Branch). Wenn Sie source angeben\n"
-"    (``-s/--source``), rebase wird dieses Changeset und all seine\n"
-"    Descendants nach dest pfropfen. Wenn Sie base angeben (``-b/--base``),\n"
-"    rebase wird Vorgänger von base auswählen, bis zu aber nicht\n"
-"    einschließlich dem gemeinsamen Vorgänger mit dest. Es ist also\n"
-"    ``-b`` weniger präzise, aber bequemer, als ``-s``: Sie können\n"
-"    jegliches Changeset im Quell-Branch angeben, und rebase wird den\n"
-"    gesamten Branch auswählen. Wenn Sie weder ``-s``noch ``-b`` angeben,\n"
-"    wird rebase den Parent des aktuellen Verzeichnisses als Base\n"
-"    auswählen."
+"    Sie können die zu verschiebenden Versionen auf zwei Arten angeben: Als\n"
+"    \"Quell-\" oder als \"Basisversion\". Mit diesen ist jeweils eine Menge\n"
+"    von topologisch verwandten Revisionen gemeint (der \"Quell\"-zweig).\n"
+"    Wenn Sie eine Quellversion (``-s/--source``) angeben, wird Mercurial\n"
+"    diese Version und alle ihrer Nachfahren verschieben. Geben Sie eine\n"
+"    Basisversion (``-b/--base``) an, so sucht Mercurial den jüngsten\n"
+"    gemeinsamen Vorfahren der Basis und des Ziels und verschiebt den Zweig,\n"
+"    der die Basis enthält, nicht jedoch den gemeinsamen Vorfahren.\n"
+"    Somit ist ``-s`` genauer, aber ``-b`` praktischer: Man gibt irgendeine\n"
+"    Version im zu verschiebenden Zweig an. Wenn Sie weder ``-s`` noch\n"
+"    ``-b`` angeben, wird den Vorfahr der Arbeitskopie als Basis verwendet."
 
 msgid ""
 "    By default, rebase recreates the changesets in the source branch\n"
@@ -7217,12 +7374,11 @@
 "    changesets in the source branch (e.g. merges from the destination\n"
 "    branch) may be dropped if they no longer contribute any change."
 msgstr ""
-"    Per Default erzeugt rebase die Changesets im Quell-Branch als\n"
-"    Descendants von dest neu, und zerstört dann die Originale. Benutzen\n"
-"    Sie ``--keep``, um die originalen Quell-Changesets zu bewahren.\n"
-"    Einige Changeset im Quell-Branch (z.B. Merges vom Ziel-Branch),\n"
-"    können gelöscht werden, wenn sie keine weiteren Änderungen\n"
-"    mehr beisteuern."
+"    Standardmäßig werden die Änderungssätze des Quellzweigs als Nachfahren\n"
+"    des Ziels erzeugt und ihr Original zerstört. Mit ``--keep`` werden\n"
+"    die Originale erhalten. Einige Änderungssätze des Quellzweigs könnten\n"
+"    entfernt werden (z.B. Zusammenführungen aus dem Zielzweig, die keine\n"
+"    eigenen Änderungen über die Zusammenführung hinaus enthalten)."
 
 msgid ""
 "    One result of the rules for selecting the destination changeset\n"
@@ -7232,11 +7388,14 @@
 "    destination (or ``update`` to the other head, if it's the head of\n"
 "    the intended source branch)."
 msgstr ""
-"    Ein Ergebnis der Regeln für das Auswählen der Ziel-Changesets und des\n"
-"    Quell-Branches ist, daß, im Gegensatz zu ``merge``, rebase nichts\n"
-"    tun wird, wenn Sie auf dem neuesten (tipmost) Head eines benannten\n"
-"    Branches mit zwei Heads sind. Sie müssen Quelle und/oder Ziel angeben\n"
-"    (oder auf den anderen Head ``update``en)."
+"    Als Folge der automatischen Auswahlregeln für Quelle und Ziel wird\n"
+"    (im Gegensatz zu einer Zusammenführung) keine Verschiebung "
+"durchgeführt,\n"
+"    wenn der jüngere von zwei Köpfen eines Zweiges aktuell ist. In diesem\n"
+"    Falle (z.B. bei lokaler Versionsübernahme nach einem Abrufen), muss\n"
+"    eine Quelle und/oder ein Ziel explizit angegeben werden. Dieser Fall\n"
+"    tritt aber vor allem ein, wenn das Arbeitsverzeichnis im Zielzweig\n"
+"    liegt, also zunächst auf den Quellzweig aktualisiert werden muss."
 
 msgid ""
 "    If a rebase is interrupted to manually resolve a merge, it can be\n"
@@ -7255,9 +7414,11 @@
 
 msgid "message can only be specified with collapse"
 msgstr ""
+"Eine Versionsmeldung kann nur für beim Zusammenfalten (--collapse) gegeben\n"
+"werden"
 
 msgid "cannot use both abort and continue"
-msgstr "abort und continue können nicht gleichzeitig genutzt werden"
+msgstr "abort und continue dürfen nicht gleichzeitig angegeben werden"
 
 msgid "cannot use collapse with continue or abort"
 msgstr "collapse kann nicht mit continue oder abort genutzt werden"
@@ -7266,19 +7427,19 @@
 msgstr "detach kann nicht mit continue oder abort genutzt werden"
 
 msgid "abort and continue do not allow specifying revisions"
-msgstr "abort und continue erlauben die Angabe einer Revision nicht"
+msgstr "abort und continue erlauben keine Angabe einer Revision"
 
 msgid "tool option will be ignored\n"
-msgstr ""
+msgstr "Die Option tool wird ignoriert\n"
 
 msgid "cannot specify both a source and a base"
-msgstr "Es können nicht Quelle und Basis gleichzeitig angegeben werden"
+msgstr "Quelle und Basis dürfen nicht gleichzeitig angegeben werden"
 
 msgid "cannot specify both a revision and a base"
-msgstr "Es können nicht Revision und Basis gleichzeitig angegeben werden"
+msgstr "Revision und Basis dürfen nicht gleichzeitig angegeben werden"
 
 msgid "cannot specify both a revision and a source"
-msgstr "Es können nicht Revision und Quelle gleichzeitig angegeben werden"
+msgstr "Revision und Quelle dürfen nicht gleichzeitig angegeben werden"
 
 msgid "detach requires a revision to be specified"
 msgstr "detach benötigt eine Revision"
@@ -7292,11 +7453,18 @@
 msgid "use --keep to keep original changesets"
 msgstr "Verwende --keep, um die ursprünglichen Änderungssätze zu behalten"
 
+#, python-format
+msgid "Can't rebase immutable changeset %s"
+msgstr "Nicht veränderbarer Änderungssatz %s kann nicht verschoben werden"
+
+msgid "see hg help phases for details"
+msgstr "Siehe hg help phases für Details"
+
 msgid "nothing to rebase\n"
-msgstr "Kein Rebase nötig\n"
+msgstr "Kein Verschiebung nötig\n"
 
 msgid "cannot collapse multiple named branches"
-msgstr "Kann nicht mehrere benannte Zweige kollabieren"
+msgstr "Mehrere benannte Zweige können nicht zusammengefaltet werden"
 
 msgid "rebasing"
 msgstr "Verschiebe"
@@ -7313,13 +7481,13 @@
 msgstr "keine Änderungen, Revision %d übersprungen\n"
 
 msgid "rebase merging completed\n"
-msgstr "Zusammenführungen des Rebase abgeschlossen\n"
+msgstr "Zusammenführungen der Verschiebung abgeschlossen\n"
 
 msgid "warning: new changesets detected on source branch, not stripping\n"
 msgstr "Warnung: Neue Änderungssätze auf Quellzweig gefunden, lösche nicht\n"
 
 msgid "rebase completed\n"
-msgstr "Rebase abgeschlossen\n"
+msgstr "Verschiebung abgeschlossen\n"
 
 #, python-format
 msgid "%d revisions have been skipped\n"
@@ -7332,39 +7500,43 @@
 #, python-format
 msgid "cannot use revision %d as base, result would have 3 parents"
 msgstr ""
-"Revision %d kann nicht als Basis genutzt werden, das Ergebnis hätte 3 "
+"Revision %d kann nicht als Basis genutzt werden: das Ergebnis hätte 3 "
 "Vorgänger"
 
 msgid "no rebase in progress"
-msgstr "Kein vorheriger Rebase zur Wiederaufnahme"
+msgstr "Keine vorherige Verschiebung zur Wiederaufnahme"
+
+msgid "warning: immutable rebased changeset detected, can't abort\n"
+msgstr ""
+"Warnung: Unveränderbare Änderungssätze gefunden. Kann nicht abbrechen\n"
 
 msgid "warning: new changesets detected on target branch, can't abort\n"
 msgstr ""
-"Warnung: Neue Änderungssätze auf Zielzweig gefunden, kann nicht abbrechen\n"
+"Warnung: Neue Änderungssätze auf Zielzweig gefunden. Kann nicht abbrechen\n"
 
 msgid "rebase aborted\n"
-msgstr "Rebase abgebrochen\n"
+msgstr "Verschiebung abgebrochen\n"
 
 msgid "cannot rebase onto an applied mq patch"
-msgstr "Rebase kann auf einem angewandten MQ-Patch nicht aufsetzen"
+msgstr "Verschiebung kann nicht auf einem angewandten MQ-Patch aufsetzen"
 
 msgid "no matching revisions"
 msgstr "keine passenden Revisionen"
 
 msgid "can't rebase multiple roots"
-msgstr ""
+msgstr "Mehrere Wurzeln können nicht verschoben werden"
 
 msgid "source is ancestor of destination"
 msgstr "Quelle ist ein Vorfahr des Ziels"
 
 msgid "--tool can only be used with --rebase"
-msgstr ""
+msgstr "--tool kann nicht gleichzeitig mit --rebase verwendet werden"
 
 msgid "rebase working directory to branch head"
-msgstr "Führt Rebase zu einem Zweigkopf auf dem Arbeitsverzeichnis aus"
+msgstr "Führt Verschiebung des Arbeitsverzeichnisses auf den Zweigkopf"
 
 msgid "specify merge tool for rebase"
-msgstr "Method für Zusammenführungen innerhalb der Verschiebung"
+msgstr "Methode für Zusammenführungen innerhalb der Verschiebung"
 
 msgid "commands to interactively select changes for commit/qrefresh"
 msgstr "Befehle um interaktiv Änderungen für commit/qrefresh zu wählen"
@@ -7389,16 +7561,16 @@
 msgstr "%d Hunks, %d Zeilen geändert\n"
 
 msgid "[Ynsfdaq?]"
-msgstr ""
+msgstr "[Jnsdfab?]"
 
 msgid "&Yes, record this change"
-msgstr "&Yes - übernimmt diese Änderung"
+msgstr "&Ja - übernimmt diese Änderung"
 
 msgid "&No, skip this change"
-msgstr "&No, überspringt diese Änderung"
+msgstr "&Nein, überspringt diese Änderung"
 
 msgid "&Skip remaining changes to this file"
-msgstr "&Überspringe die restlichen Änderungen an dieser Datei"
+msgstr "Über&springe die restlichen Änderungen an dieser Datei"
 
 msgid "Record remaining changes to this &file"
 msgstr "Zeichne die restlichen Änderungen an dieser &Datei auf"
@@ -7407,13 +7579,13 @@
 msgstr "&Fertig, überspringe die restlichen Änderungen und Dateien"
 
 msgid "Record &all changes to all remaining files"
-msgstr "Übernimmt &alle Änderungen aller restlichen Dateien"
+msgstr "Zeichne &alle Änderungen der verbleibenden Dateien auf"
 
 msgid "&Quit, recording no changes"
-msgstr "&Quit, übernimmt keine Änderungen"
+msgstr "&Beende, zeichnet keine Änderungen auf"
 
 msgid "&?"
-msgstr ""
+msgstr "&?"
 
 msgid "user quit"
 msgstr "Abbruch durch Benutzer"
@@ -7460,7 +7632,7 @@
 "      y - record this change\n"
 "      n - skip this change"
 msgstr ""
-"      y - übernimmt diese Änderung\n"
+"      j - übernimmt diese Änderung\n"
 "      n - überspringt diese Änderung"
 
 msgid ""
@@ -7475,9 +7647,9 @@
 "      a - record all changes to all remaining files\n"
 "      q - quit, recording no changes"
 msgstr ""
-"      d - fertig, überspringt verbleibende Änderungen und Dateien\n"
+"      f - fertig, überspringt verbleibende Änderungen und Dateien\n"
 "      a - übernimmt alle Änderungen aller verbleibenden Dateien\n"
-"      q - beendet ohne Änderungen zu übernehmen"
+"      b - beendet ohne Änderungen zu übernehmen"
 
 msgid "      ? - display help"
 msgstr "      ? - zeigt Hilfe an"
@@ -7507,8 +7679,8 @@
 
 msgid "cannot partially commit a merge (use \"hg commit\" instead)"
 msgstr ""
-"Eine Zusammenführung kann nicht teilweise übernommen werden (verwende "
-"stattdessen :h:`commit`)"
+"Eine Zusammenführung kann nicht teilweise übernommen werden (verwende :hg:"
+"`commit`)"
 
 msgid "no changes to record\n"
 msgstr "Keine Änderungen zu übernehmen\n"
@@ -7520,49 +7692,51 @@
 msgstr "Interaktive Auswahl der Änderungen für refresh"
 
 msgid "recreates hardlinks between repository clones"
-msgstr "stellt Hardlinks zwischen Repository Clones wieder her"
+msgstr "stellt Hardlinks zwischen Archivklonen wieder her"
 
 msgid "recreate hardlinks between two repositories"
-msgstr "stellt Hardlinks zwischen zwei Repositories wieder her"
+msgstr "stellt harte Verknüpfungen zwischen zwei Archiven wieder her"
 
 msgid ""
 "    When repositories are cloned locally, their data files will be\n"
 "    hardlinked so that they only use the space of a single repository."
 msgstr ""
-"    Wenn Repositories lokal geklont werden, werden ihre Datendateien\n"
-"    hart gelinkt, sodaß sie nur den Platz eines einzelnen Repositories\n"
-"    belegen."
+"    Wenn Archive lokal geklont werden, werden ihre Datendateien hart\n"
+"    verknüpft, sodass sie nur den Platz eines einzelnen Archivs belegen."
 
 msgid ""
 "    Unfortunately, subsequent pulls into either repository will break\n"
 "    hardlinks for any files touched by the new changesets, even if\n"
 "    both repositories end up pulling the same changes."
 msgstr ""
-"    Unglücklicherweise werden nachfolgende ``pull``s in jedes von diesen\n"
-"    Repositories Hardlinks für alle Dateien, die von dem neuen Changeset\n"
-"    betroffen sind, brechen, selbst wenn beide Repositories schlussendlich\n"
-"    die gleichen Änderungen einbeziehen."
+"    Unglücklicherweise brechen spätere Archivänderungen (z.B. Abrufen) die\n"
+"    Verknüpfungen aller Dateien, die von neuen Änderungssätzen betroffen\n"
+"    sind, selbst wenn beide Archive letzlich dieselben Änderungen enthalten."
 
 msgid ""
 "    Similarly, passing --rev to \"hg clone\" will fail to use any\n"
 "    hardlinks, falling back to a complete copy of the source\n"
 "    repository."
 msgstr ""
-"    In gleicher Weise scheitert \"hg clone\" mit --rev an Hardlinks,\n"
-"    sondern nutzt eine komplette Kopie des Quell-Repositories."
+"    In gleicher Weise scheitert \"hg clone\" mit --rev an harten\n"
+"    Verknüpfungen und nutzt eine komplette Kopie des Quellarchivs."
 
 msgid ""
 "    This command lets you recreate those hardlinks and reclaim that\n"
 "    wasted space."
 msgstr ""
-"    Dieses Kommando erlaubt Ihnen, diese Hardlinks wieder herzustellen und\n"
-"    den verlorenen Platz wieder zurück zu gewinnen."
+"    Dieses Kommando erlaubt es, diese Verknüpfungen wieder herzustellen\n"
+"    und den verlorenen Platz zurückzugewinnen."
 
 msgid ""
 "    This repository will be relinked to share space with ORIGIN, which\n"
 "    must be on the same local disk. If ORIGIN is omitted, looks for\n"
 "    \"default-relink\", then \"default\", in [paths]."
 msgstr ""
+"    Dieses Archiv wird neu verknüpft um den Speicher mit HERKUNFT, welches\n"
+"    auf derselben lokalen Platte sein muss, zu teilen. Wenn HERKUNFT nicht\n"
+"    angegeben ist, wird der Pfade (siehe [paths]) mit dem Namen\n"
+"    \"default-relink\" und schliesslich \"default\" verwendet."
 
 msgid ""
 "    Do not attempt any read operations on this repository while the\n"
@@ -7570,9 +7744,12 @@
 "    writes.)\n"
 "    "
 msgstr ""
+"    Versuchen Sie nicht, während der Aktion Leseoperationen auf diesem\n"
+"    Archiv durchzuführen. Schreiben wird von beiden Archive verhindert.\n"
+"    "
 
 msgid "hardlinks are not supported on this system"
-msgstr "Hardlinks werden von diesem System nicht unterstützt"
+msgstr "Harte Verknüpfungen werden von diesem System nicht unterstützt"
 
 msgid "must specify local origin repository"
 msgstr "Lokales Quellarchiv muss angegeben werden"
@@ -7582,11 +7759,11 @@
 msgstr "Wiederverknüpft: %s nach %s\n"
 
 msgid "there is nothing to relink\n"
-msgstr ""
+msgstr "Es gibt nichts zum wiederverknüpfen\n"
 
 #, python-format
 msgid "tip has %d files, estimated total number of files: %s\n"
-msgstr ""
+msgstr "Die Archivspitze (tip) hat %d Dateien. Geschätzte Gesamtzahl: %s\n"
 
 msgid "collecting"
 msgstr "Sammle"
@@ -7602,21 +7779,21 @@
 msgstr "Quelle und Ziel sind auf unterschiedlichen Geräten"
 
 msgid "pruning"
-msgstr ""
+msgstr "Schränke ein"
 
 #, python-format
 msgid "pruned down to %d probably relinkable files\n"
-msgstr ""
+msgstr "Schränke auf %d wahrscheinlich wiederverknüpfbare Dateien ein\n"
 
 msgid "relinking"
-msgstr ""
+msgstr "Verknüpfe erneut"
 
 #, python-format
 msgid "relinked %d files (%s reclaimed)\n"
-msgstr ""
+msgstr "%d Dateien wiederverknüpft (%s zurückgewonnen)\n"
 
 msgid "[ORIGIN]"
-msgstr ""
+msgstr "[HERKUNFT]"
 
 msgid "extend schemes with shortcuts to repository swarms"
 msgstr ""
@@ -7731,7 +7908,7 @@
 
 #, python-format
 msgid "skipping already applied revision %s\n"
-msgstr ""
+msgstr "Ãœberspringe bereits angewendete Revision %s\n"
 
 #, python-format
 msgid "skipping merge changeset %s:%s\n"
@@ -7750,14 +7927,14 @@
 msgstr ""
 
 msgid "filter failed"
-msgstr ""
+msgstr "Filter fehlgeschlagen"
 
 msgid "can only omit patchfile if merging"
 msgstr ""
 
 #, python-format
 msgid "%s: empty changeset"
-msgstr ""
+msgstr "%s: leerer Änderungssatz"
 
 msgid "fix up the merge and run hg transplant --continue"
 msgstr ""
@@ -7774,7 +7951,7 @@
 msgstr ""
 
 msgid "commit failed"
-msgstr ""
+msgstr "Übernahme der Änderungen schlug fehl"
 
 msgid "filter corrupted changeset (no user or date)"
 msgstr "filtriere beschädigte Änderungssätze (ohne Nutzer oder Datum)"
@@ -8129,8 +8306,8 @@
 msgstr "Aktualisiere Lesezeichen %s\n"
 
 #, python-format
-msgid "not updating divergent bookmark %s\n"
-msgstr "Aktualisiere nicht divergierendes Lesezeichen %s\n"
+msgid "divergent bookmark %s stored as %s\n"
+msgstr "Divergierendes Lesezeichen %s als %s gespeichert\n"
 
 msgid "searching for changed bookmarks\n"
 msgstr "Suche nach geänderten Lesezeichen\n"
@@ -8288,6 +8465,10 @@
 msgstr "Marke:           %s\n"
 
 #, python-format
+msgid "phase:       %s\n"
+msgstr "Phase:       %s\n"
+
+#, python-format
 msgid "parent:      %d:%s\n"
 msgstr "Vorgänger:       %d:%s\n"
 
@@ -8585,6 +8766,8 @@
 "    Returns 0 if all files are successfully added.\n"
 "    "
 msgstr ""
+"    Gibt 0 zurück, wenn alle Dateien erfolgreich hinzugefügt wurden.\n"
+"    "
 
 msgid "add all new files, delete all missing files"
 msgstr "Fügt alle neuen Dateien hinzu, löscht alle fehlenden Dateien"
@@ -8601,8 +8784,8 @@
 "    ``.hgignore``. As with add, these changes take effect at the next\n"
 "    commit."
 msgstr ""
-"    Neue Dateien werden ignoriert, wenn sie einem der Muster aus "
-"``.hgignore``\n"
+"    Neue Dateien werden ignoriert, wenn sie einem der Muster aus ``."
+"hgignore``\n"
 "    entsprechen. Genau wie add, wirken diese Änderungen erst beim nächsten\n"
 "    Ãœbernehmen (commit)."
 
@@ -8632,8 +8815,7 @@
 msgstr "Annotiert die angegebene Revision"
 
 msgid "follow copies/renames and list the filename (DEPRECATED)"
-msgstr ""
-"Folge Kopien/Umbenennungen und liste Dateinamen auf (VERALTET)"
+msgstr "Folge Kopien/Umbenennungen und liste Dateinamen auf (VERALTET)"
 
 msgid "don't follow copies and renames"
 msgstr "Unterläßt das Folgen von Dateikopien und Umbenennungen"
@@ -9086,17 +9268,18 @@
 msgid "track a line of development with movable markers"
 msgstr "Folgt einem Entwicklungsstrang mit einer beweglichen Markierung"
 
-msgid ""
-"    Bookmarks are pointers to certain commits that move when\n"
-"    committing. Bookmarks are local. They can be renamed, copied and\n"
-"    deleted. It is possible to use bookmark names in :hg:`merge` and\n"
-"    :hg:`update` to merge and update respectively to a given bookmark."
+#, fuzzy
+msgid ""
+"    Bookmarks are pointers to certain commits that move when committing.\n"
+"    Bookmarks are local. They can be renamed, copied and deleted. It is\n"
+"    possible to use :hg:`merge NAME` to merge from a given bookmark, and\n"
+"    :hg:`update NAME` to update to a given bookmark."
 msgstr ""
 "    Lesezeichen sind Zeiger auf bestimmte Versionen, die mitwandern,\n"
 "    wenn eine neuen Version erzeugt wird. Lesezeichen sind nur lokal.\n"
 "    Sie können umbenannt, kopiert und gelöscht werden. Es ist möglich,\n"
-"    Lesezeichen bei :hg: `merge` und :hg:`update` zu nutzen, um auf das\n"
-"    angegebene Lesezeichen zu aktualisieren."
+"    Lesezeichen bei :hg: `merge` und :hg:`update` anzugeben, um das an-\n"
+"    gegebene Lesezeichen zusammenzuführen, bzw. darauf zu aktualisieren."
 
 msgid ""
 "    You can use :hg:`bookmark NAME` to set a bookmark on the working\n"
@@ -9165,6 +9348,14 @@
 msgstr "Setzt oder zeigt den Namen des aktuellen Zweigs"
 
 msgid ""
+"    .. note::\n"
+"       Branch names are permanent and global. Use :hg:`bookmark` to create "
+"a\n"
+"       light-weight bookmark instead. See :hg:`help glossary` for more\n"
+"       information about named branches and bookmarks."
+msgstr ""
+
+msgid ""
 "    With no argument, show the current branch name. With one argument,\n"
 "    set the working directory branch name (the branch will not exist\n"
 "    in the repository until the next commit). Standard practice\n"
@@ -9201,13 +9392,6 @@
 "    :hg:`update`. Mit :hg:`commit --close-branch` wird der aktuelle Zweig\n"
 "    geschlossen."
 
-msgid ""
-"    .. note::\n"
-"       Branch names are permanent. Use :hg:`bookmark` to create a\n"
-"       light-weight bookmark instead. See :hg:`help glossary` for more\n"
-"       information about named branches and bookmarks."
-msgstr ""
-
 #, python-format
 msgid "reset working directory to branch %s\n"
 msgstr "Setze Arbeitsverzeichnis auf Zweig %s zurück\n"
@@ -9223,6 +9407,9 @@
 msgid "marked working directory as branch %s\n"
 msgstr "Arbeitsverzeichnis wurde als Zweig %s markiert\n"
 
+msgid "(branches are permanent and global, did you want a bookmark?)\n"
+msgstr ""
+
 msgid "show only branches that have unmerged heads"
 msgstr "Zeigt nur Branches deren Köpfe nicht zusammengeführt wurden"
 
@@ -9259,12 +9446,14 @@
 "    Returns 0.\n"
 "    "
 msgstr ""
+"    Gibt 0 zurück.\n"
+"    "
 
 msgid " (closed)"
-msgstr ""
+msgstr " (geschlossen)"
 
 msgid " (inactive)"
-msgstr ""
+msgstr " (inaktiv)"
 
 msgid "run even when the destination is unrelated"
 msgstr "Auch ausführen, wenn das Ziel keinen Bezug hat"
@@ -9461,7 +9650,8 @@
 "      --pull option to avoid hardlinking."
 msgstr ""
 "      Aus Effizienzgründen werden 'hardlinks' für das Klonen genutzt, wann\n"
-"      immer Quelle und Ziel auf dem selben Dateisystem liegen (dies gilt nur\n"
+"      immer Quelle und Ziel auf dem selben Dateisystem liegen (dies gilt "
+"nur\n"
 "      für die Daten des Archivs, nicht für die Arbeitskopie). Einige\n"
 "      Dateisyteme, wie etwa AFS, implementieren 'hardlinks' fehlerhaft,\n"
 "      erzeugen dabei aber keine Fehlermeldung. Dann muss die --pull Option\n"
@@ -9554,8 +9744,7 @@
 msgstr ""
 
 msgid "    See :hg:`help urls` for details on specifying URLs."
-msgstr ""
-"    Siehe auch :hg:`help urls` für das Format von Adressangaben."
+msgstr "    Siehe auch :hg:`help urls` für das Format von Adressangaben."
 
 msgid "cannot specify both --noupdate and --updaterev"
 msgstr ""
@@ -10171,8 +10360,7 @@
 msgstr "[OPTION]... [-o DATEINAMENMUSTER] REV..."
 
 msgid "dump the header and diffs for one or more changesets"
-msgstr ""
-"Gibt Kopfzeilen und Änderungsverlauf einer oder mehrerer Versionen aus"
+msgstr "Gibt Kopfzeilen und Änderungsverlauf einer oder mehrerer Versionen aus"
 
 msgid "    Print the changeset header and diffs for one or more revisions."
 msgstr ""
@@ -10221,8 +10409,10 @@
 "    :``%N``: Anzahl der generierten Patches\n"
 "    :``%R``: Revisionnummer des Änderungssatzes\n"
 "    :``%b``: Basisname des exportierten Archivs\n"
-"    :``%h``: Kurzform der Prüfsumme des Änderungssatzes (12 Byte hexadezimal)\n"
-"    :``%m``: Erste Zeile der Ãœbernahmenachricht (nur alphanumerische Zeichen)\n"
+"    :``%h``: Kurzform der Prüfsumme des Änderungssatzes (12 Byte "
+"hexadezimal)\n"
+"    :``%m``: Erste Zeile der Ãœbernahmenachricht (nur alphanumerische "
+"Zeichen)\n"
 "    :``%n``: Laufende Nummer mit führenden Nullen, beginnend bei 1\n"
 "    :``%r``: Revisionsnummer mit führenden Nullen"
 
@@ -10349,9 +10539,9 @@
 
 msgid ""
 "    If a graft merge results in conflicts, the graft process is\n"
-"    aborted so that the current merge can be manually resolved. Once\n"
-"    all conflicts are addressed, the graft process can be continued\n"
-"    with the -c/--continue option."
+"    interrupted so that the current merge can be manually resolved.\n"
+"    Once all conflicts are addressed, the graft process can be\n"
+"    continued with the -c/--continue option."
 msgstr ""
 
 msgid ""
@@ -10913,10 +11103,10 @@
 
 msgid ""
 "    With -s/--similarity, hg will attempt to discover renames and\n"
-"    copies in the patch in the same way as 'addremove'."
+"    copies in the patch in the same way as :hg:`addremove`."
 msgstr ""
 "    Mit der Option -s/--similarity werden Umbenennungen und Kopien auf\n"
-"    gleiche Weise wie mit dem Befehl \"hg addremove\" erkannt."
+"    gleiche Weise wie mit dem Befehl :hg:`addremove` erkannt."
 
 msgid ""
 "    To read a patch from standard input, use \"-\" as the patch name. If\n"
@@ -10966,7 +11156,7 @@
 msgstr ""
 
 msgid "patch is damaged or loses information"
-msgstr "Prüfsumme stimmt nicht überein: Patch korrumpiert"
+msgstr "Prüfsumme stimmt nicht überein: Patch beschädigt"
 
 msgid "applied to working directory"
 msgstr "Angewendet aufs Arbeitsverzeichnis"
@@ -11404,12 +11594,11 @@
 msgid "run 'hg heads' to see all heads"
 msgstr "'hg heads' zeigt alle Köpfe"
 
-msgid "there is nothing to merge"
+msgid "nothing to merge"
 msgstr "Es gibt nichts zum Zusammenführen"
 
-#, python-format
-msgid "%s - use \"hg update\" instead"
-msgstr "%s - Nutze \"hg update\" stattdessen"
+msgid "use 'hg update' instead"
+msgstr "Nutze stattdessen 'hg update'"
 
 msgid "working directory not at a head revision"
 msgstr "Arbeitsverzeichnis ist nicht auf Stand der Kopfversion"
@@ -11478,7 +11667,7 @@
 msgstr "'%s' nicht im Manifest gefunden!"
 
 msgid "[NAME]"
-msgstr ""
+msgstr "[NAME]"
 
 msgid "show aliases for remote repositories"
 msgstr "Zeigt Adresse für Aliasnamen von entfernten Projektarchiven an"
@@ -11525,6 +11714,61 @@
 msgid "not found!\n"
 msgstr "nicht gefunden!\n"
 
+msgid "set changeset phase to public"
+msgstr ""
+
+msgid "set changeset phase to draft"
+msgstr ""
+
+msgid "set changeset phase to secret"
+msgstr ""
+
+msgid "allow to move boundary backward"
+msgstr ""
+
+msgid "target revision"
+msgstr ""
+
+msgid "[-p|-d|-s] [-f] [-r] REV..."
+msgstr ""
+
+msgid "set or show the current phase name"
+msgstr ""
+
+msgid "    With no argument, show the phase name of specified revisions."
+msgstr ""
+
+msgid ""
+"    With one of -p/--public, -d/--draft or -s/--secret, change the\n"
+"    phase value of the specified revisions."
+msgstr ""
+
+msgid ""
+"    Unless -f/--force is specified, :hg:`phase` won't move changeset from a\n"
+"    lower phase to an higher phase. Phases are ordered as follows::"
+msgstr ""
+
+msgid "        public < draft < secret"
+msgstr ""
+
+msgid ""
+"    Return 0 on success, 1 if no phases were changed.\n"
+"    "
+msgstr ""
+
+msgid "only one phase can be specified"
+msgstr ""
+
+msgid "no revisions specified!"
+msgstr ""
+
+#, python-format
+msgid "phase change for %i changesets\n"
+msgstr ""
+
+msgid "no phases changed\n"
+msgstr ""
+
 #, python-format
 msgid "not updating: %s\n"
 msgstr "aktualisiere nicht: %s\n"
@@ -11672,8 +11916,7 @@
 msgid ""
 "    Push changesets from the local repository to the specified\n"
 "    destination."
-msgstr ""
-"    Überträgt lokale Änderungen in das angegebene Ziel."
+msgstr "    Überträgt lokale Änderungen in das angegebene Ziel."
 
 msgid ""
 "    This operation is symmetrical to pull: it is identical to a pull\n"
@@ -11728,7 +11971,6 @@
 "gezogen\n"
 "    werden. Beim Weglassen des ZIELs wird standardmäßig der 'default'-Pfad\n"
 "    genutzt. Weitere Hilfe gibt unter :hg:`help urls`."
-"    "
 
 msgid ""
 "    Returns 0 if push was successful, 1 if nothing to push.\n"
@@ -11809,7 +12051,8 @@
 msgstr ""
 "      Option -A/--after kann genutzt werden, um Dateien zu entfernen, die\n"
 "      bereits gelöscht wurden, -f/--force kann genutzt werden, um die\n"
-"      Löschung zu erzwingen. -Af entfernt Dateien aus der nächsten Revision,\n"
+"      Löschung zu erzwingen. -Af entfernt Dateien aus der nächsten "
+"Revision,\n"
 "      ohne sie im Arbeitsverzeichnis zu löschen"
 
 msgid ""
@@ -11819,7 +12062,8 @@
 "      (as reported by :hg:`status`). The actions are Warn, Remove\n"
 "      (from branch) and Delete (from disk):"
 msgstr ""
-"      Die folgende Tabelle beschreibt detailliert das Verhalten von 'remove'\n"
+"      Die folgende Tabelle beschreibt detailliert das Verhalten von "
+"'remove'\n"
 "      für unterschiedliche Dateizustände (Spalten) und Optionskombinationen\n"
 "      (Reihen). Die Dateizustände sind Hinzugefügt (A), Unverändert (C),\n"
 "      Verändert (M) und Fehlend (!) (wie von :hg:`status` angezeigt). Die\n"
@@ -11871,7 +12115,9 @@
 
 #, python-format
 msgid "not removing %s: file has been marked for add (use forget to undo)\n"
-msgstr "Entferne nicht %s: Datei soll hinzugefügt werden ('hg forget' um dies rückgängig zu machen)\n"
+msgstr ""
+"Entferne nicht %s: Datei soll hinzugefügt werden ('hg forget' um dies "
+"rückgängig zu machen)\n"
 
 msgid "record a rename that has already occurred"
 msgstr ""
@@ -11994,8 +12240,7 @@
 msgstr ""
 
 msgid "restore files to their checkout state"
-msgstr ""
-"Setzt gegebene Dateien oder Verzeichnisse auf frühere Version zurück"
+msgstr "Setzt gegebene Dateien oder Verzeichnisse auf frühere Version zurück"
 
 msgid ""
 "    .. note::\n"
@@ -12033,7 +12278,8 @@
 msgstr ""
 "    Mit der -r/--rev oder der -d/--date Option werden die Dateien oder\n"
 "    Verzeichnisse auf die gegebene Revision zurückgesetzt. Da 'revert' aber\n"
-"    nicht die mit dem Arbeitsverzeichnis assoziierte Revisionsnummer ändert,\n"
+"    nicht die mit dem Arbeitsverzeichnis assoziierte Revisionsnummer "
+"ändert,\n"
 "    gelten die betroffenen Dateien dann als modifiziert. Damit kann man\n"
 "    ungewollte aber bereits übernommene Änderungen rückgängig machen. Siehe\n"
 "    auch :hg:`backout` für eine ähnliche Methode."
@@ -12155,17 +12401,14 @@
 "    - unbundle"
 
 msgid ""
-"    It's possible to lose data with rollback: commit, update back to\n"
-"    an older changeset, and then rollback. The update removes the\n"
-"    changes you committed from the working directory, and rollback\n"
-"    removes them from history. To avoid data loss, you must pass\n"
-"    --force in this case."
-msgstr ""
-"    Es gibt die Möglichkeit durch das Zurückrollen Daten zu verlieren, z.B.\n"
-"    die Übernahme neuer Änderungen (commit) gefolgt von einer Aktualisierung\n"
-"    auf eine andere Revision und einem Zurückrollen der Übernahme.\n"
-"    Damit dies nicht aus Versehen passiert, wird in diesem Falle --force als\n"
-"    Parameter gefordert."
+"    To avoid permanent data loss, rollback will refuse to rollback a\n"
+"    commit transaction if it isn't checked out. Use --force to\n"
+"    override this protection."
+msgstr ""
+"    Um einen versehentlichen Datenverlust zu verhindern, wird rollback\n"
+"    keine Änderungssätze aus der Historie entfernen, die nicht im\n"
+"    Arbeitsverzeichnis aktuell sind. Um diesen Schutz abzuschalten,\n"
+"    muss --force (erzwingen) angegeben werden."
 
 msgid ""
 "    This command is not intended for use on public repositories. Once\n"
@@ -12396,7 +12639,8 @@
 "       relative to one merge parent."
 msgstr ""
 "    .. note:\n"
-"       Der Status kann sich vom Diff unterscheiden, wenn sich Berechtigungen\n"
+"       Der Status kann sich vom Diff unterscheiden, wenn sich "
+"Berechtigungen\n"
 "       geändert haben oder eine Zusammenführung durchgeführt wurde. Das\n"
 "       Standard-Diff-Format zeigt keine Berechtigungsänderungen an und\n"
 "       'diff' zeigt nur Änderungen relativ zu einer Vorgängerversion einer\n"
@@ -12436,9 +12680,12 @@
 "      I = ignoriert\n"
 "        = die zuvor hinzugefügt Datei (A) wurde von hier kopiert"
 
-msgid "      - show changes in the working directory relative to a changeset:"
-msgstr ""
-"      - zeigt Änderungen zwischen dem Arbeitsverzeichnis und einer Revision:"
+msgid ""
+"      - show changes in the working directory relative to a\n"
+"        changeset::"
+msgstr ""
+"      - zeigt Änderungen zwischen dem Arbeitsverzeichnis und einer\n"
+"        Revision::"
 
 msgid "          hg status --rev 9353"
 msgstr ""
@@ -12721,7 +12968,8 @@
 "    umbenannt oder manuell einem anderen Änderungssatz angehängt werden."
 
 msgid "update to new branch head if changesets were unbundled"
-msgstr "aktualisiere auf den neuen Zweigkopf when Änderungssätze entpackt wurden"
+msgstr ""
+"aktualisiere auf den neuen Zweigkopf when Änderungssätze entpackt wurden"
 
 msgid "[-u] FILE..."
 msgstr "[-u] DATEI..."
@@ -12745,7 +12993,9 @@
 msgstr "entferne nicht versionierte Änderungen (kein Backup)"
 
 msgid "update across branches if no uncommitted changes"
-msgstr "Aktualisiere auf anderen Zweig (falls keine unversionierte Änderungen ausstehen)"
+msgstr ""
+"Aktualisiere auf anderen Zweig (falls keine unversionierten Änderungen "
+"ausstehen)"
 
 msgid "[-c] [-C] [-d DATE] [[-r] REV]"
 msgstr "[-c] [-C] [-d DATUM] [[-r] REV]"
@@ -12756,10 +13006,11 @@
 msgid ""
 "    Update the repository's working directory to the specified\n"
 "    changeset. If no changeset is specified, update to the tip of the\n"
-"    current named branch."
+"    current named branch and move the current bookmark."
 msgstr ""
 "    Hebt das Arbeitsverzeichnis auf die angegebene Revision an. Ohne\n"
-"    Angabe einer Revision wird der Spitze des aktuellen Zweigs gewählt."
+"    Angabe einer Revision wird der Spitze des aktuellen Zweigs gewählt\n"
+"    und ggf. das aktuelle Lesezeichen verschoben."
 
 msgid ""
 "    If the changeset is not a descendant of the working directory's\n"
@@ -12867,11 +13118,11 @@
 msgstr "(siehe http://mercurial.selenic.com für mehr Information)"
 
 msgid ""
-"Copyright (C) 2005-2011 Matt Mackall and others\n"
+"Copyright (C) 2005-2012 Matt Mackall and others\n"
 "This is free software; see the source for copying conditions. There is NO\n"
 "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
 msgstr ""
-"Copyright (C) 2005-2011 Matt Mackall und andere\n"
+"Copyright (C) 2005-2012 Matt Mackall und andere\n"
 "Dies ist freie Software; siehe Quellen für Kopierbestimmungen. Es besteht\n"
 "KEINE Gewährleistung für das Programm, nicht einmal der Marktreife oder der\n"
 "Verwendbarkeit für einen bestimmten Zweck.\n"
@@ -13175,7 +13426,7 @@
 msgstr "Option --cwd kann nicht abgekürzt werden!"
 
 msgid ""
-"Option -R has to be separated from other options (e.g. not -qR) and --"
+"option -R has to be separated from other options (e.g. not -qR) and --"
 "repository may only be abbreviated as --repo!"
 msgstr ""
 "Option -R muss von anderen Optionen getrennt werden (also z.B. nicht -qR) "
@@ -13899,7 +14150,7 @@
 msgid ""
 "\n"
 "``annotate``\n"
-"\"\"\"\"\"\"\"\""
+"\"\"\"\"\"\"\"\"\"\"\"\""
 msgstr ""
 
 msgid ""
@@ -14502,11 +14753,14 @@
 "various actions such as starting or finishing a commit. Multiple\n"
 "hooks can be run for the same action by appending a suffix to the\n"
 "action. Overriding a site-wide hook can be done by changing its\n"
-"value or setting it to an empty string."
+"value or setting it to an empty string.  Hooks can be prioritized\n"
+"by adding a prefix of ``priority`` to the hook name on a new line\n"
+"and setting the priority.  The default priority is 0 if\n"
+"not specified."
 msgstr ""
 
 msgid "Example ``.hg/hgrc``::"
-msgstr ""
+msgstr "Beispiel ``.hg/hgrc``-Datei::"
 
 msgid ""
 "  [hooks]\n"
@@ -14515,7 +14769,9 @@
 "  # do not use the site-wide hook\n"
 "  incoming =\n"
 "  incoming.email = /my/email/hook\n"
-"  incoming.autobuild = /my/build/hook"
+"  incoming.autobuild = /my/build/hook\n"
+"  # force autobuild hook to run before other incoming hooks\n"
+"  priority.incoming.autobuild = 1"
 msgstr ""
 
 msgid ""
@@ -15798,11 +16054,12 @@
 msgstr ""
 "EDITOR\n"
 "    Manchmal muss Mercurial eine Textdatei in einem Editor öffnen, damit\n"
-"    der Nutzer sie bearbeiten kann, zum Beispiel when eine Commit-\n"
-"    Nachricht geschrieben wird. Der verwendete Editor wird aus den drei\n"
-"    Umgebungsvariablen HGEDITOR, VISUAL und EDITOR (in dieser Reihenfolge)\n"
-"    ermittelt. Der erste nicht-leere wird verwendet. Wenn alle Angaben\n"
-"    leer sind, wird der Standard 'vi' verwendet."
+"    der Nutzer sie bearbeiten kann, zum Beispiel wenn eine Versionsmeldung\n"
+"    geschrieben wird. Der verwendete Editor wird aus den drei Umgebungs-\n"
+"    variablen HGEDITOR, VISUAL und EDITOR (in dieser Reihenfolge) "
+"ermittelt.\n"
+"    Der erste nicht-leere wird verwendet. Wenn alle Angaben leer sind, wird\n"
+"    der Standard 'vi' verwendet."
 
 msgid ""
 "PYTHONPATH\n"
@@ -15993,7 +16250,7 @@
 msgid "- Find C files in a non-standard encoding::"
 msgstr ""
 
-msgid "    hg locate \"set:**.c and not encoding(ascii)\""
+msgid "    hg locate \"set:**.c and not encoding('UTF-8')\""
 msgstr ""
 
 msgid "- Revert copies of large binary files::"
@@ -16656,9 +16913,8 @@
 "character is treated as a comment character, and the ``\\`` character\n"
 "is treated as an escape character."
 msgstr ""
-"Eine ignore-Datei ist eine Textdatei, die aus einer Liste von Patterns "
-"besteht,\n"
-"mit einem Ausdruck pro Zeile. Leere Zeilen werden übersprungen.\n"
+"Eine ignore-Datei ist eine Textdatei, die aus einer Liste von Dateimustern\n"
+"besteht, mit einem Ausdruck pro Zeile. Leere Zeilen werden übersprungen.\n"
 "Das ``#``-Zeichen wird als Kommentarzeichen behandelt und das \n"
 "``\\``-Zeichen als Escape-Zeichen."
 
@@ -16666,11 +16922,11 @@
 "Mercurial supports several pattern syntaxes. The default syntax used\n"
 "is Python/Perl-style regular expressions."
 msgstr ""
-"Mercurial unterstützt verschiedene Pattern-Syntaxen. Im Normalfall\n"
+"Mercurial unterstützt verschiedene Dateimuster-Syntaxen. Im Normalfall\n"
 "werden Python/Perl-artige Reguläre Ausdrücke verwendet."
 
 msgid "To change the syntax used, use a line of the following form::"
-msgstr ""
+msgstr "Die folgende Zeile ändert die von diesem Punkt an verwendete Syntax::"
 
 msgid "  syntax: NAME"
 msgstr "  Syntax: NAME"
@@ -16689,7 +16945,7 @@
 "The chosen syntax stays in effect when parsing all patterns that\n"
 "follow, until another syntax is selected."
 msgstr ""
-"Die gewählte Syntax wird auf auf alle folgenden Patterns angewendet\n"
+"Die gewählte Syntax wird auf auf alle folgenden Muster angewendet\n"
 "bis eine andere Syntax ausgewählt wird."
 
 msgid ""
@@ -17103,8 +17359,7 @@
 msgstr "Beispiel mit regulärem Ausdruck::"
 
 msgid "  re:.*\\.c$      any name ending in \".c\", anywhere in the repository"
-msgstr ""
-"  re:.*\\.c$     jeder Name endend mit \".c\" überall im Projektarchiv"
+msgstr "  re:.*\\.c$     jeder Name endend mit \".c\" überall im Projektarchiv"
 
 msgid "File examples::"
 msgstr "Datei-Beispiele::"
@@ -17398,16 +17653,16 @@
 "subrepositories."
 msgstr ""
 "Mercurial unterstützt im Augenblick Mercurial-, Git- und Subversion-\n"
-"Subrepositories."
+"Unterarchive."
 
 msgid "Subrepositories are made of three components:"
-msgstr "Subrespositories bestehen aus drei Komponenten:"
+msgstr "Unterarchive bestehen aus drei Komponenten:"
 
 msgid ""
 "1. Nested repository checkouts. They can appear anywhere in the\n"
 "   parent working directory."
 msgstr ""
-"1. Verschachtelte Repository Checkouts. Sie können überall im\n"
+"1. Verschachtelte Archivaktualisierungen. Sie können überall im\n"
 "   übergeordneten Arbeitsverzeichnis auftauchen."
 
 msgid ""
@@ -17415,9 +17670,9 @@
 "   tell where the subrepository checkouts come from. Mercurial\n"
 "   subrepositories are referenced like:"
 msgstr ""
-"2. Verschachtelte Repository References. Sie werden in  ``.hgsub``\n"
-"   definiert und geben an, wo Subrepository Checkouts herkommen.\n"
-"   Mercurial Subrepositories werden wie folgt angegeben:"
+"2. Verschachtelte Archivreferenzen. Sie werden in ``.hgsub`` definiert\n"
+"   und geben an, wo Archivaktualisierungen herkommen.\n"
+"   Mercurial-Unterarchive werden wie folgt angegeben:"
 
 msgid "     path/to/nested = https://example.com/nested/repo/path"
 msgstr ""
@@ -17506,8 +17761,8 @@
 "To remove a subrepository from the parent repository, delete its\n"
 "reference from ``.hgsub``, then remove its files."
 msgstr ""
-"Um ein Subrepository aus seinem Parent Repository zu entfernen,\n"
-"entfernen Sie seine Verweise aus ``.hgsub`` und löschen die Dateien."
+"Um ein Unterarchiv aus seinem Elternarchiv zu entfernen, löschen Sie\n"
+"seine Verweise aus ``.hgsub`` und seine Dateien."
 
 msgid ""
 "Interaction with Mercurial Commands\n"
@@ -18125,7 +18380,7 @@
 msgstr ""
 
 msgid "use -f to force"
-msgstr "Benutzen Sie -f, um dennoch fortzufahren"
+msgstr "Benutzen Sie -f zum erzwingen"
 
 #, python-format
 msgid "named branch could not be reset: current branch is still '%s'\n"
@@ -18203,6 +18458,10 @@
 "changegroupsubset nicht unterstützt."
 
 #, python-format
+msgid "updating %s to public failed!\n"
+msgstr ""
+
+#, python-format
 msgid "%d changesets found\n"
 msgstr "%d Änderungssätze gefunden\n"
 
@@ -18339,11 +18598,13 @@
 msgstr "Zeilenangaben im Diff-Kontext müssen Zahlen sein, nicht %r"
 
 #, python-format
-msgid ""
-"untracked file in working directory differs from file in requested revision: "
-"'%s'"
-msgstr ""
-"Unversionierte Datei in der Arbeitskopie unterscheidet sich von der "
+msgid "%s: untracked file differs\n"
+msgstr "%s: Unversionierte Datei verändert\n"
+
+msgid ""
+"untracked files in working directory differ from files in requested revision"
+msgstr ""
+"Unversionierte Dateien in der Arbeitskopie unterscheidet sich von der "
 "angeforderten Revision: '%s'"
 
 #, python-format
@@ -18415,15 +18676,11 @@
 msgid "merging with a working directory ancestor has no effect"
 msgstr "Zusammenführen mit einem Vorfahren der Arbeitskopie hat keinen Effekt"
 
-msgid "nothing to merge (use 'hg update' or check 'hg heads')"
-msgstr ""
-"Nichts zum Zusammenführen gefunden (nutze 'hg update' oder überprüfe 'hg "
-"heads')"
-
-msgid "outstanding uncommitted changes (use 'hg status' to list changes)"
-msgstr ""
-"Ausstehende nicht versionierte Änderungen (nutze 'hg status' zur Auflistung "
-"der Änderungen)"
+msgid "use 'hg update' or check 'hg heads'"
+msgstr "nutze 'hg update' oder überprüfe 'hg heads'"
+
+msgid "use 'hg status' to list changes"
+msgstr "nutze 'hg status' zur Auflistung der Änderungen"
 
 #, python-format
 msgid "outstanding uncommitted changes in subrepository '%s'"
@@ -18571,6 +18828,14 @@
 msgstr ""
 
 #, python-format
+msgid "ignoring inconsistense public root from remote: %s"
+msgstr ""
+
+#, python-format
+msgid "ignoring unexpected root from remote: %i %s"
+msgstr ""
+
+#, python-format
 msgid "exited with status %d"
 msgstr "Beendet mit Status %d"
 
@@ -18796,6 +19061,14 @@
 "    Nachkommen der Änderungssätze in der Liste sind."
 
 msgid ""
+"``draft()``\n"
+"    Changeset in draft phase."
+msgstr ""
+
+msgid "draft takes no arguments"
+msgstr "draft erwartet keine Argumente"
+
+msgid ""
 "``filelog(pattern)``\n"
 "    Changesets connected to the specified filelog."
 msgstr ""
@@ -19047,6 +19320,33 @@
 "    ein Eintrag nicht gefunden wird, die leere Menge."
 
 msgid ""
+"``public()``\n"
+"    Changeset in public phase."
+msgstr ""
+
+msgid "public takes no arguments"
+msgstr "public erwartet keine Argumente"
+
+msgid ""
+"``remote([id], [path])``\n"
+"    Local revision that corresponds to the given identifier in a\n"
+"    remote repository, if present. Here, the '.' identifier is a\n"
+"    synonym for the current local branch."
+msgstr ""
+
+#. i18n: "remote" is a keyword
+msgid "outgoing takes one or two arguments"
+msgstr "'outgoing' erwartet ein oder zwei Argumente"
+
+#. i18n: "remote" is a keyword
+msgid "remote requires a string id"
+msgstr "remote erwartet eine Zeichenkette (ID)"
+
+#. i18n: "remote" is a keyword
+msgid "remote requires a repository path"
+msgstr "'remote' erwartet einen Projektarchivpfad"
+
+msgid ""
 "``removes(pattern)``\n"
 "    Changesets which remove files matching pattern."
 msgstr ""
@@ -19089,6 +19389,14 @@
 "    Änderungssätze, die keine Eltern in der Menge haben."
 
 msgid ""
+"``secret()``\n"
+"    Changeset in secret phase."
+msgstr ""
+
+msgid "secret takes no arguments"
+msgstr "secret erwartet keine Argumente"
+
+msgid ""
 "``sort(set[, [-]key...])``\n"
 "    Sort set by keys. The default sort order is ascending, specify a key\n"
 "    as ``-key`` to sort in descending order."
@@ -19109,7 +19417,7 @@
 msgstr ""
 "    - ``rev`` für die Revisionsnummer,\n"
 "    - ``branch`` für den Zweignamen,\n"
-"    - ``desc`` für die Commit-Nachricht (description),\n"
+"    - ``desc`` für die Versionsmeldung (description),\n"
 "    - ``user`` für den Benutzernamen (Alias ``author``),\n"
 "    - ``date`` für das Datum des Commits"
 
@@ -19163,7 +19471,7 @@
 
 #, python-format
 msgid "possible case-folding collision for %s"
-msgstr ""
+msgstr "Groß-/Kleinschreibungskonflikt bei %s"
 
 #, python-format
 msgid "path ends in directory separator: %s"
@@ -19197,7 +19505,7 @@
 "kopiert).\n"
 
 msgid ".hg/requires file is corrupt"
-msgstr ".hg/requires file ist korrumpiert"
+msgstr ".hg/requires file ist beschädigt"
 
 #, python-format
 msgid "unknown repository format: requires features '%s' (upgrade Mercurial)"
@@ -19216,7 +19524,7 @@
 msgstr ""
 
 msgid "searching"
-msgstr "suchen"
+msgstr ""
 
 msgid "repository is unrelated"
 msgstr "Projektarchiv steht in keinem Zusammenhang"
@@ -19253,13 +19561,13 @@
 msgid "no suitable response from remote hg"
 msgstr "Keine passende Antwort des entfernten hg"
 
-msgid "remote: "
-msgstr "Entfernt: "
-
 #, python-format
 msgid "push refused: %s"
 msgstr "Hochladen abgewiesen: %s"
 
+msgid "ssl connection failed"
+msgstr "ssk-Verbindung fehlgeschlagen"
+
 msgid "Python SSL support not found"
 msgstr "SSL-Unterstützung für Python nicht gefunden"
 
@@ -19276,33 +19584,17 @@
 msgid "IDN in certificate not supported"
 msgstr ""
 
-#, fuzzy
 msgid "no commonName or subjectAltName found in certificate"
-msgstr "Kein commonName oder subjectAltNamt gefunden im Zertifikat"
+msgstr "Kein commonName oder subjectAltName im Zertifikat gefunden"
 
 #, python-format
 msgid "could not find web.cacerts: %s"
 msgstr "Konnte web.cacerts nicht finden: %s"
 
 #, python-format
-msgid "%s certificate error: %s (use --insecure to connect insecurely)"
-msgstr ""
-"%s Zertifikatsfehler: %s (Benutzen Sie --insecure, um unsicher zu verbinden)"
-
-#, python-format
-msgid "invalid certificate for %s with fingerprint %s"
-msgstr ""
-
-#, python-format
-msgid ""
-"warning: %s certificate with fingerprint %s not verified (check "
-"hostfingerprints or web.cacerts config setting)\n"
-msgstr ""
-
-#, python-format
 msgid "host fingerprint for %s can't be verified (Python too old)"
 msgstr ""
-"Host fingerprint für %s kann nicht verifiziert werden (Python ist zu alt)"
+"Server Authentizität für %s kann nicht verifiziert werden (Python ist zu alt)"
 
 #, python-format
 msgid "warning: certificate for %s can't be verified (Python too old)\n"
@@ -19311,6 +19603,34 @@
 "alt)\n"
 
 #, python-format
+msgid "%s ssl connection error"
+msgstr ""
+
+#, python-format
+msgid "%s certificate error: no certificate received"
+msgstr "%s Zertifikatfehler: Kein Zertifikat empfangen"
+
+#, python-format
+msgid "invalid certificate for %s with fingerprint %s"
+msgstr ""
+
+#, python-format
+msgid "%s certificate error: %s"
+msgstr "%s Zertifikatfehler: %s"
+
+#, , python-format
+msgid "configure hostfingerprint %s or use --insecure to connect insecurely"
+msgstr ""
+"Erlauben Sie Serverkennung %s in der Konfiguration oder benutzen Sie "
+"--insecure, um unsicher zu verbinden"
+
+#, python-format
+msgid ""
+"warning: %s certificate with fingerprint %s not verified (check "
+"hostfingerprints or web.cacerts config setting)\n"
+msgstr ""
+
+#, python-format
 msgid "'%s' does not appear to be an hg repository"
 msgstr "'%s' scheint kein hg-Projektarchiv zu sein"
 
@@ -19451,13 +19771,13 @@
 msgid "pushing branch %s of subrepo %s\n"
 msgstr "Ãœbertrage Zweig %s von Unterarchiv %s\n"
 
-#, fuzzy, python-format
+#, python-format
 msgid ""
 "no branch checked out in subrepo %s\n"
 "cannot push revision %s"
 msgstr ""
-"kein Branch in Subrepo %s ausgecheckt\n"
-"Revision %s kann nicht gepusht werden"
+"kein Zweig in Unterarchiv %s aktuell\n"
+"Revision %s kann nicht übertragen werden"
 
 #, python-format
 msgid "%s, line %s: %s\n"
@@ -19540,13 +19860,12 @@
 msgid ":firstline: Any text. Returns the first line of text."
 msgstr ":firstline: Beliebiger Text. Gibt die erste Zeile des Texts zurück."
 
-#, fuzzy
 msgid ""
 ":hex: Any text. Convert a binary Mercurial node identifier into\n"
 "    its long hexadecimal representation."
 msgstr ""
-":hex: Beliebiger Text. Konvertiert einen binären Mercurial node identifier \n"
-"    in seine lange hexadezimale Repräsentation."
+":hex: Beliebiger Text. Konvertiert eine binären Mercurial Knoten-ID \n"
+"    in eine lange hexadezimale Repräsentation."
 
 msgid ""
 ":hgdate: Date. Returns the date as a pair of numbers: \"1157407993\n"
@@ -19613,7 +19932,6 @@
 ":short: Prüfsumme. Gibt die Kurzform der Prüfsumme zurück, d.h.\n"
 "    als 12 Zeichen lange hexadezimale Zeichenkette."
 
-#, fuzzy
 msgid ""
 ":shortbisect: Any text. Treats `text` as a bisection status, and\n"
 "    returns a single-character representing the status (G: good, B: bad,\n"
@@ -19621,11 +19939,9 @@
 "    is not a valid bisection status."
 msgstr ""
 ":shortbisect: Beliebiger text. Behandelt `text` als Teilungsstatus, und\n"
-"    gibt ein einzelnes Zeichen zurück, dass den Status repräsentiert (G: "
-"gut, B: schlecht,\n"
-"    S: übersprungen, U: ungetestet, I: ignoriert). Gibt ein einzelnes "
-"Leerzeichen zurück,\n"
-"    wenn `text` kein gültiger Teilungsstatus ist."
+"    gibt einen repräsentatives Buchstaben zurück (G: gut, B: schlecht,\n"
+"    S: übersprungen, U: ungetestet, I: ignoriert). Wenn `text` kein\n"
+"    gültiger Teilungsstatus ist, wird ein Leerzeichen zurückgegeben."
 
 msgid ":shortdate: Date. Returns a date like \"2006-09-18\"."
 msgstr ":shortdate: Datumsangabe. Gibt ein Datum wie \"2006-09-18\" zurück."
@@ -19762,9 +20078,11 @@
 ":node: Zeichenkette. Die Prüfsumme, die einen Änderungssatz identifiziert,\n"
 "    als 40 Zeichen lange hexadezimale Zeichenkette."
 
-#, fuzzy
-msgid ":rev: Integer. The changeset phase."
-msgstr ":rev: Ganze Zahl. Die Phase des Changesets."
+msgid ":rev: String. The changeset phase name."
+msgstr ""
+
+msgid ":rev: Integer. The changeset phase index."
+msgstr ""
 
 msgid ":rev: Integer. The repository-local changeset revision number."
 msgstr ""
--- a/mercurial/commands.py	Tue Feb 28 23:47:46 2012 +0200
+++ b/mercurial/commands.py	Tue Feb 28 21:17:53 2012 -0600
@@ -2154,7 +2154,11 @@
 
 @command('debugrevspec', [], ('REVSPEC'))
 def debugrevspec(ui, repo, expr):
-    '''parse and apply a revision specification'''
+    """parse and apply a revision specification
+
+    Use --verbose to print the parsed tree before and after aliases
+    expansion.
+    """
     if ui.verbose:
         tree = revset.parse(expr)[0]
         ui.note(tree, "\n")
@@ -4211,7 +4215,8 @@
 
         public < draft < secret
 
-    Return 0 on success, 1 if no phases were changed.
+    Return 0 on success, 1 if no phases were changed or some could not
+    be changed.
     """
     # search for a unique phase argument
     targetphase = None
@@ -4253,8 +4258,18 @@
             changes = 0
             newdata = repo._phaserev
             changes = sum(o != newdata[i] for i, o in enumerate(olddata))
+            rejected = [n for n in nodes
+                        if newdata[repo[n].rev()] < targetphase]
+            if rejected:
+                ui.warn(_('cannot move %i changesets to a more permissive '
+                          'phase, use --force\n') % len(rejected))
+                ret = 1
             if changes:
-                ui.note(_('phase change for %i changesets\n') % changes)
+                msg = _('phase changed for %i changesets\n') % changes
+                if ret:
+                    ui.status(msg)
+                else:
+                    ui.note(msg)
             else:
                 ui.warn(_('no phases changed\n'))
                 ret = 1
@@ -5263,18 +5278,22 @@
     if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
         copy = copies.pathcopies(repo[node1], repo[node2])
 
+    fm = ui.formatter('status', opts)
+    format = '%s %s' + end
+    if opts.get('no_status'):
+        format = '%.0s%s' + end
+
     for state, char, files in changestates:
         if state in show:
-            format = "%s %%s%s" % (char, end)
-            if opts.get('no_status'):
-                format = "%%s%s" % end
-
+            label = 'status.' + state
             for f in files:
-                ui.write(format % repo.pathto(f, cwd),
-                         label='status.' + state)
+                fm.startitem()
+                fm.write("status path", format, char,
+                         repo.pathto(f, cwd), label=label)
                 if f in copy:
-                    ui.write('  %s%s' % (repo.pathto(copy[f], cwd), end),
+                    fm.write("copy", '  %s' + end, repo.pathto(copy[f], cwd),
                              label='status.copied')
+    fm.end()
 
 @command('^summary|sum',
     [('', 'remote', None, _('check for push and pull'))], '[--remote]')
@@ -5711,18 +5730,21 @@
     if check and clean:
         raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
 
+    if date:
+        if rev is not None:
+            raise util.Abort(_("you can't specify a revision and a date"))
+        rev = cmdutil.finddate(ui, repo, date)
+
     if check:
         # we could use dirty() but we can ignore merge and branch trivia
         c = repo[None]
         if c.modified() or c.added() or c.removed():
             raise util.Abort(_("uncommitted local changes"))
-
-    if date:
-        if rev is not None:
-            raise util.Abort(_("you can't specify a revision and a date"))
-        rev = cmdutil.finddate(ui, repo, date)
-
-    if clean or check:
+        if not rev:
+            rev = repo[repo[None].branch()].rev()
+        mergemod._checkunknown(repo, repo[None], repo[rev])
+
+    if clean:
         ret = hg.clean(repo, rev)
     else:
         ret = hg.update(repo, rev)
--- a/mercurial/context.py	Tue Feb 28 23:47:46 2012 +0200
+++ b/mercurial/context.py	Tue Feb 28 21:17:53 2012 -0600
@@ -611,11 +611,12 @@
 
         return None
 
-    def ancestors(self):
+    def ancestors(self, followfirst=False):
         visit = {}
         c = self
+        cut = followfirst and 1 or None
         while True:
-            for parent in c.parents():
+            for parent in c.parents()[:cut]:
                 visit[(parent.rev(), parent.node())] = parent
             if not visit:
                 break
@@ -715,9 +716,6 @@
     def _manifest(self):
         """generate a manifest corresponding to the working directory"""
 
-        if self._unknown is None:
-            self.status(unknown=True)
-
         man = self._parents[0].manifest().copy()
         if len(self._parents) > 1:
             man2 = self.p2().manifest()
@@ -731,8 +729,7 @@
         copied = self._repo.dirstate.copies()
         ff = self._flagfunc
         modified, added, removed, deleted = self._status
-        unknown = self._unknown
-        for i, l in (("a", added), ("m", modified), ("u", unknown)):
+        for i, l in (("a", added), ("m", modified)):
             for f in l:
                 orig = copied.get(f, f)
                 man[f] = getman(orig).get(orig, nullid) + i
@@ -934,9 +931,10 @@
         finally:
             wlock.release()
 
-    def ancestors(self):
+    def ancestors(self, followfirst=False):
+        cut = followfirst and 1 or None
         for a in self._repo.changelog.ancestors(
-            *[p.rev() for p in self._parents]):
+            *[p.rev() for p in self._parents[:cut]]):
             yield changectx(self._repo, a)
 
     def undelete(self, list):
--- a/mercurial/copies.py	Tue Feb 28 23:47:46 2012 +0200
+++ b/mercurial/copies.py	Tue Feb 28 21:17:53 2012 -0600
@@ -18,15 +18,6 @@
         return ""
     return f[:s]
 
-def _dirs(files):
-    d = set()
-    for f in files:
-        f = _dirname(f)
-        while f not in d:
-            d.add(f)
-            f = _dirname(f)
-    return d
-
 def _findlimit(repo, a, b):
     """Find the earliest revision that's an ancestor of a or b but not both,
     None if no such revision exists.
@@ -174,9 +165,18 @@
         return _backwardcopies(x, y)
     return _chain(x, y, _backwardcopies(x, a), _forwardcopies(a, y))
 
-def mergecopies(repo, c1, c2, ca, checkdirs=True):
+def mergecopies(repo, c1, c2, ca):
     """
-    Find moves and copies between context c1 and c2
+    Find moves and copies between context c1 and c2 that are relevant
+    for merging.
+
+    Returns two dicts, "copy" and "diverge".
+
+    "copy" is a mapping from destination name -> source name,
+    where source is in c1 and destination is in c2 or vice-versa.
+
+    "diverge" is a mapping of source name -> list of destination names
+    for divergent renames.
     """
     # avoid silly behavior for update from empty dir
     if not c1 or not c2 or c1 == c2:
@@ -301,14 +301,14 @@
             repo.ui.debug("   %s -> %s %s\n" % (f, fullcopy[f], note))
     del diverge2
 
-    if not fullcopy or not checkdirs:
+    if not fullcopy:
         return copy, diverge
 
     repo.ui.debug("  checking for directory renames\n")
 
     # generate a directory move map
-    d1, d2 = _dirs(m1), _dirs(m2)
-    invalid = set()
+    d1, d2 = c1.dirs(), c2.dirs()
+    invalid = set([""])
     dirmove = {}
 
     # examine each file copy for a potential directory move, which is
--- a/mercurial/encoding.py	Tue Feb 28 23:47:46 2012 +0200
+++ b/mercurial/encoding.py	Tue Feb 28 21:17:53 2012 -0600
@@ -190,3 +190,80 @@
         return s.upper() # we don't know how to fold this except in ASCII
     except LookupError, k:
         raise error.Abort(k, hint="please check your locale settings")
+
+def toutf8b(s):
+    '''convert a local, possibly-binary string into UTF-8b
+
+    This is intended as a generic method to preserve data when working
+    with schemes like JSON and XML that have no provision for
+    arbitrary byte strings. As Mercurial often doesn't know
+    what encoding data is in, we use so-called UTF-8b.
+
+    If a string is already valid UTF-8 (or ASCII), it passes unmodified.
+    Otherwise, unsupported bytes are mapped to UTF-16 surrogate range,
+    uDC00-uDCFF.
+
+    Principles of operation:
+
+    - ASCII and UTF-8 data sucessfully round-trips and is understood
+      by Unicode-oriented clients
+    - filenames and file contents in arbitrary other encodings can have
+      be round-tripped or recovered by clueful clients
+    - local strings that have a cached known UTF-8 encoding (aka
+      localstr) get sent as UTF-8 so Unicode-oriented clients get the
+      Unicode data they want
+    - because we must preserve UTF-8 bytestring in places such as
+      filenames, metadata can't be roundtripped without help
+
+    (Note: "UTF-8b" often refers to decoding a mix of valid UTF-8 and
+    arbitrary bytes into an internal Unicode format that can be
+    re-encoded back into the original. Here we are exposing the
+    internal surrogate encoding as a UTF-8 string.)
+    '''
+
+    if isinstance(s, localstr):
+        return s._utf8
+
+    try:
+        if s.decode('utf-8'):
+            return s
+    except UnicodeDecodeError:
+        # surrogate-encode any characters that don't round-trip
+        s2 = s.decode('utf-8', 'ignore').encode('utf-8')
+        r = ""
+        pos = 0
+        for c in s:
+            if s2[pos:pos + 1] == c:
+                r += c
+                pos += 1
+            else:
+                r += unichr(0xdc00 + ord(c)).encode('utf-8')
+        return r
+
+def fromutf8b(s):
+    '''Given a UTF-8b string, return a local, possibly-binary string.
+
+    return the original binary string. This
+    is a round-trip process for strings like filenames, but metadata
+    that's was passed through tolocal will remain in UTF-8.
+
+    >>> m = "\\xc3\\xa9\\x99abcd"
+    >>> n = toutf8b(m)
+    >>> n
+    '\\xc3\\xa9\\xed\\xb2\\x99abcd'
+    >>> fromutf8b(n) == m
+    True
+    '''
+
+    # fast path - look for uDxxx prefixes in s
+    if "\xed" not in s:
+        return s
+
+    u = s.decode("utf-8")
+    r = ""
+    for c in u:
+        if ord(c) & 0xff00 == 0xdc00:
+            r += chr(ord(c) & 0xff)
+        else:
+            r += c.encode("utf-8")
+    return r
--- a/mercurial/filemerge.py	Tue Feb 28 23:47:46 2012 +0200
+++ b/mercurial/filemerge.py	Tue Feb 28 21:17:53 2012 -0600
@@ -19,11 +19,21 @@
 def _toollist(ui, tool, part, default=[]):
     return ui.configlist("merge-tools", tool + "." + part, default)
 
-_internal = ['internal:' + s
-             for s in 'fail local other merge prompt dump'.split()]
+internals = {}
+
+def internaltool(name, trymerge, onfailure=None):
+    '''return a decorator for populating internal merge tool table'''
+    def decorator(func):
+        fullname = 'internal:' + name
+        func.__doc__ = "``%s``\n" % fullname + func.__doc__.strip()
+        internals[fullname] = func
+        func.trymerge = trymerge
+        func.onfailure = onfailure
+        return func
+    return decorator
 
 def _findtool(ui, tool):
-    if tool in _internal:
+    if tool in internals:
         return tool
     for kn in ("regkey", "regkeyalt"):
         k = _toolstr(ui, tool, kn)
@@ -123,6 +133,131 @@
             if newdata != data:
                 util.writefile(file, newdata)
 
+@internaltool('prompt', False)
+def _iprompt(repo, mynode, orig, fcd, fco, fca, toolconf):
+    """Asks the user which of the local or the other version to keep as
+    the merged version."""
+    ui = repo.ui
+    fd = fcd.path()
+
+    if ui.promptchoice(_(" no tool found to merge %s\n"
+                         "keep (l)ocal or take (o)ther?") % fd,
+                       (_("&Local"), _("&Other")), 0):
+        return _iother(repo, mynode, orig, fcd, fco, fca, toolconf)
+    else:
+        return _ilocal(repo, mynode, orig, fcd, fco, fca, toolconf)
+
+@internaltool('local', False)
+def _ilocal(repo, mynode, orig, fcd, fco, fca, toolconf):
+    """Uses the local version of files as the merged version."""
+    return 0
+
+@internaltool('other', False)
+def _iother(repo, mynode, orig, fcd, fco, fca, toolconf):
+    """Uses the other version of files as the merged version."""
+    repo.wwrite(fcd.path(), fco.data(), fco.flags())
+    return 0
+
+@internaltool('fail', False)
+def _ifail(repo, mynode, orig, fcd, fco, fca, toolconf):
+    """
+    Rather than attempting to merge files that were modified on both
+    branches, it marks them as unresolved. The resolve command must be
+    used to resolve these conflicts."""
+    return 1
+
+def _premerge(repo, toolconf, files):
+    tool, toolpath, binary, symlink = toolconf
+    a, b, c, back = files
+
+    ui = repo.ui
+
+    # do we attempt to simplemerge first?
+    try:
+        premerge = _toolbool(ui, tool, "premerge", not (binary or symlink))
+    except error.ConfigError:
+        premerge = _toolstr(ui, tool, "premerge").lower()
+        valid = 'keep'.split()
+        if premerge not in valid:
+            _valid = ', '.join(["'" + v + "'" for v in valid])
+            raise error.ConfigError(_("%s.premerge not valid "
+                                      "('%s' is neither boolean nor %s)") %
+                                    (tool, premerge, _valid))
+
+    if premerge:
+        r = simplemerge.simplemerge(ui, a, b, c, quiet=True)
+        if not r:
+            ui.debug(" premerge successful\n")
+            return 0
+        if premerge != 'keep':
+            util.copyfile(back, a) # restore from backup and try again
+    return 1 # continue merging
+
+@internaltool('merge', True,
+              _("merging %s incomplete! "
+                "(edit conflicts, then use 'hg resolve --mark')\n"))
+def _imerge(repo, mynode, orig, fcd, fco, fca, toolconf, files):
+    """
+    Uses the internal non-interactive simple merge algorithm for merging
+    files. It will fail if there are any conflicts and leave markers in
+    the partially merged file."""
+    r = _premerge(repo, toolconf, files)
+    if r:
+        a, b, c, back = files
+
+        ui = repo.ui
+
+        r = simplemerge.simplemerge(ui, a, b, c, label=['local', 'other'])
+        return True, r
+    return False, 0
+
+@internaltool('dump', True)
+def _idump(repo, mynode, orig, fcd, fco, fca, toolconf, files):
+    """
+    Creates three versions of the files to merge, containing the
+    contents of local, other and base. These files can then be used to
+    perform a merge manually. If the file to be merged is named
+    ``a.txt``, these files will accordingly be named ``a.txt.local``,
+    ``a.txt.other`` and ``a.txt.base`` and they will be placed in the
+    same directory as ``a.txt``."""
+    r = _premerge(repo, toolconf, files)
+    if r:
+        a, b, c, back = files
+
+        fd = fcd.path()
+
+        util.copyfile(a, a + ".local")
+        repo.wwrite(fd + ".other", fco.data(), fco.flags())
+        repo.wwrite(fd + ".base", fca.data(), fca.flags())
+    return False, r
+
+def _xmerge(repo, mynode, orig, fcd, fco, fca, toolconf, files):
+    r = _premerge(repo, toolconf, files)
+    if r:
+        tool, toolpath, binary, symlink = toolconf
+        a, b, c, back = files
+        out = ""
+        env = dict(HG_FILE=fcd.path(),
+                   HG_MY_NODE=short(mynode),
+                   HG_OTHER_NODE=str(fco.changectx()),
+                   HG_BASE_NODE=str(fca.changectx()),
+                   HG_MY_ISLINK='l' in fcd.flags(),
+                   HG_OTHER_ISLINK='l' in fco.flags(),
+                   HG_BASE_ISLINK='l' in fca.flags())
+
+        ui = repo.ui
+
+        args = _toolstr(ui, tool, "args", '$local $base $other')
+        if "$output" in args:
+            out, a = a, back # read input from backup, write to original
+        replace = dict(local=a, base=b, other=c, output=out)
+        args = util.interpolate(r'\$', replace, args,
+                                lambda s: '"%s"' % util.localpath(s))
+        r = util.system(toolpath + ' ' + args, cwd=repo.root, environ=env,
+                        out=ui.fout)
+        return True, r
+    return False, 0
+
 def filemerge(repo, mynode, orig, fcd, fco, fca):
     """perform a 3-way merge in the working directory
 
@@ -153,25 +288,23 @@
     ui.debug("picked tool '%s' for %s (binary %s symlink %s)\n" %
                (tool, fd, binary, symlink))
 
-    if not tool or tool == 'internal:prompt':
-        tool = "internal:local"
-        if ui.promptchoice(_(" no tool found to merge %s\n"
-                             "keep (l)ocal or take (o)ther?") % fd,
-                           (_("&Local"), _("&Other")), 0):
-            tool = "internal:other"
-    if tool == "internal:local":
-        return 0
-    if tool == "internal:other":
-        repo.wwrite(fd, fco.data(), fco.flags())
-        return 0
-    if tool == "internal:fail":
-        return 1
+    if tool in internals:
+        func = internals[tool]
+        trymerge = func.trymerge
+        onfailure = func.onfailure
+    else:
+        func = _xmerge
+        trymerge = True
+        onfailure = _("merging %s failed!\n")
 
-    # do the actual merge
+    toolconf = tool, toolpath, binary, symlink
+
+    if not trymerge:
+        return func(repo, mynode, orig, fcd, fco, fca, toolconf)
+
     a = repo.wjoin(fd)
     b = temp("base", fca)
     c = temp("other", fco)
-    out = ""
     back = a + ".orig"
     util.copyfile(a, back)
 
@@ -182,54 +315,18 @@
 
     ui.debug("my %s other %s ancestor %s\n" % (fcd, fco, fca))
 
-    # do we attempt to simplemerge first?
-    try:
-        premerge = _toolbool(ui, tool, "premerge", not (binary or symlink))
-    except error.ConfigError:
-        premerge = _toolstr(ui, tool, "premerge").lower()
-        valid = 'keep'.split()
-        if premerge not in valid:
-            _valid = ', '.join(["'" + v + "'" for v in valid])
-            raise error.ConfigError(_("%s.premerge not valid "
-                                      "('%s' is neither boolean nor %s)") %
-                                    (tool, premerge, _valid))
-
-    if premerge:
-        r = simplemerge.simplemerge(ui, a, b, c, quiet=True)
-        if not r:
-            ui.debug(" premerge successful\n")
+    needcheck, r = func(repo, mynode, orig, fcd, fco, fca, toolconf,
+                        (a, b, c, back))
+    if not needcheck:
+        if r:
+            if onfailure:
+                ui.warn(onfailure % fd)
+        else:
             os.unlink(back)
-            os.unlink(b)
-            os.unlink(c)
-            return 0
-        if premerge != 'keep':
-            util.copyfile(back, a) # restore from backup and try again
 
-    env = dict(HG_FILE=fd,
-               HG_MY_NODE=short(mynode),
-               HG_OTHER_NODE=str(fco.changectx()),
-               HG_BASE_NODE=str(fca.changectx()),
-               HG_MY_ISLINK='l' in fcd.flags(),
-               HG_OTHER_ISLINK='l' in fco.flags(),
-               HG_BASE_ISLINK='l' in fca.flags())
-
-    if tool == "internal:merge":
-        r = simplemerge.simplemerge(ui, a, b, c, label=['local', 'other'])
-    elif tool == 'internal:dump':
-        a = repo.wjoin(fd)
-        util.copyfile(a, a + ".local")
-        repo.wwrite(fd + ".other", fco.data(), fco.flags())
-        repo.wwrite(fd + ".base", fca.data(), fca.flags())
-        return 1 # unresolved
-    else:
-        args = _toolstr(ui, tool, "args", '$local $base $other')
-        if "$output" in args:
-            out, a = a, back # read input from backup, write to original
-        replace = dict(local=a, base=b, other=c, output=out)
-        args = util.interpolate(r'\$', replace, args,
-                                lambda s: '"%s"' % util.localpath(s))
-        r = util.system(toolpath + ' ' + args, cwd=repo.root, environ=env,
-                        out=ui.fout)
+        os.unlink(b)
+        os.unlink(c)
+        return r
 
     if not r and (_toolbool(ui, tool, "checkconflicts") or
                   'conflicts' in _toollist(ui, tool, "check")):
@@ -246,24 +343,24 @@
 
     if not r and not checked and (_toolbool(ui, tool, "checkchanged") or
                                   'changed' in _toollist(ui, tool, "check")):
-        if filecmp.cmp(repo.wjoin(fd), back):
+        if filecmp.cmp(a, back):
             if ui.promptchoice(_(" output file %s appears unchanged\n"
                                  "was merge successful (yn)?") % fd,
                                (_("&Yes"), _("&No")), 1):
                 r = 1
 
     if _toolbool(ui, tool, "fixeol"):
-        _matcheol(repo.wjoin(fd), back)
+        _matcheol(a, back)
 
     if r:
-        if tool == "internal:merge":
-            ui.warn(_("merging %s incomplete! "
-                      "(edit conflicts, then use 'hg resolve --mark')\n") % fd)
-        else:
-            ui.warn(_("merging %s failed!\n") % fd)
+        if onfailure:
+            ui.warn(onfailure % fd)
     else:
         os.unlink(back)
 
     os.unlink(b)
     os.unlink(c)
     return r
+
+# tell hggettext to extract docstrings from these functions:
+i18nfunctions = internals.values()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial/formatter.py	Tue Feb 28 21:17:53 2012 -0600
@@ -0,0 +1,71 @@
+# formatter.py - generic output formatting for mercurial
+#
+# Copyright 2012 Matt Mackall <mpm@selenic.com>
+#
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2 or any later version.
+
+class baseformatter(object):
+    def __init__(self, ui, topic, opts):
+        self._ui = ui
+        self._topic = topic
+        self._style = opts.get("style")
+        self._template = opts.get("template")
+        self._item = None
+    def __bool__(self):
+        '''return False if we're not doing real templating so we can
+        skip extra work'''
+        return True
+    def _showitem(self):
+        '''show a formatted item once all data is collected'''
+        pass
+    def startitem(self):
+        '''begin an item in the format list'''
+        if self._item is not None:
+            self._showitem()
+        self._item = {}
+    def data(self, **data):
+        '''insert data into item that's not shown in default output'''
+    def write(self, fields, deftext, *fielddata, **opts):
+        '''do default text output while assigning data to item'''
+        for k, v in zip(fields.split(), fielddata):
+            self._item[k] = v
+    def plain(self, text, **opts):
+        '''show raw text for non-templated mode'''
+        pass
+    def end(self):
+        '''end output for the formatter'''
+        if self._item is not None:
+            self._showitem()
+
+class plainformatter(baseformatter):
+    '''the default text output scheme'''
+    def __init__(self, ui, topic, opts):
+        baseformatter.__init__(self, ui, topic, opts)
+    def __bool__(self):
+        return False
+    def startitem(self):
+        pass
+    def data(self, **data):
+        pass
+    def write(self, fields, deftext, *fielddata, **opts):
+        self._ui.write(deftext % fielddata, **opts)
+    def plain(self, text, **opts):
+        self._ui.write(text, **opts)
+    def end(self):
+        pass
+
+class debugformatter(baseformatter):
+    def __init__(self, ui, topic, opts):
+        baseformatter.__init__(self, ui, topic, opts)
+        self._ui.write("%s = {\n" % self._topic)
+    def _showitem(self):
+        self._ui.write("    " + repr(self._item) + ",\n")
+    def end(self):
+        baseformatter.end(self)
+        self._ui.write("}\n")
+
+def formatter(ui, topic, opts):
+    if ui.configbool('ui', 'formatdebug'):
+        return debugformatter(ui, topic, opts)
+    return plainformatter(ui, topic, opts)
--- a/mercurial/graphmod.py	Tue Feb 28 23:47:46 2012 +0200
+++ b/mercurial/graphmod.py	Tue Feb 28 21:17:53 2012 -0600
@@ -18,6 +18,7 @@
 """
 
 from mercurial.node import nullrev
+import util
 
 CHANGESET = 'C'
 
@@ -67,7 +68,7 @@
         parents = set([p.rev() for p in ctx.parents() if p.node() in include])
         yield (ctx.rev(), CHANGESET, ctx, sorted(parents))
 
-def colored(dag):
+def colored(dag, repo):
     """annotates a DAG with colored edge information
 
     For each DAG node this function emits tuples::
@@ -83,6 +84,23 @@
     seen = []
     colors = {}
     newcolor = 1
+    config = {}
+
+    for key, val in repo.ui.configitems('graph'):
+        if '.' in key:
+            branch, setting = key.rsplit('.', 1)
+            # Validation
+            if setting == "width" and val.isdigit():
+                config.setdefault(branch, {})[setting] = int(val)
+            elif setting == "color" and val.isalnum():
+                config.setdefault(branch, {})[setting] = val
+
+    if config:
+        getconf = util.lrucachefunc(
+            lambda rev: config.get(repo[rev].branch(), {}))
+    else:
+        getconf = lambda rev: {}
+
     for (cur, type, data, parents) in dag:
 
         # Compute seen and next
@@ -111,10 +129,18 @@
         edges = []
         for ecol, eid in enumerate(seen):
             if eid in next:
-                edges.append((ecol, next.index(eid), colors[eid]))
+                bconf = getconf(eid)
+                edges.append((
+                    ecol, next.index(eid), colors[eid],
+                    bconf.get('width', -1),
+                    bconf.get('color', '')))
             elif eid == cur:
                 for p in parents:
-                    edges.append((ecol, next.index(p), color))
+                    bconf = getconf(p)
+                    edges.append((
+                        ecol, next.index(p), color,
+                        bconf.get('width', -1),
+                        bconf.get('color', '')))
 
         # Yield and move on
         yield (cur, type, data, (col, color), edges)
--- a/mercurial/help.py	Tue Feb 28 23:47:46 2012 +0200
+++ b/mercurial/help.py	Tue Feb 28 21:17:53 2012 -0600
@@ -7,7 +7,7 @@
 
 from i18n import gettext, _
 import sys, os
-import extensions, revset, fileset, templatekw, templatefilters
+import extensions, revset, fileset, templatekw, templatefilters, filemerge
 import util
 
 def listexts(header, exts, indent=1):
@@ -105,6 +105,7 @@
     addtopichook(topic, add)
 
 addtopicsymbols('filesets', '.. predicatesmarker', fileset.symbols)
+addtopicsymbols('merge-tools', '.. internaltoolsmarker', filemerge.internals)
 addtopicsymbols('revsets', '.. predicatesmarker', revset.symbols)
 addtopicsymbols('templates', '.. keywordsmarker', templatekw.keywords)
 addtopicsymbols('templates', '.. filtersmarker', templatefilters.filters)
--- a/mercurial/help/config.txt	Tue Feb 28 23:47:46 2012 +0200
+++ b/mercurial/help/config.txt	Tue Feb 28 21:17:53 2012 -0600
@@ -489,24 +489,6 @@
   myfeature = ~/.hgext/myfeature.py
 
 
-``hostfingerprints``
-""""""""""""""""""""
-
-Fingerprints of the certificates of known HTTPS servers.
-A HTTPS connection to a server with a fingerprint configured here will
-only succeed if the servers certificate matches the fingerprint.
-This is very similar to how ssh known hosts works.
-The fingerprint is the SHA-1 hash value of the DER encoded certificate.
-The CA chain and web.cacerts is not used for servers with a fingerprint.
-
-For example::
-
-    [hostfingerprints]
-    hg.intevation.org = 38:76:52:7c:87:26:9a:8f:4a:f8:d3:de:08:45:3b:ea:d6:4b:ee:cc
-
-This feature is only supported when using Python 2.6 or later.
-
-
 ``format``
 """"""""""
 
@@ -534,119 +516,33 @@
     option ensures that the on-disk format of newly created
     repositories will be compatible with Mercurial before version 1.7.
 
-``merge-patterns``
-""""""""""""""""""
-
-This section specifies merge tools to associate with particular file
-patterns. Tools matched here will take precedence over the default
-merge tool. Patterns are globs by default, rooted at the repository
-root.
+``graph``
+"""""""""
 
-Example::
+Web graph view configuration. This section let you change graph
+elements display properties by branches, for instance to make the
+``default`` branch stand out.
 
-  [merge-patterns]
-  **.c = kdiff3
-  **.jpg = myimgmerge
-
-``merge-tools``
-"""""""""""""""
+Each line has the following format::
 
-This section configures external merge tools to use for file-level
-merges.
+    <branch>.<argument> = <value>
 
-Example ``~/.hgrc``::
+where ``<branch>`` is the name of the branch being
+customized. Example::
 
-  [merge-tools]
-  # Override stock tool location
-  kdiff3.executable = ~/bin/kdiff3
-  # Specify command line
-  kdiff3.args = $base $local $other -o $output
-  # Give higher priority
-  kdiff3.priority = 1
-
-  # Define new tool
-  myHtmlTool.args = -m $local $other $base $output
-  myHtmlTool.regkey = Software\FooSoftware\HtmlMerge
-  myHtmlTool.priority = 1
+    [graph]
+    # 2px width
+    default.width = 2
+    # red color
+    default.color = FF0000
 
 Supported arguments:
 
-``priority``
-  The priority in which to evaluate this tool.
-  Default: 0.
-
-``executable``
-  Either just the name of the executable or its pathname.  On Windows,
-  the path can use environment variables with ${ProgramFiles} syntax.
-  Default: the tool name.
-
-``args``
-  The arguments to pass to the tool executable. You can refer to the
-  files being merged as well as the output file through these
-  variables: ``$base``, ``$local``, ``$other``, ``$output``.
-  Default: ``$local $base $other``
-
-``premerge``
-  Attempt to run internal non-interactive 3-way merge tool before
-  launching external tool.  Options are ``true``, ``false``, or ``keep``
-  to leave markers in the file if the premerge fails.
-  Default: True
-
-``binary``
-  This tool can merge binary files. Defaults to False, unless tool
-  was selected by file pattern match.
-
-``symlink``
-  This tool can merge symlinks. Defaults to False, even if tool was
-  selected by file pattern match.
-
-``check``
-  A list of merge success-checking options:
+``width``
+    Set branch edges width in pixels.
 
-  ``changed``
-    Ask whether merge was successful when the merged file shows no changes.
-  ``conflicts``
-    Check whether there are conflicts even though the tool reported success.
-  ``prompt``
-    Always prompt for merge success, regardless of success reported by tool.
-
-``checkchanged``
-  True is equivalent to ``check = changed``.
-  Default: False
-
-``checkconflicts``
-  True is equivalent to ``check = conflicts``.
-  Default: False
-
-``fixeol``
-  Attempt to fix up EOL changes caused by the merge tool.
-  Default: False
-
-``gui``
-  This tool requires a graphical interface to run. Default: False
-
-``regkey``
-  Windows registry key which describes install location of this
-  tool. Mercurial will search for this key first under
-  ``HKEY_CURRENT_USER`` and then under ``HKEY_LOCAL_MACHINE``.
-  Default: None
-
-``regkeyalt``
-  An alternate Windows registry key to try if the first key is not
-  found.  The alternate key uses the same ``regname`` and ``regappend``
-  semantics of the primary key.  The most common use for this key
-  is to search for 32bit applications on 64bit operating systems.
-  Default: None
-
-``regname``
-  Name of value to read from specified registry key. Defaults to the
-  unnamed (default) value.
-
-``regappend``
-  String to append to the value read from the registry, typically
-  the executable name of the tool.
-  Default: None
-
+``color``
+    Set branch edges color in hexadecimal RGB notation.
 
 ``hooks``
 """""""""
@@ -827,6 +723,24 @@
 is treated as a failure.
 
 
+``hostfingerprints``
+""""""""""""""""""""
+
+Fingerprints of the certificates of known HTTPS servers.
+A HTTPS connection to a server with a fingerprint configured here will
+only succeed if the servers certificate matches the fingerprint.
+This is very similar to how ssh known hosts works.
+The fingerprint is the SHA-1 hash value of the DER encoded certificate.
+The CA chain and web.cacerts is not used for servers with a fingerprint.
+
+For example::
+
+    [hostfingerprints]
+    hg.intevation.org = 38:76:52:7c:87:26:9a:8f:4a:f8:d3:de:08:45:3b:ea:d6:4b:ee:cc
+
+This feature is only supported when using Python 2.6 or later.
+
+
 ``http_proxy``
 """"""""""""""
 
@@ -851,33 +765,118 @@
     Optional. Always use the proxy, even for localhost and any entries
     in ``http_proxy.no``. True or False. Default: False.
 
-``smtp``
-""""""""
+``merge-patterns``
+""""""""""""""""""
+
+This section specifies merge tools to associate with particular file
+patterns. Tools matched here will take precedence over the default
+merge tool. Patterns are globs by default, rooted at the repository
+root.
+
+Example::
 
-Configuration for extensions that need to send email messages.
+  [merge-patterns]
+  **.c = kdiff3
+  **.jpg = myimgmerge
+
+``merge-tools``
+"""""""""""""""
+
+This section configures external merge tools to use for file-level
+merges.
+
+Example ``~/.hgrc``::
 
-``host``
-    Host name of mail server, e.g. "mail.example.com".
+  [merge-tools]
+  # Override stock tool location
+  kdiff3.executable = ~/bin/kdiff3
+  # Specify command line
+  kdiff3.args = $base $local $other -o $output
+  # Give higher priority
+  kdiff3.priority = 1
+
+  # Define new tool
+  myHtmlTool.args = -m $local $other $base $output
+  myHtmlTool.regkey = Software\FooSoftware\HtmlMerge
+  myHtmlTool.priority = 1
+
+Supported arguments:
 
-``port``
-    Optional. Port to connect to on mail server. Default: 25.
+``priority``
+  The priority in which to evaluate this tool.
+  Default: 0.
+
+``executable``
+  Either just the name of the executable or its pathname.  On Windows,
+  the path can use environment variables with ${ProgramFiles} syntax.
+  Default: the tool name.
+
+``args``
+  The arguments to pass to the tool executable. You can refer to the
+  files being merged as well as the output file through these
+  variables: ``$base``, ``$local``, ``$other``, ``$output``.
+  Default: ``$local $base $other``
 
-``tls``
-    Optional. Method to enable TLS when connecting to mail server: starttls,
-    smtps or none. Default: none.
+``premerge``
+  Attempt to run internal non-interactive 3-way merge tool before
+  launching external tool.  Options are ``true``, ``false``, or ``keep``
+  to leave markers in the file if the premerge fails.
+  Default: True
+
+``binary``
+  This tool can merge binary files. Defaults to False, unless tool
+  was selected by file pattern match.
+
+``symlink``
+  This tool can merge symlinks. Defaults to False, even if tool was
+  selected by file pattern match.
 
-``username``
-    Optional. User name for authenticating with the SMTP server.
-    Default: none.
+``check``
+  A list of merge success-checking options:
+
+  ``changed``
+    Ask whether merge was successful when the merged file shows no changes.
+  ``conflicts``
+    Check whether there are conflicts even though the tool reported success.
+  ``prompt``
+    Always prompt for merge success, regardless of success reported by tool.
+
+``checkchanged``
+  True is equivalent to ``check = changed``.
+  Default: False
 
-``password``
-    Optional. Password for authenticating with the SMTP server. If not
-    specified, interactive sessions will prompt the user for a
-    password; non-interactive sessions will fail. Default: none.
+``checkconflicts``
+  True is equivalent to ``check = conflicts``.
+  Default: False
+
+``fixeol``
+  Attempt to fix up EOL changes caused by the merge tool.
+  Default: False
+
+``gui``
+  This tool requires a graphical interface to run. Default: False
 
-``local_hostname``
-    Optional. It's the hostname that the sender can use to identify
-    itself to the MTA.
+``regkey``
+  Windows registry key which describes install location of this
+  tool. Mercurial will search for this key first under
+  ``HKEY_CURRENT_USER`` and then under ``HKEY_LOCAL_MACHINE``.
+  Default: None
+
+``regkeyalt``
+  An alternate Windows registry key to try if the first key is not
+  found.  The alternate key uses the same ``regname`` and ``regappend``
+  semantics of the primary key.  The most common use for this key
+  is to search for 32bit applications on 64bit operating systems.
+  Default: None
+
+``regname``
+  Name of value to read from specified registry key. Defaults to the
+  unnamed (default) value.
+
+``regappend``
+  String to append to the value read from the registry, typically
+  the executable name of the tool.
+  Default: None
 
 
 ``patch``
@@ -985,6 +984,35 @@
     checking that all new file revisions specified in manifests are
     present. Default is False.
 
+``smtp``
+""""""""
+
+Configuration for extensions that need to send email messages.
+
+``host``
+    Host name of mail server, e.g. "mail.example.com".
+
+``port``
+    Optional. Port to connect to on mail server. Default: 25.
+
+``tls``
+    Optional. Method to enable TLS when connecting to mail server: starttls,
+    smtps or none. Default: none.
+
+``username``
+    Optional. User name for authenticating with the SMTP server.
+    Default: none.
+
+``password``
+    Optional. Password for authenticating with the SMTP server. If not
+    specified, interactive sessions will prompt the user for a
+    password; non-interactive sessions will fail. Default: none.
+
+``local_hostname``
+    Optional. It's the hostname that the sender can use to identify
+    itself to the MTA.
+
+
 ``subpaths``
 """"""""""""
 
--- a/mercurial/help/merge-tools.txt	Tue Feb 28 23:47:46 2012 +0200
+++ b/mercurial/help/merge-tools.txt	Tue Feb 28 21:17:53 2012 -0600
@@ -34,33 +34,7 @@
 There are some internal merge tools which can be used. The internal
 merge tools are:
 
-``internal:merge``
-   Uses the internal non-interactive simple merge algorithm for merging
-   files. It will fail if there are any conflicts and leave markers in
-   the partially merged file.
-
-``internal:fail``
-   Rather than attempting to merge files that were modified on both
-   branches, it marks them as unresolved. The resolve command must be
-   used to resolve these conflicts.
-
-``internal:local``
-   Uses the local version of files as the merged version.
-
-``internal:other``
-   Uses the other version of files as the merged version.
-
-``internal:prompt``
-   Asks the user which of the local or the other version to keep as
-   the merged version.
-
-``internal:dump``
-   Creates three versions of the files to merge, containing the
-   contents of local, other and base. These files can then be used to
-   perform a merge manually. If the file to be merged is named
-   ``a.txt``, these files will accordingly be named ``a.txt.local``,
-   ``a.txt.other`` and ``a.txt.base`` and they will be placed in the
-   same directory as ``a.txt``.
+.. internaltoolsmarker
 
 Internal tools are always available and do not require a GUI but will by default
 not handle symlinks or binary files.
--- a/mercurial/hgweb/webcommands.py	Tue Feb 28 23:47:46 2012 +0200
+++ b/mercurial/hgweb/webcommands.py	Tue Feb 28 21:17:53 2012 -0600
@@ -770,7 +770,7 @@
         startrev = uprev
 
     dag = graphmod.dagwalker(web.repo, range(startrev, downrev - 1, -1))
-    tree = list(graphmod.colored(dag))
+    tree = list(graphmod.colored(dag, web.repo))
     canvasheight = (len(tree) + 1) * bg_height - 27
     data = []
     for (id, type, ctx, vtx, edges) in tree:
--- a/mercurial/localrepo.py	Tue Feb 28 23:47:46 2012 +0200
+++ b/mercurial/localrepo.py	Tue Feb 28 21:17:53 2012 -0600
@@ -1097,37 +1097,58 @@
 
             # check subrepos
             subs = []
-            removedsubs = set()
+            commitsubs = set()
+            newstate = wctx.substate.copy()
+            # only manage subrepos and .hgsubstate if .hgsub is present
             if '.hgsub' in wctx:
-                # only manage subrepos and .hgsubstate if .hgsub is present
+                # we'll decide whether to track this ourselves, thanks
+                if '.hgsubstate' in changes[0]:
+                    changes[0].remove('.hgsubstate')
+                if '.hgsubstate' in changes[2]:
+                    changes[2].remove('.hgsubstate')
+
+                # compare current state to last committed state
+                # build new substate based on last committed state
+                oldstate = wctx.p1().substate
+                for s in sorted(newstate.keys()):
+                    if not match(s):
+                        # ignore working copy, use old state if present
+                        if s in oldstate:
+                            newstate[s] = oldstate[s]
+                            continue
+                        if not force:
+                            raise util.Abort(
+                                _("commit with new subrepo %s excluded") % s)
+                    if wctx.sub(s).dirty(True):
+                        if not self.ui.configbool('ui', 'commitsubrepos'):
+                            raise util.Abort(
+                                _("uncommitted changes in subrepo %s") % s,
+                                hint=_("use --subrepos for recursive commit"))
+                        subs.append(s)
+                        commitsubs.add(s)
+                    else:
+                        bs = wctx.sub(s).basestate()
+                        newstate[s] = (newstate[s][0], bs, newstate[s][2])
+                        if oldstate.get(s, (None, None, None))[1] != bs:
+                            subs.append(s)
+
+                # check for removed subrepos
                 for p in wctx.parents():
-                    removedsubs.update(s for s in p.substate if match(s))
-                for s in wctx.substate:
-                    removedsubs.discard(s)
-                    if match(s) and wctx.sub(s).dirty():
-                        subs.append(s)
-                if (subs or removedsubs):
+                    r = [s for s in p.substate if s not in newstate]
+                    subs += [s for s in r if match(s)]
+                if subs:
                     if (not match('.hgsub') and
                         '.hgsub' in (wctx.modified() + wctx.added())):
                         raise util.Abort(
                             _("can't commit subrepos without .hgsub"))
-                    if '.hgsubstate' not in changes[0]:
-                        changes[0].insert(0, '.hgsubstate')
-                        if '.hgsubstate' in changes[2]:
-                            changes[2].remove('.hgsubstate')
+                    changes[0].insert(0, '.hgsubstate')
+
             elif '.hgsub' in changes[2]:
                 # clean up .hgsubstate when .hgsub is removed
                 if ('.hgsubstate' in wctx and
                     '.hgsubstate' not in changes[0] + changes[1] + changes[2]):
                     changes[2].insert(0, '.hgsubstate')
 
-            if subs and not self.ui.configbool('ui', 'commitsubrepos', False):
-                changedsubs = [s for s in subs if wctx.sub(s).dirty(True)]
-                if changedsubs:
-                    raise util.Abort(_("uncommitted changes in subrepo %s")
-                                     % changedsubs[0],
-                                     hint=_("use --subrepos for recursive commit"))
-
             # make sure all explicit patterns are matched
             if not force and match.files():
                 matched = set(changes[0] + changes[1] + changes[2])
@@ -1163,16 +1184,15 @@
                 cctx._text = editor(self, cctx, subs)
             edited = (text != cctx._text)
 
-            # commit subs
-            if subs or removedsubs:
-                state = wctx.substate.copy()
-                for s in sorted(subs):
+            # commit subs and write new state
+            if subs:
+                for s in sorted(commitsubs):
                     sub = wctx.sub(s)
                     self.ui.status(_('committing subrepository %s\n') %
                         subrepo.subrelpath(sub))
                     sr = sub.commit(cctx._text, user, date)
-                    state[s] = (state[s][0], sr)
-                subrepo.writestate(self, state)
+                    newstate[s] = (newstate[s][0], sr)
+                subrepo.writestate(self, newstate)
 
             # Save commit message in case this transaction gets rolled back
             # (e.g. by a pretxncommit hook).  Leave the content alone on
--- a/mercurial/match.py	Tue Feb 28 23:47:46 2012 +0200
+++ b/mercurial/match.py	Tue Feb 28 21:17:53 2012 -0600
@@ -333,5 +333,5 @@
 
 def _anypats(patterns):
     for kind, name in patterns:
-        if kind in ('glob', 're', 'relglob', 'relre'):
+        if kind in ('glob', 're', 'relglob', 'relre', 'set'):
             return True
--- a/mercurial/merge.py	Tue Feb 28 23:47:46 2012 +0200
+++ b/mercurial/merge.py	Tue Feb 28 21:17:53 2012 -0600
@@ -81,22 +81,19 @@
             self.mark(dfile, 'r')
         return r
 
-def _checkunknown(wctx, mctx, folding):
+def _checkunknownfile(repo, wctx, mctx, f):
+    return (not repo.dirstate._ignore(f)
+        and os.path.exists(repo.wjoin(f))
+        and mctx[f].cmp(wctx[f]))
+
+def _checkunknown(repo, wctx, mctx):
     "check for collisions between unknown files and files in mctx"
-    if folding:
-        foldf = util.normcase
-    else:
-        foldf = lambda fn: fn
-    folded = {}
-    for fn in mctx:
-        folded[foldf(fn)] = fn
 
     error = False
-    for fn in wctx.unknown():
-        f = foldf(fn)
-        if f in folded and mctx[folded[f]].cmp(wctx[f]):
+    for f in mctx:
+        if f not in wctx and _checkunknownfile(repo, wctx, mctx, f):
             error = True
-            wctx._repo.ui.warn(_("%s: untracked file differs\n") % fn)
+            wctx._repo.ui.warn(_("%s: untracked file differs\n") % f)
     if error:
         raise util.Abort(_("untracked files in working directory differ "
                            "from files in requested revision"))
@@ -191,8 +188,7 @@
     elif pa == p2: # backwards
         pa = p1.p1()
     elif pa and repo.ui.configbool("merge", "followcopies", True):
-        dirs = repo.ui.configbool("merge", "followdirs", True)
-        copy, diverge = copies.mergecopies(repo, p1, p2, pa, dirs)
+        copy, diverge = copies.mergecopies(repo, p1, p2, pa)
         for of, fl in diverge.iteritems():
             act("divergent renames", "dr", of, fl)
 
@@ -248,7 +244,7 @@
                     act("prompt keep", "a", f)
             elif n[20:] == "a": # added, no remote
                 act("remote deleted", "f", f)
-            elif n[20:] != "u":
+            else:
                 act("other deleted", "r", f)
 
     for f, n in m2.iteritems():
@@ -268,7 +264,13 @@
                 act("remote moved to " + f, "m",
                     f2, f, f, fmerge(f2, f, f2), True)
         elif f not in ma:
-            act("remote created", "g", f, m2.flags(f))
+            if (not overwrite
+                and _checkunknownfile(repo, p1, p2, f)):
+                rflags = fmerge(f, f, f)
+                act("remote differs from untracked local",
+                    "m", f, f, f, rflags, False)
+            else:
+                act("remote created", "g", f, m2.flags(f))
         elif n != ma[f]:
             if repo.ui.promptchoice(
                 _("remote changed %s which local deleted\n"
@@ -542,6 +544,8 @@
             if not force and (wc.files() or wc.deleted()):
                 raise util.Abort(_("outstanding uncommitted changes"),
                                  hint=_("use 'hg status' to list changes"))
+            if not force:
+                _checkunknown(repo, wc, p2)
             for s in wc.substate:
                 if wc.sub(s).dirty():
                     raise util.Abort(_("outstanding uncommitted changes in "
@@ -558,14 +562,11 @@
                                    " --check to force update)"))
             else:
                 # Allow jumping branches if clean and specific rev given
-                overwrite = True
+                pa = p1
 
         ### calculate phase
         action = []
-        wc.status(unknown=True) # prime cache
         folding = not util.checkcase(repo.path)
-        if not force:
-            _checkunknown(wc, p2, folding)
         if folding:
             _checkcollision(p2, branchmerge and p1)
         action += _forgetremoved(wc, p2, branchmerge)
--- a/mercurial/revset.py	Tue Feb 28 23:47:46 2012 +0200
+++ b/mercurial/revset.py	Tue Feb 28 21:17:53 2012 -0600
@@ -112,7 +112,7 @@
 
 def getargs(x, min, max, err):
     l = getlist(x)
-    if len(l) < min or len(l) > max:
+    if len(l) < min or (max >= 0 and len(l) > max):
         raise error.ParseError(err)
     return l
 
@@ -441,29 +441,45 @@
     """
     return limit(repo, subset, x)
 
+def _follow(repo, subset, x, name, followfirst=False):
+    l = getargs(x, 0, 1, _("%s takes no arguments or a filename") % name)
+    c = repo['.']
+    if l:
+        x = getstring(l[0], _("%s expected a filename") % name)
+        if x in c:
+            cx = c[x]
+            s = set(ctx.rev() for ctx in cx.ancestors(followfirst=followfirst))
+            # include the revision responsible for the most recent version
+            s.add(cx.linkrev())
+        else:
+            return []
+    else:
+        cut = followfirst and 1 or None
+        cl = repo.changelog
+        s = set()
+        visit = [c.rev()]
+        while visit:
+            for prev in cl.parentrevs(visit.pop(0))[:cut]:
+                if prev not in s and prev != nodemod.nullrev:
+                    visit.append(prev)
+                    s.add(prev)
+        s.add(c.rev())
+
+    return [r for r in subset if r in s]
+
 def follow(repo, subset, x):
     """``follow([file])``
     An alias for ``::.`` (ancestors of the working copy's first parent).
     If a filename is specified, the history of the given file is followed,
     including copies.
     """
-    # i18n: "follow" is a keyword
-    l = getargs(x, 0, 1, _("follow takes no arguments or a filename"))
-    c = repo['.']
-    if l:
-        x = getstring(l[0], _("follow expected a filename"))
-        if x in c:
-            cx = c[x]
-            s = set(ctx.rev() for ctx in cx.ancestors())
-            # include the revision responsible for the most recent version
-            s.add(cx.linkrev())
-        else:
-            return []
-    else:
-        s = set(repo.changelog.ancestors(c.rev()))
-        s.add(c.rev())
+    return _follow(repo, subset, x, 'follow')
 
-    return [r for r in subset if r in s]
+def _followfirst(repo, subset, x):
+    # ``followfirst([file])``
+    # Like ``follow([file])`` but follows only the first parent of
+    # every revision or file revision.
+    return _follow(repo, subset, x, '_followfirst', followfirst=True)
 
 def getall(repo, subset, x):
     """``all()``
@@ -493,23 +509,64 @@
                 break
     return l
 
+def _matchfiles(repo, subset, x):
+    # _matchfiles takes a revset list of prefixed arguments:
+    #
+    #   [p:foo, i:bar, x:baz]
+    #
+    # builds a match object from them and filters subset. Allowed
+    # prefixes are 'p:' for regular patterns, 'i:' for include
+    # patterns and 'x:' for exclude patterns. Use 'r:' prefix to pass
+    # a revision identifier, or the empty string to reference the
+    # working directory, from which the match object is
+    # initialized. At most one 'r:' argument can be passed.
+
+    # i18n: "_matchfiles" is a keyword
+    l = getargs(x, 1, -1, _("_matchfiles requires at least one argument"))
+    pats, inc, exc = [], [], []
+    hasset = False
+    rev = None
+    for arg in l:
+        s = getstring(arg, _("_matchfiles requires string arguments"))
+        prefix, value = s[:2], s[2:]
+        if prefix == 'p:':
+            pats.append(value)
+        elif prefix == 'i:':
+            inc.append(value)
+        elif prefix == 'x:':
+            exc.append(value)
+        elif prefix == 'r:':
+            if rev is not None:
+                raise error.ParseError(_('_matchfiles expected at most one '
+                                         'revision'))
+            rev = value
+        else:
+            raise error.ParseError(_('invalid _matchfiles prefix: %s') % prefix)
+        if not hasset and matchmod.patkind(value) == 'set':
+            hasset = True
+    m = None
+    s = []
+    for r in subset:
+        c = repo[r]
+        if not m or (hasset and rev is None):
+            ctx = c
+            if rev is not None:
+                ctx = repo[rev or None]
+            m = matchmod.match(repo.root, repo.getcwd(), pats, include=inc,
+                               exclude=exc, ctx=ctx)
+        for f in c.files():
+            if m(f):
+                s.append(r)
+                break
+    return s
+
 def hasfile(repo, subset, x):
     """``file(pattern)``
     Changesets affecting files matched by pattern.
     """
     # i18n: "file" is a keyword
     pat = getstring(x, _("file requires a pattern"))
-    m = None
-    s = []
-    for r in subset:
-        c = repo[r]
-        if not m or matchmod.patkind(pat) == 'set':
-            m = matchmod.match(repo.root, repo.getcwd(), [pat], ctx=c)
-        for f in c.files():
-            if m(f):
-                s.append(r)
-                break
-    return s
+    return _matchfiles(repo, subset, ('string', 'p:' + pat))
 
 def head(repo, subset, x):
     """``head()``
@@ -936,6 +993,7 @@
     "filelog": filelog,
     "first": first,
     "follow": follow,
+    "_followfirst": _followfirst,
     "grep": grep,
     "head": head,
     "heads": heads,
@@ -943,6 +1001,7 @@
     "keyword": keyword,
     "last": last,
     "limit": limit,
+    "_matchfiles": _matchfiles,
     "max": maxrev,
     "merge": merge,
     "min": minrev,
@@ -1071,46 +1130,85 @@
         h = heads(default)
         b($1) = ancestors($1) - ancestors(default)
         '''
-        if isinstance(name, tuple): # parameter substitution
-            self.tree = name
-            self.replacement = value
-        else: # alias definition
-            m = self.funcre.search(name)
-            if m:
-                self.tree = ('func', ('symbol', m.group(1)))
-                self.args = [x.strip() for x in m.group(2).split(',')]
-                for arg in self.args:
-                    value = value.replace(arg, repr(arg))
-            else:
-                self.tree = ('symbol', name)
+        m = self.funcre.search(name)
+        if m:
+            self.name = m.group(1)
+            self.tree = ('func', ('symbol', m.group(1)))
+            self.args = [x.strip() for x in m.group(2).split(',')]
+            for arg in self.args:
+                value = value.replace(arg, repr(arg))
+        else:
+            self.name = name
+            self.tree = ('symbol', name)
+
+        self.replacement, pos = parse(value)
+        if pos != len(value):
+            raise error.ParseError(_('invalid token'), pos)
 
-            self.replacement, pos = parse(value)
-            if pos != len(value):
-                raise error.ParseError(_('invalid token'), pos)
+def _getalias(aliases, tree):
+    """If tree looks like an unexpanded alias, return it. Return None
+    otherwise.
+    """
+    if isinstance(tree, tuple) and tree:
+        if tree[0] == 'symbol' and len(tree) == 2:
+            name = tree[1]
+            alias = aliases.get(name)
+            if alias and alias.args is None and alias.tree == tree:
+                return alias
+        if tree[0] == 'func' and len(tree) > 1:
+            if tree[1][0] == 'symbol' and len(tree[1]) == 2:
+                name = tree[1][1]
+                alias = aliases.get(name)
+                if alias and alias.args is not None and alias.tree == tree[:2]:
+                    return alias
+    return None
 
-    def process(self, tree):
-        if isinstance(tree, tuple):
-            if self.args is None:
-                if tree == self.tree:
-                    return self.replacement
-            elif tree[:2] == self.tree:
-                l = getlist(tree[2])
-                if len(l) != len(self.args):
-                    raise error.ParseError(
-                        _('invalid number of arguments: %s') % len(l))
-                result = self.replacement
-                for a, v in zip(self.args, l):
-                    valalias = revsetalias(('string', a), v)
-                    result = valalias.process(result)
-                return result
-            return tuple(map(self.process, tree))
+def _expandargs(tree, args):
+    """Replace all occurences of ('string', name) with the
+    substitution value of the same name in args, recursively.
+    """
+    if not isinstance(tree, tuple):
+        return tree
+    if len(tree) == 2 and tree[0] == 'string':
+        return args.get(tree[1], tree)
+    return tuple(_expandargs(t, args) for t in tree)
+
+def _expandaliases(aliases, tree, expanding):
+    """Expand aliases in tree, recursively.
+
+    'aliases' is a dictionary mapping user defined aliases to
+    revsetalias objects.
+    """
+    if not isinstance(tree, tuple):
+        # Do not expand raw strings
         return tree
+    alias = _getalias(aliases, tree)
+    if alias is not None:
+        if alias in expanding:
+            raise error.ParseError(_('infinite expansion of revset alias "%s" '
+                                     'detected') % alias.name)
+        expanding.append(alias)
+        result = alias.replacement
+        if alias.args is not None:
+            l = getlist(tree[2])
+            if len(l) != len(alias.args):
+                raise error.ParseError(
+                    _('invalid number of arguments: %s') % len(l))
+            result = _expandargs(result, dict(zip(alias.args, l)))
+        # Recurse in place, the base expression may have been rewritten
+        result = _expandaliases(aliases, result, expanding)
+        expanding.pop()
+    else:
+        result = tuple(_expandaliases(aliases, t, expanding)
+                       for t in tree)
+    return result
 
 def findaliases(ui, tree):
+    aliases = {}
     for k, v in ui.configitems('revsetalias'):
         alias = revsetalias(k, v)
-        tree = alias.process(tree)
-    return tree
+        aliases[alias.name] = alias
+    return _expandaliases(aliases, tree, [])
 
 parse = parser.parser(tokenize, elements).parse
 
--- a/mercurial/scmutil.py	Tue Feb 28 23:47:46 2012 +0200
+++ b/mercurial/scmutil.py	Tue Feb 28 21:17:53 2012 -0600
@@ -579,7 +579,7 @@
         ret.append(p)
     return ret
 
-def match(ctx, pats=[], opts={}, globbed=False, default='relpath'):
+def matchandpats(ctx, pats=[], opts={}, globbed=False, default='relpath'):
     if pats == ("",):
         pats = []
     if not globbed and default == 'relpath':
@@ -590,7 +590,10 @@
     def badfn(f, msg):
         ctx._repo.ui.warn("%s: %s\n" % (m.rel(f), msg))
     m.bad = badfn
-    return m
+    return m, pats
+
+def match(ctx, pats=[], opts={}, globbed=False, default='relpath'):
+    return matchandpats(ctx, pats, opts, globbed, default)[0]
 
 def matchall(repo):
     return matchmod.always(repo.root, repo.getcwd())
@@ -607,6 +610,9 @@
     added, unknown, deleted, removed = [], [], [], []
     audit_path = pathauditor(repo.root)
     m = match(repo[None], pats, opts)
+    rejected = []
+    m.bad = lambda x, y: rejected.append(x)
+
     for abs in repo.walk(m):
         target = repo.wjoin(abs)
         good = True
@@ -651,6 +657,11 @@
         finally:
             wlock.release()
 
+    for f in rejected:
+        if f in m.files():
+            return 1
+    return 0
+
 def updatedir(ui, repo, patches, similarity=0):
     '''Update dirstate after patch application according to metadata'''
     if not patches:
--- a/mercurial/subrepo.py	Tue Feb 28 23:47:46 2012 +0200
+++ b/mercurial/subrepo.py	Tue Feb 28 21:17:53 2012 -0600
@@ -275,6 +275,11 @@
         """
         raise NotImplementedError
 
+    def basestate(self):
+        """current working directory base state, disregarding .hgsubstate
+        state and working directory modifications"""
+        raise NotImplementedError
+
     def checknested(self, path):
         """check if path is a subrepository within this repository"""
         return False
@@ -446,6 +451,9 @@
             return True
         return w.dirty() # working directory changed
 
+    def basestate(self):
+        return self._repo['.'].hex()
+
     def checknested(self, path):
         return self._repo._checknested(self._repo.wjoin(path))
 
@@ -666,6 +674,9 @@
                 return False
         return True
 
+    def basestate(self):
+        return self._wcrev()
+
     def commit(self, text, user, date):
         # user and date are out of our hands since svn is centralized
         changed, extchanged = self._wcchanged()
@@ -907,6 +918,9 @@
         out, code = self._gitdir(['diff-index', '--quiet', 'HEAD'])
         return code == 1
 
+    def basestate(self):
+        return self._gitstate()
+
     def get(self, state, overwrite=False):
         source, revision, kind = state
         if not revision:
--- a/mercurial/templates/gitweb/graph.tmpl	Tue Feb 28 23:47:46 2012 +0200
+++ b/mercurial/templates/gitweb/graph.tmpl	Tue Feb 28 21:17:53 2012 -0600
@@ -51,16 +51,6 @@
 var graph = new Graph();
 graph.scale({bg_height});
 
-graph.edge = function(x0, y0, x1, y1, color) \{
-	
-	this.setColor(color, 0.0, 0.65);
-	this.ctx.beginPath();
-	this.ctx.moveTo(x0, y0);
-	this.ctx.lineTo(x1, y1);
-	this.ctx.stroke();
-	
-}
-
 var revlink = '<li style="_STYLE"><span class="desc">';
 revlink += '<a class="list" href="{url}rev/_NODEID{sessionvars%urlparameter}" title="_NODEID"><b>_DESC</b></a>';
 revlink += '</span> _TAGS';
--- a/mercurial/templates/monoblue/graph.tmpl	Tue Feb 28 23:47:46 2012 +0200
+++ b/mercurial/templates/monoblue/graph.tmpl	Tue Feb 28 21:17:53 2012 -0600
@@ -49,16 +49,6 @@
     var graph = new Graph();
     graph.scale({bg_height});
 
-    graph.edge = function(x0, y0, x1, y1, color) \{
-
-        this.setColor(color, 0.0, 0.65);
-        this.ctx.beginPath();
-        this.ctx.moveTo(x0, y0);
-        this.ctx.lineTo(x1, y1);
-        this.ctx.stroke();
-
-    }
-
     var revlink = '<li style="_STYLE"><span class="desc">';
     revlink += '<a href="{url}rev/_NODEID{sessionvars%urlparameter}" title="_NODEID">_DESC</a>';
     revlink += '</span>_TAGS<span class="info">_DATE, by _USER</span></li>';
--- a/mercurial/templates/paper/graph.tmpl	Tue Feb 28 23:47:46 2012 +0200
+++ b/mercurial/templates/paper/graph.tmpl	Tue Feb 28 21:17:53 2012 -0600
@@ -62,16 +62,6 @@
 var graph = new Graph();
 graph.scale({bg_height});
 
-graph.edge = function(x0, y0, x1, y1, color) \{
-	
-	this.setColor(color, 0.0, 0.65);
-	this.ctx.beginPath();
-	this.ctx.moveTo(x0, y0);
-	this.ctx.lineTo(x1, y1);
-	this.ctx.stroke();
-	
-}
-
 var revlink = '<li style="_STYLE"><span class="desc">';
 revlink += '<a href="{url}rev/_NODEID{sessionvars%urlparameter}" title="_NODEID">_DESC</a>';
 revlink += '</span>_TAGS<span class="info">_DATE, by _USER</span></li>';
--- a/mercurial/templates/spartan/graph.tmpl	Tue Feb 28 23:47:46 2012 +0200
+++ b/mercurial/templates/spartan/graph.tmpl	Tue Feb 28 21:17:53 2012 -0600
@@ -43,16 +43,6 @@
 var graph = new Graph();
 graph.scale({bg_height});
 
-graph.edge = function(x0, y0, x1, y1, color) \{
-	
-	this.setColor(color, 0.0, 0.65);
-	this.ctx.beginPath();
-	this.ctx.moveTo(x0, y0);
-	this.ctx.lineTo(x1, y1);
-	this.ctx.stroke();
-	
-}
-
 var revlink = '<li style="_STYLE"><span class="desc">';
 revlink += '<a href="{url}rev/_NODEID{sessionvars%urlparameter}" title="_NODEID">_DESC</a>';
 revlink += '</span><span class="info">_DATE, by _USER</span></li>';
--- a/mercurial/templates/static/mercurial.js	Tue Feb 28 23:47:46 2012 +0200
+++ b/mercurial/templates/static/mercurial.js	Tue Feb 28 21:17:53 2012 -0600
@@ -58,25 +58,44 @@
 		
 		// Set the colour.
 		//
-		// Picks a distinct colour based on an internal wheel; the bg
-		// parameter provides the value that should be assigned to the 'zero'
-		// colours and the fg parameter provides the multiplier that should be
-		// applied to the foreground colours.
-		
-		color %= colors.length;
-		var red = (colors[color][0] * fg) || bg;
-		var green = (colors[color][1] * fg) || bg;
-		var blue = (colors[color][2] * fg) || bg;
-		red = Math.round(red * 255);
-		green = Math.round(green * 255);
-		blue = Math.round(blue * 255);
-		var s = 'rgb(' + red + ', ' + green + ', ' + blue + ')';
+		// If color is a string, expect an hexadecimal RGB
+		// value and apply it unchanged. If color is a number,
+		// pick a distinct colour based on an internal wheel;
+		// the bg parameter provides the value that should be
+		// assigned to the 'zero' colours and the fg parameter
+		// provides the multiplier that should be applied to
+		// the foreground colours.
+		var s;
+		if(typeof color == "string") {
+			s = "#" + color;
+		} else { //typeof color == "number"
+			color %= colors.length;
+			var red = (colors[color][0] * fg) || bg;
+			var green = (colors[color][1] * fg) || bg;
+			var blue = (colors[color][2] * fg) || bg;
+			red = Math.round(red * 255);
+			green = Math.round(green * 255);
+			blue = Math.round(blue * 255);
+			s = 'rgb(' + red + ', ' + green + ', ' + blue + ')';
+		}
 		this.ctx.strokeStyle = s;
 		this.ctx.fillStyle = s;
 		return s;
 		
 	}
 
+	this.edge = function(x0, y0, x1, y1, color, width) {
+		
+		this.setColor(color, 0.0, 0.65);
+		if(width >= 0)
+			 this.ctx.lineWidth = width;
+		this.ctx.beginPath();
+		this.ctx.moveTo(x0, y0);
+		this.ctx.lineTo(x1, y1);
+		this.ctx.stroke();
+		
+	}
+
 	this.render = function(data) {
 		
 		var backgrounds = '';
@@ -93,13 +112,20 @@
 			var edges = cur[2];
 			var fold = false;
 			
+			var prevWidth = this.ctx.lineWidth;
 			for (var j in edges) {
 				
 				line = edges[j];
 				start = line[0];
 				end = line[1];
 				color = line[2];
-
+				var width = line[3];
+				if(width < 0)
+					 width = prevWidth;
+				var branchcolor = line[4];
+				if(branchcolor)
+					color = branchcolor;
+				
 				if (end > this.columns || start > this.columns) {
 					this.columns += 1;
 				}
@@ -113,9 +139,10 @@
 				x1 = this.cell[0] + this.box_size * end + this.box_size / 2;
 				y1 = this.bg[1] + this.bg_height / 2;
 				
-				this.edge(x0, y0, x1, y1, color);
+				this.edge(x0, y0, x1, y1, color, width);
 				
 			}
+			this.ctx.lineWidth = prevWidth;
 			
 			// Draw the revision node in the right column
 			
--- a/mercurial/ui.py	Tue Feb 28 23:47:46 2012 +0200
+++ b/mercurial/ui.py	Tue Feb 28 21:17:53 2012 -0600
@@ -7,7 +7,7 @@
 
 from i18n import _
 import errno, getpass, os, socket, sys, tempfile, traceback
-import config, scmutil, util, error
+import config, scmutil, util, error, formatter
 
 class ui(object):
     def __init__(self, src=None):
@@ -46,6 +46,9 @@
     def copy(self):
         return self.__class__(self)
 
+    def formatter(self, topic, opts):
+        return formatter.formatter(self, topic, opts)
+
     def _trusted(self, fp, f):
         st = util.fstat(fp)
         if util.isowner(st):
--- a/mercurial/windows.py	Tue Feb 28 23:47:46 2012 +0200
+++ b/mercurial/windows.py	Tue Feb 28 21:17:53 2012 -0600
@@ -123,7 +123,7 @@
         msvcrt.setmode(fno(), os.O_BINARY)
 
 def pconvert(path):
-    return '/'.join(path.split(os.sep))
+    return path.replace(os.sep, '/')
 
 def localpath(path):
     return path.replace('/', '\\')
--- a/tests/bzr-definitions	Tue Feb 28 23:47:46 2012 +0200
+++ b/tests/bzr-definitions	Tue Feb 28 21:17:53 2012 -0600
@@ -9,7 +9,7 @@
 
 glog()
 {
-    hg glog --template '{rev} "{desc|firstline}" files: {files}\n' "$@"
+    hg glog --template '{rev}@{branch} "{desc|firstline}" files: {files}\n' "$@"
 }
 
 manifest()
--- a/tests/test-check-code-hg.t	Tue Feb 28 23:47:46 2012 +0200
+++ b/tests/test-check-code-hg.t	Tue Feb 28 21:17:53 2012 -0600
@@ -477,9 +477,6 @@
    >     except:
    warning: naked except clause
   mercurial/localrepo.py:0:
-   >                                      hint=_("use --subrepos for recursive commit"))
-   warning: line over 80 characters
-  mercurial/localrepo.py:0:
    >                         # we return an integer indicating remote head count change
    warning: line over 80 characters
   mercurial/localrepo.py:0:
--- a/tests/test-convert-bzr-ghosts.t	Tue Feb 28 23:47:46 2012 +0200
+++ b/tests/test-convert-bzr-ghosts.t	Tue Feb 28 21:17:53 2012 -0600
@@ -30,7 +30,7 @@
   1 Initial layout setup
   0 Commit with ghost revision
   $ glog -R source-hg
-  o  1 "Commit with ghost revision" files: somefile
+  o  1@source "Commit with ghost revision" files: somefile
   |
-  o  0 "Initial layout setup" files: somefile
+  o  0@source "Initial layout setup" files: somefile
   
--- a/tests/test-convert-bzr-merges.t	Tue Feb 28 23:47:46 2012 +0200
+++ b/tests/test-convert-bzr-merges.t	Tue Feb 28 21:17:53 2012 -0600
@@ -48,17 +48,17 @@
   1 Added brach2 file
   0 Merged branches
   $ glog -R source-hg
-  o    5 "(octopus merge fixup)" files:
+  o    5@source "(octopus merge fixup)" files:
   |\
-  | o    4 "Merged branches" files: file-branch2
+  | o    4@source "Merged branches" files: file-branch2
   | |\
-  o---+  3 "Added brach2 file" files: file-branch2
+  o---+  3@source-branch2 "Added brach2 file" files: file-branch2
    / /
-  | o  2 "Added parent file" files: file-parent
+  | o  2@source "Added parent file" files: file-parent
   | |
-  o |  1 "Added branch1 file" files: file file-branch1
+  o |  1@source-branch1 "Added branch1 file" files: file file-branch1
   |/
-  o  0 "Initial add" files: file
+  o  0@source "Initial add" files: file
   
   $ manifest source-hg tip
   % manifest of tip
--- a/tests/test-convert-bzr.t	Tue Feb 28 23:47:46 2012 +0200
+++ b/tests/test-convert-bzr.t	Tue Feb 28 21:17:53 2012 -0600
@@ -7,6 +7,17 @@
   $ mkdir test-createandrename
   $ cd test-createandrename
   $ bzr init -q source
+
+test empty repo conversion (issue3233)
+
+  $ hg convert source source-hg
+  initializing destination source-hg repository
+  scanning source...
+  sorting...
+  converting...
+
+back to the rename stuff
+
   $ cd source
   $ echo a > a
   $ echo c > c
@@ -25,16 +36,15 @@
   $ bzr commit -q -m 'rename a into b, create a, rename c into d'
   $ cd ..
   $ hg convert source source-hg
-  initializing destination source-hg repository
   scanning source...
   sorting...
   converting...
   1 Initial add: a, c, e
   0 rename a into b, create a, rename c into d
   $ glog -R source-hg
-  o  1 "rename a into b, create a, rename c into d" files: a b c d e f
+  o  1@source "rename a into b, create a, rename c into d" files: a b c d e f
   |
-  o  0 "Initial add: a, c, e" files: a c e
+  o  0@source "Initial add: a, c, e" files: a c e
   
 
 manifest
@@ -54,7 +64,7 @@
   converting...
   0 Initial add: a, c, e
   $ glog -R source-1-hg
-  o  0 "Initial add: a, c, e" files: a c e
+  o  0@source "Initial add: a, c, e" files: a c e
   
 
 test with filemap
@@ -77,22 +87,12 @@
 convert from lightweight checkout
 
   $ bzr checkout --lightweight source source-light
-  $ hg convert source-light source-light-hg
+  $ hg convert -s bzr source-light source-light-hg
   initializing destination source-light-hg repository
   warning: lightweight checkouts may cause conversion failures, try with a regular branch instead.
-  scanning source...
-  sorting...
-  converting...
-  1 Initial add: a, c, e
-  0 rename a into b, create a, rename c into d
-
-lightweight manifest
-
-  $ hg manifest -R source-light-hg -r tip
-  a
-  b
-  d
-  f
+  $TESTTMP/test-createandrename/source-light does not look like a Bazaar repository
+  abort: source-light: missing or unsupported repository
+  [255]
 
 extract timestamps that look just like hg's {date|isodate}:
 yyyy-mm-dd HH:MM zzzz (no seconds!)
@@ -147,13 +147,13 @@
   1 Editing b
   0 Merged improve branch
   $ glog -R source-hg
-  o    3 "Merged improve branch" files:
+  o    3@source "Merged improve branch" files:
   |\
-  | o  2 "Editing b" files: b
+  | o  2@source-improve "Editing b" files: b
   | |
-  o |  1 "Editing a" files: a
+  o |  1@source "Editing a" files: a
   |/
-  o  0 "Initial add" files: a b
+  o  0@source "Initial add" files: a b
   
   $ cd ..
 
@@ -208,3 +208,77 @@
   $ hg cat syma; echo
   a
 
+Multiple branches
+
+  $ bzr init-repo -q --no-trees repo
+  $ bzr init -q repo/trunk
+  $ bzr co repo/trunk repo-trunk
+  $ cd repo-trunk
+  $ echo a > a
+  $ bzr add a
+  adding a
+  $ bzr ci -qm adda --commit-time '2012-01-01 00:00:01 +0000'
+  $ bzr tag trunk-tag
+  Created tag trunk-tag.
+  $ bzr switch -b branch
+  Tree is up to date at revision 1.
+  Switched to branch: *repo/branch/ (glob)
+  $ echo b > b
+  $ bzr add b
+  adding b
+  $ bzr ci -qm addb --commit-time '2012-01-01 00:00:02 +0000'
+  $ bzr tag branch-tag
+  Created tag branch-tag.
+  $ bzr switch --force ../repo/trunk
+  Updated to revision 1.
+  Switched to branch: */repo/trunk/ (glob)
+  $ echo a >> a
+  $ bzr ci -qm changea --commit-time '2012-01-01 00:00:03 +0000'
+  $ cd ..
+  $ hg convert --datesort repo repo-bzr
+  initializing destination repo-bzr repository
+  scanning source...
+  sorting...
+  converting...
+  2 adda
+  1 addb
+  0 changea
+  updating tags
+  $ (cd repo-bzr; glog)
+  o  3@default "update tags" files: .hgtags
+  |
+  o  2@default "changea" files: a
+  |
+  | o  1@branch "addb" files: b
+  |/
+  o  0@default "adda" files: a
+  
+
+Test tags (converted identifiers are not stable because bzr ones are
+not and get incorporated in extra fields).
+
+  $ hg -R repo-bzr tags
+  tip                                3:* (glob)
+  branch-tag                         1:* (glob)
+  trunk-tag                          0:* (glob)
+
+Nested repositories (issue3254)
+
+  $ bzr init-repo -q --no-trees repo/inner
+  $ bzr init -q repo/inner/trunk
+  $ bzr co repo/inner/trunk inner-trunk
+  $ cd inner-trunk
+  $ echo b > b
+  $ bzr add b
+  adding b
+  $ bzr ci -qm addb
+  $ cd ..
+  $ hg convert --datesort repo noinner-bzr
+  initializing destination noinner-bzr repository
+  scanning source...
+  sorting...
+  converting...
+  2 adda
+  1 addb
+  0 changea
+  updating tags
--- a/tests/test-glog.t	Tue Feb 28 23:47:46 2012 +0200
+++ b/tests/test-glog.t	Tue Feb 28 21:17:53 2012 -0600
@@ -83,8 +83,26 @@
   >   hg commit -Aqd "$rev 0" -m "($rev) $msg"
   > }
 
+  $ cat > printrevset.py <<EOF
+  > from mercurial import extensions, revset, commands
+  > from hgext import graphlog
+  >  
+  > def uisetup(ui):
+  >     def printrevset(orig, ui, repo, *pats, **opts):
+  >         if opts.get('print_revset'):
+  >             expr = graphlog.revset(repo, pats, opts)[0]
+  >             tree = revset.parse(expr)[0]
+  >             ui.write(tree, "\n")
+  >             return 0
+  >         return orig(ui, repo, *pats, **opts)
+  >     entry = extensions.wrapcommand(commands.table, 'log', printrevset)
+  >     entry[1].append(('', 'print-revset', False,
+  >                      'print generated revset and exit (DEPRECATED)'))
+  > EOF
+
   $ echo "[extensions]" >> $HGRCPATH
   $ echo "graphlog=" >> $HGRCPATH
+  $ echo "printrevset=`pwd`/printrevset.py" >> $HGRCPATH
 
   $ hg init repo
   $ cd repo
@@ -1359,9 +1377,13 @@
 
 Do not crash or produce strange graphs if history is buggy
 
+  $ hg branch branch
+  marked working directory as branch branch
+  (branches are permanent and global, did you want a bookmark?)
   $ commit 36 "buggy merge: identical parents" 35 35
   $ hg glog -l5
-  @  changeset:   36:95fa8febd08a
+  @  changeset:   36:08a19a744424
+  |  branch:      branch
   |  tag:         tip
   |  parent:      35:9159c3644c5e
   |  parent:      35:9159c3644c5e
@@ -1396,76 +1418,336 @@
 
 Test log -G options
 
-  $ hg log -G -u 'something nice'
-  $ hg log -G -b 'something nice'
-  abort: unknown revision 'something nice'!
-  [255]
-  $ hg log -G -k 'something nice'
-  $ hg log -G --only-branch 'something nice'
-  abort: unknown revision 'something nice'!
-  [255]
-  $ hg log -G --include 'some file' --exclude 'another file'
-  $ hg log -G --follow  --template 'nodetag {rev}\n' | grep nodetag | wc -l
-  \s*36 (re)
-  $ hg log -G --removed --template 'nodetag {rev}\n' | grep nodetag | wc -l
-  \s*0 (re)
-  $ hg log -G --only-merges --template 'nodetag {rev}\n' | grep nodetag | wc -l
-  \s*28 (re)
-  $ hg log -G --no-merges --template 'nodetag {rev}\n'
-  o  nodetag 35
-  |
-  o    nodetag 34
-  |\
-  | \
-  | |\
-  | | \
-  | | |\
-  | | | \
-  | | | |\
-  | | | | \
-  | | | | |\
-  +-+-+-+-----o  nodetag 33
-  | | | | | |
-  +---------o  nodetag 29
-  | | | | |
-  +-+-+---o  nodetag 27
-  | | | |/
-  | | | o  nodetag 3
-  | | |/
-  | | o  nodetag 2
-  | |/
-  | o  nodetag 1
-  |/
-  o  nodetag 0
-  
+  $ testlog() {
+  >   hg log -G --print-revset "$@"
+  >   hg log --template 'nodetag {rev}\n' "$@" | grep nodetag \
+  >     | sed 's/.*nodetag/nodetag/' > log.nodes
+  >   hg log -G --template 'nodetag {rev}\n' "$@" | grep nodetag \
+  >     | sed 's/.*nodetag/nodetag/' > glog.nodes
+  >   diff -u log.nodes glog.nodes
+  > }
+
+glog always reorders nodes which explains the difference with log
+
+  $ testlog -r 27 -r 25 -r 21 -r 34 -r 32 -r 31
+  ('group', ('group', ('or', ('or', ('or', ('or', ('or', ('symbol', '27'), ('symbol', '25')), ('symbol', '21')), ('symbol', '34')), ('symbol', '32')), ('symbol', '31'))))
+  --- log.nodes	* (glob)
+  +++ glog.nodes	* (glob)
+  @@ -1,6 +1,6 @@
+  -nodetag 27
+  -nodetag 25
+  -nodetag 21
+   nodetag 34
+   nodetag 32
+   nodetag 31
+  +nodetag 27
+  +nodetag 25
+  +nodetag 21
+  [1]
+  $ testlog -u test -u not-a-user
+  ('group', ('group', ('or', ('func', ('symbol', 'user'), ('string', 'test')), ('func', ('symbol', 'user'), ('string', 'not-a-user')))))
+  $ testlog -b not-a-branch
+  ('group', ('group', ('func', ('symbol', 'branch'), ('string', 'not-a-branch'))))
+  abort: unknown revision 'not-a-branch'!
+  abort: unknown revision 'not-a-branch'!
+  $ testlog -b default -b branch --only-branch branch
+  ('group', ('group', ('or', ('or', ('func', ('symbol', 'branch'), ('string', 'default')), ('func', ('symbol', 'branch'), ('string', 'branch'))), ('func', ('symbol', 'branch'), ('string', 'branch')))))
+  $ testlog -k expand -k merge
+  ('group', ('group', ('or', ('func', ('symbol', 'keyword'), ('string', 'expand')), ('func', ('symbol', 'keyword'), ('string', 'merge')))))
+  $ testlog --only-merges
+  ('group', ('func', ('symbol', 'merge'), None))
+  $ testlog --no-merges
+  ('group', ('not', ('func', ('symbol', 'merge'), None)))
+  $ testlog --date '2 0 to 4 0'
+  ('group', ('func', ('symbol', 'date'), ('string', '2 0 to 4 0')))
   $ hg log -G -d 'brace ) in a date'
   abort: invalid date: 'brace ) in a date'
   [255]
-  $ hg log -G -P 32 --template '{rev}\n'
-  @  36
+  $ testlog --prune 31 --prune 32
+  ('group', ('group', ('and', ('not', ('group', ('or', ('string', '31'), ('func', ('symbol', 'ancestors'), ('string', '31'))))), ('not', ('group', ('or', ('string', '32'), ('func', ('symbol', 'ancestors'), ('string', '32'))))))))
+
+Dedicated repo for --follow and paths filtering. The g is crafted to
+have 2 filelog topological heads in a linear changeset graph.
+
+  $ cd ..
+  $ hg init follow
+  $ cd follow
+  $ echo a > a
+  $ echo aa > aa
+  $ echo f > f
+  $ hg ci -Am "add a"
+  adding a
+  adding aa
+  adding f
+  $ hg cp a b
+  $ hg cp f g
+  $ hg ci -m "copy a b"
+  $ mkdir dir
+  $ hg mv b dir
+  $ echo g >> g
+  $ echo f >> f
+  $ hg ci -m "mv b dir/b"
+  $ hg mv a b
+  $ hg cp -f f g
+  $ echo a > d
+  $ hg add d
+  $ hg ci -m "mv a b; add d"
+  $ hg mv dir/b e
+  $ hg ci -m "mv dir/b e"
+  $ hg glog --template '({rev}) {desc|firstline}\n'
+  @  (4) mv dir/b e
   |
-  o  35
+  o  (3) mv a b; add d
+  |
+  o  (2) mv b dir/b
+  |
+  o  (1) copy a b
   |
-  o  34
-  |
-  | o  33
-  | |
-  $ hg log -G --follow a
-  abort: -G/--graph option is incompatible with --follow with file argument
-  [255]
+  o  (0) add a
+  
+
+  $ testlog a
+  ('group', ('group', ('func', ('symbol', 'filelog'), ('string', 'a'))))
+  $ testlog a b
+  ('group', ('group', ('or', ('func', ('symbol', 'filelog'), ('string', 'a')), ('func', ('symbol', 'filelog'), ('string', 'b')))))
+
+Test falling back to slow path for non-existing files
+
+  $ testlog a c
+  ('group', ('group', ('func', ('symbol', '_matchfiles'), ('list', ('list', ('string', 'r:'), ('string', 'p:a')), ('string', 'p:c')))))
+
+Test multiple --include/--exclude/paths
+
+  $ testlog --include a --include e --exclude b --exclude e a e
+  ('group', ('group', ('func', ('symbol', '_matchfiles'), ('list', ('list', ('list', ('list', ('list', ('list', ('string', 'r:'), ('string', 'p:a')), ('string', 'p:e')), ('string', 'i:a')), ('string', 'i:e')), ('string', 'x:b')), ('string', 'x:e')))))
+
+Test glob expansion of pats
+
+  $ expandglobs=`python -c "import mercurial.util; \
+  >   print mercurial.util.expandglobs and 'true' or 'false'"`
+  $ if [ $expandglobs = "true" ]; then
+  >    testlog 'a*';
+  > else
+  >    testlog a*;
+  > fi;
+  ('group', ('group', ('func', ('symbol', 'filelog'), ('string', 'aa'))))
+
+Test --follow on a directory
+
+  $ testlog -f dir
+  abort: cannot follow file not in parent revision: "dir"
+  abort: cannot follow file not in parent revision: "dir"
+  abort: cannot follow file not in parent revision: "dir"
+
+Test --follow on file not in parent revision
+
+  $ testlog -f a
+  abort: cannot follow file not in parent revision: "a"
+  abort: cannot follow file not in parent revision: "a"
+  abort: cannot follow file not in parent revision: "a"
+
+Test --follow and patterns
+
+  $ testlog -f 'glob:*'
+  abort: can only follow copies/renames for explicit filenames
+  abort: can only follow copies/renames for explicit filenames
+  abort: can only follow copies/renames for explicit filenames
+
+Test --follow on a single rename
+
+  $ hg up -q 2
+  $ testlog -f a
+  ('group', ('group', ('func', ('symbol', 'follow'), ('string', 'a'))))
+
+Test --follow and multiple renames
+
+  $ hg up -q tip
+  $ testlog -f e
+  ('group', ('group', ('func', ('symbol', 'follow'), ('string', 'e'))))
+
+Test --follow and multiple filelog heads
+
+  $ hg up -q 2
+  $ testlog -f g
+  ('group', ('group', ('func', ('symbol', 'follow'), ('string', 'g'))))
+  $ cat log.nodes
+  nodetag 2
+  nodetag 1
+  nodetag 0
+  $ hg up -q tip
+  $ testlog -f g
+  ('group', ('group', ('func', ('symbol', 'follow'), ('string', 'g'))))
+  $ cat log.nodes
+  nodetag 3
+  nodetag 2
+  nodetag 0
+
+Test --follow and multiple files
+
+  $ testlog -f g e
+  ('group', ('group', ('or', ('func', ('symbol', 'follow'), ('string', 'g')), ('func', ('symbol', 'follow'), ('string', 'e')))))
+  $ cat log.nodes
+  nodetag 4
+  nodetag 3
+  nodetag 2
+  nodetag 1
+  nodetag 0
+
+Test --follow-first
+
+  $ hg up -q 3
+  $ echo ee > e
+  $ hg ci -Am "add another e" e
+  created new head
+  $ hg merge --tool internal:other 4
+  0 files updated, 1 files merged, 1 files removed, 0 files unresolved
+  (branch merge, don't forget to commit)
+  $ echo merge > e
+  $ hg ci -m "merge 5 and 4"
+  $ testlog --follow-first
+  ('group', ('func', ('symbol', '_followfirst'), None))
 
-Test multiple revision specifications are correctly handled
+Cannot compare with log --follow-first FILE as it never worked
 
-  $ hg log -G -r 27 -r 25 -r 21 -r 34 -r 32 -r 31 --template '{rev}\n'
-  o  34
-  |
-  o    32
+  $ hg log -G --print-revset --follow-first e
+  ('group', ('group', ('func', ('symbol', '_followfirst'), ('string', 'e'))))
+  $ hg log -G --follow-first e --template '{rev} {desc|firstline}\n'
+  @    6 merge 5 and 4
+  |\
+  o |  5 add another e
+  | |
+
+Test --copies
+
+  $ hg log -G --copies --template "{rev} {desc|firstline} \
+  >   copies: {file_copies_switch}\n"
+  @    6 merge 5 and 4   copies:
   |\
-  | o    31
-  | |\
-  o | |  27
-  |/ /
-  | o  25
+  | o  5 add another e   copies:
+  | |
+  o |  4 mv dir/b e   copies: e (dir/b)
   |/
-  o    21
-  |\
+  o  3 mv a b; add d   copies: b (a)g (f)
+  |
+  o  2 mv b dir/b   copies: dir/b (b)
+  |
+  o  1 copy a b   copies: b (a)g (f)
+  |
+  o  0 add a   copies:
+  
+Test "set:..." and parent revision
+
+  $ hg up -q 4
+  $ testlog "set:copied()"
+  ('group', ('group', ('func', ('symbol', '_matchfiles'), ('list', ('string', 'r:'), ('string', 'p:set:copied()')))))
+  $ testlog --include "set:copied()"
+  ('group', ('group', ('func', ('symbol', '_matchfiles'), ('list', ('string', 'r:'), ('string', 'i:set:copied()')))))
+  $ testlog -r "sort(file('set:copied()'), -rev)"
+  ('group', ('group', ('func', ('symbol', 'sort'), ('list', ('func', ('symbol', 'file'), ('string', 'set:copied()')), ('negate', ('symbol', 'rev'))))))
+
+Test --removed
+
+  $ testlog --removed
+  ('func', ('symbol', 'all'), None)
+  $ testlog --removed a
+  ('group', ('group', ('func', ('symbol', '_matchfiles'), ('list', ('string', 'r:'), ('string', 'p:a')))))
+  $ testlog --removed --follow a
+  abort: can only follow copies/renames for explicit filenames
+  abort: can only follow copies/renames for explicit filenames
+  abort: can only follow copies/renames for explicit filenames
+
+Test --patch and --stat with --follow and --follow-first
+
+  $ hg up -q 3
+  $ hg log -G --git --patch b
+  o  changeset:   1:216d4c92cf98
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     copy a b
+  |
+  |  diff --git a/a b/b
+  |  copy from a
+  |  copy to b
+  |
+
+  $ hg log -G --git --stat b
+  o  changeset:   1:216d4c92cf98
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     copy a b
+  |
+  |   a |  0
+  |   1 files changed, 0 insertions(+), 0 deletions(-)
+  |
+
+  $ hg log -G --git --patch --follow b
+  o  changeset:   1:216d4c92cf98
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     copy a b
+  |
+  |  diff --git a/a b/b
+  |  copy from a
+  |  copy to b
+  |
+  o  changeset:   0:f8035bb17114
+     user:        test
+     date:        Thu Jan 01 00:00:00 1970 +0000
+     summary:     add a
+  
+     diff --git a/a b/a
+     new file mode 100644
+     --- /dev/null
+     +++ b/a
+     @@ -0,0 +1,1 @@
+     +a
+  
+
+  $ hg log -G --git --stat --follow b
+  o  changeset:   1:216d4c92cf98
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     copy a b
+  |
+  |   a |  0
+  |   1 files changed, 0 insertions(+), 0 deletions(-)
+  |
+  o  changeset:   0:f8035bb17114
+     user:        test
+     date:        Thu Jan 01 00:00:00 1970 +0000
+     summary:     add a
+  
+      a |  1 +
+      1 files changed, 1 insertions(+), 0 deletions(-)
+  
+
+  $ hg up -q 6
+  $ hg log -G --git --patch --follow-first e
+  @    changeset:   6:fc281d8ff18d
+  |\   tag:         tip
+  | |  parent:      5:99b31f1c2782
+  | |  parent:      4:17d952250a9d
+  | |  user:        test
+  | |  date:        Thu Jan 01 00:00:00 1970 +0000
+  | |  summary:     merge 5 and 4
+  | |
+  | |  diff --git a/e b/e
+  | |  --- a/e
+  | |  +++ b/e
+  | |  @@ -1,1 +1,1 @@
+  | |  -ee
+  | |  +merge
+  | |
+  o |  changeset:   5:99b31f1c2782
+  | |  parent:      3:5918b8d165d1
+  | |  user:        test
+  | |  date:        Thu Jan 01 00:00:00 1970 +0000
+  | |  summary:     add another e
+  | |
+  | |  diff --git a/e b/e
+  | |  new file mode 100644
+  | |  --- /dev/null
+  | |  +++ b/e
+  | |  @@ -0,0 +1,1 @@
+  | |  +ee
+  | |
--- a/tests/test-graft.t	Tue Feb 28 23:47:46 2012 +0200
+++ b/tests/test-graft.t	Tue Feb 28 21:17:53 2012 -0600
@@ -114,7 +114,6 @@
   grafting revision 1
     searching for copies back to rev 1
     unmatched files in local:
-     a.orig
      b
     all copies found (* = to merge, ! = divergent):
      b -> a *
@@ -130,8 +129,6 @@
    b: copy a:b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3
   grafting revision 5
     searching for copies back to rev 1
-    unmatched files in local:
-     a.orig
   resolving manifests
    overwrite: False, partial: False
    ancestor: 4c60f11aa304, local: 6f5ea6ac8b70+, remote: 97f8bfe72746
@@ -141,8 +138,6 @@
   e
   grafting revision 4
     searching for copies back to rev 1
-    unmatched files in local:
-     a.orig
   resolving manifests
    overwrite: False, partial: False
    ancestor: 4c60f11aa304, local: 77eb504366ab+, remote: 9c233e8e184d
--- a/tests/test-hgweb-commands.t	Tue Feb 28 23:47:46 2012 +0200
+++ b/tests/test-hgweb-commands.t	Tue Feb 28 21:17:53 2012 -0600
@@ -24,6 +24,14 @@
   marked working directory as branch stable
   (branches are permanent and global, did you want a bookmark?)
   $ hg ci -Ambranch
+  $ hg branch unstable
+  marked working directory as branch unstable
+  (branches are permanent and global, did you want a bookmark?)
+  $ hg ci -Ambranch
+  $ echo [graph] >> .hg/hgrc
+  $ echo default.width = 3 >> .hg/hgrc
+  $ echo stable.width = 3 >> .hg/hgrc
+  $ echo stable.color = FF0000 >> .hg/hgrc
   $ hg serve --config server.uncompressed=False -n test -p $HGPORT -d --pid-file=hg.pid -E errors.log
   $ cat hg.pid >> $DAEMON_PIDS
 
@@ -43,6 +51,22 @@
   
    <entry>
     <title>branch</title>
+    <id>http://*:$HGPORT/#changeset-ba87b23d29ca67a305625d81a20ac279c1e3f444</id> (glob)
+    <link href="http://*:$HGPORT/rev/ba87b23d29ca"/> (glob)
+    <author>
+     <name>test</name>
+     <email>&#116;&#101;&#115;&#116;</email>
+    </author>
+    <updated>1970-01-01T00:00:00+00:00</updated>
+    <published>1970-01-01T00:00:00+00:00</published>
+    <content type="xhtml">
+     <div xmlns="http://www.w3.org/1999/xhtml">
+      <pre xml:space="preserve">branch</pre>
+     </div>
+    </content>
+   </entry>
+   <entry>
+    <title>branch</title>
     <id>http://*:$HGPORT/#changeset-1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe</id> (glob)
     <link href="http://*:$HGPORT/rev/1d22e65f027e"/> (glob)
     <author>
@@ -105,6 +129,22 @@
   
    <entry>
     <title>branch</title>
+    <id>http://*:$HGPORT/#changeset-ba87b23d29ca67a305625d81a20ac279c1e3f444</id> (glob)
+    <link href="http://*:$HGPORT/rev/ba87b23d29ca"/> (glob)
+    <author>
+     <name>test</name>
+     <email>&#116;&#101;&#115;&#116;</email>
+    </author>
+    <updated>1970-01-01T00:00:00+00:00</updated>
+    <published>1970-01-01T00:00:00+00:00</published>
+    <content type="xhtml">
+     <div xmlns="http://www.w3.org/1999/xhtml">
+      <pre xml:space="preserve">branch</pre>
+     </div>
+    </content>
+   </entry>
+   <entry>
+    <title>branch</title>
     <id>http://*:$HGPORT/#changeset-1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe</id> (glob)
     <link href="http://*:$HGPORT/rev/1d22e65f027e"/> (glob)
     <author>
@@ -208,14 +248,14 @@
   </div>
   <ul>
   <li class="active">log</li>
-  <li><a href="/graph/1d22e65f027e">graph</a></li>
+  <li><a href="/graph/ba87b23d29ca">graph</a></li>
   <li><a href="/tags">tags</a></li>
   <li><a href="/bookmarks">bookmarks</a></li>
   <li><a href="/branches">branches</a></li>
   </ul>
   <ul>
-  <li><a href="/rev/1d22e65f027e">changeset</a></li>
-  <li><a href="/file/1d22e65f027e">browse</a></li>
+  <li><a href="/rev/ba87b23d29ca">changeset</a></li>
+  <li><a href="/file/ba87b23d29ca">browse</a></li>
   </ul>
   <ul>
   
@@ -237,9 +277,9 @@
   </form>
   
   <div class="navigate">
-  <a href="/shortlog/2?revcount=30">less</a>
-  <a href="/shortlog/2?revcount=120">more</a>
-  | rev 2: <a href="/shortlog/2ef0ac749a14">(0)</a> <a href="/shortlog/tip">tip</a> 
+  <a href="/shortlog/3?revcount=30">less</a>
+  <a href="/shortlog/3?revcount=120">more</a>
+  | rev 3: <a href="/shortlog/2ef0ac749a14">(0)</a> <a href="/shortlog/tip">tip</a> 
   </div>
   
   <table class="bigtable">
@@ -251,14 +291,19 @@
    <tr class="parity0">
     <td class="age">Thu, 01 Jan 1970 00:00:00 +0000</td>
     <td class="author">test</td>
-    <td class="description"><a href="/rev/1d22e65f027e">branch</a><span class="branchhead">stable</span> <span class="tag">tip</span> <span class="tag">something</span> </td>
+    <td class="description"><a href="/rev/ba87b23d29ca">branch</a><span class="branchhead">unstable</span> <span class="tag">tip</span> <span class="tag">something</span> </td>
    </tr>
    <tr class="parity1">
     <td class="age">Thu, 01 Jan 1970 00:00:00 +0000</td>
     <td class="author">test</td>
+    <td class="description"><a href="/rev/1d22e65f027e">branch</a><span class="branchhead">stable</span> </td>
+   </tr>
+   <tr class="parity0">
+    <td class="age">Thu, 01 Jan 1970 00:00:00 +0000</td>
+    <td class="author">test</td>
     <td class="description"><a href="/rev/a4f92ed23982">Added tag 1.0 for changeset 2ef0ac749a14</a><span class="branchhead">default</span> </td>
    </tr>
-   <tr class="parity0">
+   <tr class="parity1">
     <td class="age">Thu, 01 Jan 1970 00:00:00 +0000</td>
     <td class="author">test</td>
     <td class="description"><a href="/rev/2ef0ac749a14">base</a><span class="tag">1.0</span> <span class="tag">anotherthing</span> </td>
@@ -267,9 +312,9 @@
   </table>
   
   <div class="navigate">
-  <a href="/shortlog/2?revcount=30">less</a>
-  <a href="/shortlog/2?revcount=120">more</a>
-  | rev 2: <a href="/shortlog/2ef0ac749a14">(0)</a> <a href="/shortlog/tip">tip</a> 
+  <a href="/shortlog/3?revcount=30">less</a>
+  <a href="/shortlog/3?revcount=120">more</a>
+  | rev 3: <a href="/shortlog/2ef0ac749a14">(0)</a> <a href="/shortlog/tip">tip</a> 
   </div>
   
   </div>
@@ -637,18 +682,19 @@
   $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/raw-tags'
   200 Script output follows
   
-  tip	1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe
+  tip	ba87b23d29ca67a305625d81a20ac279c1e3f444
   1.0	2ef0ac749a14e4f57a5a822464a0902c6f7f448f
   $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/raw-branches'
   200 Script output follows
   
-  stable	1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe	open
+  unstable	ba87b23d29ca67a305625d81a20ac279c1e3f444	open
+  stable	1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe	inactive
   default	a4f92ed23982be056b9852de5dfe873eaac7f0de	inactive
   $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/raw-bookmarks'
   200 Script output follows
   
   anotherthing	2ef0ac749a14e4f57a5a822464a0902c6f7f448f
-  something	1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe
+  something	ba87b23d29ca67a305625d81a20ac279c1e3f444
   $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/summary/?style=gitweb'
   200 Script output follows
   
@@ -688,7 +734,7 @@
   <a href="/tags?style=gitweb">tags</a> |
   <a href="/bookmarks?style=gitweb">bookmarks</a> |
   <a href="/branches?style=gitweb">branches</a> |
-  <a href="/file/1d22e65f027e?style=gitweb">files</a> |
+  <a href="/file/ba87b23d29ca?style=gitweb">files</a> |
   <a href="/help?style=gitweb">help</a>
   <br/>
   </div>
@@ -707,9 +753,23 @@
   <td class="age"><i class="age">Thu, 01 Jan 1970 00:00:00 +0000</i></td>
   <td><i>test</i></td>
   <td>
+  <a class="list" href="/rev/ba87b23d29ca?style=gitweb">
+  <b>branch</b>
+  <span class="logtags"><span class="branchtag" title="unstable">unstable</span> <span class="tagtag" title="tip">tip</span> <span class="bookmarktag" title="something">something</span> </span>
+  </a>
+  </td>
+  <td class="link" nowrap>
+  <a href="/rev/ba87b23d29ca?style=gitweb">changeset</a> |
+  <a href="/file/ba87b23d29ca?style=gitweb">files</a>
+  </td>
+  </tr>
+  <tr class="parity1">
+  <td class="age"><i class="age">Thu, 01 Jan 1970 00:00:00 +0000</i></td>
+  <td><i>test</i></td>
+  <td>
   <a class="list" href="/rev/1d22e65f027e?style=gitweb">
   <b>branch</b>
-  <span class="logtags"><span class="branchtag" title="stable">stable</span> <span class="tagtag" title="tip">tip</span> <span class="bookmarktag" title="something">something</span> </span>
+  <span class="logtags"><span class="branchtag" title="stable">stable</span> </span>
   </a>
   </td>
   <td class="link" nowrap>
@@ -717,7 +777,7 @@
   <a href="/file/1d22e65f027e?style=gitweb">files</a>
   </td>
   </tr>
-  <tr class="parity1">
+  <tr class="parity0">
   <td class="age"><i class="age">Thu, 01 Jan 1970 00:00:00 +0000</i></td>
   <td><i>test</i></td>
   <td>
@@ -731,7 +791,7 @@
   <a href="/file/a4f92ed23982?style=gitweb">files</a>
   </td>
   </tr>
-  <tr class="parity0">
+  <tr class="parity1">
   <td class="age"><i class="age">Thu, 01 Jan 1970 00:00:00 +0000</i></td>
   <td><i>test</i></td>
   <td>
@@ -777,11 +837,11 @@
   </tr>
   <tr class="parity1">
   <td class="age"><i class="age">Thu, 01 Jan 1970 00:00:00 +0000</i></td>
-  <td><a class="list" href="/rev/1d22e65f027e?style=gitweb"><b>something</b></a></td>
+  <td><a class="list" href="/rev/ba87b23d29ca?style=gitweb"><b>something</b></a></td>
   <td class="link">
-  <a href="/rev/1d22e65f027e?style=gitweb">changeset</a> |
-  <a href="/log/1d22e65f027e?style=gitweb">changelog</a> |
-  <a href="/file/1d22e65f027e?style=gitweb">files</a>
+  <a href="/rev/ba87b23d29ca?style=gitweb">changeset</a> |
+  <a href="/log/ba87b23d29ca?style=gitweb">changelog</a> |
+  <a href="/file/ba87b23d29ca?style=gitweb">files</a>
   </td>
   </tr>
   <tr class="light"><td colspan="3"><a class="list" href="/bookmarks?style=gitweb">...</a></td></tr>
@@ -792,6 +852,16 @@
   
   <tr class="parity0">
   <td class="age"><i class="age">Thu, 01 Jan 1970 00:00:00 +0000</i></td>
+  <td><a class="list" href="/shortlog/ba87b23d29ca?style=gitweb"><b>ba87b23d29ca</b></a></td>
+  <td class="">unstable</td>
+  <td class="link">
+  <a href="/changeset/ba87b23d29ca?style=gitweb">changeset</a> |
+  <a href="/log/ba87b23d29ca?style=gitweb">changelog</a> |
+  <a href="/file/ba87b23d29ca?style=gitweb">files</a>
+  </td>
+  </tr>
+  <tr class="parity1">
+  <td class="age"><i class="age">Thu, 01 Jan 1970 00:00:00 +0000</i></td>
   <td><a class="list" href="/shortlog/1d22e65f027e?style=gitweb"><b>1d22e65f027e</b></a></td>
   <td class="">stable</td>
   <td class="link">
@@ -800,7 +870,7 @@
   <a href="/file/1d22e65f027e?style=gitweb">files</a>
   </td>
   </tr>
-  <tr class="parity1">
+  <tr class="parity0">
   <td class="age"><i class="age">Thu, 01 Jan 1970 00:00:00 +0000</i></td>
   <td><a class="list" href="/shortlog/a4f92ed23982?style=gitweb"><b>a4f92ed23982</b></a></td>
   <td class="">default</td>
@@ -861,17 +931,17 @@
   <div class="page_nav">
   <a href="/summary?style=gitweb">summary</a> |
   <a href="/shortlog?style=gitweb">shortlog</a> |
-  <a href="/log/2?style=gitweb">changelog</a> |
+  <a href="/log/3?style=gitweb">changelog</a> |
   graph |
   <a href="/tags?style=gitweb">tags</a> |
   <a href="/bookmarks?style=gitweb">bookmarks</a> |
   <a href="/branches?style=gitweb">branches</a> |
-  <a href="/file/1d22e65f027e?style=gitweb">files</a> |
+  <a href="/file/ba87b23d29ca?style=gitweb">files</a> |
   <a href="/help?style=gitweb">help</a>
   <br/>
-  <a href="/graph/2?style=gitweb&revcount=30">less</a>
-  <a href="/graph/2?style=gitweb&revcount=120">more</a>
-  | <a href="/graph/2ef0ac749a14?style=gitweb">(0)</a> <a href="/graph/2ef0ac749a14?style=gitweb">-2</a> <a href="/graph/tip?style=gitweb">tip</a> <br/>
+  <a href="/graph/3?style=gitweb&revcount=30">less</a>
+  <a href="/graph/3?style=gitweb&revcount=120">more</a>
+  | <a href="/graph/2ef0ac749a14?style=gitweb">(0)</a> <a href="/graph/2ef0ac749a14?style=gitweb">-3</a> <a href="/graph/tip?style=gitweb">tip</a> <br/>
   </div>
   
   <div class="title">&nbsp;</div>
@@ -880,27 +950,17 @@
   
   <div id="wrapper">
   <ul id="nodebgs"></ul>
-  <canvas id="graph" width="480" height="129"></canvas>
+  <canvas id="graph" width="480" height="168"></canvas>
   <ul id="graphnodes"></ul>
   </div>
   
   <script>
   <!-- hide script content
   
-  var data = [["1d22e65f027e", [0, 1], [[0, 0, 1]], "branch", "test", "1970-01-01", ["stable", true], ["tip"], ["something"]], ["a4f92ed23982", [0, 1], [[0, 0, 1]], "Added tag 1.0 for changeset 2ef0ac749a14", "test", "1970-01-01", ["default", true], [], []], ["2ef0ac749a14", [0, 1], [], "base", "test", "1970-01-01", ["default", false], ["1.0"], ["anotherthing"]]];
+  var data = [["ba87b23d29ca", [0, 1], [[0, 0, 1, 3, "FF0000"]], "branch", "test", "1970-01-01", ["unstable", true], ["tip"], ["something"]], ["1d22e65f027e", [0, 1], [[0, 0, 1, 3, ""]], "branch", "test", "1970-01-01", ["stable", true], [], []], ["a4f92ed23982", [0, 1], [[0, 0, 1, 3, ""]], "Added tag 1.0 for changeset 2ef0ac749a14", "test", "1970-01-01", ["default", true], [], []], ["2ef0ac749a14", [0, 1], [], "base", "test", "1970-01-01", ["default", false], ["1.0"], ["anotherthing"]]];
   var graph = new Graph();
   graph.scale(39);
   
-  graph.edge = function(x0, y0, x1, y1, color) {
-  	
-  	this.setColor(color, 0.0, 0.65);
-  	this.ctx.beginPath();
-  	this.ctx.moveTo(x0, y0);
-  	this.ctx.lineTo(x1, y1);
-  	this.ctx.stroke();
-  	
-  }
-  
   var revlink = '<li style="_STYLE"><span class="desc">';
   revlink += '<a class="list" href="/rev/_NODEID?style=gitweb" title="_NODEID"><b>_DESC</b></a>';
   revlink += '</span> _TAGS';
@@ -960,9 +1020,9 @@
   </script>
   
   <div class="page_nav">
-  <a href="/graph/2?style=gitweb&revcount=30">less</a>
-  <a href="/graph/2?style=gitweb&revcount=120">more</a>
-  | <a href="/graph/2ef0ac749a14?style=gitweb">(0)</a> <a href="/graph/2ef0ac749a14?style=gitweb">-2</a> <a href="/graph/tip?style=gitweb">tip</a> 
+  <a href="/graph/3?style=gitweb&revcount=30">less</a>
+  <a href="/graph/3?style=gitweb&revcount=120">more</a>
+  | <a href="/graph/2ef0ac749a14?style=gitweb">(0)</a> <a href="/graph/2ef0ac749a14?style=gitweb">-3</a> <a href="/graph/tip?style=gitweb">tip</a> 
   </div>
   
   <script type="text/javascript">process_dates()</script>
@@ -991,7 +1051,7 @@
   $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=heads'
   200 Script output follows
   
-  1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe
+  ba87b23d29ca67a305625d81a20ac279c1e3f444
 
 branches
 
@@ -1005,10 +1065,11 @@
   $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=changegroup&roots=0000000000000000000000000000000000000000'
   200 Script output follows
   
-  x\x9c\xbdTMHUA\x14\xbe\xa8\xf9\xec\xda&\x10\x11*\xb8\x88\x81\x99\xbef\xe6\xce\xbdw\xc6\xf2a\x16E\x1b\x11[%\x98\xcc\xaf\x8f\x8c\xf7\xc0\xf7\x82 (esc)
-  4\x11KP2m\x95\xad*\xabE\x05AP\xd0\xc22Z\x14\xf9\x03\xb9j\xa3\x9b$\xa4MJ\xb4\x90\xc0\x9a\x9bO0\x10\xdf\x13\xa2\x81\x0f\x869g\xe6|\xe7\x9c\xef\x8ceY\xf7\xa2KO\xd2\xb7K\x16~\\n\xe9\xad\x90w\x86\xab\x93W\x8e\xdf\xb0r\\Y\xee6(\xa2)\xf6\x95\xc6\x01\xe4\x1az\x80R\xe8kN\x98\xe7R\xa4\xa9K@\xe0!A\xb4k\xa7U*m\x03\x07\xd8\x92\x1d\xd2\xc9\xa4\x1d\xc2\xe6,\xa5\xcc+\x1f\xef\xafDgi\xef\xab\x1d\x1d\xb7\x9a\xe7[W\xfbc\x8f\xde-\xcd\xe7\xcaz\xb3\xbb\x19\xd3\x81\x10>c>\x08\x00"X\x11\xc2\x84@\xd2\xe7B*L\x00\x01P\x04R\xc3@\xbaB0\xdb8#\x83:\x83\xa2h\xbc=\xcd\xdaS\xe1Y,L\xd3\xa0\xf2\xa8\x94J:\xe6\xd8\x81Q\xe0\xe8d\xa7#\xe2,\xd1\xaeR*\xed \xa5\x01\x13\x01\xa6\x0cb\xe3;\xbe\xaf\xfcK[^wK\xe1N\xaf\xbbk\xe8B\xd1\xf4\xc1\x07\xb3\xab[\x10\xfdkmvwcB\xa6\xa4\xd4G\xc4D\xc2\x141\xad\x91\x10\x00\x08J\x81\xcb}\xee	\xee+W\xba\x8a\x80\x90|\xd4\xa0\xd6\xa0\xd4T\xde\xe1\x9d,!\xe2\xb5\xa94\xe3\xe7\xd5\x9f\x06\x18\xcba\x03aP\xb8f\xcd\x04\x1a_\\9\xf1\xed\xe4\x9e\xe5\xa6\xd1\xd2\x9f\x03\xa7o\xae\x90H\xf3\xfb\xef\xffH3\xadk (esc)
-  \xb0\x90\x92\x88\xb9\x14"\x068\xc2\x1e@\x00\xbb\x8a)\xd3'\x859 (esc)
-  \xa8\x80\x84S \xa5\xbd-g\x13`\xe4\xdc\xc3H^\xdf\xe2\xc0TM\xc7\xf4BO\xcf\xde\xae\xe5\xae#\x1frM(K\x97`F\x19\x16s\x05GD\xb9\x01\xc1\x00+\x8c|\x9fp\xc11\xf0\x14\x00\x9cJ\x82<\xe0\x12\x9f\xc1\x90\xd0\xf5\xc8\x19>Pr\xaa\xeaW\xf5\xc4\xae\xd1\xfc\x17\xcf'\x13u\xb1\x9e\xcdHnC\x0e\xcc`\xc8\xa0&\xac\x0e\xf1|\x8c\x10$\xc4\x8c\xa2p\x05`\xdc\x08 \x80\xc4\xd7Rr-\x94\x10\x102\xedi;\xf3f\xf1z\x16\x86\xdb\xd8d\xe5\xe7\x8b\xf5\x8d\rzp\xb2\xfe\xac\xf5\xf2\xd3\xfe\xfckws\xedt\x96b\xd5l\x1c\x0b\x85\xb5\x170\x8f\x11\x84\xb0\x8f\x19\xa0\x00	_\x07\x1ac\xa2\xc3\x89Z\xe7\x96\xf9 \xccNFg\xc7F\xaa\x8a+\x9a\x9cc_\x17\x1b\x17\x9e]z38<\x97+\xb5,",\xc8\xc8?\\\x91\xff\x17.~U\x96\x97\xf5%\xdeN<\x8e\xf5\x97%\xe7^\xcfL\xed~\xda\x96k\xdc->\x86\x02\x83"\x96H\xa6\xe3\xaas=-\xeb7\xe5\xda\x8f\xbc (no-eol) (esc)
+  x\x9c\xbdTMHTQ\x14\x1e\xfc\xef\xd9&\x10\x11*x\x88\x81\x9aN\xf7\xddw\xdf{\xf7Y\x0efR\xb4\x11\xb1U\x82\xc5\xfd\x9d!c\x06\x9c'd\xa0\x99X\x82\x92i\xablUZ-*\x08\x84\x82\x02KkQ\xf8\x13\xe4\xaa\x8dn\x94\x906)\xd5B\x02\xeb\xbe\x9c\x01\x85\xc9\x996\x1d\xf8x\x97{\xefy\xe7;\xe7|\xe7\x06\x02\x81\xb1\xe0\xda\x13\xefN\xd1\xca\x8f\xcb-\xbde\xfc\xeepU\xecJ\xc3\xcd@\x86\x96\xc6\xb7^`\xe9"[H\xe4\x18T\x1a\x16p]\xc3\x96\x14\x13\xcbt\xa1tM\x0c\x1c\x0b2,M\xcd\x13qO\x03:\xd089"c1\xcd\x87FI\\\xa8\xbf|\xbc\xbf\x11\\p{_\xe5\xb6\xddn^j\xdd\xec\x0f=z\xb7\xb6\x94)\xebT\xbe\x89\xa3 (esc)
+  \x1f6!6p\x00\xc4H`L\x18\x83\xdc\xa6\x8c\x0b\x84\x01\x06\x06s\xb84\x1cn2F4u\x19*\xd4*\x14\x04#a\x8f\x84\xe3\xfe^\xc8OS\xa1\xfc8\xe7\x82\xebj[7\x82@\x97\xb1v\x9dEH4,\xe2\xc2\xd3\xa1\x90\x800\x07\xb9\xc4@\xea\xee\xe4\xc1\xd2\xcf\xe7\xb3\xba[\xf2\xf6X\xdd]C\x1d\x05\xf3\x87\x1f,l\xeeBt\x87\xa5\xf2\xdd\x9e\x90*\xa9kC\xac"!\x17\x12)!c\x000\xd7\x05&\xb5\xa9\xc5\xa8-Ln (esc)
+  \x0c|\xf2A\x85\x1a\x85bUy\x9d\xb6\x93(\x8b\xd4\xc4=B/\x8a?\rP'G\x15\x98B\xde\xd6\xa9Zy/\xfb'j+f\xc2\xe3\xb9\xb4\xf5\xea\x98\xf6\xa6sz\xf9{\xc3.\xa4vX*\xdf\x04\x0f\xff[\xb4\x8dGG4\xc1$\xe1:\xb9\xbaq\xf2\xeb\xa9\xfd\xebM\xa3\xc5?\x07\xce\xdc\xda\xc0\xf9\xcd\xef\xbf\xa5\xd3g\xd2\xd2\xa8\xa5uKu\x01(8$\xa6k@\x02(D\x16\x80\x00\x99\x82\x08\xa5\r\x81(t\\f`\xea\x02\xce\xb5\x7f\xba\xac\x02\x8c\\x\x98\x9f\xd5\xb7:0W\xdd6\xbf\xd2\xd3s\xa0k\xbd\xeb\xd8L\xa6	\xa5Q\x86\x91Pc\x80\x98\x8cB,L\x07#\x80\x04\x82\xb6\x8d)\xa3\x08X\x02\x00\xear\x0c-`b\x9b\x18>\xa1\x1b\xf9g\xe9@\xd1\xe9\xca_US{G\xb3\x9f?\x9b\x8d\xd6\x86zR\x91LE\xe8/\xdd& (esc)
+  C
+  \xd5~u\xb0e#\x08\r\x8c\xd5\xf83\x93\x01B\x95\xe8\x1c\x03\xdb\x92s*\x99`\xcc0\x88\xb4d\xb2\xbd\x85\xc9,\x14\xb7\xf1\xd9\xf2\xe5Ku\x8d\xf5rp\xb6\xee\\\xe0\xc5\xa7C\xd9\xd7\xefe\xda\xe94\xc5\xaa\xde>\x8a\x02I\xcb!\x16\xc1\x10"\x1b\x11\xe0\x02\xc8l\xe9H\x84\xb0\xf4\xa78\xc9-\xf1(\xa9\x15\x0f.\x8c\x8fT\x16\x965\xe9'\xbe\xac6\xaeLtN\x0f\x0e/fJ-\x8d\x08s\x12#\xe7[\xfe\xff\x0b\x17\xb9\xc6KK\xfa\xa2o\xa7\x1e\x87\xfaKb\x8b\xaf?\xcc\xed{z>\xd3\xb8\xbb\xcc}\x8eB\x01\x89\xc6\xbc\x88hO\xa6\x15\xf8\rr4\xb3\xe5 (no-eol) (esc)
 
 stream_out
 
@@ -1153,7 +1214,7 @@
 
   $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/graph/' \
   >     | grep '^var data ='
-  var data = [["40b4d6888e92", [0, 1], [[0, 0, 1]], "\u80fd", "test", "1970-01-01", ["stable", true], ["tip"], ["something"]], ["1d22e65f027e", [0, 1], [[0, 0, 1]], "branch", "test", "1970-01-01", ["stable", false], [], []], ["a4f92ed23982", [0, 1], [[0, 0, 1]], "Added tag 1.0 for changeset 2ef0ac749a14", "test", "1970-01-01", ["default", true], [], []], ["2ef0ac749a14", [0, 1], [], "base", "test", "1970-01-01", ["default", false], ["1.0"], ["anotherthing"]]];
+  var data = [["548001d11f45", [0, 1], [[0, 0, 1, -1, ""]], "\u80fd", "test", "1970-01-01", ["unstable", true], ["tip"], ["something"]], ["ba87b23d29ca", [0, 1], [[0, 0, 1, 3, "FF0000"]], "branch", "test", "1970-01-01", ["unstable", false], [], []], ["1d22e65f027e", [0, 1], [[0, 0, 1, 3, ""]], "branch", "test", "1970-01-01", ["stable", true], [], []], ["a4f92ed23982", [0, 1], [[0, 0, 1, 3, ""]], "Added tag 1.0 for changeset 2ef0ac749a14", "test", "1970-01-01", ["default", true], [], []], ["2ef0ac749a14", [0, 1], [], "base", "test", "1970-01-01", ["default", false], ["1.0"], ["anotherthing"]]];
 
 ERRORS ENCOUNTERED
 
--- a/tests/test-hgweb-empty.t	Tue Feb 28 23:47:46 2012 +0200
+++ b/tests/test-hgweb-empty.t	Tue Feb 28 21:17:53 2012 -0600
@@ -250,16 +250,6 @@
   var graph = new Graph();
   graph.scale(39);
   
-  graph.edge = function(x0, y0, x1, y1, color) {
-  	
-  	this.setColor(color, 0.0, 0.65);
-  	this.ctx.beginPath();
-  	this.ctx.moveTo(x0, y0);
-  	this.ctx.lineTo(x1, y1);
-  	this.ctx.stroke();
-  	
-  }
-  
   var revlink = '<li style="_STYLE"><span class="desc">';
   revlink += '<a href="/rev/_NODEID" title="_NODEID">_DESC</a>';
   revlink += '</span>_TAGS<span class="info">_DATE, by _USER</span></li>';
--- a/tests/test-issue612.t	Tue Feb 28 23:47:46 2012 +0200
+++ b/tests/test-issue612.t	Tue Feb 28 21:17:53 2012 -0600
@@ -24,11 +24,11 @@
 
   $ hg merge
   merging src/a.c and source/a.c to source/a.c
-  1 files updated, 1 files merged, 0 files removed, 0 files unresolved
+  0 files updated, 1 files merged, 0 files removed, 0 files unresolved
   (branch merge, don't forget to commit)
 
   $ hg status
   M source/a.c
   R src/a.c
-  ? source/a.o
+  ? src/a.o
 
--- a/tests/test-mq-subrepo-svn.t	Tue Feb 28 23:47:46 2012 +0200
+++ b/tests/test-mq-subrepo-svn.t	Tue Feb 28 21:17:53 2012 -0600
@@ -37,7 +37,6 @@
   $ hg status -S -X '**/format'
   A .hgsub
   $ hg qnew -m0 0.diff
-  committing subrepository sub
   $ cd sub
   $ echo a > a
   $ svn add a
--- a/tests/test-mq-subrepo.t	Tue Feb 28 23:47:46 2012 +0200
+++ b/tests/test-mq-subrepo.t	Tue Feb 28 21:17:53 2012 -0600
@@ -105,7 +105,6 @@
   % update substate when adding .hgsub w/clean updated subrepo
   A .hgsub
   % qnew -m0 0.diff
-  committing subrepository sub
   path sub
    source   sub
    revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
@@ -121,7 +120,6 @@
   % update substate when modifying .hgsub w/clean updated subrepo
   M .hgsub
   % qnew -m1 1.diff
-  committing subrepository sub2
   path sub
    source   sub
    revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
@@ -166,7 +164,6 @@
   % update substate when adding .hgsub w/clean updated subrepo
   A .hgsub
   % qrefresh
-  committing subrepository sub
   path sub
    source   sub
    revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
@@ -183,7 +180,6 @@
   % update substate when modifying .hgsub w/clean updated subrepo
   M .hgsub
   % qrefresh
-  committing subrepository sub2
   path sub
    source   sub
    revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
@@ -225,7 +221,6 @@
   $ echo sub = sub > .hgsub
   $ hg add .hgsub
   $ hg qnew -m0 0.diff
-  committing subrepository sub
   $ hg debugsub
   path sub
    source   sub
@@ -277,7 +272,6 @@
   diff --git a/.hgsub b/.hgsub
   new file mode 100644
   examine changes to '.hgsub'? [Ynsfdaq?] 
-  committing subrepository sub
   path sub
    source   sub
    revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
@@ -310,7 +304,6 @@
    sub = sub
   +sub2 = sub2
   record this change to '.hgsub'? [Ynsfdaq?] 
-  committing subrepository sub2
   path sub
    source   sub
    revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
@@ -360,4 +353,3 @@
   $ echo sub = sub >> .hgsub
   $ hg add .hgsub
   $ hg qnew 0.diff
-  committing subrepository sub
--- a/tests/test-mq.t	Tue Feb 28 23:47:46 2012 +0200
+++ b/tests/test-mq.t	Tue Feb 28 21:17:53 2012 -0600
@@ -70,7 +70,7 @@
    qgoto         push or pop patches until named patch is at top of stack
    qguard        set or print guards for a patch
    qheader       print the header of the topmost or specified patch
-   qimport       import a patch
+   qimport       import a patch or existing changeset
    qnew          create a new patch
    qnext         print the name of the next pushable patch
    qpop          pop the current patch off the stack
--- a/tests/test-phases.t	Tue Feb 28 23:47:46 2012 +0200
+++ b/tests/test-phases.t	Tue Feb 28 21:17:53 2012 -0600
@@ -402,3 +402,34 @@
   |
   o  0 public A
   
+test partial failure
+
+  $ hg phase --public 7
+  $ hg phase --draft '5 or 7'
+  cannot move 1 changesets to a more permissive phase, use --force
+  phase changed for 1 changesets
+  [1]
+  $ hg log -G --template "{rev} {phase} {desc}\n"
+  @    7 public merge B' and E
+  |\
+  | o  6 public B'
+  | |
+  +---o  5 draft H
+  | |
+  o |  4 public E
+  | |
+  o |  3 public D
+  | |
+  o |  2 public C
+  |/
+  o  1 public B
+  |
+  o  0 public A
+  
+
+test complete failure
+
+  $ hg phase --draft 7
+  cannot move 1 changesets to a more permissive phase, use --force
+  no phases changed
+  [1]
--- a/tests/test-rename-dir-merge.t	Tue Feb 28 23:47:46 2012 +0200
+++ b/tests/test-rename-dir-merge.t	Tue Feb 28 21:17:53 2012 -0600
@@ -27,7 +27,6 @@
     searching for copies back to rev 1
     unmatched files in local:
      a/c
-     a/d
     unmatched files in other:
      b/a
      b/b
@@ -37,33 +36,29 @@
     checking for directory renames
     dir a/ -> b/
     file a/c -> b/c
-    file a/d -> b/d
   resolving manifests
    overwrite: False, partial: False
    ancestor: f9b20c0d4c51, local: ce36d17b18fb+, remote: 397f8b00a740
-   a/d: remote renamed directory to b/d -> d
    a/c: remote renamed directory to b/c -> d
    a/b: other deleted -> r
    a/a: other deleted -> r
    b/a: remote created -> g
    b/b: remote created -> g
-  updating: a/a 1/6 files (16.67%)
+  updating: a/a 1/5 files (20.00%)
   removing a/a
-  updating: a/b 2/6 files (33.33%)
+  updating: a/b 2/5 files (40.00%)
   removing a/b
-  updating: a/c 3/6 files (50.00%)
+  updating: a/c 3/5 files (60.00%)
   moving a/c to b/c
-  updating: a/d 4/6 files (66.67%)
-  moving a/d to b/d
-  updating: b/a 5/6 files (83.33%)
+  updating: b/a 4/5 files (80.00%)
   getting b/a
-  updating: b/b 6/6 files (100.00%)
+  updating: b/b 5/5 files (100.00%)
   getting b/b
-  4 files updated, 0 files merged, 2 files removed, 0 files unresolved
+  3 files updated, 0 files merged, 2 files removed, 0 files unresolved
   (branch merge, don't forget to commit)
 
   $ echo a/* b/*
-  a/* b/a b/b b/c b/d
+  a/d b/a b/b b/c
   $ hg st -C
   M b/a
   M b/b
@@ -72,7 +67,7 @@
   R a/a
   R a/b
   R a/c
-  ? b/d
+  ? a/d
   $ hg ci -m "3 merge 2+1"
   $ hg debugrename b/c
   b/c renamed from a/c:354ae8da6e890359ef49ade27b68bbc361f3ca88 (glob)
@@ -84,7 +79,6 @@
     unmatched files in local:
      b/a
      b/b
-     b/d
     unmatched files in other:
      a/c
     all copies found (* = to merge, ! = divergent):
@@ -103,11 +97,11 @@
   (branch merge, don't forget to commit)
 
   $ echo a/* b/*
-  a/* b/a b/b b/c b/d
+  a/d b/a b/b b/c
   $ hg st -C
   A b/c
     a/c
-  ? b/d
+  ? a/d
   $ hg ci -m "4 merge 1+2"
   created new head
   $ hg debugrename b/c
--- a/tests/test-revset.t	Tue Feb 28 23:47:46 2012 +0200
+++ b/tests/test-revset.t	Tue Feb 28 21:17:53 2012 -0600
@@ -430,6 +430,7 @@
 
   $ echo '[revsetalias]' >> .hg/hgrc
   $ echo 'm = merge()' >> .hg/hgrc
+  $ echo 'sincem = descendants(m)' >> .hg/hgrc
   $ echo 'd($1) = reverse(sort($1, date))' >> .hg/hgrc
   $ echo 'rs(ARG1, ARG2) = reverse(sort(ARG1, ARG2))' >> .hg/hgrc
   $ echo 'rs4(ARG1, ARGA, ARGB, ARG2) = reverse(sort(ARG1, ARG2))' >> .hg/hgrc
@@ -438,6 +439,46 @@
   ('symbol', 'm')
   ('func', ('symbol', 'merge'), None)
   6
+
+test alias recursion
+
+  $ try sincem
+  ('symbol', 'sincem')
+  ('func', ('symbol', 'descendants'), ('func', ('symbol', 'merge'), None))
+  6
+  7
+
+test infinite recursion
+
+  $ echo 'recurse1 = recurse2' >> .hg/hgrc
+  $ echo 'recurse2 = recurse1' >> .hg/hgrc
+  $ try recurse1
+  ('symbol', 'recurse1')
+  hg: parse error: infinite expansion of revset alias "recurse1" detected
+  [255]
+
+test nesting and variable passing
+
+  $ echo 'nested($1) = nested2($1)' >> .hg/hgrc
+  $ echo 'nested2($1) = nested3($1)' >> .hg/hgrc
+  $ echo 'nested3($1) = max($1)' >> .hg/hgrc
+  $ try 'nested(2:5)'
+  ('func', ('symbol', 'nested'), ('range', ('symbol', '2'), ('symbol', '5')))
+  ('func', ('symbol', 'max'), ('range', ('symbol', '2'), ('symbol', '5')))
+  5
+
+test variable isolation, variable placeholders are rewritten as string
+then parsed and matched again as string. Check they do not leak too
+far away.
+
+  $ echo 'injectparamasstring = max("$1")' >> .hg/hgrc
+  $ echo 'callinjection($1) = descendants(injectparamasstring)' >> .hg/hgrc
+  $ try 'callinjection(2:5)'
+  ('func', ('symbol', 'callinjection'), ('range', ('symbol', '2'), ('symbol', '5')))
+  ('func', ('symbol', 'descendants'), ('func', ('symbol', 'max'), ('string', '$1')))
+  abort: unknown revision '$1'!
+  [255]
+
   $ try 'd(2:5)'
   ('func', ('symbol', 'd'), ('range', ('symbol', '2'), ('symbol', '5')))
   ('func', ('symbol', 'reverse'), ('func', ('symbol', 'sort'), ('list', ('range', ('symbol', '2'), ('symbol', '5')), ('symbol', 'date'))))
--- a/tests/test-subrepo-deep-nested-change.t	Tue Feb 28 23:47:46 2012 +0200
+++ b/tests/test-subrepo-deep-nested-change.t	Tue Feb 28 21:17:53 2012 -0600
@@ -18,7 +18,6 @@
   adding sub1/.hgsub (glob)
   adding sub1/sub1 (glob)
   $ hg commit -R sub1 -m "sub1 import"
-  committing subrepository sub2
 
 Preparing the 'main' repo which depends on the subrepo 'sub1'
 
@@ -33,7 +32,6 @@
   adding main/.hgsub (glob)
   adding main/main (glob)
   $ hg commit -R main -m "main import"
-  committing subrepository sub1
 
 Cleaning both repositories, just as a clone -U
 
--- a/tests/test-subrepo-git.t	Tue Feb 28 23:47:46 2012 +0200
+++ b/tests/test-subrepo-git.t	Tue Feb 28 21:17:53 2012 -0600
@@ -34,7 +34,6 @@
   $ git clone -q ../gitroot s
   $ hg add .hgsub
   $ hg commit -m 'new git subrepo'
-  committing subrepository s
   $ hg debugsub
   path s
    source   ../gitroot
@@ -55,7 +54,6 @@
   $ hg status --subrepos
   M s/g
   $ hg commit -m 'update git subrepo'
-  committing subrepository s
   $ hg debugsub
   path s
    source   ../gitroot
@@ -222,7 +220,6 @@
   $ git pull -q >/dev/null 2>/dev/null
   $ cd ..
   $ hg commit -m 'git upstream sync'
-  committing subrepository s
   $ hg debugsub
   path s
    source   ../gitroot
@@ -287,7 +284,6 @@
   $ echo inner = inner > .hgsub
   $ hg add .hgsub
   $ hg commit -m 'nested sub'
-  committing subrepository inner
 
 nested commit
 
@@ -339,27 +335,32 @@
   $ hg update 1 -q
   $ hg rm .hgsubstate
   $ hg commit .hgsubstate -m 'no substate'
-  created new head
+  nothing changed
+  [1]
   $ hg tag -l nosubstate
   $ hg manifest
   .hgsub
+  .hgsubstate
   a
 
   $ hg status -S
+  R .hgsubstate
   $ hg sum | grep commit
-  commit: 1 subrepos
+  commit: 1 removed, 1 subrepos (new branch head)
 
   $ hg commit -m 'restore substate'
-  committing subrepository s
+  nothing changed
+  [1]
   $ hg manifest
   .hgsub
   .hgsubstate
   a
   $ hg sum | grep commit
-  commit: (clean)
+  commit: 1 removed, 1 subrepos (new branch head)
 
   $ hg update -qC nosubstate
   $ ls s
+  g
 
 issue3109: false positives in git diff-index
 
--- a/tests/test-subrepo-missing.t	Tue Feb 28 23:47:46 2012 +0200
+++ b/tests/test-subrepo-missing.t	Tue Feb 28 21:17:53 2012 -0600
@@ -7,12 +7,10 @@
   $ echo 'subrepo = subrepo' > .hgsub
   $ hg ci -Am addsubrepo
   adding .hgsub
-  committing subrepository subrepo
   $ echo b > subrepo/b
   $ hg -R subrepo ci -Am addb
   adding b
   $ hg ci -m updatedsub
-  committing subrepository subrepo
 
 delete .hgsub and revert it
 
--- a/tests/test-subrepo-recursion.t	Tue Feb 28 23:47:46 2012 +0200
+++ b/tests/test-subrepo-recursion.t	Tue Feb 28 21:17:53 2012 -0600
@@ -79,11 +79,9 @@
 
   $ cd ..
   $ hg commit -m 0-2-1
-  committing subrepository bar
 
   $ cd ..
   $ hg commit -m 1-2-1
-  committing subrepository foo
 
 Change working directory:
 
--- a/tests/test-subrepo-relative-path.t	Tue Feb 28 23:47:46 2012 +0200
+++ b/tests/test-subrepo-relative-path.t	Tue Feb 28 21:17:53 2012 -0600
@@ -20,7 +20,6 @@
   adding main/.hgsub (glob)
   adding main/main (glob)
   $ hg commit -R main -m "main import"
-  committing subrepository sub
 
 Cleaning both repositories, just as a clone -U
 
--- a/tests/test-subrepo-svn.t	Tue Feb 28 23:47:46 2012 +0200
+++ b/tests/test-subrepo-svn.t	Tue Feb 28 21:17:53 2012 -0600
@@ -69,8 +69,6 @@
   $ svn co --quiet "$SVNREPO"/src subdir/s
   $ hg add .hgsub
   $ hg ci -m1
-  committing subrepository s
-  committing subrepository subdir/s
 
 make sure we avoid empty commits (issue2445)
 
@@ -432,7 +430,6 @@
   $ echo "s =        [svn]       $SVNREPO/src" >> .hgsub
   $ hg add .hgsub
   $ hg ci -m addsub
-  committing subrepository s
   $ echo a > a
   $ hg ci -Am adda
   adding a
@@ -440,7 +437,6 @@
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
   $ svn up -qr6 s
   $ hg ci -m updatesub
-  committing subrepository s
   created new head
   $ echo pyc > s/dir/epsilon.pyc
   $ hg up 1
@@ -462,14 +458,12 @@
   $ echo "obstruct =        [svn]       $SVNREPO/externals" >> .hgsub
   $ svn co -r5 --quiet "$SVNREPO"/externals obstruct
   $ hg commit -m 'Start making obstructed working copy'
-  committing subrepository obstruct
   $ hg book other
   $ hg co -r 'p1(tip)'
   2 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ echo "obstruct =        [svn]       $SVNREPO/src" >> .hgsub
   $ svn co -r5 --quiet "$SVNREPO"/src obstruct
   $ hg commit -m 'Other branch which will be obstructed'
-  committing subrepository obstruct
   created new head
 
 Switching back to the head where we have another path mapped to the
@@ -530,12 +524,10 @@
   Checked out revision 10.
   $ echo "recreated =        [svn]       $SVNREPO/branch" >> .hgsub
   $ hg ci -m addsub
-  committing subrepository recreated
   $ cd recreated
   $ svn up -q
   $ cd ..
   $ hg ci -m updatesub
-  committing subrepository recreated
   $ hg up -r-2
   D    *recreated/somethingnew (glob)
   A    *recreated/somethingold (glob)
--- a/tests/test-subrepo.t	Tue Feb 28 23:47:46 2012 +0200
+++ b/tests/test-subrepo.t	Tue Feb 28 21:17:53 2012 -0600
@@ -37,7 +37,6 @@
   commit: 1 added, 1 subrepos
   update: (current)
   $ hg ci -m1
-  committing subrepository s
 
 Revert can't (yet) revert subrepos:
 
@@ -105,7 +104,6 @@
   $ echo b > s/a
   $ hg -R s ci -ms1
   $ hg --config ui.commitsubrepos=no ci -m3
-  committing subrepository s
 
 leave sub dirty (and check ui.commitsubrepos=no aborts the commit)
 
@@ -455,7 +453,6 @@
   1 files updated, 0 files merged, 1 files removed, 0 files unresolved
   $ hg ci -Am1
   adding .hgsub
-  committing subrepository s
   $ hg branch br
   marked working directory as branch br
   (branches are permanent and global, did you want a bookmark?)
@@ -464,7 +461,6 @@
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg ci -Am1
   adding b
-  committing subrepository s
   $ hg up default
   1 files updated, 0 files merged, 1 files removed, 0 files unresolved
   $ echo c > c
@@ -483,7 +479,6 @@
   $ echo d > d
   $ hg ci -Am1
   adding d
-  committing subrepository s
   $ hg up 3
   2 files updated, 0 files merged, 1 files removed, 0 files unresolved
   $ hg -R s up 5
@@ -491,7 +486,6 @@
   $ echo e > e
   $ hg ci -Am1
   adding e
-  committing subrepository s
 
   $ hg up 5
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
@@ -519,8 +513,6 @@
   $ hg -R testdelete add
   adding testdelete/.hgsub (glob)
   $ hg -R testdelete ci -m "nested 1 & 2 added"
-  committing subrepository nested
-  committing subrepository nested2
   $ echo nested = nested > testdelete/.hgsub
   $ hg -R testdelete ci -m "nested 2 deleted"
   $ cat testdelete/.hgsubstate
@@ -550,8 +542,6 @@
   $ hg -R main add
   adding main/.hgsub (glob)
   $ hg -R main ci -m "add subrepos"
-  committing subrepository nested_absolute
-  committing subrepository nested_relative
   $ cd ..
   $ hg clone mercurial/main mercurial2/main
   updating to branch default
@@ -574,7 +564,6 @@
   $ echo s = s > repo/.hgsub
   $ hg -R repo ci -Am1
   adding .hgsub
-  committing subrepository s
   $ hg clone repo repo2
   updating to branch default
   cloning subrepo s from $TESTTMP/sub/repo/s (glob)
@@ -589,7 +578,6 @@
   $ hg -R repo2/s ci -m3
   created new head
   $ hg -R repo2 ci -m3
-  committing subrepository s
   $ hg -q -R repo2 push
   abort: push creates new remote head 9d66565e64e1!
   (did you forget to merge? use push -f to force)
@@ -699,7 +687,6 @@
   $ echo subrepo-2 = subrepo-2 >> .hgsub
   $ hg add .hgsub
   $ hg ci -m 'Added subrepos'
-  committing subrepository subrepo-1
   committing subrepository subrepo-2
   $ hg st subrepo-2/file
 
@@ -857,17 +844,16 @@
 
   $ hg rm -f .hgsubstate
   $ hg ci -mrm
-  committing subrepository s
-  committing subrepository t
-  created new head
+  nothing changed
+  [1]
   $ hg log -vr tip
-  changeset:   14:3941e0aa5236
+  changeset:   13:925c17564ef8
   tag:         tip
-  parent:      11:365661e5936a
   user:        test
   date:        Thu Jan 01 00:00:00 1970 +0000
+  files:       .hgsubstate
   description:
-  rm
+  13
   
   
 
@@ -875,9 +861,11 @@
 
   $ hg rm .hgsub
   $ hg ci -mrm2
+  created new head
   $ hg log -vr tip
-  changeset:   15:8b31de9d13d1
+  changeset:   14:2400bccd50af
   tag:         tip
+  parent:      11:365661e5936a
   user:        test
   date:        Thu Jan 01 00:00:00 1970 +0000
   files:       .hgsub .hgsubstate
@@ -888,13 +876,13 @@
 Test issue3153: diff -S with deleted subrepos
 
   $ hg diff --nodates -S -c .
-  diff -r 3941e0aa5236 -r 8b31de9d13d1 .hgsub
+  diff -r 365661e5936a -r 2400bccd50af .hgsub
   --- a/.hgsub
   +++ /dev/null
   @@ -1,2 +0,0 @@
   -s = s
   -t = t
-  diff -r 3941e0aa5236 -r 8b31de9d13d1 .hgsubstate
+  diff -r 365661e5936a -r 2400bccd50af .hgsubstate
   --- a/.hgsubstate
   +++ /dev/null
   @@ -1,2 +0,0 @@
@@ -909,7 +897,6 @@
   $ hg add .hgsub
   $ hg init s
   $ hg ci -m0
-  committing subrepository s
 Adding with an explicit path in a subrepo adds the file
   $ echo c1 > f1
   $ echo c2 > s/f2
@@ -923,7 +910,6 @@
   $ hg ci -R s -m0
   $ hg ci -Am1
   adding f1
-  committing subrepository s
 Adding with an explicit path in a subrepo with -S has the same behavior
   $ echo c3 > f3
   $ echo c4 > s/f4
@@ -937,7 +923,6 @@
   $ hg ci -R s -m1
   $ hg ci -Ama2
   adding f3
-  committing subrepository s
 Adding without a path or pattern silently ignores subrepos
   $ echo c5 > f5
   $ echo c6 > s/f6
@@ -956,7 +941,6 @@
   adding f6
   adding f7
   $ hg ci -m3
-  committing subrepository s
 Adding without a path or pattern with -S also adds files in subrepos
   $ echo c8 > f8
   $ echo c9 > s/f9
@@ -975,7 +959,6 @@
   A s/f9
   $ hg ci -R s -m3
   $ hg ci -m4
-  committing subrepository s
 Adding with a pattern silently ignores subrepos
   $ echo c11 > fm11
   $ echo c12 > fn12
@@ -998,7 +981,6 @@
   adding fn14
   $ hg ci -Am5
   adding fn12
-  committing subrepository s
 Adding with a pattern with -S also adds matches in subrepos
   $ echo c15 > fm15
   $ echo c16 > fn16
@@ -1021,7 +1003,6 @@
   adding fn18
   $ hg ci -Am6
   adding fn16
-  committing subrepository s
 
 Test behavior of forget for explicit path in subrepo:
 Forgetting an explicit path in a subrepo untracks the file