Use git+ prefix in flake URI schemes

Fixes #3045.
This commit is contained in:
Eelco Dolstra 2019-09-05 17:15:09 +02:00
parent 6f88fed819
commit 2fa7f2a56a
No known key found for this signature in database
GPG key ID: 8170B4726D7198DE
3 changed files with 36 additions and 26 deletions

View file

@ -27,7 +27,7 @@ const static std::string ownerRegex = "[a-zA-Z][a-zA-Z0-9_-]*";
const static std::string repoRegex = "[a-zA-Z][a-zA-Z0-9_-]*"; const static std::string repoRegex = "[a-zA-Z][a-zA-Z0-9_-]*";
// URI stuff. // URI stuff.
const static std::string schemeRegex = "(?:http|https|ssh|git|file)"; const static std::string schemeRegex = "[a-z+]+";
const static std::string authorityRegex = "[a-zA-Z0-9._~-]*"; const static std::string authorityRegex = "[a-zA-Z0-9._~-]*";
const static std::string segmentRegex = "[a-zA-Z0-9._~-]+"; const static std::string segmentRegex = "[a-zA-Z0-9._~-]+";
const static std::string pathRegex = "/?" + segmentRegex + "(?:/" + segmentRegex + ")*"; const static std::string pathRegex = "/?" + segmentRegex + "(?:/" + segmentRegex + ")*";
@ -120,8 +120,14 @@ FlakeRef::FlakeRef(const std::string & uri_, bool allowRelative)
data = d; data = d;
} }
else if (std::regex_match(uri.c_str(), match, uriRegex) else if (std::regex_match(uri.c_str(), match, uriRegex)) {
&& (match[2] == "file" || hasSuffix(match[4], ".git"))) auto & scheme = match[2];
if (scheme == "git" ||
scheme == "git+http" ||
scheme == "git+https" ||
scheme == "git+ssh" ||
scheme == "git+file" ||
scheme == "file")
{ {
IsGit d; IsGit d;
d.uri = match[1]; d.uri = match[1];
@ -135,6 +141,8 @@ FlakeRef::FlakeRef(const std::string & uri_, bool allowRelative)
if (rev && !ref) if (rev && !ref)
throw BadFlakeRef("flake URI '%s' lacks a Git ref", uri); throw BadFlakeRef("flake URI '%s' lacks a Git ref", uri);
data = d; data = d;
} else
throw BadFlakeRef("unsupported URI scheme '%s' in flake reference '%s'", scheme, uri);
} }
else if ((hasPrefix(uri, "/") || (allowRelative && (hasPrefix(uri, "./") || hasPrefix(uri, "../") || uri == "."))) else if ((hasPrefix(uri, "/") || (allowRelative && (hasPrefix(uri, "./") || hasPrefix(uri, "../") || uri == ".")))

View file

@ -52,28 +52,28 @@ namespace nix {
github:edolstra/dwarffs/unstable github:edolstra/dwarffs/unstable
github:edolstra/dwarffs/41c0c1bf292ea3ac3858ff393b49ca1123dbd553 github:edolstra/dwarffs/41c0c1bf292ea3ac3858ff393b49ca1123dbd553
* https://<server>/<path>.git(\?attr(&attr)*)? * git+https://<server>/<path>(\?attr(&attr)*)?
ssh://<server>/<path>.git(\?attr(&attr)*)? git+ssh://<server>/<path>(\?attr(&attr)*)?
git://<server>/<path>.git(\?attr(&attr)*)? git://<server>/<path>(\?attr(&attr)*)?
file:///<path>(\?attr(&attr)*)? file:///<path>(\?attr(&attr)*)?
where 'attr' is one of: where 'attr' is one of:
rev=<rev> rev=<rev>
ref=<ref> ref=<ref>
A Git repository fetched through https. Note that the path must A Git repository fetched through https. The default for "ref" is
end in ".git". The default for "ref" is "master". "master".
Examples: Examples:
https://example.org/my/repo.git git+https://example.org/my/repo.git
https://example.org/my/repo.git?ref=release-1.2.3 git+https://example.org/my/repo.git?ref=release-1.2.3
https://example.org/my/repo.git?rev=e72daba8250068216d79d2aeef40d4d95aff6666 git+https://example.org/my/repo.git?rev=e72daba8250068216d79d2aeef40d4d95aff6666
git://github.com/edolstra/dwarffs.git?ref=flake&rev=2efca4bc9da70fb001b26c3dc858c6397d3c4817 git://github.com/edolstra/dwarffs.git?ref=flake&rev=2efca4bc9da70fb001b26c3dc858c6397d3c4817
* /path.git(\?attr(&attr)*)? * /path(\?attr(&attr)*)?
Like file://path.git, but if no "ref" or "rev" is specified, the Like file://path, but if no "ref" or "rev" is specified, the
(possibly dirty) working tree will be used. Using a working tree (possibly dirty) working tree will be used. Using a working tree
is not allowed in pure evaluation mode. is not allowed in pure evaluation mode.

View file

@ -25,6 +25,8 @@ GitInfo exportGit(ref<Store> store, std::string uri,
{ {
assert(!rev || rev->type == htSHA1); assert(!rev || rev->type == htSHA1);
if (hasPrefix(uri, "git+")) uri = std::string(uri, 4);
bool isLocal = hasPrefix(uri, "/") && pathExists(uri + "/.git"); bool isLocal = hasPrefix(uri, "/") && pathExists(uri + "/.git");
// If this is a local directory (but not a file:// URI) and no ref // If this is a local directory (but not a file:// URI) and no ref