hgext/graphlog.py
changeset 16777 058e14da7044
parent 16743 38caf405d010
child 17119 2e13c1bd34dc
equal deleted inserted replaced
16776:5088d0b9a9a1 16777:058e14da7044
   390     else:
   390     else:
   391         expr = None
   391         expr = None
   392     return expr, filematcher
   392     return expr, filematcher
   393 
   393 
   394 def getlogrevs(repo, pats, opts):
   394 def getlogrevs(repo, pats, opts):
   395     """Return (revs, expr, filematcher) where revs is a list of
   395     """Return (revs, expr, filematcher) where revs is an iterable of
   396     revision numbers, expr is a revset string built from log options
   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
   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
   398     --patch are not passed filematcher is None. Otherwise it is a
   399     callable taking a revision number and returning a match objects
   399     callable taking a revision number and returning a match objects
   400     filtering the files to be detailed when displaying the revision.
   400     filtering the files to be detailed when displaying the revision.
   401     """
   401     """
       
   402     def increasingrevs(repo, revs, matcher):
       
   403         # The sorted input rev sequence is chopped in sub-sequences
       
   404         # which are sorted in ascending order and passed to the
       
   405         # matcher. The filtered revs are sorted again as they were in
       
   406         # the original sub-sequence. This achieve several things:
       
   407         #
       
   408         # - getlogrevs() now returns a generator which behaviour is
       
   409         #   adapted to log need. First results come fast, last ones
       
   410         #   are batched for performances.
       
   411         #
       
   412         # - revset matchers often operate faster on revision in
       
   413         #   changelog order, because most filters deal with the
       
   414         #   changelog.
       
   415         #
       
   416         # - revset matchers can reorder revisions. "A or B" typically
       
   417         #   returns returns the revision matching A then the revision
       
   418         #   matching B. We want to hide this internal implementation
       
   419         #   detail from the caller, and sorting the filtered revision
       
   420         #   again achieves this.
       
   421         for i, window in cmdutil.increasingwindows(0, len(revs), windowsize=1):
       
   422             orevs = revs[i:i + window]
       
   423             nrevs = set(matcher(repo, sorted(orevs)))
       
   424             for rev in orevs:
       
   425                 if rev in nrevs:
       
   426                     yield rev
       
   427 
   402     if not len(repo):
   428     if not len(repo):
   403         return [], None, None
   429         return iter([]), None, None
   404     # Default --rev value depends on --follow but --follow behaviour
   430     # Default --rev value depends on --follow but --follow behaviour
   405     # depends on revisions resolved from --rev...
   431     # depends on revisions resolved from --rev...
   406     follow = opts.get('follow') or opts.get('follow_first')
   432     follow = opts.get('follow') or opts.get('follow_first')
   407     if opts.get('rev'):
   433     if opts.get('rev'):
   408         revs = scmutil.revrange(repo, opts['rev'])
   434         revs = scmutil.revrange(repo, opts['rev'])
   410         if follow and len(repo) > 0:
   436         if follow and len(repo) > 0:
   411             revs = scmutil.revrange(repo, ['.:0'])
   437             revs = scmutil.revrange(repo, ['.:0'])
   412         else:
   438         else:
   413             revs = range(len(repo) - 1, -1, -1)
   439             revs = range(len(repo) - 1, -1, -1)
   414     if not revs:
   440     if not revs:
   415         return [], None, None
   441         return iter([]), None, None
   416     expr, filematcher = _makelogrevset(repo, pats, opts, revs)
   442     expr, filematcher = _makelogrevset(repo, pats, opts, revs)
   417     if expr:
   443     if expr:
   418         # Evaluate revisions in changelog order for performance
   444         matcher = revset.match(repo.ui, expr)
   419         # reasons but preserve the original sequence order in the
   445         revs = increasingrevs(repo, revs, matcher)
   420         # filtered result.
       
   421         matched = set(revset.match(repo.ui, expr)(repo, sorted(revs)))
       
   422         revs = [r for r in revs if r in matched]
       
   423     if not opts.get('hidden'):
   446     if not opts.get('hidden'):
   424         # --hidden is still experimental and not worth a dedicated revset
   447         # --hidden is still experimental and not worth a dedicated revset
   425         # yet. Fortunately, filtering revision number is fast.
   448         # yet. Fortunately, filtering revision number is fast.
   426         revs = [r for r in revs if r not in repo.changelog.hiddenrevs]
   449         revs = (r for r in revs if r not in repo.changelog.hiddenrevs)
       
   450     else:
       
   451         revs = iter(revs)
   427     return revs, expr, filematcher
   452     return revs, expr, filematcher
   428 
   453 
   429 def generate(ui, dag, displayer, showparents, edgefn, getrenamed=None,
   454 def generate(ui, dag, displayer, showparents, edgefn, getrenamed=None,
   430              filematcher=None):
   455              filematcher=None):
   431     seen, state = [], asciistate()
   456     seen, state = [], asciistate()