Patchwork [2,of,2] commands: introduce `hg display`

login
register
mail settings
Submitter Gregory Szorc
Date Nov. 5, 2016, 6:26 p.m.
Message ID <0ebc1e627383bdf017f5.1478370372@ubuntu-vm-main>
Download mbox | patch
Permalink /patch/17352/
State Changes Requested
Headers show

Comments

Gregory Szorc - Nov. 5, 2016, 6:26 p.m.
# HG changeset patch
# User Gregory Szorc <gregory.szorc@gmail.com>
# Date 1478370119 25200
#      Sat Nov 05 11:21:59 2016 -0700
# Node ID 0ebc1e627383bdf017f509a60725c0b39d6d40d9
# Parent  4bce42e7330311b58ecd38a4acbcd2d2dd1351ba
commands: introduce `hg display`

Currently, Mercurial has a number of commands to show information. And,
there are features coming down the pipe that will introduce more
commands for showing information.

Currently, when introducing a new class of data or a view that we
wish to expose to the user, the strategy is to introduce a new command
or overload an existing command, sometimes both. For example, there is
a desire to formalize the wip/smartlog/underway/mine functionality that
many have devised. There is also a desire to introduce a "topics"
concept. In the current model, we'd need a new command for
wip/smartlog/etc (that behaves a lot like a pre-defined alias of `hg
log`). For topics, we'd likely overload `hg topic[s]` to both display
and manipulate topics.

Adding new commands for every pre-defined query doesn't scale well
and pollutes `hg help`. Overloading commands to perform read-only and
write operations is arguably an UX anti-pattern: while having all
functionality for a given concept in one command is nice, having a
single command doing multiple discrete operations is not. Furthermore,
a user may be surprised that a command they thought was read-only
actually changes something.

We discussed this at the Mercurial 4.0 Sprint in Paris and decided that
having a single command where we could hang pre-defined views of
various data would be a good idea. Having such a command would:

* Help prevent an explosion of new query-related commands
* Create a clear separation between read and write operations
  (mitigates footguns)
* Avoids overloading the meaning of commands that manipulate data
  (bookmark, tag, branch, etc) (while we can't take away the
  existing behavior for BC reasons, we now won't introduce this
  behavior on new commands)
* Allows users to discover informational views more easily by
  aggregating them in a single location
* Lowers the barrier to creating the new views (since the barrier
  to creating a top-level command is relatively high)

So, this commit introduces the `hg display` command. This command
accepts a positional argument of the "view" to show. New views
can be registered with a decorator. To prove it works, we implement
the "bookmarks" view, which shows a table of bookmarks and their
associated nodes.

We introduce a new style to hold everything used by `hg display`.

For our initial bookmarks view, the output varies from `hg bookmarks`:

* Padding is performed in the template itself as opposed to Python
* Revision integers are not shown
* shortest() is used to display a 5 character node by default (as
  opposed to static 12 characters)

I chose to implement the "bookmarks" view first because it is simple
and shouldn't invite too much bikeshedding that detracts from the
evaluation of `hg display` itself. But there is an important point
to consider: we now have 2 ways to show a list of bookmarks. I'm not
a fan of introducing multiple ways to do very similar things. So it
might be worth discussing how we wish to tackle this issue for
bookmarks, tags, branches, MQ series, etc.

I also made the choice of explicitly declaring the default display
template not part of the standard BC guarantees. History has shown
that we make mistakes and poor choices with output formatting but
can't fix these mistakes later because random tools are parsing
output and we don't want to break these tools. Optimizing for human
consumption is one of my goals for `hg display`. So, by not covering
the formatting as part of BC, the barrier to future change is much
lower and humans benefit.

At the aforementioned Sprint, we discussed and discarded various
alternatives to `hg display`.

