mirror of
https://github.com/NixOS/nix
synced 2025-06-24 09:41:15 +02:00
Stores no longer inherit from their configs
Fix #10766 See that ticket for details. Progress (I hope!) towards #11139. Co-Authored-By: Sergei Zimmerman <xokdvium@proton.me>
This commit is contained in:
parent
f0f196cef0
commit
934918ba16
48 changed files with 743 additions and 593 deletions
|
@ -33,6 +33,7 @@ let
|
|||
{
|
||||
settings,
|
||||
doc,
|
||||
uri-schemes,
|
||||
experimentalFeature,
|
||||
}:
|
||||
let
|
||||
|
|
|
@ -44,7 +44,7 @@ static AutoCloseFD openSlotLock(const Machine & m, uint64_t slot)
|
|||
|
||||
static bool allSupportedLocally(Store & store, const StringSet& requiredFeatures) {
|
||||
for (auto & feature : requiredFeatures)
|
||||
if (!store.systemFeatures.get().count(feature)) return false;
|
||||
if (!store.config.systemFeatures.get().count(feature)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -85,7 +85,7 @@ static int main_build_remote(int argc, char * * argv)
|
|||
that gets cleared on reboot, but it wouldn't work on macOS. */
|
||||
auto currentLoadName = "/current-load";
|
||||
if (auto localStore = store.dynamic_pointer_cast<LocalFSStore>())
|
||||
currentLoad = std::string { localStore->stateDir } + currentLoadName;
|
||||
currentLoad = std::string { localStore->config.stateDir } + currentLoadName;
|
||||
else
|
||||
currentLoad = settings.nixStateDir + currentLoadName;
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ extern char ** savedArgv;
|
|||
class EvalState;
|
||||
struct Pos;
|
||||
class Store;
|
||||
class LocalFSStore;
|
||||
struct LocalFSStore;
|
||||
|
||||
static constexpr Command::Category catHelp = -1;
|
||||
static constexpr Command::Category catSecondary = 100;
|
||||
|
|
|
@ -42,7 +42,7 @@ Store * nix_store_open(nix_c_context * context, const char * uri, const char ***
|
|||
if (!params)
|
||||
return new Store{nix::openStore(uri_str)};
|
||||
|
||||
nix::Store::Params params_map;
|
||||
nix::Store::Config::Params params_map;
|
||||
for (size_t i = 0; params[i] != nullptr; i++) {
|
||||
params_map[params[i][0]] = params[i][1];
|
||||
}
|
||||
|
|
|
@ -24,16 +24,15 @@
|
|||
|
||||
namespace nix {
|
||||
|
||||
BinaryCacheStore::BinaryCacheStore(const Params & params)
|
||||
: BinaryCacheStoreConfig(params)
|
||||
, Store(params)
|
||||
BinaryCacheStore::BinaryCacheStore(Config & config)
|
||||
: config{config}
|
||||
{
|
||||
if (secretKeyFile != "")
|
||||
if (config.secretKeyFile != "")
|
||||
signers.push_back(std::make_unique<LocalSigner>(
|
||||
SecretKey { readFile(secretKeyFile) }));
|
||||
SecretKey { readFile(config.secretKeyFile) }));
|
||||
|
||||
if (secretKeyFiles != "") {
|
||||
std::stringstream ss(secretKeyFiles);
|
||||
if (config.secretKeyFiles != "") {
|
||||
std::stringstream ss(config.secretKeyFiles);
|
||||
Path keyPath;
|
||||
while (std::getline(ss, keyPath, ',')) {
|
||||
signers.push_back(std::make_unique<LocalSigner>(
|
||||
|
@ -62,9 +61,9 @@ void BinaryCacheStore::init()
|
|||
throw Error("binary cache '%s' is for Nix stores with prefix '%s', not '%s'",
|
||||
getUri(), value, storeDir);
|
||||
} else if (name == "WantMassQuery") {
|
||||
wantMassQuery.setDefault(value == "1");
|
||||
config.wantMassQuery.setDefault(value == "1");
|
||||
} else if (name == "Priority") {
|
||||
priority.setDefault(std::stoi(value));
|
||||
config.priority.setDefault(std::stoi(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -156,7 +155,11 @@ ref<const ValidPathInfo> BinaryCacheStore::addToStoreCommon(
|
|||
{
|
||||
FdSink fileSink(fdTemp.get());
|
||||
TeeSink teeSinkCompressed { fileSink, fileHashSink };
|
||||
auto compressionSink = makeCompressionSink(compression, teeSinkCompressed, parallelCompression, compressionLevel);
|
||||
auto compressionSink = makeCompressionSink(
|
||||
config.compression,
|
||||
teeSinkCompressed,
|
||||
config.parallelCompression,
|
||||
config.compressionLevel);
|
||||
TeeSink teeSinkUncompressed { *compressionSink, narHashSink };
|
||||
TeeSource teeSource { narSource, teeSinkUncompressed };
|
||||
narAccessor = makeNarAccessor(teeSource);
|
||||
|
@ -168,17 +171,17 @@ ref<const ValidPathInfo> BinaryCacheStore::addToStoreCommon(
|
|||
|
||||
auto info = mkInfo(narHashSink.finish());
|
||||
auto narInfo = make_ref<NarInfo>(info);
|
||||
narInfo->compression = compression;
|
||||
narInfo->compression = config.compression;
|
||||
auto [fileHash, fileSize] = fileHashSink.finish();
|
||||
narInfo->fileHash = fileHash;
|
||||
narInfo->fileSize = fileSize;
|
||||
narInfo->url = "nar/" + narInfo->fileHash->to_string(HashFormat::Nix32, false) + ".nar"
|
||||
+ (compression == "xz" ? ".xz" :
|
||||
compression == "bzip2" ? ".bz2" :
|
||||
compression == "zstd" ? ".zst" :
|
||||
compression == "lzip" ? ".lzip" :
|
||||
compression == "lz4" ? ".lz4" :
|
||||
compression == "br" ? ".br" :
|
||||
+ (config.compression == "xz" ? ".xz" :
|
||||
config.compression == "bzip2" ? ".bz2" :
|
||||
config.compression == "zstd" ? ".zst" :
|
||||
config.compression == "lzip" ? ".lzip" :
|
||||
config.compression == "lz4" ? ".lz4" :
|
||||
config.compression == "br" ? ".br" :
|
||||
"");
|
||||
|
||||
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(now2 - now1).count();
|
||||
|
@ -200,7 +203,7 @@ ref<const ValidPathInfo> BinaryCacheStore::addToStoreCommon(
|
|||
|
||||
/* Optionally write a JSON file containing a listing of the
|
||||
contents of the NAR. */
|
||||
if (writeNARListing) {
|
||||
if (config.writeNARListing) {
|
||||
nlohmann::json j = {
|
||||
{"version", 1},
|
||||
{"root", listNar(ref<SourceAccessor>(narAccessor), CanonPath::root, true)},
|
||||
|
@ -212,7 +215,7 @@ ref<const ValidPathInfo> BinaryCacheStore::addToStoreCommon(
|
|||
/* Optionally maintain an index of DWARF debug info files
|
||||
consisting of JSON files named 'debuginfo/<build-id>' that
|
||||
specify the NAR file and member containing the debug info. */
|
||||
if (writeDebugInfo) {
|
||||
if (config.writeDebugInfo) {
|
||||
|
||||
CanonPath buildIdDir("lib/debug/.build-id");
|
||||
|
||||
|
@ -524,7 +527,7 @@ void BinaryCacheStore::registerDrvOutput(const Realisation& info) {
|
|||
|
||||
ref<SourceAccessor> BinaryCacheStore::getFSAccessor(bool requireValidPath)
|
||||
{
|
||||
return make_ref<RemoteFSAccessor>(ref<Store>(shared_from_this()), requireValidPath, localNarCache);
|
||||
return make_ref<RemoteFSAccessor>(ref<Store>(shared_from_this()), requireValidPath, config.localNarCache);
|
||||
}
|
||||
|
||||
void BinaryCacheStore::addSignatures(const StorePath & storePath, const StringSet & sigs)
|
||||
|
|
|
@ -1284,7 +1284,7 @@ Path DerivationGoal::openLogFile()
|
|||
/* Create a log file. */
|
||||
Path logDir;
|
||||
if (auto localStore = dynamic_cast<LocalStore *>(&worker.store))
|
||||
logDir = localStore->logDir;
|
||||
logDir = localStore->config->logDir;
|
||||
else
|
||||
logDir = settings.nixLogDir;
|
||||
Path dir = fmt("%s/%s/%s/", logDir, LocalFSStore::drvsLogDir, baseName.substr(0, 2));
|
||||
|
|
|
@ -121,7 +121,7 @@ Goal::Co PathSubstitutionGoal::init()
|
|||
/* Bail out early if this substituter lacks a valid
|
||||
signature. LocalStore::addToStore() also checks for this, but
|
||||
only after we've downloaded the path. */
|
||||
if (!sub->isTrusted && worker.store.pathInfoIsUntrusted(*info))
|
||||
if (!sub->config.isTrusted && worker.store.pathInfoIsUntrusted(*info))
|
||||
{
|
||||
warn("ignoring substitute for '%s' from '%s', as it's not signed by any of the keys in 'trusted-public-keys'",
|
||||
worker.store.printStorePath(storePath), sub->getUri());
|
||||
|
@ -215,7 +215,7 @@ Goal::Co PathSubstitutionGoal::tryToRun(StorePath subPath, nix::ref<Store> sub,
|
|||
PushActivity pact(act.id);
|
||||
|
||||
copyStorePath(*sub, worker.store,
|
||||
subPath, repair, sub->isTrusted ? NoCheckSigs : CheckSigs);
|
||||
subPath, repair, sub->config.isTrusted ? NoCheckSigs : CheckSigs);
|
||||
|
||||
promise.set_value();
|
||||
} catch (...) {
|
||||
|
|
|
@ -28,7 +28,7 @@ CommonSSHStoreConfig::CommonSSHStoreConfig(std::string_view scheme, std::string_
|
|||
{
|
||||
}
|
||||
|
||||
SSHMaster CommonSSHStoreConfig::createSSHMaster(bool useMaster, Descriptor logFD)
|
||||
SSHMaster CommonSSHStoreConfig::createSSHMaster(bool useMaster, Descriptor logFD) const
|
||||
{
|
||||
return {
|
||||
host,
|
||||
|
|
|
@ -265,7 +265,7 @@ bool DerivationOptions::canBuildLocally(Store & localStore, const BasicDerivatio
|
|||
return false;
|
||||
|
||||
for (auto & feature : getRequiredSystemFeatures(drv))
|
||||
if (!localStore.systemFeatures.get().count(feature))
|
||||
if (!localStore.config.systemFeatures.get().count(feature))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
namespace nix {
|
||||
|
||||
struct DummyStoreConfig : virtual StoreConfig {
|
||||
struct DummyStoreConfig : public std::enable_shared_from_this<DummyStoreConfig>, virtual StoreConfig {
|
||||
using StoreConfig::StoreConfig;
|
||||
|
||||
DummyStoreConfig(std::string_view scheme, std::string_view authority, const Params & params)
|
||||
|
@ -13,9 +13,9 @@ struct DummyStoreConfig : virtual StoreConfig {
|
|||
throw UsageError("`%s` store URIs must not contain an authority part %s", scheme, authority);
|
||||
}
|
||||
|
||||
const std::string name() override { return "Dummy Store"; }
|
||||
static const std::string name() { return "Dummy Store"; }
|
||||
|
||||
std::string doc() override
|
||||
static std::string doc()
|
||||
{
|
||||
return
|
||||
#include "dummy-store.md"
|
||||
|
@ -25,23 +25,24 @@ struct DummyStoreConfig : virtual StoreConfig {
|
|||
static StringSet uriSchemes() {
|
||||
return {"dummy"};
|
||||
}
|
||||
|
||||
ref<Store> openStore() const override;
|
||||
};
|
||||
|
||||
struct DummyStore : public virtual DummyStoreConfig, public virtual Store
|
||||
struct DummyStore : virtual Store
|
||||
{
|
||||
DummyStore(std::string_view scheme, std::string_view authority, const Params & params)
|
||||
: StoreConfig(params)
|
||||
, DummyStoreConfig(scheme, authority, params)
|
||||
, Store(params)
|
||||
{ }
|
||||
using Config = DummyStoreConfig;
|
||||
|
||||
DummyStore(const Params & params)
|
||||
: DummyStore("dummy", "", params)
|
||||
ref<const Config> config;
|
||||
|
||||
DummyStore(ref<const Config> config)
|
||||
: Store{*config}
|
||||
, config(config)
|
||||
{ }
|
||||
|
||||
std::string getUri() override
|
||||
{
|
||||
return *uriSchemes().begin();
|
||||
return *Config::uriSchemes().begin();
|
||||
}
|
||||
|
||||
void queryPathInfoUncached(const StorePath & path,
|
||||
|
@ -88,6 +89,11 @@ struct DummyStore : public virtual DummyStoreConfig, public virtual Store
|
|||
}
|
||||
};
|
||||
|
||||
static RegisterStoreImplementation<DummyStore, DummyStoreConfig> regDummyStore;
|
||||
ref<Store> DummyStore::Config::openStore() const
|
||||
{
|
||||
return make_ref<DummyStore>(ref{shared_from_this()});
|
||||
}
|
||||
|
||||
static RegisterStoreImplementation<DummyStore::Config> regDummyStore;
|
||||
|
||||
}
|
||||
|
|
|
@ -771,7 +771,7 @@ struct curlFileTransfer : public FileTransfer
|
|||
}
|
||||
|
||||
#if NIX_WITH_S3_SUPPORT
|
||||
std::tuple<std::string, std::string, Store::Params> parseS3Uri(std::string uri)
|
||||
std::tuple<std::string, std::string, Store::Config::Params> parseS3Uri(std::string uri)
|
||||
{
|
||||
auto [path, params] = splitUriAndParams(uri);
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ static std::string gcRootsDir = "gcroots";
|
|||
void LocalStore::addIndirectRoot(const Path & path)
|
||||
{
|
||||
std::string hash = hashString(HashAlgorithm::SHA1, path).to_string(HashFormat::Nix32, false);
|
||||
Path realRoot = canonPath(fmt("%1%/%2%/auto/%3%", stateDir, gcRootsDir, hash));
|
||||
Path realRoot = canonPath(fmt("%1%/%2%/auto/%3%", config->stateDir, gcRootsDir, hash));
|
||||
makeSymlink(realRoot, path);
|
||||
}
|
||||
|
||||
|
@ -82,7 +82,7 @@ void LocalStore::createTempRootsFile()
|
|||
|
||||
void LocalStore::addTempRoot(const StorePath & path)
|
||||
{
|
||||
if (readOnly) {
|
||||
if (config->readOnly) {
|
||||
debug("Read-only store doesn't support creating lock files for temp roots, but nothing can be deleted anyways.");
|
||||
return;
|
||||
}
|
||||
|
@ -109,7 +109,7 @@ void LocalStore::addTempRoot(const StorePath & path)
|
|||
auto fdRootsSocket(_fdRootsSocket.lock());
|
||||
|
||||
if (!*fdRootsSocket) {
|
||||
auto socketPath = stateDir.get() + gcSocketPath;
|
||||
auto socketPath = config->stateDir.get() + gcSocketPath;
|
||||
debug("connecting to '%s'", socketPath);
|
||||
*fdRootsSocket = createUnixDomainSocket();
|
||||
try {
|
||||
|
@ -247,7 +247,7 @@ void LocalStore::findRoots(const Path & path, std::filesystem::file_type type, R
|
|||
else {
|
||||
target = absPath(target, dirOf(path));
|
||||
if (!pathExists(target)) {
|
||||
if (isInDir(path, std::filesystem::path{stateDir.get()} / gcRootsDir / "auto")) {
|
||||
if (isInDir(path, std::filesystem::path{config->stateDir.get()} / gcRootsDir / "auto")) {
|
||||
printInfo("removing stale link from '%1%' to '%2%'", path, target);
|
||||
unlink(path.c_str());
|
||||
}
|
||||
|
@ -288,8 +288,8 @@ void LocalStore::findRoots(const Path & path, std::filesystem::file_type type, R
|
|||
void LocalStore::findRootsNoTemp(Roots & roots, bool censor)
|
||||
{
|
||||
/* Process direct roots in {gcroots,profiles}. */
|
||||
findRoots(stateDir + "/" + gcRootsDir, std::filesystem::file_type::unknown, roots);
|
||||
findRoots(stateDir + "/profiles", std::filesystem::file_type::unknown, roots);
|
||||
findRoots(config->stateDir + "/" + gcRootsDir, std::filesystem::file_type::unknown, roots);
|
||||
findRoots(config->stateDir + "/profiles", std::filesystem::file_type::unknown, roots);
|
||||
|
||||
/* Add additional roots returned by different platforms-specific
|
||||
heuristics. This is typically used to add running programs to
|
||||
|
@ -498,7 +498,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
|
|||
readFile(*p);
|
||||
|
||||
/* Start the server for receiving new roots. */
|
||||
auto socketPath = stateDir.get() + gcSocketPath;
|
||||
auto socketPath = config->stateDir.get() + gcSocketPath;
|
||||
createDirs(dirOf(socketPath));
|
||||
auto fdServer = createUnixDomainSocket(socketPath, 0666);
|
||||
|
||||
|
@ -635,7 +635,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
|
|||
auto deleteFromStore = [&](std::string_view baseName)
|
||||
{
|
||||
Path path = storeDir + "/" + std::string(baseName);
|
||||
Path realPath = realStoreDir + "/" + std::string(baseName);
|
||||
Path realPath = config->realStoreDir + "/" + std::string(baseName);
|
||||
|
||||
/* There may be temp directories in the store that are still in use
|
||||
by another process. We need to be sure that we can acquire an
|
||||
|
@ -804,8 +804,8 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
|
|||
printInfo("determining live/dead paths...");
|
||||
|
||||
try {
|
||||
AutoCloseDir dir(opendir(realStoreDir.get().c_str()));
|
||||
if (!dir) throw SysError("opening directory '%1%'", realStoreDir);
|
||||
AutoCloseDir dir(opendir(config->realStoreDir.get().c_str()));
|
||||
if (!dir) throw SysError("opening directory '%1%'", config->realStoreDir);
|
||||
|
||||
/* Read the store and delete all paths that are invalid or
|
||||
unreachable. We don't use readDirectory() here so that
|
||||
|
@ -907,8 +907,8 @@ void LocalStore::autoGC(bool sync)
|
|||
return std::stoll(readFile(*fakeFreeSpaceFile));
|
||||
|
||||
struct statvfs st;
|
||||
if (statvfs(realStoreDir.get().c_str(), &st))
|
||||
throw SysError("getting filesystem info about '%s'", realStoreDir);
|
||||
if (statvfs(config->realStoreDir.get().c_str(), &st))
|
||||
throw SysError("getting filesystem info about '%s'", config->realStoreDir);
|
||||
|
||||
return (uint64_t) st.f_bavail * st.f_frsize;
|
||||
};
|
||||
|
|
|
@ -9,6 +9,15 @@ namespace nix {
|
|||
MakeError(UploadToHTTP, Error);
|
||||
|
||||
|
||||
StringSet HttpBinaryCacheStoreConfig::uriSchemes()
|
||||
{
|
||||
static bool forceHttp = getEnv("_NIX_FORCE_HTTP") == "1";
|
||||
auto ret = StringSet{"http", "https"};
|
||||
if (forceHttp)
|
||||
ret.insert("file");
|
||||
return ret;
|
||||
}
|
||||
|
||||
HttpBinaryCacheStoreConfig::HttpBinaryCacheStoreConfig(
|
||||
std::string_view scheme,
|
||||
std::string_view _cacheUri,
|
||||
|
@ -35,10 +44,9 @@ std::string HttpBinaryCacheStoreConfig::doc()
|
|||
}
|
||||
|
||||
|
||||
class HttpBinaryCacheStore : public virtual HttpBinaryCacheStoreConfig, public virtual BinaryCacheStore
|
||||
class HttpBinaryCacheStore :
|
||||
public virtual BinaryCacheStore
|
||||
{
|
||||
private:
|
||||
|
||||
struct State
|
||||
{
|
||||
bool enabled = true;
|
||||
|
@ -49,37 +57,37 @@ private:
|
|||
|
||||
public:
|
||||
|
||||
HttpBinaryCacheStore(
|
||||
std::string_view scheme,
|
||||
PathView cacheUri,
|
||||
const Params & params)
|
||||
: StoreConfig(params)
|
||||
, BinaryCacheStoreConfig(params)
|
||||
, HttpBinaryCacheStoreConfig(scheme, cacheUri, params)
|
||||
, Store(params)
|
||||
, BinaryCacheStore(params)
|
||||
using Config = HttpBinaryCacheStoreConfig;
|
||||
|
||||
ref<Config> config;
|
||||
|
||||
HttpBinaryCacheStore(ref<Config> config)
|
||||
: Store{*config}
|
||||
// TODO it will actually mutate the configuration
|
||||
, BinaryCacheStore{*config}
|
||||
, config{config}
|
||||
{
|
||||
diskCache = getNarInfoDiskCache();
|
||||
}
|
||||
|
||||
std::string getUri() override
|
||||
{
|
||||
return cacheUri;
|
||||
return config->cacheUri;
|
||||
}
|
||||
|
||||
void init() override
|
||||
{
|
||||
// FIXME: do this lazily?
|
||||
if (auto cacheInfo = diskCache->upToDateCacheExists(cacheUri)) {
|
||||
wantMassQuery.setDefault(cacheInfo->wantMassQuery);
|
||||
priority.setDefault(cacheInfo->priority);
|
||||
if (auto cacheInfo = diskCache->upToDateCacheExists(config->cacheUri)) {
|
||||
config->wantMassQuery.setDefault(cacheInfo->wantMassQuery);
|
||||
config->priority.setDefault(cacheInfo->priority);
|
||||
} else {
|
||||
try {
|
||||
BinaryCacheStore::init();
|
||||
} catch (UploadToHTTP &) {
|
||||
throw Error("'%s' does not appear to be a binary cache", cacheUri);
|
||||
throw Error("'%s' does not appear to be a binary cache", config->cacheUri);
|
||||
}
|
||||
diskCache->createCache(cacheUri, storeDir, wantMassQuery, priority);
|
||||
diskCache->createCache(config->cacheUri, config->storeDir, config->wantMassQuery, config->priority);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -137,7 +145,7 @@ protected:
|
|||
try {
|
||||
getFileTransfer()->upload(req);
|
||||
} catch (FileTransferError & e) {
|
||||
throw UploadToHTTP("while uploading to HTTP binary cache at '%s': %s", cacheUri, e.msg());
|
||||
throw UploadToHTTP("while uploading to HTTP binary cache at '%s': %s", config->cacheUri, e.msg());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -146,7 +154,7 @@ protected:
|
|||
return FileTransferRequest(
|
||||
hasPrefix(path, "https://") || hasPrefix(path, "http://") || hasPrefix(path, "file://")
|
||||
? path
|
||||
: cacheUri + "/" + path);
|
||||
: config->cacheUri + "/" + path);
|
||||
|
||||
}
|
||||
|
||||
|
@ -221,6 +229,14 @@ protected:
|
|||
}
|
||||
};
|
||||
|
||||
static RegisterStoreImplementation<HttpBinaryCacheStore, HttpBinaryCacheStoreConfig> regHttpBinaryCacheStore;
|
||||
ref<Store> HttpBinaryCacheStore::Config::openStore() const
|
||||
{
|
||||
return make_ref<HttpBinaryCacheStore>(ref{
|
||||
// FIXME we shouldn't actually need a mutable config
|
||||
std::const_pointer_cast<HttpBinaryCacheStore::Config>(shared_from_this())
|
||||
});
|
||||
}
|
||||
|
||||
static RegisterStoreImplementation<HttpBinaryCacheStore::Config> regHttpBinaryCacheStore;
|
||||
|
||||
}
|
||||
|
|
|
@ -54,10 +54,17 @@ struct BinaryCacheStoreConfig : virtual StoreConfig
|
|||
* @note subclasses must implement at least one of the two
|
||||
* virtual getFile() methods.
|
||||
*/
|
||||
class BinaryCacheStore : public virtual BinaryCacheStoreConfig,
|
||||
public virtual Store,
|
||||
public virtual LogStore
|
||||
struct BinaryCacheStore :
|
||||
virtual Store,
|
||||
virtual LogStore
|
||||
{
|
||||
using Config = BinaryCacheStoreConfig;
|
||||
|
||||
/**
|
||||
* Intentionally mutable because some things we update due to the
|
||||
* cache's own (remote side) settings.
|
||||
*/
|
||||
Config & config;
|
||||
|
||||
private:
|
||||
std::vector<std::unique_ptr<Signer>> signers;
|
||||
|
@ -69,7 +76,7 @@ protected:
|
|||
|
||||
const std::string cacheInfoFile = "nix-cache-info";
|
||||
|
||||
BinaryCacheStore(const Params & params);
|
||||
BinaryCacheStore(Config &);
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ struct CommonSSHStoreConfig : virtual StoreConfig
|
|||
*/
|
||||
SSHMaster createSSHMaster(
|
||||
bool useMaster,
|
||||
Descriptor logFD = INVALID_DESCRIPTOR);
|
||||
Descriptor logFD = INVALID_DESCRIPTOR) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -2,29 +2,27 @@
|
|||
|
||||
namespace nix {
|
||||
|
||||
struct HttpBinaryCacheStoreConfig : virtual BinaryCacheStoreConfig
|
||||
struct HttpBinaryCacheStoreConfig : std::enable_shared_from_this<HttpBinaryCacheStoreConfig>,
|
||||
virtual Store::Config,
|
||||
BinaryCacheStoreConfig
|
||||
{
|
||||
using BinaryCacheStoreConfig::BinaryCacheStoreConfig;
|
||||
|
||||
HttpBinaryCacheStoreConfig(std::string_view scheme, std::string_view _cacheUri, const Params & params);
|
||||
HttpBinaryCacheStoreConfig(
|
||||
std::string_view scheme, std::string_view cacheUri, const Store::Config::Params & params);
|
||||
|
||||
Path cacheUri;
|
||||
|
||||
const std::string name() override
|
||||
static const std::string name()
|
||||
{
|
||||
return "HTTP Binary Cache Store";
|
||||
}
|
||||
|
||||
static StringSet uriSchemes()
|
||||
{
|
||||
static bool forceHttp = getEnv("_NIX_FORCE_HTTP") == "1";
|
||||
auto ret = StringSet({"http", "https"});
|
||||
if (forceHttp)
|
||||
ret.insert("file");
|
||||
return ret;
|
||||
}
|
||||
static StringSet uriSchemes();
|
||||
|
||||
std::string doc() override;
|
||||
static std::string doc();
|
||||
|
||||
ref<Store> openStore() const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
namespace nix {
|
||||
|
||||
struct LegacySSHStoreConfig : virtual CommonSSHStoreConfig
|
||||
struct LegacySSHStoreConfig : std::enable_shared_from_this<LegacySSHStoreConfig>, virtual CommonSSHStoreConfig
|
||||
{
|
||||
using CommonSSHStoreConfig::CommonSSHStoreConfig;
|
||||
|
||||
|
@ -19,6 +19,15 @@ struct LegacySSHStoreConfig : virtual CommonSSHStoreConfig
|
|||
std::string_view authority,
|
||||
const Params & params);
|
||||
|
||||
#ifndef _WIN32
|
||||
// Hack for getting remote build log output.
|
||||
// Intentionally not in `LegacySSHStoreConfig` so that it doesn't appear in
|
||||
// the documentation
|
||||
const Setting<int> logFD{this, INVALID_DESCRIPTOR, "log-fd", "file descriptor to which SSH's stderr is connected"};
|
||||
#else
|
||||
Descriptor logFD = INVALID_DESCRIPTOR;
|
||||
#endif
|
||||
|
||||
const Setting<Strings> remoteProgram{this, {"nix-store"}, "remote-program",
|
||||
"Path to the `nix-store` executable on the remote machine."};
|
||||
|
||||
|
@ -35,23 +44,20 @@ struct LegacySSHStoreConfig : virtual CommonSSHStoreConfig
|
|||
*/
|
||||
std::optional<size_t> connPipeSize;
|
||||
|
||||
const std::string name() override { return "SSH Store"; }
|
||||
static const std::string name() { return "SSH Store"; }
|
||||
|
||||
static StringSet uriSchemes() { return {"ssh"}; }
|
||||
|
||||
std::string doc() override;
|
||||
static std::string doc();
|
||||
|
||||
ref<Store> openStore() const override;
|
||||
};
|
||||
|
||||
struct LegacySSHStore : public virtual LegacySSHStoreConfig, public virtual Store
|
||||
struct LegacySSHStore : public virtual Store
|
||||
{
|
||||
#ifndef _WIN32
|
||||
// Hack for getting remote build log output.
|
||||
// Intentionally not in `LegacySSHStoreConfig` so that it doesn't appear in
|
||||
// the documentation
|
||||
const Setting<int> logFD{this, INVALID_DESCRIPTOR, "log-fd", "file descriptor to which SSH's stderr is connected"};
|
||||
#else
|
||||
Descriptor logFD = INVALID_DESCRIPTOR;
|
||||
#endif
|
||||
using Config = LegacySSHStoreConfig;
|
||||
|
||||
ref<const Config> config;
|
||||
|
||||
struct Connection;
|
||||
|
||||
|
@ -59,10 +65,7 @@ struct LegacySSHStore : public virtual LegacySSHStoreConfig, public virtual Stor
|
|||
|
||||
SSHMaster master;
|
||||
|
||||
LegacySSHStore(
|
||||
std::string_view scheme,
|
||||
std::string_view host,
|
||||
const Params & params);
|
||||
LegacySSHStore(ref<const Config>);
|
||||
|
||||
ref<Connection> openConnection();
|
||||
|
||||
|
@ -187,10 +190,7 @@ public:
|
|||
* The legacy ssh protocol doesn't support checking for trusted-user.
|
||||
* Try using ssh-ng:// instead if you want to know.
|
||||
*/
|
||||
std::optional<TrustedFlag> isTrustedClient() override
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
std::optional<TrustedFlag> isTrustedClient() override;
|
||||
|
||||
void queryRealisationUncached(const DrvOutput &,
|
||||
Callback<std::shared_ptr<const Realisation>> callback) noexcept override
|
||||
|
|
|
@ -2,22 +2,30 @@
|
|||
|
||||
namespace nix {
|
||||
|
||||
struct LocalBinaryCacheStoreConfig : virtual BinaryCacheStoreConfig
|
||||
struct LocalBinaryCacheStoreConfig : std::enable_shared_from_this<LocalBinaryCacheStoreConfig>,
|
||||
virtual Store::Config,
|
||||
BinaryCacheStoreConfig
|
||||
{
|
||||
using BinaryCacheStoreConfig::BinaryCacheStoreConfig;
|
||||
|
||||
/**
|
||||
* @param binaryCacheDir `file://` is a short-hand for `file:///`
|
||||
* for now.
|
||||
*/
|
||||
LocalBinaryCacheStoreConfig(std::string_view scheme, PathView binaryCacheDir, const Params & params);
|
||||
|
||||
Path binaryCacheDir;
|
||||
|
||||
const std::string name() override
|
||||
static const std::string name()
|
||||
{
|
||||
return "Local Binary Cache Store";
|
||||
}
|
||||
|
||||
static StringSet uriSchemes();
|
||||
|
||||
std::string doc() override;
|
||||
static std::string doc();
|
||||
|
||||
ref<Store> openStore() const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -20,36 +20,39 @@ struct LocalFSStoreConfig : virtual StoreConfig
|
|||
*/
|
||||
LocalFSStoreConfig(PathView path, const Params & params);
|
||||
|
||||
const OptionalPathSetting rootDir{this, std::nullopt,
|
||||
OptionalPathSetting rootDir{this, std::nullopt,
|
||||
"root",
|
||||
"Directory prefixed to all other paths."};
|
||||
|
||||
const PathSetting stateDir{this,
|
||||
PathSetting stateDir{this,
|
||||
rootDir.get() ? *rootDir.get() + "/nix/var/nix" : settings.nixStateDir,
|
||||
"state",
|
||||
"Directory where Nix will store state."};
|
||||
|
||||
const PathSetting logDir{this,
|
||||
PathSetting logDir{this,
|
||||
rootDir.get() ? *rootDir.get() + "/nix/var/log/nix" : settings.nixLogDir,
|
||||
"log",
|
||||
"directory where Nix will store log files."};
|
||||
|
||||
const PathSetting realStoreDir{this,
|
||||
PathSetting realStoreDir{this,
|
||||
rootDir.get() ? *rootDir.get() + "/nix/store" : storeDir, "real",
|
||||
"Physical path of the Nix store."};
|
||||
};
|
||||
|
||||
class LocalFSStore : public virtual LocalFSStoreConfig,
|
||||
public virtual Store,
|
||||
public virtual GcStore,
|
||||
public virtual LogStore
|
||||
struct LocalFSStore :
|
||||
virtual Store,
|
||||
virtual GcStore,
|
||||
virtual LogStore
|
||||
{
|
||||
public:
|
||||
using Config = LocalFSStoreConfig;
|
||||
|
||||
const Config & config;
|
||||
|
||||
inline static std::string operationName = "Local Filesystem Store";
|
||||
|
||||
const static std::string drvsLogDir;
|
||||
|
||||
LocalFSStore(const Params & params);
|
||||
LocalFSStore(const Config & params);
|
||||
|
||||
void narFromPath(const StorePath & path, Sink & sink) override;
|
||||
ref<SourceAccessor> getFSAccessor(bool requireValidPath = true) override;
|
||||
|
@ -70,7 +73,7 @@ public:
|
|||
*/
|
||||
virtual Path addPermRoot(const StorePath & storePath, const Path & gcRoot) = 0;
|
||||
|
||||
virtual Path getRealStoreDir() { return realStoreDir; }
|
||||
virtual Path getRealStoreDir() { return config.realStoreDir; }
|
||||
|
||||
Path toRealPath(const Path & storePath) override
|
||||
{
|
||||
|
|
|
@ -56,9 +56,9 @@ struct LocalOverlayStoreConfig : virtual LocalStoreConfig
|
|||
The store directory is passed as an argument to the invoked executable.
|
||||
)"};
|
||||
|
||||
const std::string name() override { return "Experimental Local Overlay Store"; }
|
||||
static const std::string name() { return "Experimental Local Overlay Store"; }
|
||||
|
||||
std::optional<ExperimentalFeature> experimentalFeature() const override
|
||||
static std::optional<ExperimentalFeature> experimentalFeature()
|
||||
{
|
||||
return ExperimentalFeature::LocalOverlayStore;
|
||||
}
|
||||
|
@ -68,7 +68,9 @@ struct LocalOverlayStoreConfig : virtual LocalStoreConfig
|
|||
return { "local-overlay" };
|
||||
}
|
||||
|
||||
std::string doc() override;
|
||||
static std::string doc();
|
||||
|
||||
ref<Store> openStore() const override;
|
||||
|
||||
protected:
|
||||
/**
|
||||
|
@ -79,7 +81,9 @@ protected:
|
|||
* at that file path. It might be stored in the lower layer instead,
|
||||
* or it might not be part of this store at all.
|
||||
*/
|
||||
Path toUpperPath(const StorePath & path);
|
||||
Path toUpperPath(const StorePath & path) const;
|
||||
|
||||
friend struct LocalOverlayStore;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -88,8 +92,20 @@ protected:
|
|||
* Documentation on overridden methods states how they differ from their
|
||||
* `LocalStore` counterparts.
|
||||
*/
|
||||
class LocalOverlayStore : public virtual LocalOverlayStoreConfig, public virtual LocalStore
|
||||
struct LocalOverlayStore : virtual LocalStore
|
||||
{
|
||||
using Config = LocalOverlayStoreConfig;
|
||||
|
||||
ref<const Config> config;
|
||||
|
||||
LocalOverlayStore(ref<const Config>);
|
||||
|
||||
std::string getUri() override
|
||||
{
|
||||
return "local-overlay://";
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* The store beneath us.
|
||||
*
|
||||
|
@ -99,20 +115,6 @@ class LocalOverlayStore : public virtual LocalOverlayStoreConfig, public virtual
|
|||
*/
|
||||
ref<LocalFSStore> lowerStore;
|
||||
|
||||
public:
|
||||
LocalOverlayStore(const Params & params)
|
||||
: LocalOverlayStore("local-overlay", "", params)
|
||||
{
|
||||
}
|
||||
|
||||
LocalOverlayStore(std::string_view scheme, PathView path, const Params & params);
|
||||
|
||||
std::string getUri() override
|
||||
{
|
||||
return "local-overlay://";
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* First copy up any lower store realisation with the same key, so we
|
||||
* merge rather than mask it.
|
||||
|
|
|
@ -34,7 +34,7 @@ struct OptimiseStats
|
|||
uint64_t bytesFreed = 0;
|
||||
};
|
||||
|
||||
struct LocalStoreConfig : virtual LocalFSStoreConfig
|
||||
struct LocalStoreConfig : std::enable_shared_from_this<LocalStoreConfig>, virtual LocalFSStoreConfig
|
||||
{
|
||||
using LocalFSStoreConfig::LocalFSStoreConfig;
|
||||
|
||||
|
@ -65,18 +65,26 @@ struct LocalStoreConfig : virtual LocalFSStoreConfig
|
|||
> While the filesystem the database resides on might appear to be read-only, consider whether another user or system might have write access to it.
|
||||
)"};
|
||||
|
||||
const std::string name() override { return "Local Store"; }
|
||||
static const std::string name() { return "Local Store"; }
|
||||
|
||||
static StringSet uriSchemes()
|
||||
{ return {"local"}; }
|
||||
|
||||
std::string doc() override;
|
||||
static std::string doc();
|
||||
|
||||
ref<Store> openStore() const override;
|
||||
};
|
||||
|
||||
class LocalStore : public virtual LocalStoreConfig
|
||||
, public virtual IndirectRootStore
|
||||
, public virtual GcStore
|
||||
class LocalStore :
|
||||
public virtual IndirectRootStore,
|
||||
public virtual GcStore
|
||||
{
|
||||
public:
|
||||
|
||||
using Config = LocalStoreConfig;
|
||||
|
||||
ref<const LocalStoreConfig> config;
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
|
@ -144,11 +152,7 @@ public:
|
|||
* Initialise the local store, upgrading the schema if
|
||||
* necessary.
|
||||
*/
|
||||
LocalStore(const Params & params);
|
||||
LocalStore(
|
||||
std::string_view scheme,
|
||||
PathView path,
|
||||
const Params & params);
|
||||
LocalStore(ref<const Config> params);
|
||||
|
||||
~LocalStore();
|
||||
|
||||
|
|
|
@ -86,7 +86,7 @@ typedef std::list<Generation> Generations;
|
|||
*/
|
||||
std::pair<Generations, std::optional<GenerationNumber>> findGenerations(Path profile);
|
||||
|
||||
class LocalFSStore;
|
||||
struct LocalFSStore;
|
||||
|
||||
/**
|
||||
* Create a new generation of the given profile
|
||||
|
|
|
@ -19,7 +19,7 @@ class RemoteFSAccessor : public SourceAccessor
|
|||
|
||||
std::pair<ref<SourceAccessor>, CanonPath> fetch(const CanonPath & path);
|
||||
|
||||
friend class BinaryCacheStore;
|
||||
friend struct BinaryCacheStore;
|
||||
|
||||
Path makeCacheFile(std::string_view hashPart, const std::string & ext);
|
||||
|
||||
|
|
|
@ -35,14 +35,16 @@ struct RemoteStoreConfig : virtual StoreConfig
|
|||
* \todo RemoteStore is a misnomer - should be something like
|
||||
* DaemonStore.
|
||||
*/
|
||||
class RemoteStore : public virtual RemoteStoreConfig,
|
||||
struct RemoteStore :
|
||||
public virtual Store,
|
||||
public virtual GcStore,
|
||||
public virtual LogStore
|
||||
{
|
||||
public:
|
||||
using Config = RemoteStoreConfig;
|
||||
|
||||
RemoteStore(const Params & params);
|
||||
const Config & config;
|
||||
|
||||
RemoteStore(const Config & config);
|
||||
|
||||
/* Implementations of abstract store API methods. */
|
||||
|
||||
|
|
|
@ -55,6 +55,6 @@ struct RestrictionContext
|
|||
/**
|
||||
* Create a shared pointer to a restricted store.
|
||||
*/
|
||||
ref<Store> makeRestrictedStore(const Store::Params & params, ref<LocalStore> next, RestrictionContext & context);
|
||||
ref<Store> makeRestrictedStore(ref<LocalStore::Config> config, ref<LocalStore> next, RestrictionContext & context);
|
||||
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
namespace nix {
|
||||
|
||||
struct S3BinaryCacheStoreConfig : virtual BinaryCacheStoreConfig
|
||||
struct S3BinaryCacheStoreConfig : std::enable_shared_from_this<S3BinaryCacheStoreConfig>, virtual BinaryCacheStoreConfig
|
||||
{
|
||||
std::string bucketName;
|
||||
|
||||
|
@ -93,7 +93,7 @@ public:
|
|||
const Setting<uint64_t> bufferSize{
|
||||
this, 5 * 1024 * 1024, "buffer-size", "Size (in bytes) of each part in multi-part uploads."};
|
||||
|
||||
const std::string name() override
|
||||
static const std::string name()
|
||||
{
|
||||
return "S3 Binary Cache Store";
|
||||
}
|
||||
|
@ -103,16 +103,18 @@ public:
|
|||
return {"s3"};
|
||||
}
|
||||
|
||||
std::string doc() override;
|
||||
static std::string doc();
|
||||
|
||||
ref<Store> openStore() const override;
|
||||
};
|
||||
|
||||
class S3BinaryCacheStore : public virtual BinaryCacheStore
|
||||
struct S3BinaryCacheStore : virtual BinaryCacheStore
|
||||
{
|
||||
protected:
|
||||
using Config = S3BinaryCacheStoreConfig;
|
||||
|
||||
S3BinaryCacheStore(const Params & params);
|
||||
ref<Config> config;
|
||||
|
||||
public:
|
||||
S3BinaryCacheStore(ref<Config>);
|
||||
|
||||
struct Stats
|
||||
{
|
||||
|
|
|
@ -8,7 +8,9 @@
|
|||
|
||||
namespace nix {
|
||||
|
||||
struct SSHStoreConfig : virtual RemoteStoreConfig, virtual CommonSSHStoreConfig
|
||||
struct SSHStoreConfig : std::enable_shared_from_this<SSHStoreConfig>,
|
||||
virtual RemoteStoreConfig,
|
||||
virtual CommonSSHStoreConfig
|
||||
{
|
||||
using CommonSSHStoreConfig::CommonSSHStoreConfig;
|
||||
using RemoteStoreConfig::RemoteStoreConfig;
|
||||
|
@ -18,7 +20,7 @@ struct SSHStoreConfig : virtual RemoteStoreConfig, virtual CommonSSHStoreConfig
|
|||
const Setting<Strings> remoteProgram{
|
||||
this, {"nix-daemon"}, "remote-program", "Path to the `nix-daemon` executable on the remote machine."};
|
||||
|
||||
const std::string name() override
|
||||
static const std::string name()
|
||||
{
|
||||
return "Experimental SSH Store";
|
||||
}
|
||||
|
@ -28,19 +30,17 @@ struct SSHStoreConfig : virtual RemoteStoreConfig, virtual CommonSSHStoreConfig
|
|||
return {"ssh-ng"};
|
||||
}
|
||||
|
||||
std::string doc() override;
|
||||
static std::string doc();
|
||||
|
||||
ref<Store> openStore() const override;
|
||||
};
|
||||
|
||||
struct MountedSSHStoreConfig : virtual SSHStoreConfig, virtual LocalFSStoreConfig
|
||||
{
|
||||
using LocalFSStoreConfig::LocalFSStoreConfig;
|
||||
using SSHStoreConfig::SSHStoreConfig;
|
||||
|
||||
MountedSSHStoreConfig(StringMap params);
|
||||
|
||||
MountedSSHStoreConfig(std::string_view scheme, std::string_view host, StringMap params);
|
||||
|
||||
const std::string name() override
|
||||
static const std::string name()
|
||||
{
|
||||
return "Experimental SSH Store with filesystem mounted";
|
||||
}
|
||||
|
@ -50,12 +50,14 @@ struct MountedSSHStoreConfig : virtual SSHStoreConfig, virtual LocalFSStoreConfi
|
|||
return {"mounted-ssh-ng"};
|
||||
}
|
||||
|
||||
std::string doc() override;
|
||||
static std::string doc();
|
||||
|
||||
std::optional<ExperimentalFeature> experimentalFeature() const override
|
||||
static std::optional<ExperimentalFeature> experimentalFeature()
|
||||
{
|
||||
return ExperimentalFeature::MountedSSHStore;
|
||||
}
|
||||
|
||||
ref<Store> openStore() const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -26,32 +26,6 @@
|
|||
|
||||
namespace nix {
|
||||
|
||||
/**
|
||||
* About the class hierarchy of the store types:
|
||||
*
|
||||
* Each store type `Foo` consists of two classes:
|
||||
*
|
||||
* 1. A class `FooConfig : virtual StoreConfig` that contains the configuration
|
||||
* for the store
|
||||
*
|
||||
* It should only contain members of type `const Setting<T>` (or subclasses
|
||||
* of it) and inherit the constructors of `StoreConfig`
|
||||
* (`using StoreConfig::StoreConfig`).
|
||||
*
|
||||
* 2. A class `Foo : virtual Store, virtual FooConfig` that contains the
|
||||
* implementation of the store.
|
||||
*
|
||||
* This class is expected to have a constructor `Foo(const Params & params)`
|
||||
* that calls `StoreConfig(params)` (otherwise you're gonna encounter an
|
||||
* `assertion failure` when trying to instantiate it).
|
||||
*
|
||||
* You can then register the new store using:
|
||||
*
|
||||
* ```
|
||||
* cpp static RegisterStoreImplementation<Foo, FooConfig> regStore;
|
||||
* ```
|
||||
*/
|
||||
|
||||
MakeError(SubstError, Error);
|
||||
/**
|
||||
* denotes a permanent build failure
|
||||
|
@ -97,27 +71,48 @@ struct KeyedBuildResult;
|
|||
|
||||
typedef std::map<StorePath, std::optional<ContentAddress>> StorePathCAMap;
|
||||
|
||||
|
||||
/**
|
||||
* About the class hierarchy of the store types:
|
||||
*
|
||||
* Each store type `Foo` consists of two classes:
|
||||
*
|
||||
* 1. A class `FooConfig : virtual StoreConfig` that contains the configuration
|
||||
* for the store
|
||||
*
|
||||
* It should only contain members of type `Setting<T>` (or subclasses
|
||||
* of it) and inherit the constructors of `StoreConfig`
|
||||
* (`using StoreConfig::StoreConfig`).
|
||||
*
|
||||
* 2. A class `Foo : virtual Store` that contains the
|
||||
* implementation of the store.
|
||||
*
|
||||
* This class is expected to have:
|
||||
*
|
||||
* 1. an alias `using Config = FooConfig;`
|
||||
*
|
||||
* 2. a constructor `Foo(ref<const Config> params)`.
|
||||
*
|
||||
* You can then register the new store using:
|
||||
*
|
||||
* ```
|
||||
* cpp static RegisterStoreImplementation<FooConfig> regStore;
|
||||
* ```
|
||||
*/
|
||||
struct StoreConfig : public StoreDirConfig
|
||||
{
|
||||
using Params = StoreReference::Params;
|
||||
|
||||
using StoreDirConfig::StoreDirConfig;
|
||||
|
||||
StoreConfig() = delete;
|
||||
|
||||
static StringSet getDefaultSystemFeatures();
|
||||
|
||||
virtual ~StoreConfig() { }
|
||||
|
||||
/**
|
||||
* The name of this type of store.
|
||||
*/
|
||||
virtual const std::string name() = 0;
|
||||
static StringSet getDefaultSystemFeatures();
|
||||
|
||||
/**
|
||||
* Documentation for this type of store.
|
||||
*/
|
||||
virtual std::string doc()
|
||||
static std::string doc()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
@ -126,15 +121,15 @@ struct StoreConfig : public StoreDirConfig
|
|||
* An experimental feature this type store is gated, if it is to be
|
||||
* experimental.
|
||||
*/
|
||||
virtual std::optional<ExperimentalFeature> experimentalFeature() const
|
||||
static std::optional<ExperimentalFeature> experimentalFeature()
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const Setting<int> pathInfoCacheSize{this, 65536, "path-info-cache-size",
|
||||
Setting<int> pathInfoCacheSize{this, 65536, "path-info-cache-size",
|
||||
"Size of the in-memory store path metadata cache."};
|
||||
|
||||
const Setting<bool> isTrusted{this, false, "trusted",
|
||||
Setting<bool> isTrusted{this, false, "trusted",
|
||||
R"(
|
||||
Whether paths from this store can be used as substitutes
|
||||
even if they are not signed by a key listed in the
|
||||
|
@ -163,10 +158,38 @@ struct StoreConfig : public StoreDirConfig
|
|||
{},
|
||||
// Don't document the machine-specific default value
|
||||
false};
|
||||
|
||||
/**
|
||||
* Open a store of the type corresponding to this configuration
|
||||
* type.
|
||||
*/
|
||||
virtual ref<Store> openStore() const = 0;
|
||||
};
|
||||
|
||||
class Store : public std::enable_shared_from_this<Store>, public virtual StoreConfig
|
||||
/**
|
||||
* A Store (client)
|
||||
*
|
||||
* This is an interface type allowing for create and read operations on
|
||||
* a collection of store objects, and also building new store objects
|
||||
* from `Derivation`s. See the manual for further details.
|
||||
*
|
||||
* "client" used is because this is just one view/actor onto an
|
||||
* underlying resource, which could be an external process (daemon
|
||||
* server), file system state, etc.
|
||||
*/
|
||||
class Store : public std::enable_shared_from_this<Store>, public MixStoreDirMethods
|
||||
{
|
||||
public:
|
||||
|
||||
using Config = StoreConfig;
|
||||
|
||||
const Config & config;
|
||||
|
||||
/**
|
||||
* @note Avoid churn, since we used to inherit from `Config`.
|
||||
*/
|
||||
operator const Config &() const { return config; }
|
||||
|
||||
protected:
|
||||
|
||||
struct PathInfoCacheValue {
|
||||
|
@ -205,7 +228,7 @@ protected:
|
|||
|
||||
std::shared_ptr<NarInfoDiskCache> diskCache;
|
||||
|
||||
Store(const Params & params);
|
||||
Store(const Store::Config & config);
|
||||
|
||||
public:
|
||||
/**
|
||||
|
@ -877,7 +900,7 @@ ref<Store> openStore(StoreReference && storeURI);
|
|||
|
||||
*/
|
||||
ref<Store> openStore(const std::string & uri = settings.storeUri.get(),
|
||||
const Store::Params & extraParams = Store::Params());
|
||||
const Store::Config::Params & extraParams = Store::Config::Params());
|
||||
|
||||
|
||||
/**
|
||||
|
@ -888,46 +911,72 @@ std::list<ref<Store>> getDefaultSubstituters();
|
|||
|
||||
struct StoreFactory
|
||||
{
|
||||
/**
|
||||
* Documentation for this type of store.
|
||||
*/
|
||||
std::string doc;
|
||||
|
||||
/**
|
||||
* URIs with these schemes should be handled by this factory
|
||||
*/
|
||||
StringSet uriSchemes;
|
||||
|
||||
/**
|
||||
* An experimental feature this type store is gated, if it is to be
|
||||
* experimental.
|
||||
*/
|
||||
std::optional<ExperimentalFeature> experimentalFeature;
|
||||
|
||||
/**
|
||||
* The `authorityPath` parameter is `<authority>/<path>`, or really
|
||||
* whatever comes after `<scheme>://` and before `?<query-params>`.
|
||||
*/
|
||||
std::function<std::shared_ptr<Store> (
|
||||
std::string_view scheme,
|
||||
std::string_view authorityPath,
|
||||
const Store::Params & params)> create;
|
||||
std::function<std::shared_ptr<StoreConfig> ()> getConfig;
|
||||
std::function<ref<StoreConfig>(
|
||||
std::string_view scheme, std::string_view authorityPath, const Store::Config::Params & params)>
|
||||
parseConfig;
|
||||
|
||||
/**
|
||||
* Just for dumping the defaults. Kind of awkward this exists,
|
||||
* because it means we cannot require fields to be manually
|
||||
* specified so easily.
|
||||
*/
|
||||
std::function<ref<StoreConfig>()> getConfig;
|
||||
};
|
||||
|
||||
struct Implementations
|
||||
{
|
||||
static std::vector<StoreFactory> & registered();
|
||||
using Map = std::map<std::string, StoreFactory>;
|
||||
|
||||
template<typename T, typename TConfig>
|
||||
static Map & registered();
|
||||
|
||||
template<typename TConfig>
|
||||
static void add()
|
||||
{
|
||||
StoreFactory factory{
|
||||
.doc = TConfig::doc(),
|
||||
.uriSchemes = TConfig::uriSchemes(),
|
||||
.create =
|
||||
.experimentalFeature = TConfig::experimentalFeature(),
|
||||
.parseConfig =
|
||||
([](auto scheme, auto uri, auto & params)
|
||||
-> std::shared_ptr<Store>
|
||||
{ return std::make_shared<T>(scheme, uri, params); }),
|
||||
-> ref<StoreConfig>
|
||||
{ return make_ref<TConfig>(scheme, uri, params); }),
|
||||
.getConfig =
|
||||
([]()
|
||||
-> std::shared_ptr<StoreConfig>
|
||||
{ return std::make_shared<TConfig>(StringMap({})); })
|
||||
([]() -> ref<StoreConfig>
|
||||
{ return make_ref<TConfig>(Store::Config::Params{}); }),
|
||||
};
|
||||
registered().push_back(factory);
|
||||
auto [it, didInsert] = registered().insert({TConfig::name(), std::move(factory)});
|
||||
if (!didInsert) {
|
||||
throw Error("Already registred store with name '%s'", it->first);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename TConfig>
|
||||
template<typename TConfig>
|
||||
struct RegisterStoreImplementation
|
||||
{
|
||||
RegisterStoreImplementation()
|
||||
{
|
||||
Implementations::add<T, TConfig>();
|
||||
Implementations::add<TConfig>();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -18,22 +18,18 @@ struct SourcePath;
|
|||
MakeError(BadStorePath, Error);
|
||||
MakeError(BadStorePathName, BadStorePath);
|
||||
|
||||
struct StoreDirConfig : public Config
|
||||
/**
|
||||
* @todo This should just be part of `StoreDirConfig`. However, it would
|
||||
* be a huge amount of churn if `Store` didn't have these methods
|
||||
* anymore, forcing a bunch of code to go from `store.method(...)` to
|
||||
* `store.config.method(...)`.
|
||||
*
|
||||
* So we instead pull out the methods into their own mix-in, so can put
|
||||
* them directly on the Store too.
|
||||
*/
|
||||
struct MixStoreDirMethods
|
||||
{
|
||||
using Config::Config;
|
||||
|
||||
StoreDirConfig() = delete;
|
||||
|
||||
virtual ~StoreDirConfig() = default;
|
||||
|
||||
const PathSetting storeDir_{this, settings.nixStore,
|
||||
"store",
|
||||
R"(
|
||||
Logical location of the Nix store, usually
|
||||
`/nix/store`. Note that you can only copy store paths
|
||||
between stores if they have the same `store` setting.
|
||||
)"};
|
||||
const Path storeDir = storeDir_;
|
||||
const Path & storeDir;
|
||||
|
||||
// pure methods
|
||||
|
||||
|
@ -56,7 +52,7 @@ struct StoreDirConfig : public Config
|
|||
* Display a set of paths in human-readable form (i.e., between quotes
|
||||
* and separated by commas).
|
||||
*/
|
||||
std::string showPaths(const StorePathSet & paths);
|
||||
std::string showPaths(const StorePathSet & paths) const;
|
||||
|
||||
/**
|
||||
* @return true if *path* is in the Nix store (but not the Nix
|
||||
|
@ -104,4 +100,38 @@ struct StoreDirConfig : public Config
|
|||
PathFilter & filter = defaultPathFilter) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Need to make this a separate class so I can get the right
|
||||
* initialization order in the constructor for `StoreDirConfig`.
|
||||
*/
|
||||
struct StoreDirConfigItself : Config
|
||||
{
|
||||
using Config::Config;
|
||||
|
||||
const PathSetting storeDir_{this, settings.nixStore,
|
||||
"store",
|
||||
R"(
|
||||
Logical location of the Nix store, usually
|
||||
`/nix/store`. Note that you can only copy store paths
|
||||
between stores if they have the same `store` setting.
|
||||
)"};
|
||||
};
|
||||
|
||||
/**
|
||||
* The order of `StoreDirConfigItself` and then `MixStoreDirMethods` is
|
||||
* very important. This ensures that `StoreDirConfigItself::storeDir_`
|
||||
* is initialized before we have our one chance (because references are
|
||||
* immutable) to initialize `MixStoreDirMethods::storeDir`.
|
||||
*/
|
||||
struct StoreDirConfig : StoreDirConfigItself, MixStoreDirMethods
|
||||
{
|
||||
using Params = std::map<std::string, std::string>;
|
||||
|
||||
StoreDirConfig(const Params & params);
|
||||
|
||||
StoreDirConfig() = delete;
|
||||
|
||||
virtual ~StoreDirConfig() = default;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -7,7 +7,10 @@
|
|||
|
||||
namespace nix {
|
||||
|
||||
struct UDSRemoteStoreConfig : virtual LocalFSStoreConfig, virtual RemoteStoreConfig
|
||||
struct UDSRemoteStoreConfig :
|
||||
std::enable_shared_from_this<UDSRemoteStoreConfig>,
|
||||
virtual LocalFSStoreConfig,
|
||||
virtual RemoteStoreConfig
|
||||
{
|
||||
// TODO(fzakaria): Delete this constructor once moved over to the factory pattern
|
||||
// outlined in https://github.com/NixOS/nix/issues/10766
|
||||
|
@ -22,9 +25,11 @@ struct UDSRemoteStoreConfig : virtual LocalFSStoreConfig, virtual RemoteStoreCon
|
|||
std::string_view authority,
|
||||
const Params & params);
|
||||
|
||||
const std::string name() override { return "Local Daemon Store"; }
|
||||
UDSRemoteStoreConfig(const Params & params);
|
||||
|
||||
std::string doc() override;
|
||||
static const std::string name() { return "Local Daemon Store"; }
|
||||
|
||||
static std::string doc();
|
||||
|
||||
/**
|
||||
* The path to the unix domain socket.
|
||||
|
@ -34,32 +39,21 @@ struct UDSRemoteStoreConfig : virtual LocalFSStoreConfig, virtual RemoteStoreCon
|
|||
*/
|
||||
Path path;
|
||||
|
||||
protected:
|
||||
static constexpr char const * scheme = "unix";
|
||||
|
||||
public:
|
||||
static StringSet uriSchemes()
|
||||
{ return {scheme}; }
|
||||
{ return {"unix"}; }
|
||||
|
||||
ref<Store> openStore() const override;
|
||||
};
|
||||
|
||||
class UDSRemoteStore : public virtual UDSRemoteStoreConfig
|
||||
, public virtual IndirectRootStore
|
||||
, public virtual RemoteStore
|
||||
struct UDSRemoteStore :
|
||||
virtual IndirectRootStore,
|
||||
virtual RemoteStore
|
||||
{
|
||||
public:
|
||||
using Config = UDSRemoteStoreConfig;
|
||||
|
||||
/**
|
||||
* @deprecated This is the old API to construct the store.
|
||||
*/
|
||||
UDSRemoteStore(const Params & params);
|
||||
ref<const Config> config;
|
||||
|
||||
/**
|
||||
* @param authority is the socket path.
|
||||
*/
|
||||
UDSRemoteStore(
|
||||
std::string_view scheme,
|
||||
std::string_view authority,
|
||||
const Params & params);
|
||||
UDSRemoteStore(ref<const Config>);
|
||||
|
||||
std::string getUri() override;
|
||||
|
||||
|
|
|
@ -38,23 +38,19 @@ struct LegacySSHStore::Connection : public ServeProto::BasicClientConnection
|
|||
bool good = true;
|
||||
};
|
||||
|
||||
LegacySSHStore::LegacySSHStore(
|
||||
std::string_view scheme,
|
||||
std::string_view host,
|
||||
const Params & params)
|
||||
: StoreConfig(params)
|
||||
, CommonSSHStoreConfig(scheme, host, params)
|
||||
, LegacySSHStoreConfig(scheme, host, params)
|
||||
, Store(params)
|
||||
|
||||
LegacySSHStore::LegacySSHStore(ref<const Config> config)
|
||||
: Store{*config}
|
||||
, config{config}
|
||||
, connections(make_ref<Pool<Connection>>(
|
||||
std::max(1, (int) maxConnections),
|
||||
std::max(1, (int) config->maxConnections),
|
||||
[this]() { return openConnection(); },
|
||||
[](const ref<Connection> & r) { return r->good; }
|
||||
))
|
||||
, master(createSSHMaster(
|
||||
, master(config->createSSHMaster(
|
||||
// Use SSH master only if using more than 1 connection.
|
||||
connections->capacity() > 1,
|
||||
logFD))
|
||||
config->logFD))
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -62,16 +58,16 @@ LegacySSHStore::LegacySSHStore(
|
|||
ref<LegacySSHStore::Connection> LegacySSHStore::openConnection()
|
||||
{
|
||||
auto conn = make_ref<Connection>();
|
||||
Strings command = remoteProgram.get();
|
||||
Strings command = config->remoteProgram.get();
|
||||
command.push_back("--serve");
|
||||
command.push_back("--write");
|
||||
if (remoteStore.get() != "") {
|
||||
if (config->remoteStore.get() != "") {
|
||||
command.push_back("--store");
|
||||
command.push_back(remoteStore.get());
|
||||
command.push_back(config->remoteStore.get());
|
||||
}
|
||||
conn->sshConn = master.startCommand(std::move(command), std::list{extraSshArgs});
|
||||
if (connPipeSize) {
|
||||
conn->sshConn->trySetBufferSize(*connPipeSize);
|
||||
conn->sshConn = master.startCommand(std::move(command), std::list{config->extraSshArgs});
|
||||
if (config->connPipeSize) {
|
||||
conn->sshConn->trySetBufferSize(*config->connPipeSize);
|
||||
}
|
||||
conn->to = FdSink(conn->sshConn->in.get());
|
||||
conn->from = FdSource(conn->sshConn->out.get());
|
||||
|
@ -80,7 +76,7 @@ ref<LegacySSHStore::Connection> LegacySSHStore::openConnection()
|
|||
TeeSource tee(conn->from, saved);
|
||||
try {
|
||||
conn->remoteVersion = ServeProto::BasicClientConnection::handshake(
|
||||
conn->to, tee, SERVE_PROTOCOL_VERSION, host);
|
||||
conn->to, tee, SERVE_PROTOCOL_VERSION, config->host);
|
||||
} catch (SerialisationError & e) {
|
||||
// in.close(): Don't let the remote block on us not writing.
|
||||
conn->sshConn->in.close();
|
||||
|
@ -89,9 +85,9 @@ ref<LegacySSHStore::Connection> LegacySSHStore::openConnection()
|
|||
tee.drainInto(nullSink);
|
||||
}
|
||||
throw Error("'nix-store --serve' protocol mismatch from '%s', got '%s'",
|
||||
host, chomp(saved.s));
|
||||
config->host, chomp(saved.s));
|
||||
} catch (EndOfFile & e) {
|
||||
throw Error("cannot connect to '%1%'", host);
|
||||
throw Error("cannot connect to '%1%'", config->host);
|
||||
}
|
||||
|
||||
return conn;
|
||||
|
@ -100,7 +96,7 @@ ref<LegacySSHStore::Connection> LegacySSHStore::openConnection()
|
|||
|
||||
std::string LegacySSHStore::getUri()
|
||||
{
|
||||
return *uriSchemes().begin() + "://" + host;
|
||||
return *Config::uriSchemes().begin() + "://" + config->host;
|
||||
}
|
||||
|
||||
std::map<StorePath, UnkeyedValidPathInfo> LegacySSHStore::queryPathInfosUncached(
|
||||
|
@ -111,7 +107,7 @@ std::map<StorePath, UnkeyedValidPathInfo> LegacySSHStore::queryPathInfosUncached
|
|||
/* No longer support missing NAR hash */
|
||||
assert(GET_PROTOCOL_MINOR(conn->remoteVersion) >= 4);
|
||||
|
||||
debug("querying remote host '%s' for info on '%s'", host, concatStringsSep(", ", printStorePathSet(paths)));
|
||||
debug("querying remote host '%s' for info on '%s'", config->host, concatStringsSep(", ", printStorePathSet(paths)));
|
||||
|
||||
auto infos = conn->queryPathInfos(*this, paths);
|
||||
|
||||
|
@ -151,7 +147,7 @@ void LegacySSHStore::queryPathInfoUncached(const StorePath & path,
|
|||
void LegacySSHStore::addToStore(const ValidPathInfo & info, Source & source,
|
||||
RepairFlag repair, CheckSigsFlag checkSigs)
|
||||
{
|
||||
debug("adding path '%s' to remote host '%s'", printStorePath(info.path), host);
|
||||
debug("adding path '%s' to remote host '%s'", printStorePath(info.path), config->host);
|
||||
|
||||
auto conn(connections->get());
|
||||
|
||||
|
@ -178,7 +174,7 @@ void LegacySSHStore::addToStore(const ValidPathInfo & info, Source & source,
|
|||
conn->to.flush();
|
||||
|
||||
if (readInt(conn->from) != 1)
|
||||
throw Error("failed to add path '%s' to remote host '%s'", printStorePath(info.path), host);
|
||||
throw Error("failed to add path '%s' to remote host '%s'", printStorePath(info.path), config->host);
|
||||
|
||||
} else {
|
||||
|
||||
|
@ -390,12 +386,17 @@ LegacySSHStore::ConnectionStats LegacySSHStore::getConnectionStats()
|
|||
* The legacy ssh protocol doesn't support checking for trusted-user.
|
||||
* Try using ssh-ng:// instead if you want to know.
|
||||
*/
|
||||
std::optional<TrustedFlag> isTrustedClient()
|
||||
std::optional<TrustedFlag> LegacySSHStore::isTrustedClient()
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
|
||||
static RegisterStoreImplementation<LegacySSHStore, LegacySSHStoreConfig> regLegacySSHStore;
|
||||
ref<Store> LegacySSHStore::Config::openStore() const {
|
||||
return make_ref<LegacySSHStore>(ref{shared_from_this()});
|
||||
}
|
||||
|
||||
|
||||
static RegisterStoreImplementation<LegacySSHStore::Config> regLegacySSHStore;
|
||||
|
||||
}
|
||||
|
|
|
@ -10,9 +10,9 @@ namespace nix {
|
|||
LocalBinaryCacheStoreConfig::LocalBinaryCacheStoreConfig(
|
||||
std::string_view scheme,
|
||||
PathView binaryCacheDir,
|
||||
const Params & params)
|
||||
: StoreConfig(params)
|
||||
, BinaryCacheStoreConfig(params)
|
||||
const StoreReference::Params & params)
|
||||
: Store::Config{params}
|
||||
, BinaryCacheStoreConfig{params}
|
||||
, binaryCacheDir(binaryCacheDir)
|
||||
{
|
||||
}
|
||||
|
@ -26,29 +26,26 @@ std::string LocalBinaryCacheStoreConfig::doc()
|
|||
}
|
||||
|
||||
|
||||
struct LocalBinaryCacheStore : virtual LocalBinaryCacheStoreConfig, virtual BinaryCacheStore
|
||||
struct LocalBinaryCacheStore :
|
||||
virtual BinaryCacheStore
|
||||
{
|
||||
/**
|
||||
* @param binaryCacheDir `file://` is a short-hand for `file:///`
|
||||
* for now.
|
||||
*/
|
||||
LocalBinaryCacheStore(
|
||||
std::string_view scheme,
|
||||
PathView binaryCacheDir,
|
||||
const Params & params)
|
||||
: StoreConfig(params)
|
||||
, BinaryCacheStoreConfig(params)
|
||||
, LocalBinaryCacheStoreConfig(scheme, binaryCacheDir, params)
|
||||
, Store(params)
|
||||
, BinaryCacheStore(params)
|
||||
using Config = LocalBinaryCacheStoreConfig;
|
||||
|
||||
ref<Config> config;
|
||||
|
||||
LocalBinaryCacheStore(ref<Config> config)
|
||||
: Store{*config}
|
||||
, BinaryCacheStore{*config}
|
||||
, config{config}
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
void init() override;
|
||||
|
||||
std::string getUri() override
|
||||
{
|
||||
return "file://" + binaryCacheDir;
|
||||
return "file://" + config->binaryCacheDir;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@ -59,7 +56,7 @@ protected:
|
|||
std::shared_ptr<std::basic_iostream<char>> istream,
|
||||
const std::string & mimeType) override
|
||||
{
|
||||
auto path2 = binaryCacheDir + "/" + path;
|
||||
auto path2 = config->binaryCacheDir + "/" + path;
|
||||
static std::atomic<int> counter{0};
|
||||
Path tmp = fmt("%s.tmp.%d.%d", path2, getpid(), ++counter);
|
||||
AutoDelete del(tmp, false);
|
||||
|
@ -72,7 +69,7 @@ protected:
|
|||
void getFile(const std::string & path, Sink & sink) override
|
||||
{
|
||||
try {
|
||||
readFile(binaryCacheDir + "/" + path, sink);
|
||||
readFile(config->binaryCacheDir + "/" + path, sink);
|
||||
} catch (SysError & e) {
|
||||
if (e.errNo == ENOENT)
|
||||
throw NoSuchBinaryCacheFile("file '%s' does not exist in binary cache", path);
|
||||
|
@ -84,7 +81,7 @@ protected:
|
|||
{
|
||||
StorePathSet paths;
|
||||
|
||||
for (auto & entry : DirectoryIterator{binaryCacheDir}) {
|
||||
for (auto & entry : DirectoryIterator{config->binaryCacheDir}) {
|
||||
checkInterrupt();
|
||||
auto name = entry.path().filename().string();
|
||||
if (name.size() != 40 ||
|
||||
|
@ -106,17 +103,17 @@ protected:
|
|||
|
||||
void LocalBinaryCacheStore::init()
|
||||
{
|
||||
createDirs(binaryCacheDir + "/nar");
|
||||
createDirs(binaryCacheDir + "/" + realisationsPrefix);
|
||||
if (writeDebugInfo)
|
||||
createDirs(binaryCacheDir + "/debuginfo");
|
||||
createDirs(binaryCacheDir + "/log");
|
||||
createDirs(config->binaryCacheDir + "/nar");
|
||||
createDirs(config->binaryCacheDir + "/" + realisationsPrefix);
|
||||
if (config->writeDebugInfo)
|
||||
createDirs(config->binaryCacheDir + "/debuginfo");
|
||||
createDirs(config->binaryCacheDir + "/log");
|
||||
BinaryCacheStore::init();
|
||||
}
|
||||
|
||||
bool LocalBinaryCacheStore::fileExists(const std::string & path)
|
||||
{
|
||||
return pathExists(binaryCacheDir + "/" + path);
|
||||
return pathExists(config->binaryCacheDir + "/" + path);
|
||||
}
|
||||
|
||||
StringSet LocalBinaryCacheStoreConfig::uriSchemes()
|
||||
|
@ -127,6 +124,13 @@ StringSet LocalBinaryCacheStoreConfig::uriSchemes()
|
|||
return {"file"};
|
||||
}
|
||||
|
||||
static RegisterStoreImplementation<LocalBinaryCacheStore, LocalBinaryCacheStoreConfig> regLocalBinaryCacheStore;
|
||||
ref<Store> LocalBinaryCacheStoreConfig::openStore() const {
|
||||
return make_ref<LocalBinaryCacheStore>(ref{
|
||||
// FIXME we shouldn't actually need a mutable config
|
||||
std::const_pointer_cast<LocalBinaryCacheStore::Config>(shared_from_this())
|
||||
});
|
||||
}
|
||||
|
||||
static RegisterStoreImplementation<LocalBinaryCacheStore::Config> regLocalBinaryCacheStore;
|
||||
|
||||
}
|
||||
|
|
|
@ -22,8 +22,9 @@ LocalFSStoreConfig::LocalFSStoreConfig(PathView rootDir, const Params & params)
|
|||
{
|
||||
}
|
||||
|
||||
LocalFSStore::LocalFSStore(const Params & params)
|
||||
: Store(params)
|
||||
LocalFSStore::LocalFSStore(const Config & config)
|
||||
: Store{static_cast<const Store::Config &>(*this)}
|
||||
, config{config}
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -33,7 +34,7 @@ struct LocalStoreAccessor : PosixSourceAccessor
|
|||
bool requireValidPath;
|
||||
|
||||
LocalStoreAccessor(ref<LocalFSStore> store, bool requireValidPath)
|
||||
: PosixSourceAccessor(std::filesystem::path{store->realStoreDir.get()})
|
||||
: PosixSourceAccessor(std::filesystem::path{store->config.realStoreDir.get()})
|
||||
, store(store)
|
||||
, requireValidPath(requireValidPath)
|
||||
{
|
||||
|
@ -104,8 +105,8 @@ std::optional<std::string> LocalFSStore::getBuildLogExact(const StorePath & path
|
|||
|
||||
Path logPath =
|
||||
j == 0
|
||||
? fmt("%s/%s/%s/%s", logDir, drvsLogDir, baseName.substr(0, 2), baseName.substr(2))
|
||||
: fmt("%s/%s/%s", logDir, drvsLogDir, baseName);
|
||||
? fmt("%s/%s/%s/%s", config.logDir.get(), drvsLogDir, baseName.substr(0, 2), baseName.substr(2))
|
||||
: fmt("%s/%s/%s", config.logDir.get(), drvsLogDir, baseName);
|
||||
Path logBz2Path = logPath + ".bz2";
|
||||
|
||||
if (pathExists(logPath))
|
||||
|
|
|
@ -14,25 +14,32 @@ std::string LocalOverlayStoreConfig::doc()
|
|||
;
|
||||
}
|
||||
|
||||
Path LocalOverlayStoreConfig::toUpperPath(const StorePath & path) {
|
||||
ref<Store> LocalOverlayStoreConfig::openStore() const
|
||||
{
|
||||
return make_ref<LocalOverlayStore>(ref{
|
||||
std::dynamic_pointer_cast<const LocalOverlayStoreConfig>(shared_from_this())
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Path LocalOverlayStoreConfig::toUpperPath(const StorePath & path) const
|
||||
{
|
||||
return upperLayer + "/" + path.to_string();
|
||||
}
|
||||
|
||||
LocalOverlayStore::LocalOverlayStore(std::string_view scheme, PathView path, const Params & params)
|
||||
: StoreConfig(params)
|
||||
, LocalFSStoreConfig(path, params)
|
||||
, LocalStoreConfig(params)
|
||||
, LocalOverlayStoreConfig(scheme, path, params)
|
||||
, Store(params)
|
||||
, LocalFSStore(params)
|
||||
, LocalStore(params)
|
||||
, lowerStore(openStore(percentDecode(lowerStoreUri.get())).dynamic_pointer_cast<LocalFSStore>())
|
||||
|
||||
LocalOverlayStore::LocalOverlayStore(ref<const Config> config)
|
||||
: Store{*config}
|
||||
, LocalFSStore{*config}
|
||||
, LocalStore{static_cast<ref<const LocalStore::Config>>(config)}
|
||||
, config{config}
|
||||
, lowerStore(openStore(percentDecode(config->lowerStoreUri.get())).dynamic_pointer_cast<LocalFSStore>())
|
||||
{
|
||||
if (checkMount.get()) {
|
||||
if (config->checkMount.get()) {
|
||||
std::smatch match;
|
||||
std::string mountInfo;
|
||||
auto mounts = readFile(std::filesystem::path{"/proc/self/mounts"});
|
||||
auto regex = std::regex(R"((^|\n)overlay )" + realStoreDir.get() + R"( .*(\n|$))");
|
||||
auto regex = std::regex(R"((^|\n)overlay )" + config->realStoreDir.get() + R"( .*(\n|$))");
|
||||
|
||||
// Mount points can be stacked, so there might be multiple matching entries.
|
||||
// Loop until the last match, which will be the current state of the mount point.
|
||||
|
@ -45,13 +52,13 @@ LocalOverlayStore::LocalOverlayStore(std::string_view scheme, PathView path, con
|
|||
return std::regex_search(mountInfo, std::regex("\\b" + option + "=" + value + "( |,)"));
|
||||
};
|
||||
|
||||
auto expectedLowerDir = lowerStore->realStoreDir.get();
|
||||
if (!checkOption("lowerdir", expectedLowerDir) || !checkOption("upperdir", upperLayer)) {
|
||||
auto expectedLowerDir = lowerStore->config.realStoreDir.get();
|
||||
if (!checkOption("lowerdir", expectedLowerDir) || !checkOption("upperdir", config->upperLayer)) {
|
||||
debug("expected lowerdir: %s", expectedLowerDir);
|
||||
debug("expected upperdir: %s", upperLayer);
|
||||
debug("expected upperdir: %s", config->upperLayer);
|
||||
debug("actual mount: %s", mountInfo);
|
||||
throw Error("overlay filesystem '%s' mounted incorrectly",
|
||||
realStoreDir.get());
|
||||
config->realStoreDir.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -201,14 +208,14 @@ void LocalOverlayStore::collectGarbage(const GCOptions & options, GCResults & re
|
|||
|
||||
void LocalOverlayStore::deleteStorePath(const Path & path, uint64_t & bytesFreed)
|
||||
{
|
||||
auto mergedDir = realStoreDir.get() + "/";
|
||||
auto mergedDir = config->realStoreDir.get() + "/";
|
||||
if (path.substr(0, mergedDir.length()) != mergedDir) {
|
||||
warn("local-overlay: unexpected gc path '%s' ", path);
|
||||
return;
|
||||
}
|
||||
|
||||
StorePath storePath = {path.substr(mergedDir.length())};
|
||||
auto upperPath = toUpperPath(storePath);
|
||||
auto upperPath = config->toUpperPath(storePath);
|
||||
|
||||
if (pathExists(upperPath)) {
|
||||
debug("upper exists: %s", path);
|
||||
|
@ -257,7 +264,7 @@ LocalStore::VerificationResult LocalOverlayStore::verifyAllValidPaths(RepairFlag
|
|||
StorePathSet done;
|
||||
|
||||
auto existsInStoreDir = [&](const StorePath & storePath) {
|
||||
return pathExists(realStoreDir.get() + "/" + storePath.to_string());
|
||||
return pathExists(config->realStoreDir.get() + "/" + storePath.to_string());
|
||||
};
|
||||
|
||||
bool errors = false;
|
||||
|
@ -277,16 +284,16 @@ void LocalOverlayStore::remountIfNecessary()
|
|||
{
|
||||
if (!_remountRequired) return;
|
||||
|
||||
if (remountHook.get().empty()) {
|
||||
warn("'%s' needs remounting, set remount-hook to do this automatically", realStoreDir.get());
|
||||
if (config->remountHook.get().empty()) {
|
||||
warn("'%s' needs remounting, set remount-hook to do this automatically", config->realStoreDir.get());
|
||||
} else {
|
||||
runProgram(remountHook, false, {realStoreDir});
|
||||
runProgram(config->remountHook, false, {config->realStoreDir});
|
||||
}
|
||||
|
||||
_remountRequired = false;
|
||||
}
|
||||
|
||||
|
||||
static RegisterStoreImplementation<LocalOverlayStore, LocalOverlayStoreConfig> regLocalOverlayStore;
|
||||
static RegisterStoreImplementation<LocalOverlayStore::Config> regLocalOverlayStore;
|
||||
|
||||
}
|
||||
|
|
|
@ -75,6 +75,11 @@ std::string LocalStoreConfig::doc()
|
|||
;
|
||||
}
|
||||
|
||||
ref<Store> LocalStore::Config::openStore() const
|
||||
{
|
||||
return make_ref<LocalStore>(ref{shared_from_this()});
|
||||
}
|
||||
|
||||
struct LocalStore::State::Stmts {
|
||||
/* Some precompiled SQLite statements. */
|
||||
SQLiteStmt RegisterValidPath;
|
||||
|
@ -97,38 +102,33 @@ struct LocalStore::State::Stmts {
|
|||
SQLiteStmt AddRealisationReference;
|
||||
};
|
||||
|
||||
LocalStore::LocalStore(
|
||||
std::string_view scheme,
|
||||
PathView path,
|
||||
const Params & params)
|
||||
: StoreConfig(params)
|
||||
, LocalFSStoreConfig(path, params)
|
||||
, LocalStoreConfig(scheme, path, params)
|
||||
, Store(params)
|
||||
, LocalFSStore(params)
|
||||
, dbDir(stateDir + "/db")
|
||||
, linksDir(realStoreDir + "/.links")
|
||||
LocalStore::LocalStore(ref<const Config> config)
|
||||
: Store{*config}
|
||||
, LocalFSStore{*config}
|
||||
, config{config}
|
||||
, dbDir(config->stateDir + "/db")
|
||||
, linksDir(config->realStoreDir + "/.links")
|
||||
, reservedPath(dbDir + "/reserved")
|
||||
, schemaPath(dbDir + "/schema")
|
||||
, tempRootsDir(stateDir + "/temproots")
|
||||
, tempRootsDir(config->stateDir + "/temproots")
|
||||
, fnTempRoots(fmt("%s/%d", tempRootsDir, getpid()))
|
||||
{
|
||||
auto state(_state.lock());
|
||||
state->stmts = std::make_unique<State::Stmts>();
|
||||
|
||||
/* Create missing state directories if they don't already exist. */
|
||||
createDirs(realStoreDir.get());
|
||||
if (readOnly) {
|
||||
createDirs(config->realStoreDir.get());
|
||||
if (config->readOnly) {
|
||||
experimentalFeatureSettings.require(Xp::ReadOnlyLocalStore);
|
||||
} else {
|
||||
makeStoreWritable();
|
||||
}
|
||||
createDirs(linksDir);
|
||||
Path profilesDir = stateDir + "/profiles";
|
||||
Path profilesDir = config->stateDir + "/profiles";
|
||||
createDirs(profilesDir);
|
||||
createDirs(tempRootsDir);
|
||||
createDirs(dbDir);
|
||||
Path gcRootsDir = stateDir + "/gcroots";
|
||||
Path gcRootsDir = config->stateDir + "/gcroots";
|
||||
if (!pathExists(gcRootsDir)) {
|
||||
createDirs(gcRootsDir);
|
||||
createSymlink(profilesDir, gcRootsDir + "/profiles");
|
||||
|
@ -136,7 +136,7 @@ LocalStore::LocalStore(
|
|||
|
||||
for (auto & perUserDir : {profilesDir + "/per-user", gcRootsDir + "/per-user"}) {
|
||||
createDirs(perUserDir);
|
||||
if (!readOnly) {
|
||||
if (!config->readOnly) {
|
||||
// Skip chmod call if the directory already has the correct permissions (0755).
|
||||
// This is to avoid failing when the executing user lacks permissions to change the directory's permissions
|
||||
// even if it would be no-op.
|
||||
|
@ -153,16 +153,16 @@ LocalStore::LocalStore(
|
|||
struct group * gr = getgrnam(settings.buildUsersGroup.get().c_str());
|
||||
if (!gr)
|
||||
printError("warning: the group '%1%' specified in 'build-users-group' does not exist", settings.buildUsersGroup);
|
||||
else if (!readOnly) {
|
||||
else if (!config->readOnly) {
|
||||
struct stat st;
|
||||
if (stat(realStoreDir.get().c_str(), &st))
|
||||
throw SysError("getting attributes of path '%1%'", realStoreDir);
|
||||
if (stat(config->realStoreDir.get().c_str(), &st))
|
||||
throw SysError("getting attributes of path '%1%'", config->realStoreDir);
|
||||
|
||||
if (st.st_uid != 0 || st.st_gid != gr->gr_gid || (st.st_mode & ~S_IFMT) != perm) {
|
||||
if (chown(realStoreDir.get().c_str(), 0, gr->gr_gid) == -1)
|
||||
throw SysError("changing ownership of path '%1%'", realStoreDir);
|
||||
if (chmod(realStoreDir.get().c_str(), perm) == -1)
|
||||
throw SysError("changing permissions on path '%1%'", realStoreDir);
|
||||
if (chown(config->realStoreDir.get().c_str(), 0, gr->gr_gid) == -1)
|
||||
throw SysError("changing ownership of path '%1%'", config->realStoreDir);
|
||||
if (chmod(config->realStoreDir.get().c_str(), perm) == -1)
|
||||
throw SysError("changing permissions on path '%1%'", config->realStoreDir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -170,7 +170,7 @@ LocalStore::LocalStore(
|
|||
|
||||
/* Ensure that the store and its parents are not symlinks. */
|
||||
if (!settings.allowSymlinkedStore) {
|
||||
std::filesystem::path path = realStoreDir.get();
|
||||
std::filesystem::path path = config->realStoreDir.get();
|
||||
std::filesystem::path root = path.root_path();
|
||||
while (path != root) {
|
||||
if (std::filesystem::is_symlink(path))
|
||||
|
@ -217,12 +217,12 @@ LocalStore::LocalStore(
|
|||
|
||||
/* Acquire the big fat lock in shared mode to make sure that no
|
||||
schema upgrade is in progress. */
|
||||
if (!readOnly) {
|
||||
if (!config->readOnly) {
|
||||
Path globalLockPath = dbDir + "/big-lock";
|
||||
globalLock = openLockFile(globalLockPath.c_str(), true);
|
||||
}
|
||||
|
||||
if (!readOnly && !lockFile(globalLock.get(), ltRead, false)) {
|
||||
if (!config->readOnly && !lockFile(globalLock.get(), ltRead, false)) {
|
||||
printInfo("waiting for the big Nix store lock...");
|
||||
lockFile(globalLock.get(), ltRead, true);
|
||||
}
|
||||
|
@ -230,7 +230,7 @@ LocalStore::LocalStore(
|
|||
/* Check the current database schema and if necessary do an
|
||||
upgrade. */
|
||||
int curSchema = getSchema();
|
||||
if (readOnly && curSchema < nixSchemaVersion) {
|
||||
if (config->readOnly && curSchema < nixSchemaVersion) {
|
||||
debug("current schema version: %d", curSchema);
|
||||
debug("supported schema version: %d", nixSchemaVersion);
|
||||
throw Error(curSchema == 0 ?
|
||||
|
@ -378,15 +378,9 @@ LocalStore::LocalStore(
|
|||
}
|
||||
|
||||
|
||||
LocalStore::LocalStore(const Params & params)
|
||||
: LocalStore("local", "", params)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
AutoCloseFD LocalStore::openGCLock()
|
||||
{
|
||||
Path fnGCLock = stateDir + "/gc.lock";
|
||||
Path fnGCLock = config->stateDir + "/gc.lock";
|
||||
auto fdGCLock = open(fnGCLock.c_str(), O_RDWR | O_CREAT
|
||||
#ifndef _WIN32
|
||||
| O_CLOEXEC
|
||||
|
@ -452,17 +446,17 @@ int LocalStore::getSchema()
|
|||
|
||||
void LocalStore::openDB(State & state, bool create)
|
||||
{
|
||||
if (create && readOnly) {
|
||||
if (create && config->readOnly) {
|
||||
throw Error("cannot create database while in read-only mode");
|
||||
}
|
||||
|
||||
if (access(dbDir.c_str(), R_OK | (readOnly ? 0 : W_OK)))
|
||||
if (access(dbDir.c_str(), R_OK | (config->readOnly ? 0 : W_OK)))
|
||||
throw SysError("Nix database directory '%1%' is not writable", dbDir);
|
||||
|
||||
/* Open the Nix database. */
|
||||
std::string dbPath = dbDir + "/db.sqlite";
|
||||
auto & db(state.db);
|
||||
auto openMode = readOnly ? SQLiteOpenMode::Immutable
|
||||
auto openMode = config->readOnly ? SQLiteOpenMode::Immutable
|
||||
: create ? SQLiteOpenMode::Normal
|
||||
: SQLiteOpenMode::NoCreate;
|
||||
state.db = SQLite(dbPath, openMode);
|
||||
|
@ -575,12 +569,12 @@ void LocalStore::makeStoreWritable()
|
|||
if (!isRootUser()) return;
|
||||
/* Check if /nix/store is on a read-only mount. */
|
||||
struct statvfs stat;
|
||||
if (statvfs(realStoreDir.get().c_str(), &stat) != 0)
|
||||
if (statvfs(config->realStoreDir.get().c_str(), &stat) != 0)
|
||||
throw SysError("getting info about the Nix store mount point");
|
||||
|
||||
if (stat.f_flag & ST_RDONLY) {
|
||||
if (mount(0, realStoreDir.get().c_str(), "none", MS_REMOUNT | MS_BIND, 0) == -1)
|
||||
throw SysError("remounting %1% writable", realStoreDir);
|
||||
if (mount(0, config->realStoreDir.get().c_str(), "none", MS_REMOUNT | MS_BIND, 0) == -1)
|
||||
throw SysError("remounting %1% writable", config->realStoreDir);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -920,7 +914,7 @@ StorePathSet LocalStore::querySubstitutablePaths(const StorePathSet & paths)
|
|||
for (auto & sub : getDefaultSubstituters()) {
|
||||
if (remaining.empty()) break;
|
||||
if (sub->storeDir != storeDir) continue;
|
||||
if (!sub->wantMassQuery) continue;
|
||||
if (!sub->config.wantMassQuery) continue;
|
||||
|
||||
auto valid = sub->queryValidPaths(remaining);
|
||||
|
||||
|
@ -1032,12 +1026,12 @@ const PublicKeys & LocalStore::getPublicKeys()
|
|||
|
||||
bool LocalStore::pathInfoIsUntrusted(const ValidPathInfo & info)
|
||||
{
|
||||
return requireSigs && !info.checkSignatures(*this, getPublicKeys());
|
||||
return config->requireSigs && !info.checkSignatures(*this, getPublicKeys());
|
||||
}
|
||||
|
||||
bool LocalStore::realisationIsUntrusted(const Realisation & realisation)
|
||||
{
|
||||
return requireSigs && !realisation.checkSignatures(getPublicKeys());
|
||||
return config->requireSigs && !realisation.checkSignatures(getPublicKeys());
|
||||
}
|
||||
|
||||
void LocalStore::addToStore(const ValidPathInfo & info, Source & source,
|
||||
|
@ -1334,7 +1328,7 @@ std::pair<std::filesystem::path, AutoCloseFD> LocalStore::createTempDirInStore()
|
|||
/* There is a slight possibility that `tmpDir' gets deleted by
|
||||
the GC between createTempDir() and when we acquire a lock on it.
|
||||
We'll repeat until 'tmpDir' exists and we've locked it. */
|
||||
tmpDirFn = createTempDir(realStoreDir, "tmp");
|
||||
tmpDirFn = createTempDir(config->realStoreDir, "tmp");
|
||||
tmpDirFd = openDirectory(tmpDirFn);
|
||||
if (!tmpDirFd) {
|
||||
continue;
|
||||
|
@ -1475,7 +1469,7 @@ LocalStore::VerificationResult LocalStore::verifyAllValidPaths(RepairFlag repair
|
|||
database and the filesystem) in the loop below, in order to catch
|
||||
invalid states.
|
||||
*/
|
||||
for (auto & i : DirectoryIterator{realStoreDir.to_string()}) {
|
||||
for (auto & i : DirectoryIterator{config->realStoreDir.get()}) {
|
||||
checkInterrupt();
|
||||
try {
|
||||
storePathsInStoreDir.insert({i.path().filename().string()});
|
||||
|
@ -1664,7 +1658,7 @@ void LocalStore::addBuildLog(const StorePath & drvPath, std::string_view log)
|
|||
|
||||
auto baseName = drvPath.to_string();
|
||||
|
||||
auto logPath = fmt("%s/%s/%s/%s.bz2", logDir, drvsLogDir, baseName.substr(0, 2), baseName.substr(2));
|
||||
auto logPath = fmt("%s/%s/%s/%s.bz2", config->logDir, drvsLogDir, baseName.substr(0, 2), baseName.substr(2));
|
||||
|
||||
if (pathExists(logPath)) return;
|
||||
|
||||
|
@ -1682,6 +1676,6 @@ std::optional<std::string> LocalStore::getVersion()
|
|||
return nixVersion;
|
||||
}
|
||||
|
||||
static RegisterStoreImplementation<LocalStore, LocalStoreConfig> regLocalStore;
|
||||
static RegisterStoreImplementation<LocalStore::Config> regLocalStore;
|
||||
|
||||
} // namespace nix
|
||||
|
|
|
@ -313,6 +313,7 @@ sources = files(
|
|||
'ssh-store.cc',
|
||||
'ssh.cc',
|
||||
'store-api.cc',
|
||||
'store-dir-config.cc',
|
||||
'store-reference.cc',
|
||||
'uds-remote-store.cc',
|
||||
'worker-protocol-connection.cc',
|
||||
|
|
|
@ -101,7 +101,7 @@ void LocalStore::optimisePath_(Activity * act, OptimiseStats & stats,
|
|||
/* HFS/macOS has some undocumented security feature disabling hardlinking for
|
||||
special files within .app dirs. Known affected paths include
|
||||
*.app/Contents/{PkgInfo,Resources/\*.lproj,_CodeSignature} and .DS_Store.
|
||||
See https://github.com/NixOS/nix/issues/1443 and
|
||||
See https://github.com/NixOS/nix/issues/1443 and
|
||||
https://github.com/NixOS/nix/pull/2230 for more discussion. */
|
||||
|
||||
if (std::regex_search(path, std::regex("\\.app/Contents/.+$")))
|
||||
|
@ -216,14 +216,14 @@ void LocalStore::optimisePath_(Activity * act, OptimiseStats & stats,
|
|||
the store itself (we don't want or need to mess with its
|
||||
permissions). */
|
||||
const Path dirOfPath(dirOf(path));
|
||||
bool mustToggle = dirOfPath != realStoreDir.get();
|
||||
bool mustToggle = dirOfPath != config->realStoreDir.get();
|
||||
if (mustToggle) makeWritable(dirOfPath);
|
||||
|
||||
/* When we're done, make the directory read-only again and reset
|
||||
its timestamp back to 0. */
|
||||
MakeReadOnly makeReadOnly(mustToggle ? dirOfPath : "");
|
||||
|
||||
std::filesystem::path tempLink = fmt("%1%/.tmp-link-%2%-%3%", realStoreDir, getpid(), rand());
|
||||
std::filesystem::path tempLink = fmt("%1%/.tmp-link-%2%-%3%", config->realStoreDir, getpid(), rand());
|
||||
|
||||
try {
|
||||
std::filesystem::create_hard_link(linkPath, tempLink);
|
||||
|
@ -285,7 +285,7 @@ void LocalStore::optimiseStore(OptimiseStats & stats)
|
|||
if (!isValidPath(i)) continue; /* path was GC'ed, probably */
|
||||
{
|
||||
Activity act(*logger, lvlTalkative, actUnknown, fmt("optimising path '%s'", printStorePath(i)));
|
||||
optimisePath_(&act, stats, realStoreDir + "/" + std::string(i.to_string()), inodeHash, NoRepair);
|
||||
optimisePath_(&act, stats, config->realStoreDir + "/" + std::string(i.to_string()), inodeHash, NoRepair);
|
||||
}
|
||||
done++;
|
||||
act.progress(done, paths.size());
|
||||
|
|
|
@ -75,7 +75,7 @@ StorePath StorePath::random(std::string_view name)
|
|||
return StorePath(Hash::random(HashAlgorithm::SHA1), name);
|
||||
}
|
||||
|
||||
StorePath StoreDirConfig::parseStorePath(std::string_view path) const
|
||||
StorePath MixStoreDirMethods::parseStorePath(std::string_view path) const
|
||||
{
|
||||
// On Windows, `/nix/store` is not a canonical path. More broadly it
|
||||
// is unclear whether this function should be using the native
|
||||
|
@ -94,7 +94,7 @@ StorePath StoreDirConfig::parseStorePath(std::string_view path) const
|
|||
return StorePath(baseNameOf(p));
|
||||
}
|
||||
|
||||
std::optional<StorePath> StoreDirConfig::maybeParseStorePath(std::string_view path) const
|
||||
std::optional<StorePath> MixStoreDirMethods::maybeParseStorePath(std::string_view path) const
|
||||
{
|
||||
try {
|
||||
return parseStorePath(path);
|
||||
|
@ -103,24 +103,24 @@ std::optional<StorePath> StoreDirConfig::maybeParseStorePath(std::string_view pa
|
|||
}
|
||||
}
|
||||
|
||||
bool StoreDirConfig::isStorePath(std::string_view path) const
|
||||
bool MixStoreDirMethods::isStorePath(std::string_view path) const
|
||||
{
|
||||
return (bool) maybeParseStorePath(path);
|
||||
}
|
||||
|
||||
StorePathSet StoreDirConfig::parseStorePathSet(const PathSet & paths) const
|
||||
StorePathSet MixStoreDirMethods::parseStorePathSet(const PathSet & paths) const
|
||||
{
|
||||
StorePathSet res;
|
||||
for (auto & i : paths) res.insert(parseStorePath(i));
|
||||
return res;
|
||||
}
|
||||
|
||||
std::string StoreDirConfig::printStorePath(const StorePath & path) const
|
||||
std::string MixStoreDirMethods::printStorePath(const StorePath & path) const
|
||||
{
|
||||
return (storeDir + "/").append(path.to_string());
|
||||
}
|
||||
|
||||
PathSet StoreDirConfig::printStorePathSet(const StorePathSet & paths) const
|
||||
PathSet MixStoreDirMethods::printStorePathSet(const StorePathSet & paths) const
|
||||
{
|
||||
PathSet res;
|
||||
for (auto & i : paths) res.insert(printStorePath(i));
|
||||
|
|
|
@ -24,11 +24,11 @@
|
|||
namespace nix {
|
||||
|
||||
/* TODO: Separate these store types into different files, give them better names */
|
||||
RemoteStore::RemoteStore(const Params & params)
|
||||
: RemoteStoreConfig(params)
|
||||
, Store(params)
|
||||
RemoteStore::RemoteStore(const Config & config)
|
||||
: Store{config}
|
||||
, config{config}
|
||||
, connections(make_ref<Pool<Connection>>(
|
||||
std::max(1, maxConnections.get()),
|
||||
std::max(1, config.maxConnections.get()),
|
||||
[this]() {
|
||||
auto conn = openConnectionWrapper();
|
||||
try {
|
||||
|
@ -44,7 +44,7 @@ RemoteStore::RemoteStore(const Params & params)
|
|||
r->to.good()
|
||||
&& r->from.good()
|
||||
&& std::chrono::duration_cast<std::chrono::seconds>(
|
||||
std::chrono::steady_clock::now() - r->startTime).count() < maxConnectionAge;
|
||||
std::chrono::steady_clock::now() - r->startTime).count() < this->config.maxConnectionAge;
|
||||
}
|
||||
))
|
||||
{
|
||||
|
@ -122,7 +122,7 @@ void RemoteStore::setOptions(Connection & conn)
|
|||
<< settings.useSubstitutes;
|
||||
|
||||
if (GET_PROTOCOL_MINOR(conn.protoVersion) >= 12) {
|
||||
std::map<std::string, Config::SettingInfo> overrides;
|
||||
std::map<std::string, nix::Config::SettingInfo> overrides;
|
||||
settings.getSettings(overrides, true); // libstore settings
|
||||
fileTransferSettings.getSettings(overrides, true);
|
||||
overrides.erase(settings.keepFailed.name);
|
||||
|
|
|
@ -30,32 +30,23 @@ bool RestrictionContext::isAllowed(const DerivedPath & req)
|
|||
return isAllowed(pathPartOfReq(req));
|
||||
}
|
||||
|
||||
struct RestrictedStoreConfig : virtual LocalFSStoreConfig
|
||||
{
|
||||
using LocalFSStoreConfig::LocalFSStoreConfig;
|
||||
const std::string name() override
|
||||
{
|
||||
return "Restricted Store";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A wrapper around LocalStore that only allows building/querying of
|
||||
* paths that are in the input closures of the build or were added via
|
||||
* recursive Nix calls.
|
||||
*/
|
||||
struct RestrictedStore : public virtual RestrictedStoreConfig, public virtual IndirectRootStore, public virtual GcStore
|
||||
struct RestrictedStore : public virtual IndirectRootStore, public virtual GcStore
|
||||
{
|
||||
ref<const LocalStore::Config> config;
|
||||
|
||||
ref<LocalStore> next;
|
||||
|
||||
RestrictionContext & goal;
|
||||
|
||||
RestrictedStore(const Params & params, ref<LocalStore> next, RestrictionContext & goal)
|
||||
: StoreConfig(params)
|
||||
, LocalFSStoreConfig(params)
|
||||
, RestrictedStoreConfig(params)
|
||||
, Store(params)
|
||||
, LocalFSStore(params)
|
||||
RestrictedStore(ref<LocalStore::Config> config, ref<LocalStore> next, RestrictionContext & goal)
|
||||
: Store{*config}
|
||||
, LocalFSStore{*config}
|
||||
, config{config}
|
||||
, next(next)
|
||||
, goal(goal)
|
||||
{
|
||||
|
@ -63,7 +54,7 @@ struct RestrictedStore : public virtual RestrictedStoreConfig, public virtual In
|
|||
|
||||
Path getRealStoreDir() override
|
||||
{
|
||||
return next->realStoreDir;
|
||||
return next->config->realStoreDir;
|
||||
}
|
||||
|
||||
std::string getUri() override
|
||||
|
@ -176,9 +167,9 @@ struct RestrictedStore : public virtual RestrictedStoreConfig, public virtual In
|
|||
}
|
||||
};
|
||||
|
||||
ref<Store> makeRestrictedStore(const Store::Params & params, ref<LocalStore> next, RestrictionContext & context)
|
||||
ref<Store> makeRestrictedStore(ref<LocalStore::Config> config, ref<LocalStore> next, RestrictionContext & context)
|
||||
{
|
||||
return make_ref<RestrictedStore>(params, next, context);
|
||||
return make_ref<RestrictedStore>(config, next, context);
|
||||
}
|
||||
|
||||
StorePathSet RestrictedStore::queryAllValidPaths()
|
||||
|
|
|
@ -235,11 +235,6 @@ S3Helper::FileTransferResult S3Helper::getObject(
|
|||
return res;
|
||||
}
|
||||
|
||||
S3BinaryCacheStore::S3BinaryCacheStore(const Params & params)
|
||||
: BinaryCacheStoreConfig(params)
|
||||
, BinaryCacheStore(params)
|
||||
{ }
|
||||
|
||||
|
||||
S3BinaryCacheStoreConfig::S3BinaryCacheStoreConfig(
|
||||
std::string_view uriScheme,
|
||||
|
@ -258,6 +253,12 @@ S3BinaryCacheStoreConfig::S3BinaryCacheStoreConfig(
|
|||
throw UsageError("`%s` store requires a bucket name in its Store URI", uriScheme);
|
||||
}
|
||||
|
||||
|
||||
S3BinaryCacheStore::S3BinaryCacheStore(ref<Config> config)
|
||||
: BinaryCacheStore(*config)
|
||||
, config{config}
|
||||
{ }
|
||||
|
||||
std::string S3BinaryCacheStoreConfig::doc()
|
||||
{
|
||||
return
|
||||
|
@ -266,40 +267,37 @@ std::string S3BinaryCacheStoreConfig::doc()
|
|||
}
|
||||
|
||||
|
||||
struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual S3BinaryCacheStore
|
||||
struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStore
|
||||
{
|
||||
Stats stats;
|
||||
|
||||
S3Helper s3Helper;
|
||||
|
||||
S3BinaryCacheStoreImpl(
|
||||
std::string_view uriScheme,
|
||||
std::string_view bucketName,
|
||||
const Params & params)
|
||||
: StoreConfig(params)
|
||||
, BinaryCacheStoreConfig(params)
|
||||
, S3BinaryCacheStoreConfig(uriScheme, bucketName, params)
|
||||
, Store(params)
|
||||
, BinaryCacheStore(params)
|
||||
, S3BinaryCacheStore(params)
|
||||
, s3Helper(profile, region, scheme, endpoint)
|
||||
S3BinaryCacheStoreImpl(ref<Config> config)
|
||||
: Store{*config}
|
||||
, BinaryCacheStore{*config}
|
||||
, S3BinaryCacheStore{config}
|
||||
, s3Helper(config->profile, config->region, config->scheme, config->endpoint)
|
||||
{
|
||||
diskCache = getNarInfoDiskCache();
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
std::string getUri() override
|
||||
{
|
||||
return "s3://" + bucketName;
|
||||
return "s3://" + config->bucketName;
|
||||
}
|
||||
|
||||
void init() override
|
||||
{
|
||||
if (auto cacheInfo = diskCache->upToDateCacheExists(getUri())) {
|
||||
wantMassQuery.setDefault(cacheInfo->wantMassQuery);
|
||||
priority.setDefault(cacheInfo->priority);
|
||||
config->wantMassQuery.setDefault(cacheInfo->wantMassQuery);
|
||||
config->priority.setDefault(cacheInfo->priority);
|
||||
} else {
|
||||
BinaryCacheStore::init();
|
||||
diskCache->createCache(getUri(), storeDir, wantMassQuery, priority);
|
||||
diskCache->createCache(
|
||||
getUri(), config->storeDir, config->wantMassQuery, config->priority);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -328,7 +326,7 @@ struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual
|
|||
|
||||
auto res = s3Helper.client->HeadObject(
|
||||
Aws::S3::Model::HeadObjectRequest()
|
||||
.WithBucket(bucketName)
|
||||
.WithBucket(config->bucketName)
|
||||
.WithKey(path));
|
||||
|
||||
if (!res.IsSuccess()) {
|
||||
|
@ -372,7 +370,7 @@ struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual
|
|||
const std::string & mimeType,
|
||||
const std::string & contentEncoding)
|
||||
{
|
||||
std::string uri = "s3://" + bucketName + "/" + path;
|
||||
std::string uri = "s3://" + config->bucketName + "/" + path;
|
||||
Activity act(*logger, lvlTalkative, actFileTransfer,
|
||||
fmt("uploading '%s'", uri),
|
||||
Logger::Fields{uri}, getCurActivity());
|
||||
|
@ -387,11 +385,11 @@ struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual
|
|||
|
||||
std::call_once(transferManagerCreated, [&]()
|
||||
{
|
||||
if (multipartUpload) {
|
||||
if (config->multipartUpload) {
|
||||
TransferManagerConfiguration transferConfig(executor.get());
|
||||
|
||||
transferConfig.s3Client = s3Helper.client;
|
||||
transferConfig.bufferSize = bufferSize;
|
||||
transferConfig.bufferSize = config->bufferSize;
|
||||
|
||||
transferConfig.uploadProgressCallback =
|
||||
[](const TransferManager * transferManager,
|
||||
|
@ -421,6 +419,8 @@ struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual
|
|||
|
||||
auto now1 = std::chrono::steady_clock::now();
|
||||
|
||||
auto & bucketName = config->bucketName;
|
||||
|
||||
if (transferManager) {
|
||||
|
||||
if (contentEncoding != "")
|
||||
|
@ -508,12 +508,12 @@ struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual
|
|||
return std::make_shared<std::stringstream>(std::move(compressed));
|
||||
};
|
||||
|
||||
if (narinfoCompression != "" && hasSuffix(path, ".narinfo"))
|
||||
uploadFile(path, compress(narinfoCompression), mimeType, narinfoCompression);
|
||||
else if (lsCompression != "" && hasSuffix(path, ".ls"))
|
||||
uploadFile(path, compress(lsCompression), mimeType, lsCompression);
|
||||
else if (logCompression != "" && hasPrefix(path, "log/"))
|
||||
uploadFile(path, compress(logCompression), mimeType, logCompression);
|
||||
if (config->narinfoCompression != "" && hasSuffix(path, ".narinfo"))
|
||||
uploadFile(path, compress(config->narinfoCompression), mimeType, config->narinfoCompression);
|
||||
else if (config->lsCompression != "" && hasSuffix(path, ".ls"))
|
||||
uploadFile(path, compress(config->lsCompression), mimeType, config->lsCompression);
|
||||
else if (config->logCompression != "" && hasPrefix(path, "log/"))
|
||||
uploadFile(path, compress(config->logCompression), mimeType, config->logCompression);
|
||||
else
|
||||
uploadFile(path, istream, mimeType, "");
|
||||
}
|
||||
|
@ -523,14 +523,14 @@ struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual
|
|||
stats.get++;
|
||||
|
||||
// FIXME: stream output to sink.
|
||||
auto res = s3Helper.getObject(bucketName, path);
|
||||
auto res = s3Helper.getObject(config->bucketName, path);
|
||||
|
||||
stats.getBytes += res.data ? res.data->size() : 0;
|
||||
stats.getTimeMs += res.durationMs;
|
||||
|
||||
if (res.data) {
|
||||
printTalkative("downloaded 's3://%s/%s' (%d bytes) in %d ms",
|
||||
bucketName, path, res.data->size(), res.durationMs);
|
||||
config->bucketName, path, res.data->size(), res.durationMs);
|
||||
|
||||
sink(*res.data);
|
||||
} else
|
||||
|
@ -542,6 +542,8 @@ struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual
|
|||
StorePathSet paths;
|
||||
std::string marker;
|
||||
|
||||
auto & bucketName = config->bucketName;
|
||||
|
||||
do {
|
||||
debug("listing bucket 's3://%s' from key '%s'...", bucketName, marker);
|
||||
|
||||
|
@ -580,7 +582,15 @@ struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual
|
|||
}
|
||||
};
|
||||
|
||||
static RegisterStoreImplementation<S3BinaryCacheStoreImpl, S3BinaryCacheStoreConfig> regS3BinaryCacheStore;
|
||||
ref<Store> S3BinaryCacheStoreImpl::Config::openStore() const
|
||||
{
|
||||
return make_ref<S3BinaryCacheStoreImpl>(ref{
|
||||
// FIXME we shouldn't actually need a mutable config
|
||||
std::const_pointer_cast<S3BinaryCacheStore::Config>(shared_from_this())
|
||||
});
|
||||
}
|
||||
|
||||
static RegisterStoreImplementation<S3BinaryCacheStoreImpl::Config> regS3BinaryCacheStore;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -14,12 +14,13 @@ SSHStoreConfig::SSHStoreConfig(
|
|||
std::string_view scheme,
|
||||
std::string_view authority,
|
||||
const Params & params)
|
||||
: StoreConfig(params)
|
||||
, RemoteStoreConfig(params)
|
||||
, CommonSSHStoreConfig(scheme, authority, params)
|
||||
: Store::Config{params}
|
||||
, RemoteStore::Config{params}
|
||||
, CommonSSHStoreConfig{scheme, authority, params}
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
std::string SSHStoreConfig::doc()
|
||||
{
|
||||
return
|
||||
|
@ -27,21 +28,18 @@ std::string SSHStoreConfig::doc()
|
|||
;
|
||||
}
|
||||
|
||||
class SSHStore : public virtual SSHStoreConfig, public virtual RemoteStore
|
||||
{
|
||||
public:
|
||||
|
||||
SSHStore(
|
||||
std::string_view scheme,
|
||||
std::string_view host,
|
||||
const Params & params)
|
||||
: StoreConfig(params)
|
||||
, RemoteStoreConfig(params)
|
||||
, CommonSSHStoreConfig(scheme, host, params)
|
||||
, SSHStoreConfig(scheme, host, params)
|
||||
, Store(params)
|
||||
, RemoteStore(params)
|
||||
, master(createSSHMaster(
|
||||
struct SSHStore : virtual RemoteStore
|
||||
{
|
||||
using Config = SSHStoreConfig;
|
||||
|
||||
ref<const Config> config;
|
||||
|
||||
SSHStore(ref<const Config> config)
|
||||
: Store{*config}
|
||||
, RemoteStore{*config}
|
||||
, config{config}
|
||||
, master(config->createSSHMaster(
|
||||
// Use SSH master only if using more than 1 connection.
|
||||
connections->capacity() > 1))
|
||||
{
|
||||
|
@ -49,7 +47,7 @@ public:
|
|||
|
||||
std::string getUri() override
|
||||
{
|
||||
return *uriSchemes().begin() + "://" + host;
|
||||
return *Config::uriSchemes().begin() + "://" + host;
|
||||
}
|
||||
|
||||
// FIXME extend daemon protocol, move implementation to RemoteStore
|
||||
|
@ -101,7 +99,7 @@ MountedSSHStoreConfig::MountedSSHStoreConfig(std::string_view scheme, std::strin
|
|||
: StoreConfig(params)
|
||||
, RemoteStoreConfig(params)
|
||||
, CommonSSHStoreConfig(scheme, host, params)
|
||||
, SSHStoreConfig(params)
|
||||
, SSHStoreConfig(scheme, host, params)
|
||||
, LocalFSStoreConfig(params)
|
||||
{
|
||||
}
|
||||
|
@ -128,35 +126,21 @@ std::string MountedSSHStoreConfig::doc()
|
|||
* The difference lies in how they manage GC roots. See addPermRoot
|
||||
* below for details.
|
||||
*/
|
||||
class MountedSSHStore : public virtual MountedSSHStoreConfig, public virtual SSHStore, public virtual LocalFSStore
|
||||
struct MountedSSHStore : virtual SSHStore, virtual LocalFSStore
|
||||
{
|
||||
public:
|
||||
using Config = MountedSSHStoreConfig;
|
||||
|
||||
MountedSSHStore(
|
||||
std::string_view scheme,
|
||||
std::string_view host,
|
||||
const Params & params)
|
||||
: StoreConfig(params)
|
||||
, RemoteStoreConfig(params)
|
||||
, CommonSSHStoreConfig(scheme, host, params)
|
||||
, SSHStoreConfig(params)
|
||||
, LocalFSStoreConfig(params)
|
||||
, MountedSSHStoreConfig(params)
|
||||
, Store(params)
|
||||
, RemoteStore(params)
|
||||
, SSHStore(scheme, host, params)
|
||||
, LocalFSStore(params)
|
||||
MountedSSHStore(ref<const Config> config)
|
||||
: Store{*config}
|
||||
, RemoteStore{*config}
|
||||
, SSHStore{config}
|
||||
, LocalFSStore{*config}
|
||||
{
|
||||
extraRemoteProgramArgs = {
|
||||
"--process-ops",
|
||||
};
|
||||
}
|
||||
|
||||
std::string getUri() override
|
||||
{
|
||||
return *uriSchemes().begin() + "://" + host;
|
||||
}
|
||||
|
||||
void narFromPath(const StorePath & path, Sink & sink) override
|
||||
{
|
||||
return LocalFSStore::narFromPath(path, sink);
|
||||
|
@ -198,14 +182,26 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
ref<Store> SSHStore::Config::openStore() const {
|
||||
return make_ref<SSHStore>(ref{shared_from_this()});
|
||||
}
|
||||
|
||||
ref<Store> MountedSSHStore::Config::openStore() const {
|
||||
return make_ref<MountedSSHStore>(ref{
|
||||
std::dynamic_pointer_cast<const MountedSSHStore::Config>(shared_from_this())
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
ref<RemoteStore::Connection> SSHStore::openConnection()
|
||||
{
|
||||
auto conn = make_ref<Connection>();
|
||||
Strings command = remoteProgram.get();
|
||||
Strings command = config->remoteProgram.get();
|
||||
command.push_back("--stdio");
|
||||
if (remoteStore.get() != "") {
|
||||
if (config->remoteStore.get() != "") {
|
||||
command.push_back("--store");
|
||||
command.push_back(remoteStore.get());
|
||||
command.push_back(config->remoteStore.get());
|
||||
}
|
||||
command.insert(command.end(),
|
||||
extraRemoteProgramArgs.begin(), extraRemoteProgramArgs.end());
|
||||
|
@ -215,7 +211,7 @@ ref<RemoteStore::Connection> SSHStore::openConnection()
|
|||
return conn;
|
||||
}
|
||||
|
||||
static RegisterStoreImplementation<SSHStore, SSHStoreConfig> regSSHStore;
|
||||
static RegisterStoreImplementation<MountedSSHStore, MountedSSHStoreConfig> regMountedSSHStore;
|
||||
static RegisterStoreImplementation<SSHStore::Config> regSSHStore;
|
||||
static RegisterStoreImplementation<MountedSSHStore::Config> regMountedSSHStore;
|
||||
|
||||
}
|
||||
|
|
|
@ -29,13 +29,13 @@ using json = nlohmann::json;
|
|||
namespace nix {
|
||||
|
||||
|
||||
bool StoreDirConfig::isInStore(PathView path) const
|
||||
bool MixStoreDirMethods::isInStore(PathView path) const
|
||||
{
|
||||
return isInDir(path, storeDir);
|
||||
}
|
||||
|
||||
|
||||
std::pair<StorePath, Path> StoreDirConfig::toStorePath(PathView path) const
|
||||
std::pair<StorePath, Path> MixStoreDirMethods::toStorePath(PathView path) const
|
||||
{
|
||||
if (!isInStore(path))
|
||||
throw Error("path '%1%' is not in the Nix store", path);
|
||||
|
@ -77,7 +77,7 @@ to match.
|
|||
*/
|
||||
|
||||
|
||||
StorePath StoreDirConfig::makeStorePath(std::string_view type,
|
||||
StorePath MixStoreDirMethods::makeStorePath(std::string_view type,
|
||||
std::string_view hash, std::string_view name) const
|
||||
{
|
||||
/* e.g., "source:sha256:1abc...:/nix/store:foo.tar.gz" */
|
||||
|
@ -88,14 +88,14 @@ StorePath StoreDirConfig::makeStorePath(std::string_view type,
|
|||
}
|
||||
|
||||
|
||||
StorePath StoreDirConfig::makeStorePath(std::string_view type,
|
||||
StorePath MixStoreDirMethods::makeStorePath(std::string_view type,
|
||||
const Hash & hash, std::string_view name) const
|
||||
{
|
||||
return makeStorePath(type, hash.to_string(HashFormat::Base16, true), name);
|
||||
}
|
||||
|
||||
|
||||
StorePath StoreDirConfig::makeOutputPath(std::string_view id,
|
||||
StorePath MixStoreDirMethods::makeOutputPath(std::string_view id,
|
||||
const Hash & hash, std::string_view name) const
|
||||
{
|
||||
return makeStorePath("output:" + std::string { id }, hash, outputPathName(name, id));
|
||||
|
@ -106,7 +106,7 @@ StorePath StoreDirConfig::makeOutputPath(std::string_view id,
|
|||
hacky, but we can't put them in, say, <s2> (per the grammar above)
|
||||
since that would be ambiguous. */
|
||||
static std::string makeType(
|
||||
const StoreDirConfig & store,
|
||||
const MixStoreDirMethods & store,
|
||||
std::string && type,
|
||||
const StoreReferences & references)
|
||||
{
|
||||
|
@ -119,7 +119,7 @@ static std::string makeType(
|
|||
}
|
||||
|
||||
|
||||
StorePath StoreDirConfig::makeFixedOutputPath(std::string_view name, const FixedOutputInfo & info) const
|
||||
StorePath MixStoreDirMethods::makeFixedOutputPath(std::string_view name, const FixedOutputInfo & info) const
|
||||
{
|
||||
if (info.method == FileIngestionMethod::Git && info.hash.algo != HashAlgorithm::SHA1)
|
||||
throw Error("Git file ingestion must use SHA-1 hash");
|
||||
|
@ -141,7 +141,7 @@ StorePath StoreDirConfig::makeFixedOutputPath(std::string_view name, const Fixed
|
|||
}
|
||||
|
||||
|
||||
StorePath StoreDirConfig::makeFixedOutputPathFromCA(std::string_view name, const ContentAddressWithReferences & ca) const
|
||||
StorePath MixStoreDirMethods::makeFixedOutputPathFromCA(std::string_view name, const ContentAddressWithReferences & ca) const
|
||||
{
|
||||
// New template
|
||||
return std::visit(overloaded {
|
||||
|
@ -162,7 +162,7 @@ StorePath StoreDirConfig::makeFixedOutputPathFromCA(std::string_view name, const
|
|||
}
|
||||
|
||||
|
||||
std::pair<StorePath, Hash> StoreDirConfig::computeStorePath(
|
||||
std::pair<StorePath, Hash> MixStoreDirMethods::computeStorePath(
|
||||
std::string_view name,
|
||||
const SourcePath & path,
|
||||
ContentAddressMethod method,
|
||||
|
@ -420,7 +420,7 @@ ValidPathInfo Store::addToStoreSlow(
|
|||
return info;
|
||||
}
|
||||
|
||||
StringSet StoreConfig::getDefaultSystemFeatures()
|
||||
StringSet Store::Config::getDefaultSystemFeatures()
|
||||
{
|
||||
auto res = settings.systemFeatures.get();
|
||||
|
||||
|
@ -433,9 +433,10 @@ StringSet StoreConfig::getDefaultSystemFeatures()
|
|||
return res;
|
||||
}
|
||||
|
||||
Store::Store(const Params & params)
|
||||
: StoreConfig(params)
|
||||
, state({(size_t) pathInfoCacheSize})
|
||||
Store::Store(const Store::Config & config)
|
||||
: MixStoreDirMethods{config}
|
||||
, config{config}
|
||||
, state({(size_t) config.pathInfoCacheSize})
|
||||
{
|
||||
assertLibStoreInitialized();
|
||||
}
|
||||
|
@ -1205,7 +1206,7 @@ std::optional<ValidPathInfo> decodeValidPathInfo(const Store & store, std::istre
|
|||
}
|
||||
|
||||
|
||||
std::string StoreDirConfig::showPaths(const StorePathSet & paths)
|
||||
std::string MixStoreDirMethods::showPaths(const StorePathSet & paths) const
|
||||
{
|
||||
std::string s;
|
||||
for (auto & i : paths) {
|
||||
|
@ -1312,7 +1313,7 @@ void Store::signRealisation(Realisation & realisation)
|
|||
namespace nix {
|
||||
|
||||
ref<Store> openStore(const std::string & uri,
|
||||
const Store::Params & extraParams)
|
||||
const Store::Config::Params & extraParams)
|
||||
{
|
||||
return openStore(StoreReference::parse(uri, extraParams));
|
||||
}
|
||||
|
@ -1321,13 +1322,13 @@ ref<Store> openStore(StoreReference && storeURI)
|
|||
{
|
||||
auto & params = storeURI.params;
|
||||
|
||||
auto store = std::visit(overloaded {
|
||||
[&](const StoreReference::Auto &) -> std::shared_ptr<Store> {
|
||||
auto storeConfig = std::visit(overloaded {
|
||||
[&](const StoreReference::Auto &) -> ref<StoreConfig> {
|
||||
auto stateDir = getOr(params, "state", settings.nixStateDir);
|
||||
if (access(stateDir.c_str(), R_OK | W_OK) == 0)
|
||||
return std::make_shared<LocalStore>(params);
|
||||
return make_ref<LocalStore::Config>(params);
|
||||
else if (pathExists(settings.nixDaemonSocketFile))
|
||||
return std::make_shared<UDSRemoteStore>(params);
|
||||
return make_ref<UDSRemoteStore::Config>(params);
|
||||
#ifdef __linux__
|
||||
else if (!pathExists(stateDir)
|
||||
&& params.empty()
|
||||
|
@ -1343,31 +1344,33 @@ ref<Store> openStore(StoreReference && storeURI)
|
|||
try {
|
||||
createDirs(chrootStore);
|
||||
} catch (SystemError & e) {
|
||||
return std::make_shared<LocalStore>(params);
|
||||
return make_ref<LocalStore::Config>(params);
|
||||
}
|
||||
warn("'%s' does not exist, so Nix will use '%s' as a chroot store", stateDir, chrootStore);
|
||||
} else
|
||||
debug("'%s' does not exist, so Nix will use '%s' as a chroot store", stateDir, chrootStore);
|
||||
return std::make_shared<LocalStore>("local", chrootStore, params);
|
||||
return make_ref<LocalStore::Config>("local", chrootStore, params);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
return std::make_shared<LocalStore>(params);
|
||||
return make_ref<LocalStore::Config>(params);
|
||||
},
|
||||
[&](const StoreReference::Specified & g) {
|
||||
for (const auto & implem : Implementations::registered())
|
||||
for (const auto & [storeName, implem] : Implementations::registered())
|
||||
if (implem.uriSchemes.count(g.scheme))
|
||||
return implem.create(g.scheme, g.authority, params);
|
||||
return implem.parseConfig(g.scheme, g.authority, params);
|
||||
|
||||
throw Error("don't know how to open Nix store with scheme '%s'", g.scheme);
|
||||
},
|
||||
}, storeURI.variant);
|
||||
|
||||
experimentalFeatureSettings.require(store->experimentalFeature());
|
||||
store->warnUnknownSettings();
|
||||
experimentalFeatureSettings.require(storeConfig->experimentalFeature());
|
||||
storeConfig->warnUnknownSettings();
|
||||
|
||||
auto store = storeConfig->openStore();
|
||||
store->init();
|
||||
|
||||
return ref<Store> { store };
|
||||
return store;
|
||||
}
|
||||
|
||||
std::list<ref<Store>> getDefaultSubstituters()
|
||||
|
@ -1390,7 +1393,7 @@ std::list<ref<Store>> getDefaultSubstituters()
|
|||
addStore(uri);
|
||||
|
||||
stores.sort([](ref<Store> & a, ref<Store> & b) {
|
||||
return a->priority < b->priority;
|
||||
return a->config.priority < b->config.priority;
|
||||
});
|
||||
|
||||
return stores;
|
||||
|
@ -1399,9 +1402,9 @@ std::list<ref<Store>> getDefaultSubstituters()
|
|||
return stores;
|
||||
}
|
||||
|
||||
std::vector<StoreFactory> & Implementations::registered()
|
||||
Implementations::Map & Implementations::registered()
|
||||
{
|
||||
static std::vector<StoreFactory> registered;
|
||||
static Map registered;
|
||||
return registered;
|
||||
}
|
||||
|
||||
|
|
13
src/libstore/store-dir-config.cc
Normal file
13
src/libstore/store-dir-config.cc
Normal file
|
@ -0,0 +1,13 @@
|
|||
#include "nix/store/store-dir-config.hh"
|
||||
#include "nix/util/util.hh"
|
||||
#include "nix/store/globals.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
StoreDirConfig::StoreDirConfig(const Params & params)
|
||||
: StoreDirConfigItself(params)
|
||||
, MixStoreDirMethods{storeDir_}
|
||||
{
|
||||
}
|
||||
|
||||
}
|
|
@ -20,13 +20,13 @@ namespace nix {
|
|||
UDSRemoteStoreConfig::UDSRemoteStoreConfig(
|
||||
std::string_view scheme,
|
||||
std::string_view authority,
|
||||
const Params & params)
|
||||
: StoreConfig(params)
|
||||
, LocalFSStoreConfig(params)
|
||||
, RemoteStoreConfig(params)
|
||||
const StoreReference::Params & params)
|
||||
: Store::Config{params}
|
||||
, LocalFSStore::Config{params}
|
||||
, RemoteStore::Config{params}
|
||||
, path{authority.empty() ? settings.nixDaemonSocketFile : authority}
|
||||
{
|
||||
if (scheme != UDSRemoteStoreConfig::scheme) {
|
||||
if (uriSchemes().count(scheme) == 0) {
|
||||
throw UsageError("Scheme must be 'unix'");
|
||||
}
|
||||
}
|
||||
|
@ -44,32 +44,30 @@ std::string UDSRemoteStoreConfig::doc()
|
|||
// empty string will later default to the same nixDaemonSocketFile. Why
|
||||
// don't we just wire it all through? I believe there are cases where it
|
||||
// will live reload so we want to continue to account for that.
|
||||
UDSRemoteStore::UDSRemoteStore(const Params & params)
|
||||
: UDSRemoteStore(scheme, "", params)
|
||||
{}
|
||||
UDSRemoteStoreConfig::UDSRemoteStoreConfig(const Params & params)
|
||||
: UDSRemoteStoreConfig(*uriSchemes().begin(), "", params)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
UDSRemoteStore::UDSRemoteStore(std::string_view scheme, std::string_view authority, const Params & params)
|
||||
: StoreConfig(params)
|
||||
, LocalFSStoreConfig(params)
|
||||
, RemoteStoreConfig(params)
|
||||
, UDSRemoteStoreConfig(scheme, authority, params)
|
||||
, Store(params)
|
||||
, LocalFSStore(params)
|
||||
, RemoteStore(params)
|
||||
UDSRemoteStore::UDSRemoteStore(ref<const Config> config)
|
||||
: Store{*config}
|
||||
, LocalFSStore{*config}
|
||||
, RemoteStore{*config}
|
||||
, config{config}
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
std::string UDSRemoteStore::getUri()
|
||||
{
|
||||
return path == settings.nixDaemonSocketFile
|
||||
return config->path == settings.nixDaemonSocketFile
|
||||
? // FIXME: Not clear why we return daemon here and not default
|
||||
// to settings.nixDaemonSocketFile
|
||||
//
|
||||
// unix:// with no path also works. Change what we return?
|
||||
"daemon"
|
||||
: std::string(scheme) + "://" + path;
|
||||
: std::string(*Config::uriSchemes().begin()) + "://" + config->path;
|
||||
}
|
||||
|
||||
|
||||
|
@ -86,7 +84,7 @@ ref<RemoteStore::Connection> UDSRemoteStore::openConnection()
|
|||
/* Connect to a daemon that does the privileged work for us. */
|
||||
conn->fd = createUnixDomainSocket();
|
||||
|
||||
nix::connect(toSocket(conn->fd.get()), path);
|
||||
nix::connect(toSocket(conn->fd.get()), config->path);
|
||||
|
||||
conn->from.fd = conn->fd.get();
|
||||
conn->to.fd = conn->fd.get();
|
||||
|
@ -106,6 +104,11 @@ void UDSRemoteStore::addIndirectRoot(const Path & path)
|
|||
}
|
||||
|
||||
|
||||
static RegisterStoreImplementation<UDSRemoteStore, UDSRemoteStoreConfig> regUDSRemoteStore;
|
||||
ref<Store> UDSRemoteStore::Config::openStore() const {
|
||||
return make_ref<UDSRemoteStore>(ref{shared_from_this()});
|
||||
}
|
||||
|
||||
|
||||
static RegisterStoreImplementation<UDSRemoteStore::Config> regUDSRemoteStore;
|
||||
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
#include "store-config-private.hh"
|
||||
|
||||
#if HAVE_STATVFS
|
||||
#include <sys/statvfs.h>
|
||||
# include <sys/statvfs.h>
|
||||
#endif
|
||||
|
||||
/* Includes required for chroot support. */
|
||||
|
@ -60,9 +60,9 @@
|
|||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <spawn.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sandbox.h>
|
||||
# include <spawn.h>
|
||||
# include <sys/sysctl.h>
|
||||
# include <sandbox.h>
|
||||
|
||||
/* This definition is undocumented but depended upon by all major browsers. */
|
||||
extern "C" int sandbox_init_with_parameters(const char *profile, uint64_t flags, const char *const parameters[], char **errorbuf);
|
||||
|
@ -494,7 +494,7 @@ bool DerivationBuilderImpl::prepareBuild()
|
|||
}
|
||||
|
||||
auto & localStore = getLocalStore();
|
||||
if (localStore.storeDir != localStore.realStoreDir.get()) {
|
||||
if (localStore.storeDir != localStore.config->realStoreDir.get()) {
|
||||
#ifdef __linux__
|
||||
useChroot = true;
|
||||
#else
|
||||
|
@ -707,7 +707,7 @@ bool DerivationBuilderImpl::cleanupDecideWhetherDiskFull()
|
|||
auto & localStore = getLocalStore();
|
||||
uint64_t required = 8ULL * 1024 * 1024; // FIXME: make configurable
|
||||
struct statvfs st;
|
||||
if (statvfs(localStore.realStoreDir.get().c_str(), &st) == 0 &&
|
||||
if (statvfs(localStore.config->realStoreDir.get().c_str(), &st) == 0 &&
|
||||
(uint64_t) st.f_bavail * st.f_bsize < required)
|
||||
diskFull = true;
|
||||
if (statvfs(tmpDir.c_str(), &st) == 0 &&
|
||||
|
@ -871,7 +871,7 @@ void DerivationBuilderImpl::startBuilder()
|
|||
concatStringsSep(", ", drvOptions.getRequiredSystemFeatures(drv)),
|
||||
store.printStorePath(drvPath),
|
||||
settings.thisSystem,
|
||||
concatStringsSep<StringSet>(", ", store.systemFeatures));
|
||||
concatStringsSep<StringSet>(", ", store.config.systemFeatures));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1594,14 +1594,14 @@ void DerivationBuilderImpl::startDaemon()
|
|||
{
|
||||
experimentalFeatureSettings.require(Xp::RecursiveNix);
|
||||
|
||||
Store::Params params;
|
||||
params["path-info-cache-size"] = "0";
|
||||
params["store"] = store.storeDir;
|
||||
if (auto & optRoot = getLocalStore().rootDir.get())
|
||||
params["root"] = *optRoot;
|
||||
params["state"] = "/no-such-path";
|
||||
params["log"] = "/no-such-path";
|
||||
auto store = makeRestrictedStore(params,
|
||||
auto store = makeRestrictedStore(
|
||||
[&]{
|
||||
auto config = make_ref<LocalStore::Config>(*getLocalStore().config);
|
||||
config->pathInfoCacheSize = 0;
|
||||
config->stateDir = "/no-such-path";
|
||||
config->logDir = "/no-such-path";
|
||||
return config;
|
||||
}(),
|
||||
ref<LocalStore>(std::dynamic_pointer_cast<LocalStore>(this->store.shared_from_this())),
|
||||
*this);
|
||||
|
||||
|
@ -1946,7 +1946,7 @@ void DerivationBuilderImpl::runChild()
|
|||
createDirs(chrootRootDir + "/dev/shm");
|
||||
createDirs(chrootRootDir + "/dev/pts");
|
||||
ss.push_back("/dev/full");
|
||||
if (store.systemFeatures.get().count("kvm") && pathExists("/dev/kvm"))
|
||||
if (store.config.systemFeatures.get().count("kvm") && pathExists("/dev/kvm"))
|
||||
ss.push_back("/dev/kvm");
|
||||
ss.push_back("/dev/null");
|
||||
ss.push_back("/dev/random");
|
||||
|
|
|
@ -193,13 +193,12 @@ struct NixArgs : virtual MultiCommand, virtual MixCommonArgs, virtual RootArgs
|
|||
res["args"] = toJSON();
|
||||
|
||||
auto stores = nlohmann::json::object();
|
||||
for (auto & implem : Implementations::registered()) {
|
||||
auto storeConfig = implem.getConfig();
|
||||
auto storeName = storeConfig->name();
|
||||
for (auto & [storeName, implem] : Implementations::registered()) {
|
||||
auto & j = stores[storeName];
|
||||
j["doc"] = storeConfig->doc();
|
||||
j["settings"] = storeConfig->toJSON();
|
||||
j["experimentalFeature"] = storeConfig->experimentalFeature();
|
||||
j["doc"] = implem.doc;
|
||||
j["uri-schemes"] = implem.uriSchemes;
|
||||
j["settings"] = implem.getConfig()->toJSON();
|
||||
j["experimentalFeature"] = implem.experimentalFeature;
|
||||
}
|
||||
res["stores"] = std::move(stores);
|
||||
res["fetchers"] = fetchers::dumpRegisterInputSchemeInfo();
|
||||
|
|
|
@ -244,7 +244,7 @@ static PeerInfo getPeerInfo(int remote)
|
|||
*/
|
||||
static ref<Store> openUncachedStore()
|
||||
{
|
||||
Store::Params params; // FIXME: get params from somewhere
|
||||
Store::Config::Params params; // FIXME: get params from somewhere
|
||||
// Disable caching since the client already does that.
|
||||
params["path-info-cache-size"] = "0";
|
||||
return openStore(settings.storeUri, params);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue