hgext/graphlog.py
changeset 16405 17deb6bbfbab
parent 16316 0f1e621d3d3b
child 16406 4aa4f50c52b9
equal deleted inserted replaced
16404:9fca5b056c0a 16405:17deb6bbfbab
   269             populate()
   269             populate()
   270         return scmutil.match(wctx, fcache.get(rev, []), default='path')
   270         return scmutil.match(wctx, fcache.get(rev, []), default='path')
   271 
   271 
   272     return filematcher
   272     return filematcher
   273 
   273 
   274 def revset(repo, pats, opts):
   274 def _makelogrevset(repo, pats, opts, revs):
   275     """Return (expr, filematcher) where expr is a revset string built
   275     """Return (expr, filematcher) where expr is a revset string built
   276     log options and file patterns, or None. Note that --rev options
   276     from log options and file patterns or None. If --stat or --patch
   277     are ignored when building expr because we do not know if they are
   277     are not passed filematcher is None. Otherwise it is a callable
   278     proper revsets or legacy expressions like a 'foo-bar' tags. If
   278     taking a revision number and returning a match objects filtering
   279     --stat or --patch are not passed filematcher is None. Otherwise it
   279     the files to be detailed when displaying the revision.
   280     a a callable taking a revision number and returning a match
       
   281     objects filtering the files to be detailed when displaying the
       
   282     revision.
       
   283     """
   280     """
   284     opt2revset = {
   281     opt2revset = {
   285         'follow':           ('follow()', None),
   282         'follow':           ('follow()', None),
   286         'follow_first':     ('_followfirst()', None),
   283         'follow_first':     ('_followfirst()', None),
   287         'no_merges':        ('not merge()', None),
   284         'no_merges':        ('not merge()', None),
   296         'prune':            ('not (%(val)r or ancestors(%(val)r))', ' and '),
   293         'prune':            ('not (%(val)r or ancestors(%(val)r))', ' and '),
   297         'user':             ('user(%(val)r)', ' or '),
   294         'user':             ('user(%(val)r)', ' or '),
   298         }
   295         }
   299 
   296 
   300     opts = dict(opts)
   297     opts = dict(opts)
   301     # branch and only_branch are really aliases and must be handled at
   298     # follow or not follow?
   302     # the same time
       
   303     opts['branch'] = opts.get('branch', []) + opts.get('only_branch', [])
       
   304     follow = opts.get('follow') or opts.get('follow_first')
   299     follow = opts.get('follow') or opts.get('follow_first')
   305     followfirst = opts.get('follow_first')
   300     followfirst = opts.get('follow_first')
   306     if 'follow' in opts:
   301     if 'follow' in opts:
   307         del opts['follow']
   302         del opts['follow']
   308     if 'follow_first' in opts:
   303     if 'follow_first' in opts:
   309         del opts['follow_first']
   304         del opts['follow_first']
       
   305 
       
   306     # branch and only_branch are really aliases and must be handled at
       
   307     # the same time
       
   308     opts['branch'] = opts.get('branch', []) + opts.get('only_branch', [])
   310     # pats/include/exclude are passed to match.match() directly in
   309     # pats/include/exclude are passed to match.match() directly in
   311     # _matchfile() revset but walkchangerevs() builds its matcher with
   310     # _matchfile() revset but walkchangerevs() builds its matcher with
   312     # scmutil.match(). The difference is input pats are globbed on
   311     # scmutil.match(). The difference is input pats are globbed on
   313     # platforms without shell expansion (windows).
   312     # platforms without shell expansion (windows).
   314     pctx = repo[None]
   313     pctx = repo[None]
   390         revset = '(' + ' and '.join(revset) + ')'
   389         revset = '(' + ' and '.join(revset) + ')'
   391     else:
   390     else:
   392         revset = None
   391         revset = None
   393     return revset, filematcher
   392     return revset, filematcher
   394 
   393 
       
   394 def getlogrevs(repo, pats, opts):
       
   395     """Return (revs, expr, filematcher) where revs is a list of
       
   396     revision numbers, expr is a revset string built from log options
       
   397     and file patterns or None, and used to filter 'revs'. If --stat or
       
   398     --patch are not passed filematcher is None. Otherwise it is a
       
   399     callable taking a revision number and returning a match objects
       
   400     filtering the files to be detailed when displaying the revision.
       
   401     """
       
   402     if not len(repo):
       
   403         return [], None, None
       
   404     if opts.get('rev'):
       
   405         revs = scmutil.revrange(repo, opts['rev'])
       
   406     else:
       
   407         revs = range(len(repo))
       
   408     if not revs:
       
   409         return [], None, None
       
   410     expr, filematcher = _makelogrevset(repo, pats, opts, revs)
       
   411     if expr:
       
   412         revs = revsetmod.match(repo.ui, expr)(repo, revs)
       
   413     return revs, expr, filematcher
       
   414 
   395 def generate(ui, dag, displayer, showparents, edgefn, getrenamed=None,
   415 def generate(ui, dag, displayer, showparents, edgefn, getrenamed=None,
   396              filematcher=None):
   416              filematcher=None):
   397     seen, state = [], asciistate()
   417     seen, state = [], asciistate()
   398     for rev, type, ctx, parents in dag:
   418     for rev, type, ctx, parents in dag:
   399         char = ctx.node() in showparents and '@' or 'o'
   419         char = ctx.node() in showparents and '@' or 'o'
   432     directory.
   452     directory.
   433     """
   453     """
   434 
   454 
   435     check_unsupported_flags(pats, opts)
   455     check_unsupported_flags(pats, opts)
   436 
   456 
   437     expr, filematcher = revset(repo, pats, opts)
   457     revs, expr, filematcher = getlogrevs(repo, pats, opts)
   438     if opts.get('rev'):
       
   439         revs = scmutil.revrange(repo, opts['rev'])
       
   440     else:
       
   441         revs = range(len(repo))
       
   442     if expr:
       
   443         revs = revsetmod.match(repo.ui, expr)(repo, revs)
       
   444     revs = sorted(revs, reverse=1)
   458     revs = sorted(revs, reverse=1)
   445     limit = cmdutil.loglimit(opts)
   459     limit = cmdutil.loglimit(opts)
   446     if limit is not None:
   460     if limit is not None:
   447         revs = revs[:limit]
   461         revs = revs[:limit]
   448     revdag = graphmod.dagwalker(repo, revs)
   462     revdag = graphmod.dagwalker(repo, revs)