about summary refs log tree commit diff
path: root/pkgs/build-support/replace-direct-dependencies.nix
diff options
context:
space:
mode:
Diffstat (limited to 'pkgs/build-support/replace-direct-dependencies.nix')
-rw-r--r--pkgs/build-support/replace-direct-dependencies.nix72
1 files changed, 72 insertions, 0 deletions
diff --git a/pkgs/build-support/replace-direct-dependencies.nix b/pkgs/build-support/replace-direct-dependencies.nix
new file mode 100644
index 000000000000..57036ebd74d1
--- /dev/null
+++ b/pkgs/build-support/replace-direct-dependencies.nix
@@ -0,0 +1,72 @@
+{
+  lib,
+  runCommandLocal,
+  nix,
+}:
+
+# Replace some direct dependencies of drv, not recursing into the dependency tree.
+# You likely want to use replaceDependencies instead, unless you plan to implement your own recursion mechanism.
+{
+  drv,
+  replacements ? [ ],
+}:
+let
+  inherit (lib)
+    isStorePath
+    substring
+    stringLength
+    optionalString
+    escapeShellArgs
+    concatMap
+    ;
+in
+if replacements == [ ] then
+  drv
+else
+  let
+    drvName =
+      if isStorePath drv then
+        # Reconstruct the name from the actual store path if available.
+        substring 33 (stringLength (baseNameOf drv)) (baseNameOf drv)
+      else if drv ? drvAttrs.name then
+        # Try to get the name from the derivation arguments otherwise (for floating or deferred derivations).
+        drv.drvAttrs.name
+        + (
+          let
+            outputName = drv.outputName or "out";
+          in
+          optionalString (outputName != "out") "-${outputName}"
+        )
+      else
+        throw "cannot reconstruct the derivation name from ${drv}";
+  in
+  runCommandLocal drvName { nativeBuildInputs = [ nix.out ]; } ''
+    createRewriteScript() {
+        while [ $# -ne 0 ]; do
+            oldBasename="$(basename "$1")"
+            newBasename="$(basename "$2")"
+            shift 2
+            if [ ''${#oldBasename} -ne ''${#newBasename} ]; then
+                echo "cannot rewrite $oldBasename to $newBasename: length does not match" >&2
+                exit 1
+            fi
+            echo "s|$oldBasename|$newBasename|g" >> rewrite.sed
+        done
+    }
+    createRewriteScript ${
+      escapeShellArgs (
+        [
+          drv
+          (placeholder "out")
+        ]
+        ++ concatMap (
+          { oldDependency, newDependency }:
+          [
+            oldDependency
+            newDependency
+          ]
+        ) replacements
+      )
+    }
+    nix-store --dump ${drv} | sed -f rewrite.sed | nix-store --restore $out
+  ''