What are nix paths?

I thought the nix path type was just a data type to handle constructing paths [relative to the current source file, optionally], but it this made me confused:

nix-repl> ./dotfiles      
/home/juliano/dotfiles

nix-repl> "${./dotfiles}"  
"/nix/store/3wx89z1lm6p1i6hn76v6j1wjhpcb2ynm-dotfiles"

Does using the path type automatically map or import some [relative] path into the nix store?


Bonus wat I’d love some help understanding:

nix-repl> "${./dotfiles/homedir/.bash_profile}"
error: The path name '.bash_profile' is invalid: it is illegal to start the name with a period. Path names are alphanumeric and can include the symbols +-._?= and must not begin with a period. Note: If '.bash_profile' is a source file and you cannot rename it on disk, builtins.path { name = ... } can be used to give it an alternative name.
1 Like

Yea, ./dotfiles has type path:

nix-repl> builtins.typeOf ./dotfiles
"path"

Paths just have some unique behavior when it comes to strings. When a path is interpolated into a string or used as a derivation argument or something, Nix automatically copies that path into the store and interpolates that path instead.

nix-repl> "${./foo}"
"/nix/store/1hnsi1lbhwq0dzlikx3r69pzhhk44bnp-foo"
nix-repl> builtins.typeOf "${./foo}"
"string"

But finally, you can actually coax Nix into putting the original path into a string with toString.

nix-repl> toString ./dotfiles
"/home/will/dotfiles"
nix-repl> typeOf (toString ./dotfiles)
"string"

The error message is fairly self explanatory. Nix store paths have certain restrictions on their names. One of them is that the part immediately after the hash can’t begin with a period. You can use builtins.path { name = "bash_profile"; path = ./dotfiles/homedir/.bash_profile; } instead, as there is no period at the beginning of the name argument.

1 Like