From dcae46ab146b735aa49fcf4cad4a320e79362c5e Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 12 Dec 2018 13:20:59 +0100 Subject: [PATCH] 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 --- src/libexpr/primops/flake.cc | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) 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;