mercurial/revset.py
changeset 16409 2cbd7dd0cc1f
parent 16402 1fb2f1400ea8
child 16411 4c2edcd84175
equal deleted inserted replaced
16408:d74099ac2ac1 16409:2cbd7dd0cc1f
    10 import node as nodemod
    10 import node as nodemod
    11 import bookmarks as bookmarksmod
    11 import bookmarks as bookmarksmod
    12 import match as matchmod
    12 import match as matchmod
    13 from i18n import _
    13 from i18n import _
    14 import encoding
    14 import encoding
       
    15 
       
    16 def _revancestors(repo, revs, followfirst):
       
    17     """Like revlog.ancestors(), but supports followfirst."""
       
    18     cut = followfirst and 1 or None
       
    19     cl = repo.changelog
       
    20     visit = list(revs)
       
    21     seen = set([nodemod.nullrev])
       
    22     while visit:
       
    23         for parent in cl.parentrevs(visit.pop(0))[:cut]:
       
    24             if parent not in seen:
       
    25                 visit.append(parent)
       
    26                 seen.add(parent)
       
    27                 yield parent
       
    28 
       
    29 def _revdescendants(repo, revs, followfirst):
       
    30     """Like revlog.descendants() but supports followfirst."""
       
    31     cut = followfirst and 1 or None
       
    32     cl = repo.changelog
       
    33     first = min(revs)
       
    34     if first == nodemod.nullrev:
       
    35         # Are there nodes with a null first parent and a non-null
       
    36         # second one? Maybe. Do we care? Probably not.
       
    37         for i in cl:
       
    38             yield i
       
    39         return
       
    40 
       
    41     seen = set(revs)
       
    42     for i in xrange(first + 1, len(cl)):
       
    43         for x in cl.parentrevs(i)[:cut]:
       
    44             if x != nodemod.nullrev and x in seen:
       
    45                 seen.add(i)
       
    46                 yield i
       
    47                 break
    15 
    48 
    16 elements = {
    49 elements = {
    17     "(": (20, ("group", 1, ")"), ("func", 1, ")")),
    50     "(": (20, ("group", 1, ")"), ("func", 1, ")")),
    18     "~": (18, None, ("ancestor", 18)),
    51     "~": (18, None, ("ancestor", 18)),
    19     "^": (18, None, ("parent", 18), ("parentpost", 18)),
    52     "^": (18, None, ("parent", 18), ("parentpost", 18)),
   201         raise error.ParseError(_("ancestor arguments must be single revisions"))
   234         raise error.ParseError(_("ancestor arguments must be single revisions"))
   202     an = [repo[a[0]].ancestor(repo[b[0]]).rev()]
   235     an = [repo[a[0]].ancestor(repo[b[0]]).rev()]
   203 
   236 
   204     return [r for r in an if r in subset]
   237     return [r for r in an if r in subset]
   205 
   238 
       
   239 def _ancestors(repo, subset, x, followfirst=False):
       
   240     args = getset(repo, range(len(repo)), x)
       
   241     if not args:
       
   242         return []
       
   243     s = set(_revancestors(repo, args, followfirst)) | set(args)
       
   244     return [r for r in subset if r in s]
       
   245 
   206 def ancestors(repo, subset, x):
   246 def ancestors(repo, subset, x):
   207     """``ancestors(set)``
   247     """``ancestors(set)``
   208     Changesets that are ancestors of a changeset in set.
   248     Changesets that are ancestors of a changeset in set.
   209     """
   249     """
   210     args = getset(repo, range(len(repo)), x)
   250     return _ancestors(repo, subset, x)
   211     if not args:
   251 
   212         return []
   252 def _firstancestors(repo, subset, x):
   213     s = set(repo.changelog.ancestors(*args)) | set(args)
   253     # ``_firstancestors(set)``
   214     return [r for r in subset if r in s]
   254     # Like ``ancestors(set)`` but follows only the first parents.
       
   255     return _ancestors(repo, subset, x, followfirst=True)
   215 
   256 
   216 def ancestorspec(repo, subset, x, n):
   257 def ancestorspec(repo, subset, x, n):
   217     """``set~n``
   258     """``set~n``
   218     Changesets that are the Nth ancestor (first parents only) of a changeset in set.
   259     Changesets that are the Nth ancestor (first parents only) of a changeset in set.
   219     """
   260     """
   393         c = repo[r]
   434         c = repo[r]
   394         if ds in encoding.lower(c.description()):
   435         if ds in encoding.lower(c.description()):
   395             l.append(r)
   436             l.append(r)
   396     return l
   437     return l
   397 
   438 
       
   439 def _descendants(repo, subset, x, followfirst=False):
       
   440     args = getset(repo, range(len(repo)), x)
       
   441     if not args:
       
   442         return []
       
   443     s = set(_revdescendants(repo, args, followfirst)) | set(args)
       
   444     return [r for r in subset if r in s]
       
   445 
   398 def descendants(repo, subset, x):
   446 def descendants(repo, subset, x):
   399     """``descendants(set)``
   447     """``descendants(set)``
   400     Changesets which are descendants of changesets in set.
   448     Changesets which are descendants of changesets in set.
   401     """
   449     """
   402     args = getset(repo, range(len(repo)), x)
   450     return _descendants(repo, subset, x)
   403     if not args:
   451 
   404         return []
   452 def _firstdescendants(repo, subset, x):
   405     s = set(repo.changelog.descendants(*args)) | set(args)
   453     # ``_firstdescendants(set)``
   406     return [r for r in subset if r in s]
   454     # Like ``descendants(set)`` but follows only the first parents.
       
   455     return _descendants(repo, subset, x, followfirst=True)
   407 
   456 
   408 def draft(repo, subset, x):
   457 def draft(repo, subset, x):
   409     """``draft()``
   458     """``draft()``
   410     Changeset in draft phase."""
   459     Changeset in draft phase."""
   411     getargs(x, 0, 0, _("draft takes no arguments"))
   460     getargs(x, 0, 0, _("draft takes no arguments"))
   452             # include the revision responsible for the most recent version
   501             # include the revision responsible for the most recent version
   453             s.add(cx.linkrev())
   502             s.add(cx.linkrev())
   454         else:
   503         else:
   455             return []
   504             return []
   456     else:
   505     else:
   457         cut = followfirst and 1 or None
   506         s = set(_revancestors(repo, [c.rev()], followfirst)) | set([c.rev()])
   458         cl = repo.changelog
       
   459         s = set()
       
   460         visit = [c.rev()]
       
   461         while visit:
       
   462             for prev in cl.parentrevs(visit.pop(0))[:cut]:
       
   463                 if prev not in s and prev != nodemod.nullrev:
       
   464                     visit.append(prev)
       
   465                     s.add(prev)
       
   466         s.add(c.rev())
       
   467 
   507 
   468     return [r for r in subset if r in s]
   508     return [r for r in subset if r in s]
   469 
   509 
   470 def follow(repo, subset, x):
   510 def follow(repo, subset, x):
   471     """``follow([file])``
   511     """``follow([file])``
  1053 symbols = {
  1093 symbols = {
  1054     "adds": adds,
  1094     "adds": adds,
  1055     "all": getall,
  1095     "all": getall,
  1056     "ancestor": ancestor,
  1096     "ancestor": ancestor,
  1057     "ancestors": ancestors,
  1097     "ancestors": ancestors,
       
  1098     "_firstancestors": _firstancestors,
  1058     "author": author,
  1099     "author": author,
  1059     "bisect": bisect,
  1100     "bisect": bisect,
  1060     "bisected": bisected,
  1101     "bisected": bisected,
  1061     "bookmark": bookmark,
  1102     "bookmark": bookmark,
  1062     "branch": branch,
  1103     "branch": branch,
  1064     "closed": closed,
  1105     "closed": closed,
  1065     "contains": contains,
  1106     "contains": contains,
  1066     "date": date,
  1107     "date": date,
  1067     "desc": desc,
  1108     "desc": desc,
  1068     "descendants": descendants,
  1109     "descendants": descendants,
       
  1110     "_firstdescendants": _firstdescendants,
  1069     "draft": draft,
  1111     "draft": draft,
  1070     "file": hasfile,
  1112     "file": hasfile,
  1071     "filelog": filelog,
  1113     "filelog": filelog,
  1072     "first": first,
  1114     "first": first,
  1073     "follow": follow,
  1115     "follow": follow,