Skip to content

Commit

Permalink
Use envvars NIX_CACHE_HOME, NIX_CONFIG_HOME, NIX_DATA_HOME, NIX_STATE…
Browse files Browse the repository at this point in the history
…_HOME if defined (#11351)
  • Loading branch information
noamraph authored Sep 11, 2024
1 parent c60e1be commit 38bfbb2
Show file tree
Hide file tree
Showing 17 changed files with 117 additions and 47 deletions.
14 changes: 14 additions & 0 deletions doc/manual/rl-next/add-nix-state-home.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
synopsis: Use envvars NIX_CACHE_HOME, NIX_CONFIG_HOME, NIX_DATA_HOME, NIX_STATE_HOME if defined
prs: [11351]
---

Added new environment variables:

- `NIX_CACHE_HOME`
- `NIX_CONFIG_HOME`
- `NIX_DATA_HOME`
- `NIX_STATE_HOME`

Each, if defined, takes precedence over the corresponding [XDG environment variable](@docroot@/command-ref/env-common.md#xdg-base-directories).
This provides more fine-grained control over where Nix looks for files, and allows to have a stand-alone Nix environment, which only uses files in a specific directory, and doesn't interfere with the user environment.
15 changes: 14 additions & 1 deletion doc/manual/src/command-ref/env-common.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,19 @@ The following environment variables are used to determine locations of various s
- [`XDG_STATE_HOME`]{#env-XDG_STATE_HOME} (default `~/.local/state`)
- [`XDG_CACHE_HOME`]{#env-XDG_CACHE_HOME} (default `~/.cache`)
[XDG Base Directory Specification]: https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
[`use-xdg-base-directories`]: @docroot@/command-ref/conf-file.md#conf-use-xdg-base-directories
In addition, setting the following environment variables overrides the XDG base directories:
- [`NIX_CONFIG_HOME`]{#env-NIX_CONFIG_HOME} (default `$XDG_CONFIG_HOME/nix`)
- [`NIX_STATE_HOME`]{#env-NIX_STATE_HOME} (default `$XDG_STATE_HOME/nix`)
- [`NIX_CACHE_HOME`]{#env-NIX_CACHE_HOME} (default `$XDG_CACHE_HOME/nix`)
When [`use-xdg-base-directories`] is enabled, the configuration directory is:
1. `$NIX_CONFIG_HOME`, if it is defined
2. Otherwise, `$XDG_CONFIG_HOME/nix`, if `XDG_CONFIG_HOME` is defined
3. Otherwise, `~/.config/nix`.
Likewise for the state and cache directories.
44 changes: 24 additions & 20 deletions scripts/nix-profile.sh.in
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,33 @@ if [ -n "$HOME" ] && [ -n "$USER" ]; then

# Set up the per-user profile.

NIX_LINK="$HOME/.nix-profile"
if [ -n "${XDG_STATE_HOME-}" ]; then
NIX_LINK_NEW="$XDG_STATE_HOME/nix/profile"
if [ -n "$NIX_STATE_HOME" ]; then
NIX_LINK="$NIX_STATE_HOME/profile"
else
NIX_LINK_NEW="$HOME/.local/state/nix/profile"
fi
if [ -e "$NIX_LINK_NEW" ]; then
if [ -t 2 ] && [ -e "$NIX_LINK" ]; then
warning="\033[1;35mwarning:\033[0m"
printf "$warning Both %s and legacy %s exist; using the former.\n" "$NIX_LINK_NEW" "$NIX_LINK" 1>&2
if [ "$(realpath "$NIX_LINK")" = "$(realpath "$NIX_LINK_NEW")" ]; then
printf " Since the profiles match, you can safely delete either of them.\n" 1>&2
else
# This should be an exceptionally rare occasion: the only way to get it would be to
# 1. Update to newer Nix;
# 2. Remove .nix-profile;
# 3. Set the $NIX_LINK_NEW to something other than the default user profile;
# 4. Roll back to older Nix.
# If someone did all that, they can probably figure out how to migrate the profile.
printf "$warning Profiles do not match. You should manually migrate from %s to %s.\n" "$NIX_LINK" "$NIX_LINK_NEW" 1>&2
NIX_LINK="$HOME/.nix-profile"
if [ -n "${XDG_STATE_HOME-}" ]; then
NIX_LINK_NEW="$XDG_STATE_HOME/nix/profile"
else
NIX_LINK_NEW="$HOME/.local/state/nix/profile"
fi
if [ -e "$NIX_LINK_NEW" ]; then
if [ -t 2 ] && [ -e "$NIX_LINK" ]; then
warning="\033[1;35mwarning:\033[0m"
printf "$warning Both %s and legacy %s exist; using the former.\n" "$NIX_LINK_NEW" "$NIX_LINK" 1>&2
if [ "$(realpath "$NIX_LINK")" = "$(realpath "$NIX_LINK_NEW")" ]; then
printf " Since the profiles match, you can safely delete either of them.\n" 1>&2
else
# This should be an exceptionally rare occasion: the only way to get it would be to
# 1. Update to newer Nix;
# 2. Remove .nix-profile;
# 3. Set the $NIX_LINK_NEW to something other than the default user profile;
# 4. Roll back to older Nix.
# If someone did all that, they can probably figure out how to migrate the profile.
printf "$warning Profiles do not match. You should manually migrate from %s to %s.\n" "$NIX_LINK" "$NIX_LINK_NEW" 1>&2
fi
fi
NIX_LINK="$NIX_LINK_NEW"
fi
NIX_LINK="$NIX_LINK_NEW"
fi

# Set up environment.
Expand Down
2 changes: 1 addition & 1 deletion src/libcmd/repl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ NixRepl::NixRepl(const LookupPath & lookupPath, nix::ref<Store> store, ref<EvalS
, getValues(getValues)
, staticEnv(new StaticEnv(nullptr, state->staticBaseEnv.get()))
, runNixPtr{runNix}
, interacter(make_unique<ReadlineLikeInteracter>(getDataDir() + "/nix/repl-history"))
, interacter(make_unique<ReadlineLikeInteracter>(getDataDir() + "/repl-history"))
{
}

Expand Down
2 changes: 1 addition & 1 deletion src/libexpr/eval-cache.cc
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ struct AttrDb
{
auto state(_state->lock());

Path cacheDir = getCacheDir() + "/nix/eval-cache-v5";
Path cacheDir = getCacheDir() + "/eval-cache-v5";
createDirs(cacheDir);

Path dbPath = cacheDir + "/" + fingerprint.to_string(HashFormat::Base16, false) + ".sqlite";
Expand Down
2 changes: 1 addition & 1 deletion src/libexpr/eval-settings.cc
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ const std::string & EvalSettings::getCurrentSystem() const
Path getNixDefExpr()
{
return settings.useXDGBaseDirectories
? getStateDir() + "/nix/defexpr"
? getStateDir() + "/defexpr"
: getHome() + "/.nix-defexpr";
}

Expand Down
2 changes: 1 addition & 1 deletion src/libfetchers/cache.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ struct CacheImpl : Cache
{
auto state(_state.lock());

auto dbPath = getCacheDir() + "/nix/fetcher-cache-v2.sqlite";
auto dbPath = getCacheDir() + "/fetcher-cache-v2.sqlite";
createDirs(dirOf(dbPath));

state->db = SQLite(dbPath);
Expand Down
2 changes: 1 addition & 1 deletion src/libfetchers/git-utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1083,7 +1083,7 @@ std::vector<std::tuple<GitRepoImpl::Submodule, Hash>> GitRepoImpl::getSubmodules

ref<GitRepo> getTarballCache()
{
static auto repoDir = std::filesystem::path(getCacheDir()) / "nix" / "tarball-cache";
static auto repoDir = std::filesystem::path(getCacheDir()) / "tarball-cache";

return GitRepo::openRepo(repoDir, true, true);
}
Expand Down
2 changes: 1 addition & 1 deletion src/libfetchers/git.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ bool isCacheFileWithinTtl(time_t now, const struct stat & st)
Path getCachePath(std::string_view key, bool shallow)
{
return getCacheDir()
+ "/nix/gitv3/"
+ "/gitv3/"
+ hashString(HashAlgorithm::SHA256, key).to_string(HashFormat::Nix32, false)
+ (shallow ? "-shallow" : "");
}
Expand Down
2 changes: 1 addition & 1 deletion src/libfetchers/mercurial.cc
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ struct MercurialInputScheme : InputScheme
return makeResult(res->value, res->storePath);
}

Path cacheDir = fmt("%s/nix/hg/%s", getCacheDir(), hashString(HashAlgorithm::SHA256, actualUrl).to_string(HashFormat::Nix32, false));
Path cacheDir = fmt("%s/hg/%s", getCacheDir(), hashString(HashAlgorithm::SHA256, actualUrl).to_string(HashFormat::Nix32, false));

/* If this is a commit hash that we already have, we don't
have to pull again. */
Expand Down
4 changes: 2 additions & 2 deletions src/libfetchers/registry.cc
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ static std::shared_ptr<Registry> getSystemRegistry(const Settings & settings)

Path getUserRegistryPath()
{
return getConfigDir() + "/nix/registry.json";
return getConfigDir() + "/registry.json";
}

std::shared_ptr<Registry> getUserRegistry(const Settings & settings)
Expand Down Expand Up @@ -159,7 +159,7 @@ static std::shared_ptr<Registry> getGlobalRegistry(const Settings & settings, re
if (!hasPrefix(path, "/")) {
auto storePath = downloadFile(store, path, "flake-registry.json").storePath;
if (auto store2 = store.dynamic_pointer_cast<LocalFSStore>())
store2->addPermRoot(storePath, getCacheDir() + "/nix/flake-registry.json");
store2->addPermRoot(storePath, getCacheDir() + "/flake-registry.json");
path = store->toRealPath(storePath);
}

Expand Down
2 changes: 1 addition & 1 deletion src/libflake/flake/config.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ typedef std::map<std::string, std::map<std::string, bool>> TrustedList;

Path trustedListPath()
{
return getDataDir() + "/nix/trusted-settings.json";
return getDataDir() + "/trusted-settings.json";
}

static TrustedList readTrustedList()
Expand Down
2 changes: 1 addition & 1 deletion src/libstore/globals.cc
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ std::vector<Path> getUserConfigFiles()
std::vector<Path> files;
auto dirs = getConfigDirs();
for (auto & dir : dirs) {
files.insert(files.end(), dir + "/nix/nix.conf");
files.insert(files.end(), dir + "/nix.conf");
}
return files;
}
Expand Down
2 changes: 1 addition & 1 deletion src/libstore/nar-info-disk-cache.cc
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ class NarInfoDiskCacheImpl : public NarInfoDiskCache

Sync<State> _state;

NarInfoDiskCacheImpl(Path dbPath = getCacheDir() + "/nix/binary-cache-v6.sqlite")
NarInfoDiskCacheImpl(Path dbPath = getCacheDir() + "/binary-cache-v6.sqlite")
{
auto state(_state.lock());

Expand Down
2 changes: 1 addition & 1 deletion src/libstore/store-api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1315,7 +1315,7 @@ ref<Store> openStore(StoreReference && storeURI)
/* 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";
auto chrootStore = getDataDir() + "/root";
if (!pathExists(chrootStore)) {
try {
createDirs(chrootStore);
Expand Down
57 changes: 48 additions & 9 deletions src/libutil/users.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,42 +7,81 @@ namespace nix {

Path getCacheDir()
{
auto cacheDir = getEnv("XDG_CACHE_HOME");
return cacheDir ? *cacheDir : getHome() + "/.cache";
auto dir = getEnv("NIX_CACHE_HOME");
if (dir) {
return *dir;
} else {
auto xdgDir = getEnv("XDG_CACHE_HOME");
if (xdgDir) {
return *xdgDir + "/nix";
} else {
return getHome() + "/.cache/nix";
}
}
}


Path getConfigDir()
{
auto configDir = getEnv("XDG_CONFIG_HOME");
return configDir ? *configDir : getHome() + "/.config";
auto dir = getEnv("NIX_CONFIG_HOME");
if (dir) {
return *dir;
} else {
auto xdgDir = getEnv("XDG_CONFIG_HOME");
if (xdgDir) {
return *xdgDir + "/nix";
} else {
return getHome() + "/.config/nix";
}
}
}

std::vector<Path> getConfigDirs()
{
Path configHome = getConfigDir();
auto configDirs = getEnv("XDG_CONFIG_DIRS").value_or("/etc/xdg");
std::vector<Path> result = tokenizeString<std::vector<std::string>>(configDirs, ":");
for (auto& p : result) {
p += "/nix";
}
result.insert(result.begin(), configHome);
return result;
}


Path getDataDir()
{
auto dataDir = getEnv("XDG_DATA_HOME");
return dataDir ? *dataDir : getHome() + "/.local/share";
auto dir = getEnv("NIX_DATA_HOME");
if (dir) {
return *dir;
} else {
auto xdgDir = getEnv("XDG_DATA_HOME");
if (xdgDir) {
return *xdgDir + "/nix";
} else {
return getHome() + "/.local/share/nix";
}
}
}

Path getStateDir()
{
auto stateDir = getEnv("XDG_STATE_HOME");
return stateDir ? *stateDir : getHome() + "/.local/state";
auto dir = getEnv("NIX_STATE_HOME");
if (dir) {
return *dir;
} else {
auto xdgDir = getEnv("XDG_STATE_HOME");
if (xdgDir) {
return *xdgDir + "/nix";
} else {
return getHome() + "/.local/state/nix";
}
}
}

Path createNixStateDir()
{
Path dir = getStateDir() + "/nix";
Path dir = getStateDir();
createDirs(dir);
return dir;
}
Expand Down
8 changes: 4 additions & 4 deletions src/libutil/users.hh
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ Path getHomeOf(uid_t userId);
Path getHome();

/**
* @return $XDG_CACHE_HOME or $HOME/.cache.
* @return $NIX_CACHE_HOME or $XDG_CACHE_HOME/nix or $HOME/.cache/nix.
*/
Path getCacheDir();

/**
* @return $XDG_CONFIG_HOME or $HOME/.config.
* @return $NIX_CONFIG_HOME or $XDG_CONFIG_HOME/nix or $HOME/.config/nix.
*/
Path getConfigDir();

Expand All @@ -39,12 +39,12 @@ Path getConfigDir();
std::vector<Path> getConfigDirs();

/**
* @return $XDG_DATA_HOME or $HOME/.local/share.
* @return $NIX_DATA_HOME or $XDG_DATA_HOME/nix or $HOME/.local/share/nix.
*/
Path getDataDir();

/**
* @return $XDG_STATE_HOME or $HOME/.local/state.
* @return $NIX_STATE_HOME or $XDG_STATE_HOME/nix or $HOME/.local/state/nix.
*/
Path getStateDir();

Expand Down

0 comments on commit 38bfbb2

Please sign in to comment.