Show More
@@ -237,7 +237,7 b' def get_revs(repo, rev_opt):' | |||||
237 | return (len(repo) - 1, 0) |
|
237 | return (len(repo) - 1, 0) | |
238 |
|
238 | |||
239 | def check_unsupported_flags(pats, opts): |
|
239 | def check_unsupported_flags(pats, opts): | |
240 |
for op in [ |
|
240 | for op in ["copies", "newest_first"]: | |
241 | if op in opts and opts[op]: |
|
241 | if op in opts and opts[op]: | |
242 | raise util.Abort(_("-G/--graph option is incompatible with --%s") |
|
242 | raise util.Abort(_("-G/--graph option is incompatible with --%s") | |
243 | % op.replace("_", "-")) |
|
243 | % op.replace("_", "-")) | |
@@ -246,18 +246,20 b' def revset(repo, pats, opts):' | |||||
246 | """Return revset str built of revisions, log options and file patterns. |
|
246 | """Return revset str built of revisions, log options and file patterns. | |
247 | """ |
|
247 | """ | |
248 | opt2revset = { |
|
248 | opt2revset = { | |
249 | 'follow': ('follow()', None), |
|
249 | 'follow': ('follow()', None), | |
250 |
' |
|
250 | 'follow_first': ('_followfirst()', None), | |
251 |
' |
|
251 | 'no_merges': ('not merge()', None), | |
252 |
' |
|
252 | 'only_merges': ('merge()', None), | |
253 |
' |
|
253 | 'removed': ('removes("*")', None), | |
254 |
' |
|
254 | 'date': ('date(%(val)r)', None), | |
255 |
' |
|
255 | 'branch': ('branch(%(val)r)', ' or '), | |
256 |
'_pats |
|
256 | '_patslog': ('filelog(%(val)r)', ' or '), | |
257 |
' |
|
257 | '_patsfollow': ('follow(%(val)r)', ' or '), | |
258 | 'prune': ('not (%(val)r or ancestors(%(val)r))', ' and '), |
|
258 | '_patsfollowfirst': ('_followfirst(%(val)r)', ' or '), | |
259 |
' |
|
259 | 'keyword': ('keyword(%(val)r)', ' or '), | |
260 |
're |
|
260 | 'prune': ('not (%(val)r or ancestors(%(val)r))', ' and '), | |
|
261 | 'user': ('user(%(val)r)', ' or '), | |||
|
262 | 'rev': ('%(val)s', ' or '), | |||
261 | } |
|
263 | } | |
262 |
|
264 | |||
263 | opts = dict(opts) |
|
265 | opts = dict(opts) | |
@@ -266,9 +268,12 b' def revset(repo, pats, opts):' | |||||
266 | if 'branch' in opts and 'only_branch' in opts: |
|
268 | if 'branch' in opts and 'only_branch' in opts: | |
267 | opts['branch'] = opts['branch'] + opts.pop('only_branch') |
|
269 | opts['branch'] = opts['branch'] + opts.pop('only_branch') | |
268 |
|
270 | |||
269 | follow = opts.get('follow') |
|
271 | follow = opts.get('follow') or opts.get('follow_first') | |
|
272 | followfirst = opts.get('follow_first') | |||
270 | if 'follow' in opts: |
|
273 | if 'follow' in opts: | |
271 | del opts['follow'] |
|
274 | del opts['follow'] | |
|
275 | if 'follow_first' in opts: | |||
|
276 | del opts['follow_first'] | |||
272 | # pats/include/exclude are passed to match.match() directly in |
|
277 | # pats/include/exclude are passed to match.match() directly in | |
273 | # _matchfile() revset but walkchangerevs() builds its matcher with |
|
278 | # _matchfile() revset but walkchangerevs() builds its matcher with | |
274 | # scmutil.match(). The difference is input pats are globbed on |
|
279 | # scmutil.match(). The difference is input pats are globbed on | |
@@ -310,10 +315,16 b' def revset(repo, pats, opts):' | |||||
310 | opts['rev'] = opts.get('rev', []) + ['_matchfiles(%s)' % matchargs] |
|
315 | opts['rev'] = opts.get('rev', []) + ['_matchfiles(%s)' % matchargs] | |
311 | else: |
|
316 | else: | |
312 | if follow: |
|
317 | if follow: | |
313 |
if |
|
318 | if followfirst: | |
314 | opts['_patsfollow'] = list(pats) |
|
319 | if pats: | |
|
320 | opts['_patsfollowfirst'] = list(pats) | |||
|
321 | else: | |||
|
322 | opts['follow_first'] = True | |||
315 | else: |
|
323 | else: | |
316 |
|
|
324 | if pats: | |
|
325 | opts['_patsfollow'] = list(pats) | |||
|
326 | else: | |||
|
327 | opts['follow'] = True | |||
317 | else: |
|
328 | else: | |
318 | opts['_patslog'] = list(pats) |
|
329 | opts['_patslog'] = list(pats) | |
319 |
|
330 |
@@ -465,6 +465,40 b' def follow(repo, subset, x):' | |||||
465 |
|
465 | |||
466 | return [r for r in subset if r in s] |
|
466 | return [r for r in subset if r in s] | |
467 |
|
467 | |||
|
468 | def _followfirst(repo, subset, x): | |||
|
469 | # ``followfirst([file])`` | |||
|
470 | # Like ``follow([file])`` but follows only the first parent of | |||
|
471 | # every revision or file revision. | |||
|
472 | # i18n: "_followfirst" is a keyword | |||
|
473 | l = getargs(x, 0, 1, _("_followfirst takes no arguments or a filename")) | |||
|
474 | c = repo['.'] | |||
|
475 | if l: | |||
|
476 | x = getstring(l[0], _("_followfirst expected a filename")) | |||
|
477 | if x not in c: | |||
|
478 | return [] | |||
|
479 | cx = c[x] | |||
|
480 | visit = {} | |||
|
481 | s = set([cx.linkrev()]) | |||
|
482 | while True: | |||
|
483 | for p in cx.parents()[:1]: | |||
|
484 | visit[(p.rev(), p.node())] = p | |||
|
485 | if not visit: | |||
|
486 | break | |||
|
487 | cx = visit.pop(max(visit)) | |||
|
488 | s.add(cx.rev()) | |||
|
489 | else: | |||
|
490 | cl = repo.changelog | |||
|
491 | s = set() | |||
|
492 | visit = [c.rev()] | |||
|
493 | while visit: | |||
|
494 | for prev in cl.parentrevs(visit.pop(0))[:1]: | |||
|
495 | if prev not in s and prev != nodemod.nullrev: | |||
|
496 | visit.append(prev) | |||
|
497 | s.add(prev) | |||
|
498 | s.add(c.rev()) | |||
|
499 | ||||
|
500 | return [r for r in subset if r in s] | |||
|
501 | ||||
468 | def getall(repo, subset, x): |
|
502 | def getall(repo, subset, x): | |
469 | """``all()`` |
|
503 | """``all()`` | |
470 | All changesets, the same as ``0:tip``. |
|
504 | All changesets, the same as ``0:tip``. | |
@@ -965,6 +999,7 b' symbols = {' | |||||
965 | "filelog": filelog, |
|
999 | "filelog": filelog, | |
966 | "first": first, |
|
1000 | "first": first, | |
967 | "follow": follow, |
|
1001 | "follow": follow, | |
|
1002 | "_followfirst": _followfirst, | |||
968 | "grep": grep, |
|
1003 | "grep": grep, | |
969 | "head": head, |
|
1004 | "head": head, | |
970 | "heads": heads, |
|
1005 | "heads": heads, |
@@ -1618,3 +1618,27 b' Test --follow and multiple files' | |||||
1618 | nodetag 1 |
|
1618 | nodetag 1 | |
1619 | nodetag 0 |
|
1619 | nodetag 0 | |
1620 |
|
1620 | |||
|
1621 | Test --follow-first | |||
|
1622 | ||||
|
1623 | $ hg up -q 3 | |||
|
1624 | $ echo ee > e | |||
|
1625 | $ hg ci -Am "add another e" e | |||
|
1626 | created new head | |||
|
1627 | $ hg merge --tool internal:other 4 | |||
|
1628 | 0 files updated, 1 files merged, 1 files removed, 0 files unresolved | |||
|
1629 | (branch merge, don't forget to commit) | |||
|
1630 | $ echo merge > e | |||
|
1631 | $ hg ci -m "merge 5 and 4" | |||
|
1632 | $ testlog --follow-first | |||
|
1633 | ('group', ('func', ('symbol', '_followfirst'), None)) | |||
|
1634 | ||||
|
1635 | Cannot compare with log --follow-first FILE as it never worked | |||
|
1636 | ||||
|
1637 | $ hg log -G --print-revset --follow-first e | |||
|
1638 | ('group', ('group', ('func', ('symbol', '_followfirst'), ('string', 'e')))) | |||
|
1639 | $ hg log -G --follow-first e --template '{rev} {desc|firstline}\n' | |||
|
1640 | @ 6 merge 5 and 4 | |||
|
1641 | |\ | |||
|
1642 | o | 5 add another e | |||
|
1643 | | | | |||
|
1644 |
General Comments 0
You need to be logged in to leave comments.
Login now