[PATCH 2 of 2] templater: introduce latesttag() function to match a pattern (issue4184)

Matt Harbison mharbison72 at gmail.com
Sun Aug 23 10:14:00 CDT 2015


On Sun, 23 Aug 2015 10:33:01 -0400, Yuya Nishihara <yuya at tcha.org> wrote:

> On Sun, 23 Aug 2015 00:50:34 -0400, Matt Harbison wrote:
>> # HG changeset patch
>> # User Matt Harbison <matt_harbison at yahoo.com>
>> # Date 1440300516 14400
>> #      Sat Aug 22 23:28:36 2015 -0400
>> # Node ID b65f8c20a934f9a6d7741dd09af9d895ad36a905
>> # Parent  d315fc51e187c70ee75964f7503b8780f1c95884
>> templater: introduce latesttag() function to match a pattern (issue4184)
>>
>> This allows the latest class of tag to be found, such as a release  
>> candidate or
>> final build, instead of just the absolute latest.
>>
>> It doesn't appear that the existing keyword can be given an optional  
>> argument.
>> There is a keyword, function and filter for 'date', so it doesn't seem  
>> harmful
>> to introduce a new function with the same name as an existing keyword.   
>> Most
>> functions are pretty Mercurial agnostic, but there is {revset()} as  
>> precedent.
>>
>> It's unfortunate that the original 'latesttags' cache can't be used to  
>> determine
>> the proper values, but it isn't fully populated for the entire repo.   
>> For
>> example, the {latesttagdistance} keyword on the Mecurial repo builds  
>> the cache
>> up back to the revision for 1.4.  If the pattern was 're:^0\.\d$', that  
>> wouldn't
>> be in the cache.  Maybe this can be optimized some other way, but for  
>> now, this
>> is the simpliest implementation.
>>
>> With this in place, it is trivial to also implement a method for
>> {latesttagdistance} and {changessincelatesttag}.
>
> Just an idea: instead of new more functions, we might want to do it like
>
>   {latesttag(...) % "{tag}+{distance},{changes}"}

Nice.  I agree in principle that it would be nice not to duplicate the  
code, and the user wouldn't have to duplicate the parameter in the query.   
But I have no idea how to pull that off.  This seems like a more expansive  
form of the {plural % '{singular}'} templatekw._showlist() expansion, that  
supports multiple names, in addition to the existing singular  
{latesttag}?  Would we even need a separate {tag} name for this?

I guess if it is just a list, that handles the fact that there can be  
multiple tags nicely.  I'll see what I can figure out.

>> +def getlatesttags(repo, ctx, cache, pattern=None):
>>      '''return date, distance and name for the latest tag of rev'''
>>
>> -    if 'latesttags' not in cache:
>> +    cachename = 'latesttags'
>> +    if pattern is not None:
>> +        cachename += '-' + pattern
>> +        match = util.stringmatcher(pattern)[2]
>> +    else:
>> +        match = util.always
>> +
>> +    if cachename not in cache:
>>          # Cache mapping from rev to a tuple with tag date, tag
>>          # distance and tag name
>> -        cache['latesttags'] = {-1: (0, 0, ['null'])}
>> -    latesttags = cache['latesttags']
>> +        cache[cachename] = {-1: (0, 0, ['null'])}
>> +    latesttags = cache[cachename]
>>
>>      rev = ctx.rev()
>>      todo = [rev]
>> @@ -139,7 +146,8 @@
>>              continue
>>          ctx = repo[rev]
>>          tags = [t for t in ctx.tags()
>> -                if (repo.tagtype(t) and repo.tagtype(t) != 'local')]
>> +                if (repo.tagtype(t) and repo.tagtype(t) != 'local'
>> +                    and match(t))]
>>          if tags:
>>              latesttags[rev] = ctx.date()[0], 0, [t for t in  
>> sorted(tags)]
>>              continue
>> diff --git a/mercurial/templater.py b/mercurial/templater.py
>> --- a/mercurial/templater.py
>> +++ b/mercurial/templater.py
>> @@ -551,6 +551,22 @@
>>
>>      return minirst.format(text, style=style, keep=['verbose'])
>>
>> +def latesttag(context, mapping, args):
>> +    """:latesttag(pattern): The global tags matching the given pattern  
>> on the
>> +    most recent globally tagged ancestor of this changeset."""
>> +    if len(args) != 1:
>> +        # i18n: "latesttag" is a keyword
>> +        raise error.ParseError(_("latesttag expects one argument"))
>> +
>> +    pattern = stringify(args[0][0](context, mapping, args[0][1]))
>> +
>> +    repo, ctx = mapping['repo'], mapping['ctx']
>> +    cache = mapping['cache']
>> +    latesttags = templatekw.getlatesttags(repo, ctx, cache, pattern)[2]
>> +
>> +    return templatekw.showlist('latesttag', latesttags, separator=':',
>> +                               **mapping)
>> +
>>  def shortest(context, mapping, args):
>
> The series looks good to me.
>
> A nit is that the latesttag should be defined next to the label function.

Oops.  At one point it was 'showlatesttags' until I realized the  
convention was different in this module.


More information about the Mercurial-devel mailing list