Skip to content

Reuse input lock files #7730

Open
Open
@roberth

Description

(was: Solve dev(/test) dependencies and bloated, diverging lock files, by reconsidering the flattened lock file)

Is your feature request related to a problem? Please describe.

We've previously identified issues with the way the lock file currently works.

  • Irrelevant development dependencies are added to the lock files of all dependent flakes
  • Mututally dependent flakes cause diverging lock files as each lock file update incorporates a new version with a chain of irrelevant dependencies.
    • issue?
  • Some users just complain about the size of their lock file. Partly pedantic, but they're actually kind of right:
  • Ideally, lock file changes are reviewable, so that nothing weird creeps in through contributions that have such updates.

Describe the solution you'd like

We may consider two scenarios; one with follows and one without. Let's start without follows.

Observing that we do not exploit the apparent benefit of knowing all inputs upfront, we may consider loading the required parts of dependency lockfiles on demand.

Example scenario

  • Dependencies . -> foo -> nixpkgs
  • No follows.

Evaluation order, current situation:

  • need packages.default
  • need inputs.foo.packages.foo
  • read foo details from ./flake.lock
  • fetch foo
  • need foo.inputs.nixpkgs
  • read nixpkgs_1 details from local lock file
  • fetch nixpkgs_1

Same evaluation, partial lock file

  • need packages.default
  • need inputs.foo.packages.foo
  • read foo details from local lock file
  • fetch foo
  • need foo.inputs.nixpkgs
  • read nixpkgs details from foo/flake.lock
  • fetch nixpkgs

As you can see, the fetching characteristics remain the same.

Let's reintroduce follows, and first consider the example:

inputs.foo.nixpkgs.follows = "nixpkgs";

In other words, this injects the local nixpkgs dependency into foo. The lazy fetching behavior remains the same. This injection should be handled by call-flake.nix and does not require changes to the lock file.

Now consider the opposite follows:

inputs.nixpkgs.follows = "foo.nixpkgs";

In this case, if we were not to include a copy of foo.nixpkgs details in the local lock file, we'd have a slightly worse lazy fetching behavior, as nixpkgs would only be fetchable after foo's lock has been fetched. For this case, we do want "flat lock file" behavior, but limited to this dependency. The rule for which transitive dependencies to include in the lock file might be as simple as direct inputs + inputs referenced in follows.

This suggests the following implementation strategy:

  • When generating a lock, apply the above rule to determine which flakes to traverse and include in the lock file
  • When calling a flake, call it such that its inputs are those from its own lock // those set in the current lock
    • Lazy trees #6530 already adds an overrides parameter in call-flake.nix that appears to enable this. The missing bit is that some/many nodes would be created by reinvoking call-flake.nix rather than sharing the node identifiers. Node identifiers are local to each call-flake.nix call. i.e. overrides is a prerequisite for calling dependency locks.

Describe alternatives you've considered

Mark development dependencies explicitly.

  • This is more configuration which is generally not good.
  • This adds more corner cases and error messages.
  • This does not solve the problem of having mutually recursive development dependencies. Note that we can barely manage to make builds not mutually recursive, but flakes encompass more than builds, so expecting flakes not to be mutually recursive is not realistic.

Additional context

Priorities

Add 👍 to issues you find important.

Metadata

Assignees

Labels

featureFeature request or proposalflakesidea approvedThe given proposal has been discussed and approved by the Nix team. An implementation is welcome.

Type

No type

Projects

  • Status

    🏁 Review
  • Status

    Defined work

Relationships

None yet

Development

No branches or pull requests

Issue actions