Allow 'dir' parameter in github: URIs

E.g. 'github:edolstra/dwarffs/flake?dir=foo/bar'.
This commit is contained in:
Eelco Dolstra 2019-05-01 20:43:16 +02:00
parent a37436d792
commit 5d6e8c008b

View file

@ -33,12 +33,14 @@ const static std::string pathRegex = "/?" + segmentRegex + "(?:/" + segmentRegex
// FIXME: support escaping in query string. // FIXME: support escaping in query string.
// Note: '/' is not a valid query parameter, but so what... // Note: '/' is not a valid query parameter, but so what...
const static std::string paramRegex = "[a-z]+=[/a-zA-Z0-9._-]*"; const static std::string paramRegex = "[a-z]+=[/a-zA-Z0-9._-]*";
const static std::string paramsRegex = "(?:[?](" + paramRegex + "(?:&" + paramRegex + ")*))";
// 'dir' path elements cannot start with a '.'. We also reject // 'dir' path elements cannot start with a '.'. We also reject
// potentially dangerous characters like ';'. // potentially dangerous characters like ';'.
const static std::string subDirElemRegex = "(?:[a-zA-Z0-9_-]+[a-zA-Z0-9._-]*)"; const static std::string subDirElemRegex = "(?:[a-zA-Z0-9_-]+[a-zA-Z0-9._-]*)";
const static std::string subDirRegex = subDirElemRegex + "(?:/" + subDirElemRegex + ")*"; const static std::string subDirRegex = subDirElemRegex + "(?:/" + subDirElemRegex + ")*";
FlakeRef::FlakeRef(const std::string & uri, bool allowRelative) FlakeRef::FlakeRef(const std::string & uri, bool allowRelative)
{ {
// FIXME: could combine this into one regex. // FIXME: could combine this into one regex.
@ -48,14 +50,15 @@ FlakeRef::FlakeRef(const std::string & uri, bool allowRelative)
std::regex::ECMAScript); std::regex::ECMAScript);
static std::regex githubRegex( static std::regex githubRegex(
"github:(" + ownerRegex + ")/(" + repoRegex + ")(?:/" + revOrRefRegex + ")?", "github:(" + ownerRegex + ")/(" + repoRegex + ")(?:/" + revOrRefRegex + ")?"
+ paramsRegex + "?",
std::regex::ECMAScript); std::regex::ECMAScript);
static std::regex uriRegex( static std::regex uriRegex(
"((" + schemeRegex + "):" + "((" + schemeRegex + "):" +
"(?://(" + authorityRegex + "))?" + "(?://(" + authorityRegex + "))?" +
"(" + pathRegex + "))" + "(" + pathRegex + "))" +
"(?:[?](" + paramRegex + "(?:&" + paramRegex + ")*))?", paramsRegex + "?",
std::regex::ECMAScript); std::regex::ECMAScript);
static std::regex refRegex2(refRegex, std::regex::ECMAScript); static std::regex refRegex2(refRegex, std::regex::ECMAScript);
@ -85,6 +88,18 @@ FlakeRef::FlakeRef(const std::string & uri, bool allowRelative)
else if (match[4].matched) { else if (match[4].matched) {
ref = match[4]; ref = match[4];
} }
for (auto & param : tokenizeString<Strings>(match[5], "&")) {
auto n = param.find('=');
assert(n != param.npos);
std::string name(param, 0, n);
std::string value(param, n + 1);
if (name == "dir") {
if (value != "" && !std::regex_match(value, subDirRegex2))
throw Error("flake '%s' has invalid subdirectory '%s'", uri, value);
subdir = value;
} else
throw Error("invalid Git flake reference parameter '%s', in '%s'", name, uri);
}
data = d; data = d;
} }