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.
This commit is contained in:
parent
dd93c300bb
commit
86be605f3f
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue