mirror of
https://github.com/NixOS/nix
synced 2025-06-25 14:51:16 +02:00
Merge pull request #12157 from DeterminateSystems/fix-path-flakeref-query-without-fragment
parsePathFlakeRefWithFragment(): Handle 'path?query' without a fragment
This commit is contained in:
commit
2d9b213cc2
5 changed files with 78 additions and 28 deletions
|
@ -7,18 +7,60 @@ namespace nix {
|
||||||
|
|
||||||
/* ----------- tests for flake/flakeref.hh --------------------------------------------------*/
|
/* ----------- tests for flake/flakeref.hh --------------------------------------------------*/
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
TEST(parseFlakeRef, path) {
|
||||||
* to_string
|
experimentalFeatureSettings.experimentalFeatures.get().insert(Xp::Flakes);
|
||||||
* --------------------------------------------------------------------------*/
|
|
||||||
|
fetchers::Settings fetchSettings;
|
||||||
|
|
||||||
|
{
|
||||||
|
auto s = "/foo/bar";
|
||||||
|
auto flakeref = parseFlakeRef(fetchSettings, s);
|
||||||
|
ASSERT_EQ(flakeref.to_string(), "path:/foo/bar");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto s = "/foo/bar?revCount=123&rev=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
|
||||||
|
auto flakeref = parseFlakeRef(fetchSettings, s);
|
||||||
|
ASSERT_EQ(flakeref.to_string(), "path:/foo/bar?rev=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&revCount=123");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto s = "/foo/bar?xyzzy=123";
|
||||||
|
EXPECT_THROW(
|
||||||
|
parseFlakeRef(fetchSettings, s),
|
||||||
|
Error);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto s = "/foo/bar#bla";
|
||||||
|
EXPECT_THROW(
|
||||||
|
parseFlakeRef(fetchSettings, s),
|
||||||
|
Error);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto s = "/foo/bar#bla";
|
||||||
|
auto [flakeref, fragment] = parseFlakeRefWithFragment(fetchSettings, s);
|
||||||
|
ASSERT_EQ(flakeref.to_string(), "path:/foo/bar");
|
||||||
|
ASSERT_EQ(fragment, "bla");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto s = "/foo/bar?revCount=123#bla";
|
||||||
|
auto [flakeref, fragment] = parseFlakeRefWithFragment(fetchSettings, s);
|
||||||
|
ASSERT_EQ(flakeref.to_string(), "path:/foo/bar?revCount=123");
|
||||||
|
ASSERT_EQ(fragment, "bla");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TEST(to_string, doesntReencodeUrl) {
|
TEST(to_string, doesntReencodeUrl) {
|
||||||
fetchers::Settings fetchSettings;
|
fetchers::Settings fetchSettings;
|
||||||
auto s = "http://localhost:8181/test/+3d.tar.gz";
|
auto s = "http://localhost:8181/test/+3d.tar.gz";
|
||||||
auto flakeref = parseFlakeRef(fetchSettings, s);
|
auto flakeref = parseFlakeRef(fetchSettings, s);
|
||||||
auto parsed = flakeref.to_string();
|
auto unparsed = flakeref.to_string();
|
||||||
auto expected = "http://localhost:8181/test/%2B3d.tar.gz";
|
auto expected = "http://localhost:8181/test/%2B3d.tar.gz";
|
||||||
|
|
||||||
ASSERT_EQ(parsed, expected);
|
ASSERT_EQ(unparsed, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,23 +89,16 @@ std::pair<FlakeRef, std::string> parsePathFlakeRefWithFragment(
|
||||||
bool allowMissing,
|
bool allowMissing,
|
||||||
bool isFlake)
|
bool isFlake)
|
||||||
{
|
{
|
||||||
std::string path = url;
|
static std::regex pathFlakeRegex(
|
||||||
std::string fragment = "";
|
R"(([^?#]*)(\?([^#]*))?(#(.*))?)",
|
||||||
std::map<std::string, std::string> query;
|
std::regex::ECMAScript);
|
||||||
auto pathEnd = url.find_first_of("#?");
|
|
||||||
auto fragmentStart = pathEnd;
|
std::smatch match;
|
||||||
if (pathEnd != std::string::npos && url[pathEnd] == '?') {
|
auto succeeds = std::regex_match(url, match, pathFlakeRegex);
|
||||||
fragmentStart = url.find("#");
|
assert(succeeds);
|
||||||
}
|
auto path = match[1].str();
|
||||||
if (pathEnd != std::string::npos) {
|
auto query = decodeQuery(match[3]);
|
||||||
path = url.substr(0, pathEnd);
|
auto fragment = percentDecode(match[5].str());
|
||||||
}
|
|
||||||
if (fragmentStart != std::string::npos) {
|
|
||||||
fragment = percentDecode(url.substr(fragmentStart+1));
|
|
||||||
}
|
|
||||||
if (pathEnd != std::string::npos && fragmentStart != std::string::npos && url[pathEnd] == '?') {
|
|
||||||
query = decodeQuery(url.substr(pathEnd + 1, fragmentStart - pathEnd - 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (baseDir) {
|
if (baseDir) {
|
||||||
/* Check if 'url' is a path (either absolute or relative
|
/* Check if 'url' is a path (either absolute or relative
|
||||||
|
@ -190,11 +183,13 @@ std::pair<FlakeRef, std::string> parsePathFlakeRefWithFragment(
|
||||||
path = canonPath(path + "/" + getOr(query, "dir", ""));
|
path = canonPath(path + "/" + getOr(query, "dir", ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchers::Attrs attrs;
|
return fromParsedURL(fetchSettings, {
|
||||||
attrs.insert_or_assign("type", "path");
|
.scheme = "path",
|
||||||
attrs.insert_or_assign("path", path);
|
.authority = "",
|
||||||
|
.path = path,
|
||||||
return std::make_pair(FlakeRef(fetchers::Input::fromAttrs(fetchSettings, std::move(attrs)), ""), fragment);
|
.query = query,
|
||||||
|
.fragment = fragment
|
||||||
|
}, isFlake);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -262,6 +262,7 @@ public:
|
||||||
operator const T &() const { return value; }
|
operator const T &() const { return value; }
|
||||||
operator T &() { return value; }
|
operator T &() { return value; }
|
||||||
const T & get() const { return value; }
|
const T & get() const { return value; }
|
||||||
|
T & get() { return value; }
|
||||||
template<typename U>
|
template<typename U>
|
||||||
bool operator ==(const U & v2) const { return value == v2; }
|
bool operator ==(const U & v2) const { return value == v2; }
|
||||||
template<typename U>
|
template<typename U>
|
||||||
|
|
|
@ -22,7 +22,6 @@ ParsedURL parseURL(const std::string & url)
|
||||||
std::smatch match;
|
std::smatch match;
|
||||||
|
|
||||||
if (std::regex_match(url, match, uriRegex)) {
|
if (std::regex_match(url, match, uriRegex)) {
|
||||||
auto & base = match[1];
|
|
||||||
std::string scheme = match[2];
|
std::string scheme = match[2];
|
||||||
auto authority = match[3].matched
|
auto authority = match[3].matched
|
||||||
? std::optional<std::string>(match[3]) : std::nullopt;
|
? std::optional<std::string>(match[3]) : std::nullopt;
|
||||||
|
|
|
@ -63,3 +63,16 @@ flakeref=git+file://$rootRepo\?submodules=1\&dir=submodule
|
||||||
echo '"foo"' > "$rootRepo"/submodule/sub.nix
|
echo '"foo"' > "$rootRepo"/submodule/sub.nix
|
||||||
[[ $(nix eval --json "$flakeref#sub" ) = '"foo"' ]]
|
[[ $(nix eval --json "$flakeref#sub" ) = '"foo"' ]]
|
||||||
[[ $(nix flake metadata --json "$flakeref" | jq -r .locked.rev) = null ]]
|
[[ $(nix flake metadata --json "$flakeref" | jq -r .locked.rev) = null ]]
|
||||||
|
|
||||||
|
# Test that `nix flake metadata` parses `submodule` correctly.
|
||||||
|
cat > "$rootRepo"/flake.nix <<EOF
|
||||||
|
{
|
||||||
|
outputs = { self }: {
|
||||||
|
};
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
git -C "$rootRepo" add flake.nix
|
||||||
|
git -C "$rootRepo" commit -m "Add flake.nix"
|
||||||
|
|
||||||
|
storePath=$(nix flake metadata --json "$rootRepo?submodules=1" | jq -r .path)
|
||||||
|
[[ -e "$storePath/submodule" ]]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue