1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-16 15:32:43 +01:00

Fix ParsedURL handling of %2F in URL paths

See the new extensive doxygen in `url.hh`.
This fixes fetching gitlab: flakes.

Paths are now stored as a std::vector of individual path
segments, which can themselves contain path separators '/' (%2F).
This is necessary to make the Gitlab's /projects/ API work.

Co-authored-by: John Ericson <John.Ericson@Obsidian.Systems>
Co-authored-by: Sergei Zimmerman <sergei@zimmerman.foo>
This commit is contained in:
Jörg Thalheim 2025-08-26 12:49:28 +02:00 committed by Sergei Zimmerman
parent 6839f3de55
commit c436b7a32a
No known key found for this signature in database
19 changed files with 446 additions and 117 deletions

View file

@ -143,7 +143,7 @@ std::pair<FlakeRef, std::string> parsePathFlakeRefWithFragment(
auto parsedURL = ParsedURL{
.scheme = "git+file",
.authority = ParsedURL::Authority{},
.path = flakeRoot,
.path = splitString<std::vector<std::string>>(flakeRoot, "/"),
.query = query,
.fragment = fragment,
};
@ -172,7 +172,13 @@ std::pair<FlakeRef, std::string> parsePathFlakeRefWithFragment(
return fromParsedURL(
fetchSettings,
{.scheme = "path", .authority = ParsedURL::Authority{}, .path = path, .query = query, .fragment = fragment},
{
.scheme = "path",
.authority = ParsedURL::Authority{},
.path = splitString<std::vector<std::string>>(path, "/"),
.query = query,
.fragment = fragment,
},
isFlake);
}
@ -193,7 +199,7 @@ parseFlakeIdRef(const fetchers::Settings & fetchSettings, const std::string & ur
auto parsedURL = ParsedURL{
.scheme = "flake",
.authority = ParsedURL::Authority{},
.path = match[1],
.path = splitString<std::vector<std::string>>(match[1].str(), "/"),
};
return std::make_pair(
@ -211,8 +217,12 @@ std::optional<std::pair<FlakeRef, std::string>> parseURLFlakeRef(
{
try {
auto parsed = parseURL(url, /*lenient=*/true);
if (baseDir && (parsed.scheme == "path" || parsed.scheme == "git+file") && !isAbsolute(parsed.path))
parsed.path = absPath(parsed.path, *baseDir);
if (baseDir && (parsed.scheme == "path" || parsed.scheme == "git+file")) {
/* Here we know that the path must not contain encoded '/' or NUL bytes. */
auto path = renderUrlPathEnsureLegal(parsed.path);
if (!isAbsolute(path))
parsed.path = splitString<std::vector<std::string>>(absPath(path, *baseDir), "/");
}
return fromParsedURL(fetchSettings, std::move(parsed), isFlake);
} catch (BadURL &) {
return std::nullopt;