Files
fds-os/tools/fds_version.py
T

60 lines
2.6 KiB
Python

"""Canonical FDS build version, shared by Cargo, images and package builders."""
from pathlib import Path
import re
import subprocess
ROOT = Path(__file__).resolve().parents[1]
RELEASE = re.compile(r'v?([0-9]+(?:\.[0-9]+){1,2})\Z')
VALID = re.compile(r'[0-9][A-Za-z0-9.]{0,31}\Z')
def validate(value):
if not isinstance(value, str) or not VALID.fullmatch(value):
raise ValueError(f'Invalid FDS version: {value!r}')
return value
def git(root, *args):
return subprocess.check_output(['git', '-C', str(root), *args], text=True, stderr=subprocess.DEVNULL).strip()
def version(root=ROOT):
root = Path(root).resolve()
# Source exports carry the value resolved when the export was created.
# Never accidentally describe a containing repository during offline builds.
if not (root / '.git').exists():
return validate((root / 'FDS_VERSION').read_text().strip())
revision = git(root, 'rev-parse', '--short=12', 'HEAD')
tags = [tag for tag in git(root, 'tag', '--merged', 'HEAD').splitlines() if RELEASE.fullmatch(tag)]
if tags:
description = git(root, 'describe', '--tags', '--long', '--abbrev=12', *[f'--match={tag}' for tag in tags], 'HEAD')
tag, distance, commit = description.rsplit('-', 2)
value = RELEASE.fullmatch(tag)[1]
if int(distance):
value += f'.r{distance}.{commit}'
else:
value = f'0.dev.g{revision}'
if git(root, 'status', '--porcelain', '--untracked-files=no'):
value += '.dirty'
return validate(value)
def cargo(root=ROOT):
print(f'cargo:rustc-env=FDS_BUILD_VERSION={version(root)}')
for path in [root / 'tools/fds_version.py', root / 'tools/version', root / 'tools/version-build.rs']:
print(f'cargo:rerun-if-changed={path}')
if not (root / '.git').exists():
print(f'cargo:rerun-if-changed={root / "FDS_VERSION"}')
return
# Tag creation, ref changes, staging and edits must invalidate cached binaries.
for name in ['HEAD', 'index', 'packed-refs', 'refs']:
path = git(root, 'rev-parse', '--path-format=absolute', '--git-path', name)
print(f'cargo:rerun-if-changed={path}')
head = subprocess.run(['git', '-C', str(root), 'symbolic-ref', '-q', 'HEAD'], capture_output=True, text=True)
if head.returncode == 0:
print('cargo:rerun-if-changed=' + git(root, 'rev-parse', '--path-format=absolute', '--git-path', head.stdout.strip()))
paths = git(root, 'ls-files', '--cached', '--others', '--exclude-standard').splitlines()
for name in paths:
if name != 'vendor/void-packages':
print(f'cargo:rerun-if-changed={root / name}')