From ba87b08f8529e4d9f8c58d8c625152058ceadb75 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 22 Nov 2019 16:06:44 +0100 Subject: [PATCH] getEnv(): Return std::optional This allows distinguishing between an empty value and no value. --- src/libexpr/eval.cc | 12 ++++++------ src/libexpr/primops.cc | 2 +- src/libstore/build.cc | 4 ++-- src/libstore/gc.cc | 6 +++--- src/libstore/globals.cc | 22 +++++++++++----------- src/libstore/globals.hh | 2 +- src/libstore/local-store.hh | 2 +- src/libstore/ssh.cc | 2 +- src/libutil/util.cc | 35 +++++++++++++++-------------------- src/libutil/util.hh | 2 +- src/nix-build/nix-build.cc | 17 +++++++++-------- src/nix-daemon/nix-daemon.cc | 5 +++-- src/nix-env/nix-env.cc | 2 +- src/nix/command.cc | 2 +- src/nix/doctor.cc | 4 ++-- src/nix/run.cc | 2 +- src/nix/upgrade-nix.cc | 2 +- 17 files changed, 60 insertions(+), 63 deletions(-) diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 3c3d1a324..bb6b23ff1 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -217,7 +217,7 @@ void initGC() that GC_expand_hp() causes a lot of virtual, but not physical (resident) memory to be allocated. This might be a problem on systems that don't overcommit. */ - if (!getenv("GC_INITIAL_HEAP_SIZE")) { + if (!getEnv("GC_INITIAL_HEAP_SIZE")) { size_t size = 32 * 1024 * 1024; #if HAVE_SYSCONF && defined(_SC_PAGESIZE) && defined(_SC_PHYS_PAGES) size_t maxSize = 384 * 1024 * 1024; @@ -306,7 +306,7 @@ EvalState::EvalState(const Strings & _searchPath, ref store) , baseEnv(allocEnv(128)) , staticBaseEnv(false, 0) { - countCalls = getEnv("NIX_COUNT_CALLS", "0") != "0"; + countCalls = getEnv("NIX_COUNT_CALLS").value_or("0") != "0"; assert(gcInitialised); @@ -314,7 +314,7 @@ EvalState::EvalState(const Strings & _searchPath, ref store) /* Initialise the Nix expression search path. */ if (!evalSettings.pureEval) { - Strings paths = parseNixPath(getEnv("NIX_PATH", "")); + Strings paths = parseNixPath(getEnv("NIX_PATH").value_or("")); for (auto & i : _searchPath) addToSearchPath(i); for (auto & i : paths) addToSearchPath(i); } @@ -1753,7 +1753,7 @@ bool EvalState::eqValues(Value & v1, Value & v2) void EvalState::printStats() { - bool showStats = getEnv("NIX_SHOW_STATS", "0") != "0"; + bool showStats = getEnv("NIX_SHOW_STATS").value_or("0") != "0"; struct rusage buf; getrusage(RUSAGE_SELF, &buf); @@ -1769,7 +1769,7 @@ void EvalState::printStats() GC_get_heap_usage_safe(&heapSize, 0, 0, 0, &totalBytes); #endif if (showStats) { - auto outPath = getEnv("NIX_SHOW_STATS_PATH","-"); + auto outPath = getEnv("NIX_SHOW_STATS_PATH").value_or("-"); std::fstream fs; if (outPath != "-") fs.open(outPath, std::fstream::out); @@ -1861,7 +1861,7 @@ void EvalState::printStats() } } - if (getEnv("NIX_SHOW_SYMBOLS", "0") != "0") { + if (getEnv("NIX_SHOW_SYMBOLS").value_or("0") != "0") { auto list = topObj.list("symbols"); symbols.dump([&](const std::string & s) { list.elem(s); }); } diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index deaffa605..2cc03fe61 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -469,7 +469,7 @@ static void prim_tryEval(EvalState & state, const Pos & pos, Value * * args, Val static void prim_getEnv(EvalState & state, const Pos & pos, Value * * args, Value & v) { string name = state.forceStringNoCtx(*args[0], pos); - mkString(v, evalSettings.restrictEval || evalSettings.pureEval ? "" : getEnv(name)); + mkString(v, evalSettings.restrictEval || evalSettings.pureEval ? "" : getEnv(name).value_or("")); } diff --git a/src/libstore/build.cc b/src/libstore/build.cc index 35a5388c6..67ccfcee0 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -2503,7 +2503,7 @@ void DerivationGoal::initEnv() already know the cryptographic hash of the output). */ if (fixedOutput) { for (auto & i : parsedDrv->getStringsAttr("impureEnvVars").value_or(Strings())) - env[i] = getEnv(i); + env[i] = getEnv(i).value_or(""); } /* Currently structured log messages piggyback on stderr, but we @@ -3075,7 +3075,7 @@ void DerivationGoal::runChild() /* The tmpDir in scope points at the temporary build directory for our derivation. Some packages try different mechanisms to find temporary directories, so we want to open up a broader place for them to dump their files, if needed. */ - Path globalTmpDir = canonPath(getEnv("TMPDIR", "/tmp"), true); + Path globalTmpDir = canonPath(getEnv("TMPDIR").value_or("/tmp"), true); /* They don't like trailing slashes on subpath directives */ if (globalTmpDir.back() == '/') globalTmpDir.pop_back(); diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index 7d3da1cc8..842980fb7 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -870,11 +870,11 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) void LocalStore::autoGC(bool sync) { - static auto fakeFreeSpaceFile = getEnv("_NIX_TEST_FREE_SPACE_FILE", ""); + static auto fakeFreeSpaceFile = getEnv("_NIX_TEST_FREE_SPACE_FILE"); auto getAvail = [this]() -> uint64_t { - if (!fakeFreeSpaceFile.empty()) - return std::stoll(readFile(fakeFreeSpaceFile)); + if (fakeFreeSpaceFile) + return std::stoll(readFile(*fakeFreeSpaceFile)); struct statvfs st; if (statvfs(realStoreDir.c_str(), &st)) diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc index 249c36673..aa0823f41 100644 --- a/src/libstore/globals.cc +++ b/src/libstore/globals.cc @@ -32,20 +32,20 @@ static GlobalConfig::Register r1(&settings); Settings::Settings() : nixPrefix(NIX_PREFIX) - , nixStore(canonPath(getEnv("NIX_STORE_DIR", getEnv("NIX_STORE", NIX_STORE_DIR)))) - , nixDataDir(canonPath(getEnv("NIX_DATA_DIR", NIX_DATA_DIR))) - , nixLogDir(canonPath(getEnv("NIX_LOG_DIR", NIX_LOG_DIR))) - , nixStateDir(canonPath(getEnv("NIX_STATE_DIR", NIX_STATE_DIR))) - , nixConfDir(canonPath(getEnv("NIX_CONF_DIR", NIX_CONF_DIR))) - , nixLibexecDir(canonPath(getEnv("NIX_LIBEXEC_DIR", NIX_LIBEXEC_DIR))) - , nixBinDir(canonPath(getEnv("NIX_BIN_DIR", NIX_BIN_DIR))) + , nixStore(canonPath(getEnv("NIX_STORE_DIR").value_or(getEnv("NIX_STORE").value_or(NIX_STORE_DIR)))) + , nixDataDir(canonPath(getEnv("NIX_DATA_DIR").value_or(NIX_DATA_DIR))) + , nixLogDir(canonPath(getEnv("NIX_LOG_DIR").value_or(NIX_LOG_DIR))) + , nixStateDir(canonPath(getEnv("NIX_STATE_DIR").value_or(NIX_STATE_DIR))) + , nixConfDir(canonPath(getEnv("NIX_CONF_DIR").value_or(NIX_CONF_DIR))) + , nixLibexecDir(canonPath(getEnv("NIX_LIBEXEC_DIR").value_or(NIX_LIBEXEC_DIR))) + , nixBinDir(canonPath(getEnv("NIX_BIN_DIR").value_or(NIX_BIN_DIR))) , nixManDir(canonPath(NIX_MAN_DIR)) , nixDaemonSocketFile(canonPath(nixStateDir + DEFAULT_SOCKET_PATH)) { buildUsersGroup = getuid() == 0 ? "nixbld" : ""; - lockCPU = getEnv("NIX_AFFINITY_HACK", "1") == "1"; + lockCPU = getEnv("NIX_AFFINITY_HACK") == "1"; - caFile = getEnv("NIX_SSL_CERT_FILE", getEnv("SSL_CERT_FILE", "")); + caFile = getEnv("NIX_SSL_CERT_FILE").value_or(getEnv("SSL_CERT_FILE").value_or("")); if (caFile == "") { for (auto & fn : {"/etc/ssl/certs/ca-certificates.crt", "/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt"}) if (pathExists(fn)) { @@ -56,9 +56,9 @@ Settings::Settings() /* Backwards compatibility. */ auto s = getEnv("NIX_REMOTE_SYSTEMS"); - if (s != "") { + if (s) { Strings ss; - for (auto & p : tokenizeString(s, ":")) + for (auto & p : tokenizeString(*s, ":")) ss.push_back("@" + p); builders = concatStringsSep(" ", ss); } diff --git a/src/libstore/globals.hh b/src/libstore/globals.hh index 1221e4db7..3eb2f698c 100644 --- a/src/libstore/globals.hh +++ b/src/libstore/globals.hh @@ -66,7 +66,7 @@ public: /* File name of the socket the daemon listens to. */ Path nixDaemonSocketFile; - Setting storeUri{this, getEnv("NIX_REMOTE", "auto"), "store", + Setting storeUri{this, getEnv("NIX_REMOTE").value_or("auto"), "store", "The default Nix store to use."}; Setting keepFailed{this, false, "keep-failed", diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh index 5aa6b0519..1d4b88898 100644 --- a/src/libstore/local-store.hh +++ b/src/libstore/local-store.hh @@ -107,7 +107,7 @@ private: public: // Hack for build-remote.cc. - PathSet locksHeld = tokenizeString(getEnv("NIX_HELD_LOCKS")); + PathSet locksHeld; /* Initialise the local store, upgrading the schema if necessary. */ diff --git a/src/libstore/ssh.cc b/src/libstore/ssh.cc index 5e0e44935..ac3ccd63d 100644 --- a/src/libstore/ssh.cc +++ b/src/libstore/ssh.cc @@ -16,7 +16,7 @@ SSHMaster::SSHMaster(const std::string & host, const std::string & keyFile, bool void SSHMaster::addCommonSSHOpts(Strings & args) { - for (auto & i : tokenizeString(getEnv("NIX_SSHOPTS"))) + for (auto & i : tokenizeString(getEnv("NIX_SSHOPTS").value_or(""))) args.push_back(i); if (!keyFile.empty()) args.insert(args.end(), {"-i", keyFile}); diff --git a/src/libutil/util.cc b/src/libutil/util.cc index 79716c5a7..b4d444a67 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -58,10 +58,11 @@ std::string SysError::addErrno(const std::string & s) } -string getEnv(const string & key, const string & def) +std::optional getEnv(const std::string & key) { char * value = getenv(key.c_str()); - return value ? string(value) : def; + if (!value) return {}; + return std::string(value); } @@ -438,7 +439,7 @@ void deletePath(const Path & path, unsigned long long & bytesFreed) static Path tempName(Path tmpRoot, const Path & prefix, bool includePid, int & counter) { - tmpRoot = canonPath(tmpRoot.empty() ? getEnv("TMPDIR", "/tmp") : tmpRoot, true); + tmpRoot = canonPath(tmpRoot.empty() ? getEnv("TMPDIR").value_or("/tmp") : tmpRoot, true); if (includePid) return (format("%1%/%2%-%3%-%4%") % tmpRoot % prefix % getpid() % counter++).str(); else @@ -480,7 +481,7 @@ Path createTempDir(const Path & tmpRoot, const Path & prefix, std::string getUserName() { auto pw = getpwuid(geteuid()); - std::string name = pw ? pw->pw_name : getEnv("USER", ""); + std::string name = pw ? pw->pw_name : getEnv("USER").value_or(""); if (name.empty()) throw Error("cannot figure out user name"); return name; @@ -488,8 +489,8 @@ std::string getUserName() static Lazy getHome2([]() { - Path homeDir = getEnv("HOME"); - if (homeDir.empty()) { + auto homeDir = getEnv("HOME"); + if (!homeDir) { std::vector buf(16384); struct passwd pwbuf; struct passwd * pw; @@ -498,7 +499,7 @@ static Lazy getHome2([]() { throw Error("cannot determine user's home directory"); homeDir = pw->pw_dir; } - return homeDir; + return *homeDir; }); Path getHome() { return getHome2(); } @@ -506,25 +507,21 @@ Path getHome() { return getHome2(); } Path getCacheDir() { - Path cacheDir = getEnv("XDG_CACHE_HOME"); - if (cacheDir.empty()) - cacheDir = getHome() + "/.cache"; - return cacheDir; + auto cacheDir = getEnv("XDG_CACHE_HOME"); + return cacheDir ? *cacheDir : getHome() + "/.cache"; } Path getConfigDir() { - Path configDir = getEnv("XDG_CONFIG_HOME"); - if (configDir.empty()) - configDir = getHome() + "/.config"; - return configDir; + auto configDir = getEnv("XDG_CONFIG_HOME"); + return configDir ? *configDir : getHome() + "/.config"; } std::vector getConfigDirs() { Path configHome = getConfigDir(); - string configDirs = getEnv("XDG_CONFIG_DIRS"); + string configDirs = getEnv("XDG_CONFIG_DIRS").value_or(""); std::vector result = tokenizeString>(configDirs, ":"); result.insert(result.begin(), configHome); return result; @@ -533,10 +530,8 @@ std::vector getConfigDirs() Path getDataDir() { - Path dataDir = getEnv("XDG_DATA_HOME"); - if (dataDir.empty()) - dataDir = getHome() + "/.local/share"; - return dataDir; + auto dataDir = getEnv("XDG_DATA_HOME"); + return dataDir ? *dataDir : getHome() + "/.local/share"; } diff --git a/src/libutil/util.hh b/src/libutil/util.hh index e8fed353c..b9f9ea882 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -35,7 +35,7 @@ extern const std::string nativeSystem; /* Return an environment variable. */ -string getEnv(const string & key, const string & def = ""); +std::optional getEnv(const std::string & key); /* Get the entire environment. */ std::map getEnv(); diff --git a/src/nix-build/nix-build.cc b/src/nix-build/nix-build.cc index 1c5d71681..c506f9b0a 100755 --- a/src/nix-build/nix-build.cc +++ b/src/nix-build/nix-build.cc @@ -344,9 +344,9 @@ static void _main(int argc, char * * argv) /* Figure out what bash shell to use. If $NIX_BUILD_SHELL is not set, then build bashInteractive from . */ - auto shell = getEnv("NIX_BUILD_SHELL", ""); + auto shell = getEnv("NIX_BUILD_SHELL"); - if (shell == "") { + if (!shell) { try { auto expr = state->parseExprFromString("(import {}).bashInteractive", absPath(".")); @@ -382,7 +382,8 @@ static void _main(int argc, char * * argv) // Set the environment. auto env = getEnv(); - auto tmp = getEnv("TMPDIR", getEnv("XDG_RUNTIME_DIR", "/tmp")); + auto tmp = getEnv("TMPDIR"); + if (!tmp) tmp = getEnv("XDG_RUNTIME_DIR").value_or("/tmp"); if (pure) { decltype(env) newEnv; @@ -394,7 +395,7 @@ static void _main(int argc, char * * argv) env["__ETC_PROFILE_SOURCED"] = "1"; } - env["NIX_BUILD_TOP"] = env["TMPDIR"] = env["TEMPDIR"] = env["TMP"] = env["TEMP"] = tmp; + env["NIX_BUILD_TOP"] = env["TMPDIR"] = env["TEMPDIR"] = env["TMP"] = env["TEMP"] = *tmp; env["NIX_STORE"] = store->storeDir; env["NIX_BUILD_CORES"] = std::to_string(settings.buildCores); @@ -439,8 +440,8 @@ static void _main(int argc, char * * argv) (Path) tmpDir, (pure ? "" : "p=$PATH; "), (pure ? "" : "PATH=$PATH:$p; unset p; "), - dirOf(shell), - shell, + dirOf(*shell), + *shell, (getenv("TZ") ? (string("export TZ='") + getenv("TZ") + "'; ") : ""), envCommand)); @@ -460,9 +461,9 @@ static void _main(int argc, char * * argv) restoreSignals(); - execvp(shell.c_str(), argPtrs.data()); + execvp(shell->c_str(), argPtrs.data()); - throw SysError("executing shell '%s'", shell); + throw SysError("executing shell '%s'", *shell); } else { diff --git a/src/nix-daemon/nix-daemon.cc b/src/nix-daemon/nix-daemon.cc index 65ae88faf..9a4d60726 100644 --- a/src/nix-daemon/nix-daemon.cc +++ b/src/nix-daemon/nix-daemon.cc @@ -161,8 +161,9 @@ static void daemonLoop(char * * argv) AutoCloseFD fdSocket; /* Handle socket-based activation by systemd. */ - if (getEnv("LISTEN_FDS") != "") { - if (getEnv("LISTEN_PID") != std::to_string(getpid()) || getEnv("LISTEN_FDS") != "1") + auto listenFds = getEnv("LISTEN_FDS"); + if (listenFds) { + if (getEnv("LISTEN_PID") != std::to_string(getpid()) || listenFds != "1") throw Error("unexpected systemd environment variables"); fdSocket = SD_LISTEN_FDS_START; closeOnExec(fdSocket.get()); diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index 199dc92aa..a9c743955 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -1425,7 +1425,7 @@ static int _main(int argc, char * * argv) globals.instSource.autoArgs = myArgs.getAutoArgs(*globals.state); if (globals.profile == "") - globals.profile = getEnv("NIX_PROFILE", ""); + globals.profile = getEnv("NIX_PROFILE").value_or(""); if (globals.profile == "") { Path profileLink = getHome() + "/.nix-profile"; diff --git a/src/nix/command.cc b/src/nix/command.cc index 97c2fcf1c..724f03e5d 100644 --- a/src/nix/command.cc +++ b/src/nix/command.cc @@ -156,7 +156,7 @@ void StorePathCommand::run(ref store) Strings editorFor(const Pos & pos) { - auto editor = getEnv("EDITOR", "cat"); + auto editor = getEnv("EDITOR").value_or("cat"); auto args = tokenizeString(editor); if (pos.line > 0 && ( editor.find("emacs") != std::string::npos || diff --git a/src/nix/doctor.cc b/src/nix/doctor.cc index 795236c5f..481c93b45 100644 --- a/src/nix/doctor.cc +++ b/src/nix/doctor.cc @@ -68,7 +68,7 @@ struct CmdDoctor : StoreCommand { PathSet dirs; - for (auto & dir : tokenizeString(getEnv("PATH"), ":")) + for (auto & dir : tokenizeString(getEnv("PATH").value_or(""), ":")) if (pathExists(dir + "/nix-env")) dirs.insert(dirOf(canonPath(dir + "/nix-env", true))); @@ -87,7 +87,7 @@ struct CmdDoctor : StoreCommand { PathSet dirs; - for (auto & dir : tokenizeString(getEnv("PATH"), ":")) { + for (auto & dir : tokenizeString(getEnv("PATH").value_or(""), ":")) { Path profileDir = dirOf(dir); try { Path userEnv = canonPath(profileDir, true); diff --git a/src/nix/run.cc b/src/nix/run.cc index 90b76d666..fd4f92282 100644 --- a/src/nix/run.cc +++ b/src/nix/run.cc @@ -128,7 +128,7 @@ struct CmdRun : InstallablesCommand std::queue todo; for (auto & path : outPaths) todo.push(path); - auto unixPath = tokenizeString(getEnv("PATH"), ":"); + auto unixPath = tokenizeString(getEnv("PATH").value_or(""), ":"); while (!todo.empty()) { Path path = todo.front(); diff --git a/src/nix/upgrade-nix.cc b/src/nix/upgrade-nix.cc index 35c44a70c..6c9e37d04 100644 --- a/src/nix/upgrade-nix.cc +++ b/src/nix/upgrade-nix.cc @@ -106,7 +106,7 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand { Path where; - for (auto & dir : tokenizeString(getEnv("PATH"), ":")) + for (auto & dir : tokenizeString(getEnv("PATH").value_or(""), ":")) if (pathExists(dir + "/nix-env")) { where = dir; break;