60 lines
2.6 KiB
Python
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}')
|