aboutsummaryrefslogtreecommitdiff
path: root/src/libfetchers
diff options
context:
space:
mode:
Diffstat (limited to 'src/libfetchers')
-rw-r--r--src/libfetchers/cache.cc8
-rw-r--r--src/libfetchers/cache.hh2
-rw-r--r--src/libfetchers/fetch-settings.cc13
-rw-r--r--src/libfetchers/fetch-settings.hh93
-rw-r--r--src/libfetchers/fetchers.cc20
-rw-r--r--src/libfetchers/fetchers.hh15
-rw-r--r--src/libfetchers/git.cc44
-rw-r--r--src/libfetchers/github.cc114
-rw-r--r--src/libfetchers/indirect.cc2
-rw-r--r--src/libfetchers/mercurial.cc38
-rw-r--r--src/libfetchers/path.cc9
-rw-r--r--src/libfetchers/registry.cc4
-rw-r--r--src/libfetchers/tarball.cc33
13 files changed, 290 insertions, 105 deletions
diff --git a/src/libfetchers/cache.cc b/src/libfetchers/cache.cc
index 34ff6f85b..0c8ecac9d 100644
--- a/src/libfetchers/cache.cc
+++ b/src/libfetchers/cache.cc
@@ -52,13 +52,13 @@ struct CacheImpl : Cache
const Attrs & inAttrs,
const Attrs & infoAttrs,
const StorePath & storePath,
- bool immutable) override
+ bool locked) override
{
_state.lock()->add.use()
(attrsToJSON(inAttrs).dump())
(attrsToJSON(infoAttrs).dump())
(store->printStorePath(storePath))
- (immutable)
+ (locked)
(time(0)).exec();
}
@@ -91,7 +91,7 @@ struct CacheImpl : Cache
auto infoJSON = stmt.getStr(0);
auto storePath = store->parseStorePath(stmt.getStr(1));
- auto immutable = stmt.getInt(2) != 0;
+ auto locked = stmt.getInt(2) != 0;
auto timestamp = stmt.getInt(3);
store->addTempRoot(storePath);
@@ -105,7 +105,7 @@ struct CacheImpl : Cache
inAttrsJSON, infoJSON, store->printStorePath(storePath));
return Result {
- .expired = !immutable && (settings.tarballTtl.get() == 0 || timestamp + settings.tarballTtl < time(0)),
+ .expired = !locked && (settings.tarballTtl.get() == 0 || timestamp + settings.tarballTtl < time(0)),
.infoAttrs = jsonToAttrs(nlohmann::json::parse(infoJSON)),
.storePath = std::move(storePath)
};
diff --git a/src/libfetchers/cache.hh b/src/libfetchers/cache.hh
index 3db4f081c..3763ee2a6 100644
--- a/src/libfetchers/cache.hh
+++ b/src/libfetchers/cache.hh
@@ -13,7 +13,7 @@ struct Cache
const Attrs & inAttrs,
const Attrs & infoAttrs,
const StorePath & storePath,
- bool immutable) = 0;
+ bool locked) = 0;
virtual std::optional<std::pair<Attrs, StorePath>> lookup(
ref<Store> store,
diff --git a/src/libfetchers/fetch-settings.cc b/src/libfetchers/fetch-settings.cc
new file mode 100644
index 000000000..e7d5244dc
--- /dev/null
+++ b/src/libfetchers/fetch-settings.cc
@@ -0,0 +1,13 @@
+#include "fetch-settings.hh"
+
+namespace nix {
+
+FetchSettings::FetchSettings()
+{
+}
+
+FetchSettings fetchSettings;
+
+static GlobalConfig::Register rFetchSettings(&fetchSettings);
+
+}
diff --git a/src/libfetchers/fetch-settings.hh b/src/libfetchers/fetch-settings.hh
new file mode 100644
index 000000000..04c9feda0
--- /dev/null
+++ b/src/libfetchers/fetch-settings.hh
@@ -0,0 +1,93 @@
+#pragma once
+
+#include "types.hh"
+#include "config.hh"
+#include "util.hh"
+
+#include <map>
+#include <limits>
+
+#include <sys/types.h>
+
+namespace nix {
+
+struct FetchSettings : public Config
+{
+ FetchSettings();
+
+ Setting<StringMap> accessTokens{this, {}, "access-tokens",
+ R"(
+ Access tokens used to access protected GitHub, GitLab, or
+ other locations requiring token-based authentication.
+
+ Access tokens are specified as a string made up of
+ space-separated `host=token` values. The specific token
+ used is selected by matching the `host` portion against the
+ "host" specification of the input. The actual use of the
+ `token` value is determined by the type of resource being
+ accessed:
+
+ * Github: the token value is the OAUTH-TOKEN string obtained
+ as the Personal Access Token from the Github server (see
+ https://docs.github.com/en/developers/apps/building-oauth-apps/authorizing-oauth-apps).
+
+ * Gitlab: the token value is either the OAuth2 token or the
+ Personal Access Token (these are different types tokens
+ for gitlab, see
+ https://docs.gitlab.com/12.10/ee/api/README.html#authentication).
+ The `token` value should be `type:tokenstring` where
+ `type` is either `OAuth2` or `PAT` to indicate which type
+ of token is being specified.
+
+ Example `~/.config/nix/nix.conf`:
+
+ ```
+ access-tokens = github.com=23ac...b289 gitlab.mycompany.com=PAT:A123Bp_Cd..EfG gitlab.com=OAuth2:1jklw3jk
+ ```
+
+ Example `~/code/flake.nix`:
+
+ ```nix
+ input.foo = {
+ type = "gitlab";
+ host = "gitlab.mycompany.com";
+ owner = "mycompany";
+ repo = "pro";
+ };
+ ```
+
+ This example specifies three tokens, one each for accessing
+ github.com, gitlab.mycompany.com, and sourceforge.net.
+
+ The `input.foo` uses the "gitlab" fetcher, which might
+ requires specifying the token type along with the token
+ value.
+ )"};
+
+ Setting<bool> allowDirty{this, true, "allow-dirty",
+ "Whether to allow dirty Git/Mercurial trees."};
+
+ Setting<bool> warnDirty{this, true, "warn-dirty",
+ "Whether to warn about dirty Git/Mercurial trees."};
+
+ Setting<std::string> flakeRegistry{this, "https://github.com/NixOS/flake-registry/raw/master/flake-registry.json", "flake-registry",
+ "Path or URI of the global flake registry."};
+
+ Setting<bool> useRegistries{this, true, "use-registries",
+ "Whether to use flake registries to resolve flake references."};
+
+ Setting<bool> acceptFlakeConfig{this, false, "accept-flake-config",
+ "Whether to accept nix configuration from a flake without prompting."};
+
+ Setting<std::string> commitLockFileSummary{
+ this, "", "commit-lockfile-summary",
+ R"(
+ The commit summary to use when committing changed flake lock files. If
+ empty, the summary is generated based on the action performed.
+ )"};
+};
+
+// FIXME: don't use a global variable.
+extern FetchSettings fetchSettings;
+
+}
diff --git a/src/libfetchers/fetchers.cc b/src/libfetchers/fetchers.cc
index 7a88b4acc..4c457966d 100644
--- a/src/libfetchers/fetchers.cc
+++ b/src/libfetchers/fetchers.cc
@@ -24,11 +24,11 @@ static void fixupInput(Input & input)
input.getType();
input.getRef();
if (input.getRev())
- input.immutable = true;
+ input.locked = true;
input.getRevCount();
input.getLastModified();
if (input.getNarHash())
- input.immutable = true;
+ input.locked = true;
}
Input Input::fromURL(const ParsedURL & url)
@@ -124,15 +124,13 @@ std::pair<Tree, Input> Input::fetch(ref<Store> store) const
debug("using substituted/cached input '%s' in '%s'",
to_string(), store->printStorePath(storePath));
- auto actualPath = store->toRealPath(storePath);
-
- return {fetchers::Tree(std::move(actualPath), std::move(storePath)), *this};
+ return {Tree { .actualPath = store->toRealPath(storePath), .storePath = std::move(storePath) }, *this};
} catch (Error & e) {
debug("substitution of input '%s' failed: %s", to_string(), e.what());
}
}
- auto [tree, input] = [&]() -> std::pair<Tree, Input> {
+ auto [storePath, input] = [&]() -> std::pair<StorePath, Input> {
try {
return scheme->fetch(store, *this);
} catch (Error & e) {
@@ -141,8 +139,10 @@ std::pair<Tree, Input> Input::fetch(ref<Store> store) const
}
}();
- if (tree.actualPath == "")
- tree.actualPath = store->toRealPath(tree.storePath);
+ Tree tree {
+ .actualPath = store->toRealPath(storePath),
+ .storePath = storePath,
+ };
auto narHash = store->queryPathInfo(tree.storePath)->narHash;
input.attrs.insert_or_assign("narHash", narHash.to_string(SRI, true));
@@ -165,7 +165,7 @@ std::pair<Tree, Input> Input::fetch(ref<Store> store) const
input.to_string(), *prevRevCount);
}
- input.immutable = true;
+ input.locked = true;
assert(input.hasAllInfo());
@@ -209,7 +209,7 @@ StorePath Input::computeStorePath(Store & store) const
{
auto narHash = getNarHash();
if (!narHash)
- throw Error("cannot compute store path for mutable input '%s'", to_string());
+ throw Error("cannot compute store path for unlocked input '%s'", to_string());
return store.makeFixedOutputPath(getName(), FixedOutputInfo {
{
.method = FileIngestionMethod::Recursive,
diff --git a/src/libfetchers/fetchers.hh b/src/libfetchers/fetchers.hh
index c43b047a7..bc9a76b0b 100644
--- a/src/libfetchers/fetchers.hh
+++ b/src/libfetchers/fetchers.hh
@@ -16,7 +16,6 @@ struct Tree
{
Path actualPath;
StorePath storePath;
- Tree(Path && actualPath, StorePath && storePath) : actualPath(actualPath), storePath(std::move(storePath)) {}
};
struct InputScheme;
@@ -35,7 +34,7 @@ struct Input
std::shared_ptr<InputScheme> scheme; // note: can be null
Attrs attrs;
- bool immutable = false;
+ bool locked = false;
bool direct = true;
/* path of the parent of this input, used for relative path resolution */
@@ -60,9 +59,9 @@ public:
one that goes through a registry. */
bool isDirect() const { return direct; }
- /* Check whether this is an "immutable" input, that is,
+ /* Check whether this is a "locked" input, that is,
one that contains a commit hash or content hash. */
- bool isImmutable() const { return immutable; }
+ bool isLocked() const { return locked; }
bool hasAllInfo() const;
@@ -70,6 +69,8 @@ public:
bool contains(const Input & other) const;
+ /* Fetch the input into the Nix store, returning the location in
+ the Nix store and the locked input. */
std::pair<Tree, Input> fetch(ref<Store> store) const;
Input applyOverrides(
@@ -131,7 +132,7 @@ struct InputScheme
virtual void markChangedFile(const Input & input, std::string_view file, std::optional<std::string> commitMsg);
- virtual std::pair<Tree, Input> fetch(ref<Store> store, const Input & input) = 0;
+ virtual std::pair<StorePath, Input> fetch(ref<Store> store, const Input & input) = 0;
};
void registerInputScheme(std::shared_ptr<InputScheme> && fetcher);
@@ -147,14 +148,14 @@ DownloadFileResult downloadFile(
ref<Store> store,
const std::string & url,
const std::string & name,
- bool immutable,
+ bool locked,
const Headers & headers = {});
std::pair<Tree, time_t> downloadTarball(
ref<Store> store,
const std::string & url,
const std::string & name,
- bool immutable,
+ bool locked,
const Headers & headers = {});
}
diff --git a/src/libfetchers/git.cc b/src/libfetchers/git.cc
index 8468d2afc..c0beca2f2 100644
--- a/src/libfetchers/git.cc
+++ b/src/libfetchers/git.cc
@@ -6,6 +6,8 @@
#include "url-parts.hh"
#include "pathlocks.hh"
+#include "fetch-settings.hh"
+
#include <sys/time.h>
#include <sys/wait.h>
@@ -51,7 +53,7 @@ struct GitInputScheme : InputScheme
for (auto &[name, value] : url.query) {
if (name == "rev" || name == "ref")
attrs.emplace(name, value);
- else if (name == "shallow")
+ else if (name == "shallow" || name == "submodules")
attrs.emplace(name, Explicit<bool> { value == "1" });
else
url2.query.emplace(name, value);
@@ -172,7 +174,7 @@ struct GitInputScheme : InputScheme
return {isLocal, isLocal ? url.path : url.base};
}
- std::pair<Tree, Input> fetch(ref<Store> store, const Input & _input) override
+ std::pair<StorePath, Input> fetch(ref<Store> store, const Input & _input) override
{
Input input(_input);
@@ -187,7 +189,7 @@ struct GitInputScheme : InputScheme
if (submodules) cacheType += "-submodules";
if (allRefs) cacheType += "-all-refs";
- auto getImmutableAttrs = [&]()
+ auto getLockedAttrs = [&]()
{
return Attrs({
{"type", cacheType},
@@ -197,21 +199,18 @@ struct GitInputScheme : InputScheme
};
auto makeResult = [&](const Attrs & infoAttrs, StorePath && storePath)
- -> std::pair<Tree, Input>
+ -> std::pair<StorePath, Input>
{
assert(input.getRev());
assert(!_input.getRev() || _input.getRev() == input.getRev());
if (!shallow)
input.attrs.insert_or_assign("revCount", getIntAttr(infoAttrs, "revCount"));
input.attrs.insert_or_assign("lastModified", getIntAttr(infoAttrs, "lastModified"));
- return {
- Tree(store->toRealPath(storePath), std::move(storePath)),
- input
- };
+ return {std::move(storePath), input};
};
if (input.getRev()) {
- if (auto res = getCache()->lookup(store, getImmutableAttrs()))
+ if (auto res = getCache()->lookup(store, getLockedAttrs()))
return makeResult(res->first, std::move(res->second));
}
@@ -249,10 +248,10 @@ struct GitInputScheme : InputScheme
/* This is an unclean working tree. So copy all tracked files. */
- if (!settings.allowDirty)
+ if (!fetchSettings.allowDirty)
throw Error("Git tree '%s' is dirty", actualUrl);
- if (settings.warnDirty)
+ if (fetchSettings.warnDirty)
warn("Git tree '%s' is dirty", actualUrl);
auto gitOpts = Strings({ "-C", actualUrl, "ls-files", "-z" });
@@ -285,16 +284,13 @@ struct GitInputScheme : InputScheme
"lastModified",
haveCommits ? std::stoull(runProgram("git", true, { "-C", actualUrl, "log", "-1", "--format=%ct", "--no-show-signature", "HEAD" })) : 0);
- return {
- Tree(store->toRealPath(storePath), std::move(storePath)),
- input
- };
+ return {std::move(storePath), input};
}
}
if (!input.getRef()) input.attrs.insert_or_assign("ref", isLocal ? readHead(actualUrl) : "master");
- Attrs mutableAttrs({
+ Attrs unlockedAttrs({
{"type", cacheType},
{"name", name},
{"url", actualUrl},
@@ -313,7 +309,7 @@ struct GitInputScheme : InputScheme
} else {
- if (auto res = getCache()->lookup(store, mutableAttrs)) {
+ if (auto res = getCache()->lookup(store, unlockedAttrs)) {
auto rev2 = Hash::parseAny(getStrAttr(res->first, "rev"), htSHA1);
if (!input.getRev() || input.getRev() == rev2) {
input.attrs.insert_or_assign("rev", rev2.gitRev());
@@ -324,17 +320,13 @@ struct GitInputScheme : InputScheme
Path cacheDir = getCacheDir() + "/nix/gitv3/" + hashString(htSHA256, actualUrl).to_string(Base32, false);
repoDir = cacheDir;
- Path cacheDirLock = cacheDir + ".lock";
createDirs(dirOf(cacheDir));
- AutoCloseFD lock = openLockFile(cacheDirLock, true);
- lockFile(lock.get(), ltWrite, true);
+ PathLocks cacheDirLock({cacheDir + ".lock"});
if (!pathExists(cacheDir)) {
runProgram("git", true, { "-c", "init.defaultBranch=" + gitInitialBranch, "init", "--bare", repoDir });
}
- deleteLockFile(cacheDirLock, lock.get());
-
Path localRefFile =
input.getRef()->compare(0, 5, "refs/") == 0
? cacheDir + "/" + *input.getRef()
@@ -399,6 +391,8 @@ struct GitInputScheme : InputScheme
if (!input.getRev())
input.attrs.insert_or_assign("rev", Hash::parseAny(chomp(readFile(localRefFile)), htSHA1).gitRev());
+
+ // cache dir lock is removed at scope end; we will only use read-only operations on specific revisions in the remainder
}
bool isShallow = chomp(runProgram("git", true, { "-C", repoDir, "rev-parse", "--is-shallow-repository" })) == "true";
@@ -412,7 +406,7 @@ struct GitInputScheme : InputScheme
/* Now that we know the ref, check again whether we have it in
the store. */
- if (auto res = getCache()->lookup(store, getImmutableAttrs()))
+ if (auto res = getCache()->lookup(store, getLockedAttrs()))
return makeResult(res->first, std::move(res->second));
Path tmpDir = createTempDir();
@@ -484,14 +478,14 @@ struct GitInputScheme : InputScheme
if (!_input.getRev())
getCache()->add(
store,
- mutableAttrs,
+ unlockedAttrs,
infoAttrs,
storePath,
false);
getCache()->add(
store,
- getImmutableAttrs(),
+ getLockedAttrs(),
infoAttrs,
storePath,
true);
diff --git a/src/libfetchers/github.cc b/src/libfetchers/github.cc
index ffc44e9e2..a1430f087 100644
--- a/src/libfetchers/github.cc
+++ b/src/libfetchers/github.cc
@@ -1,13 +1,16 @@
#include "filetransfer.hh"
#include "cache.hh"
-#include "fetchers.hh"
#include "globals.hh"
#include "store-api.hh"
#include "types.hh"
#include "url-parts.hh"
+#include "fetchers.hh"
+#include "fetch-settings.hh"
+
#include <optional>
#include <nlohmann/json.hpp>
+#include <fstream>
namespace nix::fetchers {
@@ -17,7 +20,7 @@ struct DownloadUrl
Headers headers;
};
-// A github or gitlab host
+// A github, gitlab, or sourcehut host
const static std::string hostRegexS = "[a-zA-Z0-9.]*"; // FIXME: check
std::regex hostRegex(hostRegexS, std::regex::ECMAScript);
@@ -156,7 +159,7 @@ struct GitArchiveInputScheme : InputScheme
std::optional<std::string> getAccessToken(const std::string & host) const
{
- auto tokens = settings.accessTokens.get();
+ auto tokens = fetchSettings.accessTokens.get();
if (auto token = get(tokens, host))
return *token;
return {};
@@ -180,7 +183,7 @@ struct GitArchiveInputScheme : InputScheme
virtual DownloadUrl getDownloadUrl(const Input & input) const = 0;
- std::pair<Tree, Input> fetch(ref<Store> store, const Input & _input) override
+ std::pair<StorePath, Input> fetch(ref<Store> store, const Input & _input) override
{
Input input(_input);
@@ -192,17 +195,14 @@ struct GitArchiveInputScheme : InputScheme
input.attrs.erase("ref");
input.attrs.insert_or_assign("rev", rev->gitRev());
- Attrs immutableAttrs({
+ Attrs lockedAttrs({
{"type", "git-tarball"},
{"rev", rev->gitRev()},
});
- if (auto res = getCache()->lookup(store, immutableAttrs)) {
+ if (auto res = getCache()->lookup(store, lockedAttrs)) {
input.attrs.insert_or_assign("lastModified", getIntAttr(res->first, "lastModified"));
- return {
- Tree(store->toRealPath(res->second), std::move(res->second)),
- input
- };
+ return {std::move(res->second), input};
}
auto url = getDownloadUrl(input);
@@ -213,7 +213,7 @@ struct GitArchiveInputScheme : InputScheme
getCache()->add(
store,
- immutableAttrs,
+ lockedAttrs,
{
{"rev", rev->gitRev()},
{"lastModified", uint64_t(lastModified)}
@@ -221,7 +221,7 @@ struct GitArchiveInputScheme : InputScheme
tree.storePath,
true);
- return {std::move(tree), input};
+ return {std::move(tree.storePath), input};
}
};
@@ -300,7 +300,7 @@ struct GitLabInputScheme : GitArchiveInputScheme
if ("PAT" == token.substr(0, fldsplit))
return std::make_pair("Private-token", token.substr(fldsplit+1));
warn("Unrecognized GitLab token type %s", token.substr(0, fldsplit));
- return std::nullopt;
+ return std::make_pair(token.substr(0,fldsplit), token.substr(fldsplit+1));
}
Hash getRevFromRef(nix::ref<Store> store, const Input & input) const override
@@ -348,7 +348,95 @@ struct GitLabInputScheme : GitArchiveInputScheme
}
};
+struct SourceHutInputScheme : GitArchiveInputScheme
+{
+ std::string type() override { return "sourcehut"; }
+
+ std::optional<std::pair<std::string, std::string>> accessHeaderFromToken(const std::string & token) const override
+ {
+ // SourceHut supports both PAT and OAuth2. See
+ // https://man.sr.ht/meta.sr.ht/oauth.md
+ return std::pair<std::string, std::string>("Authorization", fmt("Bearer %s", token));
+ // Note: This currently serves no purpose, as this kind of authorization
+ // does not allow for downloading tarballs on sourcehut private repos.
+ // Once it is implemented, however, should work as expected.
+ }
+
+ Hash getRevFromRef(nix::ref<Store> store, const Input & input) const override
+ {
+ // TODO: In the future, when the sourcehut graphql API is implemented for mercurial
+ // and with anonymous access, this method should use it instead.
+
+ auto ref = *input.getRef();
+
+ auto host = maybeGetStrAttr(input.attrs, "host").value_or("git.sr.ht");
+ auto base_url = fmt("https://%s/%s/%s",
+ host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo"));
+
+ Headers headers = makeHeadersWithAuthTokens(host);
+
+ std::string ref_uri;
+ if (ref == "HEAD") {
+ auto file = store->toRealPath(
+ downloadFile(store, fmt("%s/HEAD", base_url), "source", false, headers).storePath);
+ std::ifstream is(file);
+ std::string line;
+ getline(is, line);
+
+ auto ref_index = line.find("ref: ");
+ if (ref_index == std::string::npos) {
+ throw BadURL("in '%d', couldn't resolve HEAD ref '%d'", input.to_string(), ref);
+ }
+
+ ref_uri = line.substr(ref_index+5, line.length()-1);
+ } else
+ ref_uri = fmt("refs/heads/%s", ref);
+
+ auto file = store->toRealPath(
+ downloadFile(store, fmt("%s/info/refs", base_url), "source", false, headers).storePath);
+ std::ifstream is(file);
+
+ std::string line;
+ std::string id;
+ while(getline(is, line)) {
+ auto index = line.find(ref_uri);
+ if (index != std::string::npos) {
+ id = line.substr(0, index-1);
+ break;
+ }
+ }
+
+ if(id.empty())
+ throw BadURL("in '%d', couldn't find ref '%d'", input.to_string(), ref);
+
+ auto rev = Hash::parseAny(id, htSHA1);
+ debug("HEAD revision for '%s' is %s", fmt("%s/%s", base_url, ref), rev.gitRev());
+ return rev;
+ }
+
+ DownloadUrl getDownloadUrl(const Input & input) const override
+ {
+ auto host = maybeGetStrAttr(input.attrs, "host").value_or("git.sr.ht");
+ auto url = fmt("https://%s/%s/%s/archive/%s.tar.gz",
+ host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo"),
+ input.getRev()->to_string(Base16, false));
+
+ Headers headers = makeHeadersWithAuthTokens(host);
+ return DownloadUrl { url, headers };
+ }
+
+ void clone(const Input & input, const Path & destDir) override
+ {
+ auto host = maybeGetStrAttr(input.attrs, "host").value_or("git.sr.ht");
+ Input::fromURL(fmt("git+https://%s/%s/%s",
+ host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo")))
+ .applyOverrides(input.getRef(), input.getRev())
+ .clone(destDir);
+ }
+};
+
static auto rGitHubInputScheme = OnStartup([] { registerInputScheme(std::make_unique<GitHubInputScheme>()); });
static auto rGitLabInputScheme = OnStartup([] { registerInputScheme(std::make_unique<GitLabInputScheme>()); });
+static auto rSourceHutInputScheme = OnStartup([] { registerInputScheme(std::make_unique<SourceHutInputScheme>()); });
}
diff --git a/src/libfetchers/indirect.cc b/src/libfetchers/indirect.cc
index 10e59919a..9288fc6cf 100644
--- a/src/libfetchers/indirect.cc
+++ b/src/libfetchers/indirect.cc
@@ -94,7 +94,7 @@ struct IndirectInputScheme : InputScheme
return input;
}
- std::pair<Tree, Input> fetch(ref<Store> store, const Input & input) override
+ std::pair<StorePath, Input> fetch(ref<Store> store, const Input & input) override
{
throw Error("indirect input '%s' cannot be fetched directly", input.to_string());
}
diff --git a/src/libfetchers/mercurial.cc b/src/libfetchers/mercurial.cc
index d52d4641b..8b82e9daa 100644
--- a/src/libfetchers/mercurial.cc
+++ b/src/libfetchers/mercurial.cc
@@ -5,6 +5,8 @@
#include "store-api.hh"
#include "url-parts.hh"
+#include "fetch-settings.hh"
+
#include <sys/time.h>
using namespace std::string_literals;
@@ -26,7 +28,7 @@ static RunOptions hgOptions(const Strings & args)
}
// runProgram wrapper that uses hgOptions instead of stock RunOptions.
-static string runHg(const Strings & args, const std::optional<std::string> & input = {})
+static std::string runHg(const Strings & args, const std::optional<std::string> & input = {})
{
RunOptions opts = hgOptions(args);
opts.input = input;
@@ -143,7 +145,7 @@ struct MercurialInputScheme : InputScheme
return {isLocal, isLocal ? url.path : url.base};
}
- std::pair<Tree, Input> fetch(ref<Store> store, const Input & _input) override
+ std::pair<StorePath, Input> fetch(ref<Store> store, const Input & _input) override
{
Input input(_input);
@@ -165,10 +167,10 @@ struct MercurialInputScheme : InputScheme
/* This is an unclean working tree. So copy all tracked
files. */
- if (!settings.allowDirty)
+ if (!fetchSettings.allowDirty)
throw Error("Mercurial tree '%s' is unclean", actualUrl);
- if (settings.warnDirty)
+ if (fetchSettings.warnDirty)
warn("Mercurial tree '%s' is unclean", actualUrl);
input.attrs.insert_or_assign("ref", chomp(runHg({ "branch", "-R", actualUrl })));
@@ -193,16 +195,13 @@ struct MercurialInputScheme : InputScheme
auto storePath = store->addToStore(input.getName(), actualUrl, FileIngestionMethod::Recursive, htSHA256, filter);
- return {
- Tree(store->toRealPath(storePath), std::move(storePath)),
- input
- };
+ return {std::move(storePath), input};
}
}
if (!input.getRef()) input.attrs.insert_or_assign("ref", "default");
- auto getImmutableAttrs = [&]()
+ auto getLockedAttrs = [&]()
{
return Attrs({
{"type", "hg"},
@@ -212,32 +211,29 @@ struct MercurialInputScheme : InputScheme
};
auto makeResult = [&](const Attrs & infoAttrs, StorePath && storePath)
- -> std::pair<Tree, Input>
+ -> std::pair<StorePath, Input>
{
assert(input.getRev());
assert(!_input.getRev() || _input.getRev() == input.getRev());
input.attrs.insert_or_assign("revCount", getIntAttr(infoAttrs, "revCount"));
- return {
- Tree(store->toRealPath(storePath), std::move(storePath)),
- input
- };
+ return {std::move(storePath), input};
};
if (input.getRev()) {
- if (auto res = getCache()->lookup(store, getImmutableAttrs()))
+ if (auto res = getCache()->lookup(store, getLockedAttrs()))
return makeResult(res->first, std::move(res->second));
}
auto revOrRef = input.getRev() ? input.getRev()->gitRev() : *input.getRef();
- Attrs mutableAttrs({
+ Attrs unlockedAttrs({
{"type", "hg"},
{"name", name},
{"url", actualUrl},
{"ref", *input.getRef()},
});
- if (auto res = getCache()->lookup(store, mutableAttrs)) {
+ if (auto res = getCache()->lookup(store, unlockedAttrs)) {
auto rev2 = Hash::parseAny(getStrAttr(res->first, "rev"), htSHA1);
if (!input.getRev() || input.getRev() == rev2) {
input.attrs.insert_or_assign("rev", rev2.gitRev());
@@ -260,7 +256,7 @@ struct MercurialInputScheme : InputScheme
runHg({ "pull", "-R", cacheDir, "--", actualUrl });
}
catch (ExecError & e) {
- string transJournal = cacheDir + "/.hg/store/journal";
+ auto transJournal = cacheDir + "/.hg/store/journal";
/* hg throws "abandoned transaction" error only if this file exists */
if (pathExists(transJournal)) {
runHg({ "recover", "-R", cacheDir });
@@ -283,7 +279,7 @@ struct MercurialInputScheme : InputScheme
auto revCount = std::stoull(tokens[1]);
input.attrs.insert_or_assign("ref", tokens[2]);
- if (auto res = getCache()->lookup(store, getImmutableAttrs()))
+ if (auto res = getCache()->lookup(store, getLockedAttrs()))
return makeResult(res->first, std::move(res->second));
Path tmpDir = createTempDir();
@@ -303,14 +299,14 @@ struct MercurialInputScheme : InputScheme
if (!_input.getRev())
getCache()->add(
store,
- mutableAttrs,
+ unlockedAttrs,
infoAttrs,
storePath,
false);
getCache()->add(
store,
- getImmutableAttrs(),
+ getLockedAttrs(),
infoAttrs,
storePath,
true);
diff --git a/src/libfetchers/path.cc b/src/libfetchers/path.cc
index fb5702c4c..59e228e97 100644
--- a/src/libfetchers/path.cc
+++ b/src/libfetchers/path.cc
@@ -80,7 +80,7 @@ struct PathInputScheme : InputScheme
// nothing to do
}
- std::pair<Tree, Input> fetch(ref<Store> store, const Input & input) override
+ std::pair<StorePath, Input> fetch(ref<Store> store, const Input & input) override
{
std::string absPath;
auto path = getStrAttr(input.attrs, "path");
@@ -97,7 +97,7 @@ struct PathInputScheme : InputScheme
// for security, ensure that if the parent is a store path, it's inside it
if (store->isInStore(parent)) {
auto storePath = store->printStorePath(store->toStorePath(parent).first);
- if (!isInDir(absPath, storePath))
+ if (!isDirOrInDir(absPath, storePath))
throw BadStorePath("relative path '%s' points outside of its parent's store path '%s'", path, storePath);
}
} else
@@ -115,10 +115,7 @@ struct PathInputScheme : InputScheme
// FIXME: try to substitute storePath.
storePath = store->addToStore("source", absPath);
- return {
- Tree(store->toRealPath(*storePath), std::move(*storePath)),
- input
- };
+ return {std::move(*storePath), input};
}
};
diff --git a/src/libfetchers/registry.cc b/src/libfetchers/registry.cc
index f35359d4b..acd1ff866 100644
--- a/src/libfetchers/registry.cc
+++ b/src/libfetchers/registry.cc
@@ -5,6 +5,8 @@
#include "store-api.hh"
#include "local-fs-store.hh"
+#include "fetch-settings.hh"
+
#include <nlohmann/json.hpp>
namespace nix::fetchers {
@@ -150,7 +152,7 @@ void overrideRegistry(
static std::shared_ptr<Registry> getGlobalRegistry(ref<Store> store)
{
static auto reg = [&]() {
- auto path = settings.flakeRegistry.get();
+ auto path = fetchSettings.flakeRegistry.get();
if (!hasPrefix(path, "/")) {
auto storePath = downloadFile(store, path, "flake-registry.json", false).storePath;
diff --git a/src/libfetchers/tarball.cc b/src/libfetchers/tarball.cc
index efd34932c..4be923148 100644
--- a/src/libfetchers/tarball.cc
+++ b/src/libfetchers/tarball.cc
@@ -13,7 +13,7 @@ DownloadFileResult downloadFile(
ref<Store> store,
const std::string & url,
const std::string & name,
- bool immutable,
+ bool locked,
const Headers & headers)
{
// FIXME: check store
@@ -67,8 +67,8 @@ DownloadFileResult downloadFile(
storePath = std::move(cached->storePath);
} else {
StringSink sink;
- dumpString(*res.data, sink);
- auto hash = hashString(htSHA256, *res.data);
+ dumpString(res.data, sink);
+ auto hash = hashString(htSHA256, res.data);
ValidPathInfo info {
*store,
{
@@ -81,10 +81,10 @@ DownloadFileResult downloadFile(
{},
},
},
- hashString(htSHA256, *sink.s),
+ hashString(htSHA256, sink.s),
};
- info.narSize = sink.s->size();
- auto source = StringSource { *sink.s };
+ info.narSize = sink.s.size();
+ auto source = StringSource { sink.s };
store->addToStore(info, source, NoRepair, NoCheckSigs);
storePath = std::move(info.path);
}
@@ -94,7 +94,7 @@ DownloadFileResult downloadFile(
inAttrs,
infoAttrs,
*storePath,
- immutable);
+ locked);
if (url != res.effectiveUri)
getCache()->add(
@@ -106,7 +106,7 @@ DownloadFileResult downloadFile(
},
infoAttrs,
*storePath,
- immutable);
+ locked);
return {
.storePath = std::move(*storePath),
@@ -119,7 +119,7 @@ std::pair<Tree, time_t> downloadTarball(
ref<Store> store,
const std::string & url,
const std::string & name,
- bool immutable,
+ bool locked,
const Headers & headers)
{
Attrs inAttrs({
@@ -132,11 +132,11 @@ std::pair<Tree, time_t> downloadTarball(
if (cached && !cached->expired)
return {
- Tree(store->toRealPath(cached->storePath), std::move(cached->storePath)),
+ Tree { .actualPath = store->toRealPath(cached->storePath), .storePath = std::move(cached->storePath) },
getIntAttr(cached->infoAttrs, "lastModified")
};
- auto res = downloadFile(store, url, name, immutable, headers);
+ auto res = downloadFile(store, url, name, locked, headers);
std::optional<StorePath> unpackedStorePath;
time_t lastModified;
@@ -166,10 +166,10 @@ std::pair<Tree, time_t> downloadTarball(
inAttrs,
infoAttrs,
*unpackedStorePath,
- immutable);
+ locked);
return {
- Tree(store->toRealPath(*unpackedStorePath), std::move(*unpackedStorePath)),
+ Tree { .actualPath = store->toRealPath(*unpackedStorePath), .storePath = std::move(*unpackedStorePath) },
lastModified,
};
}
@@ -182,6 +182,7 @@ struct TarballInputScheme : InputScheme
if (!hasSuffix(url.path, ".zip")
&& !hasSuffix(url.path, ".tar")
+ && !hasSuffix(url.path, ".tgz")
&& !hasSuffix(url.path, ".tar.gz")
&& !hasSuffix(url.path, ".tar.xz")
&& !hasSuffix(url.path, ".tar.bz2")
@@ -207,7 +208,7 @@ struct TarballInputScheme : InputScheme
Input input;
input.attrs = attrs;
- //input.immutable = (bool) maybeGetStrAttr(input.attrs, "hash");
+ //input.locked = (bool) maybeGetStrAttr(input.attrs, "hash");
return input;
}
@@ -230,10 +231,10 @@ struct TarballInputScheme : InputScheme
return true;
}
- std::pair<Tree, Input> fetch(ref<Store> store, const Input & input) override
+ std::pair<StorePath, Input> fetch(ref<Store> store, const Input & input) override
{
auto tree = downloadTarball(store, getStrAttr(input.attrs, "url"), input.getName(), false).first;
- return {std::move(tree), input};
+ return {std::move(tree.storePath), input};
}
};