D452: revset: add an order-aware intersect helper function
quark (Jun Wu)
phabricator at mercurial-scm.org
Sun Aug 20 07:27:15 UTC 2017
quark created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.
REVISION SUMMARY
The code to handle `order` is a bit repetitive and error prone (`dagrange`
is an example). This patch adds an `revset.intersect` helper function to
make related area cleaner.
REPOSITORY
rHG Mercurial
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
@@ -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,34 @@
raise error.ParseError(_("missing argument"))
return methods[x[0]](repo, subset, *x[1:], order=order)
+def intersect(subset, newset, order=followorder):
+ """intersect two revsets with order preserved as request
+
+ 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)
+ """
+ # newset is not a smartset - enforce "followorder", since "defineorder"
+ # may not make sense in this case (ex. "set" is unordered)
+ if not util.safehasattr(newset, 'isascending'):
+ return subset & newset
+
+ 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 +141,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:
@@ -1142,9 +1166,9 @@
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
+ if lim <= 1:
+ return ls & subset
+ return intersect(subset, ls, order)
@predicate('last(set, [n])', safe=True, takeorder=True)
def last(repo, subset, x, order):
@@ -1161,10 +1185,10 @@
os = getset(repo, fullreposet(repo), l[0], defineorder)
os.reverse()
ls = os.slice(0, lim)
- if order == followorder and lim > 1:
- return subset & ls
+ if lim <= 1:
+ return ls & subset
ls.reverse()
- return ls & subset
+ return intersect(subset, ls, order)
@predicate('max(set)', safe=True)
def maxrev(repo, subset, x):
@@ -1522,7 +1546,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