Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/facett

py/facett_demo/buildinfo.py

"""Version + git-hash stamp (build-version-githash LAW).

Every binary/app in the suite embeds its version + git-hash, SHOWS it in the app
(here: the sidebar) and answers a ``--version``/about query. We resolve the hash
in three tiers, most-authoritative first:

1. a baked ``_buildinfo.py`` (written by ``scripts/stamp.py`` at build/commit time);
2. a live ``git rev-parse`` of the checkout the package sits in (dev runs);
3. the literal ``"unknown"`` — an HONEST fallback, never a fake hash.
"""

from __future__ import annotations

import subprocess
from importlib import metadata as _metadata
from pathlib import Path

#: The package version, read from the INSTALLED distribution's own metadata — the
#: ONE writer is py/pyproject.toml (held to facett-build-thing's PYPI_VERSION by
#: xtask/tests/python_versions_track_the_workspace.rs). A source checkout that was
#: never installed answers `0+unknown` rather than a plausible-looking stale literal
#: (the components package learned that the hard way: 0.1.15 inside a 0.1.19 wheel).
try:
    __version__ = _metadata.version("facett-demo")
except _metadata.PackageNotFoundError:  # pragma: no cover - source checkout only
    __version__ = "0+unknown"

_UNKNOWN = "unknown"


def _baked() -> tuple[str, str] | None:
    """Return (git_hash, build_time) baked at build time, or None."""
    try:
        from . import _buildinfo  # type: ignore

        return (
            getattr(_buildinfo, "GIT_HASH", _UNKNOWN),
            getattr(_buildinfo, "BUILD_TIME", _UNKNOWN),
        )
    except Exception:
        return None


def _live_git_hash() -> str:
    """Best-effort short hash of the checkout this file lives in."""
    try:
        out = subprocess.run(
            ["git", "rev-parse", "--short", "HEAD"],
            cwd=str(Path(__file__).resolve().parent),
            capture_output=True,
            text=True,
            timeout=3,
        )
        if out.returncode == 0:
            h = out.stdout.strip()
            if h:
                return h
    except Exception:
        pass
    return _UNKNOWN


def build_info() -> dict[str, str]:
    """Resolve {version, git_hash, build_time, source} for display + --version."""
    baked = _baked()
    if baked is not None and baked[0] != _UNKNOWN:
        git_hash, build_time = baked
        source = "baked"
    else:
        git_hash = _live_git_hash()
        build_time = _UNKNOWN
        source = "live-git" if git_hash != _UNKNOWN else "none"
    return {
        "version": __version__,
        "git_hash": git_hash,
        "build_time": build_time,
        "source": source,
    }


def version_string() -> str:
    """A one-line version banner, mirroring facett's ``<ver> (<hash>)`` form."""
    bi = build_info()
    return f"facett-demo {bi['version']} ({bi['git_hash']})"