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:
Emery Hemingway 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 { }; solo5-tools = callPackage ./solo5-tools { };
stdenv = overrideHost (old: { stdenv = if prev.stdenv.hostPlatform.isGenode then
extraNativeBuildInputs = old.extraNativeBuildInputs stdenv.override (prev': {
++ [ final.buildPackages.erisPatchHook ]; extraNativeBuildInputs = prev'.extraNativeBuildInputs
}) prev.stdenv; ++ [ final.buildPackages.erisPatchHook ];
})
else
prev.stdenv;
tor = overrideAttrsHost (attrs: { tor = overrideAttrsHost (attrs: {
patches = attrs.patches or [ ] ++ [ patches = attrs.patches or [ ] ++ [

View File

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