fix: preserve installed helpers, adaptations and inventory provenance

This commit is contained in:
Codex
2026-10-13 04:40:18 +03:00
parent 0f71430b8e
commit de1a1698a9
5 changed files with 229 additions and 13 deletions
+50 -1
View File
@@ -154,6 +154,50 @@ def artifacts_valid(directory, state):
return True
def validate_package_inventory(data):
if not isinstance(data, list) or not data:
raise ImageError('Package inventory must be a nonempty array')
seen = set()
for record in data:
if not isinstance(record, dict) or set(record) != {'package', 'use', 'build_time'}:
raise ImageError('Malformed package inventory entry')
package = record['package']
if (not isinstance(package, str) or
not re.fullmatch(r'[A-Za-z0-9+_.-]+/[A-Za-z0-9+_.-]+-[0-9][A-Za-z0-9+_.-]*', package) or
package in seen):
raise ImageError('Invalid or duplicate package inventory identity')
seen.add(package)
flags = record['use']
if (not isinstance(flags, list) or any(not isinstance(flag, str) or
not re.fullmatch(r'[A-Za-z0-9+_.@-]+', flag) for flag in flags) or len(set(flags)) != len(flags)):
raise ImageError('Invalid package inventory USE flags')
built = record['build_time']
if built is not None and (not isinstance(built, str) or not re.fullmatch(r'[0-9]+', built)):
raise ImageError('Invalid package inventory build time')
return data
def read_package_inventory(path, expected_digest=None):
path = Path(path)
if path.is_symlink() or not path.is_file():
raise ImageError('Package inventory must be an ordinary file')
if expected_digest is not None and digest(path) != expected_digest:
raise ImageError('Package inventory checksum differs from checkpoint')
try:
return validate_package_inventory(json.loads(path.read_text()))
except (ValueError, UnicodeError) as error:
raise ImageError('Package inventory is not valid JSON') from error
def enable_user_audio(root):
root_path(root, 'etc/systemd/user')
result = subprocess.run(['systemctl', '--root=' + str(root), '--global', 'enable',
'pipewire.socket', 'pipewire-pulse.socket', 'wireplumber.service'],
text=True, capture_output=True)
if result.returncode:
raise ImageError('Cannot enable user audio sockets: ' + result.stderr.strip())
def configure_rootfs(root, source):
root, source = Path(root), Path(source)
# Refuse incomplete integrations before changing the exported copy.
@@ -169,6 +213,9 @@ def configure_rootfs(root, source):
package.mkdir(parents=True, exist_ok=True)
for module in sorted((source / 'hydra').glob('*.py')):
shutil.copyfile(module, root_path(root, 'usr/lib/hydra/hydra/' + module.name))
# Session helpers derive this checkout-compatible launcher from __file__.
for name in ('hydra', 'hydra-install'):
write(root, 'usr/lib/hydra/bin/' + name, (source / 'bin' / name).read_text(), 0o755)
for name, module in (('hydra', 'cli'), ('hydra-install', 'installer')):
write(root, 'usr/bin/' + name,
'#!/usr/bin/python3\nimport sys\nsys.path.insert(0, "/usr/lib/hydra")\n'
@@ -271,7 +318,7 @@ def digest(path):
def main(argv=None):
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('step', choices=('configure', 'kernel', 'network'))
parser.add_argument('step', choices=('configure', 'kernel', 'network', 'audio'))
parser.add_argument('root', nargs='?', type=Path)
parser.add_argument('--source', type=Path)
options = parser.parse_args(argv)
@@ -282,6 +329,8 @@ def main(argv=None):
raise ImageError('An isolated rootfs directory is required')
if options.step == 'kernel':
print(kernel_version(options.root))
elif options.step == 'audio':
enable_user_audio(options.root)
else:
if options.source is None:
raise ImageError('Source checkout is required')