This is a move-over of https://github.com/NixOS/nixpkgs/issues/24575 from nixpkgs, which turned out to be a nix issue.
When you use filterSource (...) ./., nix puts the basename of the current dir, that is, the name of the parent directory, into the derivation.
That is problematic because that could be gnu-hello or gnu-hello-myclone or /tmp/asdf123 etc (see #904 for more such problems).
I think that filterSource should not rely on the basename here.
The easiest solution would be to just use the hash and not try to make up a nice extra name.
@edolstra what would be the implications of name not being part of the store path hash?
This would help with determinism for many Nix functions while keeping the UX.
Well, filterSource is consistent with the behaviour of regular (unfiltered) sources BTW. If you write builder = ./builder.sh, you get a store path name /nix/store/...-builder.sh.
If you write builder = ./builder.sh, you get a store path name /nix/store/...-builder.sh
That behaviour cause problems from time to time, due to the hash being prepended to the filename. I wonder how it would be if it produced /nix/store/...-builder.sh/builder.sh instead. It looks both ugly and pretty at the same time. Ugly because of the seemingly pointless duplicated name, and pretty because now the basename is the same inside and outside the Nix store.
This adds to "a list of obstacles that makes hash dependent based on how the source is retrieved" in https://github.com/NixOS/nix/issues/904
Would anybody be opposed to changing filterSource so that it contains only the hash, and adding a separate function like filterSourceWithName where you can give a name explicitly if you want the ...hash...-name format?
@nh2 I don't think so.
For drive-by readers, the pain created by this bug is explained in detail in @domenkozar's talk at NixCon 2017.
Ugly workaround for now might be fetchGit ./., but not sure how to get that working with filterSource.
You can use builtins.path for this now.
Note: if you want to do something like nix-env -if <url.tar.gz>, it will also have a different hash than locally doing just nix-build on that unpacked folder.
To circumvent that use builtins.path as mentioned by @shlevy , minimal example: https://gist.github.com/domenkozar/766c926b6a4427d3828a0ca9600ca6cb
$ nix-env -if https://gist.github.com/domenkozar/766c926b6a4427d3828a0ca9600ca6cb/archive/1ae25b20e8ffa1fe507990b1346f4acf82b127af.tar.gz
will have the same hash as nix-build on that file anywhere locally.
Can somebody provide in here an example of how builtins.path should be used for avoiding the basename problem?
We should proably also mention that in the manuals.
Can somebody provide in here an example of how builtins.path should be used for avoiding the basename problem?
Examples:
{
src = builtins.path { name = "stack2nix"; path = ./.; };
}
With filter:
{
src = builtins.path {
name = "stack2nix";
path = ./.;
filter = path: type:
!(pkgs.lib.hasPrefix "." (baseNameOf path));
};
}
This functionality is now available in nixpkgs master via lib.cleanSourceWith. Example:
lib.cleanSourceWith {
name = "source";
src = ./.; # or a cleanSourceWith output
filter = path: type:
!(pkgs.lib.hasPrefix "." (baseNameOf path));
}
or to just rename an already cleaned source:
lib.cleanSourceWith { name = "source"; src = someSource; }
Most helpful comment
Examples:
With filter: