Patchwork templatekw: export ui.paths as {peerpaths}

login
register
mail settings
Submitter Yuya Nishihara
Date July 13, 2017, 4:21 p.m.
Message ID <0601429fa6973ef5eeb9.1499962909@mimosa>
Download mbox | patch
Permalink /patch/22297/
State Accepted
Headers show

Comments

Yuya Nishihara - July 13, 2017, 4:21 p.m.
# HG changeset patch
# User Yuya Nishihara <yuya@tcha.org>
# Date 1499873754 -32400
#      Thu Jul 13 00:35:54 2017 +0900
# Node ID 0601429fa6973ef5eeb97032772ecbdc1c54c37d
# Parent  660613df4ea547c78b4ae06e20e4af46399dc02f
templatekw: export ui.paths as {peerpaths}

It's sometimes useful to show hyperlinks in log output.

  "{get(peerpaths, "default")}/rev/{node}"

Since each path may have sub options, "{peerpaths}" is structured as a dict
of dicts, but the inner dict is rendered as if it were a string URL. The
implementation is ad-hoc, so there are some weird behaviors described in
the test. We might need to introduce a proper way of handling a hybrid
scalar object.

This patch adds _hybrid.__getitem__() so d['path']['url'] works.

The keyword is named as "peerpaths" since "paths" seemed too generic in
log context.
Sean Farley - July 13, 2017, 6:13 p.m.
Yuya Nishihara <yuya@tcha.org> writes:

> # HG changeset patch
> # User Yuya Nishihara <yuya@tcha.org>
> # Date 1499873754 -32400
> #      Thu Jul 13 00:35:54 2017 +0900
> # Node ID 0601429fa6973ef5eeb97032772ecbdc1c54c37d
> # Parent  660613df4ea547c78b4ae06e20e4af46399dc02f
> templatekw: export ui.paths as {peerpaths}
>
> It's sometimes useful to show hyperlinks in log output.
>
>   "{get(peerpaths, "default")}/rev/{node}"
>
> Since each path may have sub options, "{peerpaths}" is structured as a dict
> of dicts, but the inner dict is rendered as if it were a string URL. The
> implementation is ad-hoc, so there are some weird behaviors described in
> the test. We might need to introduce a proper way of handling a hybrid
> scalar object.
>
> This patch adds _hybrid.__getitem__() so d['path']['url'] works.
>
> The keyword is named as "peerpaths" since "paths" seemed too generic in
> log context.

I like this. Queued, thanks!
Yuya Nishihara - July 14, 2017, 2:12 p.m.
On Thu, 13 Jul 2017 11:13:20 -0700, Sean Farley wrote:
> Yuya Nishihara <yuya@tcha.org> writes:
> > # HG changeset patch
> > # User Yuya Nishihara <yuya@tcha.org>
> > # Date 1499873754 -32400
> > #      Thu Jul 13 00:35:54 2017 +0900
> > # Node ID 0601429fa6973ef5eeb97032772ecbdc1c54c37d
> > # Parent  660613df4ea547c78b4ae06e20e4af46399dc02f
> > templatekw: export ui.paths as {peerpaths}
> >
> > It's sometimes useful to show hyperlinks in log output.
> >
> >   "{get(peerpaths, "default")}/rev/{node}"
> >
> > Since each path may have sub options, "{peerpaths}" is structured as a dict
> > of dicts, but the inner dict is rendered as if it were a string URL. The
> > implementation is ad-hoc, so there are some weird behaviors described in
> > the test. We might need to introduce a proper way of handling a hybrid
> > scalar object.
> >
> > This patch adds _hybrid.__getitem__() so d['path']['url'] works.
> >
> > The keyword is named as "peerpaths" since "paths" seemed too generic in
> > log context.
> 
> I like this. Queued, thanks!

Thanks. I noticed the current data structure might not be ideal when adding
indexing operator, so I'll mark it as EXPERIMENTAL.

Patch

diff --git a/mercurial/templatekw.py b/mercurial/templatekw.py
--- a/mercurial/templatekw.py
+++ b/mercurial/templatekw.py
@@ -59,6 +59,8 @@  class _hybrid(object):
             yield makemap(x)
     def __contains__(self, x):
         return x in self._values
+    def __getitem__(self, key):
+        return self._values[key]
     def __len__(self):
         return len(self._values)
     def __iter__(self):
@@ -591,6 +593,25 @@  def showobsolete(repo, ctx, templ, **arg
         return 'obsolete'
     return ''
 
+@templatekeyword('peerpaths')
+def showpeerpaths(repo, **args):
+    """A dictionary of repository locations defined in the [paths] section
+    of your configuration file."""
+    # see commands.paths() for naming of dictionary keys
+    paths = util.sortdict()
+    for k, p in sorted(repo.ui.paths.iteritems()):
+        d = util.sortdict()
+        d['url'] = p.rawloc
+        d.update((o, v) for o, v in sorted(p.suboptions.iteritems()))
+        def f():
+            yield d['url']
+        paths[k] = hybriddict(d, gen=f())
+
+    # no hybriddict() since d['path'] can't be formatted as a string. perhaps
+    # hybriddict() should call templatefilters.stringify(d[value]).
+    return _hybrid(None, paths, lambda k: {'name': k, 'path': paths[k]},
+                   lambda d: '%s=%s' % (d['name'], d['path']['url']))
+
 @templatekeyword("predecessors")
 def showpredecessors(repo, ctx, **args):
     """Returns the list if the closest visible successors
diff --git a/tests/test-paths.t b/tests/test-paths.t
--- a/tests/test-paths.t
+++ b/tests/test-paths.t
@@ -84,7 +84,46 @@  formatter output with paths:
   ]
   [1]
 
-password should be masked in plain output, but not in machine-readable output:
+log template:
+
+ (behaves as a {name: path-string} dict by default)
+
+  $ hg log -rnull -T '{peerpaths}\n'
+  dupe=$TESTTMP/b#tip expand=$TESTTMP/a/$SOMETHING/bar (glob)
+  $ hg log -rnull -T '{join(peerpaths, "\n")}\n'
+  dupe=$TESTTMP/b#tip (glob)
+  expand=$TESTTMP/a/$SOMETHING/bar (glob)
+  $ hg log -rnull -T '{peerpaths % "{name}: {path}\n"}'
+  dupe: $TESTTMP/a/$SOMETHING/bar (glob)
+  expand: $TESTTMP/a/$SOMETHING/bar (glob)
+  $ hg log -rnull -T '{get(peerpaths, "dupe")}\n'
+  $TESTTMP/a/$SOMETHING/bar (glob)
+
+ (but a path is actually a dict of url and sub-options)
+
+  $ hg log -rnull -T '{join(get(peerpaths, "dupe"), "\n")}\n'
+  url=$TESTTMP/b#tip (glob)
+  pushurl=https://example.com/dupe
+  $ hg log -rnull -T '{get(peerpaths, "dupe") % "{key}: {value}\n"}'
+  url: $TESTTMP/b#tip (glob)
+  pushurl: https://example.com/dupe
+  $ hg log -rnull -T '{get(get(peerpaths, "dupe"), "pushurl")}\n'
+  https://example.com/dupe
+
+ (so there's weird behavior)
+
+  $ hg log -rnull -T '{get(peerpaths, "dupe")|count}\n'
+  2
+  $ hg log -rnull -T '{get(peerpaths, "dupe")|stringify|count}\n'
+  [0-9]{2,} (re)
+
+ (in JSON, it's a dict of dicts)
+
+  $ hg log -rnull -T '{peerpaths|json}\n'
+  {"dupe": {"pushurl": "https://example.com/dupe", "url": "$TESTTMP/b#tip"}, "expand": {"url": "$TESTTMP/a/$SOMETHING/bar"}} (glob)
+
+password should be masked in plain output, but not in machine-readable/template
+output:
 
   $ echo 'insecure = http://foo:insecure@example.com/' >> .hg/hgrc
   $ hg paths insecure
@@ -96,6 +135,8 @@  password should be masked in plain outpu
     "url": "http://foo:insecure@example.com/"
    }
   ]
+  $ hg log -rnull -T '{get(peerpaths, "insecure")}\n'
+  http://foo:insecure@example.com/
 
 zeroconf wraps ui.configitems(), which shouldn't crash at least: