Historically, the Network UPS Tools project release and interim iterations code base versions were identified by three or four numeric components, roughly following the Semantic Versioning (SEMVER) traditions, later codified as a formal standard at semver.org:
configure.ac
file an AC_INIT
macro, which
further generates variables like PACKAGE_VERSION
, PACKAGE_URL
and others
used (substituted) in the actual code base, often via nut_version.h
file.
MAJOR.MINOR.PATCH
triplet, which
was not strictly following the standard in that while the "major" part
did reflect architectural/design changes, and "minor" part reflected some
significant development milestones or API changes, the "patch" part did
not correspond to post-release fixes but reflected iterative development,
of which releases were the better-reviewed snapshots. Such a triplet was
only spelled in AC_INIT
for the commit tagged as that release.
MINOR
component meant development
code trees, and even values meant the stable tree. This approach was
skipped (or effectively abandoned, as over a decade passed) with the
move to Git branches for development — as numerous NUT v2.7.x based
releases were produced, and development continued into NUT v2.8.x.
AC_INIT
macro argument like
MAJOR.MINOR.PATCH.1
to provide a fourth component — which is
logically "greater than" MAJOR.MINOR.PATCH
for comparisons, so that
the developed version can formally be installed over a preceding
release (e.g. from custom testing packages).
This configuration with a single development version (.1
) was not very
helpful for the faster pace of iterations, especially as the Git workflow
and pull requests were adopted as the way of iterating the NUT development.
This did not really help identify the build being tested by CI or reported
by a community member, nor quickly determine if one custom build is "newer"
than another (e.g. can be a recommended upgrade from the previously installed
snapshot to check if some bug was fixed).
Some experiments were done adding the git describe
output to version
banners reported by programs. These provide the number of commits since
the most-recent known git tag, as well as the git hash of the NUT sources
involved. This made the builds better identifiable, but did not help
compare the feature branches and the main trunk of development: any code
committed after a release has its own count of commits since that tag,
this one number does not really suffice.
Since NUT v2.8.3, the definition which goes into AC_INIT
and further into
the code was extended in a manner similar to what git describe
produces,
but with added numbers after the common triplet of semantically versioned
numbers: X.Y.Z(.T(.B(-C+gHASH)))
Standard semver (used in releases):
Historically NUT did not diligently follow the standard semver triplet, primarily because a snapshot of trunk is tested and released, and work moves on with the PATCH part (rarely MINOR one) incremented; no actual patches are released to some sustaining track of an older release lineage. There were large re-designs that got MAJOR up to 2, though.
X
: MAJOR - incompatible API changes
Y
: MINOR - major new features and/or API evolution
Z
: PATCH - bug fixes (and new features like added drivers)
Extended semver (for snapshots of trunk):
Extended semver (for features branched off trunk):
The optional suffix (only for commits which are not git tags themselves)
is provided by git describe
:
g
character) of the described commit
The numeric part of NUT SEMVER definition mostly follows https://semver.org/ except that for development iterations the base version may have up to five dot-separated numeric components (SEMVER triplet for base release, and additional data described above). Unlike standard semver provisions for "pre-release versions" (separated by a minus sign after the triplet), which are "less than" that release for comparisons, the fourth and fifth components (if present) are "greater than" that release and any preceding development iterations made after it.
Helper script tools/gitlog2version.sh
is used to determine the project
version from packager-provided override files (or equivalents provided by
make dist
in a snapshot/release tarball), git metadata from the current
workspace, or built-in fallback defaults.
Occasionally there may be tagged pre-releases, which follow the standard
semver markup, like v2.8.0-rc3
(in git), however they would be converted
to NUT SEMVER here (as a number of commits since previous release) by default.
The script can be controlled by environment variables, including some sourced
from configuration files. It identifies a number of data items, and reports
the one specified by NUT_VERSION_QUERY
on stdout
.
It does not currently have a query to report "everything" in a manner
that can be processed by eval
in calling shell scripts (or Makefile
rule
implementations).
Table 1. Environment variables that can be used for external configuration
Variable | Description | Example |
| Top source directory | `/home/abuild/nut` |
| Top build directory (defaults to | `/home/abuild/.builds/linux/nut` |
| Set | `2.8.3` |
| Set | `2.8.3` |
| Usually sourced from either
‘${abs_top_builddir}/VERSION_DEFAULT` (if present)
or | `2.8.2.2379.2-2381+g1faa9945d` |
| If not provided by caller, or sourced files,
or defaulted with | `true` |
| Default website URL, extended for historic sub-sites for a release | `https://www.networkupstools.org/` |
| Git branch name to use for calculation of
current codebase distance from main development (as known
in local workspace index); by default, the newest branch named
like | `origin/master` |
| If | `false` |
| If | `false` |
Table 2. Intermediate variables in Git workspace processing
Variable | Description | Example (development and release) |
| Originates from | `v2.8.2-2381+g1faa9945d` |
| Nearest (annotated by default) tag preceding the | `v2.8.2` |
| The | `e9a48c9afeb4e06c758a3f4215977445c0f64780` |
| Commit count since the tag and hash of the | `-2381+g1faa9945d` |
| Full 5-component version, note we strip leading | `2.8.2.2379.2` |
| Full 5-component version | `2.8.2.2379.2-2381+g1faa9945d` |
|
|
|
|
|
|
| Exactly three leading numeric components.
Either | `2.8.0` |
Table 3. Intermediate variables in default (non-git — tarball or forced) processing
Variable | Description | Example (development and release) |
| Processed from |
|
| Grows from | `....` |
| Constructed from | `2.8.2.0.0` |
| Decreases from | `..` |
| Constructed from | `2.8.0` |
| Full 5-component version, | `2.8.2.2379.2` |
|
| `2.8.2.1` |
| Empty (no known common commits with no trunk) | `""` |
| Exactly three leading numeric components.
Either | `2.8.0` |
| Constructed as | `v2.8.0` |
The majority of identified values can be reported for debugging to stderr
,
currently as a single line (wrapped for readability in the sample below):
:; ./tools/gitlog2version.sh SEMVER=2.8.2; TRUNK='master'; BASE='e9a48c9afeb4e06c758a3f4215977445c0f64780'; DESC='v2.8.2-2381+g1faa9945d' => TAG='v2.8.2' + SUFFIX='-2381+g1faa9945d' => VER5='2.8.2.2379.2' => VER50='2.8.2.2379.2' => DESC50='2.8.2.2379.2-2381+g1faa9945d'
Table 4. Values reported via NUT_VERSION_QUERY
| Description | Example (development and release) |
| Full 5-component version (concatenated with |
|
| 3-to-5 non-zero component version (concatenated with |
|
| Full 5-component version |
|
| 3-to-5 non-zero component version |
|
| Exactly three leading numeric components | `2.8.2` |
|
|
|
| GIT: Nearest (annotated by default) tag preceding the | `v2.8.2` |
| GIT: Branch name used for calculation of current codebase distance from main development. DEFAULT: empty. | `master` |
| GIT: Commit count since the tag and hash of the |
|
| GIT: Newest common commit of development | `e9a48c9afeb4e06c758a3f4215977445c0f64780` |
| Clarify the project website URL — particularly historically frozen snapshots made for releases |
|
| Used in | `NUT_VERSION_DEFAULT='2.8.2.2379.2-2381+g1faa9945d'` |
default | Report | `v2.8.2-2381-g1faa9945d` |
Table 5. Values reported via NUT_VERSION_QUERY
Variable | Description | Example (development and release) |
| Argument to |
|
| Argument to |
|
| Derived from |
|
| Determined by | `2.8.2.695.1-696+g0e00f0777` |
| Determined by | `2.8.2` |
| Determined by | `2.8.2.695.1'` |
| Determined by | `true` or `false` |
| String determined by | `"release"` or `"development iteration"` |
Table 6. Values encoded via include/nut_version.h
, generated by include/Makefile.am
Variable | Description | Example (development and release) |
| Determined by default | `2.8.2.695.1` |
| Determined by | `2.8.2` |
| Determined by |
|
NUT_VERSION_MACRO
is used in common/common.c
and further made known
to all code base as a static string UPS_VERSION
linked via libcommon*.la
internal libraries.
Method describe_NUT_VERSION_once()
prepares the string which combines the
NUT_VERSION_MACRO
with comments that it is either a release
or a
(development iteration after $NUT_VERSION_SEMVER_MACRO)
, based on
the value of NUT_VERSION_IS_RELEASE
.
It is used from a number of other methods, such as print_banner_once()
,
nut_report_config_flags()
, and so ends up in version reports of programs
via their help()
/usage()
methods.
* Method suggest_doc_links()
prepares a uniform bit of text for driver and
tool programs to report in their help()
/usage()
methods, to refer to
their manual page under the NUT_WEBSITE_BASE
.
PACKAGE_VERSION
,
PACKAGE_VERSION
and NUT_WEBSITE_BASE
as asciidoc
attributes
when rendering HTML/PDF/man document formats.
NUT_WEBSITE_BASE
is also substituted instead of literal
https://www.networkupstools.org/*
which follows a home page:
prefix
(so that the pages rendered for a release refer to the historic website).
Service manifests include references to documentation for the tools they wrap,
including published pages under the NUT_WEBSITE_BASE
for the development or
historic variants of the NUT website.