##// END OF EJS Templates
revset: support ranges in #generations relation
av6 -
r41395:431cf2c8 default
parent child Browse files
Show More
@@ -28,7 +28,7 b' baseset = smartset.baseset'
28 28 generatorset = smartset.generatorset
29 29
30 30 # possible maximum depth between null and wdir()
31 _maxlogdepth = 0x80000000
31 maxlogdepth = 0x80000000
32 32
33 33 def _walkrevtree(pfunc, revs, startdepth, stopdepth, reverse):
34 34 """Walk DAG using 'pfunc' from the given 'revs' nodes
@@ -42,7 +42,7 b' def _walkrevtree(pfunc, revs, startdepth'
42 42 if startdepth is None:
43 43 startdepth = 0
44 44 if stopdepth is None:
45 stopdepth = _maxlogdepth
45 stopdepth = maxlogdepth
46 46 if stopdepth == 0:
47 47 return
48 48 if stopdepth < 0:
@@ -221,7 +221,7 b' def revdescendants(repo, revs, followfir'
221 221 Scan ends at the stopdepth (exlusive) if specified. Revisions found
222 222 earlier than the startdepth are omitted.
223 223 """
224 if startdepth is None and stopdepth is None:
224 if startdepth is None and (stopdepth is None or stopdepth == maxlogdepth):
225 225 gen = _genrevdescendants(repo, revs, followfirst)
226 226 else:
227 227 gen = _genrevdescendantsofdepth(repo, revs, followfirst,
@@ -225,24 +225,82 b' def notset(repo, subset, x, order):'
225 225 def relationset(repo, subset, x, y, order):
226 226 raise error.ParseError(_("can't use a relation in this context"))
227 227
228 def generationsrel(repo, subset, x, rel, n, order):
229 # TODO: support range, rewrite tests, and drop startdepth argument
230 # from ancestors() and descendants() predicates
231 if n <= 0:
232 n = -n
233 return _ancestors(repo, subset, x, startdepth=n, stopdepth=n + 1)
234 else:
235 return _descendants(repo, subset, x, startdepth=n, stopdepth=n + 1)
228 def _splitrange(a, b):
229 """Split range with bounds a and b into two ranges at 0 and return two
230 tuples of numbers for use as startdepth and stopdepth arguments of
231 revancestors and revdescendants.
232
233 >>> _splitrange(-10, -5) # [-10:-5]
234 ((5, 11), (None, None))
235 >>> _splitrange(5, 10) # [5:10]
236 ((None, None), (5, 11))
237 >>> _splitrange(-10, 10) # [-10:10]
238 ((0, 11), (0, 11))
239 >>> _splitrange(-10, 0) # [-10:0]
240 ((0, 11), (None, None))
241 >>> _splitrange(0, 10) # [0:10]
242 ((None, None), (0, 11))
243 >>> _splitrange(0, 0) # [0:0]
244 ((0, 1), (None, None))
245 >>> _splitrange(1, -1) # [1:-1]
246 ((None, None), (None, None))
247 """
248 ancdepths = (None, None)
249 descdepths = (None, None)
250 if a == b == 0:
251 ancdepths = (0, 1)
252 if a < 0:
253 ancdepths = (-min(b, 0), -a + 1)
254 if b > 0:
255 descdepths = (max(a, 0), b + 1)
256 return ancdepths, descdepths
257
258 def generationsrel(repo, subset, x, rel, a, b, order):
259 # TODO: rewrite tests, and drop startdepth argument from ancestors() and
260 # descendants() predicates
261 (ancstart, ancstop), (descstart, descstop) = _splitrange(a, b)
262
263 if ancstart is None and descstart is None:
264 return baseset()
265
266 revs = getset(repo, fullreposet(repo), x)
267 if not revs:
268 return baseset()
269
270 if ancstart is not None and descstart is not None:
271 s = dagop.revancestors(repo, revs, False, ancstart, ancstop)
272 s += dagop.revdescendants(repo, revs, False, descstart, descstop)
273 elif ancstart is not None:
274 s = dagop.revancestors(repo, revs, False, ancstart, ancstop)
275 elif descstart is not None:
276 s = dagop.revdescendants(repo, revs, False, descstart, descstop)
277
278 return subset & s
236 279
237 280 def relsubscriptset(repo, subset, x, y, z, order):
238 281 # this is pretty basic implementation of 'x#y[z]' operator, still
239 282 # experimental so undocumented. see the wiki for further ideas.
240 283 # https://www.mercurial-scm.org/wiki/RevsetOperatorPlan
241 284 rel = getsymbol(y)
242 n = getinteger(z, _("relation subscript must be an integer"))
285 try:
286 a, b = getrange(z, '')
287 except error.ParseError:
288 a = getinteger(z, _("relation subscript must be an integer"))
289 b = a
290 else:
291 def getbound(i):
292 if i is None:
293 return None
294 msg = _("relation subscript bounds must be integers")
295 return getinteger(i, msg)
296 a, b = [getbound(i) for i in (a, b)]
297 if a is None:
298 a = -(dagop.maxlogdepth - 1)
299 if b is None:
300 b = +(dagop.maxlogdepth - 1)
243 301
244 302 if rel in subscriptrelations:
245 return subscriptrelations[rel](repo, subset, x, rel, n, order)
303 return subscriptrelations[rel](repo, subset, x, rel, a, b, order)
246 304
247 305 relnames = [r for r in subscriptrelations.keys() if len(r) > 1]
248 306 raise error.UnknownIdentifier(rel, relnames)
@@ -62,6 +62,7 b" testmod('mercurial.parser')"
62 62 testmod('mercurial.pycompat')
63 63 testmod('mercurial.revlog')
64 64 testmod('mercurial.revlogutils.deltas')
65 testmod('mercurial.revset')
65 66 testmod('mercurial.revsetlang')
66 67 testmod('mercurial.smartset')
67 68 testmod('mercurial.store')
@@ -648,6 +648,9 b' parse errors of relation, subscript and '
648 648 $ hg debugrevspec '.#generations[1-2]'
649 649 hg: parse error: relation subscript must be an integer
650 650 [255]
651 $ hg debugrevspec '.#generations[foo:bar]'
652 hg: parse error: relation subscript bounds must be integers
653 [255]
651 654
652 655 suggested relations
653 656
@@ -1274,6 +1277,30 b' test ancestors/descendants relation subs'
1274 1277 $ log '.#g[(-1)]'
1275 1278 8
1276 1279
1280 $ log '6#generations[0:1]'
1281 6
1282 7
1283 $ log '6#generations[-1:1]'
1284 4
1285 5
1286 6
1287 7
1288 $ log '6#generations[0:]'
1289 6
1290 7
1291 $ log '5#generations[:0]'
1292 0
1293 1
1294 3
1295 5
1296 $ log '3#generations[:]'
1297 0
1298 1
1299 3
1300 5
1301 6
1302 7
1303
1277 1304 $ hg debugrevspec -p parsed 'roots(:)#g[2]'
1278 1305 * parsed:
1279 1306 (relsubscript
General Comments 0
You need to be logged in to leave comments. Login now