Package: lektor-git-timestamp
Lektor-Git-TimestampThis 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-updatingpub_dateandlast_modfields in Lektor datamodels.DescriptionThegittimestamptype behaves just like the built-indatetimetype, except that if the field is left blank incontents.lra
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 (typicallycontents.lr) is searched usinggit 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 theignore_commitsandskip_first_commitoptions (see below); then,
finally, a timestamp is selected from those that remain based on the
setting of thestrategyoption.Field OptionsThegittimestamptype supports the following options.ignore_commitsThis 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 usingre.search.)skip_first_commitIf this boolean option is set, the first commit in the git log for the
source file will be ignored.  This is useful for implementing alast_modfield which has a defined value only if the source file has
actually been modified since the initial commit.strategyThis 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 ConfigurationThe following global configuration options are supported.
These values are specified by way of the plugins'configuration file:configs/git-timestamp.iniunder the project site directory.By default, the--followoption is passed togit logwhen
computing timestamps.  This behavior may be adjusted on a global basis by way of the plugins'configuration file(configs/git-timestamp.iniunder the project site directory) via the following settings:follow_renamesThis is a boolean setting that specifies whether the--followoption should be passed togit logwhen
querying git for timestamps.  This options causesgitto attempt to
follow file renames.Currently, thefollow_renamesis not supported whenLektor
Alternativesare enabled.If unspecified,follow_renamesdefaults tofalse.Changedin version 1.0.0b3: The default value forfollow_renameswas changed fromtruetofalse.NoteSince we currently rungit logon a per-record basis, when--followis specified,copiedfiles may be detected as “renamed”. This may not be ideal.follow_rename_thresholdSet thesimilarity index threshold(passed togit logvia its-Moption) used when detecting renames. This should be
specified as a (floating point) number between 0 and 100,
inclusive. Settingfollow_rename_threshold = 100will limit
detection to exact renames only. The default value is 50.ExamplesHere is a simple example excerpt from a datamodel file:<...>[fields.last_mod]label=Time last modifiedtype=gittimestampOn a page using the above datamodel, so long as thelast_modfield
is left blank in thecontents.lrfile, the page modification time
will be deduced from timestamp of the most recent git commit which
affected thatcontents.lr.  (Or if that file is dirty, the value oflast_modwill 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 publishedtype=gittimestampstrategy=first[fields.last_mod]label=Time last modifiedtype=gittimestampignore_commits=\[nochange\]skip_first_commit=trueThis will get the default value of thepub_datefield from the
timestamp of the first (earliest) git commit for the source file.The default value forlast_modwill, 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 ignoredthe first commit (the one whose timestamp is used forpub_date) is ignoredIf there has only been one commit of the source file,last_modwill not have
a default value.  (It will evaluate to a jinja2 Undefined instance.)Warning: On sorting bygittimestampinLektor < 3.3A 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 usinggittimestamptimestamps with version of Lektor before 3.3.Thegittimestamptype is implemented using afield
descriptor. (This is required in order to defer computation of the
field value until after the record for the page is available.) Inlektor<3.3, field descriptors are supported for most usages, theone glaring exceptionbeing when sorting records.This was fixed in Lektor PR#789which 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.AuthorJeff Dairikidairiki@dairiki.orgChangelogRelease 1.0.0 (2024-02-06)No code changes from 1.0.0b3Release 1.0.0b3 (2024-01-23)Breaking ChangesDrop support for python 3.8.The default value for thefollow_renamesglobal config setting has
changed fromtruetofalse.Bugs FixedFix to work whenalternativesare enabled. Note that in this case
thefollow_renamesglobal option is not supported.TestingTest under python 3.12.Code StyleStyle: Userufffor style linting and formatting. This replaces
our usage ofblack,reorder-python-imports, andflake8.Release 1.0.0b2 (2023-06-15)Added type annotations.Convert packaging to PDM.Code StyleStyle: Runblackandreorder-python-importson code. Configurepre-committo keep all up-to-date.TestsDisuse the deprecated modulepkg_resources.BugletsDo not strip trailing whitespace fromgit logoutput. (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)TestingTest under python 3.10 and 3.11. (#2)Test thatlektor.db.Record.get_sort_keyworks with
descriptor-valued fields. (This requireslektor>=3.3.)Release 0.1.0.post1 (2021-08-12)No code changes.Add warning to README aboutlektor > 3.2(not yet released) being
required in order to be able to sort records bygittimestampfields.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 FixedFixed attrocious typo which prevented the use of anything other than the
defaultstrategy=lastfor picking timestamps.Release 0.1a1 (2020-06-16)Initial release.