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:
Robert Helgesson 2017-01-08 22:06:53 +01:00
parent 671805009c
commit 43fd747ba7
No known key found for this signature in database
GPG key ID: C3DB11069E65DC86
3 changed files with 89 additions and 44 deletions

View file

@ -17,16 +17,18 @@ function doRebuild() {
--argstr modulesPath "$HOME/.nixpkgs/home-manager/modules" \
--argstr confPath "$confFile" \
-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() {
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-
popd > /dev/null
}
function doListPackages() {

View file

@ -193,34 +193,26 @@ in
home.activation.linkages =
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" ''
newGenFiles="$1"
shift
for sourcePath in "$@" ; do
basePath="''${sourcePath#/nix/store/*-home-environment/}"
targetPath="$HOME/$basePath"
relativePath="$(realpath --relative-to "$newGenFiles" "$sourcePath")"
targetPath="$HOME/$relativePath"
mkdir -vp "$(dirname "$targetPath")"
ln -vsf "$sourcePath" "$targetPath"
done
'';
cleanup = pkgs.writeText "cleanup" ''
newGenFiles="$1"
oldGenFiles="$2"
shift 2
for sourcePath in "$@" ; do
basePath="''${sourcePath#/nix/store/*-home-environment/}"
targetPath="$HOME/$basePath"
relativePath="$(realpath --relative-to "$oldGenFiles" "$sourcePath")"
targetPath="$HOME/$relativePath"
echo -n "Checking $targetPath"
if [[ -f "${pak}/$basePath" ]] ; then
if [[ -f "$newGenFiles/$relativePath" ]] ; then
echo " exists"
else
echo " gone (deleting)"
@ -232,34 +224,67 @@ in
in
''
function setupVars() {
local profilesPath="/nix/var/nix/profiles/per-user/$(whoami)"
local gcPath="/nix/var/nix/gcroots/per-user/$(whoami)"
local greatestGenNum=( \
$(find "$gcPath" -name 'home-*' \
| sed 's/^.*-\([0-9]*\)$/\1/' \
$(find "$profilesPath" -name 'home-manager-*-link' \
| sed 's/^.*-\([0-9]*\)-link$/\1/' \
| sort -rn \
| head -1) \
)
if [[ -n "$greatestGenNum" ]] ; then
oldGenNum=$greatestGenNum
newGenNum=$(($oldGenNum + 1))
oldGenPath="$(readlink -e "$gcPath/home-$oldGenNum")"
else
newGenNum=1
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.
setupVars
if [[ "$oldGenPath" != "$newGenPath" ]] ; then
ln -sfv "$newGenPath" "$newGenGcPath"
find "$newGenPath" -type f -print0 | xargs -0 bash ${link}
if [[ -n "$oldGenPath" ]] ; then
echo "Cleaning up orphan links from $HOME"
find "$oldGenPath" -type f -print0 | xargs -0 bash ${cleanup}
echo oldGenNum=$oldGenNum
echo newGenNum=$newGenNum
echo oldGenPath=$oldGenPath
echo newGenPath=$newGenPath
echo newGenProfilePath=$newGenProfilePath
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
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
echo "Same home files as previous generation ... doing nothing"
fi
@ -290,14 +315,32 @@ in
${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
pkgs.stdenv.mkDerivation {
name = "activate-home";
name = "home-manager-generation";
phases = [ "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
'';
};

View file

@ -64,13 +64,15 @@ in
home.activation.reloadSystemD = stringAfter ["linkages"] ''
function systemdPostReload() {
local servicesDiffFile="$(mktemp)"
local oldUserServicePath="$oldGenPath/home-files/.config/systemd/user"
local newUserServicePath="$newGenPath/home-files/.config/systemd/user"
diff \
--new-line-format='+%L' \
--old-line-format='-%L' \
--unchanged-line-format=' %L' \
<(basename -a $(echo "$oldGenPath/.config/systemd/user/*.service") | sort) \
<(basename -a $(echo "$newGenPath/.config/systemd/user/*.service") | sort) \
<(basename -a $(echo "$oldUserServicePath/*.service") | sort) \
<(basename -a $(echo "$newUserServicePath/*.service") | sort) \
> $servicesDiffFile
local -a maybeRestart=( $(grep '^ ' $servicesDiffFile | cut -c2-) )
@ -81,8 +83,8 @@ in
for f in ''${maybeRestart[@]} ; do
if systemctl --quiet --user is-active "$f" \
&& ! cmp --quiet \
"$oldGenPath/.config/systemd/user/$f" \
"$newGenPath/.config/systemd/user/$f" ; then
"$oldUserServicePath/$f" \
"$newUserServicePath/$f" ; then
echo "Adding '$f' to restart list";
toRestart+=("$f")
fi
@ -90,7 +92,7 @@ in
rm $servicesDiffFile
sugg=""
local sugg=""
if [[ -n "''${toRestart[@]}" ]] ; then
sugg="$sugg\nsystemctl --user restart ''${toRestart[@]}"
@ -110,10 +112,8 @@ in
fi
}
if [[ "$oldGenPath" != "$newGenPath" ]] ; then
systemctl --user daemon-reload
systemdPostReload
fi
'';
};
}