Patchwork [12,of,12] templater: add a method to list labels in a namespace

login
register
mail settings
Submitter Sean Farley
Date Aug. 18, 2014, 9:18 p.m.
Message ID <fe9b72aa7e160e690813.1408396688@1.0.0.127.in-addr.arpa>
Download mbox | patch
Permalink /patch/5470/
State Changes Requested
Headers show

Comments

Sean Farley - Aug. 18, 2014, 9:18 p.m.
# HG changeset patch
# User Sean Farley <sean.michael.farley@gmail.com>
# Date 1408394323 18000
#      Mon Aug 18 15:38:43 2014 -0500
# Node ID fe9b72aa7e160e690813cfe4242b013fb147937e
# Parent  e1ab9da20be237323a1340efa16b58b03525596f
templater: add a method to list labels in a namespace
Augie Fackler - Aug. 19, 2014, 2:05 p.m.
On Mon, Aug 18, 2014 at 04:18:08PM -0500, Sean Farley wrote:
> # HG changeset patch
> # User Sean Farley <sean.michael.farley@gmail.com>
> # Date 1408394323 18000
> #      Mon Aug 18 15:38:43 2014 -0500
> # Node ID fe9b72aa7e160e690813cfe4242b013fb147937e
> # Parent  e1ab9da20be237323a1340efa16b58b03525596f
> templater: add a method to list labels in a namespace

I don't quite see the why of this series - is it so we can add other
types of labels to a changeset without having to do a bunch of
tapdancing? How would that be useful?

