1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460
|
NUT versioning
==============
Historic note
-------------
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 link:https://semver.org/[semver.org]:
* NUT uses the GNU autotools suite for recipe orchestration, and the version
string is specified in the `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.
* NUT releases were identified by a `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.
* Until NUT v2.6.x, the odd values of the `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.
* NUT development versions were specified by the next commit after a
release was published, spelling an `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.
Current NUT SEMVER definition
-----------------------------
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+H(+R))))` or `X.Y.Z(.T(.B(-R)))`
* Standard semver (used in releases):
+
NOTE: 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):
- T: (optional) Commits on trunk since previous release tag
* Extended semver (for features branched off trunk):
- B: (optional) Commits on branch since nearest ancestor which is on trunk
The optional suffix (only for commits which are not git tags themselves)
is provided by `git describe`:
* C: Commits on branch since previous release tag
* H: (Short) Git hash (prefixed by "g" character) of the described commit
The pre-release information (if provided/known) would either follow the
optional suffix detailed above, or it would be the suffix itself:
* R: If this commit has a non-release tag, it can be optionally reported
so we know that a commit some '1234' iterations after release 'N' is
also a release candidate for 'N+1'. Note that any dash in that tag value
will be replaced by a plus, e.g. `2.8.2.2878.1-2879+g882dd4b00+v2.8.3+rc6`
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.
A special case, which can mostly be seen in CI builds, concerns shallow git
checkouts -- when the currently built commit history is "grafted" (perhaps
down to there being only one commit in the whole git index), and we do not
know of any intersections with git tags or development trunk. In this case,
the script may not only fall back to a built-in version following a legacy
`X.Y.Z.1` pattern for non-release builds (like `2.8.3.1`), but would also
append a `-0-g{HASH}` suffix to the long values (`VER5`, `VER50`, `DECS5`,
`DESC50`) yielding e.g. `2.8.3.1.0-0+gb3f21f9` for a build from a shallow
git checkout of commit `b3f21f9` of a code base which otherwise fell back
to `2.8.3.1` hard-coded in its copy of the script (bumped by a maintainer
as part of the release process).
Using gitlog2version.sh
-----------------------
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`.
NOTE: 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).
.Environment variables that can be used for external configuration
[opts="header",cols="1,3,2a"]
|=========================================================================
|Variable | Description | Example
|`abs_top_srcdir` | Top source directory | `/home/abuild/nut`
|`abs_top_builddir` | Top build directory (defaults to `abs_top_srcdir`)
| `/home/abuild/.builds/linux/nut`
|`NUT_VERSION_FORCED` | Set `NUT_VERSION_DEFAULT` (extended NUT SEMVER,
may be just a triplet) to this value and enforce
`NUT_VERSION_PREFER_GIT=false`. Usually sourced
from `${abs_top_srcdir}/VERSION_FORCED` (if present)
| `2.8.2.2379` `2.8.3-rc3`
`2.8.2.2878.3-2881+g45029249f+v2.8.3+rc6`
|`NUT_VERSION_FORCED_SEMVER` | Set `SEMVER` (exactly a triplet) to this value
regardless of `NUT_VERSION_PREFER_GIT` setting. Usually
sourced from `${abs_top_srcdir}/VERSION_FORCED_SEMVER`
(if present)
| `2.8.3`
|`NUT_VERSION_DEFAULT` | Usually sourced from either
`${abs_top_builddir}/VERSION_DEFAULT` (if present)
or `${abs_top_srcdir}/VERSION_DEFAULT` (if present),
in which case the script also defaults
`NUT_VERSION_PREFER_GIT=false` (unless it is already
specified as `true` or `${abs_top_srcdir}/.git` exists).
If no value was provided, a hard-coded value is used
(updated as part of maintainers' release rituals).
| `2.8.2.2379.2-2381+g1faa9945d`
|`NUT_VERSION_PREFER_GIT` | If not provided by caller, or sourced files,
or defaulted with `NUT_VERSION_FORCED` or
`NUT_VERSION_DEFAULT` as described above, as a `false`
value, then becomes `true` if `${abs_top_srcdir}/.git`
exists or `false` otherwise (tarball builds) | `true`
|`NUT_WEBSITE` | Default website URL, extended for historic sub-sites for
a release | `https://www.networkupstools.org/`
|`NUT_VERSION_GIT_TRUNK` | 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 `master` is located (any competition is same or ancestor)
| `origin/master`
|`NUT_VERSION_GIT_ALL_TAGS` | If `true`, consider usual (not "annotated")
tags too | `false`
|`NUT_VERSION_GIT_ALWAYS_DESC` | If `true`, tell git to return just a commit
hash if no tag was matched in index. | `false`
|=========================================================================
.Intermediate variables in Git workspace processing
[opts="header",cols="1,3,2a"]
|=========================================================================
|Variable | Description | Example (development and release)
|`DESC` | Originates from `git describe`, filtered for releases (`vX.Y.Z`)
and ignoring various `rc`, `alpha`, `beta` etc. tags.
This yields the tag name, followed by number of commits added to
current `HEAD` history since that tag, and the current commit hash.
In the resulting string, the git hash is separated by a "plus"
sign (as semver build metadata) rather than the "minus" returned
by the tool.
| `v2.8.2-2381+g1faa9945d`
|`TAG` | Nearest (annotated by default) tag preceding the `HEAD` in history:
the part of `DESC` before the commit count and hash. | `v2.8.2`
|`BASE` | The `git merge-base` of current commit and `NUT_VERSION_GIT_TRUNK`
(see above). How much of the known trunk history is in current HEAD?
This may be "all of it" when we are on that branch or PR made from
its tip, "some of it" if looking at a historic snapshot, or "nothing"
if looking at the tagged commit (it is the merge base for itself and
any of its descendants) | `e9a48c9afeb4e06c758a3f4215977445c0f64780`
|`SUFFIX` | Commit count since the tag and hash of the `HEAD` commit;
empty e.g. when `HEAD` is the tagged commit | `-2381+g1faa9945d`
|`VER5` | Full 5-component version, note we strip leading `v` from the expected
`TAG` value | `2.8.2.2379.2`
|`DESC5` | Full 5-component version `VER5` concatenated with `SUFFIX`
| `2.8.2.2379.2-2381+g1faa9945d`
|`VER50` | `VER5` without trailing `.0` in fifth or fourth component
| * dev: `2.8.2.2379.2`
* trunk: `2.8.2.2379.0` => `2.8.2.2379`
* release: `2.8.2.0.0` => `2.8.2`
|`DESC50` | `VER50` concatenated with `SUFFIX`
| * release: `2.8.2-2381-g1faa9945d`
|`SEMVER` | Exactly three leading numeric components.
Either `NUT_VERSION_FORCED_SEMVER` (if provided by caller or
configuration files), or derived from `VER5` (removing fourth
and fifth numbers) | `2.8.0`
|=========================================================================
.Intermediate variables in default (non-git -- tarball or forced) processing
[opts="header",cols="1,3,2a"]
|=========================================================================
|Variable | Description | Example (development and release)
|`NUT_VERSION_DEFAULT_DOTS` | Processed from `NUT_VERSION_DEFAULT` (see above)
to count just the dot characters
| * dev: `....`
* trunk: `...`
* release: `..`
|`NUT_VERSION_DEFAULT5_DOTS` | Grows from `NUT_VERSION_DEFAULT_DOTS`,
used to construct `NUT_VERSION_DEFAULT5`
| `....`
|`NUT_VERSION_DEFAULT5` | Constructed from `NUT_VERSION_DEFAULT`, adding `.0`
numeric components as needed, to have *at least 5* of them
| `2.8.2.0.0`
|`NUT_VERSION_DEFAULT3_DOTS` | Decreases from `NUT_VERSION_DEFAULT_DOTS`,
used to construct `NUT_VERSION_DEFAULT3` | `..`
|`NUT_VERSION_DEFAULT3` | Constructed from `NUT_VERSION_DEFAULT`, adding `.0`
numeric components as needed or dropping extras, to have
*exactly 3* of them
| `2.8.0`
|`SUFFIX` | Empty, unless `NUT_VERSION_DEFAULT` had a suffix
for pre-release information roughly matching the
`-(rc|alpha|beta)[0-9]*` regular expression
| `""` `-rc6`
|`VER5` | Full 5-component version, `NUT_VERSION_DEFAULT5`
| `2.8.2.2379.2`
|`DESC5` | Constructed as `${VER5}${SUFFIX}`
| `2.8.2.2379.2` `2.8.3.0.0-rc6`
|`VER50` | `NUT_VERSION_DEFAULT` as provided by caller or
defaulted, may be with or without trailing `.0` in fifth or
fourth components
| `2.8.2.1`
|`DESC50` | Constructed as `${VER50}${SUFFIX}`
| `2.8.2.1` `2.8.3-rc6`
|`BASE` | Empty (no known common commits with no trunk) | `""`
|`SEMVER` | Exactly three leading numeric components.
Either `NUT_VERSION_FORCED_SEMVER` (if provided by caller or
configuration files), or `NUT_VERSION_DEFAULT3` (see above)
| `2.8.0`
|`TAG` | Constructed as `v${NUT_VERSION_DEFAULT3}${SUFFIX}`
| `v2.8.0` `v2.8.3-rc6`
|=========================================================================
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'
----
.Values reported via `NUT_VERSION_QUERY`
[opts="header",cols="1,3,2a"]
|=========================================================================
|`NUT_VERSION_QUERY` | Description | Example (development and release)
|`DESC5` | Full 5-component version (concatenated with `SUFFIX` for git)
| * dev: `2.8.2.2379.2-2381+g1faa9945d`
* snapshot tarball: `2.8.2.2379.2`
|`DESC50` | 3-to-5 non-zero component version (concatenated with `SUFFIX`
for git)
| * dev: `2.8.2.2381-2381+g1faa9945d`
* snapshot tarball: `2.8.2.1`
|`VER5` | Full 5-component version
| * dev: `2.8.2.2379.2`
* snapshot tarball: `2.8.2.1.0`
|`VER50` | 3-to-5 non-zero component version
| * dev: `2.8.2.2379.2`
* release tarball: `2.8.0`
|`SEMVER` | Exactly three leading numeric components | `2.8.2`
|`IS_RELEASE` | `true` if `SEMVER`==`VER50`, `false` otherwise
| * dev: `false`
* rel: `true`
|`IS_PRERELEASE` | `true` if `SUFFIX_PRERELEASE` is not empty, `false` otherwise
| * dev: `false`
* rel/RC: `true`
|`TAG` | GIT: Nearest (annotated by default) tag preceding the `HEAD` in history.
DEFAULT: Constructed from `SEMVER`
| `v2.8.2`
|`TAG_PRERELEASE` | GIT: if the `HEAD` itself has a tag matching
the `-(rc|alpha|beta)[0-9]*` regular expression.
DEFAULT: Constructed from `NUT_VERSION_DEFAULT3`
and `SUFFIX_PRERELEASE`.
Empty for not-pre-releases.
| `v2.8.2-rc3` `""`
|`TRUNK` | GIT: Branch name used for calculation of current codebase
distance from main development.
DEFAULT: empty.
| `master`
|`SUFFIX` | GIT: Commit count since the tag and hash of the `HEAD` commit
DEFAULT: empty for non-prerelease `NUT_VERSION_DEFAULT`
values, or either value of `SUFFIX_PRERELEASE` with a
leading dash for `NUT_VERSION_DEFAULT` values without
git offset info (e.g. `2.8.3.5-rc6` => `-rc6`), or the
whole tail with git and pre-release tag info.
| * dev: `-2381+g1faa9945d`
* RC git: `-2381+g1faa9945d+v2.8.3+rc6`
* RC default: `-rc6`
|`SUFFIX_PRERELEASE` | GIT: Constructed from `TAG_PRERELEASE` replacing any
dash with a plus character.
DEFAULT: empty unless `NUT_VERSION_DEFAULT` has a
suffix matching the `-(rc|alpha|beta)[0-9]*`
regular expression, or git info followed by
the pre-release tag.
NOTE: No leading dash in this value (unlike `SUFFIX`).
| * RC git: `v2.8.3+rc6`
* RC default: `rc6`
|`BASE` | GIT: Newest common commit of development `TRUNK` and the `HEAD`
commit (their `git merge-base`).
DEFAULT: empty.
| `e9a48c9afeb4e06c758a3f4215977445c0f64780`
|`URL` | Clarify the project website URL -- particularly historically
frozen snapshots made for releases
| * dev: `https://www.networkupstools.org/` (default development)
* rel: `https://www.networkupstools.org/historic/v2.8.2/index.html`
|`UPDATE_FILE` | Used in `autogen.sh` and top-level `Makefile.am` to
update the `VERSION_DEFAULT` file that goes into "dist"
tarballs; prints its contents
| `NUT_VERSION_DEFAULT='2.8.2.2379.2-2381+g1faa9945d'`
|`UPDATE_FILE_GIT_RELEASE` | Used in maintainer rituals (requires git) to
update the `VERSION_FORCED` and `VERSION_FORCED_SEMVER`
files that go into "dist" tarballs; prints their contents
| `NUT_VERSION_FORCED='2.8.2.2878.3-2881+g45029249f+v2.8.3+rc6'`
`NUT_VERSION_FORCED_SEMVER='2.8.3'`
|default | Report `DESC50` | `v2.8.2-2381-g1faa9945d`
|=========================================================================
Variables propagated by configure.ac
------------------------------------
.Values reported via `NUT_VERSION_QUERY`
[opts="header",cols="1,3,2a"]
|=========================================================================
|Variable | Description | Example (development and release)
|`PACKAGE_VERSION` | Argument to `AC_INIT` determined by
`NUT_VERSION_QUERY=VER50 gitlog2version.sh`
| * dev: `2.8.2.695.1`
* trunk: `2.8.2.695`
* release: `2.8.2`
|`PACKAGE_URL` | Argument to `AC_INIT` determined by
`NUT_VERSION_QUERY=URL gitlog2version.sh`
| * dev/trunk: `https://www.networkupstools.org/`
* release: `https://www.networkupstools.org/historic/v2.8.2/index.html`
|`NUT_WEBSITE_BASE` | Derived from `PACKAGE_URL` without a trailing slash
nor `index.html` (prefixed to documentation file URLs, etc.)
| * dev/trunk: `https://www.networkupstools.org`
* release: `https://www.networkupstools.org/historic/v2.8.2`
|`NUT_SOURCE_GITREV`
| Determined by `NUT_VERSION_QUERY=DESC50 gitlog2version.sh`
| `2.8.2.695.1-696+g0e00f0777`
|`NUT_SOURCE_GITREV_SEMVER`
| Determined by `NUT_VERSION_QUERY=SEMVER gitlog2version.sh`
| `2.8.2`
|`NUT_SOURCE_GITREV_NUMERIC`
| Determined by `NUT_SOURCE_GITREV` leaving only the numbers,
e.g. for PyPI uploads (currently without the total commit count)
| `2.8.2.695.1'`
|`NUT_SOURCE_GITREV_IS_RELEASE`
| Determined by `NUT_VERSION_QUERY=IS_RELEASE gitlog2version.sh`
| `true` or `false`
|`NUT_SOURCE_GITREV_IS_PRERELEASE`
| Determined by `NUT_VERSION_QUERY=IS_PRERELEASE gitlog2version.sh`
| `true` or `false`
|`NUT_SOURCE_GITREV_DEVREL`
| String determined by `NUT_SOURCE_GITREV_IS_RELEASE`
| `"release"` or `"development iteration"`
|=========================================================================
Variables propagated by nut_version.h
-------------------------------------
.Values encoded via `include/nut_version.h`, generated by `include/Makefile.am`
[opts="header",cols="1,3,2a"]
|=========================================================================
|Variable | Description | Example (development and release)
|`#define NUT_VERSION_MACRO "$NUT_VERSION"`
| Determined by default `gitlog2version.sh` (no `NUT_VERSION_QUERY`)
at the moment of latest build, or (as fallback) `PACKAGE_VERSION`
set during the last run of `configure` script
| `2.8.2.695.1`
|`#define NUT_VERSION_SEMVER_MACRO "$GITREV_SEMVER"`
| Determined by `NUT_VERSION_QUERY=SEMVER gitlog2version.sh` at the
moment of latest build, or (as fallback) `NUT_SOURCE_GITREV_SEMVER`
set during the last run of `configure` script
| `2.8.2`
|`#define NUT_VERSION_IS_RELEASE <0-or-1>`
| Determined by `NUT_VERSION_QUERY=IS_RELEASE gitlog2version.sh`
(falls back to `false` if that query fails)
| * `1` if `$GITREV_IS_RELEASE`
* `0` otherwise
|`#define NUT_VERSION_IS_PRERELEASE <0-or-1>`
| Determined by `NUT_VERSION_QUERY=IS_PRERELEASE gitlog2version.sh`
(falls back to `false` if that query fails)
| * `1` if `$GITREV_IS_PRERELEASE`
* `0` otherwise
|=========================================================================
Use in C code
-------------
common-nut_version.c
~~~~~~~~~~~~~~~~~~~~
* The `NUT_VERSION_MACRO` is used in `common/common-nut_version.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`.
Man pages
~~~~~~~~~
* Manual pages and other documentation consume the `PACKAGE_VERSION`,
`PACKAGE_VERSION` and `NUT_WEBSITE_BASE` as `asciidoc` attributes
when rendering HTML/PDF/man document formats.
* The `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).
systemd and SMF manifests
~~~~~~~~~~~~~~~~~~~~~~~~~
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.
NUT-Monitor (Python UI) and PyNUTClient
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* The `PACKAGE_VERSION` and `NUT_WEBSITE_BASE` are reported in the About dialog.
* Version information is propagated into PyPI packages for the `PyNUTClient`
module.
|