{ 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) isStringLike substring stringLength optionalString escapeShellArgs concatMap ; isNonCaStorePath = x: if isStringLike x then let str = toString x; in builtins.substring 0 1 str == "/" && (dirOf str == builtins.storeDir) else false; in if replacements == [ ] then drv else let drvName = if isNonCaStorePath 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 ''