mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-12 00:10:56 +02:00
fix: honor source date in mod packages
This commit is contained in:
@@ -636,6 +636,52 @@ local packed = io.open(cleanPkg, "rb")
|
||||
check(packed ~= nil, "pack writes the package")
|
||||
if packed then packed:close() end
|
||||
|
||||
-- Reproducible-build callers pin the informational pack timestamp through the
|
||||
-- standard SOURCE_DATE_EPOCH contract. Two clean invocations over the same
|
||||
-- input must then produce identical archive bytes and metadata.
|
||||
local epoch = "1234567890"
|
||||
local envPrefix = isWindows
|
||||
and ('set "SOURCE_DATE_EPOCH=%s" && '):format(epoch)
|
||||
or ("SOURCE_DATE_EPOCH=%s "):format(epoch)
|
||||
local deterministicA = root .. "/declared-a.modpkg"
|
||||
local deterministicB = root .. "/declared-b.modpkg"
|
||||
out, code = run(envPrefix ..
|
||||
("%s tools/modkit.py pack %q -o %q --base fixture")
|
||||
:format(python, declared, deterministicA))
|
||||
check(code == 0, "SOURCE_DATE_EPOCH package A succeeds: " .. out)
|
||||
out, code = run(envPrefix ..
|
||||
("%s tools/modkit.py pack %q -o %q --base fixture")
|
||||
:format(python, declared, deterministicB))
|
||||
check(code == 0, "SOURCE_DATE_EPOCH package B succeeds: " .. out)
|
||||
local archiveA = assert(io.open(deterministicA, "rb"))
|
||||
local bytesA = archiveA:read("*a")
|
||||
archiveA:close()
|
||||
local archiveB = assert(io.open(deterministicB, "rb"))
|
||||
local bytesB = archiveB:read("*a")
|
||||
archiveB:close()
|
||||
check(bytesA == bytesB, "SOURCE_DATE_EPOCH makes package bytes reproducible")
|
||||
local inspectPack = root .. "/inspect_pack.py"
|
||||
write(inspectPack, [[
|
||||
import json, sys, zipfile
|
||||
with zipfile.ZipFile(sys.argv[1]) as archive:
|
||||
meta = json.loads(archive.read(".modkit/pack.json"))
|
||||
assert meta["packed_at"] == "2009-02-13T23:31:30Z", meta["packed_at"]
|
||||
]])
|
||||
out, code = run(("%s %q %q"):format(python, inspectPack, deterministicA))
|
||||
check(code == 0, "pack metadata honors SOURCE_DATE_EPOCH: " .. out)
|
||||
local invalidEpochPrefix = isWindows
|
||||
and 'set "SOURCE_DATE_EPOCH=not-a-time" && '
|
||||
or "SOURCE_DATE_EPOCH=not-a-time "
|
||||
local invalidEpochPkg = root .. "/declared-invalid-epoch.modpkg"
|
||||
out, code = run(invalidEpochPrefix ..
|
||||
("%s tools/modkit.py pack %q -o %q --base fixture")
|
||||
:format(python, declared, invalidEpochPkg))
|
||||
check(code == 2, "invalid SOURCE_DATE_EPOCH is a usage failure: " .. out)
|
||||
check(out:find("SOURCE_DATE_EPOCH", 1, true) ~= nil,
|
||||
"invalid source epoch names the failed contract")
|
||||
check(io.open(invalidEpochPkg, "rb") == nil,
|
||||
"invalid source epoch writes no package")
|
||||
|
||||
-- MK305 diffs shipped tables against the imported dataset; fake one under
|
||||
-- a scratch repo root so the check exercises the same on ROM-less machines
|
||||
local fake = root .. "/fakerepo"
|
||||
|
||||
+19
-2
@@ -1085,6 +1085,20 @@ def cmd_lint(args, repo):
|
||||
|
||||
# ---------------------------------------------------------------- pack
|
||||
|
||||
def pack_timestamp():
|
||||
raw = os.environ.get("SOURCE_DATE_EPOCH")
|
||||
if raw is None:
|
||||
return datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"), None
|
||||
try:
|
||||
epoch = int(raw, 10)
|
||||
if epoch < 0:
|
||||
raise ValueError("negative epoch")
|
||||
stamp = datetime.fromtimestamp(epoch, timezone.utc)
|
||||
except (ValueError, OverflowError, OSError):
|
||||
return None, "SOURCE_DATE_EPOCH must be a nonnegative Unix timestamp"
|
||||
return stamp.strftime("%Y-%m-%dT%H:%M:%SZ"), None
|
||||
|
||||
|
||||
def cmd_pack(args, repo):
|
||||
mod_dir = resolve_mod_dir(repo, args.mod)
|
||||
if not mod_dir:
|
||||
@@ -1119,6 +1133,10 @@ def cmd_pack(args, repo):
|
||||
mod_id = manifest["id"]
|
||||
version = manifest.get("version", "0.0.0")
|
||||
out = args.output or f"{mod_id}-{version}.modpkg"
|
||||
packed_at, timestamp_problem = pack_timestamp()
|
||||
if timestamp_problem:
|
||||
print(f"modkit: {timestamp_problem}")
|
||||
return 2
|
||||
files = mod_files(mod_dir)
|
||||
records = []
|
||||
for rel in files:
|
||||
@@ -1127,8 +1145,7 @@ def cmd_pack(args, repo):
|
||||
"sha256": hashlib.sha256(body).hexdigest()})
|
||||
pack_meta = {
|
||||
"modkit": MODKIT_VERSION,
|
||||
"packed_at": datetime.now(timezone.utc)
|
||||
.strftime("%Y-%m-%dT%H:%M:%SZ"),
|
||||
"packed_at": packed_at,
|
||||
"id": mod_id,
|
||||
"version": version,
|
||||
"api": manifest.get("api", 1),
|
||||
|
||||
Reference in New Issue
Block a user