mercurial/dagop.py
changeset 34065 c6c8a52e28c9
parent 33284 b2670290eab4
child 35270 0d27685b4a2f
equal deleted inserted replaced
34064:8b659b7388c0 34065:c6c8a52e28c9
    73         if foundnew and pdepth < stopdepth:
    73         if foundnew and pdepth < stopdepth:
    74             for prev in pfunc(currev):
    74             for prev in pfunc(currev):
    75                 if prev != node.nullrev:
    75                 if prev != node.nullrev:
    76                     heapq.heappush(pendingheap, (heapsign * prev, pdepth))
    76                     heapq.heappush(pendingheap, (heapsign * prev, pdepth))
    77 
    77 
    78 def _genrevancestors(repo, revs, followfirst, startdepth, stopdepth):
    78 def _genrevancestors(repo, revs, followfirst, startdepth, stopdepth, cutfunc):
    79     if followfirst:
    79     if followfirst:
    80         cut = 1
    80         cut = 1
    81     else:
    81     else:
    82         cut = None
    82         cut = None
    83     cl = repo.changelog
    83     cl = repo.changelog
    84     def pfunc(rev):
    84     def plainpfunc(rev):
    85         try:
    85         try:
    86             return cl.parentrevs(rev)[:cut]
    86             return cl.parentrevs(rev)[:cut]
    87         except error.WdirUnsupported:
    87         except error.WdirUnsupported:
    88             return (pctx.rev() for pctx in repo[rev].parents()[:cut])
    88             return (pctx.rev() for pctx in repo[rev].parents()[:cut])
       
    89     if cutfunc is None:
       
    90         pfunc = plainpfunc
       
    91     else:
       
    92         pfunc = lambda rev: [r for r in plainpfunc(rev) if not cutfunc(r)]
       
    93         revs = revs.filter(lambda rev: not cutfunc(rev))
    89     return _walkrevtree(pfunc, revs, startdepth, stopdepth, reverse=True)
    94     return _walkrevtree(pfunc, revs, startdepth, stopdepth, reverse=True)
    90 
    95 
    91 def revancestors(repo, revs, followfirst, startdepth=None, stopdepth=None):
    96 def revancestors(repo, revs, followfirst=False, startdepth=None,
       
    97                  stopdepth=None, cutfunc=None):
    92     """Like revlog.ancestors(), but supports additional options, includes
    98     """Like revlog.ancestors(), but supports additional options, includes
    93     the given revs themselves, and returns a smartset
    99     the given revs themselves, and returns a smartset
    94 
   100 
    95     Scan ends at the stopdepth (exlusive) if specified. Revisions found
   101     Scan ends at the stopdepth (exlusive) if specified. Revisions found
    96     earlier than the startdepth are omitted.
   102     earlier than the startdepth are omitted.
    97     """
   103 
    98     gen = _genrevancestors(repo, revs, followfirst, startdepth, stopdepth)
   104     If cutfunc is provided, it will be used to cut the traversal of the DAG.
       
   105     When cutfunc(X) returns True, the DAG traversal stops - revision X and
       
   106     X's ancestors in the traversal path will be skipped. This could be an
       
   107     optimization sometimes.
       
   108 
       
   109     Note: if Y is an ancestor of X, cutfunc(X) returning True does not
       
   110     necessarily mean Y will also be cut. Usually cutfunc(Y) also wants to
       
   111     return True in this case. For example,
       
   112 
       
   113         D     # revancestors(repo, D, cutfunc=lambda rev: rev == B)
       
   114         |\    # will include "A", because the path D -> C -> A was not cut.
       
   115         B C   # If "B" gets cut, "A" might want to be cut too.
       
   116         |/
       
   117         A
       
   118     """
       
   119     gen = _genrevancestors(repo, revs, followfirst, startdepth, stopdepth,
       
   120                            cutfunc)
    99     return generatorset(gen, iterasc=False)
   121     return generatorset(gen, iterasc=False)
   100 
   122 
   101 def _genrevdescendants(repo, revs, followfirst):
   123 def _genrevdescendants(repo, revs, followfirst):
   102     if followfirst:
   124     if followfirst:
   103         cut = 1
   125         cut = 1