descriptionGit ChangeLog Smudger Tool
ownermackyle@fastmail.com
last changeTue, 15 Jun 2021 04:52:17 +0000 (14 21:52 -0700)
content tags
add:
readme.pod

NAME

git-changelog-smudge.pl - Smudge a ChangeLog file to include tag contents

SYNOPSIS

git-changelog-smudge.pl [options] <name-of-smudgee>

 Options:
   -h | --help                           detailed instructions
   --smudge                              perform a smudge instead of a cat
   --no-smudge                           perform a cat (default)

 Git Config:
   changelog.smudge                      "true" enables --smudge by default

OPTIONS

--help

Print the full description of git-changelog-smudge.pl's options.

--smudge

Actually perform the ChangeLog smudge operation on the input. See the "CHANGELOG SMUDGING" section below. Without this option the input is simply copied to the output without change. Overrides a previous --no-smudge option.

--no-smudge

Disable any smudge operation and always copy the input to the output. Overrides a previous --smudge option.

GIT CONFIG

changelog.smudge

If the git config option changelog.smudge is set to a "true" boolean value then the default if neither --smudge nor --no-smudge is given is to do a --smudge instead of --no-smudge. If it's set to the special value "bare" then --smudge will only become the default in a bare repository (provided, of course, no explicit --smudge or --no-smudge options are present).

DESCRIPTION

git-changelog-smudge.pl provides a mechanism to translate a simple format "ChangeLog" file into one containing the contents of zero or more Git tag comment bodies.

An attempt is made to make the output Markdown compatible so that it can be formatted very nicely as an HTML document for viewing.

The intent is that this "smudge" filter can be activated when creating an archive (via git archive) to expand the "ChangeLog" at that time so it's included fully-expanded in the resulting archive while being maintained in the working tree and repository in a non-expanded format.

CHANGELOG SMUDGING

The git-changelog-smudge.pl utility should be used as a Git "smudge" filter to replace the contents of a "ChangeLog" file that contains only blank lines, comments and Git tag names with a Markdown-compatible result that expands each of the tag names to their entire, possibly multiline, tag message.

The expansion occurs as a replacement so that final output will be ordered in the same order as the tag names are listed in the original "ChangeLog" document.

Since "git shortlog" output may commonly be included, an attempt is made to detect such usage and insert the needed blank line after each author name and count so that the description line(s) end up being recognized as preformatted text by Markdown. Note that if any 3-backticks-delimiter lines are found at all this automagical blank line insertion will be disabled.

Signature data (if present) gets stripped from the end of the message.

A Markdown-style "H1" line will be added unless the beginning of the tag message already contains one in which case it will have the tagname (or display tag name if present) prefixed to it unless it already contains (case-insensitively) the tag name (display tag name if given).

However, if a display tag name starting with "^" is used it will always become its own separate leading "H1" line.

If a display tag name starting with "~" is used it will entirely replace whatever line would have become the "H1" line.

Syntax

The first line of the file must be a shebang style comment line in this form:

        #!/usr/bin/env git-changelog-smudge.pl <optional> <options>

Or alternatively this form:

        #!/any/path/to/git-changelog-smudge.pl <optional> <options>

Or even this form (which is really just a special case of the previous one):

        #!git-changelog-smudge.pl <optional> <options>

where optional whitespace may also be included immediately following the "!" if desired.

All <optional> <options> will be automatically picked up and appended to the list of command line options when smudging. This means they can override command line options. If unrecognized options are present an error will result. This provides a means to guarantee that archives generated using "git-changelog-smudge.pl" smudging produce identical results even when additional formatting options (if there ever are any) are used. Note that adding an explicit "--no-smudge" option to the shebang line will always prevent smudging from taking place!

