Merge pull request #5771 from edolstra/single-file-flake-inputs
Re-allow inputs.x.url = "/path/to/file"
This commit is contained in:
commit
99d617bcde
|
@ -155,7 +155,7 @@ static FlakeInput parseFlakeInput(EvalState & state,
|
||||||
if (!attrs.empty())
|
if (!attrs.empty())
|
||||||
throw Error("unexpected flake input attribute '%s', at %s", attrs.begin()->first, pos);
|
throw Error("unexpected flake input attribute '%s', at %s", attrs.begin()->first, pos);
|
||||||
if (url)
|
if (url)
|
||||||
input.ref = parseFlakeRef(*url, baseDir, true);
|
input.ref = parseFlakeRef(*url, baseDir, true, input.isFlake);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!input.follows && !input.ref)
|
if (!input.follows && !input.ref)
|
||||||
|
@ -194,8 +194,8 @@ static Flake getFlake(
|
||||||
state, originalRef, allowLookup, flakeCache);
|
state, originalRef, allowLookup, flakeCache);
|
||||||
|
|
||||||
// Guard against symlink attacks.
|
// Guard against symlink attacks.
|
||||||
auto flakeDir = canonPath(sourceInfo.actualPath + "/" + lockedRef.subdir);
|
auto flakeDir = canonPath(sourceInfo.actualPath + "/" + lockedRef.subdir, true);
|
||||||
auto flakeFile = canonPath(flakeDir + "/flake.nix");
|
auto flakeFile = canonPath(flakeDir + "/flake.nix", true);
|
||||||
if (!isInDir(flakeFile, sourceInfo.actualPath))
|
if (!isInDir(flakeFile, sourceInfo.actualPath))
|
||||||
throw Error("'flake.nix' file of flake '%s' escapes from '%s'",
|
throw Error("'flake.nix' file of flake '%s' escapes from '%s'",
|
||||||
lockedRef, state.store->printStorePath(sourceInfo.storePath));
|
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
|
// 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(
|
computeLocks(
|
||||||
flake.inputs, newLockFile.root, {},
|
flake.inputs, newLockFile.root, {},
|
||||||
|
|
|
@ -48,9 +48,12 @@ FlakeRef FlakeRef::resolve(ref<Store> store) const
|
||||||
}
|
}
|
||||||
|
|
||||||
FlakeRef parseFlakeRef(
|
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 != "")
|
if (fragment != "")
|
||||||
throw Error("unexpected fragment '%s' in flake reference '%s'", fragment, url);
|
throw Error("unexpected fragment '%s' in flake reference '%s'", fragment, url);
|
||||||
return flakeRef;
|
return flakeRef;
|
||||||
|
@ -67,7 +70,10 @@ std::optional<FlakeRef> maybeParseFlakeRef(
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<FlakeRef, std::string> parseFlakeRefWithFragment(
|
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;
|
using namespace fetchers;
|
||||||
|
|
||||||
|
@ -112,46 +118,49 @@ std::pair<FlakeRef, std::string> parseFlakeRefWithFragment(
|
||||||
to 'baseDir'). If so, search upward to the root of the
|
to 'baseDir'). If so, search upward to the root of the
|
||||||
repo (i.e. the directory containing .git). */
|
repo (i.e. the directory containing .git). */
|
||||||
|
|
||||||
path = absPath(path, baseDir, true);
|
path = absPath(path, baseDir);
|
||||||
|
|
||||||
if (!S_ISDIR(lstat(path).st_mode))
|
if (isFlake) {
|
||||||
throw BadURL("path '%s' is not a flake (because it's not a directory)", path);
|
|
||||||
|
|
||||||
if (!allowMissing && !pathExists(path + "/flake.nix"))
|
if (!S_ISDIR(lstat(path).st_mode))
|
||||||
throw BadURL("path '%s' is not a flake (because it doesn't contain a 'flake.nix' file)", path);
|
throw BadURL("path '%s' is not a flake (because it's not a directory)", path);
|
||||||
|
|
||||||
auto flakeRoot = path;
|
if (!allowMissing && !pathExists(path + "/flake.nix"))
|
||||||
std::string subdir;
|
throw BadURL("path '%s' is not a flake (because it doesn't contain a 'flake.nix' file)", path);
|
||||||
|
|
||||||
while (flakeRoot != "/") {
|
auto flakeRoot = path;
|
||||||
if (pathExists(flakeRoot + "/.git")) {
|
std::string subdir;
|
||||||
auto base = std::string("git+file://") + flakeRoot;
|
|
||||||
|
|
||||||
auto parsedURL = ParsedURL{
|
while (flakeRoot != "/") {
|
||||||
.url = base, // FIXME
|
if (pathExists(flakeRoot + "/.git")) {
|
||||||
.base = base,
|
auto base = std::string("git+file://") + flakeRoot;
|
||||||
.scheme = "git+file",
|
|
||||||
.authority = "",
|
|
||||||
.path = flakeRoot,
|
|
||||||
.query = decodeQuery(match[2]),
|
|
||||||
};
|
|
||||||
|
|
||||||
if (subdir != "") {
|
auto parsedURL = ParsedURL{
|
||||||
if (parsedURL.query.count("dir"))
|
.url = base, // FIXME
|
||||||
throw Error("flake URL '%s' has an inconsistent 'dir' parameter", url);
|
.base = base,
|
||||||
parsedURL.query.insert_or_assign("dir", subdir);
|
.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);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pathExists(flakeRoot + "/.git/shallow"))
|
||||||
|
parsedURL.query.insert_or_assign("shallow", "1");
|
||||||
|
|
||||||
|
return std::make_pair(
|
||||||
|
FlakeRef(Input::fromURL(parsedURL), get(parsedURL.query, "dir").value_or("")),
|
||||||
|
fragment);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pathExists(flakeRoot + "/.git/shallow"))
|
subdir = std::string(baseNameOf(flakeRoot)) + (subdir.empty() ? "" : "/" + subdir);
|
||||||
parsedURL.query.insert_or_assign("shallow", "1");
|
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 {
|
} else {
|
||||||
|
|
|
@ -62,13 +62,19 @@ struct FlakeRef
|
||||||
std::ostream & operator << (std::ostream & str, const FlakeRef & flakeRef);
|
std::ostream & operator << (std::ostream & str, const FlakeRef & flakeRef);
|
||||||
|
|
||||||
FlakeRef parseFlakeRef(
|
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(
|
std::optional<FlakeRef> maybeParseFlake(
|
||||||
const std::string & url, const std::optional<Path> & baseDir = {});
|
const std::string & url, const std::optional<Path> & baseDir = {});
|
||||||
|
|
||||||
std::pair<FlakeRef, std::string> parseFlakeRefWithFragment(
|
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(
|
std::optional<std::pair<FlakeRef, std::string>> maybeParseFlakeRefWithFragment(
|
||||||
const std::string & url, const std::optional<Path> & baseDir = {});
|
const std::string & url, const std::optional<Path> & baseDir = {});
|
||||||
|
|
|
@ -249,6 +249,14 @@ cat > $flake3Dir/flake.nix <<EOF
|
||||||
url = git+file://$nonFlakeDir;
|
url = git+file://$nonFlakeDir;
|
||||||
flake = false;
|
flake = false;
|
||||||
};
|
};
|
||||||
|
nonFlakeFile = {
|
||||||
|
url = path://$nonFlakeDir/README.md;
|
||||||
|
flake = false;
|
||||||
|
};
|
||||||
|
nonFlakeFile2 = {
|
||||||
|
url = "$nonFlakeDir/README.md";
|
||||||
|
flake = false;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
description = "Fnord";
|
description = "Fnord";
|
||||||
|
@ -265,6 +273,8 @@ cat > $flake3Dir/flake.nix <<EOF
|
||||||
dummy2 = builtins.readFile (builtins.path { name = "source"; path = inputs.flake1; filter = path: type: baseNameOf path == "simple.nix"; } + "/simple.nix");
|
dummy2 = builtins.readFile (builtins.path { name = "source"; path = inputs.flake1; filter = path: type: baseNameOf path == "simple.nix"; } + "/simple.nix");
|
||||||
buildCommand = ''
|
buildCommand = ''
|
||||||
cat \${inputs.nonFlake}/README.md > \$out
|
cat \${inputs.nonFlake}/README.md > \$out
|
||||||
|
[[ \$(cat \${inputs.nonFlake}/README.md) = \$(cat \${inputs.nonFlakeFile}) ]]
|
||||||
|
[[ \${inputs.nonFlakeFile} = \${inputs.nonFlakeFile2} ]]
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue