Show More
@@ -242,8 +242,40 def check_unsupported_flags(pats, opts): | |||||
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("_", "-")) | |
244 |
|
244 | |||
|
245 | def makefilematcher(repo, pats, followfirst): | |||
|
246 | # When displaying a revision with --patch --follow FILE, we have | |||
|
247 | # to know which file of the revision must be diffed. With | |||
|
248 | # --follow, we want the names of the ancestors of FILE in the | |||
|
249 | # revision, stored in "fcache". "fcache" is populated by | |||
|
250 | # reproducing the graph traversal already done by --follow revset | |||
|
251 | # and relating linkrevs to file names (which is not "correct" but | |||
|
252 | # good enough). | |||
|
253 | fcache = {} | |||
|
254 | fcacheready = [False] | |||
|
255 | pctx = repo['.'] | |||
|
256 | wctx = repo[None] | |||
|
257 | ||||
|
258 | def populate(): | |||
|
259 | for fn in pats: | |||
|
260 | for i in ((pctx[fn],), pctx[fn].ancestors(followfirst=followfirst)): | |||
|
261 | for c in i: | |||
|
262 | fcache.setdefault(c.linkrev(), set()).add(c.path()) | |||
|
263 | ||||
|
264 | def filematcher(rev): | |||
|
265 | if not fcacheready[0]: | |||
|
266 | # Lazy initialization | |||
|
267 | fcacheready[0] = True | |||
|
268 | populate() | |||
|
269 | return scmutil.match(wctx, fcache.get(rev, []), default='path') | |||
|
270 | ||||
|
271 | return filematcher | |||
|
272 | ||||
245 | def revset(repo, pats, opts): |
|
273 | def revset(repo, pats, opts): | |
246 | """Return revset str built of revisions, log options and file patterns. |
|
274 | """Return (expr, filematcher) where expr is a revset string built | |
|
275 | of revisions, log options and file patterns. If --stat or --patch | |||
|
276 | are not passed filematcher is None. Otherwise it a a callable | |||
|
277 | taking a revision number and returning a match objects filtering | |||
|
278 | the files to be detailed when displaying the revision. | |||
247 | """ |
|
279 | """ | |
248 | opt2revset = { |
|
280 | opt2revset = { | |
249 | 'follow': ('follow()', None), |
|
281 | 'follow': ('follow()', None), | |
@@ -329,6 +361,13 def revset(repo, pats, opts): | |||||
329 | else: |
|
361 | else: | |
330 | opts['_patslog'] = list(pats) |
|
362 | opts['_patslog'] = list(pats) | |
331 |
|
363 | |||
|
364 | filematcher = None | |||
|
365 | if opts.get('patch') or opts.get('stat'): | |||
|
366 | if follow: | |||
|
367 | filematcher = makefilematcher(repo, pats, followfirst) | |||
|
368 | else: | |||
|
369 | filematcher = lambda rev: match | |||
|
370 | ||||
332 | revset = [] |
|
371 | revset = [] | |
333 | for op, val in opts.iteritems(): |
|
372 | for op, val in opts.iteritems(): | |
334 | if not val: |
|
373 | if not val: | |
@@ -349,9 +388,10 def revset(repo, pats, opts): | |||||
349 | revset = '(' + ' and '.join(revset) + ')' |
|
388 | revset = '(' + ' and '.join(revset) + ')' | |
350 | else: |
|
389 | else: | |
351 | revset = 'all()' |
|
390 | revset = 'all()' | |
352 | return revset |
|
391 | return revset, filematcher | |
353 |
|
392 | |||
354 |
def generate(ui, dag, displayer, showparents, edgefn, getrenamed=None |
|
393 | def generate(ui, dag, displayer, showparents, edgefn, getrenamed=None, | |
|
394 | filematcher=None): | |||
355 | seen, state = [], asciistate() |
|
395 | seen, state = [], asciistate() | |
356 | for rev, type, ctx, parents in dag: |
|
396 | for rev, type, ctx, parents in dag: | |
357 | char = ctx.node() in showparents and '@' or 'o' |
|
397 | char = ctx.node() in showparents and '@' or 'o' | |
@@ -362,7 +402,10 def generate(ui, dag, displayer, showpar | |||||
362 | rename = getrenamed(fn, ctx.rev()) |
|
402 | rename = getrenamed(fn, ctx.rev()) | |
363 | if rename: |
|
403 | if rename: | |
364 | copies.append((fn, rename[0])) |
|
404 | copies.append((fn, rename[0])) | |
365 | displayer.show(ctx, copies=copies) |
|
405 | revmatchfn = None | |
|
406 | if filematcher is not None: | |||
|
407 | revmatchfn = filematcher(ctx.rev()) | |||
|
408 | displayer.show(ctx, copies=copies, matchfn=revmatchfn) | |||
366 | lines = displayer.hunk.pop(rev).split('\n')[:-1] |
|
409 | lines = displayer.hunk.pop(rev).split('\n')[:-1] | |
367 | displayer.flush(rev) |
|
410 | displayer.flush(rev) | |
368 | edges = edgefn(type, char, lines, seen, rev, parents) |
|
411 | edges = edgefn(type, char, lines, seen, rev, parents) | |
@@ -389,7 +432,8 def graphlog(ui, repo, *pats, **opts): | |||||
389 |
|
432 | |||
390 | check_unsupported_flags(pats, opts) |
|
433 | check_unsupported_flags(pats, opts) | |
391 |
|
434 | |||
392 | revs = sorted(scmutil.revrange(repo, [revset(repo, pats, opts)]), reverse=1) |
|
435 | expr, filematcher = revset(repo, pats, opts) | |
|
436 | revs = sorted(scmutil.revrange(repo, [expr]), reverse=1) | |||
393 | limit = cmdutil.loglimit(opts) |
|
437 | limit = cmdutil.loglimit(opts) | |
394 | if limit is not None: |
|
438 | if limit is not None: | |
395 | revs = revs[:limit] |
|
439 | revs = revs[:limit] | |
@@ -403,7 +447,8 def graphlog(ui, repo, *pats, **opts): | |||||
403 | getrenamed = templatekw.getrenamedfn(repo, endrev=endrev) |
|
447 | getrenamed = templatekw.getrenamedfn(repo, endrev=endrev) | |
404 | displayer = show_changeset(ui, repo, opts, buffered=True) |
|
448 | displayer = show_changeset(ui, repo, opts, buffered=True) | |
405 | showparents = [ctx.node() for ctx in repo[None].parents()] |
|
449 | showparents = [ctx.node() for ctx in repo[None].parents()] | |
406 |
generate(ui, revdag, displayer, showparents, asciiedges, getrenamed |
|
450 | generate(ui, revdag, displayer, showparents, asciiedges, getrenamed, | |
|
451 | filematcher) | |||
407 |
|
452 | |||
408 | def graphrevs(repo, nodes, opts): |
|
453 | def graphrevs(repo, nodes, opts): | |
409 | limit = cmdutil.loglimit(opts) |
|
454 | limit = cmdutil.loglimit(opts) |
@@ -90,7 +90,7 o (0) root | |||||
90 | > def uisetup(ui): |
|
90 | > def uisetup(ui): | |
91 | > def printrevset(orig, ui, repo, *pats, **opts): |
|
91 | > def printrevset(orig, ui, repo, *pats, **opts): | |
92 | > if opts.get('print_revset'): |
|
92 | > if opts.get('print_revset'): | |
93 | > expr = graphlog.revset(repo, pats, opts) |
|
93 | > expr = graphlog.revset(repo, pats, opts)[0] | |
94 | > tree = revset.parse(expr)[0] |
|
94 | > tree = revset.parse(expr)[0] | |
95 | > ui.write(tree, "\n") |
|
95 | > ui.write(tree, "\n") | |
96 | > return 0 |
|
96 | > return 0 | |
@@ -1655,3 +1655,99 Test --removed | |||||
1655 | abort: can only follow copies/renames for explicit filenames |
|
1655 | abort: can only follow copies/renames for explicit filenames | |
1656 | abort: can only follow copies/renames for explicit filenames |
|
1656 | abort: can only follow copies/renames for explicit filenames | |
1657 | abort: can only follow copies/renames for explicit filenames |
|
1657 | abort: can only follow copies/renames for explicit filenames | |
|
1658 | ||||
|
1659 | Test --patch and --stat with --follow and --follow-first | |||
|
1660 | ||||
|
1661 | $ hg up -q 3 | |||
|
1662 | $ hg log -G --git --patch b | |||
|
1663 | o changeset: 1:216d4c92cf98 | |||
|
1664 | | user: test | |||
|
1665 | | date: Thu Jan 01 00:00:00 1970 +0000 | |||
|
1666 | | summary: copy a b | |||
|
1667 | | | |||
|
1668 | | diff --git a/a b/b | |||
|
1669 | | copy from a | |||
|
1670 | | copy to b | |||
|
1671 | | | |||
|
1672 | ||||
|
1673 | $ hg log -G --git --stat b | |||
|
1674 | o changeset: 1:216d4c92cf98 | |||
|
1675 | | user: test | |||
|
1676 | | date: Thu Jan 01 00:00:00 1970 +0000 | |||
|
1677 | | summary: copy a b | |||
|
1678 | | | |||
|
1679 | | a | 0 | |||
|
1680 | | 1 files changed, 0 insertions(+), 0 deletions(-) | |||
|
1681 | | | |||
|
1682 | ||||
|
1683 | $ hg log -G --git --patch --follow b | |||
|
1684 | o changeset: 1:216d4c92cf98 | |||
|
1685 | | user: test | |||
|
1686 | | date: Thu Jan 01 00:00:00 1970 +0000 | |||
|
1687 | | summary: copy a b | |||
|
1688 | | | |||
|
1689 | | diff --git a/a b/b | |||
|
1690 | | copy from a | |||
|
1691 | | copy to b | |||
|
1692 | | | |||
|
1693 | o changeset: 0:f8035bb17114 | |||
|
1694 | user: test | |||
|
1695 | date: Thu Jan 01 00:00:00 1970 +0000 | |||
|
1696 | summary: add a | |||
|
1697 | ||||
|
1698 | diff --git a/a b/a | |||
|
1699 | new file mode 100644 | |||
|
1700 | --- /dev/null | |||
|
1701 | +++ b/a | |||
|
1702 | @@ -0,0 +1,1 @@ | |||
|
1703 | +a | |||
|
1704 | ||||
|
1705 | ||||
|
1706 | $ hg log -G --git --stat --follow b | |||
|
1707 | o changeset: 1:216d4c92cf98 | |||
|
1708 | | user: test | |||
|
1709 | | date: Thu Jan 01 00:00:00 1970 +0000 | |||
|
1710 | | summary: copy a b | |||
|
1711 | | | |||
|
1712 | | a | 0 | |||
|
1713 | | 1 files changed, 0 insertions(+), 0 deletions(-) | |||
|
1714 | | | |||
|
1715 | o changeset: 0:f8035bb17114 | |||
|
1716 | user: test | |||
|
1717 | date: Thu Jan 01 00:00:00 1970 +0000 | |||
|
1718 | summary: add a | |||
|
1719 | ||||
|
1720 | a | 1 + | |||
|
1721 | 1 files changed, 1 insertions(+), 0 deletions(-) | |||
|
1722 | ||||
|
1723 | ||||
|
1724 | $ hg up -q 6 | |||
|
1725 | $ hg log -G --git --patch --follow-first e | |||
|
1726 | @ changeset: 6:fc281d8ff18d | |||
|
1727 | |\ tag: tip | |||
|
1728 | | | parent: 5:99b31f1c2782 | |||
|
1729 | | | parent: 4:17d952250a9d | |||
|
1730 | | | user: test | |||
|
1731 | | | date: Thu Jan 01 00:00:00 1970 +0000 | |||
|
1732 | | | summary: merge 5 and 4 | |||
|
1733 | | | | |||
|
1734 | | | diff --git a/e b/e | |||
|
1735 | | | --- a/e | |||
|
1736 | | | +++ b/e | |||
|
1737 | | | @@ -1,1 +1,1 @@ | |||
|
1738 | | | -ee | |||
|
1739 | | | +merge | |||
|
1740 | | | | |||
|
1741 | o | changeset: 5:99b31f1c2782 | |||
|
1742 | | | parent: 3:5918b8d165d1 | |||
|
1743 | | | user: test | |||
|
1744 | | | date: Thu Jan 01 00:00:00 1970 +0000 | |||
|
1745 | | | summary: add another e | |||
|
1746 | | | | |||
|
1747 | | | diff --git a/e b/e | |||
|
1748 | | | new file mode 100644 | |||
|
1749 | | | --- /dev/null | |||
|
1750 | | | +++ b/e | |||
|
1751 | | | @@ -0,0 +1,1 @@ | |||
|
1752 | | | +ee | |||
|
1753 | | | |
General Comments 0
You need to be logged in to leave comments.
Login now