Each following line of the input file is either a blank line (zero or more whitespace characters), a comment line (first non-whitespace character is #) or a tag name line.

Tag name lines consist of optional leading whitespace, a valid, case-sensitive, Git tag name optionally followed by a display name followed by optional whitespace and comment (the whitespace is required if a comment is present) like this:

        tagname[ [^|~]display name][ #comment]

Here is an example "ChangeLog" file:

        # ChangeLog for project foo

        # More recent releases
        v2.2.0 ~Version 2.2
        v2.1.0 ~Version 2.1
        v2.0.2 ~Version 2.0.2
        v2.0.1 ~Version 2.0.1
        v2.0.0 ~Version 2.0 # new world order

        # only include last release of each older series
        v1.9.3 # last of the old world
        v1.8.7
        v1.7.3
        v1.6.1
        v1.5.3 ^Broken 1.5.3 -- do not use # yikes!

In this example there are ten tag names that will be expanded. They just all happen to start with "v". Six of them have alternate display names. Two of them have comments on the tag name line and the last one has an exclusive display name (as well as a comment) and the first five have alternate display names. See the above "CHANGELOG SMUDGING" section for processing details.

Here's another valid example "ChangeLog" file:

        123 funny name
        funny-name-tag # yup
            #comments can be here too
            # more comments
        with-#char gotcha

This example contains three tag names, "123", "funny-name-tag" and "with-#char". Yup, "#" is a valid tag name character as far as Git is concerned. The astute reader will have noticed that the third and fourth lines were taken as comment lines rather than tag lines. Currently git-changelog-smudge.pl does not support tag names beginning with "#" as there is no way to "escape" such names from being treated as comment lines. Internal "#" characters in tag names work just fine (as the example demonstrates).

If any invalid or nonexistent tags are detected during "ChangeLog" smudging, an error message will be spit out to STDERR and a non-zero status code will result. Setting the "required" filter option to "true" will cause any Git smudge operations to fail in that case (the error is reported either way).

Testing

To test the output simply feed the "ChangeLog" to git-changelog-smudge.pl on its STDIN with the --smudge option like so:

        git-changelog-smudge.pl --smudge ChangeLog < ChangeLog

(Adjust the filename if the "ChangeLog" is not actually stored in "ChangeLog".)

Git Configuration

Two configuration items are required to use "git-changelog-smudge.pl" as a "smudge" filter:

The filter configuration portion may be added to the repository-local config, the global config or even the system config.

The lines should look something like this:

        [filter "changelog"]
        smudge = git-changelog-smudge.pl %f
        clean = cat
        required

The following Git commands will set up the repository's local config:

        git config filter.changelog.smudge "git-changelog-smudge.pl %f"
        git config filter.changelog.clean cat
        git config filter.changelog.required true

This variation will set up the global config:

        git config --global filter.changelog.smudge "git-changelog-smudge.pl %f"
        git config --global filter.changelog.clean cat
        git config --global filter.changelog.required true

You don't need the repository-local version if you have the global config version (but it's harmless to have both). The global makes sense if the "ChangeLog" filter will be used in multiple repositories, the local config if its use will be limited to one (or just a handful).

Once the "changelog" filter has been defined, the following line (or similar) needs to be added to one of the "gitattributes" files:

        /ChangeLog.md   filter=changelog

See the git help attributes information for more details on attributes file formats. Of note here is that by starting the pattern with "/" the specified file name ("ChangeLog.md" in this case) will only match at the top-level.

Here the extension .md is used to reflect the fact that the smudged output is intended to be Markdown compatible. Since the source file to be "smudged" must always be named exactly as shown (if no wildcards are being used) it must be named exactly "ChangeLog.md" in this case; multiple files can have the "changelog" filter attribute set on them; wildcard patterns can even be used to match multiple files (simply omitting the leading "/" will match the specified filename in any subdirectory as well).

What's important is that the name given with the "filter=" attribute (in this case "changelog") matches exactly (it is case sensitive) the name used in the git config file section. The actual name used does not matter as long as it's the same in both places.

Note that yes, Virginia, there are big bad global attributes!

This fact may not be immediately apparent from the Git attributes documentation, but the following will display the full pathname of the default "global" Git attributes file (which may not actually exist):

        sh -c 'echo "${XDG_CONFIG_HOME:-$HOME/.config}/git/attributes"'

There's also a core.attributesfile setting that may be used to replace the default location of the global attributes file. In other words, if the core.attributesfile value is set, the pathname shown by the above line of shell code will be ignored (unless, of course, core.attributesfile just happens to be set to the same value it outputs).

Since the core.attributesfile value can be set in a local repository configuration file or even using the command line -c core.attributesfile=pathname option, the actual location of the "global" attributes file can vary on a repository-by-repository (or even command-to-command) basis.

The repository-local attributes configuration is available either checked in to the repository as a .gitattributes file or local to a specific copy of the repository in its $GIT_DIR/info/attributes file.

For smudging purposes, it does not matter which "attributes" file location is chosen, but at least one of them must assign the "ChangeLog" filter to at least one file in order to make use of it.

There are pros and cons to each choice of location, but if others are expected to be using the "ChangeLog" smudger on one or more files in the repository it makes sense for the filter assignment to be listed in a .gitattributes file checked in to the repository. If use by others is not a concern then using a global attributes configuration only makes sense if more than one repository will be "smudging" and they will all have their "ChangeLog" files in the same relative location using the same name(s). Otherwise a repository-local attributes configuration ($GIT_DIR/info/attributes) makes the most sense.

Activating the Smudger

The above configuration will not actually smudge anything!

That is intentional because "git-changelog-smudge.pl" only knows how to "smudge," it doesn't know how to "clean" (but it will try to notice if it's already "smudged" and then just copy that to the output in case Git gets carried away and tries to double-smudge something).

As the "git-changelog-smudge.pl" filter's primary purpose is to be used with the "git archive" command, the recommended way to activate the "smudger" (once the required configuration mentioned above has been completed) is like this:

        git -c changelog.smudge=true archive <other> <arguments>

If the "upload-archive" facility has been enabled there's no simple way to enable "git-changelog-smudge.pl" smudging for remote client archive generation without also enabling it for local archive generation.

However, it is possible to automatically enable it for only bare repositories by setting the "changelog.smudge" config variable to "bare" instead of a boolean. If remote clients are always served from "bare" repositories (and with the advent of the "git worktree" command in Git 2.5 that's really no added space burden anymore) that should suffice. Provided, of course, that allowing a remote client to cause "git-changelog-smudge.pl" to run at all is acceptable in the first place.

LICENSE

git-changelog-smudge.pl version 1.0.1
All rights reserved.
License GPLv2: GNU GPL version 2 only.
https://www.gnu.org/licenses/gpl-2.0.html
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

SEE ALSO

Markdown

A suitable formatter for Markdown (along with syntax descriptions etc.) can be found at:

AUTHOR

Kyle J. McKay

shortlog
2021-06-15 Kyle J. McKaygit-changelog-smudge.pl: improve docs and commentsmaster
2019-01-16 Kyle J. McKaygit-changelog-smudge.pl: update links and years
2019-01-16 Kyle J. McKayreadme.pod: add readme formatting link
2017-06-22 Kyle J. McKaygit-changelog-smudge.pl: try to detect git archive...
2017-06-13 Kyle J. McKaygit-changelog-smudge.pl: initial version
heads
2 years ago master