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
This commit is contained in:
Eelco Dolstra 2018-12-12 13:20:59 +01:00
parent ef4cf4e681
commit dcae46ab14
No known key found for this signature in database
GPG key ID: 8170B4726D7198DE

View file

@ -68,7 +68,8 @@ struct Flake
Value * vProvides; // FIXME: gc 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) 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)) { if (std::regex_match(flakeUri, match, flakeRegex)) {
auto flakeName = match[1]; auto flakeName = match[1];
auto revOrRef = match[2];
auto registry = state.getFlakeRegistry(); auto registry = state.getFlakeRegistry();
auto i = registry.entries.find(flakeName); auto i = registry.entries.find(flakeName);
if (i == registry.entries.end()) if (i == registry.entries.end())
@ -83,6 +85,25 @@ static Path fetchFlake(EvalState & state, const std::string & flakeUri)
return fetchFlake(state, i->second.uri); 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://")) { else if (hasPrefix(flakeUri, "/") || hasPrefix(flakeUri, "git://")) {
auto gitInfo = exportGit(state.store, flakeUri, {}, "", "source"); auto gitInfo = exportGit(state.store, flakeUri, {}, "", "source");
return gitInfo.storePath; return gitInfo.storePath;