Skip to content

Commit

Permalink
Make the loggers truly pluggable
Browse files Browse the repository at this point in the history
Remove the static list of possible loggers, and instead generate it
dynamically from the registered ones.

This requires a conceptually small but textually invasive refactoring as
to remove some undefined behavior wrt. the orders in which static
variables are initialised, we change `nix::config` from a static
variable to a function that lazily builds a `Config` object and returns
it (the reason for that is that with a static `Config`, we might − and
apparantly do in practice − get the list of registered loggers before
they are all registered, leading to an incomplete list in the
help/man/completion).
  • Loading branch information
thufschmitt committed Sep 18, 2020
1 parent 6efa529 commit b52f6be
Show file tree
Hide file tree
Showing 64 changed files with 376 additions and 361 deletions.
2 changes: 1 addition & 1 deletion doc/manual/command-ref/conf-file.xml
Expand Up @@ -613,7 +613,7 @@ password <replaceable>my-password</replaceable>
RegisterStoreImplementation to add new store implementations,
RegisterCommand to add new subcommands to the
<literal>nix</literal> command, and RegisterSetting to add new
nix config settings. See the constructors for those types for
nix config settings()-> See the constructors for those types for
more details.
</para>
<para>
Expand Down
Binary file modified doc/manual/src/figures/user-environments.sxd
Binary file not shown.
6 changes: 3 additions & 3 deletions perl/lib/Nix/Store.xs
Expand Up @@ -28,7 +28,7 @@ static ref<Store> store()
if (!_store) {
try {
loadConfFile();
settings.lockCPU = false;
settings()->lockCPU = false;
_store = openStore();
} catch (Error & e) {
croak("%s", e.what());
Expand Down Expand Up @@ -355,9 +355,9 @@ void addTempRoot(char * storePath)

SV * getBinDir()
PPCODE:
XPUSHs(sv_2mortal(newSVpv(settings.nixBinDir.c_str(), 0)));
XPUSHs(sv_2mortal(newSVpv(settings()->nixBinDir.c_str(), 0)));


SV * getStoreDir()
PPCODE:
XPUSHs(sv_2mortal(newSVpv(settings.nixStore.c_str(), 0)));
XPUSHs(sv_2mortal(newSVpv(settings()->nixStore.c_str(), 0)));
12 changes: 6 additions & 6 deletions src/build-remote/build-remote.cc
Expand Up @@ -60,14 +60,14 @@ static int _main(int argc, char * * argv)

FdSource source(STDIN_FILENO);

/* Read the parent's settings. */
/* Read the parent's settings()-> */
while (readInt(source)) {
auto name = readString(source);
auto value = readString(source);
settings.set(name, value);
settings()->set(name, value);
}

settings.maxBuildJobs.set("1"); // hack to make tests with local?root= work
settings()->maxBuildJobs.set("1"); // hack to make tests with local?root= work

initPlugins();

Expand Down Expand Up @@ -104,8 +104,8 @@ static int _main(int argc, char * * argv)
auto requiredFeatures = readStrings<std::set<std::string>>(source);

auto canBuildLocally = amWilling
&& ( neededSystem == settings.thisSystem
|| settings.extraPlatforms.get().count(neededSystem) > 0)
&& ( neededSystem == settings()->thisSystem
|| settings()->extraPlatforms.get().count(neededSystem) > 0)
&& allSupportedLocally(*store, requiredFeatures);

/* Error ignored here, will be caught later */
Expand Down Expand Up @@ -265,7 +265,7 @@ static int _main(int argc, char * * argv)
signal(SIGALRM, old);
}

auto substitute = settings.buildersUseSubstitutes ? Substitute : NoSubstitute;
auto substitute = settings()->buildersUseSubstitutes ? Substitute : NoSubstitute;

{
Activity act(*logger, lvlTalkative, actUnknown, fmt("copying dependencies to '%s'", storeUri));
Expand Down
2 changes: 1 addition & 1 deletion src/libexpr/eval-cache.cc
Expand Up @@ -606,7 +606,7 @@ StorePath AttrCursor::forceDerivation()
{
auto aDrvPath = getAttr(root->state.sDrvPath, true);
auto drvPath = root->state.store->parseStorePath(aDrvPath->getString());
if (!root->state.store->isValidPath(drvPath) && !settings.readOnlyMode) {
if (!root->state.store->isValidPath(drvPath) && !settings()->readOnlyMode) {
/* The eval cache contains 'drvPath', but the actual path has
been garbage-collected. So force it to be regenerated. */
aDrvPath->forceValue();
Expand Down
8 changes: 4 additions & 4 deletions src/libexpr/eval.cc
Expand Up @@ -372,7 +372,7 @@ EvalState::EvalState(const Strings & _searchPath, ref<Store> store)
}

try {
addToSearchPath("nix=" + canonPath(settings.nixDataDir + "/nix/corepkgs", true));
addToSearchPath("nix=" + canonPath(settings()->nixDataDir + "/nix/corepkgs", true));
} catch (Error &) {
}

Expand Down Expand Up @@ -1820,7 +1820,7 @@ string EvalState::copyPathToStore(PathSet & context, const Path & path)
if (i != srcToStore.end())
dstPath = store->printStorePath(i->second);
else {
auto p = settings.readOnlyMode
auto p = settings()->readOnlyMode
? store->computeStorePathForPath(std::string(baseNameOf(path)), checkSourcePath(path)).first
: store->addToStore(std::string(baseNameOf(path)), checkSourcePath(path), FileIngestionMethod::Recursive, htSHA256, defaultPathFilter, repair);
dstPath = store->printStorePath(p);
Expand Down Expand Up @@ -2073,8 +2073,8 @@ Strings EvalSettings::getDefaultNixPath()
Strings res;
auto add = [&](const Path & p) { if (pathExists(p)) { res.push_back(p); } };
add(getHome() + "/.nix-defexpr/channels");
add("nixpkgs=" + settings.nixStateDir + "/nix/profiles/per-user/root/channels/nixpkgs");
add(settings.nixStateDir + "/nix/profiles/per-user/root/channels");
add("nixpkgs=" + settings()->nixStateDir + "/nix/profiles/per-user/root/channels/nixpkgs");
add(settings()->nixStateDir + "/nix/profiles/per-user/root/channels");
return res;
}

Expand Down
4 changes: 2 additions & 2 deletions src/libexpr/flake/flake.cc
Expand Up @@ -254,7 +254,7 @@ LockedFlake lockFlake(
const FlakeRef & topRef,
const LockFlags & lockFlags)
{
settings.requireExperimentalFeature("flakes");
settings()->requireExperimentalFeature("flakes");

FlakeCache flakeCache;

Expand Down Expand Up @@ -481,7 +481,7 @@ LockedFlake lockFlake(
if (lockFlags.writeLockFile) {
if (auto sourcePath = topRef.input.getSourcePath()) {
if (!newLockFile.isImmutable()) {
if (settings.warnDirty)
if (settings()->warnDirty)
warn("will not write lock file of flake '%s' because it has a mutable input", topRef);
} else {
if (!lockFlags.updateLockFile)
Expand Down
2 changes: 1 addition & 1 deletion src/libexpr/parser.y
Expand Up @@ -415,7 +415,7 @@ expr_simple
new ExprString(data->symbols.create(path)));
}
| URI {
static bool noURLLiterals = settings.isExperimentalFeatureEnabled("no-url-literals");
static bool noURLLiterals = settings()->isExperimentalFeatureEnabled("no-url-literals");
if (noURLLiterals)
throw ParseError({
.hint = hintfmt("URL literals are disabled"),
Expand Down
12 changes: 6 additions & 6 deletions src/libexpr/primops.cc
Expand Up @@ -906,7 +906,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
}

if (i->name == state.sContentAddressed) {
settings.requireExperimentalFeature("ca-derivations");
settings()->requireExperimentalFeature("ca-derivations");
contentAddressed = state.forceBool(*i->value, pos);
}

Expand Down Expand Up @@ -1204,7 +1204,7 @@ static void prim_storePath(EvalState & state, const Pos & pos, Value * * args, V
.errPos = pos
});
auto path2 = state.store->toStorePath(path).first;
if (!settings.readOnlyMode)
if (!settings()->readOnlyMode)
state.store->ensurePath(path2);
context.insert(state.store->printStorePath(path2));
mkString(v, path, context);
Expand Down Expand Up @@ -1643,7 +1643,7 @@ static void prim_toFile(EvalState & state, const Pos & pos, Value * * args, Valu
refs.insert(state.store->parseStorePath(path));
}

auto storePath = state.store->printStorePath(settings.readOnlyMode
auto storePath = state.store->printStorePath(settings()->readOnlyMode
? state.store->computeStorePathForText(name, contents, refs)
: state.store->addTextToStore(name, contents, refs, state.repair));

Expand Down Expand Up @@ -1767,7 +1767,7 @@ static void addPath(EvalState & state, const Pos & pos, const string & name, con
expectedStorePath = state.store->makeFixedOutputPath(method, *expectedHash, name);
Path dstPath;
if (!expectedHash || !state.store->isValidPath(*expectedStorePath)) {
dstPath = state.store->printStorePath(settings.readOnlyMode
dstPath = state.store->printStorePath(settings()->readOnlyMode
? state.store->computeStorePathForPath(name, path, method, htSHA256, filter).first
: state.store->addToStore(name, path, method, htSHA256, filter, state.repair));
if (expectedHash && expectedStorePath != state.store->parseStorePath(dstPath))
Expand Down Expand Up @@ -3517,7 +3517,7 @@ void EvalState::createBaseEnv()
}

if (!evalSettings.pureEval) {
mkString(v, settings.thisSystem.get());
mkString(v, settings()->thisSystem.get());
addConstant("__currentSystem", v);
}

Expand Down Expand Up @@ -3554,7 +3554,7 @@ void EvalState::createBaseEnv()

if (RegisterPrimOp::primOps)
for (auto & primOp : *RegisterPrimOp::primOps)
if (!primOp.requiredFeature || settings.isExperimentalFeatureEnabled(*primOp.requiredFeature))
if (!primOp.requiredFeature || settings()->isExperimentalFeatureEnabled(*primOp.requiredFeature))
addPrimOp({
.fun = primOp.fun,
.arity = std::max(primOp.args.size(), primOp.arity),
Expand Down
2 changes: 1 addition & 1 deletion src/libexpr/primops/context.cc
Expand Up @@ -150,7 +150,7 @@ static void prim_appendContext(EvalState & state, const Pos & pos, Value * * arg
.hint = hintfmt("Context key '%s' is not a store path", i.name),
.errPos = *i.pos
});
if (!settings.readOnlyMode)
if (!settings()->readOnlyMode)
state.store->ensurePath(state.store->parseStorePath(i.name));
state.forceAttrs(*i.value, *i.pos);
auto iter = i.value->attrs->find(sPath);
Expand Down
2 changes: 1 addition & 1 deletion src/libexpr/primops/fetchTree.cc
Expand Up @@ -148,7 +148,7 @@ static void fetchTree(

static void prim_fetchTree(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
settings.requireExperimentalFeature("flakes");
settings()->requireExperimentalFeature("flakes");
fetchTree(state, pos, args, v, std::nullopt);
}

Expand Down
2 changes: 1 addition & 1 deletion src/libfetchers/cache.cc
Expand Up @@ -105,7 +105,7 @@ struct CacheImpl : Cache
inAttrsJson, infoJson, store->printStorePath(storePath));

return Result {
.expired = !immutable && (settings.tarballTtl.get() == 0 || timestamp + settings.tarballTtl < time(0)),
.expired = !immutable && (settings()->tarballTtl.get() == 0 || timestamp + settings()->tarballTtl < time(0)),
.infoAttrs = jsonToAttrs(nlohmann::json::parse(infoJson)),
.storePath = std::move(storePath)
};
Expand Down
6 changes: 3 additions & 3 deletions src/libfetchers/git.cc
Expand Up @@ -235,10 +235,10 @@ struct GitInputScheme : InputScheme

/* This is an unclean working tree. So copy all tracked files. */

if (!settings.allowDirty)
if (!settings()->allowDirty)
throw Error("Git tree '%s' is dirty", actualUrl);

if (settings.warnDirty)
if (settings()->warnDirty)
warn("Git tree '%s' is dirty", actualUrl);

auto gitOpts = Strings({ "-C", actualUrl, "ls-files", "-z" });
Expand Down Expand Up @@ -341,7 +341,7 @@ struct GitInputScheme : InputScheme
git fetch to update the local ref to the remote ref. */
struct stat st;
doFetch = stat(localRefFile.c_str(), &st) != 0 ||
(uint64_t) st.st_mtime + settings.tarballTtl <= (uint64_t) now;
(uint64_t) st.st_mtime + settings()->tarballTtl <= (uint64_t) now;
}

if (doFetch) {
Expand Down
4 changes: 2 additions & 2 deletions src/libfetchers/github.cc
Expand Up @@ -184,7 +184,7 @@ struct GitHubInputScheme : GitArchiveInputScheme

void addAccessToken(std::string & url) const
{
std::string accessToken = settings.githubAccessToken.get();
std::string accessToken = settings()->githubAccessToken.get();
if (accessToken != "")
url += "?access_token=" + accessToken;
}
Expand Down Expand Up @@ -257,7 +257,7 @@ struct GitLabInputScheme : GitArchiveInputScheme
input.getRev()->to_string(Base16, false));

/* # FIXME: add privat token auth (`curl --header "PRIVATE-TOKEN: <your_access_token>"`)
std::string accessToken = settings.githubAccessToken.get();
std::string accessToken = settings()->githubAccessToken.get();
if (accessToken != "")
url += "?access_token=" + accessToken;*/

Expand Down
4 changes: 2 additions & 2 deletions src/libfetchers/mercurial.cc
Expand Up @@ -136,10 +136,10 @@ struct MercurialInputScheme : InputScheme
/* This is an unclean working tree. So copy all tracked
files. */

if (!settings.allowDirty)
if (!settings()->allowDirty)
throw Error("Mercurial tree '%s' is unclean", actualUrl);

if (settings.warnDirty)
if (settings()->warnDirty)
warn("Mercurial tree '%s' is unclean", actualUrl);

input.attrs.insert_or_assign("ref", chomp(runProgram("hg", true, { "branch", "-R", actualUrl })));
Expand Down
4 changes: 2 additions & 2 deletions src/libfetchers/registry.cc
Expand Up @@ -101,7 +101,7 @@ void Registry::remove(const Input & input)

static Path getSystemRegistryPath()
{
return settings.nixConfDir + "/registry.json";
return settings()->nixConfDir + "/registry.json";
}

static std::shared_ptr<Registry> getSystemRegistry()
Expand Down Expand Up @@ -142,7 +142,7 @@ void overrideRegistry(
static std::shared_ptr<Registry> getGlobalRegistry(ref<Store> store)
{
static auto reg = [&]() {
auto path = settings.flakeRegistry.get();
auto path = settings()->flakeRegistry.get();

if (!hasPrefix(path, "/")) {
auto storePath = downloadFile(store, path, "flake-registry.json", false).storePath;
Expand Down
2 changes: 1 addition & 1 deletion src/libmain/common-args.cc
Expand Up @@ -55,7 +55,7 @@ MixCommonArgs::MixCommonArgs(const string & programName)
.description = "maximum number of parallel builds",
.labels = Strings{"jobs"},
.handler = {[=](std::string s) {
settings.set("max-jobs", s);
settings()->set("max-jobs", s);
}}
});

Expand Down
32 changes: 17 additions & 15 deletions src/libmain/shared.cc
Expand Up @@ -77,7 +77,7 @@ void printMissing(ref<Store> store, const StorePathSet & willBuild,

if (!unknown.empty()) {
printMsg(lvl, fmt("don't know how to build these paths%s:",
(settings.readOnlyMode ? " (may be caused by read-only store access)" : "")));
(settings()->readOnlyMode ? " (may be caused by read-only store access)" : "")));
for (auto & i : unknown)
printMsg(lvl, fmt(" %s", store->printStorePath(i)));
}
Expand Down Expand Up @@ -182,33 +182,33 @@ LegacyArgs::LegacyArgs(const std::string & programName,
.longName = "no-build-output",
.shortName = 'Q',
.description = "do not show build output",
.handler = {[&]() {setLogFormat(LogFormat::raw); }},
.handler = {[&]() {setLogFormat(LogFormat("raw")); }},
});

addFlag({
.longName = "keep-failed",
.shortName ='K',
.description = "keep temporary directories of failed builds",
.handler = {&(bool&) settings.keepFailed, true},
.handler = {&(bool&) settings()->keepFailed, true},
});

addFlag({
.longName = "keep-going",
.shortName ='k',
.description = "keep going after a build fails",
.handler = {&(bool&) settings.keepGoing, true},
.handler = {&(bool&) settings()->keepGoing, true},
});

addFlag({
.longName = "fallback",
.description = "build from source if substitution fails",
.handler = {&(bool&) settings.tryFallback, true},
.handler = {&(bool&) settings()->tryFallback, true},
});

auto intSettingAlias = [&](char shortName, const std::string & longName,
const std::string & description, const std::string & dest) {
mkFlag<unsigned int>(shortName, longName, description, [=](unsigned int n) {
settings.set(dest, std::to_string(n));
settings()->set(dest, std::to_string(n));
});
};

Expand All @@ -217,7 +217,7 @@ LegacyArgs::LegacyArgs(const std::string & programName,
intSettingAlias(0, "timeout", "number of seconds before a build is killed", "timeout");

mkFlag(0, "readonly-mode", "do not write to the Nix store",
&settings.readOnlyMode);
&settings()->readOnlyMode);

mkFlag(0, "no-gc-warning", "disable warning about not using '--add-root'",
&gcWarning, false);
Expand All @@ -226,7 +226,7 @@ LegacyArgs::LegacyArgs(const std::string & programName,
.longName = "store",
.description = "URI of the Nix store to use",
.labels = {"store-uri"},
.handler = {&(std::string&) settings.storeUri},
.handler = {&(std::string&) settings()->storeUri},
});
}

Expand Down Expand Up @@ -277,15 +277,15 @@ void printVersion(const string & programName)
#if HAVE_SODIUM
cfg.push_back("signed-caches");
#endif
std::cout << "System type: " << settings.thisSystem << "\n";
std::cout << "Additional system types: " << concatStringsSep(", ", settings.extraPlatforms.get()) << "\n";
std::cout << "System type: " << settings()->thisSystem << "\n";
std::cout << "Additional system types: " << concatStringsSep(", ", settings()->extraPlatforms.get()) << "\n";
std::cout << "Features: " << concatStringsSep(", ", cfg) << "\n";
std::cout << "System configuration file: " << settings.nixConfDir + "/nix.conf" << "\n";
std::cout << "System configuration file: " << settings()->nixConfDir + "/nix.conf" << "\n";
std::cout << "User configuration files: " <<
concatStringsSep(":", settings.nixUserConfFiles)
concatStringsSep(":", settings()->nixUserConfFiles)
<< "\n";
std::cout << "Store directory: " << settings.nixStore << "\n";
std::cout << "State directory: " << settings.nixStateDir << "\n";
std::cout << "Store directory: " << settings()->nixStore << "\n";
std::cout << "State directory: " << settings()->nixStateDir << "\n";
}
throw Exit();
}
Expand All @@ -294,7 +294,7 @@ void printVersion(const string & programName)
void showManPage(const string & name)
{
restoreSignals();
setenv("MANPATH", settings.nixManDir.c_str(), 1);
setenv("MANPATH", settings()->nixManDir.c_str(), 1);
execlp("man", "man", name.c_str(), nullptr);
throw SysError("command 'man %1%' failed", name.c_str());
}
Expand Down Expand Up @@ -403,3 +403,5 @@ PrintFreed::~PrintFreed()
Exit::~Exit() { }

}


0 comments on commit b52f6be

Please sign in to comment.