diff --git a/src/libexpr/flake/flakeref.cc b/src/libexpr/flake/flakeref.cc index 0d2c7f414..04c52cb4c 100644 --- a/src/libexpr/flake/flakeref.cc +++ b/src/libexpr/flake/flakeref.cc @@ -92,6 +92,15 @@ std::pair parseFlakeRefWithFragment( std::smatch match; + auto fromParsedURL = [&](ParsedURL && parsedURL) + { + auto dir = getOr(parsedURL.query, "dir", ""); + parsedURL.query.erase("dir"); + std::string fragment; + std::swap(fragment, parsedURL.fragment); + return std::make_pair(FlakeRef(Input::fromURL(parsedURL), dir), fragment); + }; + /* Check if 'url' is a flake ID. This is an abbreviated syntax for 'flake:?ref=&rev='. */ @@ -112,6 +121,7 @@ std::pair parseFlakeRefWithFragment( else if (std::regex_match(url, match, pathUrlRegex)) { std::string path = match[1]; std::string fragment = percentDecode(match.str(3)); + auto query = decodeQuery(match[2]); if (baseDir) { /* Check if 'url' is a path (either absolute or relative @@ -163,7 +173,8 @@ std::pair parseFlakeRefWithFragment( .scheme = "git+file", .authority = "", .path = flakeRoot, - .query = decodeQuery(match[2]), + .query = query, + .fragment = fragment, }; if (subdir != "") { @@ -175,9 +186,7 @@ std::pair parseFlakeRefWithFragment( if (pathExists(flakeRoot + "/.git/shallow")) parsedURL.query.insert_or_assign("shallow", "1"); - return std::make_pair( - FlakeRef(Input::fromURL(parsedURL), getOr(parsedURL.query, "dir", "")), - fragment); + return fromParsedURL(std::move(parsedURL)); } subdir = std::string(baseNameOf(flakeRoot)) + (subdir.empty() ? "" : "/" + subdir); @@ -188,26 +197,21 @@ std::pair parseFlakeRefWithFragment( } else { if (!hasPrefix(path, "/")) throw BadURL("flake reference '%s' is not an absolute path", url); - auto query = decodeQuery(match[2]); - path = canonPath(path + "/" + getOr(query, "dir", "")); } - fetchers::Attrs attrs; - attrs.insert_or_assign("type", "path"); - attrs.insert_or_assign("path", path); - - return std::make_pair(FlakeRef(Input::fromAttrs(std::move(attrs)), ""), fragment); + return fromParsedURL({ + .url = path, // FIXME + .base = path, + .scheme = "path", + .authority = "", + .path = path, + .query = query, + .fragment = fragment + }); } - else { - auto parsedURL = parseURL(url); - std::string fragment; - std::swap(fragment, parsedURL.fragment); - - return std::make_pair( - FlakeRef(Input::fromURL(parsedURL), getOr(parsedURL.query, "dir", "")), - fragment); - } + else + return fromParsedURL(parseURL(url)); } std::optional> maybeParseFlakeRefWithFragment(