diff --git a/home-manager/home-manager b/home-manager/home-manager index fffffad0..9b0aa793 100644 --- a/home-manager/home-manager +++ b/home-manager/home-manager @@ -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() { diff --git a/modules/home-environment.nix b/modules/home-environment.nix index 27911d0f..2c335ba9 100644 --- a/modules/home-environment.nix +++ b/modules/home-environment.nix @@ -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 ''; }; diff --git a/modules/systemd.nix b/modules/systemd.nix index b927b04a..5e7cc6b4 100644 --- a/modules/systemd.nix +++ b/modules/systemd.nix @@ -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 + systemctl --user daemon-reload + systemdPostReload ''; }; }