(The generality is kind of nice, and I can sort of see a use for
remotebranches in that a remotebranch could become a non-tag label,
but I'm not sure I'm sold that it'd be worth doing there, because then
you'd still have to wire in some lookup mechanics.)

>
> diff --git a/mercurial/templater.py b/mercurial/templater.py
> --- a/mercurial/templater.py
> +++ b/mercurial/templater.py
> @@ -357,10 +357,23 @@ def color(context, mapping, args):
>          raise error.ParseError(_("color expects two arguments"))
>
>      # ignore args[0] (the color string) since this is supposed to be a a no-op
>      yield _evalifliteral(args[1], context, mapping)
>
> +def labels(context, mapping, args):
> +    if len(args) != 1:
> +        # i18n: "label" is a keyword
> +        raise error.ParseError(_("labels expects one argument"))
> +
> +    ctx = mapping['ctx']
> +    repo = ctx._repo
> +    namespace = args[0][1]
> +    l = sorted(l[0] for l in repo.nodelabels(ctx.node())
> +               if l[1] == namespace)
> +
> +    return templatekw.showlist('label', l, **mapping)
> +
>  def revset(context, mapping, args):
>      """usage: revset(query[, formatargs...])
>      """
>      if not len(args) > 0:
>          # i18n: "revset" is a keyword
> @@ -517,10 +530,11 @@ funcs = {
>      "if": if_,
>      "ifcontains": ifcontains,
>      "ifeq": ifeq,
>      "join": join,
>      "label": color, # backwards compatibility before 3.1
> +    "labels": labels,
>      "pad": pad,
>      "revset": revset,
>      "rstdoc": rstdoc,
>      "shortest": shortest,
>      "startswith": startswith,
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel
Sean Farley - Aug. 19, 2014, 3:21 p.m.
Augie Fackler writes:

> On Mon, Aug 18, 2014 at 04:18:08PM -0500, Sean Farley wrote:
>> # HG changeset patch
>> # User Sean Farley <sean.michael.farley@gmail.com>
>> # Date 1408394323 18000
>> #      Mon Aug 18 15:38:43 2014 -0500
>> # Node ID fe9b72aa7e160e690813cfe4242b013fb147937e
>> # Parent  e1ab9da20be237323a1340efa16b58b03525596f
>> templater: add a method to list labels in a namespace
>
> I don't quite see the why of this series - is it so we can add other
> types of labels to a changeset without having to do a bunch of
> tapdancing? How would that be useful?
>
> (The generality is kind of nice, and I can sort of see a use for
> remotebranches in that a remotebranch could become a non-tag label,
> but I'm not sure I'm sold that it'd be worth doing there, because then
> you'd still have to wire in some lookup mechanics.)

Yep, you guessed it. This series sprouted from my work on remotebranches
(to add bookmark support). The "why" of this series is to turn off the
flood of local tags (hg-git, remotebranches, etc.)

The key features of adding this machinery to core:

- no more polluting the output of 'hg tags'
- automatic template keywords / functions (see patches 11-12)
- displaying correctly in the log (see patch 7)
- automatic tab completion (see patch 9)
- automatic support for color (see patch 7)

Now, all an extension would have to do is (actual test code I used):

    repo.label("foo", "f1", repo['8a6a86c9a5b5'].node())
    repo.label("foo", "f2", repo['8a6a86c9a5b5'].node())
    repo.label("bar", "b1", repo['8a6a86c9a5b5'].node())
    repo.label("bar", "b2", repo['8a6a86c9a5b5'].node())

And they would get all the nice coloring, tab completion, and templating
without having to add that themselves (though, you could certainly add
more fancy things).

For example, imagine that the bugzilla extension could add all ticket
numbers to known commits:

    repo.label("tickets", "issue1234", repo[foo].node())

And in the command line:

    $ hg up issue<tab>
issue1234 etc.

Anyway, those are just some ideas.
Angel Ezquerra - Aug. 20, 2014, 11:51 a.m.
On Tue, Aug 19, 2014 at 5:21 PM, Sean Farley
<sean.michael.farley@gmail.com> wrote:
>
> Augie Fackler writes:
>
>> On Mon, Aug 18, 2014 at 04:18:08PM -0500, Sean Farley wrote:
>>> # HG changeset patch
>>> # User Sean Farley <sean.michael.farley@gmail.com>
>>> # Date 1408394323 18000
>>> #      Mon Aug 18 15:38:43 2014 -0500
>>> # Node ID fe9b72aa7e160e690813cfe4242b013fb147937e
>>> # Parent  e1ab9da20be237323a1340efa16b58b03525596f
>>> templater: add a method to list labels in a namespace
>>
>> I don't quite see the why of this series - is it so we can add other
>> types of labels to a changeset without having to do a bunch of
>> tapdancing? How would that be useful?
>>
>> (The generality is kind of nice, and I can sort of see a use for
>> remotebranches in that a remotebranch could become a non-tag label,
>> but I'm not sure I'm sold that it'd be worth doing there, because then
>> you'd still have to wire in some lookup mechanics.)
>
> Yep, you guessed it. This series sprouted from my work on remotebranches
> (to add bookmark support). The "why" of this series is to turn off the
> flood of local tags (hg-git, remotebranches, etc.)
>
> The key features of adding this machinery to core:
>
> - no more polluting the output of 'hg tags'
> - automatic template keywords / functions (see patches 11-12)
> - displaying correctly in the log (see patch 7)
> - automatic tab completion (see patch 9)
> - automatic support for color (see patch 7)
>
> Now, all an extension would have to do is (actual test code I used):
>
>     repo.label("foo", "f1", repo['8a6a86c9a5b5'].node())
>     repo.label("foo", "f2", repo['8a6a86c9a5b5'].node())
>     repo.label("bar", "b1", repo['8a6a86c9a5b5'].node())
>     repo.label("bar", "b2", repo['8a6a86c9a5b5'].node())
>
> And they would get all the nice coloring, tab completion, and templating
> without having to add that themselves (though, you could certainly add
> more fancy things).
>
> For example, imagine that the bugzilla extension could add all ticket
> numbers to known commits:
>
>     repo.label("tickets", "issue1234", repo[foo].node())
>
> And in the command line:
>
>     $ hg up issue<tab>
> issue1234 etc.
>
> Anyway, those are just some ideas.

This is very cool. In fact this past couple of weeks I have been
working on a small extension of may own that I am (was?) going to call
"hgmarkers" that was meant to let you add arbitrary "markers" (I also
considered calling them "labels") to revisions. I was using a
"ini-like" file to store those markers, but your solution could be
cleaner.

One important feature of this extension of mine is that a single
marker can be applied to multiple revisions (actually you can even
associate a revset to a marker). Would this be possible to do using
this repo.label command? That is, could I do:

     repo.label("foo", "f1", repo['8a6a86c9a5b5'].node())
     repo.label("foo", "f1", repo['1d875217f959'].node())

And have both revisions labelled foo/f1?

Cheers,

Angel
Pierre-Yves David - Aug. 21, 2014, 8:01 a.m.
On 08/18/2014 02:18 PM, Sean Farley wrote:
> # HG changeset patch
> # User Sean Farley <sean.michael.farley@gmail.com>
> # Date 1408394323 18000
> #      Mon Aug 18 15:38:43 2014 -0500
> # Node ID fe9b72aa7e160e690813cfe4242b013fb147937e
> # Parent  e1ab9da20be237323a1340efa16b58b03525596f
> templater: add a method to list labels in a namespace

I'm not sure about what this new function does. And the lack fo 
documentation does not helps.

It also lack tests (as, I just realised, this whole series)

>
> diff --git a/mercurial/templater.py b/mercurial/templater.py
> --- a/mercurial/templater.py
> +++ b/mercurial/templater.py
> @@ -357,10 +357,23 @@ def color(context, mapping, args):
>           raise error.ParseError(_("color expects two arguments"))
>
>       # ignore args[0] (the color string) since this is supposed to be a a no-op
>       yield _evalifliteral(args[1], context, mapping)
>
> +def labels(context, mapping, args):
> +    if len(args) != 1:
> +        # i18n: "label" is a keyword
> +        raise error.ParseError(_("labels expects one argument"))
> +
> +    ctx = mapping['ctx']
> +    repo = ctx._repo
> +    namespace = args[0][1]
> +    l = sorted(l[0] for l in repo.nodelabels(ctx.node())
> +               if l[1] == namespace)
> +
> +    return templatekw.showlist('label', l, **mapping)
> +
>   def revset(context, mapping, args):
>       """usage: revset(query[, formatargs...])
>       """
>       if not len(args) > 0:
>           # i18n: "revset" is a keyword
> @@ -517,10 +530,11 @@ funcs = {
>       "if": if_,
>       "ifcontains": ifcontains,
>       "ifeq": ifeq,
>       "join": join,
>       "label": color, # backwards compatibility before 3.1
> +    "labels": labels,
>       "pad": pad,
>       "revset": revset,
>       "rstdoc": rstdoc,
>       "shortest": shortest,
>       "startswith": startswith,
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel
>
Pierre-Yves David - Aug. 21, 2014, 8:04 a.m.
On 08/19/2014 07:05 AM, Augie Fackler wrote:
> On Mon, Aug 18, 2014 at 04:18:08PM -0500, Sean Farley wrote:
>> # HG changeset patch
>> # User Sean Farley <sean.michael.farley@gmail.com>
>> # Date 1408394323 18000
>> #      Mon Aug 18 15:38:43 2014 -0500
>> # Node ID fe9b72aa7e160e690813cfe4242b013fb147937e
>> # Parent  e1ab9da20be237323a1340efa16b58b03525596f
>> templater: add a method to list labels in a namespace
>
> I don't quite see the why of this series - is it so we can add other
> types of labels to a changeset without having to do a bunch of
> tapdancing? How would that be useful?
>
> (The generality is kind of nice, and I can sort of see a use for
> remotebranches in that a remotebranch could become a non-tag label,
> but I'm not sure I'm sold that it'd be worth doing there, because then
> you'd still have to wire in some lookup mechanics.)

The point is to have a single, first class citizen where all extensions 
can plug themself. so ou take car eof lookup and co once and for all.

I love the idea and think it worth the effort.
Sean Farley - Aug. 21, 2014, 6:27 p.m.
Pierre-Yves David writes:

> On 08/18/2014 02:18 PM, Sean Farley wrote:
>> # HG changeset patch
>> # User Sean Farley <sean.michael.farley@gmail.com>
>> # Date 1408394323 18000
>> #      Mon Aug 18 15:38:43 2014 -0500
>> # Node ID fe9b72aa7e160e690813cfe4242b013fb147937e
>> # Parent  e1ab9da20be237323a1340efa16b58b03525596f
>> templater: add a method to list labels in a namespace
>
> I'm not sure about what this new function does. And the lack fo 
> documentation does not helps.
>
> It also lack tests (as, I just realised, this whole series)

After we decide on a name, I'll add the tests and more
documentation. This patch adds the ability to do:

hg log -r . -T '{rev}:{node | short} {labels("foo") % "foo/{label} "}\n'
Sean Farley - Aug. 21, 2014, 6:30 p.m.
Angel Ezquerra writes:

> On Tue, Aug 19, 2014 at 5:21 PM, Sean Farley
> <sean.michael.farley@gmail.com> wrote:
>>
>> Augie Fackler writes:
>>
>>> On Mon, Aug 18, 2014 at 04:18:08PM -0500, Sean Farley wrote:
>>>> # HG changeset patch
>>>> # User Sean Farley <sean.michael.farley@gmail.com>
>>>> # Date 1408394323 18000
>>>> #      Mon Aug 18 15:38:43 2014 -0500
>>>> # Node ID fe9b72aa7e160e690813cfe4242b013fb147937e
>>>> # Parent  e1ab9da20be237323a1340efa16b58b03525596f
>>>> templater: add a method to list labels in a namespace
>>>
>>> I don't quite see the why of this series - is it so we can add other
>>> types of labels to a changeset without having to do a bunch of
>>> tapdancing? How would that be useful?
>>>
>>> (The generality is kind of nice, and I can sort of see a use for
>>> remotebranches in that a remotebranch could become a non-tag label,
>>> but I'm not sure I'm sold that it'd be worth doing there, because then
>>> you'd still have to wire in some lookup mechanics.)
>>
>> Yep, you guessed it. This series sprouted from my work on remotebranches
>> (to add bookmark support). The "why" of this series is to turn off the
>> flood of local tags (hg-git, remotebranches, etc.)
>>
>> The key features of adding this machinery to core:
>>
>> - no more polluting the output of 'hg tags'
>> - automatic template keywords / functions (see patches 11-12)
>> - displaying correctly in the log (see patch 7)
>> - automatic tab completion (see patch 9)
>> - automatic support for color (see patch 7)
>>
>> Now, all an extension would have to do is (actual test code I used):
>>
>>     repo.label("foo", "f1", repo['8a6a86c9a5b5'].node())
>>     repo.label("foo", "f2", repo['8a6a86c9a5b5'].node())
>>     repo.label("bar", "b1", repo['8a6a86c9a5b5'].node())
>>     repo.label("bar", "b2", repo['8a6a86c9a5b5'].node())
>>
>> And they would get all the nice coloring, tab completion, and templating
>> without having to add that themselves (though, you could certainly add
>> more fancy things).
>>
>> For example, imagine that the bugzilla extension could add all ticket
>> numbers to known commits:
>>
>>     repo.label("tickets", "issue1234", repo[foo].node())
>>
>> And in the command line:
>>
>>     $ hg up issue<tab>
>> issue1234 etc.
>>
>> Anyway, those are just some ideas.
>
> This is very cool. In fact this past couple of weeks I have been
> working on a small extension of may own that I am (was?) going to call
> "hgmarkers" that was meant to let you add arbitrary "markers" (I also
> considered calling them "labels") to revisions. I was using a
> "ini-like" file to store those markers, but your solution could be
> cleaner.

Thanks! Each plugin would have to store its own file of labels / markers
since this dictionary does not persist across invocations of hg.

> One important feature of this extension of mine is that a single
> marker can be applied to multiple revisions (actually you can even
> associate a revset to a marker). Would this be possible to do using
> this repo.label command? That is, could I do:
>
>      repo.label("foo", "f1", repo['8a6a86c9a5b5'].node())
>      repo.label("foo", "f1", repo['1d875217f959'].node())
>
> And have both revisions labelled foo/f1?

Currently, no, but let's save this discussion for after we decide on a
name and get some basic functionality first.
Pierre-Yves David - Aug. 21, 2014, 7:30 p.m.
On 08/21/2014 11:27 AM, Sean Farley wrote:
>
> Pierre-Yves David writes:
>
>> On 08/18/2014 02:18 PM, Sean Farley wrote:
>>> # HG changeset patch
>>> # User Sean Farley <sean.michael.farley@gmail.com>
>>> # Date 1408394323 18000
>>> #      Mon Aug 18 15:38:43 2014 -0500
>>> # Node ID fe9b72aa7e160e690813cfe4242b013fb147937e
>>> # Parent  e1ab9da20be237323a1340efa16b58b03525596f
>>> templater: add a method to list labels in a namespace
>>
>> I'm not sure about what this new function does. And the lack fo
>> documentation does not helps.
>>
>> It also lack tests (as, I just realised, this whole series)
>
> After we decide on a name, I'll add the tests and more
> documentation. This patch adds the ability to do:

I you can change the name in the code, you can change the name in the 
tests ;-) please add some tests quickly.

Patch

diff --git a/mercurial/templater.py b/mercurial/templater.py
--- a/mercurial/templater.py
+++ b/mercurial/templater.py
@@ -357,10 +357,23 @@  def color(context, mapping, args):
         raise error.ParseError(_("color expects two arguments"))
 
     # ignore args[0] (the color string) since this is supposed to be a a no-op
     yield _evalifliteral(args[1], context, mapping)
 
+def labels(context, mapping, args):
+    if len(args) != 1:
+        # i18n: "label" is a keyword
+        raise error.ParseError(_("labels expects one argument"))
+
+    ctx = mapping['ctx']
+    repo = ctx._repo
+    namespace = args[0][1]
+    l = sorted(l[0] for l in repo.nodelabels(ctx.node())
+               if l[1] == namespace)
+
+    return templatekw.showlist('label', l, **mapping)
+
 def revset(context, mapping, args):
     """usage: revset(query[, formatargs...])
     """
     if not len(args) > 0:
         # i18n: "revset" is a keyword
@@ -517,10 +530,11 @@  funcs = {
     "if": if_,
     "ifcontains": ifcontains,
     "ifeq": ifeq,
     "join": join,
     "label": color, # backwards compatibility before 3.1
+    "labels": labels,
     "pad": pad,
     "revset": revset,
     "rstdoc": rstdoc,
     "shortest": shortest,
     "startswith": startswith,