We considered making `hg log <view>` perform this behavior. The main
reason we can't do this is because a positional argument to `hg log`
can be a file path and if there is a conflict between a path name and
a view name, behavior is ambiguous. We could have introduced
`hg log --view` or similar, but we felt that required too much typing
(we don't want to require a command flag to show a view) and wasn't
very discoverable. Furthermore, `hg log` is optimized for showing
changelog data and there are things that `hg display` could display
that aren't changelog centric.

For the command name, we would have preferred `hg show` because it is
shorter and not ambigious with any other core command. However, a
number of people have created `hg show` as effectively an alias to
`hg export`. And, some were concerned that Git users used to `git show`
being equivalent to `hg export` would be confused by a `hg show` doing
something different.

We also considered `hg view`, but that is already used by the "hgk"
extension.

"display" is an accurate description of what the command does. The
biggest concern with "display" we identifier was "di" is a prefix with
"diff." That concern we addressed with the previous patch. So "display"
was chosen as the command name.
timeless - Nov. 6, 2016, 9:52 a.m.
Gregory Szorc wrote:
> @@ -2019,6 +2026,13 @@ Dish up an empty repo; serve it cold.
>    diff repository (or selected files)
>    </td></tr>
>    <tr><td>
> +  <a href="/help/display">
> +  display
> +  </a>
> +  </td><td>
> +  show various repository information
> +  </td></tr>
> +  <tr><td>
>    <a href="/help/export">
>    export
>    </a>

Will /help/display list the views it supports?
Denis Laxalde - Nov. 7, 2016, 10:03 a.m.
Gregory Szorc a écrit :
> For the command name, we would have preferred `hg show` because it is
> shorter and not ambigious with any other core command. However, a
> number of people have created `hg show` as effectively an alias to
> `hg export`. And, some were concerned that Git users used to `git show`
> being equivalent to `hg export` would be confused by a `hg show` doing
> something different.

`git show` is not equivalent to `hg export`, quoting git-show(1):

        Shows one or more objects (blobs, trees, tags and commits).

        For commits it shows the log message and textual diff. It also
        presents the merge commit in a special format as produced by git
        diff-tree --cc.

        For tags, it shows the tag message and the referenced objects.

        For trees, it shows the names (equivalent to git ls-tree with
        --name-only).

        For plain blobs, it shows the plain contents.

So only the first case is equivalent to `hg export` (or probably more
`hg log -vpr`). Other cases are quite close to the "view" concept
introduced here, as far as I understand.

Then if a revision can be registered as a view, `hg show` could just be
a plain replacement to the aforementioned alias I guess.

Given this and the conflict with `hg diff`, could we reconsider
the command name?
Pierre-Yves David - Nov. 7, 2016, 12:41 p.m.
On 11/05/2016 07:26 PM, Gregory Szorc wrote:
> # HG changeset patch
> # User Gregory Szorc <gregory.szorc@gmail.com>
> # Date 1478370119 25200
> #      Sat Nov 05 11:21:59 2016 -0700
> # Node ID 0ebc1e627383bdf017f509a60725c0b39d6d40d9
> # Parent  4bce42e7330311b58ecd38a4acbcd2d2dd1351ba
> commands: introduce `hg display`

I've not looked into this in details yet¹, but is looks like it should 
be flagged (EXPERIMENTAL) and having some plan page could be useful.
Gregory Szorc - Nov. 8, 2016, 3:50 a.m.
On Mon, Nov 7, 2016 at 4:41 AM, Pierre-Yves David <
pierre-yves.david@ens-lyon.org> wrote:

> On 11/05/2016 07:26 PM, Gregory Szorc wrote:
>
>> # HG changeset patch
>> # User Gregory Szorc <gregory.szorc@gmail.com>
>> # Date 1478370119 25200
>> #      Sat Nov 05 11:21:59 2016 -0700
>> # Node ID 0ebc1e627383bdf017f509a60725c0b39d6d40d9
>> # Parent  4bce42e7330311b58ecd38a4acbcd2d2dd1351ba
>> commands: introduce `hg display`
>>
>
> I've not looked into this in details yet¹, but is looks like it should be
> flagged (EXPERIMENTAL) and having some plan page could be useful.


I'm fine marking it as experimental. How do you want that done?

Regarding the plan page, this proposed command was discussed and had buy-in
at the 4.0 Sprint. I believe the commit message captures most of the
important details of that discussion.

I'm not sure what benefit a wiki page will provide. If it is capturing
planned display views, I can list those here:

* Things we have read-only commands for today (tags, branches, bookmarks,
possibly qseries)
* inprogress/smartlog/wip/unfinished (whatever we call it)
* stack
* Anything else people think of
Gregory Szorc - Nov. 8, 2016, 3:51 a.m.
On Sun, Nov 6, 2016 at 1:52 AM, timeless <timeless@gmail.com> wrote:

> Gregory Szorc wrote:
> > @@ -2019,6 +2026,13 @@ Dish up an empty repo; serve it cold.
> >    diff repository (or selected files)
> >    </td></tr>
> >    <tr><td>
> > +  <a href="/help/display">
> > +  display
> > +  </a>
> > +  </td><td>
> > +  show various repository information
> > +  </td></tr>
> > +  <tr><td>
> >    <a href="/help/export">
> >    export
> >    </a>
>
> Will /help/display list the views it supports?
>

It should. I forgot to implement that. It can be done as a follow-up easily
enough.
Gregory Szorc - Nov. 8, 2016, 4:03 a.m.
On Mon, Nov 7, 2016 at 2:03 AM, Denis Laxalde <denis.laxalde@logilab.fr>
wrote:

> Gregory Szorc a écrit :
>
>> For the command name, we would have preferred `hg show` because it is
>> shorter and not ambigious with any other core command. However, a
>> number of people have created `hg show` as effectively an alias to
>> `hg export`. And, some were concerned that Git users used to `git show`
>> being equivalent to `hg export` would be confused by a `hg show` doing
>> something different.
>>
>
> `git show` is not equivalent to `hg export`, quoting git-show(1):
>
>        Shows one or more objects (blobs, trees, tags and commits).
>
>        For commits it shows the log message and textual diff. It also
>        presents the merge commit in a special format as produced by git
>        diff-tree --cc.
>
>        For tags, it shows the tag message and the referenced objects.
>
>        For trees, it shows the names (equivalent to git ls-tree with
>        --name-only).
>
>        For plain blobs, it shows the plain contents.
>

TIL. I've only ever used `git show` for the "show a commit representation"
use case and `git cat-file` for displaying low-level objects.


>
> So only the first case is equivalent to `hg export` (or probably more
> `hg log -vpr`). Other cases are quite close to the "view" concept
> introduced here, as far as I understand.
>
> Then if a revision can be registered as a view, `hg show` could just be
> a plain replacement to the aforementioned alias I guess.
>
> Given this and the conflict with `hg diff`, could we reconsider
> the command name?
>

That is an interesting proposal. But I'm concerned with overlapping
namespaces. What values do we allow for the non-view behavior? Hash
fragments? Names (bookmarks, branches, tags)? If we allow names, what
happens when a name in a repo conflicts with a registered view name? What
happens if a view name conflicts with a changeset prefix? Of course, to
know if there is a collision you have to load names. That means (slightly
more) overhead to run the command.

FWIW, my idea for this command was to show representations of multiple
things. I'm willing to entertain the idea of "show me single entity X"
(changeset, tag, bookmark, etc). The easy solution is an argument to a view
(`hg display tag my-tag`). Things get harder when we merge namespaces.
Pierre-Yves David - Nov. 10, 2016, 5:44 p.m.
On 11/08/2016 03:50 AM, Gregory Szorc wrote:
> On Mon, Nov 7, 2016 at 4:41 AM, Pierre-Yves David
> <pierre-yves.david@ens-lyon.org <mailto:pierre-yves.david@ens-lyon.org>>
> wrote:
>
>     On 11/05/2016 07:26 PM, Gregory Szorc wrote:
>
>         # HG changeset patch
>         # User Gregory Szorc <gregory.szorc@gmail.com
>         <mailto:gregory.szorc@gmail.com>>
>         # Date 1478370119 25200
>         #      Sat Nov 05 11:21:59 2016 -0700
>         # Node ID 0ebc1e627383bdf017f509a60725c0b39d6d40d9
>         # Parent  4bce42e7330311b58ecd38a4acbcd2d2dd1351ba
>         commands: introduce `hg display`
>
>
>     I've not looked into this in details yet¹, but is looks like it
>     should be flagged (EXPERIMENTAL) and having some plan page could be
>     useful.
>
>
> I'm fine marking it as experimental. How do you want that done?

As for everything else, having "(EXPERIMENTAL)" on the first line should 
do it.

> Regarding the plan page, this proposed command was discussed and had
> buy-in at the 4.0 Sprint. I believe the commit message captures most of
> the important details of that discussion.
 >
> I'm not sure what benefit a wiki page will provide. If it is capturing
> planned display views, I can list those here:
>
> * Things we have read-only commands for today (tags, branches,
> bookmarks, possibly qseries)
> * inprogress/smartlog/wip/unfinished (whatever we call it)
> * stack
> * Anything else people think of

You certainly have buy in the the general idea, I expect many details to 
be ironed out. A wiki page will allow us to discuss and track many of them:

- Possible targets,
- Possible output,
- backward compatibility story,
- progress tracking,
- name discussion (because apparently some people have idea)
- etc,

Cheers and extra thank for tackling this,
Gregory Szorc - Nov. 16, 2016, 4:02 a.m.
On Thu, Nov 10, 2016 at 9:44 AM, Pierre-Yves David <
pierre-yves.david@ens-lyon.org> wrote:

>
>
> On 11/08/2016 03:50 AM, Gregory Szorc wrote:
>
>> On Mon, Nov 7, 2016 at 4:41 AM, Pierre-Yves David
>> <pierre-yves.david@ens-lyon.org <mailto:pierre-yves.david@ens-lyon.org>>
>> wrote:
>>
>>     On 11/05/2016 07:26 PM, Gregory Szorc wrote:
>>
>>         # HG changeset patch
>>         # User Gregory Szorc <gregory.szorc@gmail.com
>>         <mailto:gregory.szorc@gmail.com>>
>>         # Date 1478370119 25200
>>         #      Sat Nov 05 11:21:59 2016 -0700
>>         # Node ID 0ebc1e627383bdf017f509a60725c0b39d6d40d9
>>         # Parent  4bce42e7330311b58ecd38a4acbcd2d2dd1351ba
>>         commands: introduce `hg display`
>>
>>
>>     I've not looked into this in details yet¹, but is looks like it
>>     should be flagged (EXPERIMENTAL) and having some plan page could be
>>     useful.
>>
>>
>> I'm fine marking it as experimental. How do you want that done?
>>
>
> As for everything else, having "(EXPERIMENTAL)" on the first line should
> do it.
>
> Regarding the plan page, this proposed command was discussed and had
>> buy-in at the 4.0 Sprint. I believe the commit message captures most of
>> the important details of that discussion.
>>
> >
>
>> I'm not sure what benefit a wiki page will provide. If it is capturing
>> planned display views, I can list those here:
>>
>> * Things we have read-only commands for today (tags, branches,
>> bookmarks, possibly qseries)
>> * inprogress/smartlog/wip/unfinished (whatever we call it)
>> * stack
>> * Anything else people think of
>>
>
> You certainly have buy in the the general idea, I expect many details to
> be ironed out. A wiki page will allow us to discuss and track many of them:
>
> - Possible targets,
> - Possible output,
> - backward compatibility story,
> - progress tracking,
> - name discussion (because apparently some people have idea)
> - etc,
>
> Cheers and extra thank for tackling this,
>

https://www.mercurial-scm.org/wiki/DisplayCommandPlan now exists.

What are the next plans for this series? I'd *really* like to get something
landed because I feel it could benefit from us developers using it during
the 4.1 cycle. This feature is not something I feel comfortable landing
towards the end of a cycle and then shipping: it needs time to bake.

Perhaps we could take a laissez faire attitude and let it exist in @
enabled by default and make a shipping decision towards the end of the
release cycle?

Patch

diff --git a/contrib/wix/templates.wxs b/contrib/wix/templates.wxs
--- a/contrib/wix/templates.wxs
+++ b/contrib/wix/templates.wxs
@@ -32,6 +32,7 @@ 
           <File Name="map-cmdline.changelog" KeyPath="yes" />
           <File Name="map-cmdline.compact" />
           <File Name="map-cmdline.default" />
+          <File Name="map-cmdline.display" />
           <File Name="map-cmdline.bisect" />
           <File Name="map-cmdline.xml" />
           <File Name="map-cmdline.status" />
diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -61,6 +61,7 @@  from . import (
     phases,
     policy,
     pvec,
+    registrar,
     repair,
     revlog,
     revset,
@@ -3873,6 +3874,71 @@  def diff(ui, repo, *pats, **opts):
                            listsubrepos=opts.get('subrepos'),
                            root=opts.get('root'))
 
+displayview = registrar.displaycmdfunc()
+
+@command('^display', formatteropts, _('[VIEW]'))
+def display(ui, repo, view=None, template=None):
+    """show various repository information
+
+    A requested view of repository data is displayed.
+
+    If no view is requested, the list of available views is shown.
+
+    .. note::
+
+       The default output from this command is not covered under Mercurial's
+       default backwards-compatible mechanism (which puts an emphasis on
+       not changing behavior). This means output from this command may change
+       in any future release. However, the values fed to the formatter are
+       covered under the default backwards-compatible mechanism.
+
+       Automated consumers of this command should specify an explicit template
+       via ``-T/--template`` to guarantee output is stable.
+    """
+    views = displayview._table
+
+    if not view:
+        ui.write(_('available views:\n'))
+        ui.write('\n')
+
+        for name, func in sorted(views.items()):
+            ui.write(_('%s\n') % func.__doc__)
+
+        ui.write('\n')
+        raise error.Abort(_('no view requested'),
+                          hint=_('use `hg display <view>` to choose a view'))
+
+    if view not in views:
+        raise error.Abort(_('unknown view: %s') % view,
+                          hint=_('run `hg display` to see available views'))
+
+    template = template or 'display'
+    fmtopic = views[view]._topic
+    formatter = ui.formatter(fmtopic, {'template': template})
+
+    return views[view](ui, repo, formatter)
+
+@displayview('bookmarks', 'bookmarks')
+def displaybookmarks(ui, repo, fm):
+    """bookmarks and their associated changeset"""
+    marks = repo._bookmarks
+    if not len(marks):
+        ui.write_err('(no bookmarks set)\n')
+        return 0
+
+    active = repo._activebookmark
+    longest = max(len(b) for b in marks)
+
+    for bm, node in sorted(marks.items()):
+        fm.startitem()
+        fm.write('bookmark', '%s', bm)
+        fm.write('node', fm.hexfunc(node), fm.hexfunc(node))
+        fm.data(ctx=repo[node],
+                active=bm == active,
+                longestlen=longest)
+
+    fm.end()
+
 @command('^export',
     [('o', 'output', '',
      _('print output to file with formatted name'), _('FORMAT')),
diff --git a/mercurial/registrar.py b/mercurial/registrar.py
--- a/mercurial/registrar.py
+++ b/mercurial/registrar.py
@@ -247,3 +247,10 @@  class templatefunc(_templateregistrarbas
     Otherwise, explicit 'templater.loadfunction()' is needed.
     """
     _getname = _funcregistrarbase._parsefuncdecl
+
+class displaycmdfunc(_funcregistrarbase):
+    """Register a function to be invoked for an `hg display <thing>`."""
+    _docformat = pycompat.sysstr("%s -- %s")
+
+    def _extrasetup(self, name, func, topic=None):
+        func._topic = topic
diff --git a/mercurial/templates/map-cmdline.display b/mercurial/templates/map-cmdline.display
new file mode 100644
--- /dev/null
+++ b/mercurial/templates/map-cmdline.display
@@ -0,0 +1,2 @@ 
+# TODO add label() once interaction between pad() and label() is sorted out.
+bookmarks = '{if(active, "*", " ")} {pad(bookmark, longestlen + 4)}{shortest(node, 5)}\n'
diff --git a/tests/test-alias.t b/tests/test-alias.t
--- a/tests/test-alias.t
+++ b/tests/test-alias.t
@@ -457,6 +457,7 @@  invalid global arguments for normal comm
    clone         make a copy of an existing repository
    commit        commit the specified files or all outstanding changes
    diff          diff repository (or selected files)
+   display       show various repository information
    export        dump the header and diffs for one or more changesets
    forget        forget the specified files on the next commit
    init          create a new repository in the given directory
@@ -483,6 +484,7 @@  invalid global arguments for normal comm
    clone         make a copy of an existing repository
    commit        commit the specified files or all outstanding changes
    diff          diff repository (or selected files)
+   display       show various repository information
    export        dump the header and diffs for one or more changesets
    forget        forget the specified files on the next commit
    init          create a new repository in the given directory
@@ -509,6 +511,7 @@  invalid global arguments for normal comm
    clone         make a copy of an existing repository
    commit        commit the specified files or all outstanding changes
    diff          diff repository (or selected files)
+   display       show various repository information
    export        dump the header and diffs for one or more changesets
    forget        forget the specified files on the next commit
    init          create a new repository in the given directory
diff --git a/tests/test-command-template.t b/tests/test-command-template.t
--- a/tests/test-command-template.t
+++ b/tests/test-command-template.t
@@ -1108,11 +1108,11 @@  Error if no style:
 
   $ hg log --style notexist
   abort: style 'notexist' not found
-  (available styles: bisect, changelog, compact, default, phases, status, xml)
+  (available styles: bisect, changelog, compact, default, display, phases, status, xml)
   [255]
 
   $ hg log -T list
-  available styles: bisect, changelog, compact, default, phases, status, xml
+  available styles: bisect, changelog, compact, default, display, phases, status, xml
   abort: specify a template
   [255]
 
diff --git a/tests/test-commandserver.t b/tests/test-commandserver.t
--- a/tests/test-commandserver.t
+++ b/tests/test-commandserver.t
@@ -65,6 +65,7 @@  typical client does not want echo-back m
    clone         make a copy of an existing repository
    commit        commit the specified files or all outstanding changes
    diff          diff repository (or selected files)
+   display       show various repository information
    export        dump the header and diffs for one or more changesets
    forget        forget the specified files on the next commit
    init          create a new repository in the given directory
diff --git a/tests/test-completion.t b/tests/test-completion.t
--- a/tests/test-completion.t
+++ b/tests/test-completion.t
@@ -16,6 +16,7 @@  Show all commands except debug commands
   config
   copy
   diff
+  display
   export
   files
   forget
@@ -65,6 +66,7 @@  Show all commands that start with "a"
 Do not show debug commands if there are other candidates
   $ hg debugcomplete d
   diff
+  display
 
 Show debug commands if there are no other candidates
   $ hg debugcomplete debug
@@ -211,6 +213,7 @@  Show all commands + options
   clone: noupdate, updaterev, rev, branch, pull, uncompressed, ssh, remotecmd, insecure
   commit: addremove, close-branch, amend, secret, edit, interactive, include, exclude, message, logfile, date, user, subrepos
   diff: rev, change, text, git, nodates, noprefix, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, stat, root, include, exclude, subrepos
+  display: template
   export: output, switch-parent, rev, text, git, nodates
   forget: include, exclude
   init: ssh, remotecmd, insecure
diff --git a/tests/test-display.t b/tests/test-display.t
new file mode 100644
--- /dev/null
+++ b/tests/test-display.t
@@ -0,0 +1,47 @@ 
+No arguments shows available views
+
+  $ hg init empty
+  $ cd empty
+  $ hg display
+  available views:
+  
+  bookmarks -- bookmarks and their associated changeset
+  
+  abort: no view requested
+  (use `hg display <view>` to choose a view)
+  [255]
+
+Unknown view prints error
+
+  $ hg display badview
+  abort: unknown view: badview
+  (run `hg display` to see available views)
+  [255]
+
+  $ cd ..
+
+bookmarks view shows bookmarks in an aligned table
+
+  $ hg init books
+  $ cd books
+  $ touch f0
+  $ hg -q commit -A -m initial
+  $ echo book1 > f0
+  $ hg commit -m 'commit for book1'
+  $ echo book2 > f0
+  $ hg commit -m 'commit for book2'
+
+  $ hg bookmark -r 1 book1
+  $ hg bookmark a-longer-bookmark
+
+  $ hg display bookmarks
+  * a-longer-bookmark    7b570
+    book1                b757f
+
+A custom bookmarks template works
+
+  $ hg display bookmarks -T '{node} {bookmark} {active}\n'
+  7b5709ab64cbc34da9b4367b64afff47f2c4ee83 a-longer-bookmark True
+  b757f780b8ffd71267c6ccb32e0882d9d32a8cc0 book1 False
+
+  $ cd ..
diff --git a/tests/test-globalopts.t b/tests/test-globalopts.t
--- a/tests/test-globalopts.t
+++ b/tests/test-globalopts.t
@@ -303,6 +303,7 @@  Testing -h/--help:
    config        show combined config settings from all hgrc files
    copy          mark files as copied for the next commit
    diff          diff repository (or selected files)
+   display       show various repository information
    export        dump the header and diffs for one or more changesets
    files         list tracked files
    forget        forget the specified files on the next commit
@@ -386,6 +387,7 @@  Testing -h/--help:
    config        show combined config settings from all hgrc files
    copy          mark files as copied for the next commit
    diff          diff repository (or selected files)
+   display       show various repository information
    export        dump the header and diffs for one or more changesets
    files         list tracked files
    forget        forget the specified files on the next commit
diff --git a/tests/test-help.t b/tests/test-help.t
--- a/tests/test-help.t
+++ b/tests/test-help.t
@@ -10,6 +10,7 @@  Short help:
    clone         make a copy of an existing repository
    commit        commit the specified files or all outstanding changes
    diff          diff repository (or selected files)
+   display       show various repository information
    export        dump the header and diffs for one or more changesets
    forget        forget the specified files on the next commit
    init          create a new repository in the given directory
@@ -31,6 +32,7 @@  Short help:
    clone         make a copy of an existing repository
    commit        commit the specified files or all outstanding changes
    diff          diff repository (or selected files)
+   display       show various repository information
    export        dump the header and diffs for one or more changesets
    forget        forget the specified files on the next commit
    init          create a new repository in the given directory
@@ -65,6 +67,7 @@  Short help:
    config        show combined config settings from all hgrc files
    copy          mark files as copied for the next commit
    diff          diff repository (or selected files)
+   display       show various repository information
    export        dump the header and diffs for one or more changesets
    files         list tracked files
    forget        forget the specified files on the next commit
@@ -142,6 +145,7 @@  Short help:
    config        show combined config settings from all hgrc files
    copy          mark files as copied for the next commit
    diff          diff repository (or selected files)
+   display       show various repository information
    export        dump the header and diffs for one or more changesets
    files         list tracked files
    forget        forget the specified files on the next commit
@@ -297,6 +301,7 @@  Test short command list with verbose opt
    clone         make a copy of an existing repository
    commit, ci    commit the specified files or all outstanding changes
    diff, di      diff repository (or selected files)
+   display       show various repository information
    export        dump the header and diffs for one or more changesets
    forget        forget the specified files on the next commit
    init          create a new repository in the given directory
@@ -638,6 +643,7 @@  Test command without options
    clone         make a copy of an existing repository
    commit        commit the specified files or all outstanding changes
    diff          diff repository (or selected files)
+   display       show various repository information
    export        dump the header and diffs for one or more changesets
    forget        forget the specified files on the next commit
    init          create a new repository in the given directory
@@ -782,6 +788,7 @@  Test that default list of commands omits
    config        show combined config settings from all hgrc files
    copy          mark files as copied for the next commit
    diff          diff repository (or selected files)
+   display       show various repository information
    export        dump the header and diffs for one or more changesets
    files         list tracked files
    forget        forget the specified files on the next commit
@@ -2019,6 +2026,13 @@  Dish up an empty repo; serve it cold.
   diff repository (or selected files)
   </td></tr>
   <tr><td>
+  <a href="/help/display">
+  display
+  </a>
+  </td><td>
+  show various repository information
+  </td></tr>
+  <tr><td>
   <a href="/help/export">
   export
   </a>
diff --git a/tests/test-hgweb-json.t b/tests/test-hgweb-json.t
--- a/tests/test-hgweb-json.t
+++ b/tests/test-hgweb-json.t
@@ -1365,6 +1365,10 @@  help/ shows help topics
         "topic": "diff"
       },
       {
+        "summary": "show various repository information",
+        "topic": "display"
+      },
+      {
         "summary": "dump the header and diffs for one or more changesets",
         "topic": "export"
       },
diff --git a/tests/test-log.t b/tests/test-log.t
--- a/tests/test-log.t
+++ b/tests/test-log.t
@@ -148,7 +148,7 @@  log on directory
 
   $ hg log -f -l1 --style something
   abort: style 'something' not found
-  (available styles: bisect, changelog, compact, default, phases, status, xml)
+  (available styles: bisect, changelog, compact, default, display, phases, status, xml)
   [255]
 
 -f, phases style
diff --git a/tests/test-strict.t b/tests/test-strict.t
--- a/tests/test-strict.t
+++ b/tests/test-strict.t
@@ -24,6 +24,7 @@ 
    clone         make a copy of an existing repository
    commit        commit the specified files or all outstanding changes
    diff          diff repository (or selected files)
+   display       show various repository information
    export        dump the header and diffs for one or more changesets
    forget        forget the specified files on the next commit
    init          create a new repository in the given directory