about summary refs log tree commit diff
path: root/nixpkgs/pkgs/test
diff options
context:
space:
mode:
Diffstat (limited to 'nixpkgs/pkgs/test')
-rw-r--r--nixpkgs/pkgs/test/auto-patchelf-hook/default.nix6
-rw-r--r--nixpkgs/pkgs/test/auto-patchelf-hook/package.nix96
-rw-r--r--nixpkgs/pkgs/test/checkpointBuild/default.nix4
-rw-r--r--nixpkgs/pkgs/test/cuda/cuda-library-samples/extension.nix14
-rw-r--r--nixpkgs/pkgs/test/cuda/cuda-library-samples/generic.nix85
-rw-r--r--nixpkgs/pkgs/test/cuda/cuda-samples/extension.nix42
-rw-r--r--nixpkgs/pkgs/test/cuda/cuda-samples/generic.nix79
-rw-r--r--nixpkgs/pkgs/test/cuda/default.nix77
-rw-r--r--nixpkgs/pkgs/test/default.nix5
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/README.md27
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/default.nix59
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/scripts/README.md26
-rwxr-xr-xnixpkgs/pkgs/test/nixpkgs-check-by-name/scripts/fetch-tool.sh47
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/scripts/pinned-tool.json4
-rwxr-xr-xnixpkgs/pkgs/test/nixpkgs-check-by-name/scripts/run-local.sh19
-rwxr-xr-xnixpkgs/pkgs/test/nixpkgs-check-by-name/scripts/update-pinned-tool.sh40
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/src/eval.nix141
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/src/eval.rs292
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/src/main.rs62
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/src/nixpkgs_problem.rs53
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/src/ratchet.rs141
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/src/references.rs33
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/src/utils.rs4
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/aliases/aliases.nix3
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/aliases/all-packages.nix3
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/aliases/default.nix1
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/aliases/pkgs/by-name/fo/foo/package.nix (renamed from nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/ref-parse-failure/pkgs/by-name/aa/aa/package.nix)0
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/broken-autocall/default.nix2
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/empty-base/default.nix1
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/empty-base/pkgs/by-name/README.md0
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/incorrect-shard/default.nix2
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/internalCallPackage/all-packages.nix3
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/internalCallPackage/default.nix1
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/internalCallPackage/foo.nix1
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/internalCallPackage/pkgs/by-name/README.md0
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/invalid-package-name/default.nix2
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/invalid-shard-name/default.nix2
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/missing-package-nix/default.nix2
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/mock-nixpkgs.nix35
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/all-packages.nix10
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/base/default.nix1
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/base/pkgs/by-name/fo/foo1/package.nix1
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/base/pkgs/by-name/fo/foo2/package.nix1
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/base/pkgs/by-name/fo/foo3/package.nix1
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/base/pkgs/by-name/fo/foo4/package.nix1
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/default.nix1
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/expected4
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/pkgs/by-name/README.md0
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/with-config.nix1
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/without-config.nix1
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/multiple-failures/default.nix1
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/multiple-failures/expected13
l---------nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/multiple-failures/pkgs/by-name/A/fo@/foo1
l---------nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/multiple-failures/pkgs/by-name/A/fo@/package.nix1
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/multiple-failures/pkgs/by-name/aa0
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/multiple-failures/pkgs/by-name/ba/bar0
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/multiple-failures/pkgs/by-name/ba/baz/package.nix/default.nix1
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/multiple-failures/pkgs/by-name/ba/foo/package.nix6
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/multiple-failures/pkgs/by-name/fo/foo/.git-keep0
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/multiple-failures/someDrv.nix1
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/all-packages.nix11
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/base/all-packages.nix5
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/base/default.nix1
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/base/pkgs/by-name/README.md0
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/default.nix1
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/expected4
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/pkgs/by-name/README.md0
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/with-config.nix1
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/without-config.nix1
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/no-by-name/default.nix2
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/no-eval/all-packages.nix3
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/no-eval/default.nix1
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/no-eval/pkgs/by-name/fo/foo/package.nix1
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/non-attrs/default.nix2
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/non-derivation/default.nix2
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/one-letter/default.nix2
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/only-callPackage-derivations/all-packages.nix16
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/only-callPackage-derivations/default.nix1
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/only-callPackage-derivations/pkgs/by-name/README.md0
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/override-different-file/default.nix2
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/override-empty-arg-gradual/base/default.nix2
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/override-empty-arg-gradual/default.nix2
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/override-empty-arg/base/default.nix2
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/override-empty-arg/default.nix2
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/override-no-call-package/default.nix2
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/override-no-file/default.nix2
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/override-success/default.nix2
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/package-dir-is-file/default.nix2
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/package-nix-dir/default.nix2
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/ref-absolute/default.nix2
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/ref-escape/default.nix2
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/ref-nix-path/default.nix2
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/ref-parse-failure/default.nix1
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/ref-parse-failure/expected1
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/ref-parse-failure/pkgs/by-name/aa/aa/invalid.nix1
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/ref-path-subexpr/default.nix2
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/ref-success/default.nix2
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/shard-file/default.nix2
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/sorted-order/all-packages.nix6
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/sorted-order/default.nix1
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/sorted-order/expected4
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/sorted-order/pkgs/by-name/a/a/package.nix1
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/sorted-order/pkgs/by-name/c/c/package.nix1
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/success/default.nix2
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/symlink-escape/default.nix2
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/symlink-invalid/default.nix2
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/symlink-invalid/expected2
l---------nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/symlink-invalid/pkgs/by-name/fo/foo/foo1
l---------nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/symlink-invalid/pkgs/by-name/fo/foo/foo.nix1
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/uppercase/default.nix2
-rw-r--r--nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/with-readme/default.nix2
-rw-r--r--nixpkgs/pkgs/test/release/default.nix14
112 files changed, 956 insertions, 634 deletions
diff --git a/nixpkgs/pkgs/test/auto-patchelf-hook/default.nix b/nixpkgs/pkgs/test/auto-patchelf-hook/default.nix
new file mode 100644
index 000000000000..6e05e729fba8
--- /dev/null
+++ b/nixpkgs/pkgs/test/auto-patchelf-hook/default.nix
@@ -0,0 +1,6 @@
+{ lib, callPackage }:
+
+lib.recurseIntoAttrs {
+  withStructuredAttrs = callPackage ./package.nix { __structuredAttrs = true; };
+  withoutStructuredAttrs = callPackage ./package.nix { __structuredAttrs = false; };
+}
diff --git a/nixpkgs/pkgs/test/auto-patchelf-hook/package.nix b/nixpkgs/pkgs/test/auto-patchelf-hook/package.nix
new file mode 100644
index 000000000000..be03ee68c039
--- /dev/null
+++ b/nixpkgs/pkgs/test/auto-patchelf-hook/package.nix
@@ -0,0 +1,96 @@
+# This is a test for autoPatchelfHook. To test it, we just need a simple binary
+# which uses the hook. We took the derivation from tonelib-jam, which sounds
+# like a good candidate with a small closure, and trimmed it down.
+
+{ stdenv
+, lib
+, fetchurl
+, autoPatchelfHook
+, dpkg
+, freetype
+, curl
+# This test checks that the behavior of autoPatchelfHook is correct whether
+# __structuredAttrs
+# (https://nixos.org/manual/nix/stable/language/advanced-attributes#adv-attr-structuredAttrs)
+# is set or not. Hence __structuredAttrs is provided as a parameter.
+, __structuredAttrs
+}:
+
+let runtimeDependencies = [
+  (lib.getLib curl)
+  "/some/dep"
+  "/some/other/dep"
+]
+# A dependency with space only works with __structuredAttrs set to true.
+++ lib.lists.optional __structuredAttrs "/some/dep with space";
+in
+
+stdenv.mkDerivation {
+  name = "auto-patchelf-test";
+
+  src = fetchurl {
+    url = "https://tonelib.net/download/221222/ToneLib-Jam-amd64.deb";
+    sha256 = "sha256-c6At2lRPngQPpE7O+VY/Hsfw+QfIb3COIuHfbqqIEuM=";
+  };
+
+  unpackCmd = ''
+    dpkg -x $curSrc source
+  '';
+
+  nativeBuildInputs = [
+    dpkg
+    autoPatchelfHook
+  ];
+
+  installPhase = ''
+    mv usr $out
+  '';
+
+  buildInputs = [
+    freetype
+  ];
+
+  autoPatchelfIgnoreMissingDeps = [
+    "libGL.so.1"
+    "libasound.so.2"
+  ];
+
+  inherit runtimeDependencies;
+
+  # Additional phase performing the actual test.
+  installCheckPhase =
+    let allDeps = runtimeDependencies ++ [ (lib.getLib freetype) ];
+    in
+    ''
+      local binary="$out/bin/ToneLib-Jam"
+      local interpreter=$(patchelf --print-interpreter $binary)
+      local runpath=$(patchelf --print-rpath $binary)
+      local glibcStorePath="${stdenv.cc.libc}"
+
+      # Check that the glibc path is a prefix of the interpreter. If
+      # autoPatchelfHook ran correctly, the binary should have set the interpreter
+      # to point to the store.
+      echo "[auto-patchelf-hook-test]: Check that the interpreter is in the store"
+      test "''${interpreter#$glibcStorePath}" != "$interpreter"
+
+      readarray -td':' runpathArray < <(echo -n "$runpath")
+
+      echo "[auto-patchelf-hook-test]: Check that the runpath has the right number of entries"
+      test "''${#runpathArray[@]}" -eq ${builtins.toString (builtins.length allDeps)}
+
+      echo "[auto-patchelf-hook-test]: Check that the runpath contains the expected runtime deps"
+    ''
+    + lib.strings.concatStringsSep "\n"
+      (lib.lists.imap0
+        (i: path:
+          let iAsStr = builtins.toString i; in
+          ''
+            echo "[auto-patchelf-hook-test]: Check that entry ${iAsStr} is ${path}"
+            test "''${paths[${iAsStr}]}" = "$path"
+          '')
+        allDeps
+      );
+
+  doInstallCheck = true;
+  inherit __structuredAttrs;
+}
diff --git a/nixpkgs/pkgs/test/checkpointBuild/default.nix b/nixpkgs/pkgs/test/checkpointBuild/default.nix
index cdcb022086ba..0843dcd3d6eb 100644
--- a/nixpkgs/pkgs/test/checkpointBuild/default.nix
+++ b/nixpkgs/pkgs/test/checkpointBuild/default.nix
@@ -10,7 +10,7 @@ let
       patch -p1 < ${./hello.patch}
     '';
   });
-  checkpointBuiltHello = checkpointBuildTools.mkCheckpointedBuild patchedHello baseHelloArtifacts;
+  checkpointBuiltHello = checkpointBuildTools.mkCheckpointBuild patchedHello baseHelloArtifacts;
 
   checkpointBuiltHelloWithCheck = checkpointBuiltHello.overrideAttrs (old: {
     doCheck = true;
@@ -41,7 +41,7 @@ let
     '';
   });
 
-  checkpointBuiltHelloWithRemovedFile = checkpointBuildTools.mkCheckpointedBuild patchedHelloRemoveFile baseHelloRemoveFileArtifacts;
+  checkpointBuiltHelloWithRemovedFile = checkpointBuildTools.mkCheckpointBuild patchedHelloRemoveFile baseHelloRemoveFileArtifacts;
 in
 stdenv.mkDerivation {
   name = "patched-hello-returns-correct-output";
diff --git a/nixpkgs/pkgs/test/cuda/cuda-library-samples/extension.nix b/nixpkgs/pkgs/test/cuda/cuda-library-samples/extension.nix
deleted file mode 100644
index 62de715fd0b4..000000000000
--- a/nixpkgs/pkgs/test/cuda/cuda-library-samples/extension.nix
+++ /dev/null
@@ -1,14 +0,0 @@
-{hostPlatform, lib}:
-let
-  # Samples are built around the CUDA Toolkit, which is not available for
-  # aarch64. Check for both CUDA version and platform.
-  platformIsSupported = hostPlatform.isx86_64;
-
-  # Build our extension
-  extension =
-    final: _:
-    lib.attrsets.optionalAttrs platformIsSupported {
-      cuda-library-samples = final.callPackage ./generic.nix {};
-    };
-in
-extension
diff --git a/nixpkgs/pkgs/test/cuda/cuda-library-samples/generic.nix b/nixpkgs/pkgs/test/cuda/cuda-library-samples/generic.nix
deleted file mode 100644
index d4182536654e..000000000000
--- a/nixpkgs/pkgs/test/cuda/cuda-library-samples/generic.nix
+++ /dev/null
@@ -1,85 +0,0 @@
-{
-  lib,
-  backendStdenv,
-  fetchFromGitHub,
-  cmake,
-  addOpenGLRunpath,
-  cudatoolkit,
-  cutensor,
-}:
-
-let
-  rev = "5aab680905d853bce0dbad4c488e4f7e9f7b2302";
-  src = fetchFromGitHub {
-    owner = "NVIDIA";
-    repo = "CUDALibrarySamples";
-    inherit rev;
-    sha256 = "0gwgbkq05ygrfgg5hk07lmap7n7ampxv0ha1axrv8qb748ph81xs";
-  };
-  commonAttrs = {
-    version = lib.strings.substring 0 7 rev + "-" + lib.versions.majorMinor cudatoolkit.version;
-    nativeBuildInputs = [
-      cmake
-      addOpenGLRunpath
-    ];
-    buildInputs = [cudatoolkit];
-    postFixup = ''
-      for exe in $out/bin/*; do
-        addOpenGLRunpath $exe
-      done
-    '';
-    meta = {
-      description = "examples of using libraries using CUDA";
-      longDescription = ''
-        CUDA Library Samples contains examples demonstrating the use of
-        features in the math and image processing libraries cuBLAS, cuTENSOR,
-        cuSPARSE, cuSOLVER, cuFFT, cuRAND, NPP and nvJPEG.
-      '';
-      license = lib.licenses.bsd3;
-      maintainers = with lib.maintainers; [obsidian-systems-maintenance] ++ lib.teams.cuda.members;
-    };
-  };
-in
-
-{
-  cublas = backendStdenv.mkDerivation (
-    commonAttrs
-    // {
-      pname = "cuda-library-samples-cublas";
-
-      src = "${src}/cuBLASLt";
-    }
-  );
-
-  cusolver = backendStdenv.mkDerivation (
-    commonAttrs
-    // {
-      pname = "cuda-library-samples-cusolver";
-
-      src = "${src}/cuSOLVER";
-
-      sourceRoot = "cuSOLVER/gesv";
-    }
-  );
-
-  cutensor = backendStdenv.mkDerivation (
-    commonAttrs
-    // {
-      pname = "cuda-library-samples-cutensor";
-
-      src = "${src}/cuTENSOR";
-
-      buildInputs = [cutensor];
-
-      cmakeFlags = ["-DCUTENSOR_EXAMPLE_BINARY_INSTALL_DIR=${builtins.placeholder "out"}/bin"];
-
-      # CUTENSOR_ROOT is double escaped
-      postPatch = ''
-        substituteInPlace CMakeLists.txt \
-          --replace "\''${CUTENSOR_ROOT}/include" "${cutensor.dev}/include"
-      '';
-
-      CUTENSOR_ROOT = cutensor;
-    }
-  );
-}
diff --git a/nixpkgs/pkgs/test/cuda/cuda-samples/extension.nix b/nixpkgs/pkgs/test/cuda/cuda-samples/extension.nix
deleted file mode 100644
index d41da90cd5d0..000000000000
--- a/nixpkgs/pkgs/test/cuda/cuda-samples/extension.nix
+++ /dev/null
@@ -1,42 +0,0 @@
-{
-  cudaVersion,
-  hostPlatform,
-  lib,
-}:
-let
-  cudaVersionToHash = {
-    "10.0" = "sha256-XAI6iiPpDVbZtFoRaP1s6VKpu9aV3bwOqqkw33QncP8=";
-    "10.1" = "sha256-DY8E2FKCFj27jPgQEB1qE9HcLn7CfSiVGdFm+yFQE+k=";
-    "10.2" = "sha256-JDW4i7rC2MwIRvKRmUd6UyJZI9bWNHqZijrB962N4QY=";
-    "11.0" = "sha256-BRwQuUvJEVi1mTbVtGODH8Obt7rXFfq6eLH9wxCTe9g=";
-    "11.1" = "sha256-kM8gFItBaTpkoT34vercmQky9qTFtsXjXMGjCMrsUc4=";
-    "11.2" = "sha256-gX6V98dRwdAQIsvru2byDLiMswCW2lrHSBSJutyWONw=";
-    "11.3" = "sha256-34MdMFS2cufNbZVixFdSUDFfLeuKIGFwLBL9d81acU0=";
-    "11.4" = "sha256-Ewu+Qk6GtGXC37CCn1ZXHc0MQAuyXCGf3J6T4cucTSA=";
-    "11.5" = "sha256-AKRZbke0K59lakhTi8dX2cR2aBuWPZkiQxyKaZTvHrI=";
-    "11.6" = "sha256-AsLNmAplfuQbXg9zt09tXAuFJ524EtTYsQuUlV1tPkE=";
-    # The tag 11.7 of cuda-samples does not exist
-    "11.8" = "sha256-7+1P8+wqTKUGbCUBXGMDO9PkxYr2+PLDx9W2hXtXbuc=";
-    "12.0" = "sha256-Lj2kbdVFrJo5xPYPMiE4BS7Z8gpU5JLKXVJhZABUe/g=";
-    "12.1" = "sha256-xE0luOMq46zVsIEWwK4xjLs7NorcTIi9gbfZPVjIlqo=";
-    "12.2" = "sha256-pOy0qfDjA/Nr0T9PNKKefK/63gQnJV2MQsN2g3S2yng=";
-    "12.3" = "sha256-fjVp0G6uRCWxsfe+gOwWTN+esZfk0O5uxS623u0REAk=";
-  };
-
-  # Samples are built around the CUDA Toolkit, which is not available for
-  # aarch64. Check for both CUDA version and platform.
-  cudaVersionIsSupported = cudaVersionToHash ? ${cudaVersion};
-  platformIsSupported = hostPlatform.isx86_64;
-  isSupported = cudaVersionIsSupported && platformIsSupported;
-
-  # Build our extension
-  extension =
-    final: _:
-    lib.attrsets.optionalAttrs isSupported {
-      cuda-samples = final.callPackage ./generic.nix {
-        inherit cudaVersion;
-        hash = cudaVersionToHash.${cudaVersion};
-      };
-    };
-in
-extension
diff --git a/nixpkgs/pkgs/test/cuda/cuda-samples/generic.nix b/nixpkgs/pkgs/test/cuda/cuda-samples/generic.nix
deleted file mode 100644
index fb3d7cc99da9..000000000000
--- a/nixpkgs/pkgs/test/cuda/cuda-samples/generic.nix
+++ /dev/null
@@ -1,79 +0,0 @@
-{
-  autoAddOpenGLRunpathHook,
-  backendStdenv,
-  cmake,
-  cudatoolkit,
-  cudaVersion,
-  fetchFromGitHub,
-  fetchpatch,
-  freeimage,
-  glfw3,
-  hash,
-  lib,
-  pkg-config,
-}:
-let
-  inherit (lib) lists strings;
-in
-backendStdenv.mkDerivation (
-  finalAttrs: {
-    strictDeps = true;
-
-    pname = "cuda-samples";
-    version = cudaVersion;
-
-    src = fetchFromGitHub {
-      owner = "NVIDIA";
-      repo = finalAttrs.pname;
-      rev = "v${finalAttrs.version}";
-      inherit hash;
-    };
-
-    nativeBuildInputs =
-      [
-        autoAddOpenGLRunpathHook
-        pkg-config
-      ]
-      # CMake has to run as a native, build-time dependency for libNVVM samples.
-      # However, it's not the primary build tool -- that's still make.
-      # As such, we disable CMake's build system.
-      ++ lists.optionals (strings.versionAtLeast finalAttrs.version "12.2") [cmake];
-
-    dontUseCmakeConfigure = true;
-
-    buildInputs = [
-      cudatoolkit
-      freeimage
-      glfw3
-    ];
-
-    # See https://github.com/NVIDIA/cuda-samples/issues/75.
-    patches = lib.optionals (finalAttrs.version == "11.3") [
-      (fetchpatch {
-        url = "https://github.com/NVIDIA/cuda-samples/commit/5c3ec60faeb7a3c4ad9372c99114d7bb922fda8d.patch";
-        hash = "sha256-0XxdmNK9MPpHwv8+qECJTvXGlFxc+fIbta4ynYprfpU=";
-      })
-    ];
-
-    enableParallelBuilding = true;
-
-    preConfigure = ''
-      export CUDA_PATH=${cudatoolkit}
-    '';
-
-    installPhase = ''
-      runHook preInstall
-
-      install -Dm755 -t $out/bin bin/${backendStdenv.hostPlatform.parsed.cpu.name}/${backendStdenv.hostPlatform.parsed.kernel.name}/release/*
-
-      runHook postInstall
-    '';
-
-    meta = {
-      description = "Samples for CUDA Developers which demonstrates features in CUDA Toolkit";
-      # CUDA itself is proprietary, but these sample apps are not.
-      license = lib.licenses.bsd3;
-      maintainers = with lib.maintainers; [obsidian-systems-maintenance] ++ lib.teams.cuda.members;
-    };
-  }
-)
diff --git a/nixpkgs/pkgs/test/cuda/default.nix b/nixpkgs/pkgs/test/cuda/default.nix
index 8431e4b9207d..dd9ad8b814dc 100644
--- a/nixpkgs/pkgs/test/cuda/default.nix
+++ b/nixpkgs/pkgs/test/cuda/default.nix
@@ -1,32 +1,51 @@
-{callPackage}:
+{
+  lib,
+  recurseIntoAttrs,
 
-rec {
-  cuda-samplesPackages = callPackage ./cuda-samples/generic.nix {};
-  inherit (cuda-samplesPackages)
-    cuda-samples_cudatoolkit_10
-    cuda-samples_cudatoolkit_10_0
-    cuda-samples_cudatoolkit_10_1
-    cuda-samples_cudatoolkit_10_2
-    cuda-samples_cudatoolkit_11
-    cuda-samples_cudatoolkit_11_0
-    cuda-samples_cudatoolkit_11_1
-    cuda-samples_cudatoolkit_11_2
-    cuda-samples_cudatoolkit_11_3
-    cuda-samples_cudatoolkit_11_4
-    ;
+  cudaPackages,
+  cudaPackagesGoogle,
 
-  cuda-library-samplesPackages = callPackage ./cuda-library-samples/generic.nix {};
-  inherit (cuda-library-samplesPackages)
-    cuda-library-samples_cudatoolkit_10
-    cuda-library-samples_cudatoolkit_10_1
-    cuda-library-samples_cudatoolkit_10_2
-    cuda-library-samples_cudatoolkit_11
-    cuda-library-samples_cudatoolkit_11_0
-    cuda-library-samples_cudatoolkit_11_1
-    cuda-library-samples_cudatoolkit_11_2
-    cuda-library-samples_cudatoolkit_11_3
-    cuda-library-samples_cudatoolkit_11_4
-    ;
+  cudaPackages_10_0,
+  cudaPackages_10_1,
+  cudaPackages_10_2,
+  cudaPackages_10,
 
-  __attrsFailEvaluation = true;
-}
+  cudaPackages_11_0,
+  cudaPackages_11_1,
+  cudaPackages_11_2,
+  cudaPackages_11_3,
+  cudaPackages_11_4,
+  cudaPackages_11_5,
+  cudaPackages_11_6,
+  cudaPackages_11_7,
+  cudaPackages_11_8,
+  cudaPackages_11,
+
+  cudaPackages_12_0,
+  cudaPackages_12_1,
+  cudaPackages_12_2,
+  cudaPackages_12_3,
+  cudaPackages_12,
+}@args:
+
+let
+  isTest =
+    name: package:
+    builtins.elem (package.pname or null) [
+      "cuda-samples"
+      "cuda-library-samples"
+      "saxpy"
+    ];
+in
+(lib.trivial.pipe args [
+  (lib.filterAttrs (name: _: lib.hasPrefix "cudaPackages" name))
+  (lib.mapAttrs (
+    _: ps:
+    lib.pipe ps [
+      (lib.filterAttrs isTest)
+      (as: as // { __attrsFailEvaluation = true; })
+      recurseIntoAttrs
+    ]
+  ))
+  recurseIntoAttrs
+])
diff --git a/nixpkgs/pkgs/test/default.nix b/nixpkgs/pkgs/test/default.nix
index 1459e9c310da..363b0a2e1519 100644
--- a/nixpkgs/pkgs/test/default.nix
+++ b/nixpkgs/pkgs/test/default.nix
@@ -64,7 +64,6 @@ with pkgs;
             # libcxxStdenv broken
             # fix in https://github.com/NixOS/nixpkgs/pull/216273
           ] ++ lib.optionals (stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isAarch64) [
-            (filterAttrs (n: _: n != "llvmPackages_6"))
             (filterAttrs (n: _: n != "llvmPackages_8"))
             (filterAttrs (n: _: n != "llvmPackages_9"))
             (filterAttrs (n: _: n != "llvmPackages_10"))
@@ -113,7 +112,7 @@ with pkgs;
 
   install-shell-files = callPackage ./install-shell-files {};
 
-  checkpoint-build = callPackage ./checkpointBuild {};
+  checkpointBuildTools = callPackage ./checkpointBuild {};
 
   kernel-config = callPackage ./kernel.nix {};
 
@@ -169,4 +168,6 @@ with pkgs;
   pkgs-lib = recurseIntoAttrs (import ../pkgs-lib/tests { inherit pkgs; });
 
   nixpkgs-check-by-name = callPackage ./nixpkgs-check-by-name { };
+
+  auto-patchelf-hook = callPackage ./auto-patchelf-hook { };
 }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/README.md b/nixpkgs/pkgs/test/nixpkgs-check-by-name/README.md
index 19865ca0952b..1aa256978416 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/README.md
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/README.md
@@ -1,9 +1,13 @@
 # Nixpkgs pkgs/by-name checker
 
 This directory implements a program to check the [validity](#validity-checks) of the `pkgs/by-name` Nixpkgs directory.
-It is being used by [this GitHub Actions workflow](../../../.github/workflows/check-by-name.yml).
 This is part of the implementation of [RFC 140](https://github.com/NixOS/rfcs/pull/140).
 
+A [pinned version](./scripts/pinned-tool.json) of this tool is used by [this GitHub Actions workflow](../../../.github/workflows/check-by-name.yml).
+See [./scripts](./scripts/README.md#update-pinned-toolsh) for how to update the pinned version.
+
+The source of the tool being right inside Nixpkgs allows any Nixpkgs committer to make updates to it.
+
 ## Interface
 
 The interface of the tool is shown with `--help`:
@@ -28,6 +32,8 @@ These checks are performed by this tool:
 - Each package directory must not refer to files outside itself using symlinks or Nix path expressions.
 
 ### Nix evaluation checks
+
+Evaluate Nixpkgs with `system` set to `x86_64-linux` and check that:
 - For each package directory, the `pkgs.${name}` attribute must be defined as `callPackage pkgs/by-name/${shard}/${name}/package.nix args` for some `args`.
 - For each package directory, `pkgs.lib.isDerivation pkgs.${name}` must be `true`.
 
@@ -43,6 +49,8 @@ The current ratchets are:
 
 - New manual definitions of `pkgs.${name}` (e.g. in `pkgs/top-level/all-packages.nix`) with `args = { }`
   (see [nix evaluation checks](#nix-evaluation-checks)) must not be introduced.
+- New top-level packages defined using `pkgs.callPackage` must be defined with a package directory.
+  - Once a top-level package uses `pkgs/by-name`, it also can't be moved back out of it.
 
 ## Development
 
@@ -65,7 +73,7 @@ Tests are declared in [`./tests`](./tests) as subdirectories imitating Nixpkgs w
 - `default.nix`:
   Always contains
   ```nix
-  import ../mock-nixpkgs.nix { root = ./.; }
+  import <test-nixpkgs> { root = ./.; }
   ```
   which makes
   ```
@@ -92,18 +100,3 @@ Tests are declared in [`./tests`](./tests) as subdirectories imitating Nixpkgs w
 - `expected` (optional):
   A file containing the expected standard output.
   The default is expecting an empty standard output.
-
-## Hydra builds
-
-This program will always be available pre-built for `x86_64-linux` on the `nixos-unstable` channel and `nixos-XX.YY` channels.
-This is ensured by including it in the `tested` jobset description in [`nixos/release-combined.nix`](../../../nixos/release-combined.nix).
-
-This allows CI for PRs to development branches `master` and `release-XX.YY` to fetch the pre-built program from the corresponding channel and use that to check the PR. This has the following benefits:
-- It allows CI to check all PRs, even if they would break the CI tooling.
-- It makes the CI check very fast, since no Nix builds need to be done, even for mass rebuilds.
-- It improves security, since we don't have to build potentially untrusted code from PRs.
-  The tool only needs a very minimal Nix evaluation at runtime, which can work with [readonly-mode](https://nixos.org/manual/nix/stable/command-ref/opt-common.html#opt-readonly-mode) and [restrict-eval](https://nixos.org/manual/nix/stable/command-ref/conf-file.html#conf-restrict-eval).
-- It allows anybody to make updates to the tooling and for those updates to be automatically used by CI without needing a separate release mechanism.
-
-The tradeoff is that there's a delay between updates to the tool and those updates being used by CI.
-This needs to be considered when updating the [API](#api).
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/default.nix
index fc24b1fd3398..8836da1f403f 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/default.nix
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/default.nix
@@ -6,13 +6,41 @@
   clippy,
   mkShell,
   makeWrapper,
+  runCommand,
 }:
 let
   runtimeExprPath = ./src/eval.nix;
+  nixpkgsLibPath = ../../../lib;
+  testNixpkgsPath = ./tests/mock-nixpkgs.nix;
+
+  # Needed to make Nix evaluation work inside nix builds
+  initNix = ''
+    export TEST_ROOT=$(pwd)/test-tmp
+    export NIX_CONF_DIR=$TEST_ROOT/etc
+    export NIX_LOCALSTATE_DIR=$TEST_ROOT/var
+    export NIX_LOG_DIR=$TEST_ROOT/var/log/nix
+    export NIX_STATE_DIR=$TEST_ROOT/var/nix
+    export NIX_STORE_DIR=$TEST_ROOT/store
+
+    # Ensure that even if tests run in parallel, we don't get an error
+    # We'd run into https://github.com/NixOS/nix/issues/2706 unless the store is initialised first
+    nix-store --init
+  '';
+
+  fs = lib.fileset;
+
   package =
     rustPlatform.buildRustPackage {
       name = "nixpkgs-check-by-name";
-      src = lib.cleanSource ./.;
+      src = fs.toSource {
+        root = ./.;
+        fileset = fs.unions [
+          ./Cargo.lock
+          ./Cargo.toml
+          ./src
+          ./tests
+        ];
+      };
       cargoLock.lockFile = ./Cargo.lock;
       nativeBuildInputs = [
         nix
@@ -21,19 +49,8 @@ let
         makeWrapper
       ];
       env.NIX_CHECK_BY_NAME_EXPR_PATH = "${runtimeExprPath}";
-      # Needed to make Nix evaluation work inside the nix build
-      preCheck = ''
-        export TEST_ROOT=$(pwd)/test-tmp
-        export NIX_CONF_DIR=$TEST_ROOT/etc
-        export NIX_LOCALSTATE_DIR=$TEST_ROOT/var
-        export NIX_LOG_DIR=$TEST_ROOT/var/log/nix
-        export NIX_STATE_DIR=$TEST_ROOT/var/nix
-        export NIX_STORE_DIR=$TEST_ROOT/store
-
-        # Ensure that even if tests run in parallel, we don't get an error
-        # We'd run into https://github.com/NixOS/nix/issues/2706 unless the store is initialised first
-        nix-store --init
-      '';
+      env.NIX_PATH = "test-nixpkgs=${testNixpkgsPath}:test-nixpkgs/lib=${nixpkgsLibPath}";
+      preCheck = initNix;
       postCheck = ''
         cargo fmt --check
         cargo clippy -- -D warnings
@@ -44,8 +61,22 @@ let
       '';
       passthru.shell = mkShell {
         env.NIX_CHECK_BY_NAME_EXPR_PATH = toString runtimeExprPath;
+        env.NIX_PATH = "test-nixpkgs=${toString testNixpkgsPath}:test-nixpkgs/lib=${toString nixpkgsLibPath}";
         inputsFrom = [ package ];
       };
+
+      # Tests the tool on the current Nixpkgs tree, this is a good sanity check
+      passthru.tests.nixpkgs = runCommand "test-nixpkgs-check-by-name" {
+        nativeBuildInputs = [
+          package
+          nix
+        ];
+        nixpkgsPath = lib.cleanSource ../../..;
+      } ''
+        ${initNix}
+        nixpkgs-check-by-name --base "$nixpkgsPath" "$nixpkgsPath"
+        touch $out
+      '';
     };
 in
 package
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/scripts/README.md b/nixpkgs/pkgs/test/nixpkgs-check-by-name/scripts/README.md
index 41b3012b7d95..ccd4108ea288 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/scripts/README.md
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/scripts/README.md
@@ -1,6 +1,7 @@
 # CI-related Scripts
 
-This directory contains scripts used and related to the CI running the `pkgs/by-name` checks in Nixpkgs. See also the [CI GitHub Action](../../../../.github/workflows/check-by-name.yml).
+This directory contains scripts and files used and related to the CI running the `pkgs/by-name` checks in Nixpkgs.
+See also the [CI GitHub Action](../../../../.github/workflows/check-by-name.yml).
 
 ## `./run-local.sh BASE_BRANCH [REPOSITORY]`
 
@@ -15,12 +16,23 @@ Arguments:
 - `BASE_BRANCH`: The base branch to use, e.g. master or release-23.11
 - `REPOSITORY`: The repository to fetch the base branch from, defaults to https://github.com/NixOS/nixpkgs.git
 
-## `./fetch-tool.sh BASE_BRANCH OUTPUT_PATH`
+## `./update-pinned-tool.sh`
 
-Fetches the Hydra-prebuilt nixpkgs-check-by-name to use from the NixOS channel corresponding to the given base branch.
+Updates the pinned CI tool in [`./pinned-tool.json`](./pinned-tool.json) to the
+[latest version from the `nixos-unstable` channel](https://hydra.nixos.org/job/nixos/trunk-combined/nixpkgs.tests.nixpkgs-check-by-name.x86_64-linux).
 
-This script is used both by [`./run-local.sh`](#run-local-sh-base-branch-repository) and CI.
+This script needs to be called manually when the CI tooling needs to be updated.
+
+The `pinned-tool.json` file gets populated with both:
+- The `/nix/store` path for `x86_64-linux`, such that CI doesn't have to evaluate Nixpkgs and can directly fetch it from the cache instead.
+- The Nixpkgs revision, such that the `./run-local.sh` script can be used to run the checks locally on any system.
+
+To ensure that the tool is always pre-built for `x86_64-linux` in the `nixos-unstable` channel,
+it's included in the `tested` jobset description in [`nixos/release-combined.nix`](../../../nixos/release-combined.nix).
+
+Why not just build the tooling right from the PRs Nixpkgs version?
+- Because it allows CI to check all PRs, even if they would break the CI tooling.
+- Because it makes the CI check very fast, since no Nix builds need to be done, even for mass rebuilds.
+- Because it improves security, since we don't have to build potentially untrusted code from PRs.
+  The tool only needs a very minimal Nix evaluation at runtime, which can work with [readonly-mode](https://nixos.org/manual/nix/stable/command-ref/opt-common.html#opt-readonly-mode) and [restrict-eval](https://nixos.org/manual/nix/stable/command-ref/conf-file.html#conf-restrict-eval).
 
-Arguments:
-- `BASE_BRANCH`: The base branch to use, e.g. master or release-23.11
-- `OUTPUT_PATH`: The output symlink path for the tool
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/scripts/fetch-tool.sh b/nixpkgs/pkgs/test/nixpkgs-check-by-name/scripts/fetch-tool.sh
deleted file mode 100755
index 19a48b6fb1fd..000000000000
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/scripts/fetch-tool.sh
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/usr/bin/env bash
-# Fetches the prebuilt nixpkgs-check-by-name to use from
-# the NixOS channel corresponding to the given base branch
-
-set -o pipefail -o errexit -o nounset
-
-trace() { echo >&2 "$@"; }
-
-if (( $# < 2 )); then
-    trace "Usage: $0 BASE_BRANCH OUTPUT_PATH"
-    trace "BASE_BRANCH: The base branch to use, e.g. master or release-23.11"
-    trace "OUTPUT_PATH: The output symlink path for the tool"
-    exit 1
-fi
-baseBranch=$1
-output=$2
-
-trace -n "Determining the channel to use for PR base branch $baseBranch.. "
-if [[ "$baseBranch" =~ ^(release|staging|staging-next)-([0-9][0-9]\.[0-9][0-9])$ ]]; then
-  # Use the release channel for all PRs to release-XX.YY, staging-XX.YY and staging-next-XX.YY
-  preferredChannel=nixos-${BASH_REMATCH[2]}
-else
-  # Use the nixos-unstable channel for all other PRs
-  preferredChannel=nixos-unstable
-fi
-
-# Check that the channel exists. It doesn't exist for fresh release branches
-if curl -fSs "https://channels.nixos.org/$preferredChannel"; then
-    channel=$preferredChannel
-    trace "$channel"
-else
-    # Fall back to nixos-unstable, makes sense for fresh release branches
-    channel=nixos-unstable
-    trace -e "\e[33mWarning: Preferred channel $preferredChannel could not be fetched, using fallback: $channel\e[0m"
-fi
-
-trace -n "Fetching latest version of channel $channel.. "
-# This is probably the easiest way to get Nix to output the path to a downloaded channel!
-nixpkgs=$(nix-instantiate --find-file nixpkgs -I nixpkgs=channel:"$channel")
-trace "$nixpkgs"
-
-# This file only exists in channels
-trace -e "Git revision of channel $channel is \e[34m$(<"$nixpkgs/.git-revision")\e[0m"
-
-trace -n "Fetching the prebuilt version of nixpkgs-check-by-name.. "
-nix-build -o "$output" "$nixpkgs" -A tests.nixpkgs-check-by-name -j 0 >/dev/null
-realpath "$output" >&2
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/scripts/pinned-tool.json b/nixpkgs/pkgs/test/nixpkgs-check-by-name/scripts/pinned-tool.json
new file mode 100644
index 000000000000..b703ce74771e
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/scripts/pinned-tool.json
@@ -0,0 +1,4 @@
+{
+  "rev": "9b19f5e77dd906cb52dade0b7bd280339d2a1f3d",
+  "ci-path": "/nix/store/qlls5ca8q88qpyygg9ddi60gl1nmvpij-nixpkgs-check-by-name"
+}
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/scripts/run-local.sh b/nixpkgs/pkgs/test/nixpkgs-check-by-name/scripts/run-local.sh
index 72d3e8dc3de3..46cbd5e858e2 100755
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/scripts/run-local.sh
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/scripts/run-local.sh
@@ -1,4 +1,5 @@
-#!/usr/bin/env bash
+#!/usr/bin/env nix-shell
+#!nix-shell -i bash -p jq
 
 set -o pipefail -o errexit -o nounset
 
@@ -13,6 +14,7 @@ cleanup() {
 
     [[ -e "$tmp/base" ]] && git worktree remove --force "$tmp/base"
     [[ -e "$tmp/merged" ]] && git worktree remove --force "$tmp/merged"
+    [[ -e "$tmp/tool-nixpkgs" ]] && git worktree remove --force "$tmp/tool-nixpkgs"
 
     rm -rf "$tmp"
 
@@ -61,7 +63,20 @@ trace -n "Merging base branch into the HEAD commit in $tmp/merged.. "
 git -C "$tmp/merged" merge -q --no-edit "$baseSha"
 trace -e "\e[34m$(git -C "$tmp/merged" rev-parse HEAD)\e[0m"
 
-"$tmp/merged/pkgs/test/nixpkgs-check-by-name/scripts/fetch-tool.sh" "$baseBranch" "$tmp/tool"
+trace -n "Reading pinned nixpkgs-check-by-name revision from pinned-tool.json.. "
+toolSha=$(jq -r .rev "$tmp/merged/pkgs/test/nixpkgs-check-by-name/scripts/pinned-tool.json")
+trace -e "\e[34m$toolSha\e[0m"
+
+trace -n "Creating Git worktree for the nixpkgs-check-by-name revision in $tmp/tool-nixpkgs.. "
+git worktree add -q "$tmp/tool-nixpkgs" "$toolSha"
+trace "Done"
+
+trace "Building/fetching nixpkgs-check-by-name.."
+nix-build -o "$tmp/tool" "$tmp/tool-nixpkgs" \
+    -A tests.nixpkgs-check-by-name \
+    --arg config '{}' \
+    --arg overlays '[]' \
+    -j 0
 
 trace "Running nixpkgs-check-by-name.."
 "$tmp/tool/bin/nixpkgs-check-by-name" --base "$tmp/base" "$tmp/merged"
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/scripts/update-pinned-tool.sh b/nixpkgs/pkgs/test/nixpkgs-check-by-name/scripts/update-pinned-tool.sh
new file mode 100755
index 000000000000..dbc6e91df08a
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/scripts/update-pinned-tool.sh
@@ -0,0 +1,40 @@
+#!/usr/bin/env nix-shell
+#!nix-shell -i bash -p jq
+
+set -o pipefail -o errexit -o nounset
+
+trace() { echo >&2 "$@"; }
+
+SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
+
+# Determined by `runs-on: ubuntu-latest` in .github/workflows/check-by-name.yml
+CI_SYSTEM=x86_64-linux
+
+channel=nixos-unstable
+pin_file=$SCRIPT_DIR/pinned-tool.json
+
+trace -n "Fetching latest version of channel $channel.. "
+# This is probably the easiest way to get Nix to output the path to a downloaded channel!
+nixpkgs=$(nix-instantiate --find-file nixpkgs -I nixpkgs=channel:"$channel")
+trace "$nixpkgs"
+
+# This file only exists in channels
+rev=$(<"$nixpkgs/.git-revision")
+trace -e "Git revision of channel $channel is \e[34m$rev\e[0m"
+
+trace -n "Fetching the prebuilt version of nixpkgs-check-by-name for $CI_SYSTEM.. "
+# This is the architecture used by CI, we want to prefetch the exact path to avoid having to evaluate Nixpkgs
+ci_path=$(nix-build --no-out-link "$nixpkgs" \
+    -A tests.nixpkgs-check-by-name \
+    --arg config '{}' \
+    --argstr system "$CI_SYSTEM" \
+    --arg overlays '[]' \
+    -j 0 \
+    | tee /dev/stderr)
+
+trace "Updating $pin_file"
+jq -n \
+    --arg rev "$rev" \
+    --arg ci-path "$ci_path" \
+    '$ARGS.named' \
+    > "$pin_file"
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/src/eval.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/src/eval.nix
index bf9f19d8e460..87c54b6444ee 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/src/eval.nix
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/src/eval.nix
@@ -1,11 +1,7 @@
 # Takes a path to nixpkgs and a path to the json-encoded list of attributes to check.
-# Returns an attribute set containing information on each requested attribute.
-# If the attribute is missing from Nixpkgs it's also missing from the result.
-#
-# The returned information is an attribute set with:
-# - call_package_path: The <path> from `<attr> = callPackage <path> { ... }`,
-#   or null if it's not defined as with callPackage, or if the <path> is not a path
-# - is_derivation: The result of `lib.isDerivation <attr>`
+# Returns an value containing information on each requested attribute,
+# which is decoded on the Rust side.
+# See ./eval.rs for the meaning of the returned values
 {
   attrsPath,
   nixpkgsPath,
@@ -13,70 +9,107 @@
 let
   attrs = builtins.fromJSON (builtins.readFile attrsPath);
 
-  # This overlay mocks callPackage to persist the path of the first argument
-  callPackageOverlay = self: super: {
+  nixpkgsPathLength = builtins.stringLength (toString nixpkgsPath) + 1;
+  removeNixpkgsPrefix = builtins.substring nixpkgsPathLength (-1);
+
+  # We need access to the `callPackage` arguments of each attribute.
+  # The only way to do so is to override `callPackage` with our own version that adds this information to the result,
+  # and then try to access this information.
+  overlay = final: prev: {
+
+    # Information for attributes defined using `callPackage`
     callPackage = fn: args:
-      let
-        result = super.callPackage fn args;
-        variantInfo._attributeVariant = {
-          # These names are used by the deserializer on the Rust side
-          CallPackage.path =
+      addVariantInfo (prev.callPackage fn args) {
+        Manual = {
+          path =
             if builtins.isPath fn then
-              toString fn
+              removeNixpkgsPrefix (toString fn)
             else
               null;
-          CallPackage.empty_arg =
+          empty_arg =
             args == { };
         };
-      in
-      if builtins.isAttrs result then
-        # If this was the last overlay to be applied, we could just only return the `_callPackagePath`,
-        # but that's not the case because stdenv has another overlays on top of user-provided ones.
-        # So to not break the stdenv build we need to return the mostly proper result here
-        result // variantInfo
-      else
-        # It's very rare that callPackage doesn't return an attribute set, but it can occur.
-        variantInfo;
+      };
 
+    # Information for attributes that are auto-called from pkgs/by-name.
+    # This internal attribute is only used by pkgs/by-name
     _internalCallByNamePackageFile = file:
-      let
-        result = super._internalCallByNamePackageFile file;
-        variantInfo._attributeVariant = {
-          # This name is used by the deserializer on the Rust side
-          AutoCalled = null;
-        };
-      in
-      if builtins.isAttrs result then
-        # If this was the last overlay to be applied, we could just only return the `_callPackagePath`,
-        # but that's not the case because stdenv has another overlays on top of user-provided ones.
-        # So to not break the stdenv build we need to return the mostly proper result here
-        result // variantInfo
-      else
-        # It's very rare that callPackage doesn't return an attribute set, but it can occur.
-        variantInfo;
+      addVariantInfo (prev._internalCallByNamePackageFile file) {
+        Auto = null;
+      };
+
   };
 
+  # We can't just replace attribute values with their info in the overlay,
+  # because attributes can depend on other attributes, so this would break evaluation.
+  addVariantInfo = value: variant:
+    if builtins.isAttrs value then
+      value // {
+        _callPackageVariant = variant;
+      }
+    else
+      # It's very rare that callPackage doesn't return an attribute set, but it can occur.
+      # In such a case we can't really return anything sensible that would include the info,
+      # so just don't return the info and let the consumer handle it.
+      value;
+
   pkgs = import nixpkgsPath {
     # Don't let the users home directory influence this result
     config = { };
-    overlays = [ callPackageOverlay ];
+    overlays = [ overlay ];
+    # We check evaluation and callPackage only for x86_64-linux.
+    # Not ideal, but hard to fix
+    system = "x86_64-linux";
   };
 
-  attrInfo = attr:
-    let
-      value = pkgs.${attr};
-    in
-    {
-    # These names are used by the deserializer on the Rust side
-    variant = value._attributeVariant or { Other = null; };
-    is_derivation = pkgs.lib.isDerivation value;
-  };
+  attrInfo = name: value:
+    if ! builtins.isAttrs value then
+      {
+        NonAttributeSet = null;
+      }
+    else if ! value ? _callPackageVariant then
+      {
+        NonCallPackage = null;
+      }
+    else
+      {
+        CallPackage = {
+          call_package_variant = value._callPackageVariant;
+          is_derivation = pkgs.lib.isDerivation value;
+        };
+      };
 
-  attrInfos = builtins.listToAttrs (map (name: {
+  byNameAttrs = builtins.listToAttrs (map (name: {
     inherit name;
-    value = attrInfo name;
+    value.ByName =
+      if ! pkgs ? ${name} then
+        { Missing = null; }
+      else
+        { Existing = attrInfo name pkgs.${name}; };
   }) attrs);
 
+  # Information on all attributes that exist but are not in pkgs/by-name.
+  # We need this to enforce pkgs/by-name for new packages
+  nonByNameAttrs = builtins.mapAttrs (name: value:
+    let
+      output = attrInfo name value;
+      result = builtins.tryEval (builtins.deepSeq output null);
+    in
+    {
+      NonByName =
+        if result.success then
+          { EvalSuccess = output; }
+        else
+          { EvalFailure = null; };
+    }
+  ) (builtins.removeAttrs pkgs attrs);
+
+  # All attributes
+  attributes = byNameAttrs // nonByNameAttrs;
 in
-# Filter out attributes not in Nixpkgs
-builtins.intersectAttrs pkgs attrInfos
+# We output them in the form [ [ <name> <value> ] ]` such that the Rust side
+# doesn't need to sort them again to get deterministic behavior (good for testing)
+map (name: [
+  name
+  attributes.${name}
+]) (builtins.attrNames attributes)
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/src/eval.rs b/nixpkgs/pkgs/test/nixpkgs-check-by-name/src/eval.rs
index cd8c70472cf2..e4584f09d8cd 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/src/eval.rs
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/src/eval.rs
@@ -6,33 +6,63 @@ use std::path::Path;
 
 use anyhow::Context;
 use serde::Deserialize;
-use std::collections::HashMap;
 use std::path::PathBuf;
 use std::process;
 use tempfile::NamedTempFile;
 
 /// Attribute set of this structure is returned by eval.nix
 #[derive(Deserialize)]
-struct AttributeInfo {
-    variant: AttributeVariant,
+enum Attribute {
+    /// An attribute that should be defined via pkgs/by-name
+    ByName(ByNameAttribute),
+    /// An attribute not defined via pkgs/by-name
+    NonByName(NonByNameAttribute),
+}
+
+#[derive(Deserialize)]
+enum NonByNameAttribute {
+    /// The attribute doesn't evaluate
+    EvalFailure,
+    EvalSuccess(AttributeInfo),
+}
+
+#[derive(Deserialize)]
+enum ByNameAttribute {
+    /// The attribute doesn't exist at all
+    Missing,
+    Existing(AttributeInfo),
+}
+
+#[derive(Deserialize)]
+enum AttributeInfo {
+    /// The attribute exists, but its value isn't an attribute set
+    NonAttributeSet,
+    /// The attribute exists, but its value isn't defined using callPackage
+    NonCallPackage,
+    /// The attribute exists and its value is an attribute set
+    CallPackage(CallPackageInfo),
+}
+
+#[derive(Deserialize)]
+struct CallPackageInfo {
+    call_package_variant: CallPackageVariant,
+    /// Whether the attribute is a derivation (`lib.isDerivation`)
     is_derivation: bool,
 }
 
 #[derive(Deserialize)]
-enum AttributeVariant {
+enum CallPackageVariant {
     /// The attribute is auto-called as pkgs.callPackage using pkgs/by-name,
     /// and it is not overridden by a definition in all-packages.nix
-    AutoCalled,
+    Auto,
     /// The attribute is defined as a pkgs.callPackage <path> <args>,
     /// and overridden by all-packages.nix
-    CallPackage {
+    Manual {
         /// The <path> argument or None if it's not a path
         path: Option<PathBuf>,
         /// true if <args> is { }
         empty_arg: bool,
     },
-    /// The attribute is not defined as pkgs.callPackage
-    Other,
 }
 
 /// Check that the Nixpkgs attribute values corresponding to the packages in pkgs/by-name are
@@ -41,32 +71,32 @@ enum AttributeVariant {
 pub fn check_values(
     nixpkgs_path: &Path,
     package_names: Vec<String>,
-    eval_accessible_paths: &[&Path],
+    keep_nix_path: bool,
 ) -> validation::Result<ratchet::Nixpkgs> {
     // Write the list of packages we need to check into a temporary JSON file.
     // This can then get read by the Nix evaluation.
-    let attrs_file = NamedTempFile::new().context("Failed to create a temporary file")?;
+    let attrs_file = NamedTempFile::new().with_context(|| "Failed to create a temporary file")?;
     // We need to canonicalise this path because if it's a symlink (which can be the case on
     // Darwin), Nix would need to read both the symlink and the target path, therefore need 2
     // NIX_PATH entries for restrict-eval. But if we resolve the symlinks then only one predictable
     // entry is needed.
     let attrs_file_path = attrs_file.path().canonicalize()?;
 
-    serde_json::to_writer(&attrs_file, &package_names).context(format!(
-        "Failed to serialise the package names to the temporary path {}",
-        attrs_file_path.display()
-    ))?;
+    serde_json::to_writer(&attrs_file, &package_names).with_context(|| {
+        format!(
+            "Failed to serialise the package names to the temporary path {}",
+            attrs_file_path.display()
+        )
+    })?;
 
     let expr_path = std::env::var("NIX_CHECK_BY_NAME_EXPR_PATH")
-        .context("Could not get environment variable NIX_CHECK_BY_NAME_EXPR_PATH")?;
+        .with_context(|| "Could not get environment variable NIX_CHECK_BY_NAME_EXPR_PATH")?;
     // With restrict-eval, only paths in NIX_PATH can be accessed, so we explicitly specify the
     // ones needed needed
     let mut command = process::Command::new("nix-instantiate");
     command
         // Inherit stderr so that error messages always get shown
         .stderr(process::Stdio::inherit())
-        // Clear NIX_PATH to be sure it doesn't influence the result
-        .env_remove("NIX_PATH")
         .args([
             "--eval",
             "--json",
@@ -87,90 +117,174 @@ pub fn check_values(
         .arg("-I")
         .arg(nixpkgs_path);
 
-    // Also add extra paths that need to be accessible
-    for path in eval_accessible_paths {
-        command.arg("-I");
-        command.arg(path);
+    // Clear NIX_PATH to be sure it doesn't influence the result
+    // But not when requested to keep it, used so that the tests can pass extra Nix files
+    if !keep_nix_path {
+        command.env_remove("NIX_PATH");
     }
+
     command.args(["-I", &expr_path]);
     command.arg(expr_path);
 
     let result = command
         .output()
-        .context(format!("Failed to run command {command:?}"))?;
+        .with_context(|| format!("Failed to run command {command:?}"))?;
 
     if !result.status.success() {
         anyhow::bail!("Failed to run command {command:?}");
     }
     // Parse the resulting JSON value
-    let actual_files: HashMap<String, AttributeInfo> = serde_json::from_slice(&result.stdout)
-        .context(format!(
-            "Failed to deserialise {}",
-            String::from_utf8_lossy(&result.stdout)
-        ))?;
-
-    Ok(
-        validation::sequence(package_names.into_iter().map(|package_name| {
-            let relative_package_file = structure::relative_file_for_package(&package_name);
-            let absolute_package_file = nixpkgs_path.join(&relative_package_file);
-
-            if let Some(attribute_info) = actual_files.get(&package_name) {
-                let check_result = if !attribute_info.is_derivation {
-                    NixpkgsProblem::NonDerivation {
-                        relative_package_file: relative_package_file.clone(),
-                        package_name: package_name.clone(),
-                    }
-                    .into()
-                } else {
-                    Success(())
-                };
-
-                let check_result = check_result.and(match &attribute_info.variant {
-                    AttributeVariant::AutoCalled => Success(ratchet::Package {
-                        empty_non_auto_called: ratchet::EmptyNonAutoCalled::Valid,
-                    }),
-                    AttributeVariant::CallPackage { path, empty_arg } => {
-                        let correct_file = if let Some(call_package_path) = path {
-                            absolute_package_file == *call_package_path
-                        } else {
-                            false
-                        };
-
-                        if correct_file {
-                            Success(ratchet::Package {
-                                // Empty arguments for non-auto-called packages are not allowed anymore.
-                                empty_non_auto_called: if *empty_arg {
-                                    ratchet::EmptyNonAutoCalled::Invalid
-                                } else {
-                                    ratchet::EmptyNonAutoCalled::Valid
-                                },
-                            })
-                        } else {
-                            NixpkgsProblem::WrongCallPackage {
-                                relative_package_file: relative_package_file.clone(),
-                                package_name: package_name.clone(),
-                            }
-                            .into()
+    let attributes: Vec<(String, Attribute)> = serde_json::from_slice(&result.stdout)
+        .with_context(|| {
+            format!(
+                "Failed to deserialise {}",
+                String::from_utf8_lossy(&result.stdout)
+            )
+        })?;
+
+    let check_result = validation::sequence(attributes.into_iter().map(
+        |(attribute_name, attribute_value)| {
+            let relative_package_file = structure::relative_file_for_package(&attribute_name);
+
+            use ratchet::RatchetState::*;
+            use Attribute::*;
+            use AttributeInfo::*;
+            use ByNameAttribute::*;
+            use CallPackageVariant::*;
+            use NonByNameAttribute::*;
+
+            let check_result = match attribute_value {
+                // The attribute succeeds evaluation and is NOT defined in pkgs/by-name
+                NonByName(EvalSuccess(attribute_info)) => {
+                    let uses_by_name = match attribute_info {
+                        // In these cases the package doesn't qualify for being in pkgs/by-name,
+                        // so the UsesByName ratchet is already as tight as it can be
+                        NonAttributeSet => Success(Tight),
+                        NonCallPackage => Success(Tight),
+                        // This is the case when the `pkgs/by-name`-internal _internalCallByNamePackageFile
+                        // is used for a package outside `pkgs/by-name`
+                        CallPackage(CallPackageInfo {
+                            call_package_variant: Auto,
+                            ..
+                        }) => {
+                            // With the current detection mechanism, this also triggers for aliases
+                            // to pkgs/by-name packages, and there's no good method of
+                            // distinguishing alias vs non-alias.
+                            // Using `config.allowAliases = false` at least currently doesn't work
+                            // because there's nothing preventing people from defining aliases that
+                            // are present even with that disabled.
+                            // In the future we could kind of abuse this behavior to have better
+                            // enforcement of conditional aliases, but for now we just need to not
+                            // give an error.
+                            Success(Tight)
                         }
-                    }
-                    AttributeVariant::Other => NixpkgsProblem::WrongCallPackage {
-                        relative_package_file: relative_package_file.clone(),
-                        package_name: package_name.clone(),
-                    }
-                    .into(),
-                });
-
-                check_result.map(|value| (package_name.clone(), value))
-            } else {
-                NixpkgsProblem::UndefinedAttr {
+                        // Only derivations can be in pkgs/by-name,
+                        // so this attribute doesn't qualify
+                        CallPackage(CallPackageInfo {
+                            is_derivation: false,
+                            ..
+                        }) => Success(Tight),
+
+                        // The case of an attribute that qualifies:
+                        // - Uses callPackage
+                        // - Is a derivation
+                        CallPackage(CallPackageInfo {
+                            is_derivation: true,
+                            call_package_variant: Manual { path, empty_arg },
+                        }) => Success(Loose(ratchet::UsesByName {
+                            call_package_path: path,
+                            empty_arg,
+                        })),
+                    };
+                    uses_by_name.map(|x| ratchet::Package {
+                        empty_non_auto_called: Tight,
+                        uses_by_name: x,
+                    })
+                }
+                NonByName(EvalFailure) => {
+                    // This is a bit of an odd case: We don't even _know_ whether this attribute
+                    // would qualify for using pkgs/by-name. We can either:
+                    // - Assume it's not using pkgs/by-name, which has the problem that if a
+                    //   package evaluation gets broken temporarily, the fix can remove it from
+                    //   pkgs/by-name again
+                    // - Assume it's using pkgs/by-name already, which has the problem that if a
+                    //   package evaluation gets broken temporarily, fixing it requires a move to
+                    //   pkgs/by-name
+                    // We choose the latter, since we want to move towards pkgs/by-name, not away
+                    // from it
+                    Success(ratchet::Package {
+                        empty_non_auto_called: Tight,
+                        uses_by_name: Tight,
+                    })
+                }
+                ByName(Missing) => NixpkgsProblem::UndefinedAttr {
+                    relative_package_file: relative_package_file.clone(),
+                    package_name: attribute_name.clone(),
+                }
+                .into(),
+                ByName(Existing(NonAttributeSet)) => NixpkgsProblem::NonDerivation {
+                    relative_package_file: relative_package_file.clone(),
+                    package_name: attribute_name.clone(),
+                }
+                .into(),
+                ByName(Existing(NonCallPackage)) => NixpkgsProblem::WrongCallPackage {
                     relative_package_file: relative_package_file.clone(),
-                    package_name: package_name.clone(),
+                    package_name: attribute_name.clone(),
                 }
-                .into()
-            }
-        }))
-        .map(|elems| ratchet::Nixpkgs {
-            packages: elems.into_iter().collect(),
-        }),
-    )
+                .into(),
+                ByName(Existing(CallPackage(CallPackageInfo {
+                    is_derivation,
+                    call_package_variant,
+                }))) => {
+                    let check_result = if !is_derivation {
+                        NixpkgsProblem::NonDerivation {
+                            relative_package_file: relative_package_file.clone(),
+                            package_name: attribute_name.clone(),
+                        }
+                        .into()
+                    } else {
+                        Success(())
+                    };
+
+                    check_result.and(match &call_package_variant {
+                        Auto => Success(ratchet::Package {
+                            empty_non_auto_called: Tight,
+                            uses_by_name: Tight,
+                        }),
+                        Manual { path, empty_arg } => {
+                            let correct_file = if let Some(call_package_path) = path {
+                                relative_package_file == *call_package_path
+                            } else {
+                                false
+                            };
+
+                            if correct_file {
+                                Success(ratchet::Package {
+                                    // Empty arguments for non-auto-called packages are not allowed anymore.
+                                    empty_non_auto_called: if *empty_arg {
+                                        Loose(ratchet::EmptyNonAutoCalled)
+                                    } else {
+                                        Tight
+                                    },
+                                    uses_by_name: Tight,
+                                })
+                            } else {
+                                NixpkgsProblem::WrongCallPackage {
+                                    relative_package_file: relative_package_file.clone(),
+                                    package_name: attribute_name.clone(),
+                                }
+                                .into()
+                            }
+                        }
+                    })
+                }
+            };
+            check_result.map(|value| (attribute_name.clone(), value))
+        },
+    ));
+
+    Ok(check_result.map(|elems| ratchet::Nixpkgs {
+        package_names: elems.iter().map(|(name, _)| name.to_owned()).collect(),
+        package_map: elems.into_iter().collect(),
+    }))
 }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/src/main.rs b/nixpkgs/pkgs/test/nixpkgs-check-by-name/src/main.rs
index 18c950d0a6eb..8179ec8ded74 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/src/main.rs
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/src/main.rs
@@ -38,15 +38,13 @@ pub struct Args {
 
     /// Path to the base Nixpkgs to run ratchet checks against.
     /// For PRs, this should be set to a checkout of the PRs base branch.
-    /// If not specified, no ratchet checks will be performed.
-    /// However, this flag will become required once CI uses it.
     #[arg(long)]
-    base: Option<PathBuf>,
+    base: PathBuf,
 }
 
 fn main() -> ExitCode {
     let args = Args::parse();
-    match process(args.base.as_deref(), &args.nixpkgs, &[], &mut io::stderr()) {
+    match process(&args.base, &args.nixpkgs, false, &mut io::stderr()) {
         Ok(true) => {
             eprintln!("{}", "Validated successfully".green());
             ExitCode::SUCCESS
@@ -67,9 +65,9 @@ fn main() -> ExitCode {
 /// # Arguments
 /// - `base_nixpkgs`: Path to the base Nixpkgs to run ratchet checks against.
 /// - `main_nixpkgs`: Path to the main Nixpkgs to check.
-/// - `eval_accessible_paths`:
-///   Extra paths that need to be accessible to evaluate Nixpkgs using `restrict-eval`.
-///   This is used to allow the tests to access the mock-nixpkgs.nix file
+/// - `keep_nix_path`: Whether the value of the NIX_PATH environment variable should be kept for
+/// the evaluation stage, allowing its contents to be accessed.
+///   This is used to allow the tests to access e.g. the mock-nixpkgs.nix file
 /// - `error_writer`: An `io::Write` value to write validation errors to, if any.
 ///
 /// # Return value
@@ -77,28 +75,24 @@ fn main() -> ExitCode {
 /// - `Ok(false)` if there are problems, all of which will be written to `error_writer`.
 /// - `Ok(true)` if there are no problems
 pub fn process<W: io::Write>(
-    base_nixpkgs: Option<&Path>,
+    base_nixpkgs: &Path,
     main_nixpkgs: &Path,
-    eval_accessible_paths: &[&Path],
+    keep_nix_path: bool,
     error_writer: &mut W,
 ) -> anyhow::Result<bool> {
     // Check the main Nixpkgs first
-    let main_result = check_nixpkgs(main_nixpkgs, eval_accessible_paths, error_writer)?;
+    let main_result = check_nixpkgs(main_nixpkgs, keep_nix_path, error_writer)?;
     let check_result = main_result.result_map(|nixpkgs_version| {
         // If the main Nixpkgs doesn't have any problems, run the ratchet checks against the base
         // Nixpkgs
-        if let Some(base) = base_nixpkgs {
-            check_nixpkgs(base, eval_accessible_paths, error_writer)?.result_map(
-                |base_nixpkgs_version| {
-                    Ok(ratchet::Nixpkgs::compare(
-                        Some(base_nixpkgs_version),
-                        nixpkgs_version,
-                    ))
-                },
-            )
-        } else {
-            Ok(ratchet::Nixpkgs::compare(None, nixpkgs_version))
-        }
+        check_nixpkgs(base_nixpkgs, keep_nix_path, error_writer)?.result_map(
+            |base_nixpkgs_version| {
+                Ok(ratchet::Nixpkgs::compare(
+                    base_nixpkgs_version,
+                    nixpkgs_version,
+                ))
+            },
+        )
     })?;
 
     match check_result {
@@ -119,14 +113,16 @@ pub fn process<W: io::Write>(
 /// ratchet check against another result.
 pub fn check_nixpkgs<W: io::Write>(
     nixpkgs_path: &Path,
-    eval_accessible_paths: &[&Path],
+    keep_nix_path: bool,
     error_writer: &mut W,
 ) -> validation::Result<ratchet::Nixpkgs> {
     Ok({
-        let nixpkgs_path = nixpkgs_path.canonicalize().context(format!(
-            "Nixpkgs path {} could not be resolved",
-            nixpkgs_path.display()
-        ))?;
+        let nixpkgs_path = nixpkgs_path.canonicalize().with_context(|| {
+            format!(
+                "Nixpkgs path {} could not be resolved",
+                nixpkgs_path.display()
+            )
+        })?;
 
         if !nixpkgs_path.join(utils::BASE_SUBPATH).exists() {
             writeln!(
@@ -138,7 +134,7 @@ pub fn check_nixpkgs<W: io::Write>(
         } else {
             check_structure(&nixpkgs_path)?.result_map(|package_names|
                 // Only if we could successfully parse the structure, we do the evaluation checks
-                eval::check_values(&nixpkgs_path, package_names, eval_accessible_paths))?
+                eval::check_values(&nixpkgs_path, package_names, keep_nix_path))?
         }
     })
 }
@@ -230,20 +226,18 @@ mod tests {
     }
 
     fn test_nixpkgs(name: &str, path: &Path, expected_errors: &str) -> anyhow::Result<()> {
-        let extra_nix_path = Path::new("tests/mock-nixpkgs.nix");
-
         let base_path = path.join("base");
         let base_nixpkgs = if base_path.exists() {
-            Some(base_path.as_path())
+            base_path.as_path()
         } else {
-            None
+            Path::new("tests/empty-base")
         };
 
         // We don't want coloring to mess up the tests
         let writer = temp_env::with_var("NO_COLOR", Some("1"), || -> anyhow::Result<_> {
             let mut writer = vec![];
-            process(base_nixpkgs, &path, &[&extra_nix_path], &mut writer)
-                .context(format!("Failed test case {name}"))?;
+            process(base_nixpkgs, &path, true, &mut writer)
+                .with_context(|| format!("Failed test case {name}"))?;
             Ok(writer)
         })?;
 
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/src/nixpkgs_problem.rs b/nixpkgs/pkgs/test/nixpkgs-check-by-name/src/nixpkgs_problem.rs
index 2344a8cc1325..16ea65deebfc 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/src/nixpkgs_problem.rs
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/src/nixpkgs_problem.rs
@@ -1,3 +1,4 @@
+use crate::structure;
 use crate::utils::PACKAGE_NIX_FILENAME;
 use rnix::parser::ParseError;
 use std::ffi::OsString;
@@ -87,6 +88,16 @@ pub enum NixpkgsProblem {
         text: String,
         io_error: io::Error,
     },
+    MovedOutOfByName {
+        package_name: String,
+        call_package_path: Option<PathBuf>,
+        empty_arg: bool,
+    },
+    NewPackageNotUsingByName {
+        package_name: String,
+        call_package_path: Option<PathBuf>,
+        empty_arg: bool,
+    },
 }
 
 impl fmt::Display for NixpkgsProblem {
@@ -213,6 +224,48 @@ impl fmt::Display for NixpkgsProblem {
                     subpath.display(),
                     text,
                 ),
+            NixpkgsProblem::MovedOutOfByName { package_name, call_package_path, empty_arg } => {
+                let call_package_arg =
+                    if let Some(path) = &call_package_path {
+                        format!("./{}", path.display())
+                    } else {
+                        "...".into()
+                    };
+                if *empty_arg {
+                    write!(
+                        f,
+                        "pkgs.{package_name}: This top-level package was previously defined in {}, but is now manually defined as `callPackage {call_package_arg} {{ }}` (e.g. in `pkgs/top-level/all-packages.nix`). Please move the package back and remove the manual `callPackage`.",
+                        structure::relative_file_for_package(package_name).display(),
+                        )
+                } else {
+                    // This can happen if users mistakenly assume that for custom arguments,
+                    // pkgs/by-name can't be used.
+                    write!(
+                        f,
+                        "pkgs.{package_name}: This top-level package was previously defined in {}, but is now manually defined as `callPackage {call_package_arg} {{ ... }}` (e.g. in `pkgs/top-level/all-packages.nix`). While the manual `callPackage` is still needed, it's not necessary to move the package files.",
+                        structure::relative_file_for_package(package_name).display(),
+                        )
+                }
+            },
+            NixpkgsProblem::NewPackageNotUsingByName { package_name, call_package_path, empty_arg } => {
+                let call_package_arg =
+                    if let Some(path) = &call_package_path {
+                        format!("./{}", path.display())
+                    } else {
+                        "...".into()
+                    };
+                let extra =
+                    if *empty_arg {
+                        "Since the second `callPackage` argument is `{ }`, no manual `callPackage` (e.g. in `pkgs/top-level/all-packages.nix`) is needed anymore."
+                    } else {
+                        "Since the second `callPackage` argument is not `{ }`, the manual `callPackage` (e.g. in `pkgs/top-level/all-packages.nix`) is still needed."
+                    };
+                write!(
+                    f,
+                    "pkgs.{package_name}: This is a new top-level package of the form `callPackage {call_package_arg} {{ }}`. Please define it in {} instead. See `pkgs/by-name/README.md` for more details. {extra}",
+                    structure::relative_file_for_package(package_name).display(),
+                )
+            },
         }
     }
 }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/src/ratchet.rs b/nixpkgs/pkgs/test/nixpkgs-check-by-name/src/ratchet.rs
index c12f1ead2540..f8c129626cc0 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/src/ratchet.rs
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/src/ratchet.rs
@@ -6,80 +6,141 @@ use crate::nixpkgs_problem::NixpkgsProblem;
 use crate::structure;
 use crate::validation::{self, Validation, Validation::Success};
 use std::collections::HashMap;
+use std::path::PathBuf;
 
 /// The ratchet value for the entirety of Nixpkgs.
 #[derive(Default)]
 pub struct Nixpkgs {
-    /// The ratchet values for each package in `pkgs/by-name`
-    pub packages: HashMap<String, Package>,
+    /// Sorted list of packages in package_map
+    pub package_names: Vec<String>,
+    /// The ratchet values for all packages
+    pub package_map: HashMap<String, Package>,
 }
 
 impl Nixpkgs {
     /// Validates the ratchet checks for Nixpkgs
-    pub fn compare(optional_from: Option<Self>, to: Self) -> Validation<()> {
+    pub fn compare(from: Self, to: Self) -> Validation<()> {
         validation::sequence_(
             // We only loop over the current attributes,
             // we don't need to check ones that were removed
-            to.packages.into_iter().map(|(name, attr_to)| {
-                let attr_from = if let Some(from) = &optional_from {
-                    from.packages.get(&name)
-                } else {
-                    // This pretends that if there's no base version to compare against, all
-                    // attributes existed without conforming to the new strictness check for
-                    // backwards compatibility.
-                    // TODO: Remove this case. This is only needed because the `--base`
-                    // argument is still optional, which doesn't need to be once CI is updated
-                    // to pass it.
-                    Some(&Package {
-                        empty_non_auto_called: EmptyNonAutoCalled::Invalid,
-                    })
-                };
-                Package::compare(&name, attr_from, &attr_to)
+            to.package_names.into_iter().map(|name| {
+                Package::compare(&name, from.package_map.get(&name), &to.package_map[&name])
             }),
         )
     }
 }
 
-/// The ratchet value for a single package in `pkgs/by-name`
+/// The ratchet value for a top-level package
 pub struct Package {
     /// The ratchet value for the check for non-auto-called empty arguments
-    pub empty_non_auto_called: EmptyNonAutoCalled,
+    pub empty_non_auto_called: RatchetState<EmptyNonAutoCalled>,
+
+    /// The ratchet value for the check for new packages using pkgs/by-name
+    pub uses_by_name: RatchetState<UsesByName>,
 }
 
 impl Package {
-    /// Validates the ratchet checks for a single package defined in `pkgs/by-name`
+    /// Validates the ratchet checks for a top-level package
     pub fn compare(name: &str, optional_from: Option<&Self>, to: &Self) -> Validation<()> {
-        EmptyNonAutoCalled::compare(
-            name,
-            optional_from.map(|x| &x.empty_non_auto_called),
-            &to.empty_non_auto_called,
-        )
+        validation::sequence_([
+            RatchetState::<EmptyNonAutoCalled>::compare(
+                name,
+                optional_from.map(|x| &x.empty_non_auto_called),
+                &to.empty_non_auto_called,
+            ),
+            RatchetState::<UsesByName>::compare(
+                name,
+                optional_from.map(|x| &x.uses_by_name),
+                &to.uses_by_name,
+            ),
+        ])
     }
 }
 
-/// The ratchet value of a single package in `pkgs/by-name`
+/// The ratchet state of a generic ratchet check.
+pub enum RatchetState<Context> {
+    /// The ratchet is loose, it can be tightened more.
+    /// In other words, this is the legacy state we're trying to move away from.
+    /// Introducing new instances is not allowed but previous instances will continue to be allowed.
+    /// The `Context` is context for error messages in case a new instance of this state is
+    /// introduced
+    Loose(Context),
+    /// The ratchet is tight, it can't be tightened any further.
+    /// This is either because we already use the latest state, or because the ratchet isn't
+    /// relevant.
+    Tight,
+}
+
+/// A trait that can convert an attribute-specific error context into a NixpkgsProblem
+pub trait ToNixpkgsProblem {
+    /// How to convert an attribute-specific error context into a NixpkgsProblem
+    fn to_nixpkgs_problem(name: &str, context: &Self, existed_before: bool) -> NixpkgsProblem;
+}
+
+impl<Context: ToNixpkgsProblem> RatchetState<Context> {
+    /// Compare the previous ratchet state of an attribute to the new state.
+    /// The previous state may be `None` in case the attribute is new.
+    fn compare(name: &str, optional_from: Option<&Self>, to: &Self) -> Validation<()> {
+        // If we don't have a previous state, enforce a tight ratchet
+        let from = optional_from.unwrap_or(&RatchetState::Tight);
+        match (from, to) {
+            // Always okay to keep it tight or tighten the ratchet
+            (_, RatchetState::Tight) => Success(()),
+
+            // Grandfathering policy for a loose ratchet
+            (RatchetState::Loose { .. }, RatchetState::Loose { .. }) => Success(()),
+
+            // Loosening a ratchet is now allowed
+            (RatchetState::Tight, RatchetState::Loose(context)) => {
+                Context::to_nixpkgs_problem(name, context, optional_from.is_some()).into()
+            }
+        }
+    }
+}
+
+/// The ratchet value of an attribute
 /// for the non-auto-called empty argument check of a single.
 ///
 /// This checks that packages defined in `pkgs/by-name` cannot be overridden
 /// with an empty second argument like `callPackage ... { }`.
-#[derive(PartialEq, PartialOrd)]
-pub enum EmptyNonAutoCalled {
-    Invalid,
-    Valid,
+pub struct EmptyNonAutoCalled;
+
+impl ToNixpkgsProblem for EmptyNonAutoCalled {
+    fn to_nixpkgs_problem(name: &str, _context: &Self, _existed_before: bool) -> NixpkgsProblem {
+        NixpkgsProblem::WrongCallPackage {
+            relative_package_file: structure::relative_file_for_package(name),
+            package_name: name.to_owned(),
+        }
+    }
 }
 
-impl EmptyNonAutoCalled {
-    /// Validates the non-auto-called empty argument ratchet check for a single package defined in `pkgs/by-name`
-    fn compare(name: &str, optional_from: Option<&Self>, to: &Self) -> Validation<()> {
-        let from = optional_from.unwrap_or(&Self::Valid);
-        if to >= from {
-            Success(())
+/// The ratchet value of an attribute
+/// for the check that new packages use pkgs/by-name
+///
+/// This checks that all new package defined using callPackage must be defined via pkgs/by-name
+/// It also checks that once a package uses pkgs/by-name, it can't switch back to all-packages.nix
+#[derive(Clone)]
+pub struct UsesByName {
+    /// The first callPackage argument, used for better errors
+    pub call_package_path: Option<PathBuf>,
+    /// Whether the second callPackage argument is empty, used for better errors
+    pub empty_arg: bool,
+}
+
+impl ToNixpkgsProblem for UsesByName {
+    fn to_nixpkgs_problem(name: &str, a: &Self, existed_before: bool) -> NixpkgsProblem {
+        if existed_before {
+            NixpkgsProblem::MovedOutOfByName {
+                package_name: name.to_owned(),
+                call_package_path: a.call_package_path.clone(),
+                empty_arg: a.empty_arg,
+            }
         } else {
-            NixpkgsProblem::WrongCallPackage {
-                relative_package_file: structure::relative_file_for_package(name),
+            NixpkgsProblem::NewPackageNotUsingByName {
                 package_name: name.to_owned(),
+                call_package_path: a.call_package_path.clone(),
+                empty_arg: a.empty_arg,
             }
-            .into()
         }
     }
 }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/src/references.rs b/nixpkgs/pkgs/test/nixpkgs-check-by-name/src/references.rs
index 0561a9b22e85..ce7403afb32d 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/src/references.rs
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/src/references.rs
@@ -17,10 +17,12 @@ pub fn check_references(
 ) -> validation::Result<()> {
     // The empty argument here is the subpath under the package directory to check
     // An empty one means the package directory itself
-    check_path(relative_package_dir, absolute_package_dir, Path::new("")).context(format!(
-        "While checking the references in package directory {}",
-        relative_package_dir.display()
-    ))
+    check_path(relative_package_dir, absolute_package_dir, Path::new("")).with_context(|| {
+        format!(
+            "While checking the references in package directory {}",
+            relative_package_dir.display()
+        )
+    })
 }
 
 /// Checks for a specific path to not have references outside
@@ -62,7 +64,9 @@ fn check_path(
                 .map(|entry| {
                     let entry_subpath = subpath.join(entry.file_name());
                     check_path(relative_package_dir, absolute_package_dir, &entry_subpath)
-                        .context(format!("Error while recursing into {}", subpath.display()))
+                        .with_context(|| {
+                            format!("Error while recursing into {}", subpath.display())
+                        })
                 })
                 .collect_vec()?,
         )
@@ -70,8 +74,8 @@ fn check_path(
         // Only check Nix files
         if let Some(ext) = path.extension() {
             if ext == OsStr::new("nix") {
-                check_nix_file(relative_package_dir, absolute_package_dir, subpath).context(
-                    format!("Error while checking Nix file {}", subpath.display()),
+                check_nix_file(relative_package_dir, absolute_package_dir, subpath).with_context(
+                    || format!("Error while checking Nix file {}", subpath.display()),
                 )?
             } else {
                 Success(())
@@ -93,16 +97,19 @@ fn check_nix_file(
     subpath: &Path,
 ) -> validation::Result<()> {
     let path = absolute_package_dir.join(subpath);
-    let parent_dir = path.parent().context(format!(
-        "Could not get parent of path {}",
-        subpath.display()
-    ))?;
+    let parent_dir = path
+        .parent()
+        .with_context(|| format!("Could not get parent of path {}", subpath.display()))?;
 
-    let contents =
-        read_to_string(&path).context(format!("Could not read file {}", subpath.display()))?;
+    let contents = read_to_string(&path)
+        .with_context(|| format!("Could not read file {}", subpath.display()))?;
 
     let root = Root::parse(&contents);
     if let Some(error) = root.errors().first() {
+        // NOTE: There's now another Nixpkgs CI check to make sure all changed Nix files parse
+        // correctly, though that uses mainline Nix instead of rnix, so it doesn't give the same
+        // errors. In the future we should unify these two checks, ideally moving the other CI
+        // check into this tool as well and checking for both mainline Nix and rnix.
         return Ok(NixpkgsProblem::CouldNotParseNix {
             relative_package_dir: relative_package_dir.to_path_buf(),
             subpath: subpath.to_path_buf(),
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/src/utils.rs b/nixpkgs/pkgs/test/nixpkgs-check-by-name/src/utils.rs
index 5cc4a0863ba8..7e0198dede42 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/src/utils.rs
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/src/utils.rs
@@ -10,10 +10,10 @@ pub const PACKAGE_NIX_FILENAME: &str = "package.nix";
 pub fn read_dir_sorted(base_dir: &Path) -> anyhow::Result<Vec<fs::DirEntry>> {
     let listing = base_dir
         .read_dir()
-        .context(format!("Could not list directory {}", base_dir.display()))?;
+        .with_context(|| format!("Could not list directory {}", base_dir.display()))?;
     let mut shard_entries = listing
         .collect::<io::Result<Vec<_>>>()
-        .context(format!("Could not list directory {}", base_dir.display()))?;
+        .with_context(|| format!("Could not list directory {}", base_dir.display()))?;
     shard_entries.sort_by_key(|entry| entry.file_name());
     Ok(shard_entries)
 }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/aliases/aliases.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/aliases/aliases.nix
new file mode 100644
index 000000000000..c70ec23478ea
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/aliases/aliases.nix
@@ -0,0 +1,3 @@
+self: super: {
+  baz = self.foo;
+}
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/aliases/all-packages.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/aliases/all-packages.nix
new file mode 100644
index 000000000000..2cdfcef08fa6
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/aliases/all-packages.nix
@@ -0,0 +1,3 @@
+self: super: {
+  bar = self.foo;
+}
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/aliases/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/aliases/default.nix
new file mode 100644
index 000000000000..861260cdca4b
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/aliases/default.nix
@@ -0,0 +1 @@
+import <test-nixpkgs> { root = ./.; }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/ref-parse-failure/pkgs/by-name/aa/aa/package.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/aliases/pkgs/by-name/fo/foo/package.nix
index a1b92efbbadb..a1b92efbbadb 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/ref-parse-failure/pkgs/by-name/aa/aa/package.nix
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/aliases/pkgs/by-name/fo/foo/package.nix
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/broken-autocall/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/broken-autocall/default.nix
index 793dfabd6553..bd4825f8bad8 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/broken-autocall/default.nix
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/broken-autocall/default.nix
@@ -1,4 +1,4 @@
 args:
 builtins.removeAttrs
-  (import ../mock-nixpkgs.nix { root = ./.; } args)
+  (import <test-nixpkgs> { root = ./.; } args)
   [ "foo" ]
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/empty-base/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/empty-base/default.nix
new file mode 100644
index 000000000000..861260cdca4b
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/empty-base/default.nix
@@ -0,0 +1 @@
+import <test-nixpkgs> { root = ./.; }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/empty-base/pkgs/by-name/README.md b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/empty-base/pkgs/by-name/README.md
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/empty-base/pkgs/by-name/README.md
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/incorrect-shard/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/incorrect-shard/default.nix
index af25d1450122..861260cdca4b 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/incorrect-shard/default.nix
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/incorrect-shard/default.nix
@@ -1 +1 @@
-import ../mock-nixpkgs.nix { root = ./.; }
+import <test-nixpkgs> { root = ./.; }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/internalCallPackage/all-packages.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/internalCallPackage/all-packages.nix
new file mode 100644
index 000000000000..95478a87fb32
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/internalCallPackage/all-packages.nix
@@ -0,0 +1,3 @@
+self: super: {
+  foo = self._internalCallByNamePackageFile ./foo.nix;
+}
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/internalCallPackage/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/internalCallPackage/default.nix
new file mode 100644
index 000000000000..861260cdca4b
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/internalCallPackage/default.nix
@@ -0,0 +1 @@
+import <test-nixpkgs> { root = ./.; }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/internalCallPackage/foo.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/internalCallPackage/foo.nix
new file mode 100644
index 000000000000..a1b92efbbadb
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/internalCallPackage/foo.nix
@@ -0,0 +1 @@
+{ someDrv }: someDrv
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/internalCallPackage/pkgs/by-name/README.md b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/internalCallPackage/pkgs/by-name/README.md
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/internalCallPackage/pkgs/by-name/README.md
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/invalid-package-name/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/invalid-package-name/default.nix
index af25d1450122..861260cdca4b 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/invalid-package-name/default.nix
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/invalid-package-name/default.nix
@@ -1 +1 @@
-import ../mock-nixpkgs.nix { root = ./.; }
+import <test-nixpkgs> { root = ./.; }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/invalid-shard-name/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/invalid-shard-name/default.nix
index af25d1450122..861260cdca4b 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/invalid-shard-name/default.nix
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/invalid-shard-name/default.nix
@@ -1 +1 @@
-import ../mock-nixpkgs.nix { root = ./.; }
+import <test-nixpkgs> { root = ./.; }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/missing-package-nix/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/missing-package-nix/default.nix
index af25d1450122..861260cdca4b 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/missing-package-nix/default.nix
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/missing-package-nix/default.nix
@@ -1 +1 @@
-import ../mock-nixpkgs.nix { root = ./.; }
+import <test-nixpkgs> { root = ./.; }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/mock-nixpkgs.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/mock-nixpkgs.nix
index 01bb27a48038..81a9c916ac2d 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/mock-nixpkgs.nix
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/mock-nixpkgs.nix
@@ -19,34 +19,20 @@ It returns a Nixpkgs-like function that can be auto-called and evaluates to an a
   overlays ? [],
   # Passed by the checker to make sure a real Nixpkgs isn't influenced by impurities
   config ? {},
+  # Passed by the checker to make sure a real Nixpkgs isn't influenced by impurities
+  system ? null,
 }:
 let
 
   # Simplified versions of lib functions
-  lib = {
-    fix = f: let x = f x; in x;
-
-    extends = overlay: f: final:
-      let
-        prev = f final;
-      in
-      prev // overlay final prev;
-
-    callPackageWith = autoArgs: fn: args:
-      let
-        f = if builtins.isFunction fn then fn else import fn;
-        fargs = builtins.functionArgs f;
-        allArgs = builtins.intersectAttrs fargs autoArgs // args;
-      in
-      f allArgs;
-
-    isDerivation = value: value.type or null == "derivation";
-  };
+  lib = import <test-nixpkgs/lib>;
 
   # The base fixed-point function to populate the resulting attribute set
   pkgsFun = self: {
     inherit lib;
-    callPackage = lib.callPackageWith self;
+    newScope = extra: lib.callPackageWith (self // extra);
+    callPackage = self.newScope { };
+    callPackages = lib.callPackagesWith self;
     someDrv = { type = "derivation"; };
   };
 
@@ -91,12 +77,21 @@ let
     else
       [ ];
 
+  # A list optionally containing the `aliases.nix` file from the test case as an overlay
+  # But only if config.allowAliases is not false
+  optionalAliasesOverlay =
+    if (config.allowAliases or true) && builtins.pathExists (root + "/aliases.nix") then
+      [ (import (root + "/aliases.nix")) ]
+    else
+      [ ];
+
   # All the overlays in the right order, including the user-supplied ones
   allOverlays =
     [
       autoCalledPackages
     ]
     ++ optionalAllPackagesOverlay
+    ++ optionalAliasesOverlay
     ++ overlays;
 
   # Apply all the overlays in order to the base fixed-point function pkgsFun
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/all-packages.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/all-packages.nix
new file mode 100644
index 000000000000..16834c4f7856
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/all-packages.nix
@@ -0,0 +1,10 @@
+self: super: {
+  foo1 = self.callPackage ({ someDrv }: someDrv) { };
+  foo2 = self.callPackage ./without-config.nix { };
+  foo3 = self.callPackage ({ someDrv, enableFoo }: someDrv) {
+    enableFoo = null;
+  };
+  foo4 = self.callPackage ./with-config.nix {
+    enableFoo = null;
+  };
+}
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/base/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/base/default.nix
new file mode 100644
index 000000000000..861260cdca4b
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/base/default.nix
@@ -0,0 +1 @@
+import <test-nixpkgs> { root = ./.; }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/base/pkgs/by-name/fo/foo1/package.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/base/pkgs/by-name/fo/foo1/package.nix
new file mode 100644
index 000000000000..a1b92efbbadb
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/base/pkgs/by-name/fo/foo1/package.nix
@@ -0,0 +1 @@
+{ someDrv }: someDrv
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/base/pkgs/by-name/fo/foo2/package.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/base/pkgs/by-name/fo/foo2/package.nix
new file mode 100644
index 000000000000..a1b92efbbadb
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/base/pkgs/by-name/fo/foo2/package.nix
@@ -0,0 +1 @@
+{ someDrv }: someDrv
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/base/pkgs/by-name/fo/foo3/package.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/base/pkgs/by-name/fo/foo3/package.nix
new file mode 100644
index 000000000000..a1b92efbbadb
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/base/pkgs/by-name/fo/foo3/package.nix
@@ -0,0 +1 @@
+{ someDrv }: someDrv
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/base/pkgs/by-name/fo/foo4/package.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/base/pkgs/by-name/fo/foo4/package.nix
new file mode 100644
index 000000000000..a1b92efbbadb
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/base/pkgs/by-name/fo/foo4/package.nix
@@ -0,0 +1 @@
+{ someDrv }: someDrv
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/default.nix
new file mode 100644
index 000000000000..861260cdca4b
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/default.nix
@@ -0,0 +1 @@
+import <test-nixpkgs> { root = ./.; }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/expected b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/expected
new file mode 100644
index 000000000000..96da50b52491
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/expected
@@ -0,0 +1,4 @@
+pkgs.foo1: This top-level package was previously defined in pkgs/by-name/fo/foo1/package.nix, but is now manually defined as `callPackage ... { }` (e.g. in `pkgs/top-level/all-packages.nix`). Please move the package back and remove the manual `callPackage`.
+pkgs.foo2: This top-level package was previously defined in pkgs/by-name/fo/foo2/package.nix, but is now manually defined as `callPackage ./without-config.nix { }` (e.g. in `pkgs/top-level/all-packages.nix`). Please move the package back and remove the manual `callPackage`.
+pkgs.foo3: This top-level package was previously defined in pkgs/by-name/fo/foo3/package.nix, but is now manually defined as `callPackage ... { ... }` (e.g. in `pkgs/top-level/all-packages.nix`). While the manual `callPackage` is still needed, it's not necessary to move the package files.
+pkgs.foo4: This top-level package was previously defined in pkgs/by-name/fo/foo4/package.nix, but is now manually defined as `callPackage ./with-config.nix { ... }` (e.g. in `pkgs/top-level/all-packages.nix`). While the manual `callPackage` is still needed, it's not necessary to move the package files.
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/pkgs/by-name/README.md b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/pkgs/by-name/README.md
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/pkgs/by-name/README.md
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/with-config.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/with-config.nix
new file mode 100644
index 000000000000..7cca53882ea5
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/with-config.nix
@@ -0,0 +1 @@
+{ someDrv, enableFoo }: someDrv
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/without-config.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/without-config.nix
new file mode 100644
index 000000000000..a1b92efbbadb
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/without-config.nix
@@ -0,0 +1 @@
+{ someDrv }: someDrv
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/multiple-failures/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/multiple-failures/default.nix
new file mode 100644
index 000000000000..861260cdca4b
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/multiple-failures/default.nix
@@ -0,0 +1 @@
+import <test-nixpkgs> { root = ./.; }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/multiple-failures/expected b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/multiple-failures/expected
new file mode 100644
index 000000000000..ff5d18556ef0
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/multiple-failures/expected
@@ -0,0 +1,13 @@
+pkgs/by-name/A: Invalid directory name "A", must be at most 2 ASCII characters consisting of a-z, 0-9, "-" or "_".
+pkgs/by-name/A/fo@: Invalid package directory name "fo@", must be ASCII characters consisting of a-z, A-Z, 0-9, "-" or "_".
+pkgs/by-name/A/fo@: Path foo is a symlink which cannot be resolved: No such file or directory (os error 2).
+pkgs/by-name/A/fo@: Path package.nix is a symlink pointing to a path outside the directory of that package.
+pkgs/by-name/aa: This is a file, but it should be a directory.
+pkgs/by-name/ba/bar: This path is a file, but it should be a directory.
+pkgs/by-name/ba/baz: "package.nix" must be a file.
+pkgs/by-name/ba/foo: Incorrect directory location, should be pkgs/by-name/fo/foo instead.
+pkgs/by-name/ba/foo: File package.nix at line 2 contains the path expression "/bar" which cannot be resolved: No such file or directory (os error 2).
+pkgs/by-name/ba/foo: File package.nix at line 3 contains the path expression "../." which may point outside the directory of that package.
+pkgs/by-name/ba/foo: File package.nix at line 4 contains the nix search path expression "<nixpkgs>" which may point outside the directory of that package.
+pkgs/by-name/ba/foo: File package.nix at line 5 contains the path expression "./${"test"}", which is not yet supported and may point outside the directory of that package.
+pkgs/by-name/fo/foo: Missing required "package.nix" file.
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/multiple-failures/pkgs/by-name/A/fo@/foo b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/multiple-failures/pkgs/by-name/A/fo@/foo
new file mode 120000
index 000000000000..c86c3f3551ec
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/multiple-failures/pkgs/by-name/A/fo@/foo
@@ -0,0 +1 @@
+none
\ No newline at end of file
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/multiple-failures/pkgs/by-name/A/fo@/package.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/multiple-failures/pkgs/by-name/A/fo@/package.nix
new file mode 120000
index 000000000000..f079163d158a
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/multiple-failures/pkgs/by-name/A/fo@/package.nix
@@ -0,0 +1 @@
+../../../../someDrv.nix
\ No newline at end of file
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/multiple-failures/pkgs/by-name/aa b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/multiple-failures/pkgs/by-name/aa
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/multiple-failures/pkgs/by-name/aa
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/multiple-failures/pkgs/by-name/ba/bar b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/multiple-failures/pkgs/by-name/ba/bar
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/multiple-failures/pkgs/by-name/ba/bar
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/multiple-failures/pkgs/by-name/ba/baz/package.nix/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/multiple-failures/pkgs/by-name/ba/baz/package.nix/default.nix
new file mode 100644
index 000000000000..a1b92efbbadb
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/multiple-failures/pkgs/by-name/ba/baz/package.nix/default.nix
@@ -0,0 +1 @@
+{ someDrv }: someDrv
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/multiple-failures/pkgs/by-name/ba/foo/package.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/multiple-failures/pkgs/by-name/ba/foo/package.nix
new file mode 100644
index 000000000000..31b4742f5914
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/multiple-failures/pkgs/by-name/ba/foo/package.nix
@@ -0,0 +1,6 @@
+{ someDrv }: someDrv // {
+  escapeAbsolute = /bar;
+  escapeRelative = ../.;
+  nixPath = <nixpkgs>;
+  pathWithSubexpr = ./${"test"};
+}
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/multiple-failures/pkgs/by-name/fo/foo/.git-keep b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/multiple-failures/pkgs/by-name/fo/foo/.git-keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/multiple-failures/pkgs/by-name/fo/foo/.git-keep
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/multiple-failures/someDrv.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/multiple-failures/someDrv.nix
new file mode 100644
index 000000000000..a1b92efbbadb
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/multiple-failures/someDrv.nix
@@ -0,0 +1 @@
+{ someDrv }: someDrv
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/all-packages.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/all-packages.nix
new file mode 100644
index 000000000000..069119ad4c7b
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/all-packages.nix
@@ -0,0 +1,11 @@
+self: super: {
+  before = self.callPackage ({ someDrv }: someDrv) { };
+  new1 = self.callPackage ({ someDrv }: someDrv) { };
+  new2 = self.callPackage ./without-config.nix { };
+  new3 = self.callPackage ({ someDrv, enableNew }: someDrv) {
+    enableNew = null;
+  };
+  new4 = self.callPackage ./with-config.nix {
+    enableNew = null;
+  };
+}
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/base/all-packages.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/base/all-packages.nix
new file mode 100644
index 000000000000..c2665d04d5f2
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/base/all-packages.nix
@@ -0,0 +1,5 @@
+self: super: {
+
+  before = self.callPackage ({ someDrv }: someDrv) { };
+
+}
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/base/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/base/default.nix
new file mode 100644
index 000000000000..861260cdca4b
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/base/default.nix
@@ -0,0 +1 @@
+import <test-nixpkgs> { root = ./.; }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/base/pkgs/by-name/README.md b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/base/pkgs/by-name/README.md
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/base/pkgs/by-name/README.md
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/default.nix
new file mode 100644
index 000000000000..861260cdca4b
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/default.nix
@@ -0,0 +1 @@
+import <test-nixpkgs> { root = ./.; }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/expected b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/expected
new file mode 100644
index 000000000000..3f294f26dfd8
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/expected
@@ -0,0 +1,4 @@
+pkgs.new1: This is a new top-level package of the form `callPackage ... { }`. Please define it in pkgs/by-name/ne/new1/package.nix instead. See `pkgs/by-name/README.md` for more details. Since the second `callPackage` argument is `{ }`, no manual `callPackage` (e.g. in `pkgs/top-level/all-packages.nix`) is needed anymore.
+pkgs.new2: This is a new top-level package of the form `callPackage ./without-config.nix { }`. Please define it in pkgs/by-name/ne/new2/package.nix instead. See `pkgs/by-name/README.md` for more details. Since the second `callPackage` argument is `{ }`, no manual `callPackage` (e.g. in `pkgs/top-level/all-packages.nix`) is needed anymore.
+pkgs.new3: This is a new top-level package of the form `callPackage ... { }`. Please define it in pkgs/by-name/ne/new3/package.nix instead. See `pkgs/by-name/README.md` for more details. Since the second `callPackage` argument is not `{ }`, the manual `callPackage` (e.g. in `pkgs/top-level/all-packages.nix`) is still needed.
+pkgs.new4: This is a new top-level package of the form `callPackage ./with-config.nix { }`. Please define it in pkgs/by-name/ne/new4/package.nix instead. See `pkgs/by-name/README.md` for more details. Since the second `callPackage` argument is not `{ }`, the manual `callPackage` (e.g. in `pkgs/top-level/all-packages.nix`) is still needed.
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/pkgs/by-name/README.md b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/pkgs/by-name/README.md
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/pkgs/by-name/README.md
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/with-config.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/with-config.nix
new file mode 100644
index 000000000000..65bcbf9928a2
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/with-config.nix
@@ -0,0 +1 @@
+{ someDrv, enableNew }: someDrv
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/without-config.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/without-config.nix
new file mode 100644
index 000000000000..a1b92efbbadb
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/without-config.nix
@@ -0,0 +1 @@
+{ someDrv }: someDrv
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/no-by-name/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/no-by-name/default.nix
index af25d1450122..861260cdca4b 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/no-by-name/default.nix
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/no-by-name/default.nix
@@ -1 +1 @@
-import ../mock-nixpkgs.nix { root = ./.; }
+import <test-nixpkgs> { root = ./.; }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/no-eval/all-packages.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/no-eval/all-packages.nix
new file mode 100644
index 000000000000..e2831c2d542e
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/no-eval/all-packages.nix
@@ -0,0 +1,3 @@
+self: super: {
+  iDontEval = throw "I don't eval";
+}
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/no-eval/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/no-eval/default.nix
new file mode 100644
index 000000000000..861260cdca4b
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/no-eval/default.nix
@@ -0,0 +1 @@
+import <test-nixpkgs> { root = ./.; }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/no-eval/pkgs/by-name/fo/foo/package.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/no-eval/pkgs/by-name/fo/foo/package.nix
new file mode 100644
index 000000000000..a1b92efbbadb
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/no-eval/pkgs/by-name/fo/foo/package.nix
@@ -0,0 +1 @@
+{ someDrv }: someDrv
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/non-attrs/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/non-attrs/default.nix
index af25d1450122..861260cdca4b 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/non-attrs/default.nix
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/non-attrs/default.nix
@@ -1 +1 @@
-import ../mock-nixpkgs.nix { root = ./.; }
+import <test-nixpkgs> { root = ./.; }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/non-derivation/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/non-derivation/default.nix
index af25d1450122..861260cdca4b 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/non-derivation/default.nix
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/non-derivation/default.nix
@@ -1 +1 @@
-import ../mock-nixpkgs.nix { root = ./.; }
+import <test-nixpkgs> { root = ./.; }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/one-letter/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/one-letter/default.nix
index af25d1450122..861260cdca4b 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/one-letter/default.nix
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/one-letter/default.nix
@@ -1 +1 @@
-import ../mock-nixpkgs.nix { root = ./.; }
+import <test-nixpkgs> { root = ./.; }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/only-callPackage-derivations/all-packages.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/only-callPackage-derivations/all-packages.nix
new file mode 100644
index 000000000000..5b1ed9d2ccda
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/only-callPackage-derivations/all-packages.nix
@@ -0,0 +1,16 @@
+self: super: {
+  alternateCallPackage = self.myScope.callPackage ({ myScopeValue, someDrv }:
+    assert myScopeValue;
+    someDrv
+  ) { };
+
+  myScope = self.lib.makeScope self.newScope (self: {
+    myScopeValue = true;
+  });
+
+  myPackages = self.callPackages ({ someDrv }: {
+    a = someDrv;
+    b = someDrv;
+  }) { };
+  inherit (self.myPackages) a b;
+}
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/only-callPackage-derivations/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/only-callPackage-derivations/default.nix
new file mode 100644
index 000000000000..861260cdca4b
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/only-callPackage-derivations/default.nix
@@ -0,0 +1 @@
+import <test-nixpkgs> { root = ./.; }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/only-callPackage-derivations/pkgs/by-name/README.md b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/only-callPackage-derivations/pkgs/by-name/README.md
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/only-callPackage-derivations/pkgs/by-name/README.md
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/override-different-file/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/override-different-file/default.nix
index af25d1450122..861260cdca4b 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/override-different-file/default.nix
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/override-different-file/default.nix
@@ -1 +1 @@
-import ../mock-nixpkgs.nix { root = ./.; }
+import <test-nixpkgs> { root = ./.; }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/override-empty-arg-gradual/base/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/override-empty-arg-gradual/base/default.nix
index 2875ea6327ef..861260cdca4b 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/override-empty-arg-gradual/base/default.nix
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/override-empty-arg-gradual/base/default.nix
@@ -1 +1 @@
-import ../../mock-nixpkgs.nix { root = ./.; }
+import <test-nixpkgs> { root = ./.; }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/override-empty-arg-gradual/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/override-empty-arg-gradual/default.nix
index af25d1450122..861260cdca4b 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/override-empty-arg-gradual/default.nix
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/override-empty-arg-gradual/default.nix
@@ -1 +1 @@
-import ../mock-nixpkgs.nix { root = ./.; }
+import <test-nixpkgs> { root = ./.; }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/override-empty-arg/base/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/override-empty-arg/base/default.nix
index 2875ea6327ef..861260cdca4b 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/override-empty-arg/base/default.nix
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/override-empty-arg/base/default.nix
@@ -1 +1 @@
-import ../../mock-nixpkgs.nix { root = ./.; }
+import <test-nixpkgs> { root = ./.; }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/override-empty-arg/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/override-empty-arg/default.nix
index af25d1450122..861260cdca4b 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/override-empty-arg/default.nix
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/override-empty-arg/default.nix
@@ -1 +1 @@
-import ../mock-nixpkgs.nix { root = ./.; }
+import <test-nixpkgs> { root = ./.; }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/override-no-call-package/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/override-no-call-package/default.nix
index af25d1450122..861260cdca4b 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/override-no-call-package/default.nix
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/override-no-call-package/default.nix
@@ -1 +1 @@
-import ../mock-nixpkgs.nix { root = ./.; }
+import <test-nixpkgs> { root = ./.; }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/override-no-file/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/override-no-file/default.nix
index af25d1450122..861260cdca4b 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/override-no-file/default.nix
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/override-no-file/default.nix
@@ -1 +1 @@
-import ../mock-nixpkgs.nix { root = ./.; }
+import <test-nixpkgs> { root = ./.; }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/override-success/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/override-success/default.nix
index af25d1450122..861260cdca4b 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/override-success/default.nix
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/override-success/default.nix
@@ -1 +1 @@
-import ../mock-nixpkgs.nix { root = ./.; }
+import <test-nixpkgs> { root = ./.; }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/package-dir-is-file/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/package-dir-is-file/default.nix
index af25d1450122..861260cdca4b 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/package-dir-is-file/default.nix
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/package-dir-is-file/default.nix
@@ -1 +1 @@
-import ../mock-nixpkgs.nix { root = ./.; }
+import <test-nixpkgs> { root = ./.; }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/package-nix-dir/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/package-nix-dir/default.nix
index af25d1450122..861260cdca4b 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/package-nix-dir/default.nix
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/package-nix-dir/default.nix
@@ -1 +1 @@
-import ../mock-nixpkgs.nix { root = ./.; }
+import <test-nixpkgs> { root = ./.; }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/ref-absolute/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/ref-absolute/default.nix
index af25d1450122..861260cdca4b 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/ref-absolute/default.nix
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/ref-absolute/default.nix
@@ -1 +1 @@
-import ../mock-nixpkgs.nix { root = ./.; }
+import <test-nixpkgs> { root = ./.; }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/ref-escape/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/ref-escape/default.nix
index af25d1450122..861260cdca4b 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/ref-escape/default.nix
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/ref-escape/default.nix
@@ -1 +1 @@
-import ../mock-nixpkgs.nix { root = ./.; }
+import <test-nixpkgs> { root = ./.; }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/ref-nix-path/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/ref-nix-path/default.nix
index af25d1450122..861260cdca4b 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/ref-nix-path/default.nix
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/ref-nix-path/default.nix
@@ -1 +1 @@
-import ../mock-nixpkgs.nix { root = ./.; }
+import <test-nixpkgs> { root = ./.; }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/ref-parse-failure/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/ref-parse-failure/default.nix
deleted file mode 100644
index af25d1450122..000000000000
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/ref-parse-failure/default.nix
+++ /dev/null
@@ -1 +0,0 @@
-import ../mock-nixpkgs.nix { root = ./.; }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/ref-parse-failure/expected b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/ref-parse-failure/expected
deleted file mode 100644
index 281aba009236..000000000000
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/ref-parse-failure/expected
+++ /dev/null
@@ -1 +0,0 @@
-pkgs/by-name/aa/aa: File invalid.nix could not be parsed by rnix: unexpected token at 28..29
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/ref-parse-failure/pkgs/by-name/aa/aa/invalid.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/ref-parse-failure/pkgs/by-name/aa/aa/invalid.nix
deleted file mode 100644
index ee6b002a529b..000000000000
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/ref-parse-failure/pkgs/by-name/aa/aa/invalid.nix
+++ /dev/null
@@ -1 +0,0 @@
-this is not a valid nix file!
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/ref-path-subexpr/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/ref-path-subexpr/default.nix
index af25d1450122..861260cdca4b 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/ref-path-subexpr/default.nix
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/ref-path-subexpr/default.nix
@@ -1 +1 @@
-import ../mock-nixpkgs.nix { root = ./.; }
+import <test-nixpkgs> { root = ./.; }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/ref-success/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/ref-success/default.nix
index af25d1450122..861260cdca4b 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/ref-success/default.nix
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/ref-success/default.nix
@@ -1 +1 @@
-import ../mock-nixpkgs.nix { root = ./.; }
+import <test-nixpkgs> { root = ./.; }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/shard-file/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/shard-file/default.nix
index af25d1450122..861260cdca4b 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/shard-file/default.nix
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/shard-file/default.nix
@@ -1 +1 @@
-import ../mock-nixpkgs.nix { root = ./.; }
+import <test-nixpkgs> { root = ./.; }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/sorted-order/all-packages.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/sorted-order/all-packages.nix
new file mode 100644
index 000000000000..688f52b9358f
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/sorted-order/all-packages.nix
@@ -0,0 +1,6 @@
+self: super: {
+  a = self.callPackage ./pkgs/by-name/a/a/package.nix { };
+  b = self.callPackage ({ someDrv }: someDrv) { };
+  c = self.callPackage ./pkgs/by-name/c/c/package.nix { };
+  d = self.callPackage ({ someDrv }: someDrv) { };
+}
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/sorted-order/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/sorted-order/default.nix
new file mode 100644
index 000000000000..861260cdca4b
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/sorted-order/default.nix
@@ -0,0 +1 @@
+import <test-nixpkgs> { root = ./.; }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/sorted-order/expected b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/sorted-order/expected
new file mode 100644
index 000000000000..349e9ad47c41
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/sorted-order/expected
@@ -0,0 +1,4 @@
+pkgs.a: This attribute is manually defined (most likely in pkgs/top-level/all-packages.nix), which is only allowed if the definition is of the form `pkgs.callPackage pkgs/by-name/a/a/package.nix { ... }` with a non-empty second argument.
+pkgs.b: This is a new top-level package of the form `callPackage ... { }`. Please define it in pkgs/by-name/b/b/package.nix instead. See `pkgs/by-name/README.md` for more details. Since the second `callPackage` argument is `{ }`, no manual `callPackage` (e.g. in `pkgs/top-level/all-packages.nix`) is needed anymore.
+pkgs.c: This attribute is manually defined (most likely in pkgs/top-level/all-packages.nix), which is only allowed if the definition is of the form `pkgs.callPackage pkgs/by-name/c/c/package.nix { ... }` with a non-empty second argument.
+pkgs.d: This is a new top-level package of the form `callPackage ... { }`. Please define it in pkgs/by-name/d/d/package.nix instead. See `pkgs/by-name/README.md` for more details. Since the second `callPackage` argument is `{ }`, no manual `callPackage` (e.g. in `pkgs/top-level/all-packages.nix`) is needed anymore.
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/sorted-order/pkgs/by-name/a/a/package.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/sorted-order/pkgs/by-name/a/a/package.nix
new file mode 100644
index 000000000000..a1b92efbbadb
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/sorted-order/pkgs/by-name/a/a/package.nix
@@ -0,0 +1 @@
+{ someDrv }: someDrv
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/sorted-order/pkgs/by-name/c/c/package.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/sorted-order/pkgs/by-name/c/c/package.nix
new file mode 100644
index 000000000000..a1b92efbbadb
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/sorted-order/pkgs/by-name/c/c/package.nix
@@ -0,0 +1 @@
+{ someDrv }: someDrv
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/success/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/success/default.nix
index af25d1450122..861260cdca4b 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/success/default.nix
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/success/default.nix
@@ -1 +1 @@
-import ../mock-nixpkgs.nix { root = ./.; }
+import <test-nixpkgs> { root = ./.; }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/symlink-escape/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/symlink-escape/default.nix
index af25d1450122..861260cdca4b 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/symlink-escape/default.nix
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/symlink-escape/default.nix
@@ -1 +1 @@
-import ../mock-nixpkgs.nix { root = ./.; }
+import <test-nixpkgs> { root = ./.; }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/symlink-invalid/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/symlink-invalid/default.nix
index af25d1450122..861260cdca4b 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/symlink-invalid/default.nix
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/symlink-invalid/default.nix
@@ -1 +1 @@
-import ../mock-nixpkgs.nix { root = ./.; }
+import <test-nixpkgs> { root = ./.; }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/symlink-invalid/expected b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/symlink-invalid/expected
index f622f3e7fd6d..c1e7a28205a7 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/symlink-invalid/expected
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/symlink-invalid/expected
@@ -1 +1 @@
-pkgs/by-name/fo/foo: Path foo.nix is a symlink which cannot be resolved: No such file or directory (os error 2).
+pkgs/by-name/fo/foo: Path foo is a symlink which cannot be resolved: No such file or directory (os error 2).
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/symlink-invalid/pkgs/by-name/fo/foo/foo b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/symlink-invalid/pkgs/by-name/fo/foo/foo
new file mode 120000
index 000000000000..c86c3f3551ec
--- /dev/null
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/symlink-invalid/pkgs/by-name/fo/foo/foo
@@ -0,0 +1 @@
+none
\ No newline at end of file
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/symlink-invalid/pkgs/by-name/fo/foo/foo.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/symlink-invalid/pkgs/by-name/fo/foo/foo.nix
deleted file mode 120000
index 49cd425a8cdb..000000000000
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/symlink-invalid/pkgs/by-name/fo/foo/foo.nix
+++ /dev/null
@@ -1 +0,0 @@
-none.nix
\ No newline at end of file
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/uppercase/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/uppercase/default.nix
index af25d1450122..861260cdca4b 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/uppercase/default.nix
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/uppercase/default.nix
@@ -1 +1 @@
-import ../mock-nixpkgs.nix { root = ./.; }
+import <test-nixpkgs> { root = ./.; }
diff --git a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/with-readme/default.nix b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/with-readme/default.nix
index af25d1450122..861260cdca4b 100644
--- a/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/with-readme/default.nix
+++ b/nixpkgs/pkgs/test/nixpkgs-check-by-name/tests/with-readme/default.nix
@@ -1 +1 @@
-import ../mock-nixpkgs.nix { root = ./.; }
+import <test-nixpkgs> { root = ./.; }
diff --git a/nixpkgs/pkgs/test/release/default.nix b/nixpkgs/pkgs/test/release/default.nix
index f112ee6b9212..2ab730b5c482 100644
--- a/nixpkgs/pkgs/test/release/default.nix
+++ b/nixpkgs/pkgs/test/release/default.nix
@@ -31,13 +31,13 @@ pkgs.runCommand "all-attrs-eval-under-tryEval" {
 
   nix-store --init
 
-  cp -r ${pkgs-path + "/lib"} lib
-  cp -r ${pkgs-path + "/pkgs"} pkgs
-  cp -r ${pkgs-path + "/default.nix"} default.nix
-  cp -r ${pkgs-path + "/nixos"} nixos
-  cp -r ${pkgs-path + "/maintainers"} maintainers
-  cp -r ${pkgs-path + "/.version"} .version
-  cp -r ${pkgs-path + "/doc"} doc
+  cp -r ${pkgs-path}/lib lib
+  cp -r ${pkgs-path}/pkgs pkgs
+  cp -r ${pkgs-path}/default.nix default.nix
+  cp -r ${pkgs-path}/nixos nixos
+  cp -r ${pkgs-path}/maintainers maintainers
+  cp -r ${pkgs-path}/.version .version
+  cp -r ${pkgs-path}/doc doc
   echo "Running pkgs/top-level/release-attrpaths-superset.nix"
   nix-instantiate --eval --strict --json pkgs/top-level/release-attrpaths-superset.nix -A names > /dev/null