Patchwork [1,of,2] templates: add whyunstable template keyword

login
register
mail settings
Submitter Anton Shestakov
Date March 26, 2018, 11:55 a.m.
Message ID <123d9e4d706909c8912f.1522065320@neuro>
Download mbox | patch
Permalink /patch/29860/
State Superseded
Headers show

Comments

Anton Shestakov - March 26, 2018, 11:55 a.m.
# HG changeset patch
# User Anton Shestakov <av6@dwimlabs.net>
# Date 1522054812 -28800
#      Mon Mar 26 17:00:12 2018 +0800
# Node ID 123d9e4d706909c8912f11acee292735c0fb283c
# Parent  6f570c501e3ebc3d9b59920f50ed7523d93cb847
templates: add whyunstable template keyword
Yuya Nishihara - March 26, 2018, 1:13 p.m.
On Mon, 26 Mar 2018 19:55:20 +0800, Anton Shestakov wrote:
> # HG changeset patch
> # User Anton Shestakov <av6@dwimlabs.net>
> # Date 1522054812 -28800
> #      Mon Mar 26 17:00:12 2018 +0800
> # Node ID 123d9e4d706909c8912f11acee292735c0fb283c
> # Parent  6f570c501e3ebc3d9b59920f50ed7523d93cb847
> templates: add whyunstable template keyword

> +@templatekeyword('whyunstable', requires={'repo', 'ctx', 'templ'})
                                                            ^^^^^^^

'templ' is no longer needed.

> +def showwhyunstable(context, mapping):
> +    """List of dicts explaining all instabilities of a changeset.
> +    (EXPERIMENTAL)
> +    """
> +    repo = context.resource(mapping, 'repo')
> +    ctx = context.resource(mapping, 'ctx')
> +
> +    def formatnode(ctx):
> +        return '%s (%s)' % (scmutil.formatchangeid(ctx), ctx.phasestr())
> +
> +    def formatentry(entry):
> +        dnodes = ''
> +        if entry.get('divergentnodes'):
> +            dnodes = ' '.join(formatnode(ctx)
> +                              for ctx in entry['divergentnodes']) + ' '
> +        return '%s: %s%s %s' % (entry['instability'],
> +                                dnodes,
> +                                entry['reason'],
> +                                scmutil.formatchangeid(repo[entry['node']]))
> +
> +    def makemap(entry):
> +        item = {'ctx': repo[entry['node']], 'revcache': {}}
                                               ^^^^^^^^^^^^^^

'revcache' is no longer needed.

Perhaps, obsutil.whyunstable() can put 'ctx' instead of 'node'?

> +        item.update(entry)
> +        if item.get('divergentnodes'):
> +            dnhybrid = _hybrid(None, item['divergentnodes'],
> +                               lambda x: {'ctx': x, 'revcache': {}},
> +                               formatnode)

Perhaps showrevslist() can be used. Each hybrid value has to be a printable
object such as int.

> +            item['divergentnodes'] = dnhybrid
> +        return item
> +
> +    entries = obsutil.whyunstable(repo, ctx)
> +    return _hybrid(None, entries, makemap, formatentry)

It isn't correct to wrap a list of template mappings by _hybrid. Instead,
makemap() has to build a mapping dict from a printable value.

Can you hold off this series for 2-3 weeks? I have long series which will
add a wrapper for a list of template mappings. Basically it will allow us
to write the default string representation as template:

  return mappinglist(entries, tmpl='{instability}: {divergentnodes % ...')
Anton Shestakov - March 26, 2018, 1:27 p.m.
On Mon, 26 Mar 2018 22:13:18 +0900
Yuya Nishihara <yuya@tcha.org> wrote:

> Can you hold off this series for 2-3 weeks?

Sure, I'll do that.

> I have long series which will
> add a wrapper for a list of template mappings. Basically it will allow us
> to write the default string representation as template:
> 
>   return mappinglist(entries, tmpl='{instability}: {divergentnodes % ...')

Nice, I'm looking forward to it. It'll definitely simplify this series.
Anton Shestakov - April 14, 2018, 11:58 a.m.
On Mon, 26 Mar 2018 22:13:18 +0900
Yuya Nishihara <yuya@tcha.org> wrote:

> On Mon, 26 Mar 2018 19:55:20 +0800, Anton Shestakov wrote:
> > # HG changeset patch
> > # User Anton Shestakov <av6@dwimlabs.net>
> > # Date 1522054812 -28800
> > #      Mon Mar 26 17:00:12 2018 +0800
> > # Node ID 123d9e4d706909c8912f11acee292735c0fb283c
> > # Parent  6f570c501e3ebc3d9b59920f50ed7523d93cb847
> > templates: add whyunstable template keyword  

I went and revived this series. Let's see if I can squeeze some patches
in before the freeze.

> > +    def makemap(entry):
> > +        item = {'ctx': repo[entry['node']], 'revcache': {}}  
>                                                ^^^^^^^^^^^^^^
> 
> 'revcache' is no longer needed.
> 
> Perhaps, obsutil.whyunstable() can put 'ctx' instead of 'node'?

At least in content-divergent cases, common predecessor can be absent
from local repo. I don't think there's any "surrogate" ctx (i.e. created
from hash alone) that would work here yet.

