diff --git a/pkgs/top-level/config.nix b/pkgs/top-level/config.nix index f2066315efb5..de13c0a29993 100644 --- a/pkgs/top-level/config.nix +++ b/pkgs/top-level/config.nix @@ -58,6 +58,34 @@ let internal = true; }; + attrPathsDisallowedForInternalUse = mkOption { + type = types.listOf ( + types.submodule { + options.attrPath = lib.mkOption { + type = types.listOf types.str; + description = '' + Attribute path to disallow. + ''; + }; + options.reason = lib.mkOption { + type = types.nullOr types.str; + default = null; + example = /* because */ "it's dangerous."; + description = '' + Reason for it being disallowed. + ''; + }; + } + ); + internal = true; + default = [ ]; + description = '' + List of attribute paths that may not be used by other packages in Nixpkgs. + + Should usually only be defined by Nixpkgs CI. + ''; + }; + # Config options warnUndeclaredOptions = mkOption { diff --git a/pkgs/top-level/default.nix b/pkgs/top-level/default.nix index 443496f650fb..4d44abadd961 100644 --- a/pkgs/top-level/default.nix +++ b/pkgs/top-level/default.nix @@ -214,7 +214,28 @@ let ; }; - pkgs = boot stages; + fixedPoint = boot stages; + + pkgs = + if config.attrPathsDisallowedForInternalUse == [ ] then + fixedPoint + else + # See ./stage.nix, which replaced config.attrPathsDisallowedForInternalUse with aborts. + # We replace these attribute paths with their original derivations again, + # because CI would just error out from the aborting attributes themselves. + # Internally all packages still see the aborting attributes if used as dependencies, + # because we do this here after the fixed-point is calculated. + # Note that we don't want to remove the attributes entirely like what aliases.nix does, + # because unlike aliases, CI still needs to check the packages to evaluate at all, + # which it wouldn't if they're removed entirely. + lib.updateManyAttrsByPath + (map (attrs: { + path = attrs.attrPath; + update = + _: + lib.getAttrFromPath attrs.attrPath fixedPoint.__internalBeforeInternallyDisallowedAttrPathsOverlay; + }) config.attrPathsDisallowedForInternalUse) + (removeAttrs fixedPoint [ "__internalBeforeInternallyDisallowedAttrPathsOverlay" ]); in checked pkgs diff --git a/pkgs/top-level/stage.nix b/pkgs/top-level/stage.nix index 4b0abd0361c6..35929783e7c9 100644 --- a/pkgs/top-level/stage.nix +++ b/pkgs/top-level/stage.nix @@ -309,6 +309,31 @@ let }; }; + # Replaces the attributes in config.attrPathsDisallowedForInternalUse with aborts. + # Not throws because those would be ignored by nix-env, which is what CI uses to evaluate everything + # See also ./default.nix, where these attributes are added back again so they're still checked by CI + internallyDisallowedAttrPathsOverlay = + final: prev: + if config.attrPathsDisallowedForInternalUse == [ ] then + { } + else + { + # So that ./default.nix can add them back again outside the fixed point + # Don't use this in packages! + __internalBeforeInternallyDisallowedAttrPathsOverlay = prev; + } + // lib.updateManyAttrsByPath (map ( + { attrPath, reason }: + { + path = attrPath; + update = + _: + abort "${lib.concatStringsSep "." attrPath} is disallowed from being used within Nixpkgs${ + lib.optionalString (reason != null) ", because ${reason}" + }"; + } + ) config.attrPathsDisallowedForInternalUse) prev; + # The complete chain of package set builders, applied from top to bottom. # stdenvOverlays must be last as it brings package forward from the # previous bootstrapping phases which have already been overlaid. @@ -324,6 +349,7 @@ let aliases variants configOverrides + internallyDisallowedAttrPathsOverlay ] ++ overlays ++ [