log: changed implementation to use graphlog code
Now that revsets work in a lazy way, log code can be changed to parse every
option into a revset and then evaluate it lazily.
Now expressions like
"hg log -b default -b ."
are converted into a revset using the same code as graphlog.
--- a/mercurial/cmdutil.py Mon Feb 24 22:42:14 2014 +0100
+++ b/mercurial/cmdutil.py Fri Feb 28 15:10:56 2014 -0800
@@ -1673,6 +1673,54 @@
return revs, expr, filematcher
+def getlogrevs(repo, pats, opts):
+ """Return (revs, expr, filematcher) where revs is an iterable of
+ revision numbers, expr is a revset string built from log options
+ and file patterns or None, and used to filter 'revs'. If --stat or
+ --patch are not passed filematcher is None. Otherwise it is a
+ callable taking a revision number and returning a match objects
+ filtering the files to be detailed when displaying the revision.
+ """
+ limit = loglimit(opts)
+ # Default --rev value depends on --follow but --follow behaviour
+ # depends on revisions resolved from --rev...
+ follow = opts.get('follow') or opts.get('follow_first')
+ if opts.get('rev'):
+ revs = scmutil.revrange(repo, opts['rev'])
+ elif follow:
+ revs = revset.baseset(repo.revs('reverse(:.)'))
+ else:
+ revs = revset.spanset(repo)
+ revs.reverse()
+ if not revs:
+ return revset.baseset([]), None, None
+ expr, filematcher = _makelogrevset(repo, pats, opts, revs)
+ if expr:
+ # Revset matchers often operate faster on revisions in changelog
+ # order, because most filters deal with the changelog.
+ if not opts.get('rev'):
+ revs.reverse()
+ matcher = revset.match(repo.ui, expr)
+ # Revset matches can reorder revisions. "A or B" typically returns
+ # returns the revision matching A then the revision matching B. Sort
+ # again to fix that.
+ revs = matcher(repo, revs)
+ if not opts.get('rev'):
+ revs.sort(reverse=True)
+ if limit is not None:
+ count = 0
+ limitedrevs = revset.baseset([])
+ it = iter(revs)
+ while count < limit:
+ try:
+ limitedrevs.append(it.next())
+ except (StopIteration):
+ break
+ count += 1
+ revs = limitedrevs
+
+ return revs, expr, filematcher
+
def displaygraph(ui, dag, displayer, showparents, edgefn, getrenamed=None,
filematcher=None):
seen, state = [], graphmod.asciistate()
--- a/mercurial/commands.py Mon Feb 24 22:42:14 2014 +0100
+++ b/mercurial/commands.py Fri Feb 28 15:10:56 2014 -0800
@@ -4082,55 +4082,22 @@
if opts.get('graph'):
return cmdutil.graphlog(ui, repo, *pats, **opts)
- matchfn = scmutil.match(repo[None], pats, opts)
+ revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
limit = cmdutil.loglimit(opts)
count = 0
- getrenamed, endrev = None, None
+ getrenamed = None
if opts.get('copies'):
+ endrev = None
if opts.get('rev'):
- endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
+ endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
- df = False
- if opts.get("date"):
- df = util.matchdate(opts["date"])
-
- branches = opts.get('branch', []) + opts.get('only_branch', [])
- opts['branch'] = [repo.lookupbranch(b) for b in branches]
-
- displayer = cmdutil.show_changeset(ui, repo, opts, True)
- def prep(ctx, fns):
- rev = ctx.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('branch') and ctx.branch() not in opts['branch']:
- return
- if df and not df(ctx.date()[0]):
- return
-
- lower = encoding.lower
- if opts.get('user'):
- luser = lower(ctx.user())
- for k in [lower(x) for x in opts['user']]:
- if (k in luser):
- break
- else:
- return
- if opts.get('keyword'):
- luser = lower(ctx.user())
- ldesc = lower(ctx.description())
- lfiles = lower(" ".join(ctx.files()))
- for k in [lower(x) for x in opts['keyword']]:
- if (k in luser or k in ldesc or k in lfiles):
- break
- else:
- return
-
+ displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
+ for rev in revs:
+ if count == limit:
+ break
+ ctx = repo[rev]
copies = None
if getrenamed is not None and rev:
copies = []
@@ -4138,22 +4105,11 @@
rename = getrenamed(fn, rev)
if rename:
copies.append((fn, rename[0]))
-
- revmatchfn = None
- if opts.get('patch') or opts.get('stat'):
- if opts.get('follow') or opts.get('follow_first'):
- # note: this might be wrong when following through merges
- revmatchfn = scmutil.match(repo[None], fns, default='path')
- else:
- revmatchfn = matchfn
-
+ revmatchfn = filematcher and filematcher(ctx.rev()) or None
displayer.show(ctx, copies=copies, matchfn=revmatchfn)
-
- for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
- if displayer.flush(ctx.rev()):
+ if displayer.flush(rev):
count += 1
- if count == limit:
- break
+
displayer.close()
@command('manifest',
--- a/tests/test-glog.t Mon Feb 24 22:42:14 2014 +0100
+++ b/tests/test-glog.t Fri Feb 28 15:10:56 2014 -0800
@@ -1972,8 +1972,9 @@
+++ glog.nodes * (glob)
@@ -1,3 +1,3 @@
-nodetag 6
+ -nodetag 7
nodetag 8
- nodetag 7
+ +nodetag 7
+nodetag 6
Test --follow-first and forward --rev
@@ -1988,8 +1989,9 @@
+++ glog.nodes * (glob)
@@ -1,3 +1,3 @@
-nodetag 6
+ -nodetag 7
nodetag 8
- nodetag 7
+ +nodetag 7
+nodetag 6
Test --follow and backward --rev