Merge with main
authorMartin Geisler <mg@lazybytes.net>
Wed, 28 Oct 2009 20:48:24 +0100
changeset 9773 d942e06d7b14
parent 9772 1fd917793269 (current diff)
parent 9657 96c803e9018f (diff)
child 9774 03675e07d230
Merge with main
--- a/contrib/mercurial.spec	Mon Oct 26 20:58:49 2009 +0100
+++ b/contrib/mercurial.spec	Wed Oct 28 20:48:24 2009 +0100
@@ -17,7 +17,7 @@
 # python-devel provides an adequate python-dev.  The merge tool is a
 # run-time dependency.
 #
-BuildRequires: python >= 2.4, python-devel, make, gcc, asciidoc, xmlto
+BuildRequires: python >= 2.4, python-devel, make, gcc, docutils >= 0.5
 Provides: hg = %{version}-%{release}
 
 %define pythonver %(python -c 'import sys;print ".".join(map(str, sys.version_info[:2]))')
--- a/contrib/tcsh_completion	Mon Oct 26 20:58:49 2009 +0100
+++ b/contrib/tcsh_completion	Wed Oct 28 20:48:24 2009 +0100
@@ -2,7 +2,7 @@
 # tcsh completion for Mercurial
 #
 # This file has been auto-generated by tcsh_completion_build.sh for
-# Mercurial Distributed SCM (version 1.1.2)
+# Mercurial Distributed SCM (version 1.3.1+269-5d8125bbbbf4)
 #
 # Copyright (C) 2005 TK Soh.
 #
@@ -24,7 +24,6 @@
     --debugger \
     --encoding \
     --encodingmode \
-    --lsprof \
     --traceback \
     --time \
     --profile \
@@ -33,17 +32,18 @@
   'p/1/(add addremove annotate blame archive \
     backout bisect branch branches bundle \
     cat clone commit ci copy \
-    cp debugancestor debugcheckstate debugcomplete debugdata \
-    debugdate debugfsinfo debugindex debugindexdot debuginstall \
-    debugrawcommit rawcommit debugrebuildstate debugrename debugsetparents \
-    debugstate debugwalk diff export grep \
-    heads help identify id import \
-    patch incoming in init locate \
-    log history manifest merge outgoing \
-    out parents paths pull push \
-    recover remove rm rename mv \
-    resolve revert rollback root serve \
-    showconfig debugconfig status st tag \
-    tags tip unbundle update up \
-    checkout co verify version)/'
+    cp debugancestor debugcheckstate debugcommands debugcomplete \
+    debugdata debugdate debugfsinfo debugindex debugindexdot \
+    debuginstall debugrebuildstate debugrename debugsetparents debugstate \
+    debugsub debugwalk diff export forget \
+    grep heads help identify id \
+    import patch incoming in init \
+    locate log history manifest merge \
+    outgoing out parents paths pull \
+    push recover remove rm rename \
+    mv resolve revert rollback root \
+    serve showconfig debugconfig status st \
+    summary sum tag tags tip \
+    unbundle update up checkout co \
+    verify version)/'
 
--- a/contrib/win32/mercurial.iss	Mon Oct 26 20:58:49 2009 +0100
+++ b/contrib/win32/mercurial.iss	Wed Oct 28 20:48:24 2009 +0100
@@ -61,6 +61,7 @@
 Source: dist\w9xpopen.exe; DestDir: {app}
 Source: dist\add_path.exe; DestDir: {app}
 Source: doc\*.html; DestDir: {app}\Docs
+Source: doc\style.css; DestDir: {app}\Docs
 Source: locale\*.*; DestDir: {app}\locale; Flags: recursesubdirs createallsubdirs
 Source: templates\*.*; DestDir: {app}\Templates; Flags: recursesubdirs createallsubdirs
 Source: CONTRIBUTORS; DestDir: {app}; DestName: Contributors.txt
--- a/help/urls.txt	Mon Oct 26 20:58:49 2009 +0100
+++ b/help/urls.txt	Wed Oct 28 20:48:24 2009 +0100
@@ -47,7 +47,7 @@
   ...
 
 You can then use the alias for any command that uses a URL (for
-example 'hg pull alias1' would pull from the 'alias1' path).
+example 'hg pull alias1' will be treated as 'hg pull URL1').
 
 Two path aliases are special because they are used as defaults when
 you do not provide the URL to a command:
--- a/hgext/bookmarks.py	Mon Oct 26 20:58:49 2009 +0100
+++ b/hgext/bookmarks.py	Wed Oct 28 20:48:24 2009 +0100
@@ -231,7 +231,7 @@
         write(repo, marks)
 
 def reposetup(ui, repo):
-    if not isinstance(repo, localrepo.localrepository):
+    if not repo.local():
         return
 
     # init a bookmark cache as otherwise we would get a infinite reading
--- a/hgext/churn.py	Mon Oct 26 20:58:49 2009 +0100
+++ b/hgext/churn.py	Wed Oct 28 20:48:24 2009 +0100
@@ -53,14 +53,12 @@
     if opts.get('date'):
         df = util.matchdate(opts['date'])
 
-    get = util.cachefunc(lambda r: repo[r])
-    changeiter, matchfn = cmdutil.walkchangerevs(ui, repo, pats, get, opts)
-    for st, rev, fns in changeiter:
-
+    m = cmdutil.match(repo, pats, opts)
+    for st, ctx, fns in cmdutil.walkchangerevs(ui, repo, m, opts):
         if not st == 'add':
             continue
 
-        ctx = get(rev)
+        rev = ctx.rev()
         if df and not df(ctx.date()[0]): # doesn't match date format
             continue
 
--- a/hgext/color.py	Mon Oct 26 20:58:49 2009 +0100
+++ b/hgext/color.py	Wed Oct 28 20:48:24 2009 +0100
@@ -189,9 +189,25 @@
     finally:
         self.ui.write = oldwrite
 
+def colordiffstat(orig, s):
+    lines = s.split('\n')
+    for i, line in enumerate(lines):
+        if line and line[-1] in '+-':
+            name, graph = line.rsplit(' ', 1)
+            graph = graph.replace('-',
+                        render_effects('-', _diff_effects['deleted']))
+            graph = graph.replace('+',
+                        render_effects('+', _diff_effects['inserted']))
+            lines[i] = ' '.join([name, graph])
+    orig('\n'.join(lines))
+
 def colordiff(orig, ui, repo, *pats, **opts):
     '''run the diff command with colored output'''
-    oldwrite = extensions.wrapfunction(ui, 'write', colorwrap)
+    if opts.get('stat'):
+        wrapper = colordiffstat
+    else:
+        wrapper = colorwrap
+    oldwrite = extensions.wrapfunction(ui, 'write', wrapper)
     try:
         orig(ui, repo, *pats, **opts)
     finally:
--- a/hgext/convert/__init__.py	Mon Oct 26 20:58:49 2009 +0100
+++ b/hgext/convert/__init__.py	Wed Oct 28 20:48:24 2009 +0100
@@ -103,7 +103,10 @@
     revision control system whose parents should be modified (same
     format as a key in .hg/shamap). The values are the revision IDs
     (in either the source or destination revision control system) that
-    should be used as the new parents for that node.
+    should be used as the new parents for that node. For example, if
+    you have merged "release-1.0" into "trunk", then you should
+    specify the revision on "trunk" as the first parent and the one on
+    the "release-1.0" branch as the second.
 
     The branchmap is a file that allows you to rename a branch when it is
     being brought in from whatever external repository. When used in
--- a/hgext/mq.py	Mon Oct 26 20:58:49 2009 +0100
+++ b/hgext/mq.py	Wed Oct 28 20:48:24 2009 +0100
@@ -420,11 +420,20 @@
 
     def printdiff(self, repo, node1, node2=None, files=None,
                   fp=None, changes=None, opts={}):
+        stat = opts.get('stat')
+        if stat:
+            opts['unified'] = '0'
+
         m = cmdutil.match(repo, files, opts)
         chunks = patch.diff(repo, node1, node2, m, changes, self.diffopts())
         write = fp is None and repo.ui.write or fp.write
-        for chunk in chunks:
-            write(chunk)
+        if stat:
+            width = self.ui.interactive() and util.termwidth() or 80
+            write(patch.diffstat(util.iterlines(chunks), width=width,
+                                 git=self.diffopts().git))
+        else:
+            for chunk in chunks:
+                write(chunk)
 
     def mergeone(self, repo, mergeq, head, patch, rev):
         # first try just applying the patch
--- a/hgext/patchbomb.py	Mon Oct 26 20:58:49 2009 +0100
+++ b/hgext/patchbomb.py	Wed Oct 28 20:48:24 2009 +0100
@@ -76,11 +76,11 @@
 from mercurial.i18n import _
 from mercurial.node import bin
 
-def prompt(ui, prompt, default='', rest=': ', empty_ok=False):
+def prompt(ui, prompt, default=None, rest=':'):
     if not ui.interactive():
-        if default or empty_ok:
+        if default is not None:
             return default
-        raise util.Abort(_("%sPlease enter a valid value" % (prompt+rest)))
+        raise util.Abort(_("%s Please enter a valid value" % (prompt+rest)))
     if default:
         prompt += ' [%s]' % default
     prompt += rest
@@ -90,8 +90,6 @@
             return r
         if default is not None:
             return default
-        if empty_ok:
-            return r
         ui.warn(_('Please enter a valid value.\n'))
 
 def cdiffstat(ui, summary, patchlines):
@@ -99,7 +97,7 @@
     if summary:
         ui.write(summary, '\n')
         ui.write(s, '\n')
-    ans = prompt(ui, _('does the diffstat above look okay? '), 'y')
+    ans = prompt(ui, _('does the diffstat above look okay?'), 'y')
     if not ans.lower().startswith('y'):
         raise util.Abort(_('diffstat rejected'))
     return s
@@ -330,10 +328,11 @@
 
             flag = ' '.join(opts.get('flag'))
             if flag:
-                subj = '[PATCH %0*d of %d %s] ' % (tlen, 0, len(patches), flag)
+                subj = '[PATCH %0*d of %d %s]' % (tlen, 0, len(patches), flag)
             else:
-                subj = '[PATCH %0*d of %d] ' % (tlen, 0, len(patches))
-            subj += opts.get('subject') or prompt(ui, 'Subject:', rest=subj)
+                subj = '[PATCH %0*d of %d]' % (tlen, 0, len(patches))
+            subj += ' ' + (opts.get('subject') or
+                           prompt(ui, 'Subject: ', rest=subj))
 
             body = ''
             if opts.get('diffstat'):
--- a/mercurial/bundlerepo.py	Mon Oct 26 20:58:49 2009 +0100
+++ b/mercurial/bundlerepo.py	Wed Oct 28 20:48:24 2009 +0100
@@ -50,7 +50,7 @@
                 continue
             for p in (p1, p2):
                 if not p in self.nodemap:
