about summary refs log tree commit diff
path: root/nixpkgs/lib
diff options
context:
space:
mode:
authorAlyssa Ross <hi@alyssa.is>2020-04-27 21:04:56 +0000
committerAlyssa Ross <hi@alyssa.is>2020-04-27 21:04:56 +0000
commita4e6c7d26af697f4346cacb7ab18dcd7fcfc056e (patch)
tree47950e79183035018882419c4eff5047d1537b99 /nixpkgs/lib
parent5b00523fb58512232b819a301c4309f579c7f09c (diff)
parent22a3bf9fb9edad917fb6cd1066d58b5e426ee975 (diff)
downloadnixlib-a4e6c7d26af697f4346cacb7ab18dcd7fcfc056e.tar
nixlib-a4e6c7d26af697f4346cacb7ab18dcd7fcfc056e.tar.gz
nixlib-a4e6c7d26af697f4346cacb7ab18dcd7fcfc056e.tar.bz2
nixlib-a4e6c7d26af697f4346cacb7ab18dcd7fcfc056e.tar.lz
nixlib-a4e6c7d26af697f4346cacb7ab18dcd7fcfc056e.tar.xz
nixlib-a4e6c7d26af697f4346cacb7ab18dcd7fcfc056e.tar.zst
nixlib-a4e6c7d26af697f4346cacb7ab18dcd7fcfc056e.zip
Merge commit '22a3bf9fb9edad917fb6cd1066d58b5e426ee975'
Diffstat (limited to 'nixpkgs/lib')
-rw-r--r--nixpkgs/lib/attrsets.nix4
-rw-r--r--nixpkgs/lib/default.nix2
-rw-r--r--nixpkgs/lib/deprecated.nix1
-rw-r--r--nixpkgs/lib/licenses.nix70
-rw-r--r--nixpkgs/lib/options.nix9
-rw-r--r--nixpkgs/lib/strings.nix47
-rw-r--r--nixpkgs/lib/tests/maintainers.nix75
-rw-r--r--nixpkgs/lib/tests/misc.nix42
-rwxr-xr-xnixpkgs/lib/tests/modules.sh5
-rw-r--r--nixpkgs/lib/tests/release.nix8
10 files changed, 224 insertions, 39 deletions
diff --git a/nixpkgs/lib/attrsets.nix b/nixpkgs/lib/attrsets.nix
index 72430522f7d8..7d84c25de77a 100644
--- a/nixpkgs/lib/attrsets.nix
+++ b/nixpkgs/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/nixpkgs/lib/default.nix b/nixpkgs/lib/default.nix
index a909cefd60f1..d00c4abec0a9 100644
--- a/nixpkgs/lib/default.nix
+++ b/nixpkgs/lib/default.nix
@@ -141,7 +141,7 @@ let
       mergeAttrsWithFunc mergeAttrsConcatenateValues
       mergeAttrsNoOverride mergeAttrByFunc mergeAttrsByFuncDefaults
       mergeAttrsByFuncDefaultsClean mergeAttrBy
-      fakeSha256 fakeSha512
+      fakeSri fakeSha256 fakeSha512
       nixType imap;
     inherit (versions)
       splitVersion;
diff --git a/nixpkgs/lib/deprecated.nix b/nixpkgs/lib/deprecated.nix
index 155d6f0c3611..8c4fe9c390c6 100644
--- a/nixpkgs/lib/deprecated.nix
+++ b/nixpkgs/lib/deprecated.nix
@@ -272,6 +272,7 @@ rec {
   imap = imap1;
 
   # Fake hashes. Can be used as hash placeholders, when computing hash ahead isn't trivial
+  fakeSri = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
   fakeSha256 = "0000000000000000000000000000000000000000000000000000000000000000";
   fakeSha512 = "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
 }
diff --git a/nixpkgs/lib/licenses.nix b/nixpkgs/lib/licenses.nix
index e37eb57cff97..a4ac08bb20e9 100644
--- a/nixpkgs/lib/licenses.nix
+++ b/nixpkgs/lib/licenses.nix
@@ -2,7 +2,7 @@
 let
 
   spdx = lic: lic // {
-    url = "http://spdx.org/licenses/${lic.spdxId}.html";
+    url = "https://spdx.org/licenses/${lic.spdxId}.html";
   };
 
 in
@@ -40,13 +40,13 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
 
   amazonsl = {
     fullName = "Amazon Software License";
-    url = http://aws.amazon.com/asl/;
+    url = "https://aws.amazon.com/asl/";
     free = false;
   };
 
   amd = {
     fullName = "AMD License Agreement";
-    url = http://developer.amd.com/amd-license-agreement/;
+    url = "https://developer.amd.com/amd-license-agreement/";
     free = false;
   };
 
@@ -57,7 +57,7 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
 
   arphicpl = {
     fullName = "Arphic Public License";
-    url = https://www.freedesktop.org/wiki/Arphic_Public_License/;
+    url = "https://www.freedesktop.org/wiki/Arphic_Public_License/";
   };
 
   artistic1 = spdx {
@@ -107,7 +107,7 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
 
   bsl11 = {
     fullName = "Business Source License 1.1";
-    url = https://mariadb.com/bsl11;
+    url = "https://mariadb.com/bsl11";
     free = false;
   };
 
@@ -230,7 +230,7 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
 
   eapl = {
     fullName = "EPSON AVASYS PUBLIC LICENSE";
-    url = http://avasys.jp/hp/menu000000700/hpg000000603.htm;
+    url = "https://avasys.jp/hp/menu000000700/hpg000000603.htm";
     free = false;
   };
 
@@ -246,7 +246,7 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
 
   elastic = {
     fullName = "ELASTIC LICENSE";
-    url = https://github.com/elastic/elasticsearch/blob/master/licenses/ELASTIC-LICENSE.txt;
+    url = "https://github.com/elastic/elasticsearch/blob/master/licenses/ELASTIC-LICENSE.txt";
     free = false;
   };
 
@@ -262,7 +262,7 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
 
   epson = {
     fullName = "Seiko Epson Corporation Software License Agreement for Linux";
-    url = https://download.ebz.epson.net/dsc/du/02/eula/global/LINUX_EN.html;
+    url = "https://download.ebz.epson.net/dsc/du/02/eula/global/LINUX_EN.html";
     free = false;
   };
 
@@ -271,6 +271,11 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
     fullName = "European Union Public License 1.1";
   };
 
+  eupl12 = spdx {
+    spdxId = "EUPL-1.2";
+    fullName = "European Union Public License 1.2";
+  };
+
   fdl12 = spdx {
     spdxId = "GFDL-1.2-only";
     fullName = "GNU Free Documentation License v1.2 only";
@@ -293,7 +298,7 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
 
   ffsl = {
     fullName = "Floodgap Free Software License";
-    url = http://www.floodgap.com/software/ffsl/license.html;
+    url = "https://www.floodgap.com/software/ffsl/license.html";
     free = false;
   };
 
@@ -303,12 +308,12 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
 
   g4sl = {
     fullName = "Geant4 Software License";
-    url = https://geant4.web.cern.ch/geant4/license/LICENSE.html;
+    url = "https://geant4.web.cern.ch/geant4/license/LICENSE.html";
   };
 
   geogebra = {
     fullName = "GeoGebra Non-Commercial License Agreement";
-    url = https://www.geogebra.org/license;
+    url = "https://www.geogebra.org/license";
     free = false;
   };
 
@@ -334,12 +339,12 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
 
   gpl2ClasspathPlus = {
     fullName = "GNU General Public License v2.0 or later (with Classpath exception)";
-    url = https://fedoraproject.org/wiki/Licensing/GPL_Classpath_Exception;
+    url = "https://fedoraproject.org/wiki/Licensing/GPL_Classpath_Exception";
   };
 
   gpl2Oss = {
     fullName = "GNU General Public License version 2 only (with OSI approved licenses linking exception)";
-    url = https://www.mysql.com/about/legal/licensing/foss-exception;
+    url = "https://www.mysql.com/about/legal/licensing/foss-exception";
   };
 
   gpl2Plus = spdx {
@@ -359,7 +364,7 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
 
   gpl3ClasspathPlus = {
     fullName = "GNU General Public License v3.0 or later (with Classpath exception)";
-    url = https://fedoraproject.org/wiki/Licensing/GPL_Classpath_Exception;
+    url = "https://fedoraproject.org/wiki/Licensing/GPL_Classpath_Exception";
   };
 
   hpnd = spdx {
@@ -370,7 +375,7 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
   # Intel's license, seems free
   iasl = {
     fullName = "iASL";
-    url = http://www.calculate-linux.org/packages/licenses/iASL;
+    url = "https://old.calculate-linux.org/packages/licenses/iASL";
   };
 
   ijg = spdx {
@@ -385,13 +390,13 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
 
   inria-compcert = {
     fullName  = "INRIA Non-Commercial License Agreement for the CompCert verified compiler";
-    url       = "http://compcert.inria.fr/doc/LICENSE";
+    url       = "http://compcert.inria.fr/doc/LICENSE"; # https is broken
     free      = false;
   };
 
   inria-icesl = {
     fullName = "INRIA Non-Commercial License Agreement for IceSL";
-    url      = "http://shapeforge.loria.fr/icesl/EULA_IceSL_binary.pdf";
+    url      = "http://shapeforge.loria.fr/icesl/EULA_IceSL_binary.pdf"; # https is broken
     free     = false;
   };
 
@@ -413,7 +418,7 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
   # Proprietary binaries; free to redistribute without modification.
   issl = {
     fullName = "Intel Simplified Software License";
-    url = https://software.intel.com/en-us/license/intel-simplified-software-license;
+    url = "https://software.intel.com/en-us/license/intel-simplified-software-license";
     free = false;
   };
 
@@ -469,7 +474,7 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
 
   llgpl21 = {
     fullName = "Lisp LGPL; GNU Lesser General Public License version 2.1 with Franz Inc. preamble for clarification of LGPL terms in context of Lisp";
-    url = http://opensource.franz.com/preamble.html;
+    url = "https://opensource.franz.com/preamble.html";
   };
 
   lppl12 = spdx {
@@ -489,11 +494,11 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
 
   miros = {
     fullName = "MirOS License";
-    url = https://opensource.org/licenses/MirOS;
+    url = "https://opensource.org/licenses/MirOS";
   };
 
   # spdx.org does not (yet) differentiate between the X11 and Expat versions
-  # for details see http://en.wikipedia.org/wiki/MIT_License#Various_versions
+  # for details see https://en.wikipedia.org/wiki/MIT_License#Various_versions
   mit = spdx {
     spdxId = "MIT";
     fullName = "MIT License";
@@ -589,14 +594,14 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
 
   postman = {
     fullName = "Postman EULA";
-    url = https://www.getpostman.com/licenses/postman_base_app;
+    url = "https://www.getpostman.com/licenses/postman_base_app";
     free = false;
   };
 
   psfl = spdx {
     spdxId = "Python-2.0";
     fullName = "Python Software Foundation License version 2";
-    #url = http://docs.python.org/license.html;
+    url = "https://docs.python.org/license.html";
   };
 
   publicDomain = {
@@ -605,7 +610,7 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
 
   purdueBsd = {
     fullName = " Purdue BSD-Style License"; # also know as lsof license
-    url = https://enterprise.dejacode.com/licenses/public/purdue-bsd;
+    url = "https://enterprise.dejacode.com/licenses/public/purdue-bsd";
   };
 
   qhull = spdx {
@@ -620,7 +625,7 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
 
   qwt = {
     fullName = "Qwt License, Version 1.0";
-    url = http://qwt.sourceforge.net/qwtlicense.html;
+    url = "https://qwt.sourceforge.io/qwtlicense.html";
   };
 
   ruby = spdx {
@@ -646,13 +651,13 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
   smail = {
     shortName = "smail";
     fullName = "SMAIL General Public License";
-    url = http://metadata.ftp-master.debian.org/changelogs/main/d/debianutils/debianutils_4.8.1_copyright;
+    url = "https://sources.debian.org/copyright/license/debianutils/4.9.1/";
   };
 
   sspl = {
     shortName = "SSPL";
     fullName = "Server Side Public License";
-    url = https://www.mongodb.com/licensing/server-side-public-license;
+    url = "https://www.mongodb.com/licensing/server-side-public-license";
     free = false;
   };
 
@@ -663,7 +668,7 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
 
   ufl = {
     fullName = "Ubuntu Font License 1.0";
-    url = http://font.ubuntu.com/ufl/ubuntu-font-licence-1.0.txt;
+    url = "https://ubuntu.com/legal/font-licence";
   };
 
   unfree = {
@@ -682,6 +687,11 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
     # channel and NixOS images.
   };
 
+  unicode-dfs-2016 = spdx {
+    spdxId = "Unicode-DFS-2016";
+    fullName = "Unicode License Agreement - Data Files and Software (2016)";
+  };
+
   unlicense = spdx {
     spdxId = "Unlicense";
     fullName = "The Unlicense";
@@ -720,7 +730,7 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
 
   wadalab = {
     fullName = "Wadalab Font License";
-    url = https://fedoraproject.org/wiki/Licensing:Wadalab?rd=Licensing/Wadalab;
+    url = "https://fedoraproject.org/wiki/Licensing:Wadalab?rd=Licensing/Wadalab";
   };
 
   wtfpl = spdx {
@@ -735,7 +745,7 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
 
   xfig = {
     fullName = "xfig";
-    url = "http://mcj.sourceforge.net/authors.html#xfig";
+    url = "http://mcj.sourceforge.net/authors.html#xfig"; # https is broken
   };
 
   zlib = spdx {
diff --git a/nixpkgs/lib/options.nix b/nixpkgs/lib/options.nix
index 71481c9250ab..38f4f1329f21 100644
--- a/nixpkgs/lib/options.nix
+++ b/nixpkgs/lib/options.nix
@@ -191,7 +191,14 @@ rec {
 
      Example:
        (showOption ["foo" "bar" "baz"]) == "foo.bar.baz"
-       (showOption ["foo" "bar.baz" "tux"]) == "foo.\"bar.baz\".tux"
+       (showOption ["foo" "bar.baz" "tux"]) == "foo.bar.baz.tux"
+
+     Placeholders will not be quoted as they are not actual values:
+       (showOption ["foo" "*" "bar"]) == "foo.*.bar"
+       (showOption ["foo" "<name>" "bar"]) == "foo.<name>.bar"
+
+     Unlike attributes, options can also start with numbers:
+       (showOption ["windowManager" "2bwm" "enable"]) == "windowManager.2bwm.enable"
   */
   showOption = parts: let
     escapeOptionPart = part:
diff --git a/nixpkgs/lib/strings.nix b/nixpkgs/lib/strings.nix
index 4f9509ffe7c0..74e3eaa0722d 100644
--- a/nixpkgs/lib/strings.nix
+++ b/nixpkgs/lib/strings.nix
@@ -315,6 +315,21 @@ rec {
   */
   escapeNixString = s: escape ["$"] (builtins.toJSON s);
 
+  /* Quotes a string if it can't be used as an identifier directly.
+
+     Type: string -> string
+
+     Example:
+       escapeNixIdentifier "hello"
+       => "hello"
+       escapeNixIdentifier "0abc"
+       => "\"0abc\""
+  */
+  escapeNixIdentifier = s:
+    # Regex from https://github.com/NixOS/nix/blob/d048577909e383439c2549e849c5c2f2016c997e/src/libexpr/lexer.l#L91
+    if builtins.match "[a-zA-Z_][a-zA-Z0-9_'-]*" s != null
+    then s else escapeNixString s;
+
   # Obsolete - use replaceStrings instead.
   replaceChars = builtins.replaceStrings or (
     del: new: s:
@@ -678,4 +693,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/nixpkgs/lib/tests/maintainers.nix b/nixpkgs/lib/tests/maintainers.nix
new file mode 100644
index 000000000000..60d296eecae6
--- /dev/null
+++ b/nixpkgs/lib/tests/maintainers.nix
@@ -0,0 +1,75 @@
+# to run these tests:
+# nix-build nixpkgs/lib/tests/maintainers.nix
+# If nothing is output, all tests passed
+{ pkgs ? import ../.. {} }:
+
+let
+  inherit (pkgs) lib;
+  inherit (lib) types;
+
+  maintainerModule = { config, ... }: {
+    options = {
+      name = lib.mkOption {
+        type = types.str;
+      };
+      email = lib.mkOption {
+        type = types.str;
+      };
+      github = lib.mkOption {
+        type = types.nullOr types.str;
+        default = null;
+      };
+      githubId = lib.mkOption {
+        type = types.nullOr types.ints.unsigned;
+        default = null;
+      };
+      keys = lib.mkOption {
+        type = types.listOf (types.submodule {
+          options.longkeyid = lib.mkOption { type = types.str; };
+          options.fingerprint = lib.mkOption { type = types.str; };
+        });
+        default = [];
+      };
+    };
+  };
+
+  checkMaintainer = handle: uncheckedAttrs:
+  let
+      prefix = [ "lib" "maintainers" handle ];
+      checkedAttrs = (lib.modules.evalModules {
+        inherit prefix;
+        modules = [
+          maintainerModule
+          {
+            _file = toString ../../maintainers/maintainer-list.nix;
+            config = uncheckedAttrs;
+          }
+        ];
+      }).config;
+
+      checkGithubId = lib.optional (checkedAttrs.github != null && checkedAttrs.githubId == null) ''
+        echo ${lib.escapeShellArg (lib.showOption prefix)}': If `github` is specified, `githubId` must be too.'
+        # Calling this too often would hit non-authenticated API limits, but this
+        # shouldn't happen since such errors will get fixed rather quickly
+        info=$(curl -sS https://api.github.com/users/${checkedAttrs.github})
+        id=$(jq -r '.id' <<< "$info")
+        echo "The GitHub ID for GitHub user ${checkedAttrs.github} is $id:"
+        echo -e "    githubId = $id;\n"
+      '';
+    in lib.deepSeq checkedAttrs checkGithubId;
+
+  missingGithubIds = lib.concatLists (lib.mapAttrsToList checkMaintainer lib.maintainers);
+
+  success = pkgs.runCommandNoCC "checked-maintainers-success" {} ">$out";
+
+  failure = pkgs.runCommandNoCC "checked-maintainers-failure" {
+    nativeBuildInputs = [ pkgs.curl pkgs.jq ];
+    outputHash = "sha256:${lib.fakeSha256}";
+    outputHAlgo = "sha256";
+    outputHashMode = "flat";
+    SSL_CERT_FILE = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
+  } ''
+    ${lib.concatStringsSep "\n" missingGithubIds}
+    exit 1
+  '';
+in if missingGithubIds == [] then success else failure
diff --git a/nixpkgs/lib/tests/misc.nix b/nixpkgs/lib/tests/misc.nix
index 739c5d5fe15d..36ddd186d7b7 100644
--- a/nixpkgs/lib/tests/misc.nix
+++ b/nixpkgs/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 {
 
 
@@ -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";
+  };
 }
diff --git a/nixpkgs/lib/tests/modules.sh b/nixpkgs/lib/tests/modules.sh
index e81cf016ee9a..6258244457aa 100755
--- a/nixpkgs/lib/tests/modules.sh
+++ b/nixpkgs/lib/tests/modules.sh
@@ -3,7 +3,10 @@
 # This script is used to test that the module system is working as expected.
 # By default it test the version of nixpkgs which is defined in the NIX_PATH.
 
-cd ./modules
+# https://stackoverflow.com/a/246128/6605742
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
+
+cd "$DIR"/modules
 
 pass=0
 fail=0
diff --git a/nixpkgs/lib/tests/release.nix b/nixpkgs/lib/tests/release.nix
index 069c015d783a..ec0f9c32d3f7 100644
--- a/nixpkgs/lib/tests/release.nix
+++ b/nixpkgs/lib/tests/release.nix
@@ -1,7 +1,7 @@
-{ pkgs ? import ((import ../.).cleanSource ../..) {} }:
+{ pkgs ? import ../.. {} }:
 
 pkgs.runCommandNoCC "nixpkgs-lib-tests" {
-  buildInputs = [ pkgs.nix (import ./check-eval.nix) ];
+  buildInputs = [ pkgs.nix (import ./check-eval.nix) (import ./maintainers.nix { inherit pkgs; }) ];
   NIX_PATH = "nixpkgs=${toString pkgs.path}";
 } ''
     datadir="${pkgs.nix}/share"
@@ -17,8 +17,8 @@ pkgs.runCommandNoCC "nixpkgs-lib-tests" {
     cacheDir=$TEST_ROOT/binary-cache
     nix-store --init
 
-    cd ${pkgs.path}/lib/tests
-    bash ./modules.sh
+    cp -r ${../.} lib
+    bash lib/tests/modules.sh
 
     touch $out
 ''