aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2019-09-05 17:15:09 +0200
committerEelco Dolstra <edolstra@gmail.com>2019-09-05 17:15:09 +0200
commit2fa7f2a56a5c2fe11c1a0daceee5cf0584b69be9 (patch)
tree99785bfaef5aa4fda054b342333cb7beed20ca62
parent6f88fed8195c43bc46e3f9e62273599f6cc205fa (diff)
Use git+ prefix in flake URI schemes
Fixes #3045.
-rw-r--r--src/libexpr/flake/flakeref.cc40
-rw-r--r--src/libexpr/flake/flakeref.hh20
-rw-r--r--src/libexpr/primops/fetchGit.cc2
3 files changed, 36 insertions, 26 deletions
diff --git a/src/libexpr/flake/flakeref.cc b/src/libexpr/flake/flakeref.cc
index 253442566..4ce326c0b 100644
--- a/src/libexpr/flake/flakeref.cc
+++ b/src/libexpr/flake/flakeref.cc
@@ -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_-]*";
// 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 segmentRegex = "[a-zA-Z0-9._~-]+";
const static std::string pathRegex = "/?" + segmentRegex + "(?:/" + segmentRegex + ")*";
@@ -120,21 +120,29 @@ FlakeRef::FlakeRef(const std::string & uri_, bool allowRelative)
data = d;
}
- else if (std::regex_match(uri.c_str(), match, uriRegex)
- && (match[2] == "file" || hasSuffix(match[4], ".git")))
- {
- IsGit d;
- d.uri = match[1];
- for (auto & param : params) {
- if (handleGitParams(param.first, param.second))
- ;
- else
- // FIXME: should probably pass through unknown parameters
- throw BadFlakeRef("invalid Git flakeref parameter '%s', in '%s'", param.first, uri);
- }
- if (rev && !ref)
- throw BadFlakeRef("flake URI '%s' lacks a Git ref", uri);
- data = d;
+ else if (std::regex_match(uri.c_str(), match, uriRegex)) {
+ auto & scheme = match[2];
+ if (scheme == "git" ||
+ scheme == "git+http" ||
+ scheme == "git+https" ||
+ scheme == "git+ssh" ||
+ scheme == "git+file" ||
+ scheme == "file")
+ {
+ IsGit d;
+ d.uri = match[1];
+ for (auto & param : params) {
+ if (handleGitParams(param.first, param.second))
+ ;
+ else
+ // FIXME: should probably pass through unknown parameters
+ throw BadFlakeRef("invalid Git flakeref parameter '%s', in '%s'", param.first, uri);
+ }
+ if (rev && !ref)
+ throw BadFlakeRef("flake URI '%s' lacks a Git ref", uri);
+ 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 == ".")))
diff --git a/src/libexpr/flake/flakeref.hh b/src/libexpr/flake/flakeref.hh
index 9ddc227bb..6b47330a7 100644
--- a/src/libexpr/flake/flakeref.hh
+++ b/src/libexpr/flake/flakeref.hh
@@ -52,28 +52,28 @@ namespace nix {
github:edolstra/dwarffs/unstable
github:edolstra/dwarffs/41c0c1bf292ea3ac3858ff393b49ca1123dbd553
- * https://<server>/<path>.git(\?attr(&attr)*)?
- ssh://<server>/<path>.git(\?attr(&attr)*)?
- git://<server>/<path>.git(\?attr(&attr)*)?
+ * git+https://<server>/<path>(\?attr(&attr)*)?
+ git+ssh://<server>/<path>(\?attr(&attr)*)?
+ git://<server>/<path>(\?attr(&attr)*)?
file:///<path>(\?attr(&attr)*)?
where 'attr' is one of:
rev=<rev>
ref=<ref>
- A Git repository fetched through https. Note that the path must
- end in ".git". The default for "ref" is "master".
+ A Git repository fetched through https. The default for "ref" is
+ "master".
Examples:
- https://example.org/my/repo.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
+ git+https://example.org/my/repo.git?ref=release-1.2.3
+ git+https://example.org/my/repo.git?rev=e72daba8250068216d79d2aeef40d4d95aff6666
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
is not allowed in pure evaluation mode.
diff --git a/src/libexpr/primops/fetchGit.cc b/src/libexpr/primops/fetchGit.cc
index 931eac95f..48d84c4a1 100644
--- a/src/libexpr/primops/fetchGit.cc
+++ b/src/libexpr/primops/fetchGit.cc
@@ -25,6 +25,8 @@ GitInfo exportGit(ref<Store> store, std::string uri,
{
assert(!rev || rev->type == htSHA1);
+ if (hasPrefix(uri, "git+")) uri = std::string(uri, 4);
+
bool isLocal = hasPrefix(uri, "/") && pathExists(uri + "/.git");
// If this is a local directory (but not a file:// URI) and no ref