Compare commits

...

1 commit

Author SHA1 Message Date
Robert Helgesson 86be605f3f
files: manage static files in state directory
This improves atomicity since all files managed by Home Manager will
immediately switch over when the link

  $XDG_DATA_HOME/home-manager/files

is swapped over to the new generation. Removing obsolete files and
adding new ones must still done non-atomically but this improves the
situation significantly.
2020-03-30 23:59:46 +02:00
3 changed files with 46 additions and 7 deletions

View file

@ -74,6 +74,26 @@ new module `services.picom` should be used. This is because Nixpkgs no
longer packages compton, and instead packages the (mostly) compatible longer packages compton, and instead packages the (mostly) compatible
fork called picom. fork called picom.
* Entries in <<opt-home.file>> are now linked into place via an
intermediate location, `$XDG_DATA_HOME/home-manager/files`, much like
`/etc/static` in NixOS. This change was made to makes the switch
process more atomic.
+
In general this should not be noticeable but if you manually activate
an older generation it may (harmlessly) exit with an error along the
lines of
+
....
Existing file '/home/jane/foo' is in the way
Please move the above files and try again or use -b <ext> to move automatically.
....
+
where `/home/jane/foo` is a file managed through the <<opt-home.file>>
option. This is due to the older activation script not recognizing the
new XDG data home path as belonging to Home Manager. You can resolve
this by manually removing the `/home/jane/foo` symbolic link and
running the activate script again.
[[sec-release-20.03-state-version-changes]] [[sec-release-20.03-state-version-changes]]
=== State Version Changes === State Version Changes

View file

@ -50,12 +50,15 @@ in
(mapAttrsToList (n: v: v.target) (mapAttrsToList (n: v: v.target)
(filterAttrs (n: v: v.force) cfg)); (filterAttrs (n: v: v.force) cfg));
filesDir = "${config.xdg.dataHome}/home-manager/files";
check = pkgs.writeText "check" '' check = pkgs.writeText "check" ''
. ${./lib-bash/color-echo.sh} . ${./lib-bash/color-echo.sh}
# A symbolic link whose target path matches this pattern will be # A symbolic link whose target path matches this pattern will be
# considered part of a Home Manager generation. # considered part of a Home Manager generation.
homeFilePattern="$(readlink -e "${builtins.storeDir}")/*-home-manager-files/*" homeFilePatternOld="$(readlink -e "${builtins.storeDir}")/*-home-manager-files/*"
homeFilePattern="${filesDir}/*"
forcedPaths=(${forcedPaths}) forcedPaths=(${forcedPaths})
@ -76,6 +79,7 @@ in
if [[ -n $forced ]]; then if [[ -n $forced ]]; then
$VERBOSE_ECHO "Skipping collision check for $targetPath" $VERBOSE_ECHO "Skipping collision check for $targetPath"
elif [[ -e "$targetPath" \ elif [[ -e "$targetPath" \
&& ! "$(readlink "$targetPath")" == $homeFilePatternOld \
&& ! "$(readlink "$targetPath")" == $homeFilePattern ]] ; then && ! "$(readlink "$targetPath")" == $homeFilePattern ]] ; then
if [[ ! -L "$targetPath" && -n "$HOME_MANAGER_BACKUP_EXT" ]] ; then if [[ ! -L "$targetPath" && -n "$HOME_MANAGER_BACKUP_EXT" ]] ; then
backup="$targetPath.$HOME_MANAGER_BACKUP_EXT" backup="$targetPath.$HOME_MANAGER_BACKUP_EXT"
@ -133,6 +137,8 @@ in
# source and target generation. # source and target generation.
home.activation.linkGeneration = hm.dag.entryAfter ["writeBoundary"] ( home.activation.linkGeneration = hm.dag.entryAfter ["writeBoundary"] (
let let
filesDir = "${config.xdg.dataHome}/home-manager/files";
link = pkgs.writeText "link" '' link = pkgs.writeText "link" ''
newGenFiles="$1" newGenFiles="$1"
shift shift
@ -151,9 +157,10 @@ in
cleanup = pkgs.writeText "cleanup" '' cleanup = pkgs.writeText "cleanup" ''
. ${./lib-bash/color-echo.sh} . ${./lib-bash/color-echo.sh}
# A symbolic link whose target path matches this pattern will be # A symbolic link whose target path matches these patterns will be
# considered part of a Home Manager generation. # considered part of a Home Manager generation.
homeFilePattern="$(readlink -e "${builtins.storeDir}")/*-home-manager-files/*" homeFilePatternOld="$(readlink -e "${builtins.storeDir}")/*-home-manager-files/*"
homeFilePattern="${filesDir}/*"
newGenFiles="$1" newGenFiles="$1"
shift 1 shift 1
@ -161,7 +168,8 @@ in
targetPath="$HOME/$relativePath" targetPath="$HOME/$relativePath"
if [[ -e "$newGenFiles/$relativePath" ]] ; then if [[ -e "$newGenFiles/$relativePath" ]] ; then
$VERBOSE_ECHO "Checking $targetPath: exists" $VERBOSE_ECHO "Checking $targetPath: exists"
elif [[ ! "$(readlink "$targetPath")" == $homeFilePattern ]] ; then elif [[ ! "$(readlink "$targetPath")" == $homeFilePatternOld \
&& ! "$(readlink "$targetPath")" == $homeFilePattern ]] ; then
warnEcho "Path '$targetPath' not link into Home Manager generation. Skipping delete." warnEcho "Path '$targetPath' not link into Home Manager generation. Skipping delete."
else else
$VERBOSE_ECHO "Checking $targetPath: gone (deleting)" $VERBOSE_ECHO "Checking $targetPath: gone (deleting)"
@ -189,9 +197,8 @@ in
function linkNewGen() { function linkNewGen() {
echo "Creating home file links in $HOME" echo "Creating home file links in $HOME"
local newGenFiles local newGenFiles="${filesDir}"
newGenFiles="$(readlink -e "$newGenPath/home-files")" find "$newGenFiles/" \( -type f -or -type l \) \
find "$newGenFiles" \( -type f -or -type l \) \
-exec bash ${link} "$newGenFiles" {} + -exec bash ${link} "$newGenFiles" {} +
} }
@ -215,6 +222,13 @@ in
cleanOldGen cleanOldGen
if [[ ! -e "${filesDir}" \
|| "${config.home-files}" != "$(readlink "${filesDir}")" ]] ; then
$DRY_RUN_CMD ln -Tsf $VERBOSE_ARG "${config.home-files}" "${filesDir}"
else
$VERBOSE_ECHO "No change in static files, skipping linking process"
fi
if [[ ! -v oldGenPath || "$oldGenPath" != "$newGenPath" ]] ; then if [[ ! -v oldGenPath || "$oldGenPath" != "$newGenPath" ]] ; then
echo "Creating profile generation $newGenNum" echo "Creating profile generation $newGenNum"
$DRY_RUN_CMD nix-env $VERBOSE_ARG --profile "$genProfilePath" --set "$newGenPath" $DRY_RUN_CMD nix-env $VERBOSE_ARG --profile "$genProfilePath" --set "$newGenPath"

View file

@ -431,6 +431,11 @@ in
${builtins.readFile ./lib-bash/activation-init.sh} ${builtins.readFile ./lib-bash/activation-init.sh}
# Some activation blocks may need to maintain some state, which
# should be kept in this directory. We consider creation of this
# directory exempt from the write boundary.
$DRY_RUN_CMD mkdir $VERBOSE_ARG -p "${config.xdg.dataHome}/home-manager"
${activationCmds} ${activationCmds}
''; '';
in in