mercurial/revset.py
changeset 46113 59fa3890d40a
parent 45942 89a2afe31e82
child 46115 be3d8178251e
equal deleted inserted replaced
46112:d6afa9c149c3 46113:59fa3890d40a
     9 
     9 
    10 import re
    10 import re
    11 
    11 
    12 from .i18n import _
    12 from .i18n import _
    13 from .pycompat import getattr
    13 from .pycompat import getattr
       
    14 from .node import (
       
    15     bin,
       
    16     nullrev,
       
    17     wdirrev,
       
    18 )
    14 from . import (
    19 from . import (
    15     dagop,
    20     dagop,
    16     destutil,
    21     destutil,
    17     diffutil,
    22     diffutil,
    18     encoding,
    23     encoding,
    19     error,
    24     error,
    20     grep as grepmod,
    25     grep as grepmod,
    21     hbisect,
    26     hbisect,
    22     match as matchmod,
    27     match as matchmod,
    23     node,
       
    24     obsolete as obsmod,
    28     obsolete as obsmod,
    25     obsutil,
    29     obsutil,
    26     pathutil,
    30     pathutil,
    27     phases,
    31     phases,
    28     pycompat,
    32     pycompat,
    53 generatorset = smartset.generatorset
    57 generatorset = smartset.generatorset
    54 spanset = smartset.spanset
    58 spanset = smartset.spanset
    55 fullreposet = smartset.fullreposet
    59 fullreposet = smartset.fullreposet
    56 
    60 
    57 # revisions not included in all(), but populated if specified
    61 # revisions not included in all(), but populated if specified
    58 _virtualrevs = (node.nullrev, node.wdirrev)
    62 _virtualrevs = (nullrev, wdirrev)
    59 
    63 
    60 # Constants for ordering requirement, used in getset():
    64 # Constants for ordering requirement, used in getset():
    61 #
    65 #
    62 # If 'define', any nested functions and operations MAY change the ordering of
    66 # If 'define', any nested functions and operations MAY change the ordering of
    63 # the entries in the set (but if changes the ordering, it MUST ALWAYS change
    67 # the entries in the set (but if changes the ordering, it MUST ALWAYS change
   175 
   179 
   176 
   180 
   177 def _makerangeset(repo, subset, m, n, order):
   181 def _makerangeset(repo, subset, m, n, order):
   178     if m == n:
   182     if m == n:
   179         r = baseset([m])
   183         r = baseset([m])
   180     elif n == node.wdirrev:
   184     elif n == wdirrev:
   181         r = spanset(repo, m, len(repo)) + baseset([n])
   185         r = spanset(repo, m, len(repo)) + baseset([n])
   182     elif m == node.wdirrev:
   186     elif m == wdirrev:
   183         r = baseset([m]) + spanset(repo, repo.changelog.tiprev(), n - 1)
   187         r = baseset([m]) + spanset(repo, repo.changelog.tiprev(), n - 1)
   184     elif m < n:
   188     elif m < n:
   185         r = spanset(repo, m, n + 1)
   189         r = spanset(repo, m, n + 1)
   186     else:
   190     else:
   187         r = spanset(repo, m, n - 1)
   191         r = spanset(repo, m, n - 1)
   595                     matchrevs.add(bmrev)
   599                     matchrevs.add(bmrev)
   596             for bmrev in matchrevs:
   600             for bmrev in matchrevs:
   597                 bms.add(repo[bmrev].rev())
   601                 bms.add(repo[bmrev].rev())
   598     else:
   602     else:
   599         bms = {repo[r].rev() for r in repo._bookmarks.values()}
   603         bms = {repo[r].rev() for r in repo._bookmarks.values()}
   600     bms -= {node.nullrev}
   604     bms -= {nullrev}
   601     return subset & bms
   605     return subset & bms
   602 
   606 
   603 
   607 
   604 @predicate(b'branch(string or set)', safe=True, weight=10)
   608 @predicate(b'branch(string or set)', safe=True, weight=10)
   605 def branch(repo, subset, x):
   609 def branch(repo, subset, x):
   720     if not parentset:
   724     if not parentset:
   721         return baseset()
   725         return baseset()
   722     cs = set()
   726     cs = set()
   723     pr = repo.changelog.parentrevs
   727     pr = repo.changelog.parentrevs
   724     minrev = parentset.min()
   728     minrev = parentset.min()
   725     nullrev = node.nullrev
       
   726     for r in subset:
   729     for r in subset:
   727         if r <= minrev:
   730         if r <= minrev:
   728             continue
   731             continue
   729         p1, p2 = pr(r)
   732         p1, p2 = pr(r)
   730         if p1 in parentset:
   733         if p1 in parentset:
  1394             if rev is not None:
  1397             if rev is not None:
  1395                 raise error.ParseError(
  1398                 raise error.ParseError(
  1396                     b'_matchfiles expected at most one revision'
  1399                     b'_matchfiles expected at most one revision'
  1397                 )
  1400                 )
  1398             if value == b'':  # empty means working directory
  1401             if value == b'':  # empty means working directory
  1399                 rev = node.wdirrev
  1402                 rev = wdirrev
  1400             else:
  1403             else:
  1401                 rev = value
  1404                 rev = value
  1402         elif prefix == b'd:':
  1405         elif prefix == b'd:':
  1403             if default is not None:
  1406             if default is not None:
  1404                 raise error.ParseError(
  1407                 raise error.ParseError(
  1414     mcache = [None]
  1417     mcache = [None]
  1415 
  1418 
  1416     # This directly read the changelog data as creating changectx for all
  1419     # This directly read the changelog data as creating changectx for all
  1417     # revisions is quite expensive.
  1420     # revisions is quite expensive.
  1418     getfiles = repo.changelog.readfiles
  1421     getfiles = repo.changelog.readfiles
  1419     wdirrev = node.wdirrev
       
  1420 
  1422 
  1421     def matches(x):
  1423     def matches(x):
  1422         if x == wdirrev:
  1424         if x == wdirrev:
  1423             files = repo[x].files()
  1425             files = repo[x].files()
  1424         else:
  1426         else:
  1488     # argument set should never define order
  1490     # argument set should never define order
  1489     if order == defineorder:
  1491     if order == defineorder:
  1490         order = followorder
  1492         order = followorder
  1491     inputset = getset(repo, fullreposet(repo), x, order=order)
  1493     inputset = getset(repo, fullreposet(repo), x, order=order)
  1492     wdirparents = None
  1494     wdirparents = None
  1493     if node.wdirrev in inputset:
  1495     if wdirrev in inputset:
  1494         # a bit slower, but not common so good enough for now
  1496         # a bit slower, but not common so good enough for now
  1495         wdirparents = [p.rev() for p in repo[None].parents()]
  1497         wdirparents = [p.rev() for p in repo[None].parents()]
  1496         inputset = set(inputset)
  1498         inputset = set(inputset)
  1497         inputset.discard(node.wdirrev)
  1499         inputset.discard(wdirrev)
  1498     heads = repo.changelog.headrevs(inputset)
  1500     heads = repo.changelog.headrevs(inputset)
  1499     if wdirparents is not None:
  1501     if wdirparents is not None:
  1500         heads.difference_update(wdirparents)
  1502         heads.difference_update(wdirparents)
  1501         heads.add(node.wdirrev)
  1503         heads.add(wdirrev)
  1502     heads = baseset(heads)
  1504     heads = baseset(heads)
  1503     return subset & heads
  1505     return subset & heads
  1504 
  1506 
  1505 
  1507 
  1506 @predicate(b'hidden()', safe=True)
  1508 @predicate(b'hidden()', safe=True)
  1596 def merge(repo, subset, x):
  1598 def merge(repo, subset, x):
  1597     """Changeset is a merge changeset."""
  1599     """Changeset is a merge changeset."""
  1598     # i18n: "merge" is a keyword
  1600     # i18n: "merge" is a keyword
  1599     getargs(x, 0, 0, _(b"merge takes no arguments"))
  1601     getargs(x, 0, 0, _(b"merge takes no arguments"))
  1600     cl = repo.changelog
  1602     cl = repo.changelog
  1601     nullrev = node.nullrev
       
  1602 
  1603 
  1603     def ismerge(r):
  1604     def ismerge(r):
  1604         try:
  1605         try:
  1605             return cl.parentrevs(r)[1] != nullrev
  1606             return cl.parentrevs(r)[1] != nullrev
  1606         except error.WdirUnsupported:
  1607         except error.WdirUnsupported:
  1690     for ns in namespaces:
  1691     for ns in namespaces:
  1691         for name in ns.listnames(repo):
  1692         for name in ns.listnames(repo):
  1692             if name not in ns.deprecated:
  1693             if name not in ns.deprecated:
  1693                 names.update(repo[n].rev() for n in ns.nodes(repo, name))
  1694                 names.update(repo[n].rev() for n in ns.nodes(repo, name))
  1694 
  1695 
  1695     names -= {node.nullrev}
  1696     names -= {nullrev}
  1696     return subset & names
  1697     return subset & names
  1697 
  1698 
  1698 
  1699 
  1699 @predicate(b'id(string)', safe=True)
  1700 @predicate(b'id(string)', safe=True)
  1700 def node_(repo, subset, x):
  1701 def node_(repo, subset, x):
  1703     l = getargs(x, 1, 1, _(b"id requires one argument"))
  1704     l = getargs(x, 1, 1, _(b"id requires one argument"))
  1704     # i18n: "id" is a keyword
  1705     # i18n: "id" is a keyword
  1705     n = getstring(l[0], _(b"id requires a string"))
  1706     n = getstring(l[0], _(b"id requires a string"))
  1706     if len(n) == 40:
  1707     if len(n) == 40:
  1707         try:
  1708         try:
  1708             rn = repo.changelog.rev(node.bin(n))
  1709             rn = repo.changelog.rev(bin(n))
  1709         except error.WdirUnsupported:
  1710         except error.WdirUnsupported:
  1710             rn = node.wdirrev
  1711             rn = wdirrev
  1711         except (LookupError, TypeError):
  1712         except (LookupError, TypeError):
  1712             rn = None
  1713             rn = None
  1713     else:
  1714     else:
  1714         rn = None
  1715         rn = None
  1715         try:
  1716         try:
  1717             if pm is not None:
  1718             if pm is not None:
  1718                 rn = repo.changelog.rev(pm)
  1719                 rn = repo.changelog.rev(pm)
  1719         except LookupError:
  1720         except LookupError:
  1720             pass
  1721             pass
  1721         except error.WdirUnsupported:
  1722         except error.WdirUnsupported:
  1722             rn = node.wdirrev
  1723             rn = wdirrev
  1723 
  1724 
  1724     if rn is None:
  1725     if rn is None:
  1725         return baseset()
  1726         return baseset()
  1726     result = baseset([rn])
  1727     result = baseset([rn])
  1727     return result & subset
  1728     return result & subset
  1862     for r in getset(repo, fullreposet(repo), x):
  1863     for r in getset(repo, fullreposet(repo), x):
  1863         try:
  1864         try:
  1864             ps.add(cl.parentrevs(r)[0])
  1865             ps.add(cl.parentrevs(r)[0])
  1865         except error.WdirUnsupported:
  1866         except error.WdirUnsupported:
  1866             ps.add(repo[r].p1().rev())
  1867             ps.add(repo[r].p1().rev())
  1867     ps -= {node.nullrev}
  1868     ps -= {nullrev}
  1868     # XXX we should turn this into a baseset instead of a set, smartset may do
  1869     # XXX we should turn this into a baseset instead of a set, smartset may do
  1869     # some optimizations from the fact this is a baseset.
  1870     # some optimizations from the fact this is a baseset.
  1870     return subset & ps
  1871     return subset & ps
  1871 
  1872 
  1872 
  1873 
  1890             ps.add(cl.parentrevs(r)[1])
  1891             ps.add(cl.parentrevs(r)[1])
  1891         except error.WdirUnsupported:
  1892         except error.WdirUnsupported:
  1892             parents = repo[r].parents()
  1893             parents = repo[r].parents()
  1893             if len(parents) == 2:
  1894             if len(parents) == 2:
  1894                 ps.add(parents[1])
  1895                 ps.add(parents[1])
  1895     ps -= {node.nullrev}
  1896     ps -= {nullrev}
  1896     # XXX we should turn this into a baseset instead of a set, smartset may do
  1897     # XXX we should turn this into a baseset instead of a set, smartset may do
  1897     # some optimizations from the fact this is a baseset.
  1898     # some optimizations from the fact this is a baseset.
  1898     return subset & ps
  1899     return subset & ps
  1899 
  1900 
  1900 
  1901 
  1917         for r in getset(repo, fullreposet(repo), x):
  1918         for r in getset(repo, fullreposet(repo), x):
  1918             try:
  1919             try:
  1919                 up(parentrevs(r))
  1920                 up(parentrevs(r))
  1920             except error.WdirUnsupported:
  1921             except error.WdirUnsupported:
  1921                 up(p.rev() for p in repo[r].parents())
  1922                 up(p.rev() for p in repo[r].parents())
  1922     ps -= {node.nullrev}
  1923     ps -= {nullrev}
  1923     return subset & ps
  1924     return subset & ps
  1924 
  1925 
  1925 
  1926 
  1926 def _phase(repo, subset, *targets):
  1927 def _phase(repo, subset, *targets):
  1927     """helper to select all rev in <targets> phases"""
  1928     """helper to select all rev in <targets> phases"""
  1992             except error.WdirUnsupported:
  1993             except error.WdirUnsupported:
  1993                 ps.add(repo[r].p1().rev())
  1994                 ps.add(repo[r].p1().rev())
  1994         else:
  1995         else:
  1995             try:
  1996             try:
  1996                 parents = cl.parentrevs(r)
  1997                 parents = cl.parentrevs(r)
  1997                 if parents[1] != node.nullrev:
  1998                 if parents[1] != nullrev:
  1998                     ps.add(parents[1])
  1999                     ps.add(parents[1])
  1999             except error.WdirUnsupported:
  2000             except error.WdirUnsupported:
  2000                 parents = repo[r].parents()
  2001                 parents = repo[r].parents()
  2001                 if len(parents) == 2:
  2002                 if len(parents) == 2:
  2002                     ps.add(parents[1].rev())
  2003                     ps.add(parents[1].rev())
  2565 @predicate(b'wdir()', safe=True, weight=0)
  2566 @predicate(b'wdir()', safe=True, weight=0)
  2566 def wdir(repo, subset, x):
  2567 def wdir(repo, subset, x):
  2567     """Working directory. (EXPERIMENTAL)"""
  2568     """Working directory. (EXPERIMENTAL)"""
  2568     # i18n: "wdir" is a keyword
  2569     # i18n: "wdir" is a keyword
  2569     getargs(x, 0, 0, _(b"wdir takes no arguments"))
  2570     getargs(x, 0, 0, _(b"wdir takes no arguments"))
  2570     if node.wdirrev in subset or isinstance(subset, fullreposet):
  2571     if wdirrev in subset or isinstance(subset, fullreposet):
  2571         return baseset([node.wdirrev])
  2572         return baseset([wdirrev])
  2572     return baseset()
  2573     return baseset()
  2573 
  2574 
  2574 
  2575 
  2575 def _orderedlist(repo, subset, x):
  2576 def _orderedlist(repo, subset, x):
  2576     s = getstring(x, b"internal error")
  2577     s = getstring(x, b"internal error")
  2636 def _orderedhexlist(repo, subset, x):
  2637 def _orderedhexlist(repo, subset, x):
  2637     s = getstring(x, b"internal error")
  2638     s = getstring(x, b"internal error")
  2638     if not s:
  2639     if not s:
  2639         return baseset()
  2640         return baseset()
  2640     cl = repo.changelog
  2641     cl = repo.changelog
  2641     ls = [cl.rev(node.bin(r)) for r in s.split(b'\0')]
  2642     ls = [cl.rev(bin(r)) for r in s.split(b'\0')]
  2642     s = subset
  2643     s = subset
  2643     return baseset([r for r in ls if r in s])
  2644     return baseset([r for r in ls if r in s])
  2644 
  2645 
  2645 
  2646 
  2646 # for internal use
  2647 # for internal use