1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-06-27 00:11:17 +02:00

Merge remote-tracking branch 'origin/master' into large-path-warning

This commit is contained in:
Eelco Dolstra 2024-06-03 15:32:27 +02:00
commit 7f5b57d18f
435 changed files with 6086 additions and 2767 deletions

View file

@ -8,7 +8,6 @@
#include "util.hh"
#include "nar-info-disk-cache.hh"
#include "thread-pool.hh"
#include "url.hh"
#include "references.hh"
#include "archive.hh"
#include "callback.hh"
@ -21,7 +20,6 @@
#include "users.hh"
#include <nlohmann/json.hpp>
#include <regex>
using json = nlohmann::json;
@ -1274,144 +1272,63 @@ Derivation Store::readInvalidDerivation(const StorePath & drvPath)
namespace nix {
/* Split URI into protocol+hierarchy part and its parameter set. */
std::pair<std::string, Store::Params> splitUriAndParams(const std::string & uri_)
{
auto uri(uri_);
Store::Params params;
auto q = uri.find('?');
if (q != std::string::npos) {
params = decodeQuery(uri.substr(q + 1));
uri = uri_.substr(0, q);
}
return {uri, params};
}
static bool isNonUriPath(const std::string & spec)
{
return
// is not a URL
spec.find("://") == std::string::npos
// Has at least one path separator, and so isn't a single word that
// might be special like "auto"
&& spec.find("/") != std::string::npos;
}
std::shared_ptr<Store> openFromNonUri(const std::string & uri, const Store::Params & params)
{
// TODO reenable on Windows once we have `LocalStore` and
// `UDSRemoteStore`.
if (uri == "" || uri == "auto") {
auto stateDir = getOr(params, "state", settings.nixStateDir);
if (access(stateDir.c_str(), R_OK | W_OK) == 0)
return std::make_shared<LocalStore>(params);
else if (pathExists(settings.nixDaemonSocketFile))
return std::make_shared<UDSRemoteStore>(params);
#if __linux__
else if (!pathExists(stateDir)
&& params.empty()
&& !isRootUser()
&& !getEnv("NIX_STORE_DIR").has_value()
&& !getEnv("NIX_STATE_DIR").has_value())
{
/* If /nix doesn't exist, there is no daemon socket, and
we're not root, then automatically set up a chroot
store in ~/.local/share/nix/root. */
auto chrootStore = getDataDir() + "/nix/root";
if (!pathExists(chrootStore)) {
try {
createDirs(chrootStore);
} catch (Error & e) {
return std::make_shared<LocalStore>(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);
Store::Params params2;
params2["root"] = chrootStore;
return std::make_shared<LocalStore>(params2);
}
#endif
else
return std::make_shared<LocalStore>(params);
} else if (uri == "daemon") {
return std::make_shared<UDSRemoteStore>(params);
} else if (uri == "local") {
return std::make_shared<LocalStore>(params);
} else if (isNonUriPath(uri)) {
Store::Params params2 = params;
params2["root"] = absPath(uri);
return std::make_shared<LocalStore>(params2);
} else {
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)
{
auto params = extraParams;
try {
auto parsedUri = parseURL(uri_);
params.insert(parsedUri.query.begin(), parsedUri.query.end());
return openStore(StoreReference::parse(uri, extraParams));
}
auto baseURI = extractConnStr(
parsedUri.scheme,
parsedUri.authority.value_or("") + parsedUri.path
);
ref<Store> openStore(StoreReference && storeURI)
{
auto & params = storeURI.params;
for (auto implem : *Implementations::registered) {
if (implem.uriSchemes.count(parsedUri.scheme)) {
auto store = implem.create(parsedUri.scheme, baseURI, params);
if (store) {
experimentalFeatureSettings.require(store->experimentalFeature());
store->init();
store->warnUnknownSettings();
return ref<Store>(store);
}
auto store = std::visit(overloaded {
[&](const StoreReference::Auto &) -> std::shared_ptr<Store> {
auto stateDir = getOr(params, "state", settings.nixStateDir);
if (access(stateDir.c_str(), R_OK | W_OK) == 0)
return std::make_shared<LocalStore>(params);
else if (pathExists(settings.nixDaemonSocketFile))
return std::make_shared<UDSRemoteStore>(params);
#if __linux__
else if (!pathExists(stateDir)
&& params.empty()
&& !isRootUser()
&& !getEnv("NIX_STORE_DIR").has_value()
&& !getEnv("NIX_STATE_DIR").has_value())
{
/* If /nix doesn't exist, there is no daemon socket, and
we're not root, then automatically set up a chroot
store in ~/.local/share/nix/root. */
auto chrootStore = getDataDir() + "/nix/root";
if (!pathExists(chrootStore)) {
try {
createDirs(chrootStore);
} catch (Error & e) {
return std::make_shared<LocalStore>(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);
}
}
}
catch (BadURL &) {
auto [uri, uriParams] = splitUriAndParams(uri_);
params.insert(uriParams.begin(), uriParams.end());
#endif
else
return std::make_shared<LocalStore>(params);
},
[&](const StoreReference::Specified & g) {
for (auto implem : *Implementations::registered)
if (implem.uriSchemes.count(g.scheme))
return implem.create(g.scheme, g.authority, params);
if (auto store = openFromNonUri(uri, params)) {
experimentalFeatureSettings.require(store->experimentalFeature());
store->warnUnknownSettings();
return ref<Store>(store);
}
}
throw Error("don't know how to open Nix store with scheme '%s'", g.scheme);
},
}, storeURI.variant);
throw Error("don't know how to open Nix store '%s'", uri_);
experimentalFeatureSettings.require(store->experimentalFeature());
store->warnUnknownSettings();
store->init();
return ref<Store> { store };
}
std::list<ref<Store>> getDefaultSubstituters()