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")
|
check(packed ~= nil, "pack writes the package")
|
||||||
if packed then packed:close() end
|
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
|
-- 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
|
-- a scratch repo root so the check exercises the same on ROM-less machines
|
||||||
local fake = root .. "/fakerepo"
|
local fake = root .. "/fakerepo"
|
||||||
|
|||||||
+19
-2
@@ -1085,6 +1085,20 @@ def cmd_lint(args, repo):
|
|||||||
|
|
||||||
# ---------------------------------------------------------------- pack
|
# ---------------------------------------------------------------- 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):
|
def cmd_pack(args, repo):
|
||||||
mod_dir = resolve_mod_dir(repo, args.mod)
|
mod_dir = resolve_mod_dir(repo, args.mod)
|
||||||
if not mod_dir:
|
if not mod_dir:
|
||||||
@@ -1119,6 +1133,10 @@ def cmd_pack(args, repo):
|
|||||||
mod_id = manifest["id"]
|
mod_id = manifest["id"]
|
||||||
version = manifest.get("version", "0.0.0")
|
version = manifest.get("version", "0.0.0")
|
||||||
out = args.output or f"{mod_id}-{version}.modpkg"
|
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)
|
files = mod_files(mod_dir)
|
||||||
records = []
|
records = []
|
||||||
for rel in files:
|
for rel in files:
|
||||||
@@ -1127,8 +1145,7 @@ def cmd_pack(args, repo):
|
|||||||
"sha256": hashlib.sha256(body).hexdigest()})
|
"sha256": hashlib.sha256(body).hexdigest()})
|
||||||
pack_meta = {
|
pack_meta = {
|
||||||
"modkit": MODKIT_VERSION,
|
"modkit": MODKIT_VERSION,
|
||||||
"packed_at": datetime.now(timezone.utc)
|
"packed_at": packed_at,
|
||||||
.strftime("%Y-%m-%dT%H:%M:%SZ"),
|
|
||||||
"id": mod_id,
|
"id": mod_id,
|
||||||
"version": version,
|
"version": version,
|
||||||
"api": manifest.get("api", 1),
|
"api": manifest.get("api", 1),
|
||||||
|
|||||||
Reference in New Issue
Block a user