> > +        item.update(entry)
> > +        if item.get('divergentnodes'):
> > +            dnhybrid = _hybrid(None, item['divergentnodes'],
> > +                               lambda x: {'ctx': x, 'revcache': {}},
> > +                               formatnode)  
> 
> Perhaps showrevslist() can be used. Each hybrid value has to be a printable
> object such as int.

Tried it, but it feels like I'm jumping through hoops for no good
reason: doing ctx.rev() and then repo[rev] right after that just to get
ctx back. Maybe I'm doing something wrong, but I have an idea (not sure
how crazy it is): I'd like to have divergentnodes be a mappinglist with
tmpl that works from inside the entries (also mappinglist). It doesn't
work yet, but I've sent an RFC to get feedback on it.

> > +            item['divergentnodes'] = dnhybrid
> > +        return item
> > +
> > +    entries = obsutil.whyunstable(repo, ctx)
> > +    return _hybrid(None, entries, makemap, formatentry)  
> 
> It isn't correct to wrap a list of template mappings by _hybrid. Instead,
> makemap() has to build a mapping dict from a printable value.
> 
> Can you hold off this series for 2-3 weeks? I have long series which will
> add a wrapper for a list of template mappings. Basically it will allow us
> to write the default string representation as template:
> 
>   return mappinglist(entries, tmpl='{instability}: {divergentnodes % ...')

Patch

diff --git a/mercurial/templatekw.py b/mercurial/templatekw.py
--- a/mercurial/templatekw.py
+++ b/mercurial/templatekw.py
@@ -794,6 +794,40 @@  def showverbosity(context, mapping):
         return 'verbose'
     return ''
 
+@templatekeyword('whyunstable', requires={'repo', 'ctx', 'templ'})
+def showwhyunstable(context, mapping):
+    """List of dicts explaining all instabilities of a changeset.
+    (EXPERIMENTAL)
+    """
+    repo = context.resource(mapping, 'repo')
+    ctx = context.resource(mapping, 'ctx')
+
+    def formatnode(ctx):
+        return '%s (%s)' % (scmutil.formatchangeid(ctx), ctx.phasestr())
+
+    def formatentry(entry):
+        dnodes = ''
+        if entry.get('divergentnodes'):
+            dnodes = ' '.join(formatnode(ctx)
+                              for ctx in entry['divergentnodes']) + ' '
+        return '%s: %s%s %s' % (entry['instability'],
+                                dnodes,
+                                entry['reason'],
+                                scmutil.formatchangeid(repo[entry['node']]))
+
+    def makemap(entry):
+        item = {'ctx': repo[entry['node']], 'revcache': {}}
+        item.update(entry)
+        if item.get('divergentnodes'):
+            dnhybrid = _hybrid(None, item['divergentnodes'],
+                               lambda x: {'ctx': x, 'revcache': {}},
+                               formatnode)
+            item['divergentnodes'] = dnhybrid
+        return item
+
+    entries = obsutil.whyunstable(repo, ctx)
+    return _hybrid(None, entries, makemap, formatentry)
+
 def loadkeyword(ui, extname, registrarobj):
     """Load template keyword from specified registrarobj
     """
diff --git a/tests/test-obsolete-divergent.t b/tests/test-obsolete-divergent.t
--- a/tests/test-obsolete-divergent.t
+++ b/tests/test-obsolete-divergent.t
@@ -721,6 +721,13 @@  Use scmutil.cleanupnodes API to create d
   $ hg debugwhyunstable 1a2a9b5b0030
   content-divergent: 70d5a63ca112acb3764bc1d7320ca90ea688d671 (draft) predecessor a178212c3433c4e77b573f6011e29affb8aefa33
 
+  $ hg log -r 1a2a9b5b0030 --hidden -T '{whyunstable}\n'
+  content-divergent: 4:70d5a63ca112 (draft) predecessor 2:a178212c3433
+  $ hg log -r 1a2a9b5b0030 --hidden -T '{whyunstable%"{instability}: {divergentnodes} {reason} {node}\n"}'
+  content-divergent: 4:70d5a63ca112 (draft) predecessor a178212c3433c4e77b573f6011e29affb8aefa33
+  $ hg log -r 1a2a9b5b0030 --hidden -T '{whyunstable%"{instability}: {divergentnodes%"{node} ({phase})"} {reason} {node}\n"}'
+  content-divergent: 70d5a63ca112acb3764bc1d7320ca90ea688d671 (draft) predecessor a178212c3433c4e77b573f6011e29affb8aefa33
+
 #if serve
 
   $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
diff --git a/tests/test-obsolete.t b/tests/test-obsolete.t
--- a/tests/test-obsolete.t
+++ b/tests/test-obsolete.t
@@ -1039,6 +1039,14 @@  test debugwhyunstable output
   orphan: obsolete parent 3de5eca88c00aa039da7399a220f4a5221faa585
   phase-divergent: immutable predecessor 245bde4270cd1072a27757984f9cda8ba26f08ca
 
+test whyunstable template keyword
+
+  $ hg log -r 50c51b361e60 -T '{whyunstable}\n'
+  orphan: obsolete parent 6:3de5eca88c00 phase-divergent: immutable predecessor 2:245bde4270cd
+  $ hg log -r 50c51b361e60 -T '{whyunstable%"{instability}: {reason} {node}\n"}'
+  orphan: obsolete parent 3de5eca88c00aa039da7399a220f4a5221faa585
+  phase-divergent: immutable predecessor 245bde4270cd1072a27757984f9cda8ba26f08ca
+
 #if serve
 
   $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log