-                    raise error.LookupError(p1, self.indexfile,
+                    raise error.LookupError(p, self.indexfile,
                                             _("unknown parent"))
             if linkmapper is None:
                 link = n
--- a/mercurial/cmdutil.py	Mon Oct 26 20:58:49 2009 +0100
+++ b/mercurial/cmdutil.py	Wed Oct 28 20:48:24 2009 +0100
@@ -653,8 +653,6 @@
 
         log = self.repo.changelog
         date = util.datestr(ctx.date())
-        extra = ctx.extra()
-        branch = extra.get("branch")
 
         hexfunc = self.ui.debugflag and hex or short
 
@@ -663,6 +661,7 @@
 
         self.ui.write(_("changeset:   %d:%s\n") % (rev, hexfunc(changenode)))
 
+        branch = ctx.branch()
         # don't show the default branch name
         if branch != 'default':
             branch = encoding.tolocal(branch)
@@ -691,6 +690,7 @@
             copies = ['%s (%s)' % c for c in copies]
             self.ui.write(_("copies:      %s\n") % ' '.join(copies))
 
+        extra = ctx.extra()
         if extra and self.ui.debugflag:
             for key, value in sorted(extra.items()):
                 self.ui.write(_("extra:       %s=%s\n")
@@ -1024,9 +1024,9 @@
     """Find the tipmost changeset that matches the given date spec"""
     df = util.matchdate(date)
     get = util.cachefunc(lambda r: repo[r])
-    changeiter, matchfn = walkchangerevs(ui, repo, [], get, {'rev':None})
+    m = matchall(repo)
     results = {}
-    for st, rev, fns in changeiter:
+    for st, rev, fns in walkchangerevs(ui, repo, m, get, {'rev':None}):
         if st == 'add':
             d = get(rev).date()
             if df(d[0]):
@@ -1039,7 +1039,7 @@
 
     raise util.Abort(_("revision matching date not found"))
 
-def walkchangerevs(ui, repo, pats, change, opts):
+def walkchangerevs(ui, repo, match, opts):
     '''Iterate over files and the revs in which they changed.
 
     Callers most commonly need to iterate backwards over the history
@@ -1050,12 +1050,8 @@
     window, we first walk forwards to gather data, then in the desired
     order (usually backwards) to display it.
 
-    This function returns an (iterator, matchfn) tuple. The iterator
-    yields 3-tuples. They will be of one of the following forms:
-
-    "window", incrementing, lastrev: stepping through a window,
-    positive if walking forwards through revs, last rev in the
-    sequence iterated over - use to reset state for the current window
+    This function returns an iterator. The iterator yields 3-tuples.
+    They will be of one of the following forms:
 
     "add", rev, fns: out-of-order traversal of the given filenames
     fns, which changed during revision rev - use to gather data for
@@ -1078,11 +1074,10 @@
                 if windowsize < sizelimit:
                     windowsize *= 2
 
-    m = match(repo, pats, opts)
     follow = opts.get('follow') or opts.get('follow_first')
 
     if not len(repo):
-        return [], m
+        return []
 
     if follow:
         defrange = '%s:0' % repo['.'].rev()
@@ -1090,10 +1085,11 @@
         defrange = '-1:0'
     revs = revrange(repo, opts['rev'] or [defrange])
     wanted = set()
-    slowpath = m.anypats() or (m.files() and opts.get('removed'))
+    slowpath = match.anypats() or (match.files() and opts.get('removed'))
     fncache = {}
+    change = util.cachefunc(repo.changectx)
 
-    if not slowpath and not m.files():
+    if not slowpath and not match.files():
         # No files, no patterns.  Display all revs.
         wanted = set(revs)
     copies = []
@@ -1117,7 +1113,7 @@
                     if rev[0] < cl_count:
                         yield rev
         def iterfiles():
-            for filename in m.files():
+            for filename in match.files():
                 yield filename, None
             for filename_node in copies:
                 yield filename_node
@@ -1157,7 +1153,7 @@
                     yield change(j)
 
         for ctx in changerevgen():
-            matches = filter(m, ctx.files())
+            matches = filter(match, ctx.files())
             if matches:
                 fncache[ctx.rev()] = matches
                 wanted.add(ctx.rev())
@@ -1210,7 +1206,7 @@
                 wanted.discard(x)
 
     def iterate():
-        if follow and not m.files():
+        if follow and not match.files():
             ff = followfilter(onlyfirst=opts.get('follow_first'))
             def want(rev):
                 return ff.match(rev) and rev in wanted
@@ -1219,20 +1215,20 @@
                 return rev in wanted
 
         for i, window in increasing_windows(0, len(revs)):
-            yield 'window', revs[0] < revs[-1], revs[-1]
             nrevs = [rev for rev in revs[i:i+window] if want(rev)]
             for rev in sorted(nrevs):
                 fns = fncache.get(rev)
+                ctx = change(rev)
                 if not fns:
                     def fns_generator():
-                        for f in change(rev).files():
-                            if m(f):
+                        for f in ctx.files():
+                            if match(f):
                                 yield f
                     fns = fns_generator()
-                yield 'add', rev, fns
+                yield 'add', ctx, fns
             for rev in nrevs:
-                yield 'iter', rev, None
-    return iterate(), m
+                yield 'iter', change(rev), None
+    return iterate()
 
 def commit(ui, repo, commitfunc, pats, opts):
     '''commit the specified files or all outstanding changes'''
--- a/mercurial/commands.py	Mon Oct 26 20:58:49 2009 +0100
+++ b/mercurial/commands.py	Wed Oct 28 20:48:24 2009 +0100
@@ -1085,6 +1085,7 @@
 
     revs = opts.get('rev')
     change = opts.get('change')
+    stat = opts.get('stat')
 
     if revs and change:
         msg = _('cannot specify --rev and --change at the same time')
@@ -1095,10 +1096,19 @@
     else:
         node1, node2 = cmdutil.revpair(repo, revs)
 
+    if stat:
+        opts['unified'] = '0'
+    diffopts = patch.diffopts(ui, opts)
+
     m = cmdutil.match(repo, pats, opts)
-    it = patch.diff(repo, node1, node2, match=m, opts=patch.diffopts(ui, opts))
-    for chunk in it:
-        ui.write(chunk)
+    it = patch.diff(repo, node1, node2, match=m, opts=diffopts)
+    if stat:
+        width = ui.interactive() and util.termwidth() or 80
+        ui.write(patch.diffstat(util.iterlines(it), width=width,
+                                git=diffopts.git))
+    else:
+        for chunk in it:
+            ui.write(chunk)
 
 def export(ui, repo, *changesets, **opts):
     """dump the header and diffs for one or more changesets
@@ -1257,7 +1267,8 @@
                 for i in xrange(blo, bhi):
                     yield ('+', b[i])
 
-    def display(fn, r, pstates, states):
+    def display(fn, ctx, pstates, states):
+        rev = ctx.rev()
         datefunc = ui.quiet and util.shortdate or util.datestr
         found = False
         filerevmatches = {}
@@ -1266,17 +1277,17 @@
         else:
             iter = [('', l) for l in states]
         for change, l in iter:
-            cols = [fn, str(r)]
+            cols = [fn, str(rev)]
             if opts.get('line_number'):
                 cols.append(str(l.linenum))
             if opts.get('all'):
                 cols.append(change)
             if opts.get('user'):
-                cols.append(ui.shortuser(get(r).user()))
+                cols.append(ui.shortuser(ctx.user()))
             if opts.get('date'):
-                cols.append(datefunc(get(r).date()))
+                cols.append(datefunc(ctx.date()))
             if opts.get('files_with_matches'):
-                c = (fn, r)
+                c = (fn, rev)
                 if c in filerevmatches:
                     continue
                 filerevmatches[c] = 1
@@ -1288,16 +1299,12 @@
 
     skip = {}
     revfiles = {}
-    get = util.cachefunc(lambda r: repo[r])
-    changeiter, matchfn = cmdutil.walkchangerevs(ui, repo, pats, get, opts)
+    matchfn = cmdutil.match(repo, pats, opts)
     found = False
     follow = opts.get('follow')
-    for st, rev, fns in changeiter:
-        if st == 'window':
-            matches.clear()
-            revfiles.clear()
-        elif st == 'add':
-            ctx = get(rev)
+    for st, ctx, fns in cmdutil.walkchangerevs(ui, repo, matchfn, opts):
+        if st == 'add':
+            rev = ctx.rev()
             pctx = ctx.parents()[0]
             parent = pctx.rev()
             matches.setdefault(rev, {})
@@ -1331,7 +1338,8 @@
                     except error.LookupError:
                         pass
         elif st == 'iter':
-            parent = get(rev).parents()[0].rev()
+            rev = ctx.rev()
+            parent = ctx.parents()[0].rev()
             for fn in sorted(revfiles.get(rev, [])):
                 states = matches[rev][fn]
                 copy = copies.get(rev, {}).get(fn)
@@ -1341,12 +1349,14 @@
                     continue
                 pstates = matches.get(parent, {}).get(copy or fn, [])
                 if pstates or states:
-                    r = display(fn, rev, pstates, states)
+                    r = display(fn, ctx, pstates, states)
                     found = found or r
                     if r and not opts.get('all'):
                         skip[fn] = True
                         if copy:
                             skip[copy] = True
+            del matches[rev]
+            del revfiles[rev]
 
 def heads(ui, repo, *branchrevs, **opts):
     """show current repository heads or show branch heads
@@ -1604,7 +1614,7 @@
     for title, options in option_lists:
         opt_output.append(("\n%s" % title, None))
         for shortopt, longopt, default, desc in options:
-            if "DEPRECATED" in desc and not ui.verbose: continue
+            if _("DEPRECATED") in desc and not ui.verbose: continue
             opt_output.append(("%2s%s" % (shortopt and "-%s" % shortopt,
                                           longopt and " --%s" % longopt),
                                "%s%s" % (desc,
@@ -1708,7 +1718,8 @@
 def import_(ui, repo, patch1, *patches, **opts):
     """import an ordered set of patches
 
-    Import a list of patches and commit them individually.
+    Import a list of patches and commit them individually (unless
+    --no-commit is specified).
 
     If there are outstanding changes in the working directory, import
     will abort unless given the -f/--force flag.
@@ -1979,9 +1990,7 @@
     will appear in files:.
     """
 
-    get = util.cachefunc(lambda r: repo[r])
-    changeiter, matchfn = cmdutil.walkchangerevs(ui, repo, pats, get, opts)
-
+    matchfn = cmdutil.match(repo, pats, opts)
     limit = cmdutil.loglimit(opts)
     count = 0
 
@@ -2028,7 +2037,8 @@
     only_branches = opts.get('only_branch')
 
     displayer = cmdutil.show_changeset(ui, repo, opts, True, matchfn)
-    for st, rev, fns in changeiter:
+    for st, ctx, fns in cmdutil.walkchangerevs(ui, repo, matchfn, opts):
+        rev = ctx.rev()
         if st == 'add':
             parents = [p for p in repo.changelog.parentrevs(rev)
                        if p != nullrev]
@@ -2037,7 +2047,6 @@
             if opts.get('only_merges') and len(parents) != 2:
                 continue
 
-            ctx = get(rev)
             if only_branches and ctx.branch() not in only_branches:
                 continue
 
@@ -2070,6 +2079,7 @@
 
         elif st == 'iter':
             if count == limit: break
+
             if displayer.flush(rev):
                 count += 1
 
@@ -2298,6 +2308,8 @@
             raise util.Abort(err)
 
     modheads = repo.pull(other, heads=revs, force=opts.get('force'))
+    if checkout:
+        checkout = str(repo.changelog.rev(other.lookup(checkout)))
     return postincoming(ui, repo, modheads, opts.get('update'), checkout)
 
 def push(ui, repo, dest=None, **opts):
@@ -2433,7 +2445,7 @@
 def resolve(ui, repo, *pats, **opts):
     """retry file merges from a merge or update
 
-    This command will cleanly retry unresolved file merges using file
+    This command can cleanly retry unresolved file merges using file
     revisions preserved from the last update or merge. To attempt to
     resolve all unresolved files, use the -a/--all switch.
 
@@ -2451,7 +2463,8 @@
       R = resolved
     """
 
-    all, mark, unmark, show = [opts.get(o) for o in 'all mark unmark list'.split()]
+    all, mark, unmark, show, nostatus = \
+        [opts.get(o) for o in 'all mark unmark list no_status'.split()]
 
     if (show and (mark or unmark)) or (mark and unmark):
         raise util.Abort(_("too many options specified"))
@@ -2467,7 +2480,10 @@
     for f in ms:
         if m(f):
             if show:
-                ui.write("%s %s\n" % (ms[f].upper(), f))
+                if nostatus:
+                    ui.write("%s\n" % f)
+                else:
+                    ui.write("%s %s\n" % (ms[f].upper(), f))
             elif mark:
                 ms.mark(f, "r")
             elif unmark:
@@ -3260,7 +3276,8 @@
      _('ignore changes in the amount of white space')),
     ('B', 'ignore-blank-lines', None,
      _('ignore changes whose lines are all blank')),
-    ('U', 'unified', '', _('number of lines of context to show'))
+    ('U', 'unified', '', _('number of lines of context to show')),
+    ('', 'stat', None, _('output diffstat-style summary of changes')),
 ]
 
 similarityopts = [
@@ -3475,7 +3492,7 @@
           ('n', 'newest-first', None, _('show newest record first')),
           ('', 'bundle', '', _('file to store the bundles into')),
           ('r', 'rev', [],
-           _('a specific revision up to which you would like to pull')),
+           _('a specific remote revision up to which you would like to pull')),
          ] + logopts + remoteopts,
          _('[-p] [-n] [-M] [-f] [-r REV]...'
            ' [--bundle FILENAME] [SOURCE]')),
@@ -3543,7 +3560,7 @@
           ('f', 'force', None,
            _('run even when remote repository is unrelated')),
           ('r', 'rev', [],
-           _('a specific revision up to which you would like to pull')),
+           _('a specific remote revision up to which you would like to pull')),
          ] + remoteopts,
          _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
     "^push":
@@ -3573,7 +3590,8 @@
          [('a', 'all', None, _('remerge all unresolved files')),
           ('l', 'list', None, _('list state of files needing merge')),
           ('m', 'mark', None, _('mark files as resolved')),
-          ('u', 'unmark', None, _('unmark files as resolved'))]
+          ('u', 'unmark', None, _('unmark files as resolved')),
+          ('n', 'no-status', None, _('hide status prefix'))]
           + walkopts,
           _('[OPTION]... [FILE]...')),
     "revert":
--- a/mercurial/patch.py	Mon Oct 26 20:58:49 2009 +0100
+++ b/mercurial/patch.py	Wed Oct 28 20:48:24 2009 +0100
@@ -1364,7 +1364,8 @@
     for line in lines:
         if line.startswith('diff'):
             if filename:
-                yield (filename, adds, removes)
+                isbinary = adds == 0 and removes == 0
+                yield (filename, adds, removes, isbinary)
             # set numbers to 0 anyway when starting new file
             adds, removes = 0, 0
             if line.startswith('diff --git'):
@@ -1377,21 +1378,27 @@
         elif line.startswith('-') and not line.startswith('---'):
             removes += 1
     if filename:
-        yield (filename, adds, removes)
+        isbinary = adds == 0 and removes == 0
+        yield (filename, adds, removes, isbinary)
 
-def diffstat(lines, width=80):
+def diffstat(lines, width=80, git=False):
     output = []
     stats = list(diffstatdata(lines))
 
     maxtotal, maxname = 0, 0
     totaladds, totalremoves = 0, 0
-    for filename, adds, removes in stats:
+    hasbinary = False
+    for filename, adds, removes, isbinary in stats:
         totaladds += adds
         totalremoves += removes
         maxname = max(maxname, len(filename))
         maxtotal = max(maxtotal, adds+removes)
+        if isbinary:
+            hasbinary = True
 
     countwidth = len(str(maxtotal))
+    if hasbinary and countwidth < 3:
+        countwidth = 3
     graphwidth = width - countwidth - maxname - 6
     if graphwidth < 10:
         graphwidth = 10
@@ -1404,11 +1411,15 @@
         # if there were at least some changes.
         return max(i * graphwidth // maxtotal, int(bool(i)))
 
-    for filename, adds, removes in stats:
+    for filename, adds, removes, isbinary in stats:
+        if git and isbinary:
+            count = 'Bin'
+        else:
+            count = adds + removes
         pluses = '+' * scale(adds)
         minuses = '-' * scale(removes)
-        output.append(' %-*s |  %*.d %s%s\n' % (maxname, filename, countwidth,
-                                                adds+removes, pluses, minuses))
+        output.append(' %-*s |  %*s %s%s\n' % (maxname, filename, countwidth,
+                                               count, pluses, minuses))
 
     if stats:
         output.append(_(' %d files changed, %d insertions(+), %d deletions(-)\n')
--- a/mercurial/verify.py	Mon Oct 26 20:58:49 2009 +0100
+++ b/mercurial/verify.py	Wed Oct 28 20:48:24 2009 +0100
@@ -27,6 +27,7 @@
     ui = repo.ui
     cl = repo.changelog
     mf = repo.manifest
+    lrugetctx = util.lrucachefunc(repo.changectx)
 
     if not repo.cancopy():
         raise util.Abort(_("cannot verify bundle or remote repos"))
@@ -78,6 +79,13 @@
                 msg = _("rev %d points to unexpected changeset %d")
             err(None, msg % (i, lr), f)
             if linkrevs:
+                if f and len(linkrevs) > 1:
+                    try:
+                        # attempt to filter down to real linkrevs
+                        linkrevs = [l for l in linkrevs
+                                    if lrugetctx(l)[f].filenode() == node]
+                    except:
+                        pass
                 warn(_(" (expected %s)") % " ".join(map(str, linkrevs)))
             lr = None # can't be trusted
 
@@ -136,9 +144,7 @@
                 if not f:
                     err(lr, _("file without name in manifest"))
                 elif f != "/dev/null":
-                    fns = filenodes.setdefault(f, {})
-                    if fn not in fns:
-                        fns[fn] = i
+                    filenodes.setdefault(f, {}).setdefault(fn, lr)
         except Exception, inst:
             exc(lr, _("reading manifest delta %s") % short(n), inst)
 
@@ -173,7 +179,6 @@
         elif size > 0:
             storefiles.add(f)
 
-    lrugetctx = util.lrucachefunc(repo.changectx)
     files = sorted(set(filenodes) | set(filelinkrevs))
     for f in files:
         try:
@@ -250,7 +255,7 @@
 
         # cross-check
         if f in filenodes:
-            fns = [(mf.linkrev(l), n) for n,l in filenodes[f].iteritems()]
+            fns = [(lr, n) for n,lr in filenodes[f].iteritems()]
             for lr, node in sorted(fns):
                 err(lr, _("%s in manifests not found") % short(node), f)
 
--- a/tests/test-convert.out	Mon Oct 26 20:58:49 2009 +0100
+++ b/tests/test-convert.out	Wed Oct 28 20:48:24 2009 +0100
@@ -81,7 +81,10 @@
     revision ID in the source revision control system whose parents should be
     modified (same format as a key in .hg/shamap). The values are the revision
     IDs (in either the source or destination revision control system) that
-    should be used as the new parents for that node.
+    should be used as the new parents for that node. For example, if you have
+    merged "release-1.0" into "trunk", then you should specify the revision on
+    "trunk" as the first parent and the one on the "release-1.0" branch as the
+    second.
 
     The branchmap is a file that allows you to rename a branch when it is
     being brought in from whatever external repository. When used in
--- a/tests/test-debugcomplete.out	Mon Oct 26 20:58:49 2009 +0100
+++ b/tests/test-debugcomplete.out	Wed Oct 28 20:48:24 2009 +0100
@@ -167,7 +167,7 @@
 annotate: rev, follow, text, user, date, number, changeset, line-number, include, exclude
 clone: noupdate, rev, pull, uncompressed, ssh, remotecmd
 commit: addremove, close-branch, include, exclude, message, logfile, date, user
-diff: rev, change, text, git, nodates, show-function, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, include, exclude
+diff: rev, change, text, git, nodates, show-function, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, stat, include, exclude
 export: output, switch-parent, text, git, nodates
 forget: include, exclude
 init: ssh, remotecmd
@@ -218,7 +218,7 @@
 paths: 
 recover: 
 rename: after, force, include, exclude, dry-run
-resolve: all, list, mark, unmark, include, exclude
+resolve: all, list, mark, unmark, no-status, include, exclude
 revert: all, date, rev, no-backup, include, exclude, dry-run
 rollback: 
 root: 
--- a/tests/test-diff-color	Mon Oct 26 20:58:49 2009 +0100
+++ b/tests/test-diff-color	Wed Oct 28 20:48:24 2009 +0100
@@ -35,6 +35,9 @@
 echo '% --unified=2'
 hg diff --nodates -U 2  --color=always
 
+echo '% diffstat'
+hg diff --stat --color=always
+
 echo "record=" >> $HGRCPATH
 echo "[ui]" >> $HGRCPATH
 echo "interactive=true" >> $HGRCPATH
--- a/tests/test-diff-color.out	Mon Oct 26 20:58:49 2009 +0100
+++ b/tests/test-diff-color.out	Wed Oct 28 20:48:24 2009 +0100
@@ -23,6 +23,9 @@
 +dd
  a
  a
+% diffstat
+ a |  2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
 % record
 diff --git a/a b/a
 old mode 100644
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-diffstat	Wed Oct 28 20:48:24 2009 +0100
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+hg init repo
+cd repo
+i=0; while [ "$i" -lt 213 ]; do echo a >> a; i=$(($i + 1)); done
+hg add a
+
+echo '% wide diffstat'
+hg diff --stat
+
+echo '% diffstat width'
+COLUMNS=24 hg diff --config ui.interactive=true --stat
+
+hg ci -m adda
+
+cat >> a <<EOF
+a
+a
+a
+EOF
+
+echo '% narrow diffstat'
+hg diff --stat
+
+hg ci -m appenda
+
+printf '\0' > b
+hg add b
+
+echo '% binary diffstat'
+hg diff --stat
+
+echo '% binary git diffstat'
+hg diff --stat --git
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-diffstat.out	Wed Oct 28 20:48:24 2009 +0100
@@ -0,0 +1,15 @@
+% wide diffstat
+ a |  213 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 files changed, 213 insertions(+), 0 deletions(-)
+% diffstat width
+ a |  213 ++++++++++++++
+ 1 files changed, 213 insertions(+), 0 deletions(-)
+% narrow diffstat
+ a |  3 +++
+ 1 files changed, 3 insertions(+), 0 deletions(-)
+% binary diffstat
+ b |    0 
+ 1 files changed, 0 insertions(+), 0 deletions(-)
+% binary git diffstat
+ b |  Bin 
+ 1 files changed, 0 insertions(+), 0 deletions(-)
--- a/tests/test-help.out	Mon Oct 26 20:58:49 2009 +0100
+++ b/tests/test-help.out	Wed Oct 28 20:48:24 2009 +0100
@@ -241,6 +241,7 @@
  -b --ignore-space-change  ignore changes in the amount of white space
  -B --ignore-blank-lines   ignore changes whose lines are all blank
  -U --unified              number of lines of context to show
+    --stat                 output diffstat-style summary of changes
  -I --include              include names matching the given patterns
  -X --exclude              exclude names matching the given patterns
 
--- a/tests/test-patchbomb.out	Mon Oct 26 20:58:49 2009 +0100
+++ b/tests/test-patchbomb.out	Wed Oct 28 20:48:24 2009 +0100
@@ -1177,7 +1177,7 @@
 +ff2c9fa2018b15fa74b33363bda9527323e2a99f two
 +ff2c9fa2018b15fa74b33363bda9527323e2a99f two.diff
 
-abort: Subject:[PATCH 0 of 2] Please enter a valid value
+abort: Subject: [PATCH 0 of 2] Please enter a valid value
 This patch series consists of 2 patches.
 
 This patch series consists of 2 patches.