166 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
			
		
		
	
	
			166 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
{ lib, stdenv, lndir }:
 | 
						|
 | 
						|
rec {
 | 
						|
 | 
						|
  # Run the shell command `buildCommand' to produce a store path named
 | 
						|
  # `name'.  The attributes in `env' are added to the environment
 | 
						|
  # prior to running the command.
 | 
						|
  runCommand = name: env: buildCommand:
 | 
						|
    stdenv.mkDerivation ({
 | 
						|
      inherit name buildCommand;
 | 
						|
    } // env);
 | 
						|
 | 
						|
 | 
						|
  # Create a single file.
 | 
						|
  writeTextFile =
 | 
						|
    { name # the name of the derivation
 | 
						|
    , text
 | 
						|
    , executable ? false # run chmod +x ?
 | 
						|
    , destination ? ""   # relative path appended to $out eg "/bin/foo"
 | 
						|
    }:
 | 
						|
    runCommand name
 | 
						|
      { inherit text executable;
 | 
						|
        passAsFile = [ "text" ];
 | 
						|
        # Pointless to do this on a remote machine.
 | 
						|
        preferLocalBuild = true;
 | 
						|
        allowSubstitutes = false;
 | 
						|
      }
 | 
						|
      ''
 | 
						|
        n=$out${destination}
 | 
						|
        mkdir -p "$(dirname "$n")"
 | 
						|
 | 
						|
        if [ -e "$textPath" ]; then
 | 
						|
          mv "$textPath" "$n"
 | 
						|
        else
 | 
						|
          echo -n "$text" > "$n"
 | 
						|
        fi
 | 
						|
 | 
						|
        (test -n "$executable" && chmod +x "$n") || true
 | 
						|
      '';
 | 
						|
 | 
						|
 | 
						|
  # Shorthands for `writeTextFile'.
 | 
						|
  writeText = name: text: writeTextFile {inherit name text;};
 | 
						|
  writeTextDir = name: text: writeTextFile {inherit name text; destination = "/${name}";};
 | 
						|
  writeScript = name: text: writeTextFile {inherit name text; executable = true;};
 | 
						|
  writeScriptBin = name: text: writeTextFile {inherit name text; executable = true; destination = "/bin/${name}";};
 | 
						|
 | 
						|
 | 
						|
  # Create a forest of symlinks to the files in `paths'.
 | 
						|
  symlinkJoin = name: paths:
 | 
						|
    runCommand name { inherit paths; }
 | 
						|
      ''
 | 
						|
        mkdir -p $out
 | 
						|
        for i in $paths; do
 | 
						|
          ${lndir}/bin/lndir $i $out
 | 
						|
        done
 | 
						|
      '';
 | 
						|
 | 
						|
 | 
						|
  # Make a package that just contains a setup hook with the given contents.
 | 
						|
  makeSetupHook = { deps ? [], substitutions ? {} }: script:
 | 
						|
    runCommand "hook" substitutions
 | 
						|
      (''
 | 
						|
        mkdir -p $out/nix-support
 | 
						|
        cp ${script} $out/nix-support/setup-hook
 | 
						|
      '' + lib.optionalString (deps != []) ''
 | 
						|
        echo ${toString deps} > $out/nix-support/propagated-native-build-inputs
 | 
						|
      '' + lib.optionalString (substitutions != {}) ''
 | 
						|
        substituteAll ${script} $out/nix-support/setup-hook
 | 
						|
      '');
 | 
						|
 | 
						|
 | 
						|
  # Write the references (i.e. the runtime dependencies in the Nix store) of `path' to a file.
 | 
						|
  writeReferencesToFile = path: runCommand "runtime-deps"
 | 
						|
    {
 | 
						|
      exportReferencesGraph = ["graph" path];
 | 
						|
    }
 | 
						|
    ''
 | 
						|
      touch $out
 | 
						|
      while read path; do
 | 
						|
        echo $path >> $out
 | 
						|
        read dummy
 | 
						|
        read nrRefs
 | 
						|
        for ((i = 0; i < nrRefs; i++)); do read ref; done
 | 
						|
      done < graph
 | 
						|
    '';
 | 
						|
 | 
						|
  # Quickly create a set of symlinks to derivations.
 | 
						|
  # entries is a list of attribute sets like { name = "name" ; path = "/nix/store/..."; }
 | 
						|
  linkFarm = name: entries: runCommand name {} ("mkdir -p $out; cd $out; \n" +
 | 
						|
    (lib.concatMapStrings (x: "ln -s '${x.path}' '${x.name}';\n") entries));
 | 
						|
 | 
						|
  # Require file
 | 
						|
  requireFile = { name ? null
 | 
						|
                , sha256 ? null
 | 
						|
                , sha1 ? null
 | 
						|
                , url ? null
 | 
						|
                , message ? null
 | 
						|
                } :
 | 
						|
    assert (message != null) || (url != null);
 | 
						|
    assert (sha256 != null) || (sha1 != null);
 | 
						|
    assert (name != null) || (url != null);
 | 
						|
    let msg =
 | 
						|
      if message != null then message
 | 
						|
      else ''
 | 
						|
        Unfortunately, we may not download file ${name_} automatically.
 | 
						|
        Please, go to ${url} to download it yourself, and add it to the Nix store
 | 
						|
        using either
 | 
						|
          nix-store --add-fixed ${hashAlgo} ${name_}
 | 
						|
        or
 | 
						|
          nix-prefetch-url --type ${hashAlgo} file:///path/to/${name_}
 | 
						|
      '';
 | 
						|
      hashAlgo = if sha256 != null then "sha256" else "sha1";
 | 
						|
      hash = if sha256 != null then sha256 else sha1;
 | 
						|
      name_ = if name == null then baseNameOf (toString url) else name;
 | 
						|
    in
 | 
						|
    stdenv.mkDerivation {
 | 
						|
      name = name_;
 | 
						|
      outputHashAlgo = hashAlgo;
 | 
						|
      outputHash = hash;
 | 
						|
      preferLocalBuild = true;
 | 
						|
      builder = writeScript "restrict-message" ''
 | 
						|
        source ${stdenv}/setup
 | 
						|
        cat <<_EOF_
 | 
						|
 | 
						|
        ***
 | 
						|
        ${msg}
 | 
						|
        ***
 | 
						|
 | 
						|
        _EOF_
 | 
						|
      '';
 | 
						|
    };
 | 
						|
 | 
						|
  # Search in the environment if the same program exists with a set uid or
 | 
						|
  # set gid bit.  If it exists, run the first program found, otherwise run
 | 
						|
  # the default binary.
 | 
						|
  useSetUID = drv: path:
 | 
						|
    let
 | 
						|
      name = baseNameOf path;
 | 
						|
      bin = "${drv}${path}";
 | 
						|
    in assert name != "";
 | 
						|
      writeScript "setUID-${name}" ''
 | 
						|
        #!${stdenv.shell}
 | 
						|
        inode=$(stat -Lc %i ${bin})
 | 
						|
        for file in $(type -ap ${name}); do
 | 
						|
          case $(stat -Lc %a $file) in
 | 
						|
            ([2-7][0-7][0-7][0-7])
 | 
						|
              if test -r "$file".real; then
 | 
						|
                orig=$(cat "$file".real)
 | 
						|
                if test $inode = $(stat -Lc %i "$orig"); then
 | 
						|
                  exec "$file" "$@"
 | 
						|
                fi
 | 
						|
              fi;;
 | 
						|
          esac
 | 
						|
        done
 | 
						|
        exec ${bin} "$@"
 | 
						|
      '';
 | 
						|
 | 
						|
  # Copy a path to the Nix store.
 | 
						|
  copyPathToStore = builtins.filterSource (p: t: true);
 | 
						|
 | 
						|
  # Copy a list of paths to the Nix store.
 | 
						|
  copyPathsToStore = builtins.map copyPathToStore;
 | 
						|
 | 
						|
}
 |