How to prevent a overlay from being applied more than once?

Suppose I have some Nixpkgs overlays composed from other overlays:

overlayFoo = self: super: {
  # ...
};
overlayBar = pkgs.lib.fixedPoints.composeExtensions overlayFoo (self: super: {
  # ...
};
overlayBaz = pkgs.lib.fixedPoints.composeExtensions overlayFoo (self: super: {
  # ...
});

And the user of the overlays would like to use them like this:

pkgs = import nixpkgs {
  inherit system;
  overlays = [overlayBar overlayBaz];
};

Since both overlayBar and overlayBaz depend on overlayFoo, how can I prevent overlayFoo from being applied more than once?

You could add a marker to nixpkgs to check if the overlay has been applied already:

let
  overlayFoo = super.lib.optionalAttrs (!super.__fooHasBeenApplied or false) {
    __fooHasBeenApplied = true;
    # …
  };
in
#…

It is probably simpler to get rid of the composeExtensions though.

1 Like

Shell we add a helper function to add the marker?

Instead of

overlayFoo = self: super: self.lib.optionalAttrs (!super.__fooHasBeenApplied or false) {
  __fooHasBeenApplied = true;
  # ...
};

we might want:

overlayFoo = self: super: super.lib.fixedPoints.applyOnce "foo" {
  # ...
};

I don’t think this comes up often enough, honestly, and I also wouldn’t want to encourage it.

Agreed. An overlay should be seen as an independent thing. Its dependencies should be externally managed, not locally composed. After all, the whole point of overlays is that the packages and things they change or use come from outside sources.

Suppose you are creating two overlays and both of them depend on the nightly version of Rust provided by Mozilla’s rust-overlay, if you don’t specify the dependency to rust-overlay, the users of your overlays would be surprised when your overlays raise some errors about non-existing nightly Rust.

In that case, the two overlays you’re creating should ideally not expose packages from rust-overlay and only use it as a dependency

1 Like

What would this look like? I’m trying to figure out the idiomatic way to depend on external overlays without exposing the packages of those overlays.

Maybe try not using overlays? AFAIK, flake-parts support deduplication.