nmattia / niv

Easy dependency management for Nix projects
https://github.com/nmattia/niv
MIT License
1.55k stars 77 forks source link

niv status, sources discovery and niv init templates #272

Open nmattia opened 4 years ago

nmattia commented 4 years ago

Got a lot of feedback over the past few months, and a lot more experience with niv. This in an outline of the sources handling changes that will happen soon; it's aimed at making basic nix projects even simpler, while giving people more flexibility re. the location of niv's files. Speak now or forever hold your peace!

discovery

sources.json: niv will go up in the directories (til filesystem boundary) until if finds either a sources.json or a nix/sources.json. When it does, it will try to parse it (should be an object and all values should be objects). If it doesn't parse, keep searching.

sources.nix: same as above, but with sources.nix or nix/sources.nix, and will hash it for a known sources.nix hash (or niv: no_update)

inlined sources.nix: niv will go up in the directories (til filesystem boundary) and for every file with a .nix extension in . and ./nix/ and will scan them (up to n characters) for the upload URL of sources.nix (i.e. https://raw.githubusercontent.com/nmattia/niv/<version>/nix/sources.nix) and the sha256 of a known sources.nix.

Generally the discovery should be done lazily (not performed if not needed), should be short-circuited with global flags (like --sources-file does already) and should not take more than n milliseconds.

niv status

This is a new command that displays:

niv init templates

niv init tries to discover sources.json and sources.nix. If it finds them (NOTE: both or either?) it considers niv was already initiated and only updates sources.nix (if necessary). If it does not find them, then it initializes directory.

There will be two templates to start with, light and heavy (not sure yet on the name). light is the default.

$ niv init (--light|--heavy)

light:

# default.nix
{ system ? builtins.currentSystem
, crossSystem ? null
, config ? {}
}:
let
  sources = import sourcesnix { sourcesFile = ./sources.json; inherit pkgs; }; # path to sources.json customizable

  sourcesnix = builtins.fetchurl {
    url = https://raw.githubusercontent.com/nmattia/niv/<version>/nix/sources.nix; # the release commit will be tagged with version
    sha256 = "<sha256>";
  };

  pkgs = import sources.nixpkgs {
    inherit system crossSystem config; # or whatever is best practices nowadays
    overlays = [ (self: super: { inherit sources; } ) ];
  };
in
pkgs.hello
# sources.json
{ "nixpkgs" : { ... } }

heavy:

nix/default.nix similar to default.nix in light, except that it returns pkgs (not pkgs.hello) and that it imports a local sources.nix that's written in nix/sources.nix. Might add a flag (--remote-sources) to disable this.

# default.nix
{ system ? builtins.currentSystem
, crossSystem ? null
, config ? {}
}:
let pkgs = import ./nix/default.nix { inherit system crossSystem config; }; in pkgs.hello

the sources.json go to nix/sources.json (instead of ./sources.json) and include niv as well (instead of just nixpkgs).

xavierzwirtz commented 4 years ago

Love it, more opinionation is always good in this kind of tooling.

michaelpj commented 4 years ago

Some personal feelings:

I think a bunch of these issues center around the fact that niv has no configuration and so relies a lot on the (implicit) locations of its files. So here's a sketch of an alternate design:

leotaku commented 4 years ago

To me, the original proposal sounds very reasonable, but I do have some theoretical concerns. I realize that these might not be actual flaws in the design, but I'd still like to see them addressed.

Unlike @michaelpj, I do not think Niv would work better with a configuration file. The original proposal is very opinionated, but should already be flexible enough to support most workflows.

Thanks for giving the community an opportunity to respond to your plans!

PierreR commented 4 years ago

I just want to chime in and say that @michaelpj concerns about discovery seems quite fair to me.

I am probably missing the point but I don't see why niv makes it so complex. Why not doing what every other tools would do; go and search a default place. For users with special requirements, make it possible to specify another default.

In any case, I would challenge any added complexity, would go with sane defaults and have good documentation for users that want to follow more advanced avenues.

I am actually using niv in some global overlays without any default.nix. I only do sources = import ./nix/sources.nix; so the whole business with niv init (--light|--heavy) goes a bit off the top of my head.

deliciouslytyped commented 3 years ago

This would be nice, because sometimes I put files in nonstandard directories, and passing -s source.json to niv still fails, because 1) it's doesn't seem to be the right thing anyway 2) it can't find sources.nix even though it's right next to it.