Skip to content

Commit

Permalink
Merge pull request #83241 from Infinisil/valid-drv-name
Browse files Browse the repository at this point in the history
lib/strings: Add `sanitizeDerivationName` function
  • Loading branch information
infinisil committed Apr 2, 2020
2 parents 783da8c + 4b206ac commit f75c11c
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 2 deletions.
4 changes: 2 additions & 2 deletions lib/attrsets.nix
Expand Up @@ -4,7 +4,7 @@
let
inherit (builtins) head tail length;
inherit (lib.trivial) and;
inherit (lib.strings) concatStringsSep;
inherit (lib.strings) concatStringsSep sanitizeDerivationName;
inherit (lib.lists) fold concatMap concatLists;
in

Expand Down Expand Up @@ -310,7 +310,7 @@ rec {
path' = builtins.storePath path;
res =
{ type = "derivation";
name = builtins.unsafeDiscardStringContext (builtins.substring 33 (-1) (baseNameOf path'));
name = sanitizeDerivationName (builtins.substring 33 (-1) (baseNameOf path'));
outPath = path';
outputs = [ "out" ];
out = res;
Expand Down
32 changes: 32 additions & 0 deletions lib/strings.nix
Expand Up @@ -678,4 +678,36 @@ rec {
=> "1.0"
*/
fileContents = file: removeSuffix "\n" (builtins.readFile file);


/* Creates a valid derivation name from a potentially invalid one.
Type: sanitizeDerivationName :: String -> String
Example:
sanitizeDerivationName "../hello.bar # foo"
=> "-hello.bar-foo"
sanitizeDerivationName ""
=> "unknown"
sanitizeDerivationName pkgs.hello
=> "-nix-store-2g75chlbpxlrqn15zlby2dfh8hr9qwbk-hello-2.10"
*/
sanitizeDerivationName = string: lib.pipe string [
# Get rid of string context. This is safe under the assumption that the
# resulting string is only used as a derivation name
builtins.unsafeDiscardStringContext
# Strip all leading "."
(x: builtins.elemAt (builtins.match "\\.*(.*)" x) 0)
# Split out all invalid characters
# https://github.com/NixOS/nix/blob/2.3.2/src/libstore/store-api.cc#L85-L112
# https://github.com/NixOS/nix/blob/2242be83c61788b9c0736a92bb0b5c7bbfc40803/nix-rust/src/store/path.rs#L100-L125
(builtins.split "[^[:alnum:]+._?=-]+")
# Replace invalid character ranges with a "-"
(concatMapStrings (s: if lib.isList s then "-" else s))
# Limit to 211 characters (minus 4 chars for ".drv")
(x: substring (lib.max (stringLength x - 207) 0) (-1) x)
# If the result is empty, replace it with "unknown"
(x: if stringLength x == 0 then "unknown" else x)
];

}
42 changes: 42 additions & 0 deletions lib/tests/misc.nix
Expand Up @@ -3,6 +3,23 @@
# if the resulting list is empty, all tests passed
with import ../default.nix;

let

testSanitizeDerivationName = { name, expected }:
let
drv = derivation {
name = strings.sanitizeDerivationName name;
builder = "x";
system = "x";
};
in {
# Evaluate the derivation so an invalid name would be caught
expr = builtins.seq drv.drvPath drv.name;
inherit expected;
};

in

runTests {


Expand Down Expand Up @@ -490,4 +507,29 @@ runTests {

expected = "'-X' 'PUT' '--data' '{\"id\":0}' '--retry' '3' '--url' 'https://example.com/foo' '--url' 'https://example.com/bar' '--verbose'";
};

testSanitizeDerivationNameLeadingDots = testSanitizeDerivationName {
name = "..foo";
expected = "foo";
};

testSanitizeDerivationNameAscii = testSanitizeDerivationName {
name = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
expected = "-+--.-0123456789-=-?-ABCDEFGHIJKLMNOPQRSTUVWXYZ-_-abcdefghijklmnopqrstuvwxyz-";
};

testSanitizeDerivationNameTooLong = testSanitizeDerivationName {
name = "This string is loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong";
expected = "loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong";
};

testSanitizeDerivationNameTooLongWithInvalid = testSanitizeDerivationName {
name = "Hello there aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa &&&&&&&&";
expected = "there-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-";
};

testSanitizeDerivationNameEmpty = testSanitizeDerivationName {
name = "";
expected = "unknown";
};
}

0 comments on commit f75c11c

Please sign in to comment.