diff --git a/flake.nix b/flake.nix index 580f572ff32c6..d1e2934f7b336 100644 --- a/flake.nix +++ b/flake.nix @@ -9,8 +9,8 @@ nixpkgs = self; }; - libVersionInfoOverlay = import ./lib/flake-version-info.nix self; - lib = (import ./lib).extend libVersionInfoOverlay; + libFlakeInfoOverlay = import ./lib/flake-info.nix self; + lib = (import ./lib).extend libFlakeInfoOverlay; forAllSystems = lib.genAttrs lib.systems.flakeExposed; in @@ -72,7 +72,7 @@ # information rich. legacyPackages = forAllSystems (system: (import ./. { inherit system; }).extend (final: prev: { - lib = prev.lib.extend libVersionInfoOverlay; + lib = prev.lib.extend libFlakeInfoOverlay; }) ); diff --git a/lib/flake-version-info.nix b/lib/flake-info.nix similarity index 53% rename from lib/flake-version-info.nix rename to lib/flake-info.nix index de15be94bee8a..dd57462899aa3 100644 --- a/lib/flake-version-info.nix +++ b/lib/flake-info.nix @@ -16,5 +16,16 @@ finalLib: prevLib: # lib overlay versionSuffix = ".${finalLib.substring 0 8 (self.lastModifiedDate or "19700101")}.${self.shortRev or "dirty"}"; revisionWithDefault = default: self.rev or default; + + # This overrides the nixpkgsStorePathString logic in lib/trivial.nix for + # the special case of flakes, where we are in pure eval mode and thus + # would not be able to use builtins.storePath to establish a dependency on + # this nixpkgs' sources (https://github.com/NixOS/nix/issues/5868). + # + # However, in this particular case, due to being used from a flake, we *do* + # have a string with context for our own sources in the store in the + # `outPath` of the `self` flake input, which we obtain by calling toString + # on it. + nixpkgsStorePathString = toString self; }; } diff --git a/lib/flake.nix b/lib/flake.nix index ca09ed5f4a420..eac8e855bf6f7 100644 --- a/lib/flake.nix +++ b/lib/flake.nix @@ -5,6 +5,6 @@ let lib0 = import ./.; in { - lib = lib0.extend (import ./flake-version-info.nix self); + lib = lib0.extend (import ./flake-info.nix self); }; } diff --git a/lib/trivial.nix b/lib/trivial.nix index b2796096e8bc1..90178deee8471 100644 --- a/lib/trivial.nix +++ b/lib/trivial.nix @@ -232,6 +232,48 @@ in { nixpkgsVersion = builtins.trace "`lib.nixpkgsVersion` is deprecated, use `lib.version` instead!" version; + /* The store path to this nixpkgs as a string with context. This can be used + to incur a dependency on this nixpkgs, for example, to symlink it into a + NixOS closure. + + If this nixpkgs is used as a flake directly (via `nixpkgs.lib.trivial` + rather than via `import nixpkgs`), or it is already in the Nix store in + non-flake usage such as being fetched via `builtins.fetchTarball`, + evaluating this attribute is quick and does not copy anything new to the + store. + + This is different than pkgs.path if nixpkgs is already in the Nix store, + since pkgs.path is a path to nixpkgs rather than a string-with-context, + and thus its usage typically, undesirably, results in copying this + nixpkgs. + + See: https://github.com/NixOS/nix/issues/5868 + https://github.com/NixOS/nix/issues/9428 + + Type: String + */ + + nixpkgsStorePathString = + # Note: this is overlayed by lib/flake-info.nix if nixpkgs is used directly + # as a flake. + if lib.strings.isStorePath (toString ../.) then + # While `toString ../.` is already a store path here, it doesn't contain + # a dependency on that store path in its string context. + # We can use `builtins.storePath` to establishes a dependency on an + # existing store path that nixpkgs was imported with. + if lib.trivial.inPureEvalMode then + # However, in pure eval mode, that builtin is not currently supported, see https://github.com/NixOS/nix/issues/5868. + # So we fall back to string interpolation of a path, which copies the path that's already in the store to the store once more, + # which is slow and gives it a doubly-hashed base name, but there's not much we can do + # See also https://github.com/NixOS/nix/issues/9428 + "${../.}" + else + # Only outside pure eval we can actually use builtins.storePath, which can re-use the existing store path + builtins.storePath ../. + else + # Here ../. is not in the store already, so we need to use string interpolation to copy the path to the store. + "${../.}"; + /* Determine whether the function is being called from inside a Nix shell.