diff --git a/doc/manual/src/command-ref/env-common.md b/doc/manual/src/command-ref/env-common.md index 3f3eb6915..6947dbf4c 100644 --- a/doc/manual/src/command-ref/env-common.md +++ b/doc/manual/src/command-ref/env-common.md @@ -8,41 +8,10 @@ Most Nix commands interpret the following environment variables: - [`NIX_PATH`]{#env-NIX_PATH}\ A colon-separated list of directories used to look up Nix - expressions enclosed in angle brackets (i.e., ``). For - instance, the value - - /home/eelco/Dev:/etc/nixos - - will cause Nix to look for paths relative to `/home/eelco/Dev` and - `/etc/nixos`, in this order. It is also possible to match paths - against a prefix. For example, the value - - nixpkgs=/home/eelco/Dev/nixpkgs-branch:/etc/nixos - - will cause Nix to search for `` in - `/home/eelco/Dev/nixpkgs-branch/path` and `/etc/nixos/nixpkgs/path`. - - If a path in the Nix search path starts with `http://` or - `https://`, it is interpreted as the URL of a tarball that will be - downloaded and unpacked to a temporary location. The tarball must - consist of a single top-level directory. For example, setting - `NIX_PATH` to - - nixpkgs=https://github.com/NixOS/nixpkgs/archive/master.tar.gz - - tells Nix to download and use the current contents of the - `master` branch in the `nixpkgs` repository. - - The URLs of the tarballs from the official nixos.org channels (see - [the manual for `nix-channel`](nix-channel.md)) can be abbreviated - as `channel:`. For instance, the following two - values of `NIX_PATH` are equivalent: - - nixpkgs=channel:nixos-21.05 - nixpkgs=https://nixos.org/channels/nixos-21.05/nixexprs.tar.xz - - The Nix search path can also be extended using the `-I` option to - many Nix commands, which takes precedence over `NIX_PATH`. + expressions enclosed in angle brackets (i.e., ``), + e.g. `/home/eelco/Dev:/etc/nixos`. It can be extended using the + `-I` option. For more information about the semantics of the Nix + search path, see the documentation for `-I`. - [`NIX_IGNORE_SYMLINK_STORE`]{#env-NIX_IGNORE_SYMLINK_STORE}\ Normally, the Nix store directory (typically `/nix/store`) is not diff --git a/doc/manual/src/release-notes/rl-next.md b/doc/manual/src/release-notes/rl-next.md index 78ae99f4b..3e903d221 100644 --- a/doc/manual/src/release-notes/rl-next.md +++ b/doc/manual/src/release-notes/rl-next.md @@ -1,2 +1,10 @@ # Release X.Y (202?-??-??) +* You can now use flake references in the old CLI, e.g. + + ``` + # nix-build flake:nixpkgs -A hello + # nix-build -I nixpkgs=flake:github:NixOS/nixpkgs/nixos-22.05 \ + '' -A hello + # NIX_PATH=nixpkgs=flake:nixpkgs nix-build '' -A hello + ``` diff --git a/src/libcmd/common-eval-args.cc b/src/libcmd/common-eval-args.cc index 53d892530..13ff9a399 100644 --- a/src/libcmd/common-eval-args.cc +++ b/src/libcmd/common-eval-args.cc @@ -36,7 +36,68 @@ MixEvalArgs::MixEvalArgs() addFlag({ .longName = "include", .shortName = 'I', - .description = "Add *path* to the list of locations used to look up `<...>` file names.", + .description = R"( + Add *path* to the Nix search path. The Nix search path is + initialized from the colon-separated `NIX_PATH` environment + variable, and is used to look up Nix expressions enclosed in angle + brackets (i.e., ``). For instance, if the Nix search path + consists of the entries + + ``` + /home/eelco/Dev + /etc/nixos + ``` + + Nix will look for paths relative to `/home/eelco/Dev` and + `/etc/nixos`, in this order. It is also possible to match paths + against a prefix. For example, the search path + + ``` + nixpkgs=/home/eelco/Dev/nixpkgs-branch + /etc/nixos + ``` + + will cause Nix to search for `` in + `/home/eelco/Dev/nixpkgs-branch/path` and `/etc/nixos/nixpkgs/path`. + + If a path in the Nix search path starts with `http://` or `https://`, + it is interpreted as the URL of a tarball that will be downloaded and + unpacked to a temporary location. The tarball must consist of a single + top-level directory. For example, setting `NIX_PATH` to + + ``` + nixpkgs=https://github.com/NixOS/nixpkgs/archive/master.tar.gz + ``` + + tells Nix to download and use the current contents of the `master` + branch in the `nixpkgs` repository. + + The URLs of the tarballs from the official `nixos.org` channels + (see [the manual page for `nix-channel`](nix-channel.md)) can be + abbreviated as `channel:`. For instance, the + following two values of `NIX_PATH` are equivalent: + + ``` + nixpkgs=channel:nixos-21.05 + nixpkgs=https://nixos.org/channels/nixos-21.05/nixexprs.tar.xz + ``` + + You can also use refer to source trees looked up in the flake + registry. For instance, + + ``` + nixpkgs=flake:nixpkgs + ``` + + specifies that the prefix `nixpkgs` shall refer to the source tree + downloaded from the `nixpkgs` entry in the flake registry. Similarly, + + ``` + nixpkgs=flake:github:NixOS/nixpkgs/nixos-22.05 + + makes `` refer to a particular branch of the + `NixOS/nixpkgs` repository on GitHub. + ```)", .category = category, .labels = {"path"}, .handler = {[&](std::string s) { searchPath.push_back(s); }} @@ -98,11 +159,21 @@ SourcePath lookupFileArg(EvalState & state, std::string_view s) state.store, EvalSettings::resolvePseudoUrl(s), "source", false).first; auto accessor = makeStorePathAccessor(state.store, storePath); state.registerAccessor(accessor); - return {accessor, CanonPath::root}; - } else if (s.size() > 2 && s.at(0) == '<' && s.at(s.size() - 1) == '>') { + return accessor->root(); + } + + else if (hasPrefix(s, "flake:")) { + auto flakeRef = parseFlakeRef(std::string(s.substr(6)), {}, true, false); + auto [accessor, _] = flakeRef.resolve(state.store).lazyFetch(state.store); + return accessor->root(); + } + + else if (s.size() > 2 && s.at(0) == '<' && s.at(s.size() - 1) == '>') { Path p(s.substr(1, s.size() - 2)); return state.findFile(p); - } else + } + + else return state.rootPath(absPath(std::string(s))); } diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index e0bd4469c..9ec6b04c6 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -405,7 +405,8 @@ static Strings parseNixPath(const std::string & s) } if (*p == ':') { - if (EvalSettings::isPseudoUrl(std::string(start2, s.end()))) { + auto prefix = std::string(start2, s.end()); + if (EvalSettings::isPseudoUrl(prefix) || hasPrefix(prefix, "flake:")) { ++p; while (p != s.end() && *p != ':') ++p; } diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y index 2d140d95d..96a08ab9b 100644 --- a/src/libexpr/parser.y +++ b/src/libexpr/parser.y @@ -637,6 +637,7 @@ formal #include "fs-input-accessor.hh" #include "tarball.hh" #include "store-api.hh" +#include "flake/flake.hh" namespace nix { @@ -789,13 +790,22 @@ std::optional EvalState::resolveSearchPathElem(const SearchPathElem store, EvalSettings::resolvePseudoUrl(elem.second), "source", false).first; auto accessor = makeStorePathAccessor(store, storePath); registerAccessor(accessor); - res.emplace(SourcePath {accessor, CanonPath::root}); + res.emplace(accessor->root()); } catch (FileTransferError & e) { logWarning({ .msg = hintfmt("Nix search path entry '%1%' cannot be downloaded, ignoring", elem.second) }); } - } else { + } + + else if (hasPrefix(elem.second, "flake:")) { + auto flakeRef = parseFlakeRef(elem.second.substr(6), {}, true, false); + debug("fetching flake search path element '%s''", elem.second); + auto [accessor, _] = flakeRef.resolve(store).lazyFetch(store); + res.emplace(accessor->root()); + } + + else { auto path = rootPath(absPath(elem.second)); /* Allow access to paths in the search path. */ diff --git a/tests/flakes/flakes.sh b/tests/flakes/flakes.sh index f998dab19..fc5cd3b03 100644 --- a/tests/flakes/flakes.sh +++ b/tests/flakes/flakes.sh @@ -53,7 +53,11 @@ cat > $flake3Dir/flake.nix < $flake3Dir/default.nix < $nonFlakeDir/README.md < $badFlakeDir/flake.nix @@ -469,3 +473,9 @@ nix store delete $(nix store add-path $badFlakeDir) [[ $(nix path-info $(nix store add-path $flake1Dir)) =~ flake1 ]] [[ $(nix path-info path:$(nix store add-path $flake1Dir)) =~ simple ]] + +# Test fetching flakerefs in the legacy CLI. +[[ $(nix-instantiate --eval flake:flake3 -A x) = 123 ]] +[[ $(nix-instantiate --eval flake:git+file://$flake3Dir -A x) = 123 ]] +[[ $(nix-instantiate -I flake3=flake:flake3 --eval '' -A x) = 123 ]] +[[ $(NIX_PATH=flake3=flake:flake3 nix-instantiate --eval '' -A x) = 123 ]]