Lektor type to deduce page modification time from git
Project description
Lektor-Git-Timestamp
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 pub_date
and last_mod
fields in Lektor datamodels.
Description
The gittimestamp
type behaves just like the built-in datetime
type, except that if the field is left blank in contents.lr
a
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
ignore_commits
and skip_first_commit
options (see below); then,
finally, a timestamp is selected from those that remain based on the
setting of the strategy
option.
Field Options
The gittimestamp
type supports the following options.
ignore_commits
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 re.search
.)
skip_first_commit
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.
strategy
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 is used. -
latest
: The latest timestamp is used. Normally this produces the same result atlast
, 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 result atfirst
, but if the timestamps in the git log are not monotonic, this will select the minimum of all the timestamps remaining after any filtering.
Global Configuration
The following global configuration options are supported.
These values are specified by way of the plugins' configuration file:
configs/git-timestamp.ini
under the project site directory.
By default, the --follow
option is passed to git log
when
computing timestamps. This behavior may be adjusted on a global basis by way of the plugins' configuration file (configs/git-timestamp.ini
under the project site directory) via the following settings:
follow_renames
This is a boolean setting that specifies whether the
--follow
option should be passed to git log
when
querying git for timestamps. This options causes git
to attempt to
follow file renames.
Currently, the follow_renames
is not supported when Lektor
Alternatives are enabled.
If unspecified, follow_renames
defaults to false.
Changed in version 1.0.0b3: The default value for
follow_renames
was changed from true to false.
Note Since we currently run
git log
on a per-record basis, when--follow
is specified, copied files may be detected as “renamed”. This may not be ideal.
follow_rename_threshold
Set the similarity index threshold (passed to git log
via its
-M
option) used when detecting renames. This should be
specified as a (floating point) number between 0 and 100,
inclusive. Setting follow_rename_threshold = 100
will limit
detection to exact renames only. The default value is 50.
Examples
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 last_mod
field
is left blank in the contents.lr
file, the page modification time
will be deduced from timestamp of the most recent git commit which
affected that 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:
- any commits whose commit message include the tag
[nochange]
will be ignored - the first commit (the one whose timestamp is used for
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.)
Warning: On sorting by gittimestamp
in Lektor < 3.3
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 with version of Lektor before 3.3.
The 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.3
, 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, but didn't make it into a release until Lektor 3.3, released on December 13 2021.
Author
Jeff Dairiki dairiki@dairiki.org
Changelog
Release 1.0.0 (2024-02-06)
No code changes from 1.0.0b3
Release 1.0.0b3 (2024-01-23)
Breaking Changes
- Drop support for python 3.8.
- The default value for the
follow_renames
global config setting has changed from true to false.
Bugs Fixed
- Fix to work when alternatives are enabled. Note that in this case
the
follow_renames
global option is not supported.
Testing
- Test under python 3.12.
Code Style
- Style: Use ruff for style linting and formatting. This replaces
our usage of
black
,reorder-python-imports
, andflake8
.
Release 1.0.0b2 (2023-06-15)
- Added type annotations.
- Convert packaging to PDM.
Code Style
- Style: Run black and reorder-python-imports on code. Configure pre-commit to keep all up-to-date.
Tests
- Disuse the deprecated module
pkg_resources
.
Buglets
- Do not strip trailing whitespace from
git log
output. (This was erroneously removing trailing newlines from the final commit message.)
Release 1.0.0b1 (2023-04-11)
- Drop support for python 2.7 and 3.6. (#2)
Testing
-
Test under python 3.10 and 3.11. (#2)
-
Test that
lektor.db.Record.get_sort_key
works with descriptor-valued fields. (This requireslektor>=3.3
.)
Release 0.1.0.post1 (2021-08-12)
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 gittimestamp
fields.
Release 0.1 (2021-02-05)
No code changes.
Update development status classifier to "stable".
Add functional tests.
Release 0.1a2 (2021-02-03)
Bugs Fixed
Fixed attrocious typo which prevented the use of anything other than the
default strategy=last
for picking timestamps.
Release 0.1a1 (2020-06-16)
Initial release.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file lektor_git_timestamp-1.0.0.tar.gz
.
File metadata
- Download URL: lektor_git_timestamp-1.0.0.tar.gz
- Upload date:
- Size: 19.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: pdm/2.12.3 CPython/3.10.12
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 366a3b06c43ea643749a37cdc433f631de77806290f5a3a13517da1b20a111ef |
|
MD5 | e2d8513e6e70e04fd3b3220a82b9ea1a |
|
BLAKE2b-256 | 344de5856a3b6ea138815cba3ad7e32c29ce2281081de7af7223b26a9c3cc652 |
File details
Details for the file lektor_git_timestamp-1.0.0-py3-none-any.whl
.
File metadata
- Download URL: lektor_git_timestamp-1.0.0-py3-none-any.whl
- Upload date:
- Size: 9.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: pdm/2.12.3 CPython/3.10.12
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | af04e0fcbd4e31b340a40703602dacc16d8ff6bcb850b844d618fc2ada95a311 |
|
MD5 | 1faef6d6da8b9cf2b850796a9550497a |
|
BLAKE2b-256 | 028cac028b27e7b844977c69d52ba765e4b05b4ff5dd6d507da1f17593778d42 |