aboutsummaryrefslogtreecommitdiff
path: root/src/libexpr/flake
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2021-12-13 20:54:43 +0100
committerEelco Dolstra <edolstra@gmail.com>2021-12-13 20:59:33 +0100
commit32a62b0d25116ffe0d66ecaf6a479fbc915d196e (patch)
treed82dc384c14d73c6561b0b538f901ca5a69f9180 /src/libexpr/flake
parent46d86e06ba54dc708fa8fd7d0109845fa2ac402e (diff)
Re-allow inputs.x.url = "/path/to/file"
Diffstat (limited to 'src/libexpr/flake')
-rw-r--r--src/libexpr/flake/flake.cc8
-rw-r--r--src/libexpr/flake/flakeref.cc77
-rw-r--r--src/libexpr/flake/flakeref.hh10
3 files changed, 55 insertions, 40 deletions
diff --git a/src/libexpr/flake/flake.cc b/src/libexpr/flake/flake.cc
index 33d253eee..f598400fc 100644
--- a/src/libexpr/flake/flake.cc
+++ b/src/libexpr/flake/flake.cc
@@ -155,7 +155,7 @@ static FlakeInput parseFlakeInput(EvalState & state,
if (!attrs.empty())
throw Error("unexpected flake input attribute '%s', at %s", attrs.begin()->first, pos);
if (url)
- input.ref = parseFlakeRef(*url, baseDir, true);
+ input.ref = parseFlakeRef(*url, baseDir, true, input.isFlake);
}
if (!input.follows && !input.ref)
@@ -194,8 +194,8 @@ static Flake getFlake(
state, originalRef, allowLookup, flakeCache);
// Guard against symlink attacks.
- auto flakeDir = canonPath(sourceInfo.actualPath + "/" + lockedRef.subdir);
- auto flakeFile = canonPath(flakeDir + "/flake.nix");
+ auto flakeDir = canonPath(sourceInfo.actualPath + "/" + lockedRef.subdir, true);
+ auto flakeFile = canonPath(flakeDir + "/flake.nix", true);
if (!isInDir(flakeFile, sourceInfo.actualPath))
throw Error("'flake.nix' file of flake '%s' escapes from '%s'",
lockedRef, state.store->printStorePath(sourceInfo.storePath));
@@ -570,7 +570,7 @@ LockedFlake lockFlake(
};
// Bring in the current ref for relative path resolution if we have it
- auto parentPath = canonPath(flake.sourceInfo->actualPath + "/" + flake.lockedRef.subdir);
+ auto parentPath = canonPath(flake.sourceInfo->actualPath + "/" + flake.lockedRef.subdir, true);
computeLocks(
flake.inputs, newLockFile.root, {},
diff --git a/src/libexpr/flake/flakeref.cc b/src/libexpr/flake/flakeref.cc
index 29128d789..c3b74e0fe 100644
--- a/src/libexpr/flake/flakeref.cc
+++ b/src/libexpr/flake/flakeref.cc
@@ -48,9 +48,12 @@ FlakeRef FlakeRef::resolve(ref<Store> store) const
}
FlakeRef parseFlakeRef(
- const std::string & url, const std::optional<Path> & baseDir, bool allowMissing)
+ const std::string & url,
+ const std::optional<Path> & baseDir,
+ bool allowMissing,
+ bool isFlake)
{
- auto [flakeRef, fragment] = parseFlakeRefWithFragment(url, baseDir, allowMissing);
+ auto [flakeRef, fragment] = parseFlakeRefWithFragment(url, baseDir, allowMissing, isFlake);
if (fragment != "")
throw Error("unexpected fragment '%s' in flake reference '%s'", fragment, url);
return flakeRef;
@@ -67,7 +70,10 @@ std::optional<FlakeRef> maybeParseFlakeRef(
}
std::pair<FlakeRef, std::string> parseFlakeRefWithFragment(
- const std::string & url, const std::optional<Path> & baseDir, bool allowMissing)
+ const std::string & url,
+ const std::optional<Path> & baseDir,
+ bool allowMissing,
+ bool isFlake)
{
using namespace fetchers;
@@ -112,46 +118,49 @@ std::pair<FlakeRef, std::string> parseFlakeRefWithFragment(
to 'baseDir'). If so, search upward to the root of the
repo (i.e. the directory containing .git). */
- path = absPath(path, baseDir, true);
+ path = absPath(path, baseDir);
- if (!S_ISDIR(lstat(path).st_mode))
- throw BadURL("path '%s' is not a flake (because it's not a directory)", path);
+ if (isFlake) {
- 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 (!S_ISDIR(lstat(path).st_mode))
+ throw BadURL("path '%s' is not a flake (because it's not a directory)", path);
- auto flakeRoot = path;
- std::string subdir;
+ if (!allowMissing && !pathExists(path + "/flake.nix"))
+ throw BadURL("path '%s' is not a flake (because it doesn't contain a 'flake.nix' file)", path);
- while (flakeRoot != "/") {
- if (pathExists(flakeRoot + "/.git")) {
- auto base = std::string("git+file://") + flakeRoot;
+ auto flakeRoot = path;
+ std::string subdir;
- auto parsedURL = ParsedURL{
- .url = base, // FIXME
- .base = base,
- .scheme = "git+file",
- .authority = "",
- .path = flakeRoot,
- .query = decodeQuery(match[2]),
- };
+ while (flakeRoot != "/") {
+ if (pathExists(flakeRoot + "/.git")) {
+ auto base = std::string("git+file://") + flakeRoot;
- 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);
- }
+ auto parsedURL = ParsedURL{
+ .url = base, // FIXME
+ .base = base,
+ .scheme = "git+file",
+ .authority = "",
+ .path = flakeRoot,
+ .query = decodeQuery(match[2]),
+ };
- if (pathExists(flakeRoot + "/.git/shallow"))
- parsedURL.query.insert_or_assign("shallow", "1");
+ 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(Input::fromURL(parsedURL), get(parsedURL.query, "dir").value_or("")),
- fragment);
- }
+ if (pathExists(flakeRoot + "/.git/shallow"))
+ parsedURL.query.insert_or_assign("shallow", "1");
- subdir = std::string(baseNameOf(flakeRoot)) + (subdir.empty() ? "" : "/" + subdir);
- flakeRoot = dirOf(flakeRoot);
+ return std::make_pair(
+ FlakeRef(Input::fromURL(parsedURL), get(parsedURL.query, "dir").value_or("")),
+ fragment);
+ }
+
+ subdir = std::string(baseNameOf(flakeRoot)) + (subdir.empty() ? "" : "/" + subdir);
+ flakeRoot = dirOf(flakeRoot);
+ }
}
} else {
diff --git a/src/libexpr/flake/flakeref.hh b/src/libexpr/flake/flakeref.hh
index 0292eb210..1fddfd9a0 100644
--- a/src/libexpr/flake/flakeref.hh
+++ b/src/libexpr/flake/flakeref.hh
@@ -62,13 +62,19 @@ struct FlakeRef
std::ostream & operator << (std::ostream & str, const FlakeRef & flakeRef);
FlakeRef parseFlakeRef(
- const std::string & url, const std::optional<Path> & baseDir = {}, bool allowMissing = false);
+ const std::string & url,
+ const std::optional<Path> & baseDir = {},
+ bool allowMissing = false,
+ bool isFlake = true);
std::optional<FlakeRef> maybeParseFlake(
const std::string & url, const std::optional<Path> & baseDir = {});
std::pair<FlakeRef, std::string> parseFlakeRefWithFragment(
- const std::string & url, const std::optional<Path> & baseDir = {}, bool allowMissing = false);
+ const std::string & url,
+ const std::optional<Path> & baseDir = {},
+ bool allowMissing = false,
+ bool isFlake = true);
std::optional<std::pair<FlakeRef, std::string>> maybeParseFlakeRefWithFragment(
const std::string & url, const std::optional<Path> & baseDir = {});