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, |