diff --git a/hgext/show.py b/hgext/show.py --- a/hgext/show.py +++ b/hgext/show.py @@ -161,9 +161,10 @@ ui.write(_('(no bookmarks set)\n')) return + revs = [repo[node].rev() for node in marks.values()] active = repo._activebookmark longestname = max(len(b) for b in marks) - # TODO consider exposing longest shortest(node). + nodelen = longestshortest(repo, revs) for bm, node in sorted(marks.items()): fm.startitem() @@ -172,7 +173,7 @@ fm.write('node', fm.hexfunc(node), fm.hexfunc(node)) fm.data(active=bm == active, longestbookmarklen=longestname, - nodelen=5) + nodelen=nodelen) @showview('stack', csettopic='stack') def showstack(ui, repo, displayer): @@ -236,6 +237,9 @@ else: newheads = set() + allrevs = set(stackrevs) | newheads | set([baserev]) + nodelen = longestshortest(repo, allrevs) + try: cmdutil.findcmd('rebase', commands.table) haverebase = True @@ -247,7 +251,7 @@ # our simplicity and the customizations required. # TODO use proper graph symbols from graphmod - shortesttmpl = formatter.maketemplater(ui, '{shortest(node, 5)}') + shortesttmpl = formatter.maketemplater(ui, '{shortest(node, %d)}' % nodelen) def shortest(ctx): return shortesttmpl.render({'ctx': ctx, 'node': ctx.hex()}) @@ -278,7 +282,7 @@ ui.write(' ') ui.write(('o ')) - displayer.show(ctx, nodelen=5) + displayer.show(ctx, nodelen=nodelen) displayer.flush(ctx) ui.write('\n') @@ -318,7 +322,7 @@ ui.write(' ') ui.write(symbol, ' ') - displayer.show(ctx, nodelen=5) + displayer.show(ctx, nodelen=nodelen) displayer.flush(ctx) ui.write('\n') @@ -335,7 +339,7 @@ ui.write(_('(stack base)'), '\n', label='stack.label') ui.write(('o ')) - displayer.show(basectx, nodelen=5) + displayer.show(basectx, nodelen=nodelen) displayer.flush(basectx) ui.write('\n') @@ -394,12 +398,13 @@ """changesets that aren't finished""" # TODO support date-based limiting when calling revset. revs = repo.revs('sort(_underway(), topo)') + nodelen = longestshortest(repo, revs) revdag = graphmod.dagwalker(repo, revs) ui.setconfig('experimental', 'graphshorten', True) cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges, - props={'nodelen': 5}) + props={'nodelen': nodelen}) def extsetup(ui): # Alias `hg ` to `hg show `. @@ -420,6 +425,27 @@ ui.setconfig('alias', name, 'show %s' % view, source='show') +def longestshortest(repo, revs, minlen=4): + """Return the length of the longest shortest node to identify revisions. + + The result of this function can be used with the ``shortest()`` template + function to ensure that a value is unique and unambiguous for a given + set of nodes. + + The number of revisions in the repo is taken into account to prevent + a numeric node prefix from conflicting with an integer revision number. + If we fail to do this, a value of e.g. ``10023`` could mean either + revision 10023 or node ``10023abc...``. + """ + tmpl = formatter.maketemplater(repo.ui, '{shortest(node, %d)}' % minlen) + lens = [minlen] + for rev in revs: + ctx = repo[rev] + shortest = tmpl.render({'ctx': ctx, 'node': ctx.hex()}) + lens.append(len(shortest)) + + return max(lens) + # Adjust the docstring of the show command so it shows all registered views. # This is a bit hacky because it runs at the end of module load. When moved # into core or when another extension wants to provide a view, we'll need diff --git a/tests/test-show-stack.t b/tests/test-show-stack.t --- a/tests/test-show-stack.t +++ b/tests/test-show-stack.t @@ -17,7 +17,7 @@ $ echo 0 > foo $ hg -q commit -A -m 'commit 0' $ hg show stack - @ 9f171 commit 0 + @ 9f17 commit 0 Stack displays multiple draft changesets @@ -30,48 +30,48 @@ $ echo 4 > foo $ hg commit -m 'commit 4' $ hg show stack - @ 2737b commit 4 - o d1a69 commit 3 - o 128c8 commit 2 - o 181cc commit 1 - o 9f171 commit 0 + @ 2737 commit 4 + o d1a6 commit 3 + o 128c commit 2 + o 181c commit 1 + o 9f17 commit 0 Public parent of draft base is displayed, separated from stack $ hg phase --public -r 0 $ hg show stack - @ 2737b commit 4 - o d1a69 commit 3 - o 128c8 commit 2 - o 181cc commit 1 + @ 2737 commit 4 + o d1a6 commit 3 + o 128c commit 2 + o 181c commit 1 / (stack base) - o 9f171 commit 0 + o 9f17 commit 0 $ hg phase --public -r 1 $ hg show stack - @ 2737b commit 4 - o d1a69 commit 3 - o 128c8 commit 2 + @ 2737 commit 4 + o d1a6 commit 3 + o 128c commit 2 / (stack base) - o 181cc commit 1 + o 181c commit 1 Draft descendants are shown $ hg -q up 2 $ hg show stack - o 2737b commit 4 - o d1a69 commit 3 - @ 128c8 commit 2 + o 2737 commit 4 + o d1a6 commit 3 + @ 128c commit 2 / (stack base) - o 181cc commit 1 + o 181c commit 1 $ hg -q up 3 $ hg show stack - o 2737b commit 4 - @ d1a69 commit 3 - o 128c8 commit 2 + o 2737 commit 4 + @ d1a6 commit 3 + o 128c commit 2 / (stack base) - o 181cc commit 1 + o 181c commit 1 working dir on public changeset should display special message @@ -89,10 +89,10 @@ $ hg show stack \ / (multiple children) | - o d1a69 commit 3 - @ 128c8 commit 2 + o d1a6 commit 3 + @ 128c commit 2 / (stack base) - o 181cc commit 1 + o 181c commit 1 $ cd .. @@ -117,9 +117,9 @@ TODO doesn't yet handle case where wdir is a draft merge $ hg show stack - @ 8ee90 merge heads + @ 8ee9 merge heads / (stack base) - o 59478 head 1 + o 5947 head 1 $ echo d1 > foo $ hg commit -m 'draft 1' @@ -127,10 +127,10 @@ $ hg commit -m 'draft 2' $ hg show stack - @ 430d5 draft 2 - o 787b1 draft 1 + @ 430d draft 2 + o 787b draft 1 / (stack base) - o 8ee90 merge heads + o 8ee9 merge heads $ cd .. @@ -156,36 +156,36 @@ Newer draft heads don't impact output $ hg show stack - @ eaffc draft 2 - o 2b218 draft 1 + @ eaff draft 2 + o 2b21 draft 1 / (stack base) - o b66bb base + o b66b base Newer public heads are rendered $ hg phase --public -r '::tip' $ hg show stack - o baa4b new 2 + o baa4 new 2 / (2 commits ahead) : : (stack head) - : @ eaffc draft 2 - : o 2b218 draft 1 + : @ eaff draft 2 + : o 2b21 draft 1 :/ (stack base) - o b66bb base + o b66b base If rebase is available, we show a hint how to rebase to that head $ hg --config extensions.rebase= show stack - o baa4b new 2 - / (2 commits ahead; hg rebase --source 2b218 --dest baa4b) + o baa4 new 2 + / (2 commits ahead; hg rebase --source 2b21 --dest baa4) : : (stack head) - : @ eaffc draft 2 - : o 2b218 draft 1 + : @ eaff draft 2 + : o 2b21 draft 1 :/ (stack base) - o b66bb base + o b66b base Similar tests but for multiple heads @@ -196,25 +196,25 @@ $ hg -q up 2 $ hg show stack - o baa4b new 2 + o baa4 new 2 / (2 commits ahead) - : o 9a848 new head 2 + : o 9a84 new head 2 :/ (1 commits ahead) : : (stack head) - : @ eaffc draft 2 - : o 2b218 draft 1 + : @ eaff draft 2 + : o 2b21 draft 1 :/ (stack base) - o b66bb base + o b66b base $ hg --config extensions.rebase= show stack - o baa4b new 2 - / (2 commits ahead; hg rebase --source 2b218 --dest baa4b) - : o 9a848 new head 2 - :/ (1 commits ahead; hg rebase --source 2b218 --dest 9a848) + o baa4 new 2 + / (2 commits ahead; hg rebase --source 2b21 --dest baa4) + : o 9a84 new head 2 + :/ (1 commits ahead; hg rebase --source 2b21 --dest 9a84) : : (stack head) - : @ eaffc draft 2 - : o 2b218 draft 1 + : @ eaff draft 2 + : o 2b21 draft 1 :/ (stack base) - o b66bb base + o b66b base diff --git a/tests/test-show-work.t b/tests/test-show-work.t --- a/tests/test-show-work.t +++ b/tests/test-show-work.t @@ -16,20 +16,20 @@ $ hg -q commit -A -m 'commit 0' $ hg show work - @ 9f171 commit 0 + @ 9f17 commit 0 Even when it isn't the wdir $ hg -q up null $ hg show work - o 9f171 commit 0 + o 9f17 commit 0 Single changeset is still there when public because it is a head $ hg phase --public -r 0 $ hg show work - o 9f171 commit 0 + o 9f17 commit 0 A draft child will show both it and public parent @@ -38,8 +38,8 @@ $ hg commit -m 'commit 1' $ hg show work - @ 181cc commit 1 - o 9f171 commit 0 + @ 181c commit 1 + o 9f17 commit 0 Multiple draft children will be shown @@ -47,16 +47,16 @@ $ hg commit -m 'commit 2' $ hg show work - @ 128c8 commit 2 - o 181cc commit 1 - o 9f171 commit 0 + @ 128c commit 2 + o 181c commit 1 + o 9f17 commit 0 Bumping first draft changeset to public will hide its parent $ hg phase --public -r 1 $ hg show work - @ 128c8 commit 2 - o 181cc commit 1 + @ 128c commit 2 + o 181c commit 1 | ~ @@ -68,10 +68,10 @@ created new head $ hg show work - @ f0abc commit 3 - | o 128c8 commit 2 + @ f0ab commit 3 + | o 128c commit 2 |/ - o 181cc commit 1 + o 181c commit 1 | ~ @@ -80,10 +80,10 @@ $ hg -q up null $ hg show work - o f0abc commit 3 - | o 128c8 commit 2 + o f0ab commit 3 + | o 128c commit 2 |/ - o 181cc commit 1 + o 181c commit 1 | ~ @@ -95,13 +95,13 @@ created new head $ hg show work - @ 668ca commit 4 - | o f0abc commit 3 - | | o 128c8 commit 2 + @ 668c commit 4 + | o f0ab commit 3 + | | o 128c commit 2 | |/ - | o 181cc commit 1 + | o 181c commit 1 |/ - o 9f171 commit 0 + o 9f17 commit 0 $ cd .. @@ -126,11 +126,11 @@ $ hg commit -m 'commit 4' $ hg show work - @ f8dd3 (mybranch) commit 4 - o 90cfc (mybranch) commit 3 - | o 128c8 commit 2 + @ f8dd (mybranch) commit 4 + o 90cf (mybranch) commit 3 + | o 128c commit 2 |/ - o 181cc commit 1 + o 181c commit 1 | ~ @@ -157,11 +157,11 @@ $ hg bookmark mybook $ hg show work - @ cac82 (mybook) commit 4 - o f0abc commit 3 - | o 128c8 (@) commit 2 + @ cac8 (mybook) commit 4 + o f0ab commit 3 + | o 128c (@) commit 2 |/ - o 181cc commit 1 + o 181c commit 1 | ~ @@ -182,9 +182,9 @@ $ hg tag 0.2 $ hg show work - @ 37582 Added tag 0.2 for changeset 6379c25b76f1 - o 6379c (0.2) commit 3 - o a2ad9 Added tag 0.1 for changeset 6a75536ea0b1 + @ 3758 Added tag 0.2 for changeset 6379c25b76f1 + o 6379 (0.2) commit 3 + o a2ad Added tag 0.1 for changeset 6a75536ea0b1 | ~ @@ -205,15 +205,15 @@ $ hg commit -m 'commit 2' $ hg show work - @ 34834 (mybook) (mybranch) commit 2 - o 97fcc commit 1 + @ 3483 (mybook) (mybranch) commit 2 + o 97fc commit 1 Multiple bookmarks on same changeset render properly $ hg book mybook2 $ hg show work - @ 34834 (mybook mybook2) (mybranch) commit 2 - o 97fcc commit 1 + @ 3483 (mybook mybook2) (mybranch) commit 2 + o 97fc commit 1 $ cd .. @@ -230,8 +230,38 @@ $ hg commit -m 'commit 3' $ hg --config extensions.revnames=$TESTDIR/revnamesext.py show work - @ 32f3e (r2) commit 3 - o 6a755 (r1) commit 2 - o 97fcc (r0) commit 1 + @ 32f3 (r2) commit 3 + o 6a75 (r1) commit 2 + o 97fc (r0) commit 1 $ cd .. + +Prefix collision on hashes increases shortest node length + + $ hg init hashcollision + $ cd hashcollision + $ echo 0 > a + $ hg -q commit -Am 0 + $ for i in 17 1057 2857 4025; do + > hg -q up 0 + > echo $i > a + > hg -q commit -m $i + > echo 0 > a + > hg commit -m "$i commit 2" + > done + + $ hg show work + @ cfd04 4025 commit 2 + o c562d 4025 + | o 08048 2857 commit 2 + | o c5623 2857 + |/ + | o 6a6b6 1057 commit 2 + | o c5625 1057 + |/ + | o 96b4e 17 commit 2 + | o 11424 17 + |/ + o b4e73 0 + + $ cd .. diff --git a/tests/test-show.t b/tests/test-show.t --- a/tests/test-show.t +++ b/tests/test-show.t @@ -95,8 +95,8 @@ $ hg bookmark a-longer-bookmark $ hg show bookmarks - * a-longer-bookmark 7b570 - book1 b757f + * a-longer-bookmark 7b57 + book1 b757 A custom bookmarks template works @@ -113,14 +113,14 @@ "bookmark": "a-longer-bookmark", "longestbookmarklen": 17, "node": "7b5709ab64cbc34da9b4367b64afff47f2c4ee83", - "nodelen": 5 + "nodelen": 4 }, { "active": false, "bookmark": "book1", "longestbookmarklen": 17, "node": "b757f780b8ffd71267c6ccb32e0882d9d32a8cc0", - "nodelen": 5 + "nodelen": 4 } ] @@ -138,19 +138,19 @@ (no bookmarks set) $ hg --config commands.show.aliasprefix=sh shwork - @ 7b570 commit for book2 - o b757f commit for book1 - o ba592 initial + @ 7b57 commit for book2 + o b757 commit for book1 + o ba59 initial $ hg --config commands.show.aliasprefix='s sh' swork - @ 7b570 commit for book2 - o b757f commit for book1 - o ba592 initial + @ 7b57 commit for book2 + o b757 commit for book1 + o ba59 initial $ hg --config commands.show.aliasprefix='s sh' shwork - @ 7b570 commit for book2 - o b757f commit for book1 - o ba592 initial + @ 7b57 commit for book2 + o b757 commit for book1 + o ba59 initial The aliases don't appear in `hg config`