1
0
Fork 0
mirror of https://github.com/nix-community/home-manager.git synced 2025-11-08 19:46:05 +01:00

home-manager: migrate profiles to nix state directory

If the user runs a recent Nix version that places per-user profiles in
`$XDG_STATE_DIR/nix/profiles`, then migrate the home-manager profile
there.

Also clean up `setupVars` a bit.
This commit is contained in:
Robert Helgesson 2023-04-07 14:01:45 +02:00
parent 440faf5ae4
commit 93f5cb2482
No known key found for this signature in database
GPG key ID: 36BDAA14C2797E89
4 changed files with 113 additions and 88 deletions

View file

@ -1,55 +1,61 @@
# Moves the existing profile from /nix to ~ to match changed behavior in Nix
# 2.14. See https://github.com/NixOS/nix/pull/5226.
#
# Note, this function is intentionally unused for now. There remains a few open
# questions about backwards compatibility and support from
# `nix-collect-garbage`.
# Moves the existing profile from /nix or $XDG_STATE_HOME/home-manager to
# $XDG_STATE_HOME/nix to match changed behavior in Nix 2.14. See
# https://github.com/NixOS/nix/pull/5226.
function migrateProfile() {
declare -r stateHome="${XDG_STATE_HOME:-$HOME/.local/state}"
declare -r userNixStateDir="$stateHome/nix"
declare -r hmStateDir="$stateHome/home-manager"
declare -r nixStateDir="${NIX_STATE_DIR:-/nix/var/nix}"
declare -r newProfilesDir="$hmStateDir/profiles"
declare -r oldProfilesDir="$nixStateDir/profiles/per-user/$USER"
declare -r globalNixStateDir="${NIX_STATE_DIR:-/nix/var/nix}"
declare -r globalProfilesDir="$globalNixStateDir/profiles/per-user/$USER"
if [[ ! -d $newProfilesDir ]]; then
_i 'Migrating profiles from %s to %s' "$oldProfilesDir" "$newProfilesDir"
mkdir -p "$newProfilesDir"
for p in "$oldProfilesDir"/home-manager-*; do
declare -r name="${p##*/}"
nix-store --realise "$p" --add-root "$newProfilesDir/$name" > /dev/null
done
cp -P "$oldProfilesDir/home-manager" "$newProfilesDir"
if [[ -e $globalProfilesDir/home-manager ]]; then
declare -r oldProfilesDir="$globalProfilesDir"
elif [[ -e $hmStateDir/profiles/home-manager ]]; then
declare -r oldProfilesDir="$hmStateDir/profiles"
fi
rm "$oldProfilesDir"/home-manager-*
declare -r newProfilesDir="$userNixStateDir/profiles"
if [[ -v oldProfilesDir && -e $newProfilesDir ]]; then
if [[ ! -e $newProfilesDir/home-manager ]]; then
_i 'Migrating profile from %s to %s' "$oldProfilesDir" "$newProfilesDir"
for p in "$oldProfilesDir"/home-manager-*; do
declare name="${p##*/}"
nix-store --realise "$p" --add-root "$newProfilesDir/$name" > /dev/null
done
cp -P "$oldProfilesDir/home-manager" "$newProfilesDir"
fi
rm "$oldProfilesDir/home-manager" "$oldProfilesDir"/home-manager-*
fi
}
function setupVars() {
declare -r nixStateDir="${NIX_STATE_DIR:-/nix/var/nix}"
declare -r globalProfilesDir="$nixStateDir/profiles/per-user/$USER"
declare -r globalGcrootsDir="$nixStateDir/gcroots/per-user/$USER"
declare -r stateHome="${XDG_STATE_HOME:-$HOME/.local/state}"
declare -r hmStateDir="$stateHome/home-manager"
declare -r hmGcrootsDir="$hmStateDir/gcroots"
declare -r userNixStateDir="$stateHome/nix"
declare -r hmGcrootsDir="$stateHome/home-manager/gcroots"
# If the global profiles path exists or we can create it, then place the HM
# profile there. Otherwise place it in the HM data directory. We prefer to
# use the global location since it makes it visible to
# `nix-collect-garbage`.
#
# In the future we may perform a one-shot migration to the new location.
declare -r globalNixStateDir="${NIX_STATE_DIR:-/nix/var/nix}"
declare -r globalProfilesDir="$globalNixStateDir/profiles/per-user/$USER"
declare -r globalGcrootsDir="$globalNixStateDir/gcroots/per-user/$USER"
# If the user Nix profiles path exists, then place the HM profile there.
# Otherwise, if the global Nix per-user state directory exists then use
# that. If neither exists, then we give up.
#
# shellcheck disable=2174
if [[ -d "$globalProfilesDir" ]] || mkdir -m 0755 -p "$globalProfilesDir" 2>/dev/null; then
declare -r hmProfilesDir="$globalProfilesDir"
if [[ -d $userNixStateDir/profiles ]]; then
declare -r profilesDir="$userNixStateDir/profiles"
elif [[ -d $globalProfilesDir ]]; then
declare -r profilesDir="$globalProfilesDir"
else
declare -r hmProfilesDir="$hmStateDir/profiles"
mkdir -m 0755 -p "$hmProfilesDir"
_iError 'Could not find suitable profile directory, tried %s and %s' \
"$userNixStateDir/profiles" "$globalProfilesDir" >&2
exit 1
fi
declare -gr genProfilePath="$hmProfilesDir/home-manager"
declare -gr genProfilePath="$profilesDir/home-manager"
declare -gr newGenPath="@GENERATION_DIR@";
declare -gr newGenGcPath="$hmGcrootsDir/current-home"
declare -gr legacyGenGcPath="$globalGcrootsDir/current-home"
@ -77,7 +83,7 @@ function setupVars() {
|| ! -v oldGenNum && -v oldGenPath ]]; then
_i $'The previous generation number and path are in conflict! These\nmust be either both empty or both set but are now set to\n\n \'%s\' and \'%s\'\n\nIf you don\'t mind losing previous profile generations then\nthe easiest solution is probably to run\n\n rm %s/home-manager*\n rm %s/current-home\n\nand trying home-manager switch again. Good luck!' \
"${oldGenNum:-}" "${oldGenPath:-}" \
"$hmProfilesDir" "$hmGcrootsDir"
"$profilesDir" "$hmGcrootsDir"
exit 1
fi
}
@ -99,6 +105,7 @@ _i "Starting Home Manager activation"
$VERBOSE_RUN _i "Sanity checking Nix"
nix-build --expr '{}' --no-out-link
migrateProfile
setupVars
if [[ -v DRY_RUN ]] ; then
@ -109,7 +116,6 @@ else
$VERBOSE_RUN _i "This is a live run"
export DRY_RUN_CMD=""
export DRY_RUN_NULL=/dev/null
fi
if [[ -v VERBOSE ]]; then