Lektor type to deduce page modification time from git
Author: Jeff Dairiki
View all tags.
This Lektor plugin implements a new datetime-like type,
gittimestamp, which gets it's default value from git timestamps.
This can be used to implement auto-updating
fields in Lektor datamodels.
gittimestamp type behaves just like the built-in
type, except that if the field is left blank in
default value will be deduced from git timestamps for the file (or
possibly the file’s filesystem mtime.)
If an explicit value for the field is not found, the git log for the
source file (typically
contents.lr) is searched using
git log --follow --remove-empty -- <source_filename>, and the author
timestamp of all matching commits are considered. Additionally, if
the source file is dirty with respect to git’s HEAD, or if the file is
not checked into the git tree, the file’s mtime is prepended to that
list of timestamps. That list of timestamps is filtered based on the
skip_first_commit options (see below); then,
finally, a timestamp is selected from those that remain based on the
setting of the
gittimestamp type supports the following options.
This can be set to a string, which is interpreted as a regular
expression. Any git commits whose commit message matches this pattern
are ignored when computing a default timestamp value for the field.
(The matching is performed using
If this boolean option is set, the first commit in the git log for the
source file will be ignored. This is useful for implementing a
last_mod field which has a defined value only if the source file has
actually been modified since the initial commit.
This option determines which timestamp is selected from the git log (and/or the file mtime). This can be set to one of four values:
last: If the source file is dirty (with respect to the git HEAD
tree), the mtime of the file is used. Otherwise, the timestamp of
the last (nominally the most recent) non-ignored git commit is
used. This is the default strategy.
first: The timestamp of the first (nominally the earliest) commit
latest: The latest timestamp is used. Normally this produces the same
last, however due to rebasing, cherry-picking, etc. the git timestamps
may not be monotonically increasing, in which case this option causes the
greatest (most recent) timestamp remaining after any filtering to be selected.
earliest: The earliest timestamp is used. Normally this produces the same
first, but if the timestamps in the git log are not monotonic,
this will select the minimum of all the timestamps remaining after any filtering.
Here is a simple example excerpt from a datamodel file:
<...> [fields.last_mod] label = Time last modified type = gittimestamp
On a page using the above datamodel, so long as the
is left blank in the
contents.lr file, the page modification time
will be deduced from timestamp of the most recent git commit which
contents.lr. (Or if that file is dirty, the value of
last_mod will be taken from the file’s filesystem mtime.)
Here is a more complicated example which demonstrates the use of all the options.
<...> [fields.pub_date] label = Time first published type = gittimestamp strategy = first [fields.last_mod] label = Time last modified type = gittimestamp ignore_commits = \[nochange\] skip_first_commit = true
This will get the default value of the
pub_date field from the
timestamp of the first (earliest) git commit for the source file.
The default value for
last_mod will, as in the previous example, be taken from the
most recent commit for the file, except that:
[nochange]will be ignored
pub_date) is ignored
If there has only been one commit of the source file,
last_mod will not have
a default value. (It will evaluate to a jinja2 Undefined instance.)
Lektor <= 3.2
A common use case for timestamps is for sorting records.
E.g. in a blog one generally wants to display posts in reverse
chronological order by post date. This generally won't work using
gittimestamp timestamps under any currently released version of Lektor.
gittimestamp type is implemented using a field
descriptor. (This is required in order to defer computation of the
field value until after the record for the page is available.) In
lektor<=3.2, field descriptors are supported for most usages, the
one glaring exception being when sorting records.
This was fixed in Lektor PR
#789 which was merged to
the master branch on February 6, 2021.
Unfortunately, the last released version of Lektor (as of August 12,
2021) is version 3.2, released August 20, 2020. For now, you'll have
to install Lektor from git if you want to be able to sort records by
Jeff Dairiki email@example.com
No code changes.
Add warning to README about
lektor > 3.2 (not yet released) being
required in order to be able to sort records by
No code changes.
Update development status classifier to "stable".
Add functional tests.
Fixed attrocious typo which prevented the use of anything other than the
strategy=last for picking timestamps.