From 8a556f9e147070660e682e0773ef31c673a9ea94 Mon Sep 17 00:00:00 2001 From: nmbro Date: Wed, 14 Oct 2026 21:06:38 +0200 Subject: [PATCH 1/5] build: keep full git version out of config.h include/config.h is included by every source file, and carried the full git-derived version (e.g. 2.8.5.1466.13) in PACKAGE_VERSION, PACKAGE_STRING and VERSION macros. It changed with every commit, so ccache direct mode missed for all objects on each new commit or fresh CI checkout. Without -g3, preprocessed mode mostly recovered the hits (no code uses these macros), but with -g3 (e.g. AppVeyor) the preprocessed output keeps all #define lines, so every object was recompiled. Pass the base SEMVER (e.g. 2.8.5) to AC_INIT, so config.h only changes with releases, and set the shell PACKAGE_VERSION/PACKAGE_STRING right after it back to the full VER50 value, so all @PACKAGE_VERSION@ substitutions (Makefiles, *.pc files, packaging recipes, tarball names, configure reports) keep the full version. Use AM_INIT_AUTOMAKE no-define (PACKAGE and VERSION macros are unused) and reset VERSION for distdir. Programs still report the full version via NUT_VERSION_MACRO in include/nut_version.h, consumed by two files. Checked with CCACHE_DEBUG=1 builds across two commits (WSL gcc 13, ubuntu-plucky gcc 14): config.h byte-identical, all objects direct hits except upsclient.o and common-nut_version.o. Also checked a dist tarball build (VERSION_DEFAULT), NUT_VERSION_FORCED, and autoconf 2.69 on CentOS 7 and Ubuntu Trusty. Docs go into the "Repetitive build/test optimizations" chapter of INSTALL.nut.adoc. Follow-up to PR #3754. Co-Authored-By: Claude Opus 5.5 Signed-off-by: nmbro --- INSTALL.nut.adoc | 10 ++++++++++ NEWS.adoc | 6 ++++++ UPGRADING.adoc | 11 +++++++++++ configure.ac | 22 ++++++++++++++++++++-- docs/developers.txt | 9 +++++++++ 5 files changed, 56 insertions(+), 2 deletions(-) diff --git a/INSTALL.nut.adoc b/INSTALL.nut.adoc index b4280d2229..98bdd73d44 100644 --- a/INSTALL.nut.adoc +++ b/INSTALL.nut.adoc @@ -279,6 +279,16 @@ for developers iterating on some features. changed. On many systems it suffices to add e.g. `/usr/lib/ccache` early in `PATH` and populate it with symlinks to e.g. `/usr/bin/ccache` using various compiler program names. + The full Git-derived NUT version, which changes with every commit, is not + stored in the `include/config.h` file (included by all sources) but only + in `include/nut_version.h` (included by a couple of source files), so after + a new commit or in a fresh checkout, only those few objects get recompiled. + If several Git work trees or checkout directories share one cache, set + `CCACHE_BASEDIR` to a common parent directory so that absolute paths in + compiler command lines do not prevent cache hits. +* When you iterate code development, `make NUT_VERSION_H_GENERATED=true` + can skip regeneration of `include/nut_version.h` (at a cost of a less + precise version reported by the built programs). * If you are a developer iterating with debug builds on different branches, `export CI_AUTOGEN_STABLE_VERSION=true` can additionally ensure that the `AC_INIT` in the generated `configure` script would not follow NUT SEMVER diff --git a/NEWS.adoc b/NEWS.adoc index cc2640c4fc..07b795780c 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -962,6 +962,12 @@ https://github.com/networkupstools/nut/milestone/13 with both a current and an old (7.1, as on CentOS 7) version of the `aspell-en` dictionary. Local builds keep the default of `configure --enable-spellcheck=auto`. [PR #3752] + * The `include/config.h` file no longer carries the full Git-derived NUT + version (which changes with every commit), only the base semantic + version, so `ccache` and similar build caches can re-use compiled + objects across commits and fresh CI checkouts. The full version is + still provided by `include/nut_version.h` and in the substituted + `@PACKAGE_VERSION@` values. [PR #3754 follow-up] Release notes for NUT 2.8.5 - what's new since 2.8.4 diff --git a/UPGRADING.adoc b/UPGRADING.adoc index 15fa29dece..049dbc0d3f 100644 --- a/UPGRADING.adoc +++ b/UPGRADING.adoc @@ -33,6 +33,17 @@ Changes from 2.8.5 to 2.8.6 - PLANNED: Keep track of any further API clean-up? +- The `PACKAGE_VERSION` and `PACKAGE_STRING` macros in the generated + `include/config.h` now only carry the base semantic version (e.g. `2.8.5`) + rather than the full Git-derived version (e.g. `2.8.5.1466.13`), and the + `PACKAGE` and `VERSION` macros are no longer defined there, so that build + caches remain valid across commits. The `./configure --version` output + also reports the base semantic version. Code which needs the full version + should use `NUT_VERSION_MACRO` from the generated `include/nut_version.h`. + The `@PACKAGE_VERSION@` and `@VERSION@` values substituted into Makefiles, + `*.pc` files, packaging recipes and tarball names are not changed. + [PR #3754 follow-up] + - The Perl `UPS::Nut` module now decodes NUT quoting and backslash escapes in query/list values and `nutauth.conf`, including include paths. Remove manual decoding of these returned values and pass literal credentials diff --git a/configure.ac b/configure.ac index c5e5e411d9..f64bd4ae32 100644 --- a/configure.ac +++ b/configure.ac @@ -23,12 +23,26 @@ dnl See https://github.com/networkupstools/nut/issues/1949 for details. dnl Oddly, autoconf-2.69 on CentOS 7 both complains that AC INIT argument dnl is not a literal, and does contain expected values in the generated dnl script and include/config.h. A "pure" m4 solution would be quieter. +dnl NOTE: AC_INIT gets the base SEMVER (e.g. "2.8.5"), which does not change +dnl between releases. It ends up in include/config.h as PACKAGE_VERSION and +dnl PACKAGE_STRING macros, and every source file includes config.h, so with +dnl the full git-derived version there every new commit would invalidate all +dnl compiled objects in ccache (direct mode) or similar build caches. The +dnl full version (VER50, e.g. "2.8.5.1466.13") is assigned to the shell +dnl variables right below, so all AC_SUBST'ed @PACKAGE_VERSION@ and friends +dnl (Makefiles, *.pc files, packaging recipes, tarball names) are not changed. +dnl C code should use NUT_VERSION_MACRO from include/nut_version.h which is +dnl generated by make and only consumed by a couple of source files. AC_INIT([nut], - m4_esyscmd_s([NUT_VERSION_QUERY=VER50 "`dirname \"$0\"`/tools/gitlog2version.sh" 2>/dev/null]), + m4_esyscmd_s([NUT_VERSION_QUERY=SEMVER "`dirname \"$0\"`/tools/gitlog2version.sh" 2>/dev/null]), [https://github.com/networkupstools/nut/issues],[nut], m4_esyscmd_s([NUT_VERSION_QUERY=URL "`dirname \"$0\"`/tools/gitlog2version.sh" 2>/dev/null])) dnl See docs/maintainer-guide.txt about releases - updating the version dnl above is a small part of the consistent ritual! +NUT_ACINIT_VERSION="${PACKAGE_VERSION}" +PACKAGE_VERSION='m4_esyscmd_s([NUT_VERSION_QUERY=VER50 "`dirname \"$0\"`/tools/gitlog2version.sh" 2>/dev/null])' +test -n "${PACKAGE_VERSION}" || PACKAGE_VERSION="${NUT_ACINIT_VERSION}" +PACKAGE_STRING="${PACKAGE_NAME} ${PACKAGE_VERSION}" dnl Detect usable grep and egrep as soon as possible, to let called scripts dnl use them. Unfortunately, init must happen before macros that output text, @@ -218,7 +232,11 @@ AC_SUBST([NUT_CONFIG_LDFLAGS]) NUT_STASH_WARNINGS AC_CONFIG_HEADERS([include/config.h]) AC_PREFIX_DEFAULT(/usr/local/ups) -AM_INIT_AUTOMAKE([subdir-objects tar-pax]) +dnl Do not define PACKAGE and VERSION macros in config.h (not used by code); +dnl the VERSION substitution would be the AC_INIT SEMVER, so (re-)set it to +dnl the full version for Makefile purposes (distdir, tarball names...) +AM_INIT_AUTOMAKE([subdir-objects tar-pax no-define]) +VERSION="${PACKAGE_VERSION}" AS_CASE([${target_os}], [*mingw*], [AS_CASE([${CFLAGS-}${CXXFLAGS-}], diff --git a/docs/developers.txt b/docs/developers.txt index 3848c24e42..1bf71f1c90 100644 --- a/docs/developers.txt +++ b/docs/developers.txt @@ -336,6 +336,15 @@ build agent preparation,NUTCI_farm_agents]. See also "Repetitive build/test optimizations" in `INSTALL.nut.adoc` file for suggestions specific to this area. +The full Git-derived NUT version (e.g. `2.8.5.1466.13`) changes with every +commit, so it is kept out of `include/config.h` (included by all sources) +to let `ccache` re-use objects: the `PACKAGE_VERSION` and `PACKAGE_STRING` +macros there only carry the base semantic version (e.g. `2.8.5`). Please +do not use these macros in new C code; the full version is provided by +`NUT_VERSION_MACRO` in the generated `include/nut_version.h` file (exposed +to programs by the `UPS_VERSION` string in common code), and that header +should not be included by more source files than necessary. + Integrated Development Environments (IDEs) and debugging NUT ------------------------------------------------------------ From 9ac68a3a27524b515266513fe5c4c9b703114222 Mon Sep 17 00:00:00 2001 From: nmbro Date: Wed, 14 Oct 2026 21:28:09 +0200 Subject: [PATCH 2/5] ci: drop CI_AUTOGEN_STABLE_VERSION workaround With the full git version kept out of include/config.h, there is no need for ci_build.sh to force a shortened version into autogen.sh to keep ccache hits across pull requests. The workaround was AppVeyor only, still changed whenever master advanced, and also shortened the substituted @PACKAGE_VERSION@ (tarball, *.pc). Restore the plain autogen.sh call and drop the setting from appveyor.yml and the docs. Co-Authored-By: Claude Opus 5.5 Signed-off-by: nmbro --- INSTALL.nut.adoc | 10 +++------- NEWS.adoc | 4 +++- appveyor.yml | 3 --- ci_build.sh | 31 +++++-------------------------- 4 files changed, 11 insertions(+), 37 deletions(-) diff --git a/INSTALL.nut.adoc b/INSTALL.nut.adoc index 98bdd73d44..4614e742a0 100644 --- a/INSTALL.nut.adoc +++ b/INSTALL.nut.adoc @@ -283,19 +283,15 @@ for developers iterating on some features. stored in the `include/config.h` file (included by all sources) but only in `include/nut_version.h` (included by a couple of source files), so after a new commit or in a fresh checkout, only those few objects get recompiled. + This matters especially for debug builds with options like `-g3` which + embed all macro definitions into compiled objects, so `ccache` can not + fall back to its preprocessor mode to find a match for a changed macro. If several Git work trees or checkout directories share one cache, set `CCACHE_BASEDIR` to a common parent directory so that absolute paths in compiler command lines do not prevent cache hits. * When you iterate code development, `make NUT_VERSION_H_GENERATED=true` can skip regeneration of `include/nut_version.h` (at a cost of a less precise version reported by the built programs). -* If you are a developer iterating with debug builds on different branches, - `export CI_AUTOGEN_STABLE_VERSION=true` can additionally ensure that the - `AC_INIT` in the generated `configure` script would not follow NUT SEMVER - but use a shorter and temporally stable version string. This helps on some - systems where enabling debug options embeds all macros into compiled objects, - so an ever-changing `PACKAGE_VERSION` in `config.h` which does follow NUT - SEMVER prevents `ccache` direct mode (because each build is deemed unique). * Using `export DO_USE_NUTCI_CACHE=yes` (and derived environment variables like `DO_USE_AUTOCONF_CACHE` or `DO_USE_NIT_TESTCERT_CACHE`) can be used to speed up re-builds with `ci_build.sh` and re-runs of NUT Integration diff --git a/NEWS.adoc b/NEWS.adoc index 07b795780c..54e592ce21 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -967,7 +967,9 @@ https://github.com/networkupstools/nut/milestone/13 version, so `ccache` and similar build caches can re-use compiled objects across commits and fresh CI checkouts. The full version is still provided by `include/nut_version.h` and in the substituted - `@PACKAGE_VERSION@` values. [PR #3754 follow-up] + `@PACKAGE_VERSION@` values. This makes the `CI_AUTOGEN_STABLE_VERSION` + setting of `ci_build.sh` redundant, so it was removed. + [PR #3754 follow-up] Release notes for NUT 2.8.5 - what's new since 2.8.4 diff --git a/appveyor.yml b/appveyor.yml index 8ae93250fa..74097fdee3 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -35,9 +35,6 @@ environment: # ccache max_size is capped below (see install steps) to leave a margin # for the other entries (pacman packages ~100MB, nut-win-deps, nut-ci): APPVEYOR_CACHE_ENTRY_ZIP_ARGS: -t7z -mx=0 - # Keep config.h stable across PRs, so ccache can reuse -g3 objects - # (see ci_build.sh for details): - CI_AUTOGEN_STABLE_VERSION: true CCACHE_DIR: /home/appveyor/.ccache DO_CLEAN_NUTCI_CACHE: no DO_USE_NUTCI_CACHE: yes diff --git a/ci_build.sh b/ci_build.sh index 7a6e36292e..d666aa6471 100755 --- a/ci_build.sh +++ b/ci_build.sh @@ -1136,32 +1136,11 @@ do_autogen_get_CONFIGURE_SCRIPT() { # older system) we have to remove it when we already have the script. # This matches the use-case of distro-building from release tarballs that # include all needed pre-generated files to rely less on OS facilities. - ( - # Optionally drop the PR-specific last component of the version - # (e.g. 2.8.5.1466.13 => 2.8.5.1466) which AC_INIT puts into - # config.h as PACKAGE_VERSION. The ccache direct mode hashes all - # included headers, so a version change misses for nearly every - # file and defeats ccache across pull requests. Only autogen.sh gets - # this setting, so `make` still generates nut_version.h (and the - # UPS_VERSION reported by programs) from actual Git metadata. - if [ x"${CI_AUTOGEN_STABLE_VERSION-}" = xtrue ] && [ -z "${NUT_VERSION_FORCED-}" ] ; then - _NUT_VERSION_STABLE="`NUT_VERSION_QUERY=VER50 ./tools/gitlog2version.sh 2>/dev/null`" || _NUT_VERSION_STABLE="" - case "${_NUT_VERSION_STABLE}" in - *.*.*.*.*) _NUT_VERSION_STABLE="${_NUT_VERSION_STABLE%.*}" ;; - esac - if [ -n "${_NUT_VERSION_STABLE}" ] ; then - echo "INFO: CI_AUTOGEN_STABLE_VERSION: using NUT_VERSION_FORCED='${_NUT_VERSION_STABLE}' for autogen.sh" >&2 - NUT_VERSION_FORCED="${_NUT_VERSION_STABLE}" - export NUT_VERSION_FORCED - fi - fi - - if [ "$CI_OS_NAME" = "windows" ] ; then - $CI_TIME ./autogen.sh || true - else - $CI_TIME ./autogen.sh ### 2>/dev/null - fi - ) || exit + if [ "$CI_OS_NAME" = "windows" ] ; then + $CI_TIME ./autogen.sh || true + else + $CI_TIME ./autogen.sh ### 2>/dev/null + fi || exit fi # Retain the full path to configure script file From 4878552e1b7bf00696b33b5e881654482a995412 Mon Sep 17 00:00:00 2001 From: nmbro Date: Thu, 15 Oct 2026 00:03:26 +0200 Subject: [PATCH 3/5] build: add SEMVER_ACINIT for AC_INIT version Pass a new SEMVER_ACINIT query of gitlog2version.sh to AC_INIT instead of the bare SEMVER: it is the SEMVER for releases, and by the legacy convention a nominal "SEMVER.1" for any development iteration after that release, so the include/config.h macros still tell releases and development builds apart, but do not change between releases and keep build caches valid. It is built from the triplet, so a 4-component NUT_VERSION_DEFAULT (e.g. 2.8.5.1) does not get a second ".1" suffix. For pre-release tagged commits SEMVER is the upcoming release, so the VER50 triplet is used there (unless NUT_VERSION_FORCED_SEMVER is set). Checked with sh, dash and bash for git and NUT_VERSION_DEFAULT values (release, development, tarball and pre-release ones), and that config.h gets 2.8.5.1 while Makefiles keep the full 2.8.5.1503.2. Spellcheck passes with both current and old aspell-en 7.1. Update the gitlog2version test expectations in tests/nut-driver-enumerator-test.sh for the SEMVER_ACINIT value now included in the debug output, and add test cases for the new query (release, development, 4-component default and release candidate). Suggested in PR #3759 review. Co-Authored-By: Claude Opus 5.5 Signed-off-by: nmbro --- NEWS.adoc | 12 +++--- UPGRADING.adoc | 7 ++-- configure.ac | 10 +++-- docs/developers.txt | 3 +- docs/nut-versioning.adoc | 7 ++++ docs/nut.dict | 3 +- tests/nut-driver-enumerator-test.sh | 61 +++++++++++++++++++++++------ tools/gitlog2version.sh | 22 ++++++++++- 8 files changed, 97 insertions(+), 28 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index 54e592ce21..8491ad61c0 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -964,11 +964,13 @@ https://github.com/networkupstools/nut/milestone/13 `configure --enable-spellcheck=auto`. [PR #3752] * The `include/config.h` file no longer carries the full Git-derived NUT version (which changes with every commit), only the base semantic - version, so `ccache` and similar build caches can re-use compiled - objects across commits and fresh CI checkouts. The full version is - still provided by `include/nut_version.h` and in the substituted - `@PACKAGE_VERSION@` values. This makes the `CI_AUTOGEN_STABLE_VERSION` - setting of `ci_build.sh` redundant, so it was removed. + version (e.g. `2.8.5` for a release, or `2.8.5.1` for any development + iteration after it), so `ccache` and similar build caches can re-use + compiled objects across commits and fresh CI checkouts. The full + version is still provided by `include/nut_version.h` and in the + substituted `@PACKAGE_VERSION@` values. This makes the + `CI_AUTOGEN_STABLE_VERSION` setting of `ci_build.sh` redundant, + so it was removed. [PR #3754 follow-up] diff --git a/UPGRADING.adoc b/UPGRADING.adoc index 049dbc0d3f..b68421c75b 100644 --- a/UPGRADING.adoc +++ b/UPGRADING.adoc @@ -34,11 +34,12 @@ Changes from 2.8.5 to 2.8.6 - PLANNED: Keep track of any further API clean-up? - The `PACKAGE_VERSION` and `PACKAGE_STRING` macros in the generated - `include/config.h` now only carry the base semantic version (e.g. `2.8.5`) - rather than the full Git-derived version (e.g. `2.8.5.1466.13`), and the + `include/config.h` now only carry the base semantic version (e.g. `2.8.5` + for a release, or `2.8.5.1` for any development iteration after it) rather + than the full Git-derived version (e.g. `2.8.5.1466.13`), and the `PACKAGE` and `VERSION` macros are no longer defined there, so that build caches remain valid across commits. The `./configure --version` output - also reports the base semantic version. Code which needs the full version + also reports this shortened version. Code which needs the full version should use `NUT_VERSION_MACRO` from the generated `include/nut_version.h`. The `@PACKAGE_VERSION@` and `@VERSION@` values substituted into Makefiles, `*.pc` files, packaging recipes and tarball names are not changed. diff --git a/configure.ac b/configure.ac index f64bd4ae32..60242b6cb7 100644 --- a/configure.ac +++ b/configure.ac @@ -23,9 +23,11 @@ dnl See https://github.com/networkupstools/nut/issues/1949 for details. dnl Oddly, autoconf-2.69 on CentOS 7 both complains that AC INIT argument dnl is not a literal, and does contain expected values in the generated dnl script and include/config.h. A "pure" m4 solution would be quieter. -dnl NOTE: AC_INIT gets the base SEMVER (e.g. "2.8.5"), which does not change -dnl between releases. It ends up in include/config.h as PACKAGE_VERSION and -dnl PACKAGE_STRING macros, and every source file includes config.h, so with +dnl NOTE: AC_INIT gets the base SEMVER for releases (e.g. "2.8.5"), and a +dnl nominal "SEMVER.1" for any development iteration after it (e.g. "2.8.5.1"), +dnl which does not change between releases. It ends up in include/config.h +dnl as PACKAGE_VERSION and PACKAGE_STRING macros, and every source file +dnl includes config.h, so with dnl the full git-derived version there every new commit would invalidate all dnl compiled objects in ccache (direct mode) or similar build caches. The dnl full version (VER50, e.g. "2.8.5.1466.13") is assigned to the shell @@ -34,7 +36,7 @@ dnl (Makefiles, *.pc files, packaging recipes, tarball names) are not changed. dnl C code should use NUT_VERSION_MACRO from include/nut_version.h which is dnl generated by make and only consumed by a couple of source files. AC_INIT([nut], - m4_esyscmd_s([NUT_VERSION_QUERY=SEMVER "`dirname \"$0\"`/tools/gitlog2version.sh" 2>/dev/null]), + m4_esyscmd_s([NUT_VERSION_QUERY=SEMVER_ACINIT "`dirname \"$0\"`/tools/gitlog2version.sh" 2>/dev/null]), [https://github.com/networkupstools/nut/issues],[nut], m4_esyscmd_s([NUT_VERSION_QUERY=URL "`dirname \"$0\"`/tools/gitlog2version.sh" 2>/dev/null])) dnl See docs/maintainer-guide.txt about releases - updating the version diff --git a/docs/developers.txt b/docs/developers.txt index 1bf71f1c90..0f9d4da082 100644 --- a/docs/developers.txt +++ b/docs/developers.txt @@ -339,7 +339,8 @@ for suggestions specific to this area. The full Git-derived NUT version (e.g. `2.8.5.1466.13`) changes with every commit, so it is kept out of `include/config.h` (included by all sources) to let `ccache` re-use objects: the `PACKAGE_VERSION` and `PACKAGE_STRING` -macros there only carry the base semantic version (e.g. `2.8.5`). Please +macros there only carry the base semantic version (e.g. `2.8.5`, or +`2.8.5.1` for any development iteration after that release). Please do not use these macros in new C code; the full version is provided by `NUT_VERSION_MACRO` in the generated `include/nut_version.h` file (exposed to programs by the `UPS_VERSION` string in common code), and that header diff --git a/docs/nut-versioning.adoc b/docs/nut-versioning.adoc index e632ecd6f6..4d7239e7a3 100644 --- a/docs/nut-versioning.adoc +++ b/docs/nut-versioning.adoc @@ -322,6 +322,13 @@ DESC='v2.8.2-2381+g1faa9945d' * DESC5X with default width (6): `000002.000008.000004.000910.000002-912+g081755da0` |`SEMVER` | Exactly three leading numeric components | * `2.8.2` +|`SEMVER_ACINIT` | `SEMVER` for releases, or a nominal `SEMVER.1` for any + development iteration after that release (for pre-releases, + the triplet of `VER50` is used, unless forced otherwise). + Used for `AC_INIT` (so ends up in `config.h` macros), and + does not change between releases, to benefit build caches. + | * dev: `2.8.2.1` + * rel: `2.8.2` |`IS_RELEASE` | `true` if `SEMVER`==`VER50`, `false` otherwise | * dev: `false` * rel: `true` diff --git a/docs/nut.dict b/docs/nut.dict index 0eec4ef8cb..314a667148 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,9 +1,10 @@ -personal_ws-1.1 en 3893 utf-8 +personal_ws-1.1 en 3894 utf-8 AAC AAS ABI ACFAIL ACFREQ +ACINIT ACK ACM ACPI diff --git a/tests/nut-driver-enumerator-test.sh b/tests/nut-driver-enumerator-test.sh index dbe9a0e83f..8df6dda563 100755 --- a/tests/nut-driver-enumerator-test.sh +++ b/tests/nut-driver-enumerator-test.sh @@ -528,7 +528,7 @@ testcase_gitlog2version() { TRUNK='origin/master' BASE='adfdbe3aba19e157010075c42fba7c3174e9baa7' \ run_testcase_generic callG2V \ "Testing that parsing from a NUT_VERSION_FORCED string for a known git checkout returns same results, for a release candidate" 0 \ -"SEMVER=2.8.4; TRUNK=''; BASE=''; DESC='v2.8.3-786+gadfdbe3ab' => TAG='v2.8.3' + SUFFIX='-786+gadfdbe3ab+v2.8.4+rc3' => VER5='2.8.3.786.0' => DESC5='2.8.3.786.0-786+gadfdbe3ab+v2.8.4+rc3' => VER50='2.8.3.786' => DESC50='2.8.3.786-786+gadfdbe3ab+v2.8.4+rc3' +"SEMVER=2.8.4; SEMVER_ACINIT=2.8.3.1; TRUNK=''; BASE=''; DESC='v2.8.3-786+gadfdbe3ab' => TAG='v2.8.3' + SUFFIX='-786+gadfdbe3ab+v2.8.4+rc3' => VER5='2.8.3.786.0' => DESC5='2.8.3.786.0-786+gadfdbe3ab+v2.8.4+rc3' => VER50='2.8.3.786' => DESC50='2.8.3.786-786+gadfdbe3ab+v2.8.4+rc3' 2.8.3.786-786+gadfdbe3ab+v2.8.4+rc3" # Taken from `git checkout v2.8.4` (emptied TRUNK and BASE): @@ -536,14 +536,14 @@ testcase_gitlog2version() { TRUNK='origin/master' BASE='541c2ecf0b2ec33dadb9f40b16acbe39042bd103' \ run_testcase_generic callG2V \ "Testing that parsing from a NUT_VERSION_FORCED string for a known git checkout returns same results, for a release (tag)" 0 \ -"SEMVER=2.8.4; TRUNK=''; BASE=''; DESC='v2.8.4' => TAG='v2.8.4' + SUFFIX='' => VER5='2.8.4.0.0' => DESC5='2.8.4.0.0' => VER50='2.8.4' => DESC50='2.8.4' +"SEMVER=2.8.4; SEMVER_ACINIT=2.8.4; TRUNK=''; BASE=''; DESC='v2.8.4' => TAG='v2.8.4' + SUFFIX='' => VER5='2.8.4.0.0' => DESC5='2.8.4.0.0' => VER50='2.8.4' => DESC50='2.8.4' 2.8.4" NUT_VERSION_QUERY=DESC5X \ NUT_VERSION_FORCED=3.14.159.2653.59-2712+gdeadbeef+v3.14.160+rc1 \ run_testcase_generic callG2V \ "Complex (forced) NUT version expanded for alphanumeric comparisons, for a release candidate, with extra fields" 0 \ -"SEMVER=3.14.160; TRUNK=''; BASE=''; DESC='v3.14.159-2712+gdeadbeef' => TAG='v3.14.159' + SUFFIX='-2712+gdeadbeef+v3.14.160+rc1' => VER5='3.14.159.2653.59' => DESC5='3.14.159.2653.59-2712+gdeadbeef+v3.14.160+rc1' => VER50='3.14.159.2653.59' => DESC50='3.14.159.2653.59-2712+gdeadbeef+v3.14.160+rc1' +"SEMVER=3.14.160; SEMVER_ACINIT=3.14.159.1; TRUNK=''; BASE=''; DESC='v3.14.159-2712+gdeadbeef' => TAG='v3.14.159' + SUFFIX='-2712+gdeadbeef+v3.14.160+rc1' => VER5='3.14.159.2653.59' => DESC5='3.14.159.2653.59-2712+gdeadbeef+v3.14.160+rc1' => VER50='3.14.159.2653.59' => DESC50='3.14.159.2653.59-2712+gdeadbeef+v3.14.160+rc1' 000003.000014.000159.002653.000059-2712+gdeadbeef+v3.14.160+rc1" NUT_VERSION_QUERY=VER5X \ @@ -551,7 +551,7 @@ testcase_gitlog2version() { NUT_VERSION_EXTRA_WIDTH=9 \ run_testcase_generic callG2V \ "Complex (forced) NUT version expanded for alphanumeric comparisons, for a release candidate, just the numeric part" 0 \ -"SEMVER=3.14.160; TRUNK=''; BASE=''; DESC='v3.14.159-2712+gdeadbeef' => TAG='v3.14.159' + SUFFIX='-2712+gdeadbeef+v3.14.160+rc1' => VER5='3.14.159.2653.59' => DESC5='3.14.159.2653.59-2712+gdeadbeef+v3.14.160+rc1' => VER50='3.14.159.2653.59' => DESC50='3.14.159.2653.59-2712+gdeadbeef+v3.14.160+rc1' +"SEMVER=3.14.160; SEMVER_ACINIT=3.14.159.1; TRUNK=''; BASE=''; DESC='v3.14.159-2712+gdeadbeef' => TAG='v3.14.159' + SUFFIX='-2712+gdeadbeef+v3.14.160+rc1' => VER5='3.14.159.2653.59' => DESC5='3.14.159.2653.59-2712+gdeadbeef+v3.14.160+rc1' => VER50='3.14.159.2653.59' => DESC50='3.14.159.2653.59-2712+gdeadbeef+v3.14.160+rc1' 000000003.000000014.000000159.000002653.000000059" # Reset NUT_VERSION_EXTRA_WIDTH for ksh out there @@ -560,7 +560,7 @@ testcase_gitlog2version() { NUT_VERSION_FORCED=3.14.159.2653.59-2712+gdeadbeef \ run_testcase_generic callG2V \ "Complex (forced) NUT version expanded for alphanumeric comparisons, for a dev iteration, with extra fields" 0 \ -"SEMVER=3.14.159; TRUNK=''; BASE=''; DESC='v3.14.159-2712+gdeadbeef' => TAG='v3.14.159' + SUFFIX='-2712+gdeadbeef' => VER5='3.14.159.2653.59' => DESC5='3.14.159.2653.59-2712+gdeadbeef' => VER50='3.14.159.2653.59' => DESC50='3.14.159.2653.59-2712+gdeadbeef' +"SEMVER=3.14.159; SEMVER_ACINIT=3.14.159.1; TRUNK=''; BASE=''; DESC='v3.14.159-2712+gdeadbeef' => TAG='v3.14.159' + SUFFIX='-2712+gdeadbeef' => VER5='3.14.159.2653.59' => DESC5='3.14.159.2653.59-2712+gdeadbeef' => VER50='3.14.159.2653.59' => DESC50='3.14.159.2653.59-2712+gdeadbeef' 000003.000014.000159.002653.000059-2712+gdeadbeef" NUT_VERSION_QUERY=VER5X \ @@ -568,7 +568,7 @@ testcase_gitlog2version() { NUT_VERSION_EXTRA_WIDTH=8 \ run_testcase_generic callG2V \ "Complex (forced) NUT version expanded for alphanumeric comparisons, for a dev iteration, just the numeric part, wider numbers" 0 \ -"SEMVER=3.14.159; TRUNK=''; BASE=''; DESC='v3.14.159-2712+gdeadbeef' => TAG='v3.14.159' + SUFFIX='-2712+gdeadbeef' => VER5='3.14.159.2653.59' => DESC5='3.14.159.2653.59-2712+gdeadbeef' => VER50='3.14.159.2653.59' => DESC50='3.14.159.2653.59-2712+gdeadbeef' +"SEMVER=3.14.159; SEMVER_ACINIT=3.14.159.1; TRUNK=''; BASE=''; DESC='v3.14.159-2712+gdeadbeef' => TAG='v3.14.159' + SUFFIX='-2712+gdeadbeef' => VER5='3.14.159.2653.59' => DESC5='3.14.159.2653.59-2712+gdeadbeef' => VER50='3.14.159.2653.59' => DESC50='3.14.159.2653.59-2712+gdeadbeef' 00000003.00000014.00000159.00002653.00000059" # Reset NUT_VERSION_EXTRA_WIDTH for ksh out there @@ -577,14 +577,14 @@ testcase_gitlog2version() { NUT_VERSION_FORCED=3.14.159.2653 \ run_testcase_generic callG2V \ "Complex (forced) NUT version expanded for alphanumeric comparisons, for a master merge increment, just the numeric part (requiring at least 5 numeric components)" 0 \ -"SEMVER=3.14.159; TRUNK=''; BASE=''; DESC='v3.14.159' => TAG='v3.14.159' + SUFFIX='' => VER5='3.14.159.2653.0' => DESC5='3.14.159.2653.0' => VER50='3.14.159.2653' => DESC50='3.14.159.2653' +"SEMVER=3.14.159; SEMVER_ACINIT=3.14.159.1; TRUNK=''; BASE=''; DESC='v3.14.159' => TAG='v3.14.159' + SUFFIX='' => VER5='3.14.159.2653.0' => DESC5='3.14.159.2653.0' => VER50='3.14.159.2653' => DESC50='3.14.159.2653' 000003.000014.000159.002653.000000" NUT_VERSION_QUERY=VER50X \ NUT_VERSION_FORCED=3.14.159.2653 \ run_testcase_generic callG2V \ "Complex (forced) NUT version expanded for alphanumeric comparisons, for a master merge increment, just the numeric part (dropping trailing zero numeric components)" 0 \ -"SEMVER=3.14.159; TRUNK=''; BASE=''; DESC='v3.14.159' => TAG='v3.14.159' + SUFFIX='' => VER5='3.14.159.2653.0' => DESC5='3.14.159.2653.0' => VER50='3.14.159.2653' => DESC50='3.14.159.2653' +"SEMVER=3.14.159; SEMVER_ACINIT=3.14.159.1; TRUNK=''; BASE=''; DESC='v3.14.159' => TAG='v3.14.159' + SUFFIX='' => VER5='3.14.159.2653.0' => DESC5='3.14.159.2653.0' => VER50='3.14.159.2653' => DESC50='3.14.159.2653' 000003.000014.000159.002653" # Note that DESC must be either a tag as is, @@ -594,14 +594,14 @@ testcase_gitlog2version() { NUT_VERSION_FORCED=3.14.159+gdeadbeef \ run_testcase_generic callG2V \ "Complex (forced) NUT version expanded for alphanumeric comparisons, with a trailing gHASH but no commit count" 0 \ -"SEMVER=3.14.159; TRUNK=''; BASE=''; DESC='v3.14.159-0+gdeadbeef' => TAG='v3.14.159' + SUFFIX='-0+gdeadbeef' => VER5='3.14.159.0.0' => DESC5='3.14.159.0.0-0+gdeadbeef' => VER50='3.14.159' => DESC50='3.14.159-0+gdeadbeef' +"SEMVER=3.14.159; SEMVER_ACINIT=3.14.159; TRUNK=''; BASE=''; DESC='v3.14.159-0+gdeadbeef' => TAG='v3.14.159' + SUFFIX='-0+gdeadbeef' => VER5='3.14.159.0.0' => DESC5='3.14.159.0.0-0+gdeadbeef' => VER50='3.14.159' => DESC50='3.14.159-0+gdeadbeef' 3.14.159-0+gdeadbeef" # ...auto-account the offset since tag correctly: NUT_VERSION_FORCED=3.14.159.2653+gdeadbeef \ run_testcase_generic callG2V \ "Complex (forced) NUT version expanded for alphanumeric comparisons, with a trailing gHASH but no commit count" 0 \ -"SEMVER=3.14.159; TRUNK=''; BASE=''; DESC='v3.14.159-2653+gdeadbeef' => TAG='v3.14.159' + SUFFIX='-2653+gdeadbeef' => VER5='3.14.159.2653.0' => DESC5='3.14.159.2653.0-2653+gdeadbeef' => VER50='3.14.159.2653' => DESC50='3.14.159.2653-2653+gdeadbeef' +"SEMVER=3.14.159; SEMVER_ACINIT=3.14.159.1; TRUNK=''; BASE=''; DESC='v3.14.159-2653+gdeadbeef' => TAG='v3.14.159' + SUFFIX='-2653+gdeadbeef' => VER5='3.14.159.2653.0' => DESC5='3.14.159.2653.0-2653+gdeadbeef' => VER50='3.14.159.2653' => DESC50='3.14.159.2653-2653+gdeadbeef' 3.14.159.2653-2653+gdeadbeef" # ...auto-account the offset since tag correctly @@ -609,7 +609,7 @@ testcase_gitlog2version() { NUT_VERSION_FORCED=3.14.159.2653.5+gdeadbeef \ run_testcase_generic callG2V \ "Complex (forced) NUT version expanded for alphanumeric comparisons, with a trailing gHASH but no commit count" 0 \ -"SEMVER=3.14.159; TRUNK=''; BASE=''; DESC='v3.14.159-2658+gdeadbeef' => TAG='v3.14.159' + SUFFIX='-2658+gdeadbeef' => VER5='3.14.159.2653.5' => DESC5='3.14.159.2653.5-2658+gdeadbeef' => VER50='3.14.159.2653.5' => DESC50='3.14.159.2653.5-2658+gdeadbeef' +"SEMVER=3.14.159; SEMVER_ACINIT=3.14.159.1; TRUNK=''; BASE=''; DESC='v3.14.159-2658+gdeadbeef' => TAG='v3.14.159' + SUFFIX='-2658+gdeadbeef' => VER5='3.14.159.2653.5' => DESC5='3.14.159.2653.5-2658+gdeadbeef' => VER50='3.14.159.2653.5' => DESC50='3.14.159.2653.5-2658+gdeadbeef' 3.14.159.2653.5-2658+gdeadbeef" NUT_VERSION_QUERY=DESC5X \ @@ -617,7 +617,7 @@ testcase_gitlog2version() { NUT_VERSION_STRIP_LEADING_ZEROES=true \ run_testcase_generic callG2V \ "Complex (forced) NUT version expanded for alphanumeric comparisons, with leading zeroes, also a trailing gHASH but no commit count" 0 \ -"SEMVER=3.14.159; TRUNK=''; BASE=''; DESC='v3.14.159-2658+gdeadbeef' => TAG='v3.14.159' + SUFFIX='-2658+gdeadbeef' => VER5='3.14.159.2653.5' => DESC5='3.14.159.2653.5-2658+gdeadbeef' => VER50='3.14.159.2653.5' => DESC50='3.14.159.2653.5-2658+gdeadbeef' +"SEMVER=3.14.159; SEMVER_ACINIT=3.14.159.1; TRUNK=''; BASE=''; DESC='v3.14.159-2658+gdeadbeef' => TAG='v3.14.159' + SUFFIX='-2658+gdeadbeef' => VER5='3.14.159.2653.5' => DESC5='3.14.159.2653.5-2658+gdeadbeef' => VER50='3.14.159.2653.5' => DESC50='3.14.159.2653.5-2658+gdeadbeef' 000003.000014.000159.002653.000005-2658+gdeadbeef" # Note here SEMVER is taken from the future version that the RC is for @@ -626,8 +626,43 @@ testcase_gitlog2version() { NUT_VERSION_STRIP_LEADING_ZEROES=true \ run_testcase_generic callG2V \ "Complex (forced) NUT version expanded for alphanumeric comparisons, with leading zeroes, also in the commit count and RC suffix" 0 \ -"SEMVER=4.5.6; TRUNK=''; BASE=''; DESC='v3.14.159-002658+gdeadbeef' => TAG='v3.14.159' + SUFFIX='-002658+gdeadbeef+v04.005.0006+rc001' => VER5='3.14.159.2653.5' => DESC5='3.14.159.2653.5-002658+gdeadbeef+v04.005.0006+rc001' => VER50='3.14.159.2653.5' => DESC50='3.14.159.2653.5-002658+gdeadbeef+v04.005.0006+rc001' +"SEMVER=4.5.6; SEMVER_ACINIT=3.14.159.1; TRUNK=''; BASE=''; DESC='v3.14.159-002658+gdeadbeef' => TAG='v3.14.159' + SUFFIX='-002658+gdeadbeef+v04.005.0006+rc001' => VER5='3.14.159.2653.5' => DESC5='3.14.159.2653.5-002658+gdeadbeef+v04.005.0006+rc001' => VER50='3.14.159.2653.5' => DESC50='3.14.159.2653.5-002658+gdeadbeef+v04.005.0006+rc001' 000003.000014.000159.002653.000005-002658+gdeadbeef+v04.005.0006+rc001" + + # SEMVER_ACINIT (for AC_INIT and so config.h) is the SEMVER for + # releases, and a nominal "triplet.1" for development iterations + # Reset NUT_VERSION_STRIP_LEADING_ZEROES for ksh out there + NUT_VERSION_STRIP_LEADING_ZEROES='' \ + NUT_VERSION_QUERY=SEMVER_ACINIT \ + NUT_VERSION_FORCED=2.8.4 \ + run_testcase_generic callG2V \ + "Stable NUT version for AC_INIT, for a release (tag)" 0 \ +"SEMVER=2.8.4; SEMVER_ACINIT=2.8.4; TRUNK=''; BASE=''; DESC='v2.8.4' => TAG='v2.8.4' + SUFFIX='' => VER5='2.8.4.0.0' => DESC5='2.8.4.0.0' => VER50='2.8.4' => DESC50='2.8.4' +2.8.4" + + NUT_VERSION_QUERY=SEMVER_ACINIT \ + NUT_VERSION_FORCED=3.14.159.2653.59-2712+gdeadbeef \ + run_testcase_generic callG2V \ + "Stable NUT version for AC_INIT, for a dev iteration" 0 \ +"SEMVER=3.14.159; SEMVER_ACINIT=3.14.159.1; TRUNK=''; BASE=''; DESC='v3.14.159-2712+gdeadbeef' => TAG='v3.14.159' + SUFFIX='-2712+gdeadbeef' => VER5='3.14.159.2653.59' => DESC5='3.14.159.2653.59-2712+gdeadbeef' => VER50='3.14.159.2653.59' => DESC50='3.14.159.2653.59-2712+gdeadbeef' +3.14.159.1" + + # Like NUT_VERSION_DEFAULT between releases: no second ".1" suffix + NUT_VERSION_QUERY=SEMVER_ACINIT \ + NUT_VERSION_FORCED=2.8.5.1 \ + run_testcase_generic callG2V \ + "Stable NUT version for AC_INIT, for a 4-component default version" 0 \ +"SEMVER=2.8.5; SEMVER_ACINIT=2.8.5.1; TRUNK=''; BASE=''; DESC='v2.8.5' => TAG='v2.8.5' + SUFFIX='' => VER5='2.8.5.1.0' => DESC5='2.8.5.1.0' => VER50='2.8.5.1' => DESC50='2.8.5.1' +2.8.5.1" + + # For a release candidate, SEMVER is the upcoming release, but + # SEMVER_ACINIT is a dev iteration after the preceding release + NUT_VERSION_QUERY=SEMVER_ACINIT \ + NUT_VERSION_FORCED=2.8.3.786-786+gadfdbe3ab+v2.8.4+rc3 \ + run_testcase_generic callG2V \ + "Stable NUT version for AC_INIT, for a release candidate" 0 \ +"SEMVER=2.8.4; SEMVER_ACINIT=2.8.3.1; TRUNK=''; BASE=''; DESC='v2.8.3-786+gadfdbe3ab' => TAG='v2.8.3' + SUFFIX='-786+gadfdbe3ab+v2.8.4+rc3' => VER5='2.8.3.786.0' => DESC5='2.8.3.786.0-786+gadfdbe3ab+v2.8.4+rc3' => VER50='2.8.3.786' => DESC50='2.8.3.786-786+gadfdbe3ab+v2.8.4+rc3' +2.8.3.1" } testcase_semver_compare() { diff --git a/tools/gitlog2version.sh b/tools/gitlog2version.sh index f15acda867..07c12bea0a 100755 --- a/tools/gitlog2version.sh +++ b/tools/gitlog2version.sh @@ -499,9 +499,27 @@ getver_default() { fi } +getver_acinit() { + # Temporally stable version for AC_INIT (ends up in config.h macros): + # exactly SEMVER for releases, and by legacy convention a nominal + # "triplet.1" for any development iteration after that release. + # Note that for pre-release tagged commits SEMVER is the upcoming + # release, while the code is still a development iteration after the + # previous one (unless the caller forced a SEMVER), so take the + # triplet from VER50 in that case. Starting from a triplet ensures + # we do not add a second ".1" to 4-component NUT_VERSION_DEFAULT. + if [ x"${SEMVER}" = x"${VER50}" ] ; then + SEMVER_ACINIT="${SEMVER}" + elif [ -n "${SUFFIX_PRERELEASE}" ] && [ -z "${NUT_VERSION_FORCED_SEMVER-}" ] ; then + SEMVER_ACINIT="`echo \"${VER50}\" | sed -e 's/^\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\)[^0-9].*$/\1/'`.1" + else + SEMVER_ACINIT="${SEMVER}.1" + fi +} + report_debug() { # Debug - echo "SEMVER=${SEMVER}; TRUNK='${NUT_VERSION_GIT_TRUNK-}'; BASE='${BASE}'; DESC='${DESC}' => TAG='${TAG}' + SUFFIX='${SUFFIX}' => VER5='${VER5}' => DESC5='${DESC5}' => VER50='${VER50}' => DESC50='${DESC50}'" >&2 + echo "SEMVER=${SEMVER}; SEMVER_ACINIT=${SEMVER_ACINIT}; TRUNK='${NUT_VERSION_GIT_TRUNK-}'; BASE='${BASE}'; DESC='${DESC}' => TAG='${TAG}' + SUFFIX='${SUFFIX}' => VER5='${VER5}' => DESC5='${DESC5}' => VER50='${VER50}' => DESC50='${DESC50}'" >&2 } report_output() { @@ -515,6 +533,7 @@ report_output() { "VER50") echo "${VER50}" ;; "VER50x"|"VER50X") "${SEMVER_COMPARE}" --expand "${VER50}" ;; "SEMVER") echo "${SEMVER}" ;; + "SEMVER_ACINIT") echo "${SEMVER_ACINIT}" ;; "IS_RELEASE") [ x"${SEMVER}" = x"${VER50}" ] && echo true || echo false ;; "IS_PRERELEASE") [ x"${SUFFIX_PRERELEASE}" != x ] && echo true || echo false ;; "TAG") echo "${TAG}" ;; @@ -639,6 +658,7 @@ if [ x"$DESC" = x ]; then fi fi +getver_acinit report_debug report_output From b056457e360128207a236285e5fb709b4f2a92ff Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 15 Oct 2026 18:29:04 +0200 Subject: [PATCH 4/5] tools/gitlog2version.sh, tests/nut-driver-enumerator-test.sh: handle SEMVER_ACINIT corner case of `X.Y.Z.0(.0...)` [#3759] Signed-off-by: Jim Klimov --- tests/nut-driver-enumerator-test.sh | 11 +++++++++++ tools/gitlog2version.sh | 11 ++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/tests/nut-driver-enumerator-test.sh b/tests/nut-driver-enumerator-test.sh index 8df6dda563..54ebd7bf79 100755 --- a/tests/nut-driver-enumerator-test.sh +++ b/tests/nut-driver-enumerator-test.sh @@ -638,6 +638,17 @@ testcase_gitlog2version() { run_testcase_generic callG2V \ "Stable NUT version for AC_INIT, for a release (tag)" 0 \ "SEMVER=2.8.4; SEMVER_ACINIT=2.8.4; TRUNK=''; BASE=''; DESC='v2.8.4' => TAG='v2.8.4' + SUFFIX='' => VER5='2.8.4.0.0' => DESC5='2.8.4.0.0' => VER50='2.8.4' => DESC50='2.8.4' +2.8.4" + + # NOTE: VER50 retains trailing .0 from the input, but SEMVER_ACINIT + # should not become 2.8.4.1 for what is still a release (zero commits + # after tag) + NUT_VERSION_STRIP_LEADING_ZEROES='' \ + NUT_VERSION_QUERY=SEMVER_ACINIT \ + NUT_VERSION_FORCED=2.8.4.0 \ + run_testcase_generic callG2V \ + "Stable NUT version for AC_INIT, for a release (tag)" 0 \ +"SEMVER=2.8.4; SEMVER_ACINIT=2.8.4; TRUNK=''; BASE=''; DESC='v2.8.4' => TAG='v2.8.4' + SUFFIX='' => VER5='2.8.4.0.0' => DESC5='2.8.4.0.0' => VER50='2.8.4.0' => DESC50='2.8.4.0' 2.8.4" NUT_VERSION_QUERY=SEMVER_ACINIT \ diff --git a/tools/gitlog2version.sh b/tools/gitlog2version.sh index 07c12bea0a..d89c2246a9 100755 --- a/tools/gitlog2version.sh +++ b/tools/gitlog2version.sh @@ -513,7 +513,16 @@ getver_acinit() { elif [ -n "${SUFFIX_PRERELEASE}" ] && [ -z "${NUT_VERSION_FORCED_SEMVER-}" ] ; then SEMVER_ACINIT="`echo \"${VER50}\" | sed -e 's/^\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\)[^0-9].*$/\1/'`.1" else - SEMVER_ACINIT="${SEMVER}.1" + # Check if the version forced from input is like `X.Y.Z.0(.0...)` + # (still a release, zero commits after tag), and do not turn it + # into `X.Y.Z.1` needlessly. + _VER50="`echo \"${VER50}\" | sed -e 's/^\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\)\(\.00*\)*$/\1/'`" + if [ x"${SEMVER}" = x"${_VER50}" ] ; then + SEMVER_ACINIT="${SEMVER}" + else + SEMVER_ACINIT="${SEMVER}.1" + fi + unset _VER50 fi } From 6056077618e45961c09f4110ab4891d4504ab3e7 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 15 Oct 2026 18:32:02 +0200 Subject: [PATCH 5/5] NEWS.adoc: `CI_AUTOGEN_STABLE_VERSION` never appeared in a release so not worth mentioning in these notes [#3759] Signed-off-by: Jim Klimov --- NEWS.adoc | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index 8491ad61c0..5beabe0983 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -968,10 +968,7 @@ https://github.com/networkupstools/nut/milestone/13 iteration after it), so `ccache` and similar build caches can re-use compiled objects across commits and fresh CI checkouts. The full version is still provided by `include/nut_version.h` and in the - substituted `@PACKAGE_VERSION@` values. This makes the - `CI_AUTOGEN_STABLE_VERSION` setting of `ci_build.sh` redundant, - so it was removed. - [PR #3754 follow-up] + substituted `@PACKAGE_VERSION@` values. [PR #3759, follow-up to PR #3754] Release notes for NUT 2.8.5 - what's new since 2.8.4