From b6cc0a704d8c1432e230ff65d4b74ea7114a730b Mon Sep 17 00:00:00 2001 From: Tom Bereknyei Date: Fri, 3 Dec 2021 10:53:41 -0500 Subject: [PATCH] flakes: search up to git or filesystem boundary While parsing a flakeref, upon not finding a flake.nix, search upwards until git or filesystem boundary. --- doc/manual/src/release-notes/rl-next.md | 2 ++ src/libexpr/flake/flakeref.cc | 23 +++++++++++++++++++++-- tests/flake-searching.sh | 24 ++++++++++++++++++++++++ tests/local.mk | 1 + 4 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 tests/flake-searching.sh diff --git a/doc/manual/src/release-notes/rl-next.md b/doc/manual/src/release-notes/rl-next.md index a6b22dfa7..2826fc8be 100644 --- a/doc/manual/src/release-notes/rl-next.md +++ b/doc/manual/src/release-notes/rl-next.md @@ -8,3 +8,5 @@ * New built-in function: `builtins.groupBy`, with the same functionality as Nixpkgs' `lib.groupBy`, but faster. + +* Nix now searches for a flake.nix up until git or filesystem boundary. diff --git a/src/libexpr/flake/flakeref.cc b/src/libexpr/flake/flakeref.cc index 29128d789..074727f06 100644 --- a/src/libexpr/flake/flakeref.cc +++ b/src/libexpr/flake/flakeref.cc @@ -117,8 +117,27 @@ std::pair parseFlakeRefWithFragment( if (!S_ISDIR(lstat(path).st_mode)) throw BadURL("path '%s' is not a flake (because it's not a directory)", path); - if (!allowMissing && !pathExists(path + "/flake.nix")) - throw BadURL("path '%s' is not a flake (because it doesn't contain a 'flake.nix' file)", path); + if (!allowMissing && !pathExists(path + "/flake.nix")){ + notice("path '%s' does not contain a 'flake.nix', searching up",path); + + // Save device to detect filesystem boundary + dev_t device = lstat(path).st_dev; + bool found = false; + while (path != "/") { + if (pathExists(path + "/flake.nix")) { + found = true; + break; + } else if (pathExists(path + "/.git")) + throw Error("unable to find a flake before encountering git boundary at '%s'", path); + else { + if (lstat(path).st_dev != device) + throw Error("unable to find a flake before encountering filesystem boundary at '%s'", path); + } + path = dirOf(path); + } + if (!found) + throw BadURL("could not find a flake.nix file"); + } auto flakeRoot = path; std::string subdir; diff --git a/tests/flake-searching.sh b/tests/flake-searching.sh new file mode 100644 index 000000000..82ae66894 --- /dev/null +++ b/tests/flake-searching.sh @@ -0,0 +1,24 @@ +source common.sh + +clearStore + +cp ./simple.nix ./simple.builder.sh ./config.nix $TEST_HOME +cd $TEST_HOME +cat < flake.nix +{ + outputs = a: { + defaultPackage.$system = import ./simple.nix; + packages.$system.test = import ./simple.nix; + }; +} +EOF +mkdir subdir +cd subdir + +for i in "" . "$PWD" .# .#test; do + nix build $i || fail "flake should be found by searching up directories" +done + +for i in "path:$PWD"; do + ! nix build $i || fail "flake should not search up directories when using 'path:'" +done diff --git a/tests/local.mk b/tests/local.mk index 936b72c2a..9277c0b1b 100644 --- a/tests/local.mk +++ b/tests/local.mk @@ -47,6 +47,7 @@ nix_tests = \ describe-stores.sh \ flakes.sh \ flake-local-settings.sh \ + flake-searching.sh \ build.sh \ repl.sh ca/repl.sh \ ca/build.sh \