aboutsummaryrefslogtreecommitdiff
path: root/src/libexpr/primops/flake.cc
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2018-12-12 13:20:59 +0100
committerEelco Dolstra <edolstra@gmail.com>2019-02-11 12:05:17 +0100
commitdcae46ab146b735aa49fcf4cad4a320e79362c5e (patch)
treed48ef2b512c2fe04992552282ca2d58d4242c127 /src/libexpr/primops/flake.cc
parentef4cf4e681bfe30b15b8c2940b51b322bce5b6d8 (diff)
Add github URIs
For example, github:edolstra/dwarffs is more-or-less equivalent to https://github.com/edolstra/dwarffs.git. It's a much faster way to get GitHub repositories: it fetches tarballs rather than entire Git repositories. It also allows fetching specific revisions by hash without specifying a ref (e.g. a branch name): github:edolstra/dwarffs/41c0c1bf292ea3ac3858ff393b49ca1123dbd553
Diffstat (limited to 'src/libexpr/primops/flake.cc')
-rw-r--r--src/libexpr/primops/flake.cc23
1 files changed, 22 insertions, 1 deletions
diff --git a/src/libexpr/primops/flake.cc b/src/libexpr/primops/flake.cc
index 9dc6fa1f1..81e912402 100644
--- a/src/libexpr/primops/flake.cc
+++ b/src/libexpr/primops/flake.cc
@@ -68,7 +68,8 @@ struct Flake
Value * vProvides; // FIXME: gc
};
-std::regex flakeRegex("^flake:([a-zA-Z][a-zA-Z0-9_-]+)$");
+std::regex flakeRegex("^flake:([a-zA-Z][a-zA-Z0-9_-]*)(/[a-zA-Z][a-zA-Z0-9_.-]*)?$");
+std::regex githubRegex("^github:([a-zA-Z][a-zA-Z0-9_-]*)/([a-zA-Z][a-zA-Z0-9_-]*)(/([a-zA-Z][a-zA-Z0-9_-]*))?$");
static Path fetchFlake(EvalState & state, const std::string & flakeUri)
{
@@ -76,6 +77,7 @@ static Path fetchFlake(EvalState & state, const std::string & flakeUri)
if (std::regex_match(flakeUri, match, flakeRegex)) {
auto flakeName = match[1];
+ auto revOrRef = match[2];
auto registry = state.getFlakeRegistry();
auto i = registry.entries.find(flakeName);
if (i == registry.entries.end())
@@ -83,6 +85,25 @@ static Path fetchFlake(EvalState & state, const std::string & flakeUri)
return fetchFlake(state, i->second.uri);
}
+ else if (std::regex_match(flakeUri, match, githubRegex)) {
+ auto owner = match[1];
+ auto repo = match[2];
+ auto revOrRef = match[4].str();
+ if (revOrRef.empty()) revOrRef = "master";
+
+ // FIXME: require hash in pure mode.
+
+ // FIXME: use regular /archive URLs instead? api.github.com
+ // might have stricter rate limits.
+ auto storePath = getDownloader()->downloadCached(state.store,
+ fmt("https://api.github.com/repos/%s/%s/tarball/%s", owner, repo, revOrRef),
+ true, "source");
+
+ // FIXME: extract revision hash from ETag.
+
+ return storePath;
+ }
+
else if (hasPrefix(flakeUri, "/") || hasPrefix(flakeUri, "git://")) {
auto gitInfo = exportGit(state.store, flakeUri, {}, "", "source");
return gitInfo.storePath;