commit 2457481a7ebee7bf69b149d3632af2c3c7b3bd62
parent ff2f68d689487276ee746194af022a6b90942068
Author: Jan Pobrislo <ccx@te2000.cz>
Date: Mon, 15 Dec 2025 02:49:16 +0000
Handle hashes/paths for namedenvs correctly
Diffstat:
| M | genpkg.py | | | 51 | +++++++++++++++++++++++++++++++++++++++++---------- |
1 file changed, 41 insertions(+), 10 deletions(-)
diff --git a/genpkg.py b/genpkg.py
@@ -114,12 +114,35 @@ def _skip_package(*args, **kwargs):
raise SkipPackageException(*args, **kwargs)
-def to_install_name(name, hash):
+def to_install_name(name, pkg_hash, env_hash=None):
rootname = name.split(":")[0]
if rootname.endswith('.environment'):
- return "env.%s" % (hash,)
+ if env_hash is None:
+ raise RuntimeError("can't derive namedenv hash without data")
+ return "env." + env_hash
else:
- return "%s.%s" % (rootname, hash)
+ return "%s.%s" % (rootname, pkg_hash)
+
+
+def parse_package_deps(script_data):
+ lines = script_data.split(b'\n')
+ assert lines[0].startswith(b"#!")
+ for line in lines[1:]:
+ if line == b'':
+ return
+ elif line.startswith(b'#@'):
+ pass
+ elif line.startswith(b'#+'):
+ yield line[2:]
+ else:
+ raise ValueError(line)
+
+
+def package_env_hash(script_data):
+ deps = sorted(d + b'\n' for d in parse_package_deps(script_data))
+ if not deps:
+ return None
+ return hashlib.sha256(b''.join(deps)).hexdigest()
class Main:
@@ -157,6 +180,7 @@ class Main:
self.env.globals["setitem"] = operator.setitem
self.env.filters["shesc"] = lambda s: "'%s'" % s.replace("'", r"'\''")
self.package_hashes = {}
+ self.package_buildenv_hashes = {}
self.rendering = []
self.deps = {}
@@ -197,16 +221,22 @@ class Main:
return hashlib.sha256(envlist.encode()).hexdigest()
def pkg_sha256(self, name):
+ return self.pkg_sha256_env_sha256(name)[0]
+
+ def pkg_sha256_env_sha256(self, name):
current = self.rendering[-1]
if current not in self.deps:
self.deps[current] = set((name,))
else:
self.deps[current].add(name)
- return self._pkg_sha256(name)
+ return self._pkg_sha256_env_sha256(name)
+
+ def _pkg_sha256(self, name, *args, **kwargs):
+ return self._pkg_sha256_env_sha256(name, *args, **kwargs)[0]
- def _pkg_sha256(self, name, error_on_skip=True):
+ def _pkg_sha256_env_sha256(self, name, error_on_skip=True):
if name in self.package_hashes:
- return self.package_hashes[name]
+ return (self.package_hashes[name], self.package_buildenv_hashes[name])
if name in self.rendering:
raise RuntimeError("circular dependency: %r", self.rendering)
@@ -231,6 +261,7 @@ class Main:
out_path.unlink()
raise
self.package_hashes[name] = hashlib.sha256(data).hexdigest()
+ self.package_buildenv_hashes[name] = package_env_hash(data)
lastname = self.rendering.pop()
assert name == lastname
@@ -243,10 +274,10 @@ class Main:
tmp_path.write_bytes(data)
tmp_path.replace(out_path)
- return self.package_hashes[name]
+ return (self.package_hashes[name], self.package_buildenv_hashes[name])
def pkg_install_name(self, name):
- return to_install_name(name, self.pkg_sha256(name))
+ return to_install_name(name, *self.pkg_sha256_env_sha256(name))
def pkg_install_dir(self, name):
return os.path.join(
@@ -277,7 +308,7 @@ class Main:
print("digraph G {")
for pkgname in self.list_packages():
try:
- pkghash = self._pkg_sha256(pkgname, False)
+ fullname = to_install_name(pkgname, *self._pkg_sha256_env_sha256(pkgname, False))
except SkipPackageException as e:
print("// [SKIPPED: %s] %s" % (pkgname, e))
continue
@@ -287,7 +318,7 @@ class Main:
% (
pkgname,
"note" if pkgname.endswith('.environment') else "box",
- to_install_name(pkgname, pkghash),
+ fullname,
)
)
for dep in sorted(self.deps.get(pkgname, ())):