39 lines
1.7 KiB
Python
39 lines
1.7 KiB
Python
#!/usr/bin/env python3
|
|
"""Download-only resolution against verified target status; never installs."""
|
|
from pathlib import Path
|
|
import hashlib
|
|
import json
|
|
import os
|
|
import re
|
|
import subprocess
|
|
|
|
BASE = Path(__file__).resolve().parent
|
|
ROOTFS_SHA = 'bb415d824822c4b878125729af451a5d18fb13d1cf5cbed9a7393ad64ac6039e'
|
|
|
|
|
|
def main():
|
|
status = BASE/'rootfs-dpkg-status'
|
|
if not status.is_file() or b'Package: base-files\n' not in status.read_bytes():
|
|
raise SystemExit('refuse absent/incomplete target dpkg status')
|
|
env = dict(os.environ, APT_CONFIG=str(BASE/'apt.conf'), LC_ALL='C')
|
|
r = subprocess.run(['apt-get','--simulate','--no-remove','install','openssh-server','nftables'],
|
|
env=env, capture_output=True, text=True, check=True)
|
|
(BASE/'resolution.txt').write_text(r.stdout+r.stderr)
|
|
if re.search(r'^Remv ',r.stdout,re.M): raise SystemExit('removal refused')
|
|
packages = []
|
|
for line in r.stdout.splitlines():
|
|
if line.startswith('Inst '):
|
|
m=re.match(r'Inst (\S+)(?: \[[^]]+\])? \((\S+)',line)
|
|
if not m: raise SystemExit('unparsed installation record')
|
|
packages.append(m[1]+'='+m[2])
|
|
if not packages: raise SystemExit('empty package plan')
|
|
(BASE/'package-pins.json').write_text(json.dumps(packages,indent=2)+'\n')
|
|
# Exact versions, target rootfs state, download-only flag: no dpkg invocation.
|
|
r=subprocess.run(['apt-get','--download-only','--yes','--no-remove','install',*packages],
|
|
env=env,capture_output=True,text=True)
|
|
(BASE/'download.txt').write_text(r.stdout+r.stderr)
|
|
r.check_returncode()
|
|
print(json.dumps({'downloaded_package_count':len(packages),'installed':False}))
|
|
|
|
|
|
if __name__=='__main__':main()
|