[PATCH 3 of 3 RFC V3] log: changed implementation to use graphlog code

Pierre-Yves David pierre-yves.david at ens-lyon.org
Mon Apr 14 00:01:47 CDT 2014


On 03/10/2014 02:27 PM, Lucas Moscovicz wrote:
> # HG changeset patch
> # User Lucas Moscovicz <lmoscovicz at fb.com>
> # Date 1393629056 28800
> #      Fri Feb 28 15:10:56 2014 -0800
> # Node ID c92e09b96370180719b1fdc4c23e3119c8466564
> # Parent  b30cc2e46ac6cc9c41799dc911be8b4bfc1a9f18
> log: changed implementation to use graphlog code

What about this RFC patches, is that something we ended up queuing 
before you left? Or is this something that still needs to be done?


>
> 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
> @@ -1451,7 +1451,7 @@
>
>       return filematcher
>
> -def _makegraphlogrevset(repo, pats, opts, revs):
> +def _makelogrevset(repo, pats, opts, revs):
>       """Return (expr, filematcher) where expr is a revset string built
>       from log options and file patterns or None. If --stat or --patch
>       are not passed filematcher is None. Otherwise it is a callable
> @@ -1606,7 +1606,7 @@
>       possiblyunsorted = False # whether revs might need sorting
>       if opts.get('rev'):
>           revs = scmutil.revrange(repo, opts['rev'])
> -        # Don't sort here because _makegraphlogrevset might depend on the
> +        # Don't sort here because _makelogrevset might depend on the
>           # order of revs
>           possiblyunsorted = True
>       else:
> @@ -1617,7 +1617,7 @@
>               revs.reverse()
>       if not revs:
>           return revset.baseset([]), None, None
> -    expr, filematcher = _makegraphlogrevset(repo, pats, opts, revs)
> +    expr, filematcher = _makelogrevset(repo, pats, opts, revs)
>       if possiblyunsorted:
>           revs.sort(reverse=True)
>       if expr:
> @@ -1644,6 +1644,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()
> diff --git a/mercurial/commands.py b/mercurial/commands.py
> --- a/mercurial/commands.py
> +++ b/mercurial/commands.py
> @@ -4054,55 +4054,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 = []
> @@ -4110,22 +4077,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',
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel at selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel
>


More information about the Mercurial-devel mailing list