D452: revset: add an order-aware intersect helper function
quark (Jun Wu)
phabricator at mercurial-scm.org
Sun Aug 20 16:14:00 EDT 2017
quark updated this revision to Diff 1112.
REPOSITORY
rHG Mercurial
CHANGES SINCE LAST UPDATE
https://phab.mercurial-scm.org/D452?vs=1109&id=1112
REVISION DETAIL
https://phab.mercurial-scm.org/D452
AFFECTED FILES
mercurial/revset.py
tests/test-revset.t
CHANGE DETAILS
diff --git a/tests/test-revset.t b/tests/test-revset.t
--- a/tests/test-revset.t
+++ b/tests/test-revset.t
@@ -1477,7 +1477,7 @@
* set:
<filteredset
<spanset+ 0:2>,
- <spanset+ 0:3>>
+ <spanset- 0:3>>
0
1
@@ -1978,7 +1978,7 @@
<spanset- 0:4>,
<spanset+ 0:4>>,
<not
- <spanset+ 1:3>>>
+ <spanset- 1:3>>>
3
0
@@ -2403,8 +2403,8 @@
('string', '0\x002\x001'))))
* set:
<filteredset
- <spanset- 0:3>,
- <baseset [1]>>
+ <baseset [1]>,
+ <spanset- 0:3>>
1
'A & B' can be rewritten as 'B & A' by weight. When ordering needs to be
@@ -2521,13 +2521,11 @@
('symbol', '2'))))))
* set:
<filteredset
- <baseset [0, 2, 1]>,
- <baseset+ [0, 1, 2]>>
+ <baseset+ [0, 1, 2]>,
+ <baseset [0, 2, 1]>>
0
+ 1
2
- 1
-
- WRONG: should take dagrange order (0, 1, 2)
'A + B' can be rewritten to 'B + A' by weight only when the order doesn't
matter (e.g. 'X & (A + B)' can be 'X & (B + A)', but '(A + B) & X' can't):
diff --git a/mercurial/revset.py b/mercurial/revset.py
--- a/mercurial/revset.py
+++ b/mercurial/revset.py
@@ -57,6 +57,39 @@
raise error.ParseError(_("missing argument"))
return methods[x[0]](repo, subset, *x[1:], order=order)
+def intersect(subset, newset, order):
+ """intersect two revsets with order preserved as requested
+
+ If order is "followorder", preserve subset's order. If order is
+ "defineorder", preserve newset's order.
+
+ A typical use of this function is::
+
+ @revsetpredicate('myrevset', takeorder=True)
+ def myrevset(repo, subset, x, order):
+ newset = ... # a smartset that implements "myrevset"
+ return revset.intersect(subset, newset, order)
+ """
+ # some old code does not use smartset, normalize to smartset
+ if not util.safehasattr(newset, 'isascending'):
+ newset = subset & newset
+ if order == defineorder:
+ newset.sort()
+
+ # ordering does not matter if there are at most 1 revision (test quickly)
+ if isinstance(newset, baseset) and len(newset) <= 1:
+ return newset & subset
+
+ if order == followorder:
+ return subset & newset
+ elif order == defineorder:
+ return newset & subset
+
+ assert order == anyorder
+
+ # newset is usually smaller, prefer it on the left
+ return newset & subset
+
def _getrevsource(repo, r):
extra = repo[r].extra()
for label in ('source', 'transplant_source', 'rebase_source'):
@@ -113,17 +146,13 @@
else:
r = spanset(repo, m, n - 1)
- if order == defineorder:
- return r & subset
- else:
- # carrying the sorting over when possible would be more efficient
- return subset & r
+ return intersect(subset, r, order)
def dagrange(repo, subset, x, y, order):
r = fullreposet(repo)
xs = dagop.reachableroots(repo, getset(repo, r, x), getset(repo, r, y),
includepath=True)
- return subset & xs
+ return intersect(subset, xs, order)
def andset(repo, subset, x, y, order):
if order == anyorder:
@@ -1143,9 +1172,7 @@
raise error.ParseError(_("negative offset"))
os = getset(repo, fullreposet(repo), args['set'], defineorder)
ls = os.slice(ofs, ofs + lim)
- if order == followorder and lim > 1:
- return subset & ls
- return ls & subset
+ return intersect(subset, ls, order)
@predicate('last(set, [n])', safe=True, takeorder=True)
def last(repo, subset, x, order):
@@ -1162,10 +1189,8 @@
os = getset(repo, fullreposet(repo), l[0], defineorder)
os.reverse()
ls = os.slice(0, lim)
- if order == followorder and lim > 1:
- return subset & ls
ls.reverse()
- return ls & subset
+ return intersect(subset, ls, order)
@predicate('max(set)', safe=True)
def maxrev(repo, subset, x):
@@ -1523,7 +1548,7 @@
parents = repo[r].parents()
if len(parents) == 2:
ps.add(parents[1].rev())
- return subset & ps
+ return intersect(subset, ps, order)
@predicate('present(set)', safe=True, takeorder=True)
def present(repo, subset, x, order):
To: quark, #hg-reviewers
Cc: mercurial-devel
More information about the Mercurial-devel
mailing list