hgext/show.py
changeset 43077 687b865b95ad
parent 43076 2372284d9457
child 43080 86e4daa2d54c
equal deleted inserted replaced
43076:2372284d9457 43077:687b865b95ad
    47 
    47 
    48 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
    48 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
    49 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
    49 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
    50 # be specifying the version(s) of Mercurial they are tested with, or
    50 # be specifying the version(s) of Mercurial they are tested with, or
    51 # leave the attribute unspecified.
    51 # leave the attribute unspecified.
    52 testedwith = 'ships-with-hg-core'
    52 testedwith = b'ships-with-hg-core'
    53 
    53 
    54 cmdtable = {}
    54 cmdtable = {}
    55 command = registrar.command(cmdtable)
    55 command = registrar.command(cmdtable)
    56 
    56 
    57 revsetpredicate = registrar.revsetpredicate()
    57 revsetpredicate = registrar.revsetpredicate()
    59 
    59 
    60 class showcmdfunc(registrar._funcregistrarbase):
    60 class showcmdfunc(registrar._funcregistrarbase):
    61     """Register a function to be invoked for an `hg show <thing>`."""
    61     """Register a function to be invoked for an `hg show <thing>`."""
    62 
    62 
    63     # Used by _formatdoc().
    63     # Used by _formatdoc().
    64     _docformat = '%s -- %s'
    64     _docformat = b'%s -- %s'
    65 
    65 
    66     def _extrasetup(self, name, func, fmtopic=None, csettopic=None):
    66     def _extrasetup(self, name, func, fmtopic=None, csettopic=None):
    67         """Called with decorator arguments to register a show view.
    67         """Called with decorator arguments to register a show view.
    68 
    68 
    69         ``name`` is the sub-command name.
    69         ``name`` is the sub-command name.
    86 
    86 
    87 showview = showcmdfunc()
    87 showview = showcmdfunc()
    88 
    88 
    89 
    89 
    90 @command(
    90 @command(
    91     'show',
    91     b'show',
    92     [
    92     [
    93         # TODO: Switch this template flag to use cmdutil.formatteropts if
    93         # TODO: Switch this template flag to use cmdutil.formatteropts if
    94         # 'hg show' becomes stable before --template/-T is stable. For now,
    94         # 'hg show' becomes stable before --template/-T is stable. For now,
    95         # we are putting it here without the '(EXPERIMENTAL)' flag because it
    95         # we are putting it here without the '(EXPERIMENTAL)' flag because it
    96         # is an important part of the 'hg show' user experience and the entire
    96         # is an important part of the 'hg show' user experience and the entire
    97         # 'hg show' experience is experimental.
    97         # 'hg show' experience is experimental.
    98         ('T', 'template', '', 'display with template', _('TEMPLATE')),
    98         (b'T', b'template', b'', b'display with template', _(b'TEMPLATE')),
    99     ],
    99     ],
   100     _('VIEW'),
   100     _(b'VIEW'),
   101     helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
   101     helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
   102 )
   102 )
   103 def show(ui, repo, view=None, template=None):
   103 def show(ui, repo, view=None, template=None):
   104     """show various repository information
   104     """show various repository information
   105 
   105 
   117        ``-T/--template``.
   117        ``-T/--template``.
   118 
   118 
   119     List of available views:
   119     List of available views:
   120     """
   120     """
   121     if ui.plain() and not template:
   121     if ui.plain() and not template:
   122         hint = _('invoke with -T/--template to control output format')
   122         hint = _(b'invoke with -T/--template to control output format')
   123         raise error.Abort(_('must specify a template in plain mode'), hint=hint)
   123         raise error.Abort(
       
   124             _(b'must specify a template in plain mode'), hint=hint
       
   125         )
   124 
   126 
   125     views = showview._table
   127     views = showview._table
   126 
   128 
   127     if not view:
   129     if not view:
   128         ui.pager('show')
   130         ui.pager(b'show')
   129         # TODO consider using formatter here so available views can be
   131         # TODO consider using formatter here so available views can be
   130         # rendered to custom format.
   132         # rendered to custom format.
   131         ui.write(_('available views:\n'))
   133         ui.write(_(b'available views:\n'))
   132         ui.write('\n')
   134         ui.write(b'\n')
   133 
   135 
   134         for name, func in sorted(views.items()):
   136         for name, func in sorted(views.items()):
   135             ui.write('%s\n' % pycompat.sysbytes(func.__doc__))
   137             ui.write(b'%s\n' % pycompat.sysbytes(func.__doc__))
   136 
   138 
   137         ui.write('\n')
   139         ui.write(b'\n')
   138         raise error.Abort(
   140         raise error.Abort(
   139             _('no view requested'),
   141             _(b'no view requested'),
   140             hint=_('use "hg show VIEW" to choose a view'),
   142             hint=_(b'use "hg show VIEW" to choose a view'),
   141         )
   143         )
   142 
   144 
   143     # TODO use same logic as dispatch to perform prefix matching.
   145     # TODO use same logic as dispatch to perform prefix matching.
   144     if view not in views:
   146     if view not in views:
   145         raise error.Abort(
   147         raise error.Abort(
   146             _('unknown view: %s') % view,
   148             _(b'unknown view: %s') % view,
   147             hint=_('run "hg show" to see available views'),
   149             hint=_(b'run "hg show" to see available views'),
   148         )
   150         )
   149 
   151 
   150     template = template or 'show'
   152     template = template or b'show'
   151 
   153 
   152     fn = views[view]
   154     fn = views[view]
   153     ui.pager('show')
   155     ui.pager(b'show')
   154 
   156 
   155     if fn._fmtopic:
   157     if fn._fmtopic:
   156         fmtopic = 'show%s' % fn._fmtopic
   158         fmtopic = b'show%s' % fn._fmtopic
   157         with ui.formatter(fmtopic, {'template': template}) as fm:
   159         with ui.formatter(fmtopic, {b'template': template}) as fm:
   158             return fn(ui, repo, fm)
   160             return fn(ui, repo, fm)
   159     elif fn._csettopic:
   161     elif fn._csettopic:
   160         ref = 'show%s' % fn._csettopic
   162         ref = b'show%s' % fn._csettopic
   161         spec = formatter.lookuptemplate(ui, ref, template)
   163         spec = formatter.lookuptemplate(ui, ref, template)
   162         displayer = logcmdutil.changesettemplater(ui, repo, spec, buffered=True)
   164         displayer = logcmdutil.changesettemplater(ui, repo, spec, buffered=True)
   163         return fn(ui, repo, displayer)
   165         return fn(ui, repo, displayer)
   164     else:
   166     else:
   165         return fn(ui, repo)
   167         return fn(ui, repo)
   166 
   168 
   167 
   169 
   168 @showview('bookmarks', fmtopic='bookmarks')
   170 @showview(b'bookmarks', fmtopic=b'bookmarks')
   169 def showbookmarks(ui, repo, fm):
   171 def showbookmarks(ui, repo, fm):
   170     """bookmarks and their associated changeset"""
   172     """bookmarks and their associated changeset"""
   171     marks = repo._bookmarks
   173     marks = repo._bookmarks
   172     if not len(marks):
   174     if not len(marks):
   173         # This is a bit hacky. Ideally, templates would have a way to
   175         # This is a bit hacky. Ideally, templates would have a way to
   174         # specify an empty output, but we shouldn't corrupt JSON while
   176         # specify an empty output, but we shouldn't corrupt JSON while
   175         # waiting for this functionality.
   177         # waiting for this functionality.
   176         if not isinstance(fm, formatter.jsonformatter):
   178         if not isinstance(fm, formatter.jsonformatter):
   177             ui.write(_('(no bookmarks set)\n'))
   179             ui.write(_(b'(no bookmarks set)\n'))
   178         return
   180         return
   179 
   181 
   180     revs = [repo[node].rev() for node in marks.values()]
   182     revs = [repo[node].rev() for node in marks.values()]
   181     active = repo._activebookmark
   183     active = repo._activebookmark
   182     longestname = max(len(b) for b in marks)
   184     longestname = max(len(b) for b in marks)
   183     nodelen = longestshortest(repo, revs)
   185     nodelen = longestshortest(repo, revs)
   184 
   186 
   185     for bm, node in sorted(marks.items()):
   187     for bm, node in sorted(marks.items()):
   186         fm.startitem()
   188         fm.startitem()
   187         fm.context(ctx=repo[node])
   189         fm.context(ctx=repo[node])
   188         fm.write('bookmark', '%s', bm)
   190         fm.write(b'bookmark', b'%s', bm)
   189         fm.write('node', fm.hexfunc(node), fm.hexfunc(node))
   191         fm.write(b'node', fm.hexfunc(node), fm.hexfunc(node))
   190         fm.data(
   192         fm.data(
   191             active=bm == active, longestbookmarklen=longestname, nodelen=nodelen
   193             active=bm == active, longestbookmarklen=longestname, nodelen=nodelen
   192         )
   194         )
   193 
   195 
   194 
   196 
   195 @showview('stack', csettopic='stack')
   197 @showview(b'stack', csettopic=b'stack')
   196 def showstack(ui, repo, displayer):
   198 def showstack(ui, repo, displayer):
   197     """current line of work"""
   199     """current line of work"""
   198     wdirctx = repo['.']
   200     wdirctx = repo[b'.']
   199     if wdirctx.rev() == nullrev:
   201     if wdirctx.rev() == nullrev:
   200         raise error.Abort(
   202         raise error.Abort(
   201             _('stack view only available when there is a ' 'working directory')
   203             _(
       
   204                 b'stack view only available when there is a '
       
   205                 b'working directory'
       
   206             )
   202         )
   207         )
   203 
   208 
   204     if wdirctx.phase() == phases.public:
   209     if wdirctx.phase() == phases.public:
   205         ui.write(
   210         ui.write(
   206             _(
   211             _(
   207                 '(empty stack; working directory parent is a published '
   212                 b'(empty stack; working directory parent is a published '
   208                 'changeset)\n'
   213                 b'changeset)\n'
   209             )
   214             )
   210         )
   215         )
   211         return
   216         return
   212 
   217 
   213     # TODO extract "find stack" into a function to facilitate
   218     # TODO extract "find stack" into a function to facilitate
   218 
   223 
   219     if baserev is None:
   224     if baserev is None:
   220         baserev = wdirctx.rev()
   225         baserev = wdirctx.rev()
   221         stackrevs = {wdirctx.rev()}
   226         stackrevs = {wdirctx.rev()}
   222     else:
   227     else:
   223         stackrevs = set(repo.revs('%d::.', baserev))
   228         stackrevs = set(repo.revs(b'%d::.', baserev))
   224 
   229 
   225     ctx = repo[baserev]
   230     ctx = repo[baserev]
   226     if ctx.p1().rev() != nullrev:
   231     if ctx.p1().rev() != nullrev:
   227         basectx = ctx.p1()
   232         basectx = ctx.p1()
   228 
   233 
   254     # merge or rebase targets.
   259     # merge or rebase targets.
   255     if basectx:
   260     if basectx:
   256         # TODO make this customizable?
   261         # TODO make this customizable?
   257         newheads = set(
   262         newheads = set(
   258             repo.revs(
   263             repo.revs(
   259                 'heads(%d::) - %ld - not public()', basectx.rev(), stackrevs
   264                 b'heads(%d::) - %ld - not public()', basectx.rev(), stackrevs
   260             )
   265             )
   261         )
   266         )
   262     else:
   267     else:
   263         newheads = set()
   268         newheads = set()
   264 
   269 
   265     allrevs = set(stackrevs) | newheads | {baserev}
   270     allrevs = set(stackrevs) | newheads | {baserev}
   266     nodelen = longestshortest(repo, allrevs)
   271     nodelen = longestshortest(repo, allrevs)
   267 
   272 
   268     try:
   273     try:
   269         cmdutil.findcmd('rebase', commands.table)
   274         cmdutil.findcmd(b'rebase', commands.table)
   270         haverebase = True
   275         haverebase = True
   271     except (error.AmbiguousCommand, error.UnknownCommand):
   276     except (error.AmbiguousCommand, error.UnknownCommand):
   272         haverebase = False
   277         haverebase = False
   273 
   278 
   274     # TODO use templating.
   279     # TODO use templating.
   276     # our simplicity and the customizations required.
   281     # our simplicity and the customizations required.
   277     # TODO use proper graph symbols from graphmod
   282     # TODO use proper graph symbols from graphmod
   278 
   283 
   279     tres = formatter.templateresources(ui, repo)
   284     tres = formatter.templateresources(ui, repo)
   280     shortesttmpl = formatter.maketemplater(
   285     shortesttmpl = formatter.maketemplater(
   281         ui, '{shortest(node, %d)}' % nodelen, resources=tres
   286         ui, b'{shortest(node, %d)}' % nodelen, resources=tres
   282     )
   287     )
   283 
   288 
   284     def shortest(ctx):
   289     def shortest(ctx):
   285         return shortesttmpl.renderdefault({'ctx': ctx, 'node': ctx.hex()})
   290         return shortesttmpl.renderdefault({b'ctx': ctx, b'node': ctx.hex()})
   286 
   291 
   287     # We write out new heads to aid in DAG awareness and to help with decision
   292     # We write out new heads to aid in DAG awareness and to help with decision
   288     # making on how the stack should be reconciled with commits made since the
   293     # making on how the stack should be reconciled with commits made since the
   289     # branch point.
   294     # branch point.
   290     if newheads:
   295     if newheads:
   305 
   310 
   306         for i, rev in enumerate(sortedheads):
   311         for i, rev in enumerate(sortedheads):
   307             ctx = repo[rev]
   312             ctx = repo[rev]
   308 
   313 
   309             if i:
   314             if i:
   310                 ui.write(': ')
   315                 ui.write(b': ')
   311             else:
   316             else:
   312                 ui.write('  ')
   317                 ui.write(b'  ')
   313 
   318 
   314             ui.write('o  ')
   319             ui.write(b'o  ')
   315             displayer.show(ctx, nodelen=nodelen)
   320             displayer.show(ctx, nodelen=nodelen)
   316             displayer.flush(ctx)
   321             displayer.flush(ctx)
   317             ui.write('\n')
   322             ui.write(b'\n')
   318 
   323 
   319             if i:
   324             if i:
   320                 ui.write(':/')
   325                 ui.write(b':/')
   321             else:
   326             else:
   322                 ui.write(' /')
   327                 ui.write(b' /')
   323 
   328 
   324             ui.write('    (')
   329             ui.write(b'    (')
   325             ui.write(
   330             ui.write(
   326                 _('%d commits ahead') % revdistance[rev],
   331                 _(b'%d commits ahead') % revdistance[rev],
   327                 label='stack.commitdistance',
   332                 label=b'stack.commitdistance',
   328             )
   333             )
   329 
   334 
   330             if haverebase:
   335             if haverebase:
   331                 # TODO may be able to omit --source in some scenarios
   336                 # TODO may be able to omit --source in some scenarios
   332                 ui.write('; ')
   337                 ui.write(b'; ')
   333                 ui.write(
   338                 ui.write(
   334                     (
   339                     (
   335                         'hg rebase --source %s --dest %s'
   340                         b'hg rebase --source %s --dest %s'
   336                         % (shortest(sourcectx), shortest(ctx))
   341                         % (shortest(sourcectx), shortest(ctx))
   337                     ),
   342                     ),
   338                     label='stack.rebasehint',
   343                     label=b'stack.rebasehint',
   339                 )
   344                 )
   340 
   345 
   341             ui.write(')\n')
   346             ui.write(b')\n')
   342 
   347 
   343         ui.write(':\n:    ')
   348         ui.write(b':\n:    ')
   344         ui.write(_('(stack head)\n'), label='stack.label')
   349         ui.write(_(b'(stack head)\n'), label=b'stack.label')
   345 
   350 
   346     if branchpointattip:
   351     if branchpointattip:
   347         ui.write(' \\ /  ')
   352         ui.write(b' \\ /  ')
   348         ui.write(_('(multiple children)\n'), label='stack.label')
   353         ui.write(_(b'(multiple children)\n'), label=b'stack.label')
   349         ui.write('  |\n')
   354         ui.write(b'  |\n')
   350 
   355 
   351     for rev in stackrevs:
   356     for rev in stackrevs:
   352         ctx = repo[rev]
   357         ctx = repo[rev]
   353         symbol = '@' if rev == wdirctx.rev() else 'o'
   358         symbol = b'@' if rev == wdirctx.rev() else b'o'
   354 
   359 
   355         if newheads:
   360         if newheads:
   356             ui.write(': ')
   361             ui.write(b': ')
   357         else:
   362         else:
   358             ui.write('  ')
   363             ui.write(b'  ')
   359 
   364 
   360         ui.write(symbol, '  ')
   365         ui.write(symbol, b'  ')
   361         displayer.show(ctx, nodelen=nodelen)
   366         displayer.show(ctx, nodelen=nodelen)
   362         displayer.flush(ctx)
   367         displayer.flush(ctx)
   363         ui.write('\n')
   368         ui.write(b'\n')
   364 
   369 
   365     # TODO display histedit hint?
   370     # TODO display histedit hint?
   366 
   371 
   367     if basectx:
   372     if basectx:
   368         # Vertically and horizontally separate stack base from parent
   373         # Vertically and horizontally separate stack base from parent
   369         # to reinforce stack boundary.
   374         # to reinforce stack boundary.
   370         if newheads:
   375         if newheads:
   371             ui.write(':/   ')
   376             ui.write(b':/   ')
   372         else:
   377         else:
   373             ui.write(' /   ')
   378             ui.write(b' /   ')
   374 
   379 
   375         ui.write(_('(stack base)'), '\n', label='stack.label')
   380         ui.write(_(b'(stack base)'), b'\n', label=b'stack.label')
   376         ui.write('o  ')
   381         ui.write(b'o  ')
   377 
   382 
   378         displayer.show(basectx, nodelen=nodelen)
   383         displayer.show(basectx, nodelen=nodelen)
   379         displayer.flush(basectx)
   384         displayer.flush(basectx)
   380         ui.write('\n')
   385         ui.write(b'\n')
   381 
   386 
   382 
   387 
   383 @revsetpredicate('_underway([commitage[, headage]])')
   388 @revsetpredicate(b'_underway([commitage[, headage]])')
   384 def underwayrevset(repo, subset, x):
   389 def underwayrevset(repo, subset, x):
   385     args = revset.getargsdict(x, 'underway', 'commitage headage')
   390     args = revset.getargsdict(x, b'underway', b'commitage headage')
   386     if 'commitage' not in args:
   391     if b'commitage' not in args:
   387         args['commitage'] = None
   392         args[b'commitage'] = None
   388     if 'headage' not in args:
   393     if b'headage' not in args:
   389         args['headage'] = None
   394         args[b'headage'] = None
   390 
   395 
   391     # We assume callers of this revset add a topographical sort on the
   396     # We assume callers of this revset add a topographical sort on the
   392     # result. This means there is no benefit to making the revset lazy
   397     # result. This means there is no benefit to making the revset lazy
   393     # since the topographical sort needs to consume all revs.
   398     # since the topographical sort needs to consume all revs.
   394     #
   399     #
   397 
   402 
   398     # Mutable changesets (non-public) are the most important changesets
   403     # Mutable changesets (non-public) are the most important changesets
   399     # to return. ``not public()`` will also pull in obsolete changesets if
   404     # to return. ``not public()`` will also pull in obsolete changesets if
   400     # there is a non-obsolete changeset with obsolete ancestors. This is
   405     # there is a non-obsolete changeset with obsolete ancestors. This is
   401     # why we exclude obsolete changesets from this query.
   406     # why we exclude obsolete changesets from this query.
   402     rs = 'not public() and not obsolete()'
   407     rs = b'not public() and not obsolete()'
   403     rsargs = []
   408     rsargs = []
   404     if args['commitage']:
   409     if args[b'commitage']:
   405         rs += ' and date(%s)'
   410         rs += b' and date(%s)'
   406         rsargs.append(
   411         rsargs.append(
   407             revsetlang.getstring(
   412             revsetlang.getstring(
   408                 args['commitage'], _('commitage requires a string')
   413                 args[b'commitage'], _(b'commitage requires a string')
   409             )
   414             )
   410         )
   415         )
   411 
   416 
   412     mutable = repo.revs(rs, *rsargs)
   417     mutable = repo.revs(rs, *rsargs)
   413     relevant = revset.baseset(mutable)
   418     relevant = revset.baseset(mutable)
   414 
   419 
   415     # Add parents of mutable changesets to provide context.
   420     # Add parents of mutable changesets to provide context.
   416     relevant += repo.revs('parents(%ld)', mutable)
   421     relevant += repo.revs(b'parents(%ld)', mutable)
   417 
   422 
   418     # We also pull in (public) heads if they a) aren't closing a branch
   423     # We also pull in (public) heads if they a) aren't closing a branch
   419     # b) are recent.
   424     # b) are recent.
   420     rs = 'head() and not closed()'
   425     rs = b'head() and not closed()'
   421     rsargs = []
   426     rsargs = []
   422     if args['headage']:
   427     if args[b'headage']:
   423         rs += ' and date(%s)'
   428         rs += b' and date(%s)'
   424         rsargs.append(
   429         rsargs.append(
   425             revsetlang.getstring(
   430             revsetlang.getstring(
   426                 args['headage'], _('headage requires a string')
   431                 args[b'headage'], _(b'headage requires a string')
   427             )
   432             )
   428         )
   433         )
   429 
   434 
   430     relevant += repo.revs(rs, *rsargs)
   435     relevant += repo.revs(rs, *rsargs)
   431 
   436 
   432     # Add working directory parent.
   437     # Add working directory parent.
   433     wdirrev = repo['.'].rev()
   438     wdirrev = repo[b'.'].rev()
   434     if wdirrev != nullrev:
   439     if wdirrev != nullrev:
   435         relevant += revset.baseset({wdirrev})
   440         relevant += revset.baseset({wdirrev})
   436 
   441 
   437     return subset & relevant
   442     return subset & relevant
   438 
   443 
   439 
   444 
   440 @showview('work', csettopic='work')
   445 @showview(b'work', csettopic=b'work')
   441 def showwork(ui, repo, displayer):
   446 def showwork(ui, repo, displayer):
   442     """changesets that aren't finished"""
   447     """changesets that aren't finished"""
   443     # TODO support date-based limiting when calling revset.
   448     # TODO support date-based limiting when calling revset.
   444     revs = repo.revs('sort(_underway(), topo)')
   449     revs = repo.revs(b'sort(_underway(), topo)')
   445     nodelen = longestshortest(repo, revs)
   450     nodelen = longestshortest(repo, revs)
   446 
   451 
   447     revdag = graphmod.dagwalker(repo, revs)
   452     revdag = graphmod.dagwalker(repo, revs)
   448 
   453 
   449     ui.setconfig('experimental', 'graphshorten', True)
   454     ui.setconfig(b'experimental', b'graphshorten', True)
   450     logcmdutil.displaygraph(
   455     logcmdutil.displaygraph(
   451         ui,
   456         ui,
   452         repo,
   457         repo,
   453         revdag,
   458         revdag,
   454         displayer,
   459         displayer,
   455         graphmod.asciiedges,
   460         graphmod.asciiedges,
   456         props={'nodelen': nodelen},
   461         props={b'nodelen': nodelen},
   457     )
   462     )
   458 
   463 
   459 
   464 
   460 def extsetup(ui):
   465 def extsetup(ui):
   461     # Alias `hg <prefix><view>` to `hg show <view>`.
   466     # Alias `hg <prefix><view>` to `hg show <view>`.
   462     for prefix in ui.configlist('commands', 'show.aliasprefix'):
   467     for prefix in ui.configlist(b'commands', b'show.aliasprefix'):
   463         for view in showview._table:
   468         for view in showview._table:
   464             name = '%s%s' % (prefix, view)
   469             name = b'%s%s' % (prefix, view)
   465 
   470 
   466             choice, allcommands = cmdutil.findpossible(
   471             choice, allcommands = cmdutil.findpossible(
   467                 name, commands.table, strict=True
   472                 name, commands.table, strict=True
   468             )
   473             )
   469 
   474 
   470             # This alias is already a command name. Don't set it.
   475             # This alias is already a command name. Don't set it.
   471             if name in choice:
   476             if name in choice:
   472                 continue
   477                 continue
   473 
   478 
   474             # Same for aliases.
   479             # Same for aliases.
   475             if ui.config('alias', name, None):
   480             if ui.config(b'alias', name, None):
   476                 continue
   481                 continue
   477 
   482 
   478             ui.setconfig('alias', name, 'show %s' % view, source='show')
   483             ui.setconfig(b'alias', name, b'show %s' % view, source=b'show')
   479 
   484 
   480 
   485 
   481 def longestshortest(repo, revs, minlen=4):
   486 def longestshortest(repo, revs, minlen=4):
   482     """Return the length of the longest shortest node to identify revisions.
   487     """Return the length of the longest shortest node to identify revisions.
   483 
   488 
   514                 pycompat.sysstr(key.ljust(longest)),
   519                 pycompat.sysstr(key.ljust(longest)),
   515                 showview._table[key]._origdoc,
   520                 showview._table[key]._origdoc,
   516             )
   521             )
   517         )
   522         )
   518 
   523 
   519     cmdtable['show'][0].__doc__ = pycompat.sysstr('%s\n\n%s\n    ') % (
   524     cmdtable[b'show'][0].__doc__ = pycompat.sysstr(b'%s\n\n%s\n    ') % (
   520         cmdtable['show'][0].__doc__.rstrip(),
   525         cmdtable[b'show'][0].__doc__.rstrip(),
   521         pycompat.sysstr('\n\n').join(entries),
   526         pycompat.sysstr(b'\n\n').join(entries),
   522     )
   527     )
   523 
   528 
   524 
   529 
   525 _updatedocstring()
   530 _updatedocstring()