Patchwork [V2] lfs: add the '{lfsattrs}' template keyword to '{lfs_files}'

login
register
mail settings
Submitter Matt Harbison
Date Jan. 19, 2018, 5:05 a.m.
Message ID <fccf09e44f5124abf18a.1516338342@Envy>
Download mbox | patch
Permalink /patch/26942/
State Accepted
Headers show

Comments

Matt Harbison - Jan. 19, 2018, 5:05 a.m.
# HG changeset patch
# User Matt Harbison <matt_harbison@yahoo.com>
# Date 1515967224 18000
#      Sun Jan 14 17:00:24 2018 -0500
# Node ID fccf09e44f5124abf18ae898fab553ea6d91e951
# Parent  45b678bf3a787085d56fad5bee494e0c160aa120
lfs: add the '{lfsattrs}' template keyword to '{lfs_files}'

This provides access to the metadata dictionary contained within the tracked
pointer file.  The OID is probably the most important attribute, and has its own
keyword.  But we might as well have this for completeness.

I liked {pointer} better, but couldn't make it work with the singular/plural
forms.
Yuya Nishihara - Jan. 19, 2018, 12:21 p.m.
On Fri, 19 Jan 2018 00:05:42 -0500, Matt Harbison wrote:
> # HG changeset patch
> # User Matt Harbison <matt_harbison@yahoo.com>
> # Date 1515967224 18000
> #      Sun Jan 14 17:00:24 2018 -0500
> # Node ID fccf09e44f5124abf18ae898fab553ea6d91e951
> # Parent  45b678bf3a787085d56fad5bee494e0c160aa120
> lfs: add the '{lfsattrs}' template keyword to '{lfs_files}'

Queued updated version, thanks.

> I liked {pointer} better, but couldn't make it work with the singular/plural
> forms.

I think {pointer} is okay here since its singular form is ({key}, {value}).

> @@ -303,6 +304,8 @@
>      # when writing a bundle via "hg bundle" command, upload related LFS blobs
>      wrapfunction(bundle2, 'writenewbundle', wrapper.writenewbundle)
>  
> +    templatekw.defaulttempl['lfsattr'] = '{key}={value}'

This isn't needed. Dropped.

> @@ -311,9 +314,16 @@
>      pointers = wrapper.pointersfromctx(ctx) # {path: pointer}
>      files = sorted(pointers.keys())
>  
> +    def lfsattrs(v):
> +        # In the file spec, version is first and the other keys are sorted.
> +        sortkeyfunc = lambda x: (x[0] != 'version', x)
> +        items = sorted(pointers[v].iteritems(), key=sortkeyfunc)
> +        return util.sortdict(kv for kv in items)

s/kv for kv in//

> diff --git a/tests/test-lfs.t b/tests/test-lfs.t
> --- a/tests/test-lfs.t
> +++ b/tests/test-lfs.t
> @@ -865,6 +865,17 @@
>    oid sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
>    size 29
>    x-is-binary 0
> +  $ hg --cwd convert_lfs log -r 0 -T "{lfs_files % '{lfsattrs % \"{lfsattr}\n\"}'}"

This example just applies defaulttempl['lfsattr']. Inlined '{key}={value}'.
Matt Harbison - Jan. 20, 2018, 6:34 a.m.
On Fri, 19 Jan 2018 07:21:30 -0500, Yuya Nishihara <yuya@tcha.org> wrote:

> On Fri, 19 Jan 2018 00:05:42 -0500, Matt Harbison wrote:
>> # HG changeset patch
>> # User Matt Harbison <matt_harbison@yahoo.com>
>> # Date 1515967224 18000
>> #      Sun Jan 14 17:00:24 2018 -0500
>> # Node ID fccf09e44f5124abf18ae898fab553ea6d91e951
>> # Parent  45b678bf3a787085d56fad5bee494e0c160aa120
>> lfs: add the '{lfsattrs}' template keyword to '{lfs_files}'
>
> Queued updated version, thanks.
>
>> I liked {pointer} better, but couldn't make it work with the  
>> singular/plural
>> forms.
>
> I think {pointer} is okay here since its singular form is ({key},  
> {value}).

OK, I'll rename after the freeze.

>> @@ -303,6 +304,8 @@
>>      # when writing a bundle via "hg bundle" command, upload related  
>> LFS blobs
>>      wrapfunction(bundle2, 'writenewbundle', wrapper.writenewbundle)
>>
>> +    templatekw.defaulttempl['lfsattr'] = '{key}={value}'
>
> This isn't needed. Dropped.

Does that mean the envvar entry isn't needed?  Somehow, the output I was  
getting was all of the keys run together, and that made me think of  
envvar.  (Unfortunately, I didn't commit the code, so I can't go back to  
see what exactly was wrong.)

I wonder if this strategy is wrong in general.  Regular templates have  
{files}, {file_adds}, {file_copies}, {file_copies_switch}, {file_dels},  
{file_mods}, and {files(PATTERN)}.  It would be silly to copy all of  
that.  But filters seem only text oriented.  Could a hypothetical  
{lfs_files()}
filter all of these to lfs only, and tack {pointer} and {oid} on to each  
entry somehow?
Yuya Nishihara - Jan. 20, 2018, 7:38 a.m.
On Sat, 20 Jan 2018 01:34:49 -0500, Matt Harbison wrote:
> On Fri, 19 Jan 2018 07:21:30 -0500, Yuya Nishihara <yuya@tcha.org> wrote:
> 
> > On Fri, 19 Jan 2018 00:05:42 -0500, Matt Harbison wrote:
> >> # HG changeset patch
> >> # User Matt Harbison <matt_harbison@yahoo.com>
> >> # Date 1515967224 18000
> >> #      Sun Jan 14 17:00:24 2018 -0500
> >> # Node ID fccf09e44f5124abf18ae898fab553ea6d91e951
> >> # Parent  45b678bf3a787085d56fad5bee494e0c160aa120
> >> lfs: add the '{lfsattrs}' template keyword to '{lfs_files}'
> >
> > Queued updated version, thanks.
> >
> >> I liked {pointer} better, but couldn't make it work with the  
> >> singular/plural
> >> forms.
> >
> > I think {pointer} is okay here since its singular form is ({key},  
> > {value}).
> 
> OK, I'll rename after the freeze.

I think it's okay to rename that before cutting rc. Can you send a patch?

> >> @@ -303,6 +304,8 @@
> >>      # when writing a bundle via "hg bundle" command, upload related  
> >> LFS blobs
> >>      wrapfunction(bundle2, 'writenewbundle', wrapper.writenewbundle)
> >>
> >> +    templatekw.defaulttempl['lfsattr'] = '{key}={value}'
> >
> > This isn't needed. Dropped.
> 
> Does that mean the envvar entry isn't needed?  Somehow, the output I was  
> getting was all of the keys run together, and that made me think of  
> envvar.  (Unfortunately, I didn't commit the code, so I can't go back to  
> see what exactly was wrong.)

showdict|list() requires defaulttempl entry to support old-style list
templates. hybriddict|list() doesn't.

> I wonder if this strategy is wrong in general.  Regular templates have  
> {files}, {file_adds}, {file_copies}, {file_copies_switch}, {file_dels},  
> {file_mods}, and {files(PATTERN)}.  It would be silly to copy all of  
> that.  But filters seem only text oriented.  Could a hypothetical  
> {lfs_files()}
> filter all of these to lfs only,

A unary template function can acts as a filter.

> and tack {pointer} and {oid} on to each
> entry somehow?

Alternatively, we could add pointer and oid to files entry only when it
is backed by lfs.
Matt Harbison - Jan. 20, 2018, 8:06 a.m.
On Sat, 20 Jan 2018 02:38:11 -0500, Yuya Nishihara <yuya@tcha.org> wrote:

> On Sat, 20 Jan 2018 01:34:49 -0500, Matt Harbison wrote:
>> On Fri, 19 Jan 2018 07:21:30 -0500, Yuya Nishihara <yuya@tcha.org>  
>> wrote:
>>
>> > On Fri, 19 Jan 2018 00:05:42 -0500, Matt Harbison wrote:
>> >> # HG changeset patch
>> >> # User Matt Harbison <matt_harbison@yahoo.com>
>> >> # Date 1515967224 18000
>> >> #      Sun Jan 14 17:00:24 2018 -0500
>> >> # Node ID fccf09e44f5124abf18ae898fab553ea6d91e951
>> >> # Parent  45b678bf3a787085d56fad5bee494e0c160aa120
>> >> lfs: add the '{lfsattrs}' template keyword to '{lfs_files}'
>> >
>> > Queued updated version, thanks.
>> >
>> >> I liked {pointer} better, but couldn't make it work with the
>> >> singular/plural
>> >> forms.
>> >
>> > I think {pointer} is okay here since its singular form is ({key},
>> > {value}).
>>
>> OK, I'll rename after the freeze.
>
> I think it's okay to rename that before cutting rc. Can you send a patch?

Done.

>> >> @@ -303,6 +304,8 @@
>> >>      # when writing a bundle via "hg bundle" command, upload related
>> >> LFS blobs
>> >>      wrapfunction(bundle2, 'writenewbundle', wrapper.writenewbundle)
>> >>
>> >> +    templatekw.defaulttempl['lfsattr'] = '{key}={value}'
>> >
>> > This isn't needed. Dropped.
>>
>> Does that mean the envvar entry isn't needed?  Somehow, the output I was
>> getting was all of the keys run together, and that made me think of
>> envvar.  (Unfortunately, I didn't commit the code, so I can't go back to
>> see what exactly was wrong.)
>
> showdict|list() requires defaulttempl entry to support old-style list
> templates. hybriddict|list() doesn't.
>
>> I wonder if this strategy is wrong in general.  Regular templates have
>> {files}, {file_adds}, {file_copies}, {file_copies_switch}, {file_dels},
>> {file_mods}, and {files(PATTERN)}.  It would be silly to copy all of
>> that.  But filters seem only text oriented.  Could a hypothetical
>> {lfs_files()}
>> filter all of these to lfs only,
>
> A unary template function can acts as a filter.

I saw the comment in there suggesting that, but in practice it looks like  
pretty much everything is text, plus some optional control parameters.   
Minimally, this would need a context too.

>> and tack {pointer} and {oid} on to each
>> entry somehow?
>
> Alternatively, we could add pointer and oid to files entry only when it
> is backed by lfs.

I like this idea better, because then it's always available, not just when  
run through the filter/function.  But short of hard coding it in core,  
what else can be done?  Wrap templatekw._showlist(), look for file related  
name arguments and modify the mapping parameter?  Would a {...|lfs} filter  
be OK in addition to this for readability?
Yuya Nishihara - Jan. 20, 2018, 8:26 a.m.
On Sat, 20 Jan 2018 03:06:59 -0500, Matt Harbison wrote:
> >> and tack {pointer} and {oid} on to each
> >> entry somehow?
> >
> > Alternatively, we could add pointer and oid to files entry only when it
> > is backed by lfs.
> 
> I like this idea better, because then it's always available, not just when  
> run through the filter/function.  But short of hard coding it in core,  
> what else can be done?  Wrap templatekw._showlist(), look for file related  
> name arguments and modify the mapping parameter?  Would a {...|lfs} filter  
> be OK in addition to this for readability?

We'll need a hook point to extend makemap() function of files* keywords.

Maybe we can also add oid and pointer keywords globally and obtain fctx as
ctx[file], but currently we have no way to document these keywords depend
on file contexts.
via Mercurial-devel - Jan. 22, 2018, 5:24 p.m.
On Fri, Jan 19, 2018 at 10:34 PM, Matt Harbison <mharbison72@gmail.com> wrote:
> On Fri, 19 Jan 2018 07:21:30 -0500, Yuya Nishihara <yuya@tcha.org> wrote:
>
>> On Fri, 19 Jan 2018 00:05:42 -0500, Matt Harbison wrote:
>>>
>>> # HG changeset patch
>>> # User Matt Harbison <matt_harbison@yahoo.com>
>>> # Date 1515967224 18000
>>> #      Sun Jan 14 17:00:24 2018 -0500
>>> # Node ID fccf09e44f5124abf18ae898fab553ea6d91e951
>>> # Parent  45b678bf3a787085d56fad5bee494e0c160aa120
>>> lfs: add the '{lfsattrs}' template keyword to '{lfs_files}'
>>
>>
>> Queued updated version, thanks.
>>
>>> I liked {pointer} better, but couldn't make it work with the
>>> singular/plural
>>> forms.
>>
>>
>> I think {pointer} is okay here since its singular form is ({key},
>> {value}).
>
>
> OK, I'll rename after the freeze.

Sorry, I found this discussion only now. I'm a little worried that
{pointer} is too generic. There's no indication that it has anything
to do with lfs, and I suppose it does mean that we can't use {pointer}
for something in core later. If something outside of core would want
to use use it, that's less of a concern, because that other thing
could just include a prefix (e.g. {rflpointer} for something in
remotefilelog). I'm not too worried about it, but I thought I'd
mention it.
Matt Harbison - Jan. 22, 2018, 8:21 p.m.
> On Jan 22, 2018, at 12:24 PM, Martin von Zweigbergk <martinvonz@google.com> wrote:
> 
>> On Fri, Jan 19, 2018 at 10:34 PM, Matt Harbison <mharbison72@gmail.com> wrote:
>>> On Fri, 19 Jan 2018 07:21:30 -0500, Yuya Nishihara <yuya@tcha.org> wrote:
>>> 
>>>> On Fri, 19 Jan 2018 00:05:42 -0500, Matt Harbison wrote:
>>>> 
>>>> # HG changeset patch
>>>> # User Matt Harbison <matt_harbison@yahoo.com>
>>>> # Date 1515967224 18000
>>>> #      Sun Jan 14 17:00:24 2018 -0500
>>>> # Node ID fccf09e44f5124abf18ae898fab553ea6d91e951
>>>> # Parent  45b678bf3a787085d56fad5bee494e0c160aa120
>>>> lfs: add the '{lfsattrs}' template keyword to '{lfs_files}'
>>> 
>>> 
>>> Queued updated version, thanks.
>>> 
>>>> I liked {pointer} better, but couldn't make it work with the
>>>> singular/plural
>>>> forms.
>>> 
>>> 
>>> I think {pointer} is okay here since its singular form is ({key},
>>> {value}).
>> 
>> 
>> OK, I'll rename after the freeze.
> 
> Sorry, I found this discussion only now. I'm a little worried that
> {pointer} is too generic. There's no indication that it has anything
> to do with lfs, and I suppose it does mean that we can't use {pointer}
> for something in core later. If something outside of core would want
> to use use it, that's less of a concern, because that other thing
> could just include a prefix (e.g. {rflpointer} for something in
> remotefilelog). I'm not too worried about it, but I thought I'd
> mention it.

Fair point. The revelation that this could be an attribute of core file templates came late to me.  Do you want to try to slip in a rename to “lfs_pointer” or similar before the -rc tag drops?  It will be several hours before I can do that.
Augie Fackler - Jan. 22, 2018, 9:22 p.m.
On Sat, Jan 20, 2018 at 01:34:49AM -0500, Matt Harbison wrote:
> On Fri, 19 Jan 2018 07:21:30 -0500, Yuya Nishihara <yuya@tcha.org> wrote:
>
> > On Fri, 19 Jan 2018 00:05:42 -0500, Matt Harbison wrote:
> > > # HG changeset patch
> > > # User Matt Harbison <matt_harbison@yahoo.com>
> > > # Date 1515967224 18000
> > > #      Sun Jan 14 17:00:24 2018 -0500
> > > # Node ID fccf09e44f5124abf18ae898fab553ea6d91e951
> > > # Parent  45b678bf3a787085d56fad5bee494e0c160aa120
> > > lfs: add the '{lfsattrs}' template keyword to '{lfs_files}'
> >
> > Queued updated version, thanks.
> >
> > > I liked {pointer} better, but couldn't make it work with the
> > > singular/plural
> > > forms.
> >
> > I think {pointer} is okay here since its singular form is ({key},
> > {value}).
>
> OK, I'll rename after the freeze.

