--- a/hgext/churn.py Wed Oct 28 22:47:46 2009 -0500
+++ b/hgext/churn.py Fri Oct 30 09:53:39 2009 +0100
@@ -54,13 +54,10 @@
df = util.matchdate(opts['date'])
m = cmdutil.match(repo, pats, opts)
- for st, ctx, fns in cmdutil.walkchangerevs(ui, repo, m, opts):
- if not st == 'add':
- continue
-
+ def prep(ctx, fns):
rev = ctx.rev()
if df and not df(ctx.date()[0]): # doesn't match date format
- continue
+ return
key = getkey(ctx)
key = amap.get(key, key) # alias remap
@@ -70,7 +67,7 @@
parents = ctx.parents()
if len(parents) > 1:
ui.note(_('Revision %d is a merge, ignoring...\n') % (rev,))
- continue
+ return
ctx1 = parents[0]
lines = changedlines(ui, repo, ctx1, ctx, fns)
@@ -84,6 +81,9 @@
ui.write("\r" + _("generating stats: %d%%") % pct)
sys.stdout.flush()
+ for ctx in cmdutil.walkchangerevs(repo, m, opts, prep):
+ continue
+
if opts.get('progress'):
ui.write("\r")
sys.stdout.flush()
--- a/mercurial/cmdutil.py Wed Oct 28 22:47:46 2009 -0500
+++ b/mercurial/cmdutil.py Fri Oct 30 09:53:39 2009 +0100
@@ -1022,24 +1022,26 @@
def finddate(ui, repo, date):
"""Find the tipmost changeset that matches the given date spec"""
+
df = util.matchdate(date)
m = matchall(repo)
results = {}
- for st, ctx, fns in walkchangerevs(ui, repo, m, {'rev': None}):
+
+ def prep(ctx, fns):
+ d = ctx.date()
+ if df(d[0]):
+ results[rev] = d
+
+ for ctx in walkchangerevs(repo, m, {'rev': None}, prep):
rev = ctx.rev()
- if st == 'add':
- d = ctx.date()
- if df(d[0]):
- results[rev] = d
- elif st == 'iter':
- if rev in results:
- ui.status(_("Found revision %s from %s\n") %
- (rev, util.datestr(results[rev])))
- return str(rev)
+ if rev in results:
+ ui.status(_("Found revision %s from %s\n") %
+ (rev, util.datestr(results[rev])))
+ return str(rev)
raise util.Abort(_("revision matching date not found"))
-def walkchangerevs(ui, repo, match, opts):
+def walkchangerevs(repo, match, opts, prepare):
'''Iterate over files and the revs in which they changed.
Callers most commonly need to iterate backwards over the history
@@ -1050,15 +1052,9 @@
window, we first walk forwards to gather data, then in the desired
order (usually backwards) to display it.
- 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
- possible display
-
- "iter", rev, None: in-order traversal of the revs earlier iterated
- over with "add" - use to display data'''
+ This function returns an iterator yielding contexts. Before
+ yielding each context, the iterator will first call the prepare
+ function on each context in the window in forward order.'''
def increasing_windows(start, end, windowsize=8, sizelimit=512):
if start < end:
@@ -1093,6 +1089,7 @@
# No files, no patterns. Display all revs.
wanted = set(revs)
copies = []
+
if not slowpath:
# Only files, no patterns. Check the history of each file.
def filerevgen(filelog, node):
@@ -1129,8 +1126,6 @@
slowpath = True
break
else:
- ui.warn(_('%s:%s copy source revision cannot be found!\n')
- % (file_, short(node)))
continue
for rev, copied in filerevgen(filelog, node):
if rev <= maxrev:
@@ -1215,6 +1210,7 @@
return rev in wanted
for i, window in increasing_windows(0, len(revs)):
+ change = util.cachefunc(repo.changectx)
nrevs = [rev for rev in revs[i:i+window] if want(rev)]
for rev in sorted(nrevs):
fns = fncache.get(rev)
@@ -1225,9 +1221,9 @@
if match(f):
yield f
fns = fns_generator()
- yield 'add', ctx, fns
+ prepare(ctx, fns)
for rev in nrevs:
- yield 'iter', change(rev), None
+ yield change(rev)
return iterate()
def commit(ui, repo, commitfunc, pats, opts):
--- a/mercurial/commands.py Wed Oct 28 22:47:46 2009 -0500
+++ b/mercurial/commands.py Fri Oct 30 09:53:39 2009 +0100
@@ -1302,61 +1302,62 @@
matchfn = cmdutil.match(repo, pats, opts)
found = False
follow = opts.get('follow')
- 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, {})
- matches.setdefault(parent, {})
- files = revfiles.setdefault(rev, [])
- for fn in fns:
- flog = getfile(fn)
+
+ def prep(ctx, fns):
+ rev = ctx.rev()
+ pctx = ctx.parents()[0]
+ parent = pctx.rev()
+ matches.setdefault(rev, {})
+ matches.setdefault(parent, {})
+ files = revfiles.setdefault(rev, [])
+ for fn in fns:
+ flog = getfile(fn)
+ try:
+ fnode = ctx.filenode(fn)
+ except error.LookupError:
+ continue
+
+ copied = flog.renamed(fnode)
+ copy = follow and copied and copied[0]
+ if copy:
+ copies.setdefault(rev, {})[fn] = copy
+ if fn in skip:
+ if copy:
+ skip[copy] = True
+ continue
+ files.append(fn)
+
+ if fn not in matches[rev]:
+ grepbody(fn, rev, flog.read(fnode))
+
+ pfn = copy or fn
+ if pfn not in matches[parent]:
try:
- fnode = ctx.filenode(fn)
+ fnode = pctx.filenode(pfn)
+ grepbody(pfn, parent, flog.read(fnode))
except error.LookupError:
- continue
-
- copied = flog.renamed(fnode)
- copy = follow and copied and copied[0]
+ pass
+
+ for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
+ 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)
+ if fn in skip:
if copy:
- copies.setdefault(rev, {})[fn] = copy
- if fn in skip:
+ skip[copy] = True
+ continue
+ pstates = matches.get(parent, {}).get(copy or fn, [])
+ if pstates or 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
- continue
- files.append(fn)
-
- if fn not in matches[rev]:
- grepbody(fn, rev, flog.read(fnode))
-
- pfn = copy or fn
- if pfn not in matches[parent]:
- try:
- fnode = pctx.filenode(pfn)
- grepbody(pfn, parent, flog.read(fnode))
- except error.LookupError:
- pass
- elif st == 'iter':
- 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)
- if fn in skip:
- if copy:
- skip[copy] = True
- continue
- pstates = matches.get(parent, {}).get(copy or fn, [])
- if pstates or 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]
+ del matches[rev]
+ del revfiles[rev]
def heads(ui, repo, *branchrevs, **opts):
"""show current repository heads or show branch heads
@@ -2034,53 +2035,42 @@
if opts["date"]:
df = util.matchdate(opts["date"])
- only_branches = opts.get('only_branch')
-
displayer = cmdutil.show_changeset(ui, repo, opts, True, matchfn)
- for st, ctx, fns in cmdutil.walkchangerevs(ui, repo, matchfn, opts):
+ def prep(ctx, fns):
rev = ctx.rev()
- if st == 'add':
- parents = [p for p in repo.changelog.parentrevs(rev)
- if p != nullrev]
- if opts.get('no_merges') and len(parents) == 2:
- continue
- if opts.get('only_merges') and len(parents) != 2:
- continue
-
- if only_branches and ctx.branch() not in only_branches:
- continue
-
- if df and not df(ctx.date()[0]):
- continue
-
- if opts.get('keyword'):
- miss = 0
- for k in [kw.lower() for kw in opts['keyword']]:
- if not (k in ctx.user().lower() or
- k in ctx.description().lower() or
- k in " ".join(ctx.files()).lower()):
- miss = 1
- break
- if miss:
- continue
-
- if opts['user']:
- if not [k for k in opts['user'] if k in ctx.user()]:
- continue
-
- copies = []
- if opts.get('copies') and rev:
- for fn in ctx.files():
- rename = getrenamed(fn, rev)
- if rename:
- copies.append((fn, rename[0]))
-
- displayer.show(ctx, copies=copies)
-
- elif st == 'iter':
- if count == limit: break
-
- if displayer.flush(rev):
+ parents = [p for p in repo.changelog.parentrevs(rev)
+ if p != nullrev]
+ if opts.get('no_merges') and len(parents) == 2:
+ return
+ if opts.get('only_merges') and len(parents) != 2:
+ return
+ if opts.get('only_branch') and ctx.branch() not in opts['only_branch']:
+ return
+ if df and not df(ctx.date()[0]):
+ return
+ if opts['user'] and not [k for k in opts['user'] if k in ctx.user()]:
+ return
+ if opts.get('keyword'):
+ for k in [kw.lower() for kw in opts['keyword']]:
+ if (k in ctx.user().lower() or
+ k in ctx.description().lower() or
+ k in " ".join(ctx.files()).lower()):
+ break
+ else:
+ return
+
+ copies = []
+ if opts.get('copies') and rev:
+ for fn in ctx.files():
+ rename = getrenamed(fn, rev)
+ if rename:
+ copies.append((fn, rename[0]))
+
+ displayer.show(ctx, copies=copies)
+
+ for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
+ if count != limit:
+ if displayer.flush(ctx.rev()):
count += 1
def manifest(ui, repo, node=None, rev=None):