mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-26 07:46:21 +02:00
Merge pull request #9850 from obsidiansystems/missing-store-urls
Ensure all store types support "real" URIs
This commit is contained in:
commit
5f7673c7ee
19 changed files with 170 additions and 75 deletions
|
@ -18,9 +18,12 @@ struct DummyStoreConfig : virtual StoreConfig {
|
||||||
|
|
||||||
struct DummyStore : public virtual DummyStoreConfig, public virtual Store
|
struct DummyStore : public virtual DummyStoreConfig, public virtual Store
|
||||||
{
|
{
|
||||||
DummyStore(const std::string scheme, const std::string uri, const Params & params)
|
DummyStore(std::string_view scheme, std::string_view authority, const Params & params)
|
||||||
: DummyStore(params)
|
: DummyStore(params)
|
||||||
{ }
|
{
|
||||||
|
if (!authority.empty())
|
||||||
|
throw UsageError("`%s` store URIs must not contain an authority part %s", scheme, authority);
|
||||||
|
}
|
||||||
|
|
||||||
DummyStore(const Params & params)
|
DummyStore(const Params & params)
|
||||||
: StoreConfig(params)
|
: StoreConfig(params)
|
||||||
|
|
|
@ -39,15 +39,20 @@ private:
|
||||||
public:
|
public:
|
||||||
|
|
||||||
HttpBinaryCacheStore(
|
HttpBinaryCacheStore(
|
||||||
const std::string & scheme,
|
std::string_view scheme,
|
||||||
const Path & _cacheUri,
|
PathView _cacheUri,
|
||||||
const Params & params)
|
const Params & params)
|
||||||
: StoreConfig(params)
|
: StoreConfig(params)
|
||||||
, BinaryCacheStoreConfig(params)
|
, BinaryCacheStoreConfig(params)
|
||||||
, HttpBinaryCacheStoreConfig(params)
|
, HttpBinaryCacheStoreConfig(params)
|
||||||
, Store(params)
|
, Store(params)
|
||||||
, BinaryCacheStore(params)
|
, BinaryCacheStore(params)
|
||||||
, cacheUri(scheme + "://" + _cacheUri)
|
, cacheUri(
|
||||||
|
std::string { scheme }
|
||||||
|
+ "://"
|
||||||
|
+ (!_cacheUri.empty()
|
||||||
|
? _cacheUri
|
||||||
|
: throw UsageError("`%s` Store requires a non-empty authority in Store URL", scheme)))
|
||||||
{
|
{
|
||||||
while (!cacheUri.empty() && cacheUri.back() == '/')
|
while (!cacheUri.empty() && cacheUri.back() == '/')
|
||||||
cacheUri.pop_back();
|
cacheUri.pop_back();
|
||||||
|
|
|
@ -28,8 +28,18 @@ struct LegacySSHStore::Connection : public ServeProto::BasicClientConnection
|
||||||
bool good = true;
|
bool good = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
LegacySSHStore::LegacySSHStore(
|
||||||
|
std::string_view scheme,
|
||||||
|
std::string_view host,
|
||||||
|
const Params & params)
|
||||||
|
: LegacySSHStore{scheme, LegacySSHStoreConfig::extractConnStr(scheme, host), params}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
LegacySSHStore::LegacySSHStore(const std::string & scheme, const std::string & host, const Params & params)
|
LegacySSHStore::LegacySSHStore(
|
||||||
|
std::string_view scheme,
|
||||||
|
std::string host,
|
||||||
|
const Params & params)
|
||||||
: StoreConfig(params)
|
: StoreConfig(params)
|
||||||
, CommonSSHStoreConfig(params)
|
, CommonSSHStoreConfig(params)
|
||||||
, LegacySSHStoreConfig(params)
|
, LegacySSHStoreConfig(params)
|
||||||
|
@ -42,8 +52,8 @@ LegacySSHStore::LegacySSHStore(const std::string & scheme, const std::string & h
|
||||||
))
|
))
|
||||||
, master(
|
, master(
|
||||||
host,
|
host,
|
||||||
sshKey,
|
sshKey.get(),
|
||||||
sshPublicHostKey,
|
sshPublicHostKey.get(),
|
||||||
// Use SSH master only if using more than 1 connection.
|
// Use SSH master only if using more than 1 connection.
|
||||||
connections->capacity() > 1,
|
connections->capacity() > 1,
|
||||||
compress,
|
compress,
|
||||||
|
|
|
@ -41,7 +41,17 @@ struct LegacySSHStore : public virtual LegacySSHStoreConfig, public virtual Stor
|
||||||
|
|
||||||
static std::set<std::string> uriSchemes() { return {"ssh"}; }
|
static std::set<std::string> uriSchemes() { return {"ssh"}; }
|
||||||
|
|
||||||
LegacySSHStore(const std::string & scheme, const std::string & host, const Params & params);
|
LegacySSHStore(
|
||||||
|
std::string_view scheme,
|
||||||
|
std::string_view host,
|
||||||
|
const Params & params);
|
||||||
|
|
||||||
|
private:
|
||||||
|
LegacySSHStore(
|
||||||
|
std::string_view scheme,
|
||||||
|
std::string host,
|
||||||
|
const Params & params);
|
||||||
|
public:
|
||||||
|
|
||||||
ref<Connection> openConnection();
|
ref<Connection> openConnection();
|
||||||
|
|
||||||
|
|
|
@ -28,9 +28,13 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param binaryCacheDir `file://` is a short-hand for `file:///`
|
||||||
|
* for now.
|
||||||
|
*/
|
||||||
LocalBinaryCacheStore(
|
LocalBinaryCacheStore(
|
||||||
const std::string scheme,
|
std::string_view scheme,
|
||||||
const Path & binaryCacheDir,
|
PathView binaryCacheDir,
|
||||||
const Params & params)
|
const Params & params)
|
||||||
: StoreConfig(params)
|
: StoreConfig(params)
|
||||||
, BinaryCacheStoreConfig(params)
|
, BinaryCacheStoreConfig(params)
|
||||||
|
|
|
@ -463,10 +463,20 @@ LocalStore::LocalStore(const Params & params)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LocalStore::LocalStore(std::string scheme, std::string path, const Params & params)
|
LocalStore::LocalStore(
|
||||||
: LocalStore(params)
|
std::string_view scheme,
|
||||||
|
PathView path,
|
||||||
|
const Params & _params)
|
||||||
|
: LocalStore([&]{
|
||||||
|
// Default `?root` from `path` if non set
|
||||||
|
if (!path.empty() && _params.count("root") == 0) {
|
||||||
|
auto params = _params;
|
||||||
|
params.insert_or_assign("root", std::string { path });
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
return _params;
|
||||||
|
}())
|
||||||
{
|
{
|
||||||
throw UnimplementedError("LocalStore");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -137,12 +137,15 @@ public:
|
||||||
* necessary.
|
* necessary.
|
||||||
*/
|
*/
|
||||||
LocalStore(const Params & params);
|
LocalStore(const Params & params);
|
||||||
LocalStore(std::string scheme, std::string path, const Params & params);
|
LocalStore(
|
||||||
|
std::string_view scheme,
|
||||||
|
PathView path,
|
||||||
|
const Params & params);
|
||||||
|
|
||||||
~LocalStore();
|
~LocalStore();
|
||||||
|
|
||||||
static std::set<std::string> uriSchemes()
|
static std::set<std::string> uriSchemes()
|
||||||
{ return {}; }
|
{ return {"local"}; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementations of abstract store API methods.
|
* Implementations of abstract store API methods.
|
||||||
|
|
|
@ -269,8 +269,8 @@ struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual
|
||||||
S3Helper s3Helper;
|
S3Helper s3Helper;
|
||||||
|
|
||||||
S3BinaryCacheStoreImpl(
|
S3BinaryCacheStoreImpl(
|
||||||
const std::string & uriScheme,
|
std::string_view uriScheme,
|
||||||
const std::string & bucketName,
|
std::string_view bucketName,
|
||||||
const Params & params)
|
const Params & params)
|
||||||
: StoreConfig(params)
|
: StoreConfig(params)
|
||||||
, BinaryCacheStoreConfig(params)
|
, BinaryCacheStoreConfig(params)
|
||||||
|
@ -281,6 +281,8 @@ struct S3BinaryCacheStoreImpl : virtual S3BinaryCacheStoreConfig, public virtual
|
||||||
, bucketName(bucketName)
|
, bucketName(bucketName)
|
||||||
, s3Helper(profile, region, scheme, endpoint)
|
, s3Helper(profile, region, scheme, endpoint)
|
||||||
{
|
{
|
||||||
|
if (bucketName.empty())
|
||||||
|
throw UsageError("`%s` store requires a bucket name in its Store URI", uriScheme);
|
||||||
diskCache = getNarInfoDiskCache();
|
diskCache = getNarInfoDiskCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
24
src/libstore/ssh-store-config.cc
Normal file
24
src/libstore/ssh-store-config.cc
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
|
#include "ssh-store-config.hh"
|
||||||
|
|
||||||
|
namespace nix {
|
||||||
|
|
||||||
|
std::string CommonSSHStoreConfig::extractConnStr(std::string_view scheme, std::string_view _connStr)
|
||||||
|
{
|
||||||
|
if (_connStr.empty())
|
||||||
|
throw UsageError("`%s` store requires a valid SSH host as the authority part in Store URI", scheme);
|
||||||
|
|
||||||
|
std::string connStr{_connStr};
|
||||||
|
|
||||||
|
std::smatch result;
|
||||||
|
static std::regex v6AddrRegex("^((.*)@)?\\[(.*)\\]$");
|
||||||
|
|
||||||
|
if (std::regex_match(connStr, result, v6AddrRegex)) {
|
||||||
|
connStr = result[1].matched ? result.str(1) + result.str(3) : result.str(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
return connStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -24,6 +24,29 @@ struct CommonSSHStoreConfig : virtual StoreConfig
|
||||||
to be used on the remote machine. The default is `auto`
|
to be used on the remote machine. The default is `auto`
|
||||||
(i.e. use the Nix daemon or `/nix/store` directly).
|
(i.e. use the Nix daemon or `/nix/store` directly).
|
||||||
)"};
|
)"};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The `parseURL` function supports both IPv6 URIs as defined in
|
||||||
|
* RFC2732, but also pure addresses. The latter one is needed here to
|
||||||
|
* connect to a remote store via SSH (it's possible to do e.g. `ssh root@::1`).
|
||||||
|
*
|
||||||
|
* This function now ensures that a usable connection string is available:
|
||||||
|
*
|
||||||
|
* - If the store to be opened is not an SSH store, nothing will be done.
|
||||||
|
*
|
||||||
|
* - If the URL looks like `root@[::1]` (which is allowed by the URL parser and probably
|
||||||
|
* needed to pass further flags), it
|
||||||
|
* will be transformed into `root@::1` for SSH (same for `[::1]` -> `::1`).
|
||||||
|
*
|
||||||
|
* - If the URL looks like `root@::1` it will be left as-is.
|
||||||
|
*
|
||||||
|
* - In any other case, the string will be left as-is.
|
||||||
|
*
|
||||||
|
* Will throw an error if `connStr` is empty too.
|
||||||
|
*/
|
||||||
|
static std::string extractConnStr(
|
||||||
|
std::string_view scheme,
|
||||||
|
std::string_view connStr);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,9 +32,10 @@ struct SSHStoreConfig : virtual RemoteStoreConfig, virtual CommonSSHStoreConfig
|
||||||
|
|
||||||
class SSHStore : public virtual SSHStoreConfig, public virtual RemoteStore
|
class SSHStore : public virtual SSHStoreConfig, public virtual RemoteStore
|
||||||
{
|
{
|
||||||
public:
|
SSHStore(
|
||||||
|
std::string_view scheme,
|
||||||
SSHStore(const std::string & scheme, const std::string & host, const Params & params)
|
std::string host,
|
||||||
|
const Params & params)
|
||||||
: StoreConfig(params)
|
: StoreConfig(params)
|
||||||
, RemoteStoreConfig(params)
|
, RemoteStoreConfig(params)
|
||||||
, CommonSSHStoreConfig(params)
|
, CommonSSHStoreConfig(params)
|
||||||
|
@ -44,14 +45,24 @@ public:
|
||||||
, host(host)
|
, host(host)
|
||||||
, master(
|
, master(
|
||||||
host,
|
host,
|
||||||
sshKey,
|
sshKey.get(),
|
||||||
sshPublicHostKey,
|
sshPublicHostKey.get(),
|
||||||
// Use SSH master only if using more than 1 connection.
|
// Use SSH master only if using more than 1 connection.
|
||||||
connections->capacity() > 1,
|
connections->capacity() > 1,
|
||||||
compress)
|
compress)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
SSHStore(
|
||||||
|
std::string_view scheme,
|
||||||
|
std::string_view host,
|
||||||
|
const Params & params)
|
||||||
|
: SSHStore{scheme, SSHStoreConfig::extractConnStr(scheme, host), params}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
static std::set<std::string> uriSchemes() { return {"ssh-ng"}; }
|
static std::set<std::string> uriSchemes() { return {"ssh-ng"}; }
|
||||||
|
|
||||||
std::string getUri() override
|
std::string getUri() override
|
||||||
|
@ -141,7 +152,10 @@ class MountedSSHStore : public virtual MountedSSHStoreConfig, public virtual SSH
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
MountedSSHStore(const std::string & scheme, const std::string & host, const Params & params)
|
MountedSSHStore(
|
||||||
|
std::string_view scheme,
|
||||||
|
std::string_view host,
|
||||||
|
const Params & params)
|
||||||
: StoreConfig(params)
|
: StoreConfig(params)
|
||||||
, RemoteStoreConfig(params)
|
, RemoteStoreConfig(params)
|
||||||
, CommonSSHStoreConfig(params)
|
, CommonSSHStoreConfig(params)
|
||||||
|
|
|
@ -6,7 +6,11 @@
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
SSHMaster::SSHMaster(const std::string & host, const std::string & keyFile, const std::string & sshPublicHostKey, bool useMaster, bool compress, int logFD)
|
SSHMaster::SSHMaster(
|
||||||
|
std::string_view host,
|
||||||
|
std::string_view keyFile,
|
||||||
|
std::string_view sshPublicHostKey,
|
||||||
|
bool useMaster, bool compress, int logFD)
|
||||||
: host(host)
|
: host(host)
|
||||||
, fakeSSH(host == "localhost")
|
, fakeSSH(host == "localhost")
|
||||||
, keyFile(keyFile)
|
, keyFile(keyFile)
|
||||||
|
|
|
@ -39,7 +39,11 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
SSHMaster(const std::string & host, const std::string & keyFile, const std::string & sshPublicHostKey, bool useMaster, bool compress, int logFD = -1);
|
SSHMaster(
|
||||||
|
std::string_view host,
|
||||||
|
std::string_view keyFile,
|
||||||
|
std::string_view sshPublicHostKey,
|
||||||
|
bool useMaster, bool compress, int logFD = -1);
|
||||||
|
|
||||||
struct Connection
|
struct Connection
|
||||||
{
|
{
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
#include "users.hh"
|
#include "users.hh"
|
||||||
|
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
#include <regex>
|
|
||||||
|
|
||||||
using json = nlohmann::json;
|
using json = nlohmann::json;
|
||||||
|
|
||||||
|
@ -1321,9 +1320,7 @@ std::shared_ptr<Store> openFromNonUri(const std::string & uri, const Store::Para
|
||||||
warn("'%s' does not exist, so Nix will use '%s' as a chroot store", stateDir, chrootStore);
|
warn("'%s' does not exist, so Nix will use '%s' as a chroot store", stateDir, chrootStore);
|
||||||
} else
|
} else
|
||||||
debug("'%s' does not exist, so Nix will use '%s' as a chroot store", stateDir, chrootStore);
|
debug("'%s' does not exist, so Nix will use '%s' as a chroot store", stateDir, chrootStore);
|
||||||
Store::Params params2;
|
return std::make_shared<LocalStore>("local", chrootStore, params);
|
||||||
params2["root"] = chrootStore;
|
|
||||||
return std::make_shared<LocalStore>(params2);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
else
|
else
|
||||||
|
@ -1333,42 +1330,12 @@ std::shared_ptr<Store> openFromNonUri(const std::string & uri, const Store::Para
|
||||||
} else if (uri == "local") {
|
} else if (uri == "local") {
|
||||||
return std::make_shared<LocalStore>(params);
|
return std::make_shared<LocalStore>(params);
|
||||||
} else if (isNonUriPath(uri)) {
|
} else if (isNonUriPath(uri)) {
|
||||||
Store::Params params2 = params;
|
return std::make_shared<LocalStore>("local", absPath(uri), params);
|
||||||
params2["root"] = absPath(uri);
|
|
||||||
return std::make_shared<LocalStore>(params2);
|
|
||||||
} else {
|
} else {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The `parseURL` function supports both IPv6 URIs as defined in
|
|
||||||
// RFC2732, but also pure addresses. The latter one is needed here to
|
|
||||||
// connect to a remote store via SSH (it's possible to do e.g. `ssh root@::1`).
|
|
||||||
//
|
|
||||||
// This function now ensures that a usable connection string is available:
|
|
||||||
// * If the store to be opened is not an SSH store, nothing will be done.
|
|
||||||
// * If the URL looks like `root@[::1]` (which is allowed by the URL parser and probably
|
|
||||||
// needed to pass further flags), it
|
|
||||||
// will be transformed into `root@::1` for SSH (same for `[::1]` -> `::1`).
|
|
||||||
// * If the URL looks like `root@::1` it will be left as-is.
|
|
||||||
// * In any other case, the string will be left as-is.
|
|
||||||
static std::string extractConnStr(const std::string &proto, const std::string &connStr)
|
|
||||||
{
|
|
||||||
if (proto.rfind("ssh") != std::string::npos) {
|
|
||||||
std::smatch result;
|
|
||||||
std::regex v6AddrRegex("^((.*)@)?\\[(.*)\\]$");
|
|
||||||
|
|
||||||
if (std::regex_match(connStr, result, v6AddrRegex)) {
|
|
||||||
if (result[1].matched) {
|
|
||||||
return result.str(1) + result.str(3);
|
|
||||||
}
|
|
||||||
return result.str(3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return connStr;
|
|
||||||
}
|
|
||||||
|
|
||||||
ref<Store> openStore(const std::string & uri_,
|
ref<Store> openStore(const std::string & uri_,
|
||||||
const Store::Params & extraParams)
|
const Store::Params & extraParams)
|
||||||
{
|
{
|
||||||
|
@ -1377,10 +1344,7 @@ ref<Store> openStore(const std::string & uri_,
|
||||||
auto parsedUri = parseURL(uri_);
|
auto parsedUri = parseURL(uri_);
|
||||||
params.insert(parsedUri.query.begin(), parsedUri.query.end());
|
params.insert(parsedUri.query.begin(), parsedUri.query.end());
|
||||||
|
|
||||||
auto baseURI = extractConnStr(
|
auto baseURI = parsedUri.authority.value_or("") + parsedUri.path;
|
||||||
parsedUri.scheme,
|
|
||||||
parsedUri.authority.value_or("") + parsedUri.path
|
|
||||||
);
|
|
||||||
|
|
||||||
for (auto implem : *Implementations::registered) {
|
for (auto implem : *Implementations::registered) {
|
||||||
if (implem.uriSchemes.count(parsedUri.scheme)) {
|
if (implem.uriSchemes.count(parsedUri.scheme)) {
|
||||||
|
|
|
@ -901,7 +901,14 @@ std::list<ref<Store>> getDefaultSubstituters();
|
||||||
struct StoreFactory
|
struct StoreFactory
|
||||||
{
|
{
|
||||||
std::set<std::string> uriSchemes;
|
std::set<std::string> uriSchemes;
|
||||||
std::function<std::shared_ptr<Store> (const std::string & scheme, const std::string & uri, const Store::Params & params)> create;
|
/**
|
||||||
|
* 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<std::shared_ptr<StoreConfig> ()> getConfig;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -916,7 +923,7 @@ struct Implementations
|
||||||
StoreFactory factory{
|
StoreFactory factory{
|
||||||
.uriSchemes = T::uriSchemes(),
|
.uriSchemes = T::uriSchemes(),
|
||||||
.create =
|
.create =
|
||||||
([](const std::string & scheme, const std::string & uri, const Store::Params & params)
|
([](auto scheme, auto uri, auto & params)
|
||||||
-> std::shared_ptr<Store>
|
-> std::shared_ptr<Store>
|
||||||
{ return std::make_shared<T>(scheme, uri, params); }),
|
{ return std::make_shared<T>(scheme, uri, params); }),
|
||||||
.getConfig =
|
.getConfig =
|
||||||
|
|
|
@ -40,12 +40,13 @@ UDSRemoteStore::UDSRemoteStore(const Params & params)
|
||||||
|
|
||||||
|
|
||||||
UDSRemoteStore::UDSRemoteStore(
|
UDSRemoteStore::UDSRemoteStore(
|
||||||
const std::string scheme,
|
std::string_view scheme,
|
||||||
std::string socket_path,
|
PathView socket_path,
|
||||||
const Params & params)
|
const Params & params)
|
||||||
: UDSRemoteStore(params)
|
: UDSRemoteStore(params)
|
||||||
{
|
{
|
||||||
path.emplace(socket_path);
|
if (!socket_path.empty())
|
||||||
|
path.emplace(socket_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -54,6 +55,7 @@ std::string UDSRemoteStore::getUri()
|
||||||
if (path) {
|
if (path) {
|
||||||
return std::string("unix://") + *path;
|
return std::string("unix://") + *path;
|
||||||
} else {
|
} else {
|
||||||
|
// unix:// with no path also works. Change what we return?
|
||||||
return "daemon";
|
return "daemon";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,10 @@ class UDSRemoteStore : public virtual UDSRemoteStoreConfig
|
||||||
public:
|
public:
|
||||||
|
|
||||||
UDSRemoteStore(const Params & params);
|
UDSRemoteStore(const Params & params);
|
||||||
UDSRemoteStore(const std::string scheme, std::string path, const Params & params);
|
UDSRemoteStore(
|
||||||
|
std::string_view scheme,
|
||||||
|
PathView path,
|
||||||
|
const Params & params);
|
||||||
|
|
||||||
std::string getUri() override;
|
std::string getUri() override;
|
||||||
|
|
||||||
|
|
|
@ -92,7 +92,7 @@ class LocalOverlayStore : public virtual LocalOverlayStoreConfig, public virtual
|
||||||
public:
|
public:
|
||||||
LocalOverlayStore(const Params & params);
|
LocalOverlayStore(const Params & params);
|
||||||
|
|
||||||
LocalOverlayStore(std::string scheme, std::string path, const Params & params)
|
LocalOverlayStore(std::string_view scheme, PathView path, const Params & params)
|
||||||
: LocalOverlayStore(params)
|
: LocalOverlayStore(params)
|
||||||
{
|
{
|
||||||
if (!path.empty())
|
if (!path.empty())
|
||||||
|
|
|
@ -10,6 +10,9 @@ happy () {
|
||||||
# We can do a read-only query just fine with a read-only store
|
# We can do a read-only query just fine with a read-only store
|
||||||
nix --store local?read-only=true path-info $dummyPath
|
nix --store local?read-only=true path-info $dummyPath
|
||||||
|
|
||||||
|
# `local://` also works.
|
||||||
|
nix --store local://?read-only=true path-info $dummyPath
|
||||||
|
|
||||||
# We can "write" an already-present store-path a read-only store, because no IO is actually required
|
# We can "write" an already-present store-path a read-only store, because no IO is actually required
|
||||||
nix-store --store local?read-only=true --add dummy
|
nix-store --store local?read-only=true --add dummy
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue