aboutsummaryrefslogtreecommitdiff
path: root/src/libexpr/flake/flakeref.cc
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2020-04-27 22:53:11 +0200
committerEelco Dolstra <edolstra@gmail.com>2020-04-27 22:53:11 +0200
commit6521c92ce8289a5f9e959c6789ab24dacdad082e (patch)
tree659c7ce34b0cb970aa7d99bcda991de50e8d27ac /src/libexpr/flake/flakeref.cc
parent829dcb35d52443636d7c6df0d54270b9995bc71a (diff)
Improve path:// handling
In particular, doing 'nix build /path/to/dir' now works if /path/to/dir is not a Git tree (it only has to contain a flake.nix file). Also, 'nix flake init' no longer requires a Git tree (but it will do a 'git add flake.nix' if it's a Git tree)
Diffstat (limited to 'src/libexpr/flake/flakeref.cc')
-rw-r--r--src/libexpr/flake/flakeref.cc64
1 files changed, 36 insertions, 28 deletions
diff --git a/src/libexpr/flake/flakeref.cc b/src/libexpr/flake/flakeref.cc
index de91f2eed..a70261a41 100644
--- a/src/libexpr/flake/flakeref.cc
+++ b/src/libexpr/flake/flakeref.cc
@@ -47,9 +47,9 @@ FlakeRef FlakeRef::resolve(ref<Store> store) const
}
FlakeRef parseFlakeRef(
- const std::string & url, const std::optional<Path> & baseDir)
+ const std::string & url, const std::optional<Path> & baseDir, bool allowMissing)
{
- auto [flakeRef, fragment] = parseFlakeRefWithFragment(url, baseDir);
+ auto [flakeRef, fragment] = parseFlakeRefWithFragment(url, baseDir, allowMissing);
if (fragment != "")
throw Error("unexpected fragment '%s' in flake reference '%s'", fragment, url);
return flakeRef;
@@ -66,7 +66,7 @@ std::optional<FlakeRef> maybeParseFlakeRef(
}
std::pair<FlakeRef, std::string> parseFlakeRefWithFragment(
- const std::string & url, const std::optional<Path> & baseDir)
+ const std::string & url, const std::optional<Path> & baseDir, bool allowMissing)
{
using namespace fetchers;
@@ -115,39 +115,47 @@ std::pair<FlakeRef, std::string> 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);
+
+ auto fragment = percentDecode(std::string(match[3]));
+
auto flakeRoot = path;
std::string subdir;
- while (true) {
- if (pathExists(flakeRoot + "/.git")) break;
+ while (flakeRoot != "/") {
+ if (pathExists(flakeRoot + "/.git")) {
+ auto base = std::string("git+file://") + flakeRoot;
+
+ auto parsedURL = ParsedURL{
+ .url = base, // FIXME
+ .base = base,
+ .scheme = "git+file",
+ .authority = "",
+ .path = flakeRoot,
+ .query = decodeQuery(match[2]),
+ };
+
+ if (subdir != "") {
+ if (parsedURL.query.count("dir"))
+ throw Error("flake URL '%s' has an inconsistent 'dir' parameter", url);
+ parsedURL.query.insert_or_assign("dir", subdir);
+ }
+
+ return std::make_pair(
+ FlakeRef(inputFromURL(parsedURL), get(parsedURL.query, "dir").value_or("")),
+ fragment);
+ }
+
subdir = std::string(baseNameOf(flakeRoot)) + (subdir.empty() ? "" : "/" + subdir);
flakeRoot = dirOf(flakeRoot);
- if (flakeRoot == "/")
- throw BadURL("path '%s' is not a flake (because it does not reference a Git repository)", path);
}
- auto base = std::string("git+file://") + flakeRoot;
+ fetchers::Attrs attrs;
+ attrs.insert_or_assign("type", "path");
+ attrs.insert_or_assign("path", path);
- auto parsedURL = ParsedURL{
- .url = base, // FIXME
- .base = base,
- .scheme = "git+file",
- .authority = "",
- .path = flakeRoot,
- .query = decodeQuery(match[2]),
- };
-
- auto fragment = percentDecode(std::string(match[3]));
-
- if (subdir != "") {
- if (parsedURL.query.count("dir"))
- throw Error("flake URL '%s' has an inconsistent 'dir' parameter", url);
- parsedURL.query.insert_or_assign("dir", subdir);
- }
-
- return std::make_pair(
- FlakeRef(inputFromURL(parsedURL), get(parsedURL.query, "dir").value_or("")),
- fragment);
+ return std::make_pair(FlakeRef(inputFromAttrs(attrs), ""), fragment);
}
else {