-
-
Notifications
You must be signed in to change notification settings - Fork 413
Description
Autoconf tricks to allow embedding the git version are explored in autoconf's own build scripts:
- http://git.savannah.gnu.org/gitweb/?p=autoconf.git;a=blob_plain;f=build-aux/git-version-gen;hb=refs/heads/master
- https://stackoverflow.com/questions/22871340/using-a-variable-in-ac-init
- https://www.gnu.org/software/autoconf/manual/autoconf-2.71/html_node/Initializing-configure.html (note that earlier revisions starting with https://www.gnu.org/software/autoconf/manual/autoconf-2.67/html_node/Initializing-configure.html suggested more m4 methods for the tricks)
A practical implementation example (not with git version, but still - with a command) can be seen at https://github.com/exfatprogs/exfatprogs/blob/master/configure.ac#L3-L11 or MidnightCommander/mc@eab8439 with a fully-fledged script.
The idea here might be to determine a release tag (annotated? by pattern?) as opposed to major milestones, release candidates etc. tagged during development), and count the number of commits since then.
A release might be tagged v2.8.0 (disregarding items like v2.8.0-Windows, Windows-v2.8.0-alpha4 or v2.8.1-rc1 which might have happened later, but maybe including patterns like v2.8.0-signed (which should refer to same commit as original v2.8.0 but with a signed tag object) and then the custom build would be configured as AC_INIT([nut], [2.8.0.123]...) for 123 commits after that release.
If this tweak to metadata works, it would be more idiomatic (and welcoming to rolling-release packaging form master branch by CI, for example) than calling all such custom builds formally 2.8.0.1 and detailing the git maturity level in plain comments or help messages which are not easily machine-parsable.
For bonus points, we may want to track the codebase maturity compared to both master and last release, perhaps 2.8.0.123.45 meaning that "master" branch had 123 commits since last release (2.8.0) and then the currently branched-off effort for a PR added 45 commits on top of that newest commit in the PR branch that is also in known master branch history (the branching or last-resync point), or alternately - just say 345 commits tracked in the PR branch overall when also counting since that release, which may be easier to tackle.
Then a build from newer master branch with 130 commits (or of a PR with foundations on that baseline) would win in terms of automated packaging version resolution, etc. despite the longer (and variable) amount of commits in development branches.
By either count, a release (tag, tarball) would then be pedantically (equivalent to) 2.8.1.0 or 2.8.1.0.0; for most packaging systems trailing zeroes may be ignored so 2.8.1 as usual.
UPDATE from Jul 2024: In current configure.ac we track AC_INIT with a fixed version string (e.g. 2.8.2 committed manually when making a release, and 2.8.2.1 persisting for development versions), and separately define NUT_SOURCE_GITREV via shell script parsing of tailored git describe output. This is further stripped into NUT_SOURCE_GITREV_NUMERIC substituted into e.g. PyPI packaging manifest:
:; grep NUT_SOU config.log
NUT_SOURCE_GITREV='2.8.2-3880-g118c427c7'
NUT_SOURCE_GITREV_NUMERIC='2.8.2.3880'
Elaborating on the idea of tracking two version increments on top of a formal release - of trunk (master) since last release and of current code since trunk, so that snapshot package versions are incremental and easy to upgrade:
- As a trick seen from
mcrecipe linked above,--abbrev=0can be used to strip the commit count and current hash, leaving just the nearest git tag name. - Note in
configure.acwe add a lot of arguments to strip non-release tags from consideration. - Code snippet to experiment with:
getver() (TAG="`git describe --match 'v[0-9]*.[0-9]*.[0-9]' --exclude '*-signed' --exclude '*rc*' --exclude '*alpha*' --exclude '*beta*' --exclude '*Windows*' --exclude '*IPM*' --always --abbrev=0`";
echo "${TAG/v}.`git log --oneline "$TAG"..master | wc -l`.`git log --oneline master..HEAD | wc -l`" | sed -e 's/\.0$//' -e 's/\.0$//'; )
- As an example, the
FTYbranch has so far thousands of DMF and other commits that are not part ofmaster-branch history. Even though it is lately regularly merged-into frommaster, there are many commits seen as unique to it (thanks to backports per Upstreaming improvements from 42ity/nut fork #1316 many of these bring no diff's in content, just metadata). So the current state in one PR branch is NUT releasev2.8.2as baseline (the TAG), with currentmasteradding 695 commits on top of that, and the branch having 3200 commits different from master:
nut-DMF$ getver
2.8.2.695.3200
- Same expression for a release, with intentionally stripped one or two dot-zeroes in the end of line:
:; git checkout master
:; getver
2.8.2.695
:; git tag -a v2.8.3 -m test
:; getver
2.8.3
:; git tag -d v2.8.3
- Note that for an existing historic tag this exact query would not be right, as it would not show e.g.
2.8.2but2.8.2.695just because newermasterhistory is knownand reference is hard-coded in the example line. But this example shows that the possibilities are there. Just need to compare history lengths leading to HEAD via branch-off from master (which would be 0 in case of older tag). - TODO: consider https://stackoverflow.com/questions/63623762/git-log-range-but-only-include-one-path-of-commits and https://stackoverflow.com/questions/36433572/how-does-ancestry-path-work-with-git-log =>
git log --ancestry-path a..b
UPDATE2: Looking at "git merge-base" of current HEAD and known master trunk history, as the branch-off point (or just an older tag or other commit present in trunk) yields reasonable results:
getver() (TRUNK=master;
TAG="`git describe --match 'v[0-9]*.[0-9]*.[0-9]' --exclude '*-signed' --exclude '*rc*' --exclude '*alpha*' --exclude '*beta*' --exclude '*Windows*' --exclude '*IPM*' --always --abbrev=0`";
BASE="`git merge-base HEAD $TRUNK`" ;
echo "${TAG/v}.`git log --oneline $TAG..$BASE | wc -l`.`git log --oneline $TRUNK..HEAD | wc -l`" | sed -e 's/\.0$//' -e 's/\.0$//'; )
# PR branch recently synced from trunk
:; git checkout issue-2450 && getver
2.8.2.695.60
# Recent abandoned PR (current NUT release tag as predecessor, fewer trunk commits in between)
:; git checkout issue-1316-str_concat && getver
Switched to a new branch 'issue-1316-str_concat'
2.8.2.338.1
# Older abandoned PR, with one commit (and older NUT release tag as predecessor)
:; git checkout issue-1754-bcmxcp && getver
Switched to a new branch 'issue-1754-bcmxcp'
2.8.1.328.1
# Older commit ON trunk
git checkout master~30 && getver
HEAD is now at c91684f4b Merge pull request #2526 from jimklimov/issue-2523-cleanup
2.8.2.580
# Older tag
:; git checkout v2.8.1 && getver
HEAD is now at 4ba352d8f configure.ac: update AC_INIT for NUT v2.8.1 release
2.8.1
Primary question would rather be how to reconcile any such value derived from git with static offline-only files available in tarballs (return to some version.txt?); perhaps have a default-version file with e.g. 2.8.2.1 as used in AC_INIT now, tracked in SCM (and tarballs by extension) and updated from autogen.sh or configure.ac only if git is usable. Note that building or developing based on code from tarballs without git, and re-generating with autogen.sh along the way, is a valid scenario.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status