This is convenient for new template keyword, which doesn't need to support
the legacy list hack (provided by _showlist()), but still wants to have
a string representation.
The goal is to fix "{hybrid_obj|json}" output.
A _hybrid object must act as a list or a dict as well as a generator of
legacy template strings. Before, _hybrid.__iter__() was assigned for legacy
template, which conflicted with list.__iter__() API.
This patch drops _hybrid.__iter__() and makes stringify/flatten functions
unwrap a generator instead.
My initial expectation was that the list would be empty, and therefore
detectable with {if()}. The map for {latesttag()} is populated with real values
in this case (except {tag}), so it probably doesn't make any sense to change
this to an empty list.
This was originally written for JSON templating where we would have to be
careful to not add extra comma, but seems generally useful.
Inner loop started by % operator has its own counter.
Since extras may contain blob, the default template escapes its values:
'extra': '{key}={value|stringescape}'
join() should follow the output style of the default template.
These templates are used when rendering inner lists of some template keywords,
so it makes sense to define them in templatekw. This allows us to reuse them
to create a templateformatter knowing changectx.
The result of diffstatdata should not depend on having noprefix set or not, as
was reported in issue 4755. Forcing noprefix to false on call makes sure the
parser receives the diff in the correct format and returns the proper result.
Another way to fix this would have been to change the regular expressions in
path.diffstatdata(), but that would have introduced many unecessary special
cases.
The "troubles" template keyword returns a list of evolution troubles.
It is EXPERIMENTAL, as anything else related to changeset evolution.
Test it in test-obsolete.t which has troubled changesets.
Now that all the functionality has been moved to manifestlog/manifestrevlog/etc,
we can finally change all the uses of repo.manifest to use the new versions. A
future diff will then delete repo.manifest.
One additional change in this commit is to change repo.manifestlog to be a
@storecache property instead of @property. This is required by some uses of
repo.manifest require that it be settable (contrib/perf.py and the static http
server). We can't do this in a prior change because we can't use @storecache on
this until repo.manifest is no longer used anywhere.
We've fixed several bugs caused by the misuse of the default joinfmt. Make
it more explicit to prevent future bugs.
dict.values()[0] is replaced by dict[element] as showlist() knows what the
key is.
Since the default joinfmt() can't process a dict of multiple keywords, we
need a dedicated joinfmt for showparents().
Unlike revset(), parents are formatted as '{rev}:{node|formatnode}' by default.
We copy the default formatting just like showextras() and showfilecopies() do.
It's been broken since eef3c19484ca, which made makemap() return a dict of
multiple keywords. Because the default joinfmt() randomly picks one item
from a dict, we have to make revset() select d[name] explicitly.
Using decorator can localize changes for adding (or removing) a
template keyword function in source code.
This patch also removes leading ":KEYWORD:" part in help document of
each keywords, because using templatekeyword makes it useless.
For similarity to decorator introduced by subsequent patches, this
patch uses 'templatekeyword' instead of 'keyword' as a decorator name,
even though the former is a little redundant in 'templatekw.py'.
file name reason
=================== ================= ==================================
templatekw.py templatekeyword for similarity to others
templatefilters.py templatefilter 'filter' hides Python built-in one
templaters.py templatefunc 'func' is too generic
_templateregistrarbase is defined as a super class of templatekeyword,
for ease of adding template common features between "keyword",
"filter" and "function".
This patch also adds loadkeyword() to templatekw, because this
combination helps to figure out how they cooperate with each other.
Listing up loadkeyword() in dispatch.extraloaders causes implicit
loading template keyword functions at loading (3rd party) extension.
This change requires that "templatekeyword" attribute of (3rd party)
extension is registrar.templatekeyword or so.
This is the same semantics as revset() introduced at eef3c19484ca. Before
this patch, {parents} provided nothing useful in new-style template. For
example, '{parents % "{parent}"}' generated cryptic string like
"rev12345node0123abcdef...".
This patch drops {parent} variable since it was useless. We can get a revision
number by '{parents % "{rev}"}'.
Because templater.revset() returns a list of strings, repo["-1"] was mapped to
the tipmost revision. Ideally, we should make revset() return a list of integer
revisions, but it turned out not simple. If revset() is a list of integers,
"{ifcontains(rev, revset(), ...)}" would fail because "ifcontains" casts "rev"
to a string.
So this patch just converts a string back to an integer revision.
This provides a general-purpose interface to all custom namespaces.
The {namespaces} keyword honors the definition order of namespaces as they
are kept by sortdict.
In templater, a callable symbol exists for lazy evaluation, which should have
f(**mapping) signature. On the other hand, _hybrid.__call__(), which was
introduced by 4e182fb53989, generates mapping for each element.
This patch renames _hybrid.__call__() to _hybrid.itermaps() so that a _hybrid
object can be a value of a mapping dict.
{namespaces % "{namespace}: {names % "{name }"}\n"}
~~~~~
a _hybrid object
This mitigates the minor perf regression introduced by the previous patch.
% hg log -G -R mozilla-central -l10000 --time > /dev/null
(original) real 2.200 secs
(previous) real 2.590 secs
(this) real 2.280 secs
This provides a default node symbol. Tests will be added later.
"showparents" variable is renamed to "wpnodes" to avoid confusion with the
existing showparents() function.
The keywords {changes}, {distance} and {tag} will be available on a future
template method that will allow pattern matching against tag names. For
consistency, these should be available on the existing {latesttag} keyword as
well.
I debated whether or not to add {tag} instead of just continuing with the
existing {latesttag}. But it seems clearer not to have the same name for two
distinct things (a list in the LHS of %, and an individual tag value on the
right).
The value of latesttags[0] is the date of commit for the cset to which the tag
is applied (i.e. not the date the tag was applied), and therefore isn't made
visible because it doesn't seem interesting. It appears that this is merely an
internal implementation detail for sorting csets in a stable manner when there
are different branches.
This will allow the latest class of tag to be found, such as a release candidate
or final build, instead of just the absolute latest. It will be exposed in a
future patch.
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.
It isn't cool, but we can peek at ui flag via repo.ui. So, it is possible
to implement showparents() in templatekw, and therefore we can eliminate the
dockeywords hack.
Because revset() function generates a list of revisions, it seems sensible
to switch the ctx as well where a list expression will be evaluated. I think
"{revset(...) % "..."}" expression wasn't considered well when it was
introduced at 45e0e191755f.
wdirrev/wdirnode identifiers are still experimental, but {node} is mapped to
wdirnode. So {rev} should do the same for consistency.
I'm not sure if templatekw can import scmutil. If not, we should move intrev()
to node module.
This will prevent crash by "hg log -r 'wdir()' -Tdefault". We could use the
pseudo ff... hash introduced by 187c3ec3d83f, but it isn't proven idea yet.
For now, I want to make "hg log" just works in order to test 'wdir()' revset.
Note that unlike its name, "{manifest}" is not a list of files in that
revision, but a pair of (manifestrev, manifestnode).
This maintains the previous behavior of expanding {latesttag} to a string
containing all of the tags, joined by ':'. But now it also allows list type
operations.
I'm unsure if the plural handling is correct (i.e. it seems like it is usually
"{foos % '{foo}'}"), but I guess we are stuck with this because the singular
form previously existed.
Archive is putting a value with the same name in the metadata file, to count all
of the changes not covered by the latest tag, instead of just along the longest
path. It seems that this would be useful to have on the command line as well.
It might be nice for the name to start with 'latesttag' so that it is grouped
with the other tag keywords, but I can't think of a better name.
The initial version of this counted a clean wdir() and '.' as the same value,
and a dirty wdir() as the same value after it is committed. Yuya objected on
the grounds of consistency [1]. Since revsets can be used to conditionally
select a dirty wdir() or '.' when clean, I can build the version string I need
and will defer to him on this.
[1] https://www.selenic.com/pipermail/mercurial-devel/2015-June/071588.html
This will be used in the next patch.
It also points out that the documentation for '{latesttag}' is not quite
accurate, since it says "most recent global tag" (singular). I assume it is too
radical of a change to convert it to a list of strings. At least ':' is
currently a reserved character in tag names.
Before this patch, template keywords `{file_mods}`, `{file_adds}` and
`{file_dels}` use values gotten by `repo.status(ctx.p1().node(),
ctx.node())`.
But this doesn't work as expected if `ctx` is `memctx` or
`workingcommitctx`. Typical case of templating with these contexts is
customization of the text shown in the commit message editor by
`[committemplate]` configuration.
In this case, `ctx.node()` returns None and it causes comparison
between `ctx.p1()` and `workingctx`. `workingctx` lists up all changed
files in the working directory even at selective committing.
BTW, `{files}` uses `ctx.files()` and it works as expected.
To compare target context and its parent exactly, this patch passes
`ctx.p1()` and `ctx` without `node()`-nize. This avoids unexpected
comparison with `workingctx`.
This patch uses a little redundant template configurations in
`test-commit.t`, but they are needed to avoid regression around
problems fixed by 17e2fda16f58 and 2b999bc2d89a: accessing on `ctx`
may break `ctx._status` field.