Patchwork [4,of,6] log: rewrite default template to use labels (issue2866)

login
register
mail settings
Submitter Jordi Gutiérrez Hermoso
Date Oct. 5, 2014, 1:05 a.m.
Message ID <e2e9f9da5f6ce85a7c5b.1412471153@Iris>
Download mbox | patch
Permalink /patch/6123/
State Accepted
Commit 0ded0f0b1c04eea1307846b147180119ac4a89cc
Headers show

Comments

Jordi Gutiérrez Hermoso - Oct. 5, 2014, 1:05 a.m.
# HG changeset patch
# User Jordi Gutiérrez Hermoso <jordigh@octave.org>
# Date 1412380136 14400
#      Fri Oct 03 19:48:56 2014 -0400
# Node ID e2e9f9da5f6ce85a7c5b9fee7c78755946a39f25
# Parent  c28167265129cb945c2f0967c2a9bc89cbaa6fa9
log: rewrite default template to use labels (issue2866)

This is a complete rewrite of the default template to use labels. This
seems ultimately useless to me in most cases. The biggest benefit of
this patch to me seems to be a fairly complicated example of the
templating engine. It was a lot of hard work to figure out the precise
acceptable syntax, since it's almost undocumented. Hat tip to Steve
Losh's smartlog template, which helped me figure out a lot of the
syntax. Hopefully later I can use the present default log template
as an example for documenting the templating engine.

A test is attached. My goal was to match the --color=debug output,
which may differ slightly in newlines from the actual ANSI escape
codes output. I consider this an acceptable invisible deviation.

There seems to be a considerable slowdown with this rewrite.

Before:

    $ time hg log -T default -r .~100::. > /dev/null
    real  0m0.882s
    user  0m0.812s
    sys   0m0.064s
    $ time hg log -T default -r .~100::. > /dev/null
    real  0m0.872s
    user  0m0.796s
    sys   0m0.068s
    $ time hg log -T default -r .~100::. > /dev/null
    real  0m0.917s
    user  0m0.836s
    sys   0m0.076s

After:

    $ time hg log -T default -r .~100::. > /dev/null
    real  0m1.480s
    user  0m1.392s
    sys   0m0.072s
    $ time hg log -T default -r .~100::. > /dev/null
    real  0m1.500s
    user  0m1.400s
    sys   0m0.088s
    $ time hg log -T default -r .~100::. > /dev/null
    real  0m1.462s
    user  0m1.364s
    sys   0m0.092s

Following the maxim, "make it work, profile, make it faster, in that
order", I deem this slowdown acceptable for now.

I suspect but have not confirmed that a big slowdown comes from
calling keywords twice in the file templates, once to test the
existence of output and again to actually list the output. If so, a
simple speedup might be to improve the templating engine to cache
keywords when called more than once on the same revision.

TODO: I found a bug while working on this. The following stack traces:

    hg log -r . -T '{ifcontains(phase, "secret public", "lol", "omg")}\n'
Martin Geisler - Oct. 6, 2014, 11:50 a.m.
Jordi Gutiérrez Hermoso <jordigh@octave.org> writes:

> # HG changeset patch
> # User Jordi Gutiérrez Hermoso <jordigh@octave.org>
> # Date 1412380136 14400
> #      Fri Oct 03 19:48:56 2014 -0400
> # Node ID e2e9f9da5f6ce85a7c5b9fee7c78755946a39f25
> # Parent  c28167265129cb945c2f0967c2a9bc89cbaa6fa9
> log: rewrite default template to use labels (issue2866)
>
> This is a complete rewrite of the default template to use labels. This
> seems ultimately useless to me in most cases.

Not useless at all: I've seen people ask why colors disappeared when
they used 'hg log -T default'. This typically comes up when they copy
the default template to tweak it.

Patch

diff --git a/mercurial/templates/map-cmdline.default b/mercurial/templates/map-cmdline.default
--- a/mercurial/templates/map-cmdline.default
+++ b/mercurial/templates/map-cmdline.default
@@ -1,25 +1,73 @@ 
-changeset = 'changeset:   {rev}:{node|short}\n{branches}{bookmarks}{tags}{parents}user:        {author}\ndate:        {date|date}\nsummary:     {desc|firstline}\n\n'
-changeset_quiet = '{rev}:{node|short}\n'
-changeset_verbose = 'changeset:   {rev}:{node|short}\n{branches}{bookmarks}{tags}{parents}user:        {author}\ndate:        {date|date}\n{files}{file_copies_switch}description:\n{desc|strip}\n\n\n'
-changeset_debug = 'changeset:   {rev}:{node}\n{branches}{bookmarks}{tags}phase:       {phase}\n{parents}{manifest}user:        {author}\ndate:        {date|date}\n{file_mods}{file_adds}{file_dels}{file_copies_switch}{extras}description:\n{desc|strip}\n\n\n'
-start_files = 'files:      '
-file = ' {file}'
-end_files = '\n'
-start_file_mods = 'files:      '
-file_mod = ' {file_mod}'
-end_file_mods = '\n'
-start_file_adds = 'files+:     '
-file_add = ' {file_add}'
-end_file_adds = '\n'
-start_file_dels = 'files-:     '
-file_del = ' {file_del}'
-end_file_dels = '\n'
-start_file_copies = 'copies:     '
-file_copy = ' {name} ({source})'
-end_file_copies = '\n'
-parent = 'parent:      {rev}:{node|formatnode}\n'
-manifest = 'manifest:    {rev}:{node}\n'
-branch = 'branch:      {branch}\n'
-tag = 'tag:         {tag}\n'
-bookmark = 'bookmark:    {bookmark}\n'
-extra = 'extra:       {key}={value|stringescape}\n'
+# Base templates. Due to name clashes with existing keywords, we have
+# to replace some keywords with 'lkeyword', for 'labelled keyword'
+changeset = '{cset}{branches}{bookmarks}{tags}{parents}{user}{ldate}{summary}\n'
+changeset_quiet = '{node}'
+changeset_verbose = '{cset}{branches}{bookmarks}{tags}{parents}{user}{ldate}{lfiles}{lfile_copies_switch}{description}\n'
+changeset_debug = '{fullcset}{branches}{bookmarks}{tags}{lphase}{parents}{manifest}{user}{ldate}{lfile_mods}{lfile_adds}{lfile_dels}{lfile_copies_switch}{extras}{description}\n'
+
+# File templates
+lfiles = '{if(files,
+               label("ui.note log.files",
+                     "files:       {files}\n"))}'
+
+lfile_mods = '{if(file_mods,
+                  label("ui.debug log.files",
+                        "files:       {file_mods}\n"))}'
+
+lfile_adds = '{if(file_adds,
+                  label("ui.debug log.files",
+                        "files+:      {file_adds}\n"))}'
+
+lfile_dels = '{if(file_dels,
+                  label("ui.debug log.files",
+                        "files-:      {file_dels}\n"))}'
+
+lfile_copies_switch = '{if(file_copies_switch,
+                           label("ui.note log.copies",
+                                 "copies:     {file_copies_switch
+                                               % ' {name} ({source})'}\n"))}'
+
+# General templates
+cset = '{label("log.changeset changeset.{phase}",
+               "changeset:   {rev}:{node|short}")}\n'
+
+lphase = '{label("log.phase",
+                 "phase:       {phase}")}\n'
+
+fullcset = '{label("log.changeset changeset.{phase}",
+                   "changeset:   {rev}:{node}")}\n'
+
+parent = '{label("log.parent changeset.{phase}",
+                  "parent:      {rev}:{node|formatnode}")}\n'
+
+node = '{label("log.node",
+                "{rev}:{node|short}")}\n'
+
+manifest = '{label("ui.debug log.manifest",
+                   "manifest:    {rev}:{node}")}\n'
+
+branch = '{label("log.branch",
+                 "branch:      {branch}")}\n'
+
+tag = '{label("log.tag",
+              "tag:         {tag}")}\n'
+
+bookmark = '{label("log.bookmark",
+                   "bookmark:    {bookmark}")}\n'
+
+user = '{label("log.user",
+               "user:        {author}")}\n'
+
+summary = '{label("log.summary",
+                  "summary:     {desc|firstline}")}\n'
+
+ldate = '{label("log.date",
+                "date:        {date|date}")}\n'
+
+extra = '{label("ui.debug log.extra",
+                "extra:       {key}={value|stringescape}")}\n'
+
+description = '{label("ui.note log.description",
+                       "description:")}
+               {label("ui.note log.description",
+                       "{desc|strip}")}\n\n'
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
@@ -105,6 +105,26 @@  Default style is like normal output:
   $ hg log --debug --style default > style.out
   $ cmp log.out style.out || diff -u log.out style.out
 
+Default style should also preserve color information (issue2866):
+
+  $ cp $HGRCPATH $HGRCPATH-bak
+  $ cat <<EOF >> $HGRCPATH
+  > [extensions]
+  > color=
+  > EOF
+
+  $ hg --color=debug log > log.out
+  $ hg --color=debug log --style default > style.out
+  $ cmp log.out style.out || diff -u log.out style.out
+  $ hg --color=debug -v log > log.out
+  $ hg --color=debug -v log --style default > style.out
+  $ cmp log.out style.out || diff -u log.out style.out
+  $ hg --color=debug --debug log > log.out
+  $ hg --color=debug --debug log --style default > style.out
+  $ cmp log.out style.out || diff -u log.out style.out
+
+  $ mv $HGRCPATH-bak $HGRCPATH
+
 Revision with no copies (used to print a traceback):
 
   $ hg tip -v --template '\n'