Skip to content

Commit

Permalink
Ignore local registries for lock file generation
Browse files Browse the repository at this point in the history
When resolving indirect flake references like `nixpkgs` in `flake.nix`
files, Nix will no longer use the system and user flake registries. It
will only use the global flake registry and overrides given on the
command line via `--override-flake`.
  • Loading branch information
edolstra authored and Mic92 committed Dec 16, 2024
1 parent ab5a9cf commit 7ddf730
Show file tree
Hide file tree
Showing 8 changed files with 51 additions and 7 deletions.
22 changes: 22 additions & 0 deletions doc/manual/rl-next/ignore-local-registries.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
synopsis: "Flake lock file generation now ignores local registries"
prs: [12019]
---

When resolving indirect flake references like `nixpkgs` in `flake.nix` files, Nix will no longer use the system and user flake registries. It will only use the global flake registry and overrides given on the command line via `--override-flake`.

This avoids accidents where users have local registry overrides that map `nixpkgs` to a `path:` flake in the local file system, which then end up in committed lock files pushed to other users.

In the future, we may remove the use of the registry during lock file generation altogether. It's better to explicitly specify the URL of a flake input. For example, instead of
```nix
{
outputs = { self, nixpkgs }: { ... };
}
```
write
```nix
{
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";
outputs = { self, nixpkgs }: { ... };
}
```
4 changes: 3 additions & 1 deletion src/libfetchers/registry.cc
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,8 @@ Registries getRegistries(const Settings & settings, ref<Store> store)

std::pair<Input, Attrs> lookupInRegistries(
ref<Store> store,
const Input & _input)
const Input & _input,
const RegistryFilter & filter)
{
Attrs extraAttrs;
int n = 0;
Expand All @@ -190,6 +191,7 @@ std::pair<Input, Attrs> lookupInRegistries(
if (n > 100) throw Error("cycle detected in flake registry for '%s'", input.to_string());

for (auto & registry : getRegistries(*input.settings, store)) {
if (filter && !filter(registry->type)) continue;
// FIXME: O(n)
for (auto & entry : registry->entries) {
if (entry.exact) {
Expand Down
9 changes: 8 additions & 1 deletion src/libfetchers/registry.hh
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,15 @@ void overrideRegistry(
const Input & to,
const Attrs & extraAttrs);

using RegistryFilter = std::function<bool(Registry::RegistryType)>;

/**
* Rewrite a flakeref using the registries. If `filter` is set, only
* use the registries for which the filter function returns true.
*/
std::pair<Input, Attrs> lookupInRegistries(
ref<Store> store,
const Input & input);
const Input & input,
const RegistryFilter & filter = {});

}
8 changes: 7 additions & 1 deletion src/libflake/flake/flake.cc
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,13 @@ static std::tuple<StorePath, FlakeRef, FlakeRef> fetchOrSubstituteTree(
fetched.emplace(originalRef.fetchTree(state.store));
} else {
if (allowLookup) {
resolvedRef = originalRef.resolve(state.store);
resolvedRef = originalRef.resolve(
state.store,
[](fetchers::Registry::RegistryType type) {
/* Only use the global registry and CLI flags
to resolve indirect flakerefs. */
return type == fetchers::Registry::Flag || type == fetchers::Registry::Global;
});
auto fetchedResolved = lookupInFlakeCache(flakeCache, originalRef);
if (!fetchedResolved) fetchedResolved.emplace(resolvedRef.fetchTree(state.store));
flakeCache.push_back({resolvedRef, *fetchedResolved});
Expand Down
5 changes: 3 additions & 2 deletions src/libflake/flake/flakeref.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
#include "url.hh"
#include "url-parts.hh"
#include "fetchers.hh"
#include "registry.hh"

namespace nix {

Expand Down Expand Up @@ -36,7 +35,9 @@ std::ostream & operator << (std::ostream & str, const FlakeRef & flakeRef)
return str;
}

FlakeRef FlakeRef::resolve(ref<Store> store) const
FlakeRef FlakeRef::resolve(
ref<Store> store,
const fetchers::RegistryFilter & filter) const
{
auto [input2, extraAttrs] = lookupInRegistries(store, input);
return FlakeRef(std::move(input2), fetchers::maybeGetStrAttr(extraAttrs, "dir").value_or(subdir));
Expand Down
5 changes: 4 additions & 1 deletion src/libflake/flake/flakeref.hh
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "types.hh"
#include "fetchers.hh"
#include "outputs-spec.hh"
#include "registry.hh"

namespace nix {

Expand Down Expand Up @@ -57,7 +58,9 @@ struct FlakeRef

fetchers::Attrs toAttrs() const;

FlakeRef resolve(ref<Store> store) const;
FlakeRef resolve(
ref<Store> store,
const fetchers::RegistryFilter & filter = {}) const;

static FlakeRef fromAttrs(
const fetchers::Settings & fetchSettings,
Expand Down
3 changes: 2 additions & 1 deletion src/nix/flake.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,8 @@ can occur in *locked* flake references and are available to Nix code:

Currently the `type` attribute can be one of the following:

* `indirect`: *The default*. Indirection through the flake registry.
* `indirect`: *The default*. These are symbolic references to flakes
that are looked up in [the flake registries](./nix3-registry.md).
These have the form

```
Expand Down
2 changes: 2 additions & 0 deletions src/nix/registry.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ highest precedence:
* Overrides specified on the command line using the option
`--override-flake`.

Note that the system and user registries are not used to resolve flake references in `flake.nix`. They are only used to resolve flake references on the command line.

# Registry format

A registry is a JSON file with the following format:
Expand Down

0 comments on commit 7ddf730

Please sign in to comment.