Merge pull request #5588 from tweag/balsoft/xdg
Follow XDG Base Directory standard
This commit is contained in:
commit
9ebbe35817
|
@ -91,3 +91,16 @@ Most Nix commands interpret the following environment variables:
|
|||
variable sets the initial size of the heap in bytes. It defaults to
|
||||
384 MiB. Setting it to a low value reduces memory consumption, but
|
||||
will increase runtime due to the overhead of garbage collection.
|
||||
|
||||
## XDG Base Directory
|
||||
|
||||
New Nix commands conform to the [XDG Base Directory Specification], and use the following environment variables to determine locations of various state and configuration files:
|
||||
|
||||
- [`XDG_CONFIG_HOME`]{#env-XDG_CONFIG_HOME} (default `~/.config`)
|
||||
- [`XDG_STATE_HOME`]{#env-XDG_STATE_HOME} (default `~/.local/state`)
|
||||
- [`XDG_CACHE_HOME`]{#env-XDG_CACHE_HOME} (default `~/.cache`)
|
||||
|
||||
Classic Nix commands can also be made to follow this standard using the [`use-xdg-base-directories`] configuration option.
|
||||
|
||||
[XDG Base Directory Specification]: https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
|
||||
[`use-xdg-base-directories`]: ../command-ref/conf-file.md#conf-use-xdg-base-directories
|
|
@ -136,7 +136,7 @@ EOF
|
|||
cat <<EOF
|
||||
$step. Delete the files Nix added to your system:
|
||||
|
||||
sudo rm -rf /etc/nix $NIX_ROOT $ROOT_HOME/.nix-profile $ROOT_HOME/.nix-defexpr $ROOT_HOME/.nix-channels $HOME/.nix-profile $HOME/.nix-defexpr $HOME/.nix-channels
|
||||
sudo rm -rf "/etc/nix" "$NIX_ROOT" "$ROOT_HOME/.nix-profile" "$ROOT_HOME/.nix-defexpr" "$ROOT_HOME/.nix-channels" "$ROOT_HOME/.local/state/nix" "$ROOT_HOME/.cache/nix" "$HOME/.nix-profile" "$HOME/.nix-defexpr" "$HOME/.nix-channels" "$HOME/.local/state/nix" "$HOME/.cache/nix"
|
||||
|
||||
and that is it.
|
||||
|
||||
|
|
|
@ -188,6 +188,8 @@ fi
|
|||
# shellcheck source=./nix-profile.sh.in
|
||||
. "$nix/etc/profile.d/nix.sh"
|
||||
|
||||
NIX_LINK="$HOME/.nix-profile"
|
||||
|
||||
if ! "$nix/bin/nix-env" -i "$nix"; then
|
||||
echo "$0: unable to install Nix into your default profile" >&2
|
||||
exit 1
|
||||
|
@ -196,7 +198,7 @@ fi
|
|||
# Install an SSL certificate bundle.
|
||||
if [ -z "$NIX_SSL_CERT_FILE" ] || ! [ -f "$NIX_SSL_CERT_FILE" ]; then
|
||||
"$nix/bin/nix-env" -i "$cacert"
|
||||
export NIX_SSL_CERT_FILE="$HOME/.nix-profile/etc/ssl/certs/ca-bundle.crt"
|
||||
export NIX_SSL_CERT_FILE="$NIX_LINK/etc/ssl/certs/ca-bundle.crt"
|
||||
fi
|
||||
|
||||
# Subscribe the user to the Nixpkgs channel and fetch it.
|
||||
|
@ -214,8 +216,8 @@ fi
|
|||
|
||||
added=
|
||||
p=
|
||||
p_sh=$HOME/.nix-profile/etc/profile.d/nix.sh
|
||||
p_fish=$HOME/.nix-profile/etc/profile.d/nix.fish
|
||||
p_sh=$NIX_LINK/etc/profile.d/nix.sh
|
||||
p_fish=$NIX_LINK/etc/profile.d/nix.fish
|
||||
if [ -z "$NIX_INSTALLER_NO_MODIFY_PROFILE" ]; then
|
||||
# Make the shell source nix.sh during login.
|
||||
for i in .bash_profile .bash_login .profile; do
|
||||
|
|
|
@ -2,7 +2,33 @@
|
|||
if [ -n "${__ETC_PROFILE_NIX_SOURCED:-}" ]; then return; fi
|
||||
__ETC_PROFILE_NIX_SOURCED=1
|
||||
|
||||
export NIX_PROFILES="@localstatedir@/nix/profiles/default $HOME/.nix-profile"
|
||||
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" ]; then
|
||||
NIX_LINK="$NIX_LINK_NEW"
|
||||
else
|
||||
if [ -t 2 ] && [ -e "$NIX_LINK_NEW" ]; then
|
||||
warning="\033[1;35mwarning:\033[0m"
|
||||
printf "$warning Both %s and legacy %s exist; using the latter.\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
|
||||
fi
|
||||
|
||||
export NIX_PROFILES="@localstatedir@/nix/profiles/default $NIX_LINK"
|
||||
|
||||
# Set $NIX_SSL_CERT_FILE so that Nixpkgs applications like curl work.
|
||||
if [ -n "${NIX_SSL_CERT_FILE:-}" ]; then
|
||||
|
@ -34,4 +60,5 @@ else
|
|||
unset -f check_nix_profiles
|
||||
fi
|
||||
|
||||
export PATH="$HOME/.nix-profile/bin:@localstatedir@/nix/profiles/default/bin:$PATH"
|
||||
export PATH="$NIX_LINK/bin:@localstatedir@/nix/profiles/default/bin:$PATH"
|
||||
unset NIX_LINK
|
||||
|
|
|
@ -2,11 +2,35 @@ if [ -n "$HOME" ] && [ -n "$USER" ]; then
|
|||
|
||||
# Set up the per-user profile.
|
||||
|
||||
NIX_LINK=$HOME/.nix-profile
|
||||
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" ]; then
|
||||
NIX_LINK="$NIX_LINK_NEW"
|
||||
else
|
||||
if [ -t 2 ] && [ -e "$NIX_LINK_NEW" ]; then
|
||||
warning="\033[1;35mwarning:\033[0m"
|
||||
printf "$warning Both %s and legacy %s exist; using the latter.\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
|
||||
fi
|
||||
|
||||
# Set up environment.
|
||||
# This part should be kept in sync with nixpkgs:nixos/modules/programs/environment.nix
|
||||
export NIX_PROFILES="@localstatedir@/nix/profiles/default $HOME/.nix-profile"
|
||||
export NIX_PROFILES="@localstatedir@/nix/profiles/default $NIX_LINK"
|
||||
|
||||
# Set $NIX_SSL_CERT_FILE so that Nixpkgs applications like curl work.
|
||||
if [ -e /etc/ssl/certs/ca-certificates.crt ]; then # NixOS, Ubuntu, Debian, Gentoo, Arch
|
||||
|
@ -31,5 +55,5 @@ if [ -n "$HOME" ] && [ -n "$USER" ]; then
|
|||
fi
|
||||
|
||||
export PATH="$NIX_LINK/bin:$PATH"
|
||||
unset NIX_LINK
|
||||
unset NIX_LINK NIX_LINK_NEW
|
||||
fi
|
||||
|
|
|
@ -2496,7 +2496,7 @@ Strings EvalSettings::getDefaultNixPath()
|
|||
res.push_back(s ? *s + "=" + p : p);
|
||||
};
|
||||
|
||||
add(getHome() + "/.nix-defexpr/channels");
|
||||
add(settings.useXDGBaseDirectories ? getStateDir() + "/nix/defexpr/channels" : getHome() + "/.nix-defexpr/channels");
|
||||
add(settings.nixStateDir + "/profiles/per-user/root/channels/nixpkgs", "nixpkgs");
|
||||
add(settings.nixStateDir + "/profiles/per-user/root/channels");
|
||||
|
||||
|
|
|
@ -945,6 +945,27 @@ public:
|
|||
resolves to a different location from that of the build machine. You
|
||||
can enable this setting if you are sure you're not going to do that.
|
||||
)"};
|
||||
|
||||
Setting<bool> useXDGBaseDirectories{
|
||||
this, false, "use-xdg-base-directories",
|
||||
R"(
|
||||
If set to `true`, Nix will conform to the [XDG Base Directory Specification] for files in `$HOME`.
|
||||
The environment variables used to implement this are documented in the [Environment Variables section](@docroot@/installation/env-variables.md).
|
||||
|
||||
[XDG Base Directory Specification]: https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
|
||||
|
||||
> **Warning**
|
||||
> This changes the location of some well-known symlinks that Nix creates, which might break tools that rely on the old, non-XDG-conformant locations.
|
||||
|
||||
In particular, the following locations change:
|
||||
|
||||
| Old | New |
|
||||
|-------------------|--------------------------------|
|
||||
| `~/.nix-profile` | `$XDG_STATE_HOME/nix/profile` |
|
||||
| `~/.nix-defexpr` | `$XDG_STATE_HOME/nix/defexpr` |
|
||||
| `~/.nix-channels` | `$XDG_STATE_HOME/nix/channels` |
|
||||
)"
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -282,7 +282,7 @@ std::string optimisticLockProfile(const Path & profile)
|
|||
|
||||
Path profilesDir()
|
||||
{
|
||||
auto profileRoot = getDataDir() + "/nix/profiles";
|
||||
auto profileRoot = createNixStateDir() + "/profiles";
|
||||
createDirs(profileRoot);
|
||||
return profileRoot;
|
||||
}
|
||||
|
@ -290,7 +290,7 @@ Path profilesDir()
|
|||
|
||||
Path getDefaultProfile()
|
||||
{
|
||||
Path profileLink = getHome() + "/.nix-profile";
|
||||
Path profileLink = settings.useXDGBaseDirectories ? createNixStateDir() + "/profile" : getHome() + "/.nix-profile";
|
||||
try {
|
||||
auto profile =
|
||||
getuid() == 0
|
||||
|
|
|
@ -72,8 +72,9 @@ std::string optimisticLockProfile(const Path & profile);
|
|||
profiles. */
|
||||
Path profilesDir();
|
||||
|
||||
/* Resolve ~/.nix-profile. If ~/.nix-profile doesn't exist yet, create
|
||||
it. */
|
||||
/* Resolve the default profile (~/.nix-profile by default, $XDG_STATE_HOME/
|
||||
nix/profile if XDG Base Directory Support is enabled), and create if doesn't
|
||||
exist */
|
||||
Path getDefaultProfile();
|
||||
|
||||
}
|
||||
|
|
|
@ -608,6 +608,19 @@ Path getDataDir()
|
|||
return dataDir ? *dataDir : getHome() + "/.local/share";
|
||||
}
|
||||
|
||||
Path getStateDir()
|
||||
{
|
||||
auto stateDir = getEnv("XDG_STATE_HOME");
|
||||
return stateDir ? *stateDir : getHome() + "/.local/state";
|
||||
}
|
||||
|
||||
Path createNixStateDir()
|
||||
{
|
||||
Path dir = getStateDir() + "/nix";
|
||||
createDirs(dir);
|
||||
return dir;
|
||||
}
|
||||
|
||||
|
||||
std::optional<Path> getSelfExe()
|
||||
{
|
||||
|
|
|
@ -158,6 +158,12 @@ Path getDataDir();
|
|||
/* Return the path of the current executable. */
|
||||
std::optional<Path> getSelfExe();
|
||||
|
||||
/* Return $XDG_STATE_HOME or $HOME/.local/state. */
|
||||
Path getStateDir();
|
||||
|
||||
/* Create the Nix state directory and return the path to it. */
|
||||
Path createNixStateDir();
|
||||
|
||||
/* Create a directory and all its parents, if necessary. Returns the
|
||||
list of created directories, in order of creation. */
|
||||
Paths createDirs(const Path & path);
|
||||
|
|
|
@ -164,8 +164,8 @@ static int main_nix_channel(int argc, char ** argv)
|
|||
{
|
||||
// Figure out the name of the `.nix-channels' file to use
|
||||
auto home = getHome();
|
||||
channelsList = home + "/.nix-channels";
|
||||
nixDefExpr = home + "/.nix-defexpr";
|
||||
channelsList = settings.useXDGBaseDirectories ? createNixStateDir() + "/channels" : home + "/.nix-channels";
|
||||
nixDefExpr = settings.useXDGBaseDirectories ? createNixStateDir() + "/defexpr" : home + "/.nix-defexpr";
|
||||
|
||||
// Figure out the name of the channels profile.
|
||||
profile = profilesDir() + "/channels";
|
||||
|
|
|
@ -1289,7 +1289,7 @@ static void opSwitchProfile(Globals & globals, Strings opFlags, Strings opArgs)
|
|||
throw UsageError("exactly one argument expected");
|
||||
|
||||
Path profile = absPath(opArgs.front());
|
||||
Path profileLink = getHome() + "/.nix-profile";
|
||||
Path profileLink = settings.useXDGBaseDirectories ? createNixStateDir() + "/profile" : getHome() + "/.nix-profile";
|
||||
|
||||
switchLink(profileLink, profile);
|
||||
}
|
||||
|
@ -1393,7 +1393,10 @@ static int main_nix_env(int argc, char * * argv)
|
|||
Globals globals;
|
||||
|
||||
globals.instSource.type = srcUnknown;
|
||||
globals.instSource.nixExprPath = getHome() + "/.nix-defexpr";
|
||||
{
|
||||
Path nixExprPath = settings.useXDGBaseDirectories ? createNixStateDir() + "/defexpr" : getHome() + "/.nix-defexpr";
|
||||
globals.instSource.nixExprPath = nixExprPath;
|
||||
}
|
||||
globals.instSource.systemFilter = "*";
|
||||
|
||||
if (!pathExists(globals.instSource.nixExprPath)) {
|
||||
|
|
|
@ -27,6 +27,8 @@ export NIX_REMOTE=$NIX_REMOTE_
|
|||
unset NIX_PATH
|
||||
export TEST_HOME=$TEST_ROOT/test-home
|
||||
export HOME=$TEST_HOME
|
||||
unset XDG_STATE_HOME
|
||||
unset XDG_DATA_HOME
|
||||
unset XDG_CONFIG_HOME
|
||||
unset XDG_CONFIG_DIRS
|
||||
unset XDG_CACHE_HOME
|
||||
|
@ -62,8 +64,8 @@ readLink() {
|
|||
}
|
||||
|
||||
clearProfiles() {
|
||||
profiles="$HOME"/.local/share/nix/profiles
|
||||
rm -rf $profiles
|
||||
profiles="$HOME"/.local/state/nix/profiles
|
||||
rm -rf "$profiles"
|
||||
}
|
||||
|
||||
clearStore() {
|
||||
|
|
|
@ -12,6 +12,19 @@ nix-channel --remove xyzzy
|
|||
[ -e $TEST_HOME/.nix-channels ]
|
||||
[ "$(cat $TEST_HOME/.nix-channels)" = '' ]
|
||||
|
||||
# Test the XDG Base Directories support
|
||||
|
||||
export NIX_CONFIG="use-xdg-base-directories = true"
|
||||
|
||||
nix-channel --add http://foo/bar xyzzy
|
||||
nix-channel --list | grep -q http://foo/bar
|
||||
nix-channel --remove xyzzy
|
||||
|
||||
unset NIX_CONFIG
|
||||
|
||||
[ -e $TEST_HOME/.local/state/nix/channels ]
|
||||
[ "$(cat $TEST_HOME/.local/state/nix/channels)" = '' ]
|
||||
|
||||
# Create a channel.
|
||||
rm -rf $TEST_ROOT/foo
|
||||
mkdir -p $TEST_ROOT/foo
|
||||
|
|
|
@ -56,6 +56,14 @@ nix profile history
|
|||
nix profile history | grep "packages.$system.default: ∅ -> 1.0"
|
||||
nix profile diff-closures | grep 'env-manifest.nix: ε → ∅'
|
||||
|
||||
# Test XDG Base Directories support
|
||||
|
||||
export NIX_CONFIG="use-xdg-base-directories = true"
|
||||
nix profile remove 1
|
||||
nix profile install $flake1Dir
|
||||
[[ $($TEST_HOME/.local/state/nix/profile/bin/hello) = "Hello World" ]]
|
||||
unset NIX_CONFIG
|
||||
|
||||
# Test upgrading a package.
|
||||
printf NixOS > $flake1Dir/who
|
||||
printf 2.0 > $flake1Dir/version
|
||||
|
|
Loading…
Reference in a new issue