substitute: Deprecate replacements, introduce replacementsList

Also:
- Add tests
- Treewide update
- Improve docs
This commit is contained in:
Silvan Mosberger 2024-02-09 04:30:09 +01:00 committed by Silvan Mosberger
parent 0151be1b32
commit cd5dc76d83
9 changed files with 160 additions and 12 deletions

View File

@ -52,7 +52,7 @@ in {
# See: https://github.com/NixOS/nixpkgs/issues/213408
pkgs.substitute {
src = "${systemd}/example/sysctl.d/50-coredump.conf";
replacements = [
substitutions = [
"--replace"
"${systemd}"
"${pkgs.symlinkJoin { name = "systemd"; paths = [ systemd ]; }}"

View File

@ -1,14 +1,58 @@
{ stdenvNoCC }:
{ lib, stdenvNoCC }:
/*
This is a wrapper around `substitute` in the stdenv.
Attribute arguments:
- `name` (optional): The name of the resulting derivation
- `src`: The path to the file to substitute
- `substitutions`: The list of substitution arguments to pass
See https://nixos.org/manual/nixpkgs/stable/#fun-substitute
- `replacements`: Deprecated version of `substitutions`
that doesn't support spaces in arguments.
Example:
```nix
{ substitute }:
substitute {
src = ./greeting.txt;
substitutions = [
"--replace"
"world"
"paul"
];
}
```
See ../../test/substitute for tests
*/
args:
# This is a wrapper around `substitute` in the stdenv.
# The `replacements` attribute should be a list of list of arguments
# to `substitute`, such as `[ "--replace" "sourcetext" "replacementtext" ]`
stdenvNoCC.mkDerivation ({
let
name = if args ? name then args.name else baseNameOf (toString args.src);
deprecationReplacement = lib.pipe args.replacements [
lib.toList
(map (lib.splitString " "))
lib.concatLists
(lib.concatMapStringsSep " " lib.strings.escapeNixString)
];
optionalDeprecationWarning =
# substitutions is only available starting 24.05.
# TODO: Remove support for replacements sometime after the next release
lib.warnIf (args ? replacements && lib.isInOldestRelease 2405) ''
pkgs.substitute: For "${name}", `replacements` is used, which is deprecated since it doesn't support arguments with spaces. Use `substitutions` instead:
substitutions = [ ${deprecationReplacement} ];'';
in
optionalDeprecationWarning
stdenvNoCC.mkDerivation ({
inherit name;
builder = ./substitute.sh;
inherit (args) src;
preferLocalBuild = true;
allowSubstitutes = false;
} // args // { replacements = args.replacements; })
} // args // lib.optionalAttrs (args ? substitutions) {
substitutions =
assert lib.assertMsg (lib.isList args.substitutions) ''
pkgs.substitute: For "${name}", `substitutions` is passed, which is expected to be a list, but it's a ${builtins.typeOf args.substitutions} instead.'';
lib.escapeShellArgs args.substitutions;
})

View File

@ -8,7 +8,13 @@ if test -n "$dir"; then
mkdir -p $out/$dir
fi
substitute $src $target $replacements
substitutionsList=($replacements)
if [[ -v substitutions ]]; then
eval "substitutionsList+=($substitutions)"
fi
substitute $src $target "${substitutionsList[@]}"
if test -n "$isExecutable"; then
chmod +x $target

View File

@ -12,7 +12,7 @@ stdenv.mkDerivation rec {
patches = [
(substitute {
src = ./libamplsolver-sharedlib.patch;
replacements = [ "--replace" "@sharedlibext@" "${stdenv.hostPlatform.extensions.sharedLibrary}" ];
substitutions = [ "--replace" "@sharedlibext@" "${stdenv.hostPlatform.extensions.sharedLibrary}" ];
})
];

View File

@ -91,7 +91,7 @@ stdenv.mkDerivation {
# this patch is from debian:
# https://sources.debian.org/data/main/b/binutils/2.38-3/debian/patches/mips64-default-n64.diff
(if stdenv.targetPlatform.isMusl
then substitute { src = ./mips64-default-n64.patch; replacements = [ "--replace" "gnuabi64" "muslabi64" ]; }
then substitute { src = ./mips64-default-n64.patch; substitutions = [ "--replace" "gnuabi64" "muslabi64" ]; }
else ./mips64-default-n64.patch)
# On PowerPC, when generating assembly code, GCC generates a `.machine`
# custom instruction which instructs the assembler to generate code for this

View File

@ -105,7 +105,7 @@ stdenv.mkDerivation (finalAttrs: {
# this patch is from debian:
# https://sources.debian.org/data/main/b/binutils/2.38-3/debian/patches/mips64-default-n64.diff
(if stdenv.targetPlatform.isMusl
then substitute { src = ./mips64-default-n64.patch; replacements = [ "--replace" "gnuabi64" "muslabi64" ]; }
then substitute { src = ./mips64-default-n64.patch; substitutions = [ "--replace" "gnuabi64" "muslabi64" ]; }
else ./mips64-default-n64.patch)
# This patch fixes a bug in 2.40 on MinGW, which breaks DXVK when cross-building from Darwin.
# See https://sourceware.org/bugzilla/show_bug.cgi?id=30079

View File

@ -18,7 +18,7 @@ callPackage ./generic.nix rec {
patches = [(substitute {
src = ./disable-git-version.patch;
replacements = [ "--subst-var-by" "version" version ];
substitutions = [ "--subst-var-by" "version" version ];
})];
depsHash = "sha256-0P/BcjNnbDN25DguRcCyzPuUG7bouxEx1ySodIbSwvg=";

View File

@ -177,4 +177,6 @@ with pkgs;
auto-patchelf-hook = callPackage ./auto-patchelf-hook { };
systemd = callPackage ./systemd { };
substitute = recurseIntoAttrs (callPackage ./substitute { });
}

View File

@ -0,0 +1,96 @@
{ substitute, testers, runCommand }:
let
# Ofborg doesn't allow any traces on stderr,
# so mock `lib` to not trace warnings,
# because substitute gives a deprecation warning
substituteSilent = substitute.override (prevArgs: {
lib = prevArgs.lib.extend (finalLib: prevLib: {
trivial = prevLib.trivial // {
warn = msg: value: value;
};
});
});
in {
substitutions = testers.testEqualContents {
assertion = "substitutions-spaces";
actual = substitute {
src = builtins.toFile "source" ''
Hello world!
'';
substitutions = [
"--replace-fail"
"Hello world!"
"Yo peter!"
];
};
expected = builtins.toFile "expected" ''
Yo peter!
'';
};
legacySingleReplace = testers.testEqualContents {
assertion = "substitute-single-replace";
actual = substituteSilent {
src = builtins.toFile "source" ''
Hello world!
'';
replacements = [
"--replace-fail" "world" "paul"
];
};
expected = builtins.toFile "expected" ''
Hello paul!
'';
};
legacyString = testers.testEqualContents {
assertion = "substitute-string";
actual = substituteSilent {
src = builtins.toFile "source" ''
Hello world!
'';
# Not great that this works at all, but is supported
replacements = "--replace-fail world string";
};
expected = builtins.toFile "expected" ''
Hello string!
'';
};
legacySingleArg = testers.testEqualContents {
assertion = "substitute-single-arg";
actual = substituteSilent {
src = builtins.toFile "source" ''
Hello world!
'';
# Not great that this works at all, but is supported
replacements = [
"--replace-fail world list"
];
};
expected = builtins.toFile "expected" ''
Hello list!
'';
};
legacyVar = testers.testEqualContents {
assertion = "substitute-var";
actual = substituteSilent {
src = builtins.toFile "source" ''
@greeting@ @name@!
'';
# Not great that this works at all, but is supported
replacements = [
"--subst-var name"
"--subst-var-by greeting Yo"
];
name = "peter";
};
expected = builtins.toFile "expected" ''
Yo peter!
'';
};
}