1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-06-24 18:01:16 +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:
John Ericson 2025-05-07 17:07:23 -04:00
parent f0f196cef0
commit 934918ba16
48 changed files with 743 additions and 593 deletions

View file

@ -33,6 +33,7 @@ let
{
settings,
doc,
uri-schemes,
experimentalFeature,
}:
let

View file

@ -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;

View file

@ -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;

View file

@ -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];
}

View file

@ -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)

View file

@ -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));

View file

@ -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 (...) {

View file

@ -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,

View file

@ -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;

View file

@ -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;
}

View file

@ -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);

View file

@ -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;
};

View file

@ -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;
}

View file

@ -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:

View file

@ -56,7 +56,7 @@ struct CommonSSHStoreConfig : virtual StoreConfig
*/
SSHMaster createSSHMaster(
bool useMaster,
Descriptor logFD = INVALID_DESCRIPTOR);
Descriptor logFD = INVALID_DESCRIPTOR) const;
};
}

View file

@ -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;
};
}

View file

@ -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

View file

@ -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;
};
}

View file

@ -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
{

View file

@ -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.

View file

@ -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();

View file

@ -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

View file

@ -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);

View file

@ -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. */

View file

@ -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);
}

View file

@ -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
{

View file

@ -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;
};
}

View file

@ -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>();
}
};

View file

@ -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;
};
}

View file

@ -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;

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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))

View file

@ -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;
}

View file

@ -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

View file

@ -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',

View file

@ -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());

View file

@ -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));

View file

@ -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);

View file

@ -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()

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View 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_}
{
}
}

View file

@ -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;
}

View file

@ -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");

View file

@ -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();

View file

@ -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);