aboutsummaryrefslogtreecommitdiff
path: root/src/libfetchers
diff options
context:
space:
mode:
Diffstat (limited to 'src/libfetchers')
-rw-r--r--src/libfetchers/fetchers.hh2
-rw-r--r--src/libfetchers/github.cc76
-rw-r--r--src/libfetchers/registry.cc2
-rw-r--r--src/libfetchers/tarball.cc9
4 files changed, 65 insertions, 24 deletions
diff --git a/src/libfetchers/fetchers.hh b/src/libfetchers/fetchers.hh
index 89b1e6e7d..62807e53b 100644
--- a/src/libfetchers/fetchers.hh
+++ b/src/libfetchers/fetchers.hh
@@ -118,12 +118,14 @@ struct DownloadFileResult
DownloadFileResult downloadFile(
ref<Store> store,
const std::string & url,
+ const Headers & headers,
const std::string & name,
bool immutable);
std::pair<Tree, time_t> downloadTarball(
ref<Store> store,
const std::string & url,
+ const Headers & headers,
const std::string & name,
bool immutable);
diff --git a/src/libfetchers/github.cc b/src/libfetchers/github.cc
index 1cc0c5e2e..d8d0351b9 100644
--- a/src/libfetchers/github.cc
+++ b/src/libfetchers/github.cc
@@ -3,11 +3,24 @@
#include "fetchers.hh"
#include "globals.hh"
#include "store-api.hh"
+#include "types.hh"
#include <nlohmann/json.hpp>
namespace nix::fetchers {
+struct DownloadUrl
+{
+ std::string url;
+ std::optional<std::pair<std::string, std::string>> access_token_header;
+
+ DownloadUrl(const std::string & url)
+ : url(url) { }
+
+ DownloadUrl(const std::string & url, const std::pair<std::string, std::string> & access_token_header)
+ : url(url), access_token_header(access_token_header) { }
+};
+
// A github or gitlab url
const static std::string urlRegexS = "[a-zA-Z0-9.]*"; // FIXME: check
std::regex urlRegex(urlRegexS, std::regex::ECMAScript);
@@ -16,6 +29,8 @@ struct GitArchiveInputScheme : InputScheme
{
virtual std::string type() = 0;
+ virtual std::pair<std::string, std::string> accessHeaderFromToken(const std::string & token) const = 0;
+
std::optional<Input> inputFromURL(const ParsedURL & url) override
{
if (url.scheme != type()) return {};
@@ -131,7 +146,7 @@ struct GitArchiveInputScheme : InputScheme
virtual Hash getRevFromRef(nix::ref<Store> store, const Input & input) const = 0;
- virtual std::string getDownloadUrl(const Input & input) const = 0;
+ virtual DownloadUrl getDownloadUrl(const Input & input) const = 0;
std::pair<Tree, Input> fetch(ref<Store> store, const Input & _input) override
{
@@ -160,7 +175,12 @@ struct GitArchiveInputScheme : InputScheme
auto url = getDownloadUrl(input);
- auto [tree, lastModified] = downloadTarball(store, url, "source", true);
+ Headers headers;
+ if (url.access_token_header) {
+ headers.push_back(*url.access_token_header);
+ }
+
+ auto [tree, lastModified] = downloadTarball(store, url.url, headers, "source", true);
input.attrs.insert_or_assign("lastModified", lastModified);
@@ -182,11 +202,8 @@ struct GitHubInputScheme : GitArchiveInputScheme
{
std::string type() override { return "github"; }
- void addAccessToken(std::string & url) const
- {
- std::string accessToken = settings.githubAccessToken.get();
- if (accessToken != "")
- url += "?access_token=" + accessToken;
+ std::pair<std::string, std::string> accessHeaderFromToken(const std::string & token) const {
+ return std::pair<std::string, std::string>("Authorization", fmt("token %s", token));
}
Hash getRevFromRef(nix::ref<Store> store, const Input & input) const override
@@ -195,18 +212,21 @@ struct GitHubInputScheme : GitArchiveInputScheme
auto url = fmt("https://api.%s/repos/%s/%s/commits/%s", // FIXME: check
host_url, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo"), *input.getRef());
- addAccessToken(url);
+ Headers headers;
+ std::string accessToken = settings.githubAccessToken.get();
+ if (accessToken != "")
+ headers.push_back(accessHeaderFromToken(accessToken));
auto json = nlohmann::json::parse(
readFile(
store->toRealPath(
- downloadFile(store, url, "source", false).storePath)));
+ downloadFile(store, url, headers, "source", false).storePath)));
auto rev = Hash::parseAny(std::string { json["sha"] }, htSHA1);
debug("HEAD revision for '%s' is %s", url, rev.gitRev());
return rev;
}
- std::string getDownloadUrl(const Input & input) const override
+ DownloadUrl getDownloadUrl(const Input & input) const override
{
// FIXME: use regular /archive URLs instead? api.github.com
// might have stricter rate limits.
@@ -215,9 +235,13 @@ struct GitHubInputScheme : GitArchiveInputScheme
host_url, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo"),
input.getRev()->to_string(Base16, false));
- addAccessToken(url);
-
- return url;
+ std::string accessToken = settings.githubAccessToken.get();
+ if (accessToken != "") {
+ auto auth_header = accessHeaderFromToken(accessToken);
+ return DownloadUrl(url, auth_header);
+ } else {
+ return DownloadUrl(url);
+ }
}
void clone(const Input & input, const Path & destDir) override
@@ -234,21 +258,31 @@ struct GitLabInputScheme : GitArchiveInputScheme
{
std::string type() override { return "gitlab"; }
+ std::pair<std::string, std::string> accessHeaderFromToken(const std::string & token) const {
+ return std::pair<std::string, std::string>("Authorization", fmt("Bearer %s", token));
+ }
+
Hash getRevFromRef(nix::ref<Store> store, const Input & input) const override
{
auto host_url = maybeGetStrAttr(input.attrs, "url").value_or("gitlab.com");
auto url = fmt("https://%s/api/v4/projects/%s%%2F%s/repository/commits?ref_name=%s",
host_url, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo"), *input.getRef());
+
+ Headers headers;
+ std::string accessToken = settings.gitlabAccessToken.get();
+ if (accessToken != "")
+ headers.push_back(accessHeaderFromToken(accessToken));
+
auto json = nlohmann::json::parse(
readFile(
store->toRealPath(
- downloadFile(store, url, "source", false).storePath)));
+ downloadFile(store, url, headers, "source", false).storePath)));
auto rev = Hash::parseAny(std::string(json[0]["id"]), htSHA1);
debug("HEAD revision for '%s' is %s", url, rev.gitRev());
return rev;
}
- std::string getDownloadUrl(const Input & input) const override
+ DownloadUrl getDownloadUrl(const Input & input) const override
{
// FIXME: This endpoint has a rate limit threshold of 5 requests per minute
auto host_url = maybeGetStrAttr(input.attrs, "url").value_or("gitlab.com");
@@ -256,12 +290,14 @@ struct GitLabInputScheme : GitArchiveInputScheme
host_url, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo"),
input.getRev()->to_string(Base16, false));
- /* # FIXME: add privat token auth (`curl --header "PRIVATE-TOKEN: <your_access_token>"`)
- std::string accessToken = settings.githubAccessToken.get();
- if (accessToken != "")
- url += "?access_token=" + accessToken;*/
+ std::string accessToken = settings.gitlabAccessToken.get();
+ if (accessToken != "") {
+ auto auth_header = accessHeaderFromToken(accessToken);
+ return DownloadUrl(url, auth_header);
+ } else {
+ return DownloadUrl(url);
+ }
- return url;
}
void clone(const Input & input, const Path & destDir) override
diff --git a/src/libfetchers/registry.cc b/src/libfetchers/registry.cc
index 4367ee810..551e7684a 100644
--- a/src/libfetchers/registry.cc
+++ b/src/libfetchers/registry.cc
@@ -145,7 +145,7 @@ static std::shared_ptr<Registry> getGlobalRegistry(ref<Store> store)
auto path = settings.flakeRegistry.get();
if (!hasPrefix(path, "/")) {
- auto storePath = downloadFile(store, path, "flake-registry.json", false).storePath;
+ auto storePath = downloadFile(store, path, Headers {}, "flake-registry.json", false).storePath;
if (auto store2 = store.dynamic_pointer_cast<LocalFSStore>())
store2->addPermRoot(storePath, getCacheDir() + "/nix/flake-registry.json");
path = store->toRealPath(storePath);
diff --git a/src/libfetchers/tarball.cc b/src/libfetchers/tarball.cc
index a2d16365e..cf6d6e3d2 100644
--- a/src/libfetchers/tarball.cc
+++ b/src/libfetchers/tarball.cc
@@ -5,12 +5,14 @@
#include "store-api.hh"
#include "archive.hh"
#include "tarfile.hh"
+#include "types.hh"
namespace nix::fetchers {
DownloadFileResult downloadFile(
ref<Store> store,
const std::string & url,
+ const Headers & headers,
const std::string & name,
bool immutable)
{
@@ -36,7 +38,7 @@ DownloadFileResult downloadFile(
if (cached && !cached->expired)
return useCached();
- FileTransferRequest request(url);
+ FileTransferRequest request(url, headers);
if (cached)
request.expectedETag = getStrAttr(cached->infoAttrs, "etag");
FileTransferResult res;
@@ -110,6 +112,7 @@ DownloadFileResult downloadFile(
std::pair<Tree, time_t> downloadTarball(
ref<Store> store,
const std::string & url,
+ const Headers & headers,
const std::string & name,
bool immutable)
{
@@ -127,7 +130,7 @@ std::pair<Tree, time_t> downloadTarball(
getIntAttr(cached->infoAttrs, "lastModified")
};
- auto res = downloadFile(store, url, name, immutable);
+ auto res = downloadFile(store, url, headers, name, immutable);
std::optional<StorePath> unpackedStorePath;
time_t lastModified;
@@ -222,7 +225,7 @@ struct TarballInputScheme : InputScheme
std::pair<Tree, Input> fetch(ref<Store> store, const Input & input) override
{
- auto tree = downloadTarball(store, getStrAttr(input.attrs, "url"), "source", false).first;
+ auto tree = downloadTarball(store, getStrAttr(input.attrs, "url"), Headers {}, "source", false).first;
return {std::move(tree), input};
}
};