mirror of
https://github.com/nix-community/home-manager
synced 2024-11-26 21:19:45 +01:00
Use a generation directory
Before we put only user files in the generation directory but that was quite limiting. In particular, we lost track of the activation script.
This commit is contained in:
parent
671805009c
commit
43fd747ba7
3 changed files with 89 additions and 44 deletions
|
@ -17,16 +17,18 @@ function doRebuild() {
|
||||||
--argstr modulesPath "$HOME/.nixpkgs/home-manager/modules" \
|
--argstr modulesPath "$HOME/.nixpkgs/home-manager/modules" \
|
||||||
--argstr confPath "$confFile" \
|
--argstr confPath "$confFile" \
|
||||||
-A activation-script \
|
-A activation-script \
|
||||||
-o "$wrkdir/activate"
|
-o "$wrkdir/generation"
|
||||||
|
|
||||||
"$wrkdir/activate/libexec/home-activate"
|
"$wrkdir/generation/activate"
|
||||||
|
|
||||||
rm -rv "$wrkdir"
|
rm -r "$wrkdir"
|
||||||
}
|
}
|
||||||
|
|
||||||
function doListGens() {
|
function doListGens() {
|
||||||
ls --color=yes -gG --sort time "/nix/var/nix/gcroots/per-user/$(whoami)" \
|
pushd "/nix/var/nix/profiles/per-user/$USER" > /dev/null
|
||||||
|
ls --color=yes -gG --sort time home-manager-*-link \
|
||||||
| cut -d' ' -f 4-
|
| cut -d' ' -f 4-
|
||||||
|
popd > /dev/null
|
||||||
}
|
}
|
||||||
|
|
||||||
function doListPackages() {
|
function doListPackages() {
|
||||||
|
|
|
@ -193,34 +193,26 @@ in
|
||||||
|
|
||||||
home.activation.linkages =
|
home.activation.linkages =
|
||||||
let
|
let
|
||||||
pak = pkgs.stdenv.mkDerivation {
|
|
||||||
name = "home-environment";
|
|
||||||
|
|
||||||
phases = [ "installPhase" ];
|
|
||||||
|
|
||||||
installPhase =
|
|
||||||
concatStringsSep "\n" (
|
|
||||||
mapAttrsToList (name: value:
|
|
||||||
"install -v -D -m${value.mode} ${value.source} $out/${value.target}"
|
|
||||||
) cfg.file
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
link = pkgs.writeText "link" ''
|
link = pkgs.writeText "link" ''
|
||||||
|
newGenFiles="$1"
|
||||||
|
shift
|
||||||
for sourcePath in "$@" ; do
|
for sourcePath in "$@" ; do
|
||||||
basePath="''${sourcePath#/nix/store/*-home-environment/}"
|
relativePath="$(realpath --relative-to "$newGenFiles" "$sourcePath")"
|
||||||
targetPath="$HOME/$basePath"
|
targetPath="$HOME/$relativePath"
|
||||||
mkdir -vp "$(dirname "$targetPath")"
|
mkdir -vp "$(dirname "$targetPath")"
|
||||||
ln -vsf "$sourcePath" "$targetPath"
|
ln -vsf "$sourcePath" "$targetPath"
|
||||||
done
|
done
|
||||||
'';
|
'';
|
||||||
|
|
||||||
cleanup = pkgs.writeText "cleanup" ''
|
cleanup = pkgs.writeText "cleanup" ''
|
||||||
|
newGenFiles="$1"
|
||||||
|
oldGenFiles="$2"
|
||||||
|
shift 2
|
||||||
for sourcePath in "$@" ; do
|
for sourcePath in "$@" ; do
|
||||||
basePath="''${sourcePath#/nix/store/*-home-environment/}"
|
relativePath="$(realpath --relative-to "$oldGenFiles" "$sourcePath")"
|
||||||
targetPath="$HOME/$basePath"
|
targetPath="$HOME/$relativePath"
|
||||||
echo -n "Checking $targetPath"
|
echo -n "Checking $targetPath"
|
||||||
if [[ -f "${pak}/$basePath" ]] ; then
|
if [[ -f "$newGenFiles/$relativePath" ]] ; then
|
||||||
echo " exists"
|
echo " exists"
|
||||||
else
|
else
|
||||||
echo " gone (deleting)"
|
echo " gone (deleting)"
|
||||||
|
@ -232,34 +224,67 @@ in
|
||||||
in
|
in
|
||||||
''
|
''
|
||||||
function setupVars() {
|
function setupVars() {
|
||||||
|
local profilesPath="/nix/var/nix/profiles/per-user/$(whoami)"
|
||||||
local gcPath="/nix/var/nix/gcroots/per-user/$(whoami)"
|
local gcPath="/nix/var/nix/gcroots/per-user/$(whoami)"
|
||||||
local greatestGenNum=( \
|
local greatestGenNum=( \
|
||||||
$(find "$gcPath" -name 'home-*' \
|
$(find "$profilesPath" -name 'home-manager-*-link' \
|
||||||
| sed 's/^.*-\([0-9]*\)$/\1/' \
|
| sed 's/^.*-\([0-9]*\)-link$/\1/' \
|
||||||
| sort -rn \
|
| sort -rn \
|
||||||
| head -1) \
|
| head -1) \
|
||||||
)
|
)
|
||||||
|
|
||||||
if [[ -n "$greatestGenNum" ]] ; then
|
if [[ -n "$greatestGenNum" ]] ; then
|
||||||
oldGenNum=$greatestGenNum
|
oldGenNum=$greatestGenNum
|
||||||
newGenNum=$(($oldGenNum + 1))
|
newGenNum=$(($oldGenNum + 1))
|
||||||
oldGenPath="$(readlink -e "$gcPath/home-$oldGenNum")"
|
|
||||||
else
|
else
|
||||||
newGenNum=1
|
newGenNum=1
|
||||||
fi
|
fi
|
||||||
newGenPath="${pak}";
|
|
||||||
newGenGcPath="$gcPath/home-$newGenNum"
|
if [[ -e "$gcPath/current-home" ]] ; then
|
||||||
|
oldGenPath="$(readlink -e "$gcPath/current-home")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
newGenPath="@GENERATION_DIR@";
|
||||||
|
newGenProfilePath="$profilesPath/home-manager-$newGenNum-link"
|
||||||
|
newGenGcPath="$gcPath/current-home"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Set some vars, these can be used later on as well.
|
# Set some vars, these can be used later on as well.
|
||||||
setupVars
|
setupVars
|
||||||
|
|
||||||
if [[ "$oldGenPath" != "$newGenPath" ]] ; then
|
echo oldGenNum=$oldGenNum
|
||||||
ln -sfv "$newGenPath" "$newGenGcPath"
|
echo newGenNum=$newGenNum
|
||||||
find "$newGenPath" -type f -print0 | xargs -0 bash ${link}
|
echo oldGenPath=$oldGenPath
|
||||||
if [[ -n "$oldGenPath" ]] ; then
|
echo newGenPath=$newGenPath
|
||||||
echo "Cleaning up orphan links from $HOME"
|
echo newGenProfilePath=$newGenProfilePath
|
||||||
find "$oldGenPath" -type f -print0 | xargs -0 bash ${cleanup}
|
echo newGenGcPath=$newGenGcPath
|
||||||
|
|
||||||
|
function linkNewGen() {
|
||||||
|
local newGenFiles
|
||||||
|
newGenFiles="$(readlink -e "$newGenPath/home-files")"
|
||||||
|
find "$newGenFiles" -type f -print0 \
|
||||||
|
| xargs -0 bash ${link} "$newGenFiles"
|
||||||
|
}
|
||||||
|
|
||||||
|
function cleanOldGen() {
|
||||||
|
if [[ -z "$oldGenPath" ]] ; then
|
||||||
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
echo "Cleaning up orphan links from $HOME"
|
||||||
|
|
||||||
|
local newGenFiles oldGenFiles
|
||||||
|
newGenFiles="$(readlink -e "$newGenPath/home-files")"
|
||||||
|
oldGenFiles="$(readlink -e "$oldGenPath/home-files")"
|
||||||
|
find "$oldGenFiles" -type f -print0 \
|
||||||
|
| xargs -0 bash ${cleanup} "$newGenFiles" "$oldGenFiles"
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ "$oldGenPath" != "$newGenPath" ]] ; then
|
||||||
|
ln -Tsfv "$newGenPath" "$newGenProfilePath"
|
||||||
|
ln -Tsfv "$newGenPath" "$newGenGcPath"
|
||||||
|
linkNewGen
|
||||||
|
cleanOldGen
|
||||||
else
|
else
|
||||||
echo "Same home files as previous generation ... doing nothing"
|
echo "Same home files as previous generation ... doing nothing"
|
||||||
fi
|
fi
|
||||||
|
@ -290,14 +315,32 @@ in
|
||||||
|
|
||||||
${activationCmds}
|
${activationCmds}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
home-files = pkgs.stdenv.mkDerivation {
|
||||||
|
name = "home-manager-files";
|
||||||
|
|
||||||
|
phases = [ "installPhase" ];
|
||||||
|
|
||||||
|
installPhase =
|
||||||
|
concatStringsSep "\n" (
|
||||||
|
mapAttrsToList (name: value:
|
||||||
|
"install -v -D -m${value.mode} ${value.source} $out/${value.target}"
|
||||||
|
) cfg.file
|
||||||
|
);
|
||||||
|
};
|
||||||
in
|
in
|
||||||
pkgs.stdenv.mkDerivation {
|
pkgs.stdenv.mkDerivation {
|
||||||
name = "activate-home";
|
name = "home-manager-generation";
|
||||||
|
|
||||||
phases = [ "installPhase" ];
|
phases = [ "installPhase" ];
|
||||||
|
|
||||||
installPhase = ''
|
installPhase = ''
|
||||||
install -v -D -m755 ${sf} $out/libexec/home-activate
|
install -v -D -m755 ${sf} $out/activate
|
||||||
|
|
||||||
|
substituteInPlace $out/activate \
|
||||||
|
--subst-var-by GENERATION_DIR $out
|
||||||
|
|
||||||
|
ln -vs ${home-files} $out/home-files
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -64,13 +64,15 @@ in
|
||||||
home.activation.reloadSystemD = stringAfter ["linkages"] ''
|
home.activation.reloadSystemD = stringAfter ["linkages"] ''
|
||||||
function systemdPostReload() {
|
function systemdPostReload() {
|
||||||
local servicesDiffFile="$(mktemp)"
|
local servicesDiffFile="$(mktemp)"
|
||||||
|
local oldUserServicePath="$oldGenPath/home-files/.config/systemd/user"
|
||||||
|
local newUserServicePath="$newGenPath/home-files/.config/systemd/user"
|
||||||
|
|
||||||
diff \
|
diff \
|
||||||
--new-line-format='+%L' \
|
--new-line-format='+%L' \
|
||||||
--old-line-format='-%L' \
|
--old-line-format='-%L' \
|
||||||
--unchanged-line-format=' %L' \
|
--unchanged-line-format=' %L' \
|
||||||
<(basename -a $(echo "$oldGenPath/.config/systemd/user/*.service") | sort) \
|
<(basename -a $(echo "$oldUserServicePath/*.service") | sort) \
|
||||||
<(basename -a $(echo "$newGenPath/.config/systemd/user/*.service") | sort) \
|
<(basename -a $(echo "$newUserServicePath/*.service") | sort) \
|
||||||
> $servicesDiffFile
|
> $servicesDiffFile
|
||||||
|
|
||||||
local -a maybeRestart=( $(grep '^ ' $servicesDiffFile | cut -c2-) )
|
local -a maybeRestart=( $(grep '^ ' $servicesDiffFile | cut -c2-) )
|
||||||
|
@ -81,8 +83,8 @@ in
|
||||||
for f in ''${maybeRestart[@]} ; do
|
for f in ''${maybeRestart[@]} ; do
|
||||||
if systemctl --quiet --user is-active "$f" \
|
if systemctl --quiet --user is-active "$f" \
|
||||||
&& ! cmp --quiet \
|
&& ! cmp --quiet \
|
||||||
"$oldGenPath/.config/systemd/user/$f" \
|
"$oldUserServicePath/$f" \
|
||||||
"$newGenPath/.config/systemd/user/$f" ; then
|
"$newUserServicePath/$f" ; then
|
||||||
echo "Adding '$f' to restart list";
|
echo "Adding '$f' to restart list";
|
||||||
toRestart+=("$f")
|
toRestart+=("$f")
|
||||||
fi
|
fi
|
||||||
|
@ -90,7 +92,7 @@ in
|
||||||
|
|
||||||
rm $servicesDiffFile
|
rm $servicesDiffFile
|
||||||
|
|
||||||
sugg=""
|
local sugg=""
|
||||||
|
|
||||||
if [[ -n "''${toRestart[@]}" ]] ; then
|
if [[ -n "''${toRestart[@]}" ]] ; then
|
||||||
sugg="$sugg\nsystemctl --user restart ''${toRestart[@]}"
|
sugg="$sugg\nsystemctl --user restart ''${toRestart[@]}"
|
||||||
|
@ -110,10 +112,8 @@ in
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
if [[ "$oldGenPath" != "$newGenPath" ]] ; then
|
|
||||||
systemctl --user daemon-reload
|
systemctl --user daemon-reload
|
||||||
systemdPostReload
|
systemdPostReload
|
||||||
fi
|
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue