Modify type of ERIS­Dhall manifest

Make the Dhall manifest have a general type, with the exception
of the top-level attrset which can be made general with "toMap".
This commit is contained in:
Ehmry - 2023-09-28 11:49:50 +01:00
parent 4d3d152f50
commit 9a98437796
2 changed files with 64 additions and 29 deletions

View File

@ -264,10 +264,13 @@ in nullPkgs // {
solo5-tools = callPackage ./solo5-tools { };
stdenv = overrideHost (old: {
extraNativeBuildInputs = old.extraNativeBuildInputs
++ [ final.buildPackages.erisPatchHook ];
}) prev.stdenv;
stdenv = if prev.stdenv.hostPlatform.isGenode then
stdenv.override (prev': {
extraNativeBuildInputs = prev'.extraNativeBuildInputs
++ [ final.buildPackages.erisPatchHook ];
})
else
prev.stdenv;
tor = overrideAttrsHost (attrs: {
patches = attrs.patches or [ ] ++ [

View File

@ -3,6 +3,20 @@ import cbor, dhall/[render, terms], eris
const selfDescribedCbor = 55799
type
Manifest = Table[string, ManifestEntry]
ManifestEntry = object
cap, path: string
closure: Table[string, string]
proc parseManifestFile(path: string): Manifest =
let js = parseFile(path)
for key, val in js.pairs:
var entry: ManifestEntry
entry.cap = val["cap"].getStr
entry.path = val["path"].getStr
result[key] = entry
proc writeErisLinks(path: string; node: CborNode) =
# Inspired by "Package Metadata for Core Files"
# - https://systemd.io/COREDUMP_PACKAGE_METADATA/
@ -25,16 +39,33 @@ proc toCbor(cap: ErisCap): CborNode =
result = initCborBytes(cap.bytes)
result.tag = erisCborTag
proc toDhall(js: JsonNode): Value =
case js.kind
of JString:
result = newValue(js.str)
of JObject:
result = newRecordLiteral(js.fields.len)
for key, val in js.fields.pairs:
result.table[key] = val.toDhall
else:
raiseAssert "unhandled JSON value"
proc toDhall(entry: ManifestEntry): Value =
var closure = newSeqOfCap[Value](entry.closure.len+1)
closure.add newRecordLiteral(
{ "cap": newValue $entry.cap, "path": newValue entry.path})
for path, urn in entry.closure.pairs:
closure.add newRecordLiteral(
{ "cap": newValue urn, "path": newValue path })
newRecordLiteral {
"cap": newValue entry.cap,
"closure": newValue closure,
}
proc toDhall(manifest: Manifest): Value =
result = newRecordLiteral(manifest.len)
for name, entry in manifest.pairs:
result.table[name] = entry.toDhall
proc toJson(entry: ManifestEntry): JsonNode =
var closure = newJObject()
for path, urn in entry.closure.pairs:
closure[path] = %urn
%*{ "cap": entry.cap, "closure": closure, "path": entry.path }
proc toJson(manifest: Manifest): JsonNode =
result = newJObject()
for name, entry in manifest.pairs:
result[name] = entry.toJSON
proc isElf(path: string): bool =
var magic: array[4, char]
@ -66,7 +97,7 @@ proc main =
erisLinks: CborNode
var
outputManifests = initTable[string, JsonNode]()
outputManifests = initTable[string, Manifest]()
pendingFiles = initDeque[PendingFile]()
failed = false
if getEnv("outputs") == "":
@ -78,7 +109,7 @@ proc main =
if fileExists(outputRoot / jsonManifestSubPath):
stderr.writeLine "Not running ERIS patch hook again"
quit 0
outputManifests[outputRoot] = newJObject()
outputManifests[outputRoot] = Manifest()
let buildInputs = getEnv("buildInputs").splitWhitespace
@ -149,10 +180,10 @@ proc main =
let manifestPath = storePath / jsonManifestSubPath
if fileExists(manifestPath):
let
manifest = parseFile(manifestPath)
manifest = parseManifestFile(manifestPath)
entry = manifest[filePath.extractFilename]
for path, urn in entry["closure"].pairs:
result[path] = parseErisUrn urn.getStr
for path, urn in entry.closure.pairs:
result[path] = parseErisUrn urn
let otherClosure = fileClosure(path)
for otherPath, otherCap in otherClosure.pairs:
# merge the closure of the dependency
@ -196,7 +227,7 @@ proc main =
pendingFiles.addLast(pendingFile)
break selfReferenceCheck
var
closure = newJObject()
closure = initTable[string, string]()
replaceCmd = patchelf & " --set-rpath '' " & filePath
for need, replacementPath in pendingFile.replacements.pairs:
if replacementPath == "": continue
@ -204,11 +235,11 @@ proc main =
cap = fileCap(replacementPath)
urn = $cap
stderr.writeLine "replace reference to ", need, " with ", urn
closure[replacementPath] = %urn
closure[replacementPath] = urn
pendingFile.erisLinks[ replacementPath.toCbor] = cap.toCbor
replaceCmd.add(" --replace-needed $# $#" % [need, urn])
for path, cap in fileClosure(replacementPath).pairs:
closure[path] = %($cap)
closure[path] = $cap
pendingFile.erisLinks[path.toCbor] = cap.toCbor
if runPatchelf and pendingFile.replacements.len != 0:
@ -238,11 +269,12 @@ proc main =
quit("Adding note to $1 failed" % pendingFile.filePath)
moveFile(tmpFile, pendingFile.filePath)
outputManifests[pendingFile.outputRoot][filePath.extractFilename] = %* {
"cap": $fileCap(filePath),
"closure": closure,
"path": filePath
}
outputManifests[pendingFile.outputRoot][filePath.extractFilename] =
ManifestEntry(
cap: $fileCap(filePath),
closure: closure,
path: filePath,
)
if pendingFiles.len == prevPrevLen:
failed = true
@ -260,7 +292,7 @@ proc main =
for outputRoot, manifest in outputManifests:
let supportDir = outputRoot / "nix-support"
createDir(supportDir)
writeFile(outputRoot / jsonManifestSubPath, $manifest)
writeFile(outputRoot / dhallManifestSubPath, $(manifest.toDhall))
writeFile(outputRoot / jsonManifestSubPath, $manifest.toJson)
writeFile(outputRoot / dhallManifestSubPath, $manifest.toDhall)
main()