clangd broke because it can't look through symlinks. compile_commands manipulation does not fix it, clangd configuration does not fix it, a vfs overlay does not fix it, and while a combination of those can fix it with a bind mount in place that's just too cursed to even consider clangd bug: https://github.com/llvm/llvm-project/issues/116877 Change-Id: I8e3e8489548eb3a7aa65ac9d12a5ec8abf814aec
127 lines
4.5 KiB
C++
127 lines
4.5 KiB
C++
#include "lix/libexpr/flake/flake.hh"
|
|
#include "lix/libutil/logging.hh"
|
|
#include "lix/libutil/users.hh"
|
|
#include "lix/libfetchers/fetch-settings.hh"
|
|
|
|
#include <nlohmann/json.hpp>
|
|
|
|
namespace nix::flake {
|
|
|
|
// setting name -> setting value -> allow or ignore.
|
|
typedef std::map<std::string, std::map<std::string, bool>> TrustedList;
|
|
|
|
Path trustedListPath()
|
|
{
|
|
return getDataDir() + "/nix/trusted-settings.json";
|
|
}
|
|
|
|
static TrustedList readTrustedList()
|
|
{
|
|
auto path = trustedListPath();
|
|
if (!pathExists(path)) return {};
|
|
auto json = nlohmann::json::parse(readFile(path));
|
|
return json;
|
|
}
|
|
|
|
static void writeTrustedList(const TrustedList & trustedList)
|
|
{
|
|
auto path = trustedListPath();
|
|
createDirs(dirOf(path));
|
|
writeFile(path, nlohmann::json(trustedList).dump());
|
|
}
|
|
|
|
static bool askForSetting(
|
|
bool & negativeTrustOverride,
|
|
TrustedList & trustedList,
|
|
const std::string & name,
|
|
const std::string & valueS)
|
|
{
|
|
bool trusted = false;
|
|
|
|
// FIXME: filter ANSI escapes, newlines, \r, etc.
|
|
auto reply = logger->ask(fmt("Do you want to allow configuration setting '%s' to be set to '" ANSI_RED "%s" ANSI_NORMAL "'?\nThis may allow the flake to gain root, see the nix.conf manual page (" ANSI_BOLD "y" ANSI_NORMAL "es/" ANSI_BOLD "n" ANSI_NORMAL "o/" ANSI_BOLD "N" ANSI_NORMAL "o to all) ", name, valueS)).value_or('n');
|
|
|
|
if (reply == 'N') {
|
|
warn("Rejecting all untrusted nix.conf entries");
|
|
warn("you can set '%s' to '%b' to automatically reject configuration options supplied by flakes", "accept-flake-config", false);
|
|
negativeTrustOverride = true;
|
|
} else {
|
|
if (std::tolower(reply) == 'y') {
|
|
trusted = true;
|
|
} else {
|
|
warn("you can set '%s' to '%b' to automatically reject configuration options supplied by flakes", "accept-flake-config", false);
|
|
}
|
|
|
|
if (std::tolower(logger->ask(fmt("do you want to permanently (in %s) mark this value as %s? (y/N) ", trustedListPath(), trusted ? "trusted": "untrusted" )).value_or('n')) == 'y') {
|
|
trustedList[name][valueS] = trusted;
|
|
writeTrustedList(trustedList);
|
|
}
|
|
}
|
|
|
|
return trusted;
|
|
}
|
|
|
|
void ConfigFile::apply()
|
|
{
|
|
std::set<std::string> whitelist{"bash-prompt", "bash-prompt-prefix", "bash-prompt-suffix", "flake-registry", "commit-lockfile-summary"};
|
|
|
|
// Allows to ignore all subsequent settings from this file.
|
|
bool negativeTrustOverride = false;
|
|
|
|
for (auto & [name, value] : settings) {
|
|
|
|
auto baseName = name.starts_with("extra-") ? std::string(name, 6) : name;
|
|
|
|
// FIXME: Move into libutil/config.cc.
|
|
std::string valueS;
|
|
if (auto* s = std::get_if<std::string>(&value))
|
|
valueS = *s;
|
|
else if (auto* n = std::get_if<int64_t>(&value))
|
|
valueS = fmt("%d", *n);
|
|
else if (auto* b = std::get_if<Explicit<bool>>(&value))
|
|
valueS = b->t ? "true" : "false";
|
|
else if (auto ss = std::get_if<std::vector<std::string>>(&value))
|
|
valueS = concatStringsSep(" ", *ss); // FIXME: evil
|
|
else
|
|
assert(false);
|
|
|
|
bool trusted = whitelist.count(baseName);
|
|
if (!trusted) {
|
|
switch (nix::fetchSettings.acceptFlakeConfig.get()) {
|
|
case AcceptFlakeConfig::True: {
|
|
trusted = true;
|
|
break;
|
|
}
|
|
case AcceptFlakeConfig::Ask: {
|
|
auto trustedList = readTrustedList();
|
|
auto tlname = get(trustedList, name);
|
|
if (auto saved = tlname ? get(*tlname, valueS) : nullptr) {
|
|
trusted = *saved;
|
|
printInfo("Using saved setting for '%s = %s' from ~/.local/share/nix/trusted-settings.json.", name, valueS);
|
|
} else {
|
|
if (negativeTrustOverride) {
|
|
trusted = false;
|
|
} else {
|
|
trusted = askForSetting(negativeTrustOverride, trustedList, name, valueS);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case nix::AcceptFlakeConfig::False: {
|
|
trusted = false;
|
|
break;
|
|
};
|
|
}
|
|
}
|
|
|
|
if (trusted) {
|
|
debug("accepting trusted flake configuration setting '%s'", name);
|
|
globalConfig.set(name, valueS);
|
|
} else {
|
|
warn("ignoring untrusted flake configuration setting '%s', pass '%s' to trust it (may allow the flake to gain root, see the nix.conf manual page)", name, "--accept-flake-config");
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|