ansible-later: 2.0.22 -> 2.0.23
[NixPkgs.git] / pkgs / build-support / trivial-builders.nix
bloba8c291b823240c7f8678f3fff383be59d3326539
1 { lib, stdenv, stdenvNoCC, lndir, runtimeShell, shellcheck }:
3 let
4   inherit (lib)
5     optionalAttrs
6     warn
7     ;
8 in
10 rec {
12   /* Run the shell command `buildCommand' to produce a store path named
13   * `name'.  The attributes in `env' are added to the environment
14   * prior to running the command. By default `runCommand` runs in a
15   * stdenv with no compiler environment. `runCommandCC` uses the default
16   * stdenv, `pkgs.stdenv`.
17   *
18   * Examples:
19   * runCommand "name" {envVariable = true;} ''echo hello > $out''
20   * runCommandCC "name" {} ''gcc -o myfile myfile.c; cp myfile $out'';
21   *
22   * The `*Local` variants force a derivation to be built locally,
23   * it is not substituted.
24   *
25   * This is intended for very cheap commands (<1s execution time).
26   * It saves on the network roundrip and can speed up a build.
27   *
28   * It is the same as adding the special fields
29   * `preferLocalBuild = true;`
30   * `allowSubstitutes = false;`
31   * to a derivation’s attributes.
32   */
33   runCommand = name: env: runCommandWith {
34     stdenv = stdenvNoCC;
35     runLocal = false;
36     inherit name;
37     derivationArgs = env;
38   };
39   runCommandLocal = name: env: runCommandWith {
40     stdenv = stdenvNoCC;
41     runLocal = true;
42     inherit name;
43     derivationArgs = env;
44   };
46   runCommandCC = name: env: runCommandWith {
47     stdenv = stdenv;
48     runLocal = false;
49     inherit name;
50     derivationArgs = env;
51   };
52   # `runCommandCCLocal` left out on purpose.
53   # We shouldn’t force the user to have a cc in scope.
55   /* Generalized version of the `runCommand`-variants
56    * which does customized behavior via a single
57    * attribute set passed as the first argument
58    * instead of having a lot of variants like
59    * `runCommand*`. Additionally it allows changing
60    * the used `stdenv` freely and has a more explicit
61    * approach to changing the arguments passed to
62    * `stdenv.mkDerivation`.
63    */
64   runCommandWith =
65     let
66       # prevent infinite recursion for the default stdenv value
67       defaultStdenv = stdenv;
68     in
69     { stdenv ? defaultStdenv
70     # which stdenv to use, defaults to a stdenv with a C compiler, pkgs.stdenv
71     , runLocal ? false
72     # whether to build this derivation locally instead of substituting
73     , derivationArgs ? {}
74     # extra arguments to pass to stdenv.mkDerivation
75     , name
76     # name of the resulting derivation
77     # TODO(@Artturin): enable strictDeps always
78     }: buildCommand:
79     stdenv.mkDerivation ({
80       enableParallelBuilding = true;
81       inherit buildCommand name;
82       passAsFile = [ "buildCommand" ]
83         ++ (derivationArgs.passAsFile or []);
84     }
85     // (lib.optionalAttrs runLocal {
86           preferLocalBuild = true;
87           allowSubstitutes = false;
88        })
89     // builtins.removeAttrs derivationArgs [ "passAsFile" ]);
92   /* Writes a text file to the nix store.
93    * The contents of text is added to the file in the store.
94    *
95    * Examples:
96    * # Writes my-file to /nix/store/<store path>
97    * writeTextFile {
98    *   name = "my-file";
99    *   text = ''
100    *     Contents of File
101    *   '';
102    * }
103    * # See also the `writeText` helper function below.
104    *
105    * # Writes executable my-file to /nix/store/<store path>/bin/my-file
106    * writeTextFile {
107    *   name = "my-file";
108    *   text = ''
109    *     Contents of File
110    *   '';
111    *   executable = true;
112    *   destination = "/bin/my-file";
113    * }
114    */
115   writeTextFile =
116     { name # the name of the derivation
117     , text
118     , executable ? false # run chmod +x ?
119     , destination ? ""   # relative path appended to $out eg "/bin/foo"
120     , checkPhase ? ""    # syntax checks, e.g. for scripts
121     , meta ? { }
122     }:
123     runCommand name
124       { inherit text executable checkPhase meta;
125         passAsFile = [ "text" ];
126         # Pointless to do this on a remote machine.
127         preferLocalBuild = true;
128         allowSubstitutes = false;
129       }
130       ''
131         target=$out${lib.escapeShellArg destination}
132         mkdir -p "$(dirname "$target")"
134         if [ -e "$textPath" ]; then
135           mv "$textPath" "$target"
136         else
137           echo -n "$text" > "$target"
138         fi
140         eval "$checkPhase"
142         (test -n "$executable" && chmod +x "$target") || true
143       '';
145   /*
146    * Writes a text file to nix store with no optional parameters available.
147    *
148    * Example:
149    * # Writes contents of file to /nix/store/<store path>
150    * writeText "my-file"
151    *   ''
152    *   Contents of File
153    *   '';
154    *
155   */
156   writeText = name: text: writeTextFile {inherit name text;};
158   /*
159    * Writes a text file to nix store in a specific directory with no
160    * optional parameters available.
161    *
162    * Example:
163    * # Writes contents of file to /nix/store/<store path>/share/my-file
164    * writeTextDir "share/my-file"
165    *   ''
166    *   Contents of File
167    *   '';
168    *
169   */
170   writeTextDir = path: text: writeTextFile {
171     inherit text;
172     name = builtins.baseNameOf path;
173     destination = "/${path}";
174   };
176   /*
177    * Writes a text file to /nix/store/<store path> and marks the file as
178    * executable.
179    *
180    * If passed as a build input, will be used as a setup hook. This makes setup
181    * hooks more efficient to create: you don't need a derivation that copies
182    * them to $out/nix-support/setup-hook, instead you can use the file as is.
183    *
184    * Example:
185    * # Writes my-file to /nix/store/<store path> and makes executable
186    * writeScript "my-file"
187    *   ''
188    *   Contents of File
189    *   '';
190    *
191   */
192   writeScript = name: text: writeTextFile {inherit name text; executable = true;};
194   /*
195    * Writes a text file to /nix/store/<store path>/bin/<name> and
196    * marks the file as executable.
197    *
198    * Example:
199    * # Writes my-file to /nix/store/<store path>/bin/my-file and makes executable.
200    * writeScriptBin "my-file"
201    *   ''
202    *   Contents of File
203    *   '';
204    *
205   */
206   writeScriptBin = name: text: writeTextFile {inherit name text; executable = true; destination = "/bin/${name}";};
208   /*
209    * Similar to writeScript. Writes a Shell script and checks its syntax.
210    * Automatically includes interpreter above the contents passed.
211    *
212    * Example:
213    * # Writes my-file to /nix/store/<store path> and makes executable.
214    * writeShellScript "my-file"
215    *   ''
216    *   Contents of File
217    *   '';
218    *
219   */
220   writeShellScript = name: text:
221     writeTextFile {
222       inherit name;
223       executable = true;
224       text = ''
225         #!${runtimeShell}
226         ${text}
227         '';
228       checkPhase = ''
229         ${stdenv.shellDryRun} "$target"
230       '';
231     };
233   /*
234    * Similar to writeShellScript and writeScriptBin.
235    * Writes an executable Shell script to /nix/store/<store path>/bin/<name> and checks its syntax.
236    * Automatically includes interpreter above the contents passed.
237    *
238    * Example:
239    * # Writes my-file to /nix/store/<store path>/bin/my-file and makes executable.
240    * writeShellScriptBin "my-file"
241    *   ''
242    *   Contents of File
243    *   '';
244    *
245   */
246   writeShellScriptBin = name : text :
247     writeTextFile {
248       inherit name;
249       executable = true;
250       destination = "/bin/${name}";
251       text = ''
252         #!${runtimeShell}
253         ${text}
254         '';
255       checkPhase = ''
256         ${stdenv.shellDryRun} "$target"
257       '';
258     };
260   /*
261    * Similar to writeShellScriptBin and writeScriptBin.
262    * Writes an executable Shell script to /nix/store/<store path>/bin/<name> and
263    * checks its syntax with shellcheck and the shell's -n option.
264    * Automatically includes sane set of shellopts (errexit, nounset, pipefail)
265    * and handles creation of PATH based on runtimeInputs
266    *
267    * Note that the checkPhase uses stdenv.shell for the test run of the script,
268    * while the generated shebang uses runtimeShell. If, for whatever reason,
269    * those were to mismatch you might lose fidelity in the default checks.
270    *
271    * Example:
272    * # Writes my-file to /nix/store/<store path>/bin/my-file and makes executable.
273    * writeShellApplication {
274    *   name = "my-file";
275    *   runtimeInputs = [ curl w3m ];
276    *   text = ''
277    *     curl -s 'https://nixos.org' | w3m -dump -T text/html
278    *    '';
279    * }
280   */
281   writeShellApplication =
282     { name
283     , text
284     , runtimeInputs ? [ ]
285     , checkPhase ? null
286     }:
287     writeTextFile {
288       inherit name;
289       executable = true;
290       destination = "/bin/${name}";
291       text = ''
292         #!${runtimeShell}
293         set -o errexit
294         set -o nounset
295         set -o pipefail
296       '' + lib.optionalString (runtimeInputs != [ ]) ''
298         export PATH="${lib.makeBinPath runtimeInputs}:$PATH"
299       '' + ''
301         ${text}
302       '';
304       checkPhase =
305         if checkPhase == null then ''
306           runHook preCheck
307           ${stdenv.shellDryRun} "$target"
308           ${shellcheck}/bin/shellcheck "$target"
309           runHook postCheck
310         ''
311         else checkPhase;
313       meta.mainProgram = name;
314     };
316   # Create a C binary
317   writeCBin = name: code:
318     runCommandCC name
319     {
320       inherit name code;
321       executable = true;
322       passAsFile = ["code"];
323       # Pointless to do this on a remote machine.
324       preferLocalBuild = true;
325       allowSubstitutes = false;
326     }
327     ''
328       n=$out/bin/$name
329       mkdir -p "$(dirname "$n")"
330       mv "$codePath" code.c
331       $CC -x c code.c -o "$n"
332     '';
335   /* concat a list of files to the nix store.
336    * The contents of files are added to the file in the store.
337    *
338    * Examples:
339    * # Writes my-file to /nix/store/<store path>
340    * concatTextFile {
341    *   name = "my-file";
342    *   files = [ drv1 "${drv2}/path/to/file" ];
343    * }
344    * # See also the `concatText` helper function below.
345    *
346    * # Writes executable my-file to /nix/store/<store path>/bin/my-file
347    * concatTextFile {
348    *   name = "my-file";
349    *   files = [ drv1 "${drv2}/path/to/file" ];
350    *   executable = true;
351    *   destination = "/bin/my-file";
352    * }
353    */
354   concatTextFile =
355     { name # the name of the derivation
356     , files
357     , executable ? false # run chmod +x ?
358     , destination ? ""   # relative path appended to $out eg "/bin/foo"
359     , checkPhase ? ""    # syntax checks, e.g. for scripts
360     , meta ? { }
361     }:
362     runCommandLocal name
363       { inherit files executable checkPhase meta destination; }
364       ''
365         file=$out$destination
366         mkdir -p "$(dirname "$file")"
367         cat $files > "$file"
369         (test -n "$executable" && chmod +x "$file") || true
370         eval "$checkPhase"
371       '';
374   /*
375    * Writes a text file to nix store with no optional parameters available.
376    *
377    * Example:
378    * # Writes contents of files to /nix/store/<store path>
379    * concatText "my-file" [ file1 file2 ]
380    *
381   */
382   concatText = name: files: concatTextFile { inherit name files; };
384     /*
385    * Writes a text file to nix store with and mark it as executable.
386    *
387    * Example:
388    * # Writes contents of files to /nix/store/<store path>
389    * concatScript "my-file" [ file1 file2 ]
390    *
391   */
392   concatScript = name: files: concatTextFile { inherit name files; executable = true; };
395   /*
396    * Create a forest of symlinks to the files in `paths'.
397    *
398    * This creates a single derivation that replicates the directory structure
399    * of all the input paths.
400    *
401    * BEWARE: it may not "work right" when the passed paths contain symlinks to directories.
402    *
403    * Examples:
404    * # adds symlinks of hello to current build.
405    * symlinkJoin { name = "myhello"; paths = [ pkgs.hello ]; }
406    *
407    * # adds symlinks of hello and stack to current build and prints "links added"
408    * symlinkJoin { name = "myexample"; paths = [ pkgs.hello pkgs.stack ]; postBuild = "echo links added"; }
409    *
410    * This creates a derivation with a directory structure like the following:
411    *
412    * /nix/store/sglsr5g079a5235hy29da3mq3hv8sjmm-myexample
413    * |-- bin
414    * |   |-- hello -> /nix/store/qy93dp4a3rqyn2mz63fbxjg228hffwyw-hello-2.10/bin/hello
415    * |   `-- stack -> /nix/store/6lzdpxshx78281vy056lbk553ijsdr44-stack-2.1.3.1/bin/stack
416    * `-- share
417    *     |-- bash-completion
418    *     |   `-- completions
419    *     |       `-- stack -> /nix/store/6lzdpxshx78281vy056lbk553ijsdr44-stack-2.1.3.1/share/bash-completion/completions/stack
420    *     |-- fish
421    *     |   `-- vendor_completions.d
422    *     |       `-- stack.fish -> /nix/store/6lzdpxshx78281vy056lbk553ijsdr44-stack-2.1.3.1/share/fish/vendor_completions.d/stack.fish
423    * ...
424    *
425    * symlinkJoin and linkFarm are similar functions, but they output
426    * derivations with different structure.
427    *
428    * symlinkJoin is used to create a derivation with a familiar directory
429    * structure (top-level bin/, share/, etc), but with all actual files being symlinks to
430    * the files in the input derivations.
431    *
432    * symlinkJoin is used many places in nixpkgs to create a single derivation
433    * that appears to contain binaries, libraries, documentation, etc from
434    * multiple input derivations.
435    *
436    * linkFarm is instead used to create a simple derivation with symlinks to
437    * other derivations.  A derivation created with linkFarm is often used in CI
438    * as a easy way to build multiple derivations at once.
439    */
440   symlinkJoin =
441     args_@{ name
442          , paths
443          , preferLocalBuild ? true
444          , allowSubstitutes ? false
445          , postBuild ? ""
446          , ...
447          }:
448     let
449       args = removeAttrs args_ [ "name" "postBuild" ]
450         // {
451           inherit preferLocalBuild allowSubstitutes;
452           passAsFile = [ "paths" ];
453         }; # pass the defaults
454     in runCommand name args
455       ''
456         mkdir -p $out
457         for i in $(cat $pathsPath); do
458           ${lndir}/bin/lndir -silent $i $out
459         done
460         ${postBuild}
461       '';
463   /*
464    * Quickly create a set of symlinks to derivations.
465    *
466    * This creates a simple derivation with symlinks to all inputs.
467    *
468    * entries is a list of attribute sets like
469    * { name = "name" ; path = "/nix/store/..."; }
470    *
471    * Example:
472    *
473    * # Symlinks hello and stack paths in store to current $out/hello-test and
474    * # $out/foobar.
475    * linkFarm "myexample" [ { name = "hello-test"; path = pkgs.hello; } { name = "foobar"; path = pkgs.stack; } ]
476    *
477    * This creates a derivation with a directory structure like the following:
478    *
479    * /nix/store/qc5728m4sa344mbks99r3q05mymwm4rw-myexample
480    * |-- foobar -> /nix/store/6lzdpxshx78281vy056lbk553ijsdr44-stack-2.1.3.1
481    * `-- hello-test -> /nix/store/qy93dp4a3rqyn2mz63fbxjg228hffwyw-hello-2.10
482    *
483    * See the note on symlinkJoin for the difference between linkFarm and symlinkJoin.
484    */
485   linkFarm = name: entries: runCommand name { preferLocalBuild = true; allowSubstitutes = false; }
486     ''mkdir -p $out
487       cd $out
488       ${lib.concatMapStrings (x: ''
489           mkdir -p "$(dirname ${lib.escapeShellArg x.name})"
490           ln -s ${lib.escapeShellArg "${x.path}"} ${lib.escapeShellArg x.name}
491       '') entries}
492     '';
494   /*
495    * Easily create a linkFarm from a set of derivations.
496    *
497    * This calls linkFarm with a list of entries created from the list of input
498    * derivations.  It turns each input derivation into an attribute set
499    * like { name = drv.name ; path = drv }, and passes this to linkFarm.
500    *
501    * Example:
502    *
503    * # Symlinks the hello, gcc, and ghc derivations in $out
504    * linkFarmFromDrvs "myexample" [ pkgs.hello pkgs.gcc pkgs.ghc ]
505    *
506    * This creates a derivation with a directory structure like the following:
507    *
508    * /nix/store/m3s6wkjy9c3wy830201bqsb91nk2yj8c-myexample
509    * |-- gcc-wrapper-9.2.0 -> /nix/store/fqhjxf9ii4w4gqcsx59fyw2vvj91486a-gcc-wrapper-9.2.0
510    * |-- ghc-8.6.5 -> /nix/store/gnf3s07bglhbbk4y6m76sbh42siym0s6-ghc-8.6.5
511    * `-- hello-2.10 -> /nix/store/k0ll91c4npk4lg8lqhx00glg2m735g74-hello-2.10
512    */
513   linkFarmFromDrvs = name: drvs:
514     let mkEntryFromDrv = drv: { name = drv.name; path = drv; };
515     in linkFarm name (map mkEntryFromDrv drvs);
518   /*
519    * Make a package that just contains a setup hook with the given contents.
520    * This setup hook will be invoked by any package that includes this package
521    * as a buildInput. Optionally takes a list of substitutions that should be
522    * applied to the resulting script.
523    *
524    * Examples:
525    * # setup hook that depends on the hello package and runs ./myscript.sh
526    * myhellohook = makeSetupHook { deps = [ hello ]; } ./myscript.sh;
527    *
528    * # writes a Linux-exclusive setup hook where @bash@ myscript.sh is substituted for the
529    * # bash interpreter.
530    * myhellohookSub = makeSetupHook {
531    *                 deps = [ hello ];
532    *                 substitutions = { bash = "${pkgs.bash}/bin/bash"; };
533    *                 meta.platforms = lib.platforms.linux;
534    *               } ./myscript.sh;
535    *
536    * # setup hook with a package test
537    * myhellohookTested = makeSetupHook {
538    *                 deps = [ hello ];
539    *                 substitutions = { bash = "${pkgs.bash}/bin/bash"; };
540    *                 meta.platforms = lib.platforms.linux;
541    *                 passthru.tests.greeting = callPackage ./test { };
542    *               } ./myscript.sh;
543    */
544   makeSetupHook = { name ? "hook", deps ? [], substitutions ? {}, meta ? {}, passthru ? {} }: script:
545     runCommand name
546       (substitutions // {
547         inherit meta;
548         strictDeps = true;
549         # TODO 2023-01, no backport: simplify to inherit passthru;
550         passthru = passthru
551           // optionalAttrs (substitutions?passthru)
552             (warn "makeSetupHook (name = ${lib.strings.escapeNixString name}): `substitutions.passthru` is deprecated. Please set `passthru` directly."
553               substitutions.passthru);
554       })
555       (''
556         mkdir -p $out/nix-support
557         cp ${script} $out/nix-support/setup-hook
558       '' + lib.optionalString (deps != []) ''
559         printWords ${toString deps} > $out/nix-support/propagated-build-inputs
560       '' + lib.optionalString (substitutions != {}) ''
561         substituteAll ${script} $out/nix-support/setup-hook
562       '');
565   # Write the references (i.e. the runtime dependencies in the Nix store) of `path' to a file.
567   writeReferencesToFile = path: runCommand "runtime-deps"
568     {
569       exportReferencesGraph = ["graph" path];
570     }
571     ''
572       touch $out
573       while read path; do
574         echo $path >> $out
575         read dummy
576         read nrRefs
577         for ((i = 0; i < nrRefs; i++)); do read ref; done
578       done < graph
579     '';
581   /*
582     Write the set of references to a file, that is, their immediate dependencies.
584     This produces the equivalent of `nix-store -q --references`.
585    */
586   writeDirectReferencesToFile = path: runCommand "runtime-references"
587     {
588       exportReferencesGraph = ["graph" path];
589       inherit path;
590     }
591     ''
592       touch ./references
593       while read p; do
594         read dummy
595         read nrRefs
596         if [[ $p == $path ]]; then
597           for ((i = 0; i < nrRefs; i++)); do
598             read ref;
599             echo $ref >>./references
600           done
601         else
602           for ((i = 0; i < nrRefs; i++)); do
603             read ref;
604           done
605         fi
606       done < graph
607       sort ./references >$out
608     '';
611   /*
612    * Extract a string's references to derivations and paths (its
613    * context) and write them to a text file, removing the input string
614    * itself from the dependency graph. This is useful when you want to
615    * make a derivation depend on the string's references, but not its
616    * contents (to avoid unnecessary rebuilds, for example).
617    *
618    * Note that this only works as intended on Nix >= 2.3.
619    */
620   writeStringReferencesToFile = string:
621     /*
622     * The basic operation this performs is to copy the string context
623     * from `string' to a second string and wrap that string in a
624     * derivation. However, that alone is not enough, since nothing in the
625     * string refers to the output paths of the derivations/paths in its
626     * context, meaning they'll be considered build-time dependencies and
627     * removed from the wrapper derivation's closure. Putting the
628     * necessary output paths in the new string is however not very
629     * straightforward - the attrset returned by `getContext' contains
630     * only references to derivations' .drv-paths, not their output
631     * paths. In order to "convert" them, we try to extract the
632     * corresponding paths from the original string using regex.
633     */
634     let
635       # Taken from https://github.com/NixOS/nix/blob/130284b8508dad3c70e8160b15f3d62042fc730a/src/libutil/hash.cc#L84
636       nixHashChars = "0123456789abcdfghijklmnpqrsvwxyz";
637       context = builtins.getContext string;
638       derivations = lib.filterAttrs (n: v: v ? outputs) context;
639       # Objects copied from outside of the store, such as paths and
640       # `builtins.fetch*`ed ones
641       sources = lib.attrNames (lib.filterAttrs (n: v: v ? path) context);
642       packages =
643         lib.mapAttrs'
644           (name: value:
645             {
646               inherit value;
647               name = lib.head (builtins.match "${builtins.storeDir}/[${nixHashChars}]+-(.*)\.drv" name);
648             })
649           derivations;
650       # The syntax of output paths differs between outputs named `out`
651       # and other, explicitly named ones. For explicitly named ones,
652       # the output name is suffixed as `-name`, but `out` outputs
653       # aren't suffixed at all, and thus aren't easily distinguished
654       # from named output paths. Therefore, we find all the named ones
655       # first so we can use them to remove false matches when looking
656       # for `out` outputs (see the definition of `outputPaths`).
657       namedOutputPaths =
658         lib.flatten
659           (lib.mapAttrsToList
660             (name: value:
661               (map
662                 (output:
663                   lib.filter
664                     lib.isList
665                     (builtins.split "(${builtins.storeDir}/[${nixHashChars}]+-${name}-${output})" string))
666                 (lib.remove "out" value.outputs)))
667             packages);
668       # Only `out` outputs
669       outputPaths =
670         lib.flatten
671           (lib.mapAttrsToList
672             (name: value:
673               if lib.elem "out" value.outputs then
674                 lib.filter
675                   (x: lib.isList x &&
676                       # If the matched path is in `namedOutputPaths`,
677                       # it's a partial match of an output path where
678                       # the output name isn't `out`
679                       lib.all (o: !lib.hasPrefix (lib.head x) o) namedOutputPaths)
680                   (builtins.split "(${builtins.storeDir}/[${nixHashChars}]+-${name})" string)
681               else
682                 [])
683             packages);
684       allPaths = lib.concatStringsSep "\n" (lib.unique (sources ++ namedOutputPaths ++ outputPaths));
685       allPathsWithContext = builtins.appendContext allPaths context;
686     in
687       if builtins ? getContext then
688         writeText "string-references" allPathsWithContext
689       else
690         writeDirectReferencesToFile (writeText "string-file" string);
693   /* Print an error message if the file with the specified name and
694    * hash doesn't exist in the Nix store. This function should only
695    * be used by non-redistributable software with an unfree license
696    * that we need to require the user to download manually. It produces
697    * packages that cannot be built automatically.
698    *
699    * Examples:
700    *
701    * requireFile {
702    *   name = "my-file";
703    *   url = "http://example.com/download/";
704    *   sha256 = "ffffffffffffffffffffffffffffffffffffffffffffffffffff";
705    * }
706    */
707   requireFile = { name ? null
708                 , sha256 ? null
709                 , sha1 ? null
710                 , url ? null
711                 , message ? null
712                 , hashMode ? "flat"
713                 } :
714     assert (message != null) || (url != null);
715     assert (sha256 != null) || (sha1 != null);
716     assert (name != null) || (url != null);
717     let msg =
718       if message != null then message
719       else ''
720         Unfortunately, we cannot download file ${name_} automatically.
721         Please go to ${url} to download it yourself, and add it to the Nix store
722         using either
723           nix-store --add-fixed ${hashAlgo} ${name_}
724         or
725           nix-prefetch-url --type ${hashAlgo} file:///path/to/${name_}
726       '';
727       hashAlgo = if sha256 != null then "sha256" else "sha1";
728       hash = if sha256 != null then sha256 else sha1;
729       name_ = if name == null then baseNameOf (toString url) else name;
730     in
731     stdenvNoCC.mkDerivation {
732       name = name_;
733       outputHashMode = hashMode;
734       outputHashAlgo = hashAlgo;
735       outputHash = hash;
736       preferLocalBuild = true;
737       allowSubstitutes = false;
738       builder = writeScript "restrict-message" ''
739         source ${stdenvNoCC}/setup
740         cat <<_EOF_
742         ***
743         ${msg}
744         ***
746         _EOF_
747         exit 1
748       '';
749     };
752   # Copy a path to the Nix store.
753   # Nix automatically copies files to the store before stringifying paths.
754   # If you need the store path of a file, ${copyPathToStore <path>} can be
755   # shortened to ${<path>}.
756   copyPathToStore = builtins.filterSource (p: t: true);
759   # Copy a list of paths to the Nix store.
760   copyPathsToStore = builtins.map copyPathToStore;
762   /* Applies a list of patches to a source directory.
763    *
764    * Examples:
765    *
766    * # Patching nixpkgs:
767    * applyPatches {
768    *   src = pkgs.path;
769    *   patches = [
770    *     (pkgs.fetchpatch {
771    *       url = "https://github.com/NixOS/nixpkgs/commit/1f770d20550a413e508e081ddc08464e9d08ba3d.patch";
772    *       sha256 = "1nlzx171y3r3jbk0qhvnl711kmdk57jlq4na8f8bs8wz2pbffymr";
773    *     })
774    *   ];
775    * }
776    */
777   applyPatches =
778     { src
779     , name ? (if builtins.typeOf src == "path"
780               then builtins.baseNameOf src
781               else
782                 if builtins.isAttrs src && builtins.hasAttr "name" src
783                 then src.name
784                 else throw "applyPatches: please supply a `name` argument because a default name can only be computed when the `src` is a path or is an attribute set with a `name` attribute."
785              ) + "-patched"
786     , patches   ? []
787     , postPatch ? ""
788     }: stdenvNoCC.mkDerivation {
789       inherit name src patches postPatch;
790       preferLocalBuild = true;
791       allowSubstitutes = false;
792       phases = "unpackPhase patchPhase installPhase";
793       installPhase = "cp -R ./ $out";
794     };
796   /* An immutable file in the store with a length of 0 bytes. */
797   emptyFile = runCommand "empty-file" {
798     outputHashAlgo = "sha256";
799     outputHashMode = "recursive";
800     outputHash = "0ip26j2h11n1kgkz36rl4akv694yz65hr72q4kv4b3lxcbi65b3p";
801     preferLocalBuild = true;
802   } "touch $out";
804   /* An immutable empty directory in the store. */
805   emptyDirectory = runCommand "empty-directory" {
806     outputHashAlgo = "sha256";
807     outputHashMode = "recursive";
808     outputHash = "0sjjj9z1dhilhpc8pq4154czrb79z9cm044jvn75kxcjv6v5l2m5";
809     preferLocalBuild = true;
810   } "mkdir $out";