Please feel encouraged to send the patch now, so it's in the release
as the thing we expect to keep long term.

>
> > > @@ -303,6 +304,8 @@
> > >      # when writing a bundle via "hg bundle" command, upload related
> > > LFS blobs
> > >      wrapfunction(bundle2, 'writenewbundle', wrapper.writenewbundle)
> > >
> > > +    templatekw.defaulttempl['lfsattr'] = '{key}={value}'
> >
> > This isn't needed. Dropped.
>
> Does that mean the envvar entry isn't needed?  Somehow, the output I was
> getting was all of the keys run together, and that made me think of envvar.
> (Unfortunately, I didn't commit the code, so I can't go back to see what
> exactly was wrong.)
>
> I wonder if this strategy is wrong in general.  Regular templates have
> {files}, {file_adds}, {file_copies}, {file_copies_switch}, {file_dels},
> {file_mods}, and {files(PATTERN)}.  It would be silly to copy all of that.
> But filters seem only text oriented.  Could a hypothetical {lfs_files()}
> filter all of these to lfs only, and tack {pointer} and {oid} on to each
> entry somehow?
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@mercurial-scm.org
> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Matt Harbison - Jan. 22, 2018, 10:28 p.m.
> On Jan 22, 2018, at 4:22 PM, Augie Fackler <raf@durin42.com> wrote:
> 
>> On Sat, Jan 20, 2018 at 01:34:49AM -0500, Matt Harbison wrote:
>>> On Fri, 19 Jan 2018 07:21:30 -0500, Yuya Nishihara <yuya@tcha.org> wrote:
>>> 
>>>> On Fri, 19 Jan 2018 00:05:42 -0500, Matt Harbison wrote:
>>>> # HG changeset patch
>>>> # User Matt Harbison <matt_harbison@yahoo.com>
>>>> # Date 1515967224 18000
>>>> #      Sun Jan 14 17:00:24 2018 -0500
>>>> # Node ID fccf09e44f5124abf18ae898fab553ea6d91e951
>>>> # Parent  45b678bf3a787085d56fad5bee494e0c160aa120
>>>> lfs: add the '{lfsattrs}' template keyword to '{lfs_files}'
>>> 
>>> Queued updated version, thanks.
>>> 
>>>> I liked {pointer} better, but couldn't make it work with the
>>>> singular/plural
>>>> forms.
>>> 
>>> I think {pointer} is okay here since its singular form is ({key},
>>> {value}).
>> 
>> OK, I'll rename after the freeze.
> 
> Please feel encouraged to send the patch now, so it's in the release
> as the thing we expect to keep long term.

To be clear, it’s only on {lfs_files} right now. The goal is to put it on {files}, and probably drop the former.  So something will need to change next time anyway, as {lfs_files} is currently the only option.

If that’s reasonable, I’ll rename to {lfs_pointer}. (We allow _ there, right?)

>> 
>>>> @@ -303,6 +304,8 @@
>>>>     # when writing a bundle via "hg bundle" command, upload related
>>>> LFS blobs
>>>>     wrapfunction(bundle2, 'writenewbundle', wrapper.writenewbundle)
>>>> 
>>>> +    templatekw.defaulttempl['lfsattr'] = '{key}={value}'
>>> 
>>> This isn't needed. Dropped.
>> 
>> Does that mean the envvar entry isn't needed?  Somehow, the output I was
>> getting was all of the keys run together, and that made me think of envvar.
>> (Unfortunately, I didn't commit the code, so I can't go back to see what
>> exactly was wrong.)
>> 
>> I wonder if this strategy is wrong in general.  Regular templates have
>> {files}, {file_adds}, {file_copies}, {file_copies_switch}, {file_dels},
>> {file_mods}, and {files(PATTERN)}.  It would be silly to copy all of that.
>> But filters seem only text oriented.  Could a hypothetical {lfs_files()}
>> filter all of these to lfs only, and tack {pointer} and {oid} on to each
>> entry somehow?
>> _______________________________________________
>> Mercurial-devel mailing list
>> Mercurial-devel@mercurial-scm.org
>> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
via Mercurial-devel - Jan. 22, 2018, 10:51 p.m.
On Mon, Jan 22, 2018 at 12:21 PM, Matt Harbison <mharbison72@gmail.com>
wrote:

>
> > On Jan 22, 2018, at 12:24 PM, Martin von Zweigbergk <
> martinvonz@google.com> wrote:
> >
> >> On Fri, Jan 19, 2018 at 10:34 PM, Matt Harbison <mharbison72@gmail.com>
> wrote:
> >>> On Fri, 19 Jan 2018 07:21:30 -0500, Yuya Nishihara <yuya@tcha.org>
> wrote:
> >>>
> >>>> On Fri, 19 Jan 2018 00:05:42 -0500, Matt Harbison wrote:
> >>>>
> >>>> # HG changeset patch
> >>>> # User Matt Harbison <matt_harbison@yahoo.com>
> >>>> # Date 1515967224 18000
> >>>> #      Sun Jan 14 17:00:24 2018 -0500
> >>>> # Node ID fccf09e44f5124abf18ae898fab553ea6d91e951
> >>>> # Parent  45b678bf3a787085d56fad5bee494e0c160aa120
> >>>> lfs: add the '{lfsattrs}' template keyword to '{lfs_files}'
> >>>
> >>>
> >>> Queued updated version, thanks.
> >>>
> >>>> I liked {pointer} better, but couldn't make it work with the
> >>>> singular/plural
> >>>> forms.
> >>>
> >>>
> >>> I think {pointer} is okay here since its singular form is ({key},
> >>> {value}).
> >>
> >>
> >> OK, I'll rename after the freeze.
> >
> > Sorry, I found this discussion only now. I'm a little worried that
> > {pointer} is too generic. There's no indication that it has anything
> > to do with lfs, and I suppose it does mean that we can't use {pointer}
> > for something in core later. If something outside of core would want
> > to use use it, that's less of a concern, because that other thing
> > could just include a prefix (e.g. {rflpointer} for something in
> > remotefilelog). I'm not too worried about it, but I thought I'd
> > mention it.
>
> Fair point. The revelation that this could be an attribute of core file
> templates came late to me.  Do you want to try to slip in a rename to
> “lfs_pointer” or similar before the -rc tag drops?  It will be several
> hours before I can do that.
>
>
The other discussion in this thread made me wonder if {pointer} is just
applicable in the {lfsattrs} context (i.e. something like '{lfsattrs %
{pointer}}'). If that's the case, I have no problem with calling it just
{pointer}.
Matt Harbison - Jan. 22, 2018, 11:08 p.m.
> On Jan 22, 2018, at 5:51 PM, Martin von Zweigbergk <martinvonz@google.com> wrote:
> 
> 
> 
>> On Mon, Jan 22, 2018 at 12:21 PM, Matt Harbison <mharbison72@gmail.com> wrote:
>> 
>> > On Jan 22, 2018, at 12:24 PM, Martin von Zweigbergk <martinvonz@google.com> wrote:
>> >
>> >> On Fri, Jan 19, 2018 at 10:34 PM, Matt Harbison <mharbison72@gmail.com> wrote:
>> >>> On Fri, 19 Jan 2018 07:21:30 -0500, Yuya Nishihara <yuya@tcha.org> wrote:
>> >>>
>> >>>> On Fri, 19 Jan 2018 00:05:42 -0500, Matt Harbison wrote:
>> >>>>
>> >>>> # HG changeset patch
>> >>>> # User Matt Harbison <matt_harbison@yahoo.com>
>> >>>> # Date 1515967224 18000
>> >>>> #      Sun Jan 14 17:00:24 2018 -0500
>> >>>> # Node ID fccf09e44f5124abf18ae898fab553ea6d91e951
>> >>>> # Parent  45b678bf3a787085d56fad5bee494e0c160aa120
>> >>>> lfs: add the '{lfsattrs}' template keyword to '{lfs_files}'
>> >>>
>> >>>
>> >>> Queued updated version, thanks.
>> >>>
>> >>>> I liked {pointer} better, but couldn't make it work with the
>> >>>> singular/plural
>> >>>> forms.
>> >>>
>> >>>
>> >>> I think {pointer} is okay here since its singular form is ({key},
>> >>> {value}).
>> >>
>> >>
>> >> OK, I'll rename after the freeze.
>> >
>> > Sorry, I found this discussion only now. I'm a little worried that
>> > {pointer} is too generic. There's no indication that it has anything
>> > to do with lfs, and I suppose it does mean that we can't use {pointer}
>> > for something in core later. If something outside of core would want
>> > to use use it, that's less of a concern, because that other thing
>> > could just include a prefix (e.g. {rflpointer} for something in
>> > remotefilelog). I'm not too worried about it, but I thought I'd
>> > mention it.
>> 
>> Fair point. The revelation that this could be an attribute of core file templates came late to me.  Do you want to try to slip in a rename to “lfs_pointer” or similar before the -rc tag drops?  It will be several hours before I can do that.
>> 
> 
> The other discussion in this thread made me wonder if {pointer} is just applicable in the {lfsattrs} context (i.e. something like '{lfsattrs % {pointer}}'). If that's the case, I have no problem with calling it just {pointer}.

It’s currently meant for {lfs_files % {pointer}}, but Yuya asked that I change the {lfs_file} sub-keyword to {file} for consistency with the core templates.  It seems reasonable that this should be something that could be added to the core templates without renaming too.

I submitted the patch, so at least there’s options now.  I don’t want to be the one delaying the rc.

Patch

diff --git a/hgext/lfs/__init__.py b/hgext/lfs/__init__.py
--- a/hgext/lfs/__init__.py
+++ b/hgext/lfs/__init__.py
@@ -97,6 +97,7 @@ 
     scmutil,
     templatekw,
     upgrade,
+    util,
     vfs as vfsmod,
     wireproto,
 )
@@ -303,6 +304,8 @@ 
     # when writing a bundle via "hg bundle" command, upload related LFS blobs
     wrapfunction(bundle2, 'writenewbundle', wrapper.writenewbundle)
 
+    templatekw.defaulttempl['lfsattr'] = '{key}={value}'
+
 @templatekeyword('lfs_files')
 def lfsfiles(repo, ctx, **args):
     """List of strings. LFS files added or modified by the changeset."""
@@ -311,9 +314,16 @@ 
     pointers = wrapper.pointersfromctx(ctx) # {path: pointer}
     files = sorted(pointers.keys())
 
+    def lfsattrs(v):
+        # In the file spec, version is first and the other keys are sorted.
+        sortkeyfunc = lambda x: (x[0] != 'version', x)
+        items = sorted(pointers[v].iteritems(), key=sortkeyfunc)
+        return util.sortdict(kv for kv in items)
+
     makemap = lambda v: {
         'file': v,
         'oid': pointers[v].oid(),
+        'lfsattrs': templatekw.hybriddict(lfsattrs(v)),
     }
 
     # TODO: make the separator ', '?
diff --git a/tests/test-lfs.t b/tests/test-lfs.t
--- a/tests/test-lfs.t
+++ b/tests/test-lfs.t
@@ -865,6 +865,17 @@ 
   oid sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
   size 29
   x-is-binary 0
+  $ hg --cwd convert_lfs log -r 0 -T "{lfs_files % '{lfsattrs % \"{lfsattr}\n\"}'}"
+  version=https://git-lfs.github.com/spec/v1
+  oid=sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
+  size=29
+  x-is-binary=0
+  $ hg --cwd convert_lfs log -r 0 \
+  >    -T '{lfs_files % "{get(lfsattrs, \"oid\")}\n"}{lfs_files % "{lfsattrs.oid}\n"}'
+  sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
+  sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
+  $ hg --cwd convert_lfs log -r 0 -T '{lfs_files % "{lfsattrs}\n"}'
+  version=https://git-lfs.github.com/spec/v1 oid=sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024 size=29 x-is-binary=0
   $ hg --cwd convert_lfs \
   >     log -r 'all()' -T '{rev}: {lfs_files % "{file}: {oid}\n"}'
   0: a1: 5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024