about summary refs log tree commit diff
path: root/pkgs/test
diff options
context:
space:
mode:
authorSilvan Mosberger <silvan.mosberger@tweag.io>2024-01-05 01:03:37 +0100
committerSilvan Mosberger <silvan.mosberger@tweag.io>2024-01-10 19:29:26 +0100
commit57afdc545bdc9894754c51265ab993da556915e4 (patch)
treebe5867408d24fc4b8a0d1452d421d5a6cd24ab72 /pkgs/test
parent69fc71a82c0e3acba5045666b48cdaf5adc8d4c3 (diff)
downloadnixlib-57afdc545bdc9894754c51265ab993da556915e4.tar
nixlib-57afdc545bdc9894754c51265ab993da556915e4.tar.gz
nixlib-57afdc545bdc9894754c51265ab993da556915e4.tar.bz2
nixlib-57afdc545bdc9894754c51265ab993da556915e4.tar.lz
nixlib-57afdc545bdc9894754c51265ab993da556915e4.tar.xz
nixlib-57afdc545bdc9894754c51265ab993da556915e4.tar.zst
nixlib-57afdc545bdc9894754c51265ab993da556915e4.zip
tests.nixpkgs-check-by-name: Enforce pkgs/by-name for new packages
Diffstat (limited to 'pkgs/test')
-rw-r--r--pkgs/test/nixpkgs-check-by-name/README.md2
-rw-r--r--pkgs/test/nixpkgs-check-by-name/src/eval.nix10
-rw-r--r--pkgs/test/nixpkgs-check-by-name/src/eval.rs69
-rw-r--r--pkgs/test/nixpkgs-check-by-name/src/nixpkgs_problem.rs61
-rw-r--r--pkgs/test/nixpkgs-check-by-name/src/ratchet.rs52
-rw-r--r--pkgs/test/nixpkgs-check-by-name/tests/internalCallPackage/all-packages.nix3
-rw-r--r--pkgs/test/nixpkgs-check-by-name/tests/internalCallPackage/default.nix1
-rw-r--r--pkgs/test/nixpkgs-check-by-name/tests/internalCallPackage/expected1
-rw-r--r--pkgs/test/nixpkgs-check-by-name/tests/internalCallPackage/foo.nix1
-rw-r--r--pkgs/test/nixpkgs-check-by-name/tests/internalCallPackage/pkgs/by-name/README.md0
-rw-r--r--pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/all-packages.nix10
-rw-r--r--pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/base/default.nix1
-rw-r--r--pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/base/pkgs/by-name/fo/foo1/package.nix1
-rw-r--r--pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/base/pkgs/by-name/fo/foo2/package.nix1
-rw-r--r--pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/base/pkgs/by-name/fo/foo3/package.nix1
-rw-r--r--pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/base/pkgs/by-name/fo/foo4/package.nix1
-rw-r--r--pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/default.nix1
-rw-r--r--pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/expected4
-rw-r--r--pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/pkgs/by-name/README.md0
-rw-r--r--pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/with-config.nix1
-rw-r--r--pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/without-config.nix1
-rw-r--r--pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/all-packages.nix11
-rw-r--r--pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/base/all-packages.nix5
-rw-r--r--pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/base/default.nix1
-rw-r--r--pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/base/pkgs/by-name/README.md0
-rw-r--r--pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/default.nix1
-rw-r--r--pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/expected4
-rw-r--r--pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/pkgs/by-name/README.md0
-rw-r--r--pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/with-config.nix1
-rw-r--r--pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/without-config.nix1
-rw-r--r--pkgs/test/nixpkgs-check-by-name/tests/no-eval/all-packages.nix3
-rw-r--r--pkgs/test/nixpkgs-check-by-name/tests/no-eval/default.nix1
-rw-r--r--pkgs/test/nixpkgs-check-by-name/tests/no-eval/pkgs/by-name/fo/foo/package.nix1
33 files changed, 241 insertions, 10 deletions
diff --git a/pkgs/test/nixpkgs-check-by-name/README.md b/pkgs/test/nixpkgs-check-by-name/README.md
index 871847bd74cc..d779529c7baf 100644
--- a/pkgs/test/nixpkgs-check-by-name/README.md
+++ b/pkgs/test/nixpkgs-check-by-name/README.md
@@ -45,6 +45,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
 
diff --git a/pkgs/test/nixpkgs-check-by-name/src/eval.nix b/pkgs/test/nixpkgs-check-by-name/src/eval.nix
index 9c0248486c66..f13dbd167a00 100644
--- a/pkgs/test/nixpkgs-check-by-name/src/eval.nix
+++ b/pkgs/test/nixpkgs-check-by-name/src/eval.nix
@@ -93,10 +93,18 @@ let
   # 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 = map (name:
+    let
+      output = attrInfo name pkgs.${name};
+      result = builtins.tryEval (builtins.deepSeq output null);
+    in
     [
       name
       {
-        NonByName = null;
+        NonByName =
+          if result.success then
+            { EvalSuccess = output; }
+          else
+            { EvalFailure = null; };
       }
     ]
   ) (builtins.attrNames (builtins.removeAttrs pkgs attrs));
diff --git a/pkgs/test/nixpkgs-check-by-name/src/eval.rs b/pkgs/test/nixpkgs-check-by-name/src/eval.rs
index fdf74eba2cb5..39653a871604 100644
--- a/pkgs/test/nixpkgs-check-by-name/src/eval.rs
+++ b/pkgs/test/nixpkgs-check-by-name/src/eval.rs
@@ -16,7 +16,14 @@ enum Attribute {
     /// An attribute that should be defined via pkgs/by-name
     ByName(ByNameAttribute),
     /// An attribute not defined via pkgs/by-name
-    NonByName,
+    NonByName(NonByNameAttribute),
+}
+
+#[derive(Deserialize)]
+enum NonByNameAttribute {
+    /// The attribute doesn't evaluate
+    EvalFailure,
+    EvalSuccess(AttributeInfo),
 }
 
 #[derive(Deserialize)]
@@ -145,11 +152,63 @@ pub fn check_values(
             use AttributeInfo::*;
             use ByNameAttribute::*;
             use CallPackageVariant::*;
+            use NonByNameAttribute::*;
 
             let check_result = match attribute_value {
-                NonByName => Success(ratchet::Package {
-                    empty_non_auto_called: Tight,
-                }),
+                // 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 an odd case when _internalCallByNamePackageFile is used to define a package.
+                        CallPackage(CallPackageInfo {
+                            call_package_variant: Auto,
+                            ..
+                        }) => NixpkgsProblem::InternalCallPackageUsed {
+                            attr_name: attribute_name.clone(),
+                        }
+                        .into(),
+                        // 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(),
@@ -182,6 +241,7 @@ pub fn check_values(
                     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 {
@@ -198,6 +258,7 @@ pub fn check_values(
                                     } else {
                                         Tight
                                     },
+                                    uses_by_name: Tight,
                                 })
                             } else {
                                 NixpkgsProblem::WrongCallPackage {
diff --git a/pkgs/test/nixpkgs-check-by-name/src/nixpkgs_problem.rs b/pkgs/test/nixpkgs-check-by-name/src/nixpkgs_problem.rs
index 2344a8cc1325..127583078074 100644
--- a/pkgs/test/nixpkgs-check-by-name/src/nixpkgs_problem.rs
+++ b/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,19 @@ pub enum NixpkgsProblem {
         text: String,
         io_error: io::Error,
     },
+    InternalCallPackageUsed {
+        attr_name: String,
+    },
+    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 +227,53 @@ impl fmt::Display for NixpkgsProblem {
                     subpath.display(),
                     text,
                 ),
+            NixpkgsProblem::InternalCallPackageUsed { attr_name } =>
+                write!(
+                    f,
+                    "pkgs.{attr_name}: This attribute is defined using `_internalCallByNamePackageFile`, which is an internal function not intended for manual use.",
+                ),
+            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/pkgs/test/nixpkgs-check-by-name/src/ratchet.rs b/pkgs/test/nixpkgs-check-by-name/src/ratchet.rs
index 46d71baae1b5..f8c129626cc0 100644
--- a/pkgs/test/nixpkgs-check-by-name/src/ratchet.rs
+++ b/pkgs/test/nixpkgs-check-by-name/src/ratchet.rs
@@ -6,6 +6,7 @@ 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)]
@@ -33,16 +34,26 @@ impl Nixpkgs {
 pub struct Package {
     /// The ratchet value for the check for non-auto-called empty arguments
     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 top-level package
     pub fn compare(name: &str, optional_from: Option<&Self>, to: &Self) -> Validation<()> {
-        RatchetState::<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,
+            ),
+        ])
     }
 }
 
@@ -102,3 +113,34 @@ impl ToNixpkgsProblem for EmptyNonAutoCalled {
         }
     }
 }
+
+/// 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::NewPackageNotUsingByName {
+                package_name: name.to_owned(),
+                call_package_path: a.call_package_path.clone(),
+                empty_arg: a.empty_arg,
+            }
+        }
+    }
+}
diff --git a/pkgs/test/nixpkgs-check-by-name/tests/internalCallPackage/all-packages.nix b/pkgs/test/nixpkgs-check-by-name/tests/internalCallPackage/all-packages.nix
new file mode 100644
index 000000000000..95478a87fb32
--- /dev/null
+++ b/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/pkgs/test/nixpkgs-check-by-name/tests/internalCallPackage/default.nix b/pkgs/test/nixpkgs-check-by-name/tests/internalCallPackage/default.nix
new file mode 100644
index 000000000000..af25d1450122
--- /dev/null
+++ b/pkgs/test/nixpkgs-check-by-name/tests/internalCallPackage/default.nix
@@ -0,0 +1 @@
+import ../mock-nixpkgs.nix { root = ./.; }
diff --git a/pkgs/test/nixpkgs-check-by-name/tests/internalCallPackage/expected b/pkgs/test/nixpkgs-check-by-name/tests/internalCallPackage/expected
new file mode 100644
index 000000000000..404795ee5c79
--- /dev/null
+++ b/pkgs/test/nixpkgs-check-by-name/tests/internalCallPackage/expected
@@ -0,0 +1 @@
+pkgs.foo: This attribute is defined using `_internalCallByNamePackageFile`, which is an internal function not intended for manual use.
diff --git a/pkgs/test/nixpkgs-check-by-name/tests/internalCallPackage/foo.nix b/pkgs/test/nixpkgs-check-by-name/tests/internalCallPackage/foo.nix
new file mode 100644
index 000000000000..a1b92efbbadb
--- /dev/null
+++ b/pkgs/test/nixpkgs-check-by-name/tests/internalCallPackage/foo.nix
@@ -0,0 +1 @@
+{ someDrv }: someDrv
diff --git a/pkgs/test/nixpkgs-check-by-name/tests/internalCallPackage/pkgs/by-name/README.md b/pkgs/test/nixpkgs-check-by-name/tests/internalCallPackage/pkgs/by-name/README.md
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/pkgs/test/nixpkgs-check-by-name/tests/internalCallPackage/pkgs/by-name/README.md
diff --git a/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/all-packages.nix b/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/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/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/base/default.nix b/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/base/default.nix
new file mode 100644
index 000000000000..2875ea6327ef
--- /dev/null
+++ b/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/base/default.nix
@@ -0,0 +1 @@
+import ../../mock-nixpkgs.nix { root = ./.; }
diff --git a/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/base/pkgs/by-name/fo/foo1/package.nix b/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/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/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/base/pkgs/by-name/fo/foo2/package.nix b/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/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/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/base/pkgs/by-name/fo/foo3/package.nix b/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/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/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/base/pkgs/by-name/fo/foo4/package.nix b/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/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/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/default.nix b/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/default.nix
new file mode 100644
index 000000000000..af25d1450122
--- /dev/null
+++ b/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/default.nix
@@ -0,0 +1 @@
+import ../mock-nixpkgs.nix { root = ./.; }
diff --git a/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/expected b/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/expected
new file mode 100644
index 000000000000..96da50b52491
--- /dev/null
+++ b/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/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/pkgs/by-name/README.md b/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/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/pkgs/by-name/README.md
diff --git a/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/with-config.nix b/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/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/with-config.nix
@@ -0,0 +1 @@
+{ someDrv, enableFoo }: someDrv
diff --git a/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/without-config.nix b/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/pkgs/test/nixpkgs-check-by-name/tests/move-to-non-by-name/without-config.nix
@@ -0,0 +1 @@
+{ someDrv }: someDrv
diff --git a/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/all-packages.nix b/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/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/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/base/all-packages.nix b/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/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/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/base/default.nix b/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/base/default.nix
new file mode 100644
index 000000000000..2875ea6327ef
--- /dev/null
+++ b/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/base/default.nix
@@ -0,0 +1 @@
+import ../../mock-nixpkgs.nix { root = ./.; }
diff --git a/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/base/pkgs/by-name/README.md b/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/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/base/pkgs/by-name/README.md
diff --git a/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/default.nix b/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/default.nix
new file mode 100644
index 000000000000..af25d1450122
--- /dev/null
+++ b/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/default.nix
@@ -0,0 +1 @@
+import ../mock-nixpkgs.nix { root = ./.; }
diff --git a/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/expected b/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/expected
new file mode 100644
index 000000000000..3f294f26dfd8
--- /dev/null
+++ b/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/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/pkgs/by-name/README.md b/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/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/pkgs/by-name/README.md
diff --git a/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/with-config.nix b/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/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/with-config.nix
@@ -0,0 +1 @@
+{ someDrv, enableNew }: someDrv
diff --git a/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/without-config.nix b/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/pkgs/test/nixpkgs-check-by-name/tests/new-package-non-by-name/without-config.nix
@@ -0,0 +1 @@
+{ someDrv }: someDrv
diff --git a/pkgs/test/nixpkgs-check-by-name/tests/no-eval/all-packages.nix b/pkgs/test/nixpkgs-check-by-name/tests/no-eval/all-packages.nix
new file mode 100644
index 000000000000..e2831c2d542e
--- /dev/null
+++ b/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/pkgs/test/nixpkgs-check-by-name/tests/no-eval/default.nix b/pkgs/test/nixpkgs-check-by-name/tests/no-eval/default.nix
new file mode 100644
index 000000000000..af25d1450122
--- /dev/null
+++ b/pkgs/test/nixpkgs-check-by-name/tests/no-eval/default.nix
@@ -0,0 +1 @@
+import ../mock-nixpkgs.nix { root = ./.; }
diff --git a/pkgs/test/nixpkgs-check-by-name/tests/no-eval/pkgs/by-name/fo/foo/package.nix b/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/pkgs/test/nixpkgs-check-by-name/tests/no-eval/pkgs/by-name/fo/foo/package.nix
@@ -0,0 +1 @@
+{ someDrv }: someDrv