about summary refs log tree commit diff
path: root/lib
diff options
context:
space:
mode:
authorSilvan Mosberger <contact@infinisil.com>2020-01-27 23:03:38 +0100
committerSilvan Mosberger <contact@infinisil.com>2020-03-30 01:15:30 +0200
commit4b206ac83ba23e44231088b1d5f23d96adbced05 (patch)
tree28d473e718049da788322588e477c869ce82fc48 /lib
parent5e46d5a7b59d69e7b86239195f58d26277ae0370 (diff)
downloadnixlib-4b206ac83ba23e44231088b1d5f23d96adbced05.tar
nixlib-4b206ac83ba23e44231088b1d5f23d96adbced05.tar.gz
nixlib-4b206ac83ba23e44231088b1d5f23d96adbced05.tar.bz2
nixlib-4b206ac83ba23e44231088b1d5f23d96adbced05.tar.lz
nixlib-4b206ac83ba23e44231088b1d5f23d96adbced05.tar.xz
nixlib-4b206ac83ba23e44231088b1d5f23d96adbced05.tar.zst
nixlib-4b206ac83ba23e44231088b1d5f23d96adbced05.zip
lib/strings: Add sanitizeDerivationName function
Diffstat (limited to 'lib')
-rw-r--r--lib/attrsets.nix4
-rw-r--r--lib/strings.nix32
-rw-r--r--lib/tests/misc.nix42
3 files changed, 76 insertions, 2 deletions
diff --git a/lib/attrsets.nix b/lib/attrsets.nix
index 32994432d53d..d76e361aedff 100644
--- a/lib/attrsets.nix
+++ b/lib/attrsets.nix
@@ -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
 
@@ -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;
diff --git a/lib/strings.nix b/lib/strings.nix
index 6dbb3d3a3e8b..6ba000987548 100644
--- a/lib/strings.nix
+++ b/lib/strings.nix
@@ -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)
+  ];
+
 }
diff --git a/lib/tests/misc.nix b/lib/tests/misc.nix
index 59ed1e507e24..c1b2f738ead7 100644
--- a/lib/tests/misc.nix
+++ b/lib/tests/misc.nix
@@ -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 {
 
 
@@ -478,4 +495,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";
+  };
 }