Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use envvars NIX_CACHE_HOME, NIX_CONFIG_HOME, NIX_DATA_HOME, NIX_STATE_HOME if defined #11351

Merged
merged 10 commits into from
Sep 11, 2024
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`.

fricklerhandwerk marked this conversation as resolved.
Show resolved Hide resolved
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
Loading