# HG changeset patch # User Lucas Moscovicz # Date 2014-02-28 23:10:56 # Node ID 69402eb72115417b67c86eef6161e5f11394fb2f # Parent 99b5eaf372a77e249f1481dc02bcc31a893d4901 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. diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py --- a/mercurial/cmdutil.py +++ b/mercurial/cmdutil.py @@ -1673,6 +1673,54 @@ def getgraphlogrevs(repo, pats, opts): 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() diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -4082,55 +4082,22 @@ def log(ui, repo, *pats, **opts): 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 @@ def log(ui, repo, *pats, **opts): 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', diff --git a/tests/test-glog.t b/tests/test-glog.t --- a/tests/test-glog.t +++ b/tests/test-glog.t @@ -1972,8 +1972,9 @@ Test --follow and forward --rev +++ 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 @@ Test --follow-first and forward --rev +++ glog.nodes * (glob) @@ -1,3 +1,3 @@ -nodetag 6 + -nodetag 7 nodetag 8 - nodetag 7 + +nodetag 7 +nodetag 6 Test --follow and backward --rev