-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
imports don't resolve symlinks absolutely, leading to unexpected behaviour #2109
Comments
Another case to consider is the same directory layout as in the first example but with an explicit
i.e. the expected result. So I agree that there is a bug at least in the way that at minimum the result should be consistent. |
Interesting. For me, the existing behavior is the expected behavior. Symlinks represent real files in real directories, and shouldn't serve as portals to elsewhere. I opened #2150 because nix-shell is tunneling through the portal, and that surprised me. I guess now someone gets to figure out which of us has the "wrong" intuition. :) |
I actually came here to report the discrepancy that @dezgeg pointed out and before reading this issue I was on the same side as @chreekat. But I have to admit that the nixos example is very convincing and it made me think about the standard practices of handling symlinks in terms of context. From my experiments if I do:
the output is the listing of the root directory, not of the current one, as I would expect, which means that my and @chreekat’s intuition is actually wrong and the standard practice is for symlinks to actually serve as portals 🤷♂️. |
I marked this as stale due to inactivity. → More info |
it looks even weirder with
Next works fine and returns run nix eval '(import ./dir/ref.nix)'
run nix eval '(import ./ref.nix)' # follows symlink into folder `dir` and subsequent `import ../42.nix` is relative to it But when symlink is in the middle of path rather than terminal it computes it from path with symlink unresolved run nix eval '(import ./dir/subdir/ref.nix)'
nix run nixpkgs-unstable.nixFlakes -c nix --experimental-features nix-command eval --impure --expr '(import ./dir/subdir/ref.nix)' Causing error like:
Tried both P.S. Real use-case affected by this is when |
My best guess is this code for Note that POSIX.1-2001 conformant systems have |
This addresses some cases of NixOS#2109
This addresses some cases of NixOS#2109
This addresses some cases of NixOS#2109
#4678 fixes scenarios mentioned in this issue. But there is a problem with |
I'm not surprised by the current behavior and I don't think the
If you need more than one file from the nixos tree, you can factor out the path into a separate file. |
@roberth, there is system behavior of symlinks and in POSIX systems they should be resolved for each path component incrementally from left to right. If I understand correctly Nix will not work on other systems anyway (at least C++ implementation). Beside that behavior of Nix in terms of relative imports clearly indicates attempt to have same behavior, but before #4678 it had it inconsistent depending on where symlinks appears in path making only last element resolved and following relative imports with traversing will affect that. More obvious bug of using cat dir/subdir/../42.nix returns nix eval '(builtins.readFile ./dir/subdir/../42.nix)' returns Unfortunately it is not fixed with #4678 because it is other places where call either Work-around you suggest will work only for files. To emulate correct behavior of symlinked |
Yeah, I'm not saying it's perfect. That's impossible with symlinks. (OT: |
Handling symlinks supposed to be transparent and that's why you don't usually have to write My guess is that Nix wants to canonicalize paths that will appear in future in order to keep hashes insensitive to various forms of same path. Just checked >>> os.path.realpath('dir/missing-subdir/../42.nix')
'/tmp/ws/example/dir/42.nix'
>>> os.path.realpath('dir/subdir/../42.nix')
'/tmp/ws/example/42.nix' But I don't think Nix should follow that. |
I marked this as stale due to inactivity. → More info |
(I still think this should be considered) |
It would be big breaking change, but one we should opt-into and then someday make the default. |
I just designed a configuration structure using symlinks and got bitten. |
I noticed at least one case where this was fixed (regression in 2.16): #9298 Unfortunately, it did not fix the case from OP: $ mkdir test test/{1,2}
ln -s ../2/default.nix test/1
echo '"In 1"' > test/1/content.nix
echo '"In 2"' > test/2/content.nix
echo 'import ./content.nix' > test/2/default.nix
$ nix-instantiate --eval test/1
"In 1"
$ nix-instantiate --eval test/2
"In 2" |
Have a look at the following directory structure:
Now this is what happens with evaluation:
However what I expect to happen is
because the symlink should have influenced all imports as well.
This can lead to unexpected behaviour. A good example of this is if I were to have a directory like this (with
/path/to/nixpkgs
being a nixpkgs checkout):Then trying to use this folder will fail:
The text was updated successfully, but these errors were encountered: