Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
at python-updates 129 lines 4.0 kB view raw
1{ lib, stdenvNoCC }: 2 3/** 4 `replaceVarsWith` is a wrapper around the [bash function `substitute`](https://nixos.org/manual/nixpkgs/stable/#fun-substitute) 5 in the stdenv. It allows for terse replacement of names in the specified path, while checking 6 for common mistakes such as naming a replacement that does nothing or forgetting a variable which 7 needs to be replaced. 8 9 As with the [`--subst-var-by`](https://nixos.org/manual/nixpkgs/stable/#fun-substitute-subst-var-by) 10 flag, names are encoded as `@name@` in the provided file at the provided path. 11 12 Any unmatched variable names in the file at the provided path will cause a build failure. 13 14 By default, any remaining text that matches `@[A-Za-z_][0-9A-Za-z_'-]@` in the output after replacement 15 has occurred will cause a build failure. Variables can be excluded from this check by passing "null" for them. 16 17 # Inputs 18 19 `src` ([Store Path](https://nixos.org/manual/nix/latest/store/store-path.html#store-path) String) 20 : The file in which to replace variables. 21 22 `replacements` (AttrsOf String) 23 : Each entry in this set corresponds to a `--subst-var-by` entry in [`substitute`](https://nixos.org/manual/nixpkgs/stable/#fun-substitute) or 24 null to keep it unchanged. 25 26 `dir` (String) 27 : Sub directory in $out to store the result in. Commonly set to "bin". 28 29 `isExecutable` (Boolean) 30 : Whether to mark the output file as executable. 31 32 Most arguments supported by mkDerivation are also supported, with some exceptions for which 33 an error will be thrown. 34 35 # Example 36 37 ```nix 38 { replaceVarsWith }: 39 40 replaceVarsWith { 41 src = ./my-setup-hook.sh; 42 replacements = { world = "hello"; }; 43 dir = "bin"; 44 isExecutable = true; 45 } 46 ``` 47 48 See `../../test/replace-vars/default.nix` for tests of this function. Also see `replaceVars` for a short 49 version with src and replacements only. 50*/ 51{ 52 src, 53 replacements, 54 dir ? null, 55 isExecutable ? false, 56 ... 57}@attrs: 58 59let 60 # We use `--replace-fail` instead of `--subst-var-by` so that if the thing isn't there, we fail. 61 subst-var-by = name: value: [ 62 "--replace-fail" 63 (lib.escapeShellArg "@${name}@") 64 (lib.escapeShellArg (lib.defaultTo "@${name}@" value)) 65 ]; 66 67 substitutions = lib.concatLists (lib.mapAttrsToList subst-var-by replacements); 68 69 left-overs = map ({ name, ... }: name) ( 70 builtins.filter ({ value, ... }: value == null) (lib.attrsToList replacements) 71 ); 72 73 optionalAttrs = 74 if (builtins.intersectAttrs attrs forcedAttrs == { }) then 75 builtins.removeAttrs attrs [ "replacements" ] 76 else 77 throw "Passing any of ${builtins.concatStringsSep ", " (builtins.attrNames forcedAttrs)} to replaceVarsWith is not supported."; 78 79 forcedAttrs = { 80 doCheck = true; 81 dontUnpack = true; 82 preferLocalBuild = true; 83 allowSubstitutes = false; 84 85 buildPhase = '' 86 runHook preBuild 87 88 target=$out 89 if test -n "$dir"; then 90 target=$out/$dir/$name 91 mkdir -p $out/$dir 92 fi 93 94 substitute "$src" "$target" ${lib.concatStringsSep " " substitutions} 95 96 if test -n "$isExecutable"; then 97 chmod +x $target 98 fi 99 100 runHook postBuild 101 ''; 102 103 # Look for Nix identifiers surrounded by `@` that aren't substituted. 104 checkPhase = 105 let 106 lookahead = 107 if builtins.length left-overs == 0 then "" else "(?!${builtins.concatStringsSep "|" left-overs}@)"; 108 regex = lib.escapeShellArg "@${lookahead}[a-zA-Z_][0-9A-Za-z_'-]*@"; 109 in 110 '' 111 runHook preCheck 112 if grep -Pqe ${regex} "$target"; then 113 echo The following look like unsubstituted Nix identifiers that remain in "$target": 114 grep -Poe ${regex} "$target" 115 echo Use the more precise '`substitute`' function if this check is in error. 116 exit 1 117 fi 118 runHook postCheck 119 ''; 120 }; 121in 122 123stdenvNoCC.mkDerivation ( 124 { 125 name = baseNameOf (toString src); 126 } 127 // optionalAttrs 128 // forcedAttrs 129)