~ehmry/sigil

9a9843779630dc7f8ea8595babdfa7114ba48554 — Emery Hemingway 1 year, 7 days ago 4d3d152
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".
2 files changed, 64 insertions(+), 29 deletions(-)

M overlay/default.nix
M overlay/eris-patch-hook/eris_patch.nim
M overlay/default.nix => overlay/default.nix +7 -4
@@ 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 [ ] ++ [

M overlay/eris-patch-hook/eris_patch.nim => overlay/eris-patch-hook/eris_patch.nim +57 -25
@@ 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()