hgext/show.py
changeset 34203 e6b5e7329ff2
parent 34202 4441c1113eb2
child 34518 592a3cc1ebc4
--- a/hgext/show.py	Thu Aug 03 21:51:34 2017 -0700
+++ b/hgext/show.py	Wed Sep 13 21:15:46 2017 -0700
@@ -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 <prefix><view>` to `hg show <view>`.
@@ -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