Compare commits

..
Author SHA1 Message Date
Robert Helgesson 8a1297444b files: clean up
Specifically, replace the `link` and `clean` scripts by inline Bash
functions. This avoids a number of Bash invocations and simplifies the
code a little. This should also make it slightly easier to implement
support for arbitrary file locations.
2021-07-27 00:14:05 +02:00
4 changed files with 94 additions and 152 deletions
+91 -116
View File
@@ -106,7 +106,8 @@ in
$VERBOSE_ECHO "Skipping collision check for $targetPath"
elif [[ -e "$targetPath" \
&& ! "$(readlink "$targetPath")" == $homeFilePattern ]] ; then
if [[ ! -L "$targetPath" && -n "$HOME_MANAGER_BACKUP_EXT" ]] ; then
if [[ ! -L "$targetPath" \
&& -v HOME_MANAGER_BACKUP_EXT && -n "$HOME_MANAGER_BACKUP_EXT" ]] ; then
backup="$targetPath.$HOME_MANAGER_BACKUP_EXT"
if [[ -e "$backup" ]]; then
errorEcho "Existing file '$backup' would be clobbered by backing up '$targetPath'"
@@ -160,127 +161,101 @@ in
# and a failure during the intermediate state FA ∩ FB will not
# result in lost links because this set of links are in both the
# source and target generation.
home.activation.linkGeneration = hm.dag.entryAfter ["writeBoundary"] (
let
link = pkgs.writeShellScript "link" ''
rootPath="$1"
newGenFiles="$2"
shift 2
for sourcePath in "$@" ; do
relativePath="''${sourcePath#$newGenFiles/}"
targetPath="$rootPath/$relativePath"
if [[ -e "$targetPath" && ! -L "$targetPath" && -n "$HOME_MANAGER_BACKUP_EXT" ]] ; then
backup="$targetPath.$HOME_MANAGER_BACKUP_EXT"
$DRY_RUN_CMD mv $VERBOSE_ARG "$targetPath" "$backup" || errorEcho "Moving '$targetPath' failed!"
fi
$DRY_RUN_CMD mkdir -p $VERBOSE_ARG "$(dirname "$targetPath")"
$DRY_RUN_CMD ln -nsf $VERBOSE_ARG "$sourcePath" "$targetPath"
done
'';
home.activation.linkGeneration = hm.dag.entryAfter ["writeBoundary"] (''
function clean() {
# A symbolic link whose target path matches this pattern will be
# considered part of a Home Manager generation.
local homeFilePattern
homeFilePattern="$(readlink -e ${escapeShellArg builtins.storeDir})/*-home-manager-files/*"
cleanup = pkgs.writeShellScript "cleanup" ''
. ${./lib-bash/color-echo.sh}
local newGenFiles="$1"
local relativePath="$2"
local targetPath="$HOME/$relativePath"
if [[ -e "$newGenFiles/$relativePath" ]] ; then
$VERBOSE_ECHO "Checking $targetPath: exists"
elif [[ ! "$(readlink "$targetPath")" == $homeFilePattern ]] ; then
warnEcho "Path '$targetPath' does not link into a Home Manager generation. Skipping delete."
else
$VERBOSE_ECHO "Checking $targetPath: gone (deleting)"
$DRY_RUN_CMD rm $VERBOSE_ARG "$targetPath"
# A symbolic link whose target path matches this pattern will be
# considered part of a Home Manager generation.
homeFilePattern="$(readlink -e ${escapeShellArg builtins.storeDir})/*-home-manager-files/*"
# Recursively delete empty parent directories.
targetDir="$(dirname "$relativePath")"
if [[ "$targetDir" != "." ]] ; then
pushd "$HOME" > /dev/null
rootPath="$1"
newGenFiles="$2"
shift 2
for relativePath in "$@" ; do
targetPath="$rootPath/$relativePath"
if [[ -e "$newGenFiles/$relativePath" ]] ; then
$VERBOSE_ECHO "Checking $targetPath: exists"
elif [[ ! "$(readlink "$targetPath")" == $homeFilePattern ]] ; then
warnEcho "Path '$targetPath' does not link into a Home Manager generation. Skipping delete."
else
$VERBOSE_ECHO "Checking $targetPath: gone (deleting)"
$DRY_RUN_CMD rm $VERBOSE_ARG "$targetPath"
# Call rmdir with a relative path excluding $HOME.
# Otherwise, it might try to delete $HOME and exit
# with a permission error.
$DRY_RUN_CMD rmdir $VERBOSE_ARG \
-p --ignore-fail-on-non-empty \
"$targetDir"
# Recursively delete empty parent directories.
targetDir="$(dirname "$relativePath")"
if [[ "$targetDir" != "." ]] ; then
# TODO
# pushd "$HOME" > /dev/null
# Call rmdir with a relative path excluding $HOME.
# Otherwise, it might try to delete $HOME and exit
# with a permission error.
$DRY_RUN_CMD rmdir $VERBOSE_ARG \
-p --ignore-fail-on-non-empty \
"$targetDir"
# popd > /dev/null
fi
fi
done
'';
in
''
function linkNewGen() {
echo "Creating home file links"
local rootPath=
if [[ $newGenLayoutVersion -eq 0 ]] ; then
rootPath="$HOME"
fi
local newGenFiles
newGenFiles="$(readlink -e "$newGenPath/home-files")"
find "$newGenFiles" \( -type f -or -type l \) \
-exec bash ${link} "$rootPath" "$newGenFiles" {} +
}
function cleanOldGen() {
if [[ ! -v oldGenPath ]] ; then
return
fi
echo "Cleaning up orphan links"
local newGenFiles oldGenFiles
newGenFiles="$(readlink -e "$newGenPath/home-files")"
oldGenFiles="$(readlink -e "$oldGenPath/home-files")"
# When transitioning from layout 0 to 1 we need to prefix all old
# paths with the home directory. Conversely, if we ever go from
# layout 1 to 0 we need to "subtract" the home directory from the
# old generation path, this is done by appending an "antiprefix" to
# the layout 1 paths.
local prefix= antiprefix=
if [[ $oldGenLayoutVersion -eq 0 && $newGenLayoutVersion -ge 1 ]] ; then
prefix="''${HOME#/}/"
elif [[ $oldGenLayoutVersion -ge 1 && $newGenLayoutVersion -eq 0 ]] ; then
antiprefix="/$HOME"
fi
local rootPath=
if [[ $newGenLayoutVersion -eq 0 ]] ; then
rootPath="$HOME"
fi
$VERBOSE_ECHO "Orphan link cleanup uses prefix=$prefix antiprefix=$antiprefix rootPath=$rootPath"
# Apply the cleanup script on each leaf in the old generation. The
# find command below will print the relative path of the entry.
find "$oldGenFiles$antiprefix" '(' -type f -or -type l ')' -printf "$prefix%P\0" \
| xargs -0 bash ${cleanup} "$rootPath" "$newGenFiles"
}
cleanOldGen
if [[ ! -v oldGenPath || "$oldGenPath" != "$newGenPath" ]] ; then
echo "Creating profile generation $newGenNum"
$DRY_RUN_CMD nix-env $VERBOSE_ARG --profile "$genProfilePath" --set "$newGenPath"
$DRY_RUN_CMD ln -Tsf $VERBOSE_ARG "$newGenPath" "$newGenGcPath"
else
echo "No change so reusing latest profile generation $oldGenNum"
popd > /dev/null
fi
fi
}
linkNewGen
''
);
function cleanOldGen() {
if [[ ! -v 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")"
# Apply the cleanup script on each leaf in the old
# generation. The find command below will print the
# relative path of the entry.
find "$oldGenFiles" '(' -type f -or -type l ')' -printf '%P\0' \
| while IFS= read -r -d "" relativePath ; do \
clean "$newGenFiles" "$relativePath"; \
done
}
function link() {
local newGenFiles="$1"
local sourcePath="$2"
local relativePath="''${sourcePath#$newGenFiles/}"
local targetPath="$HOME/$relativePath"
if [[ -e "$targetPath" && ! -L "$targetPath" \
&& -v HOME_MANAGER_BACKUP_EXT && -n "$HOME_MANAGER_BACKUP_EXT" ]] ; then
local backup="$targetPath.$HOME_MANAGER_BACKUP_EXT"
$DRY_RUN_CMD mv $VERBOSE_ARG "$targetPath" "$backup" \
|| errorEcho "Moving '$targetPath' failed!"
fi
$DRY_RUN_CMD mkdir -p $VERBOSE_ARG "$(dirname "$targetPath")"
$DRY_RUN_CMD ln -nsf $VERBOSE_ARG "$sourcePath" "$targetPath"
}
function linkNewGen() {
echo "Creating home file links in $HOME"
local newGenFiles
newGenFiles="$(readlink -e "$newGenPath/home-files")"
find "$newGenFiles" \( -type f -or -type l \) -print0 \
| while IFS= read -r -d "" sourcePath ; do \
link "$newGenFiles" "$sourcePath"; \
done
}
cleanOldGen
if [[ ! -v oldGenPath || "$oldGenPath" != "$newGenPath" ]] ; then
echo "Creating profile generation $newGenNum"
$DRY_RUN_CMD nix-env $VERBOSE_ARG --profile "$genProfilePath" --set "$newGenPath"
$DRY_RUN_CMD ln -Tsf $VERBOSE_ARG "$newGenPath" "$newGenGcPath"
else
echo "No change so reusing latest profile generation $oldGenNum"
fi
linkNewGen
unset -f clean cleanOldGen link linkNewGen
'');
home.activation.checkFilesChanged = hm.dag.entryBefore ["linkGeneration"] (
let
-7
View File
@@ -622,13 +622,6 @@ in
mkdir $out/bin
ln -s $out/activate $out/bin/home-manager-generation
# The generation directory layout version.
#
# - Version 0 (also implied when file is missing) means
# "legacy layout".
# - Version 1 adds full home file paths.
echo 0 > $out/version
substituteInPlace $out/activate \
--subst-var-by GENERATION_DIR $out
+3 -18
View File
@@ -5,17 +5,9 @@ function setupVars() {
local profilesPath="$nixStateDir/profiles/per-user/$USER"
local gcPath="$nixStateDir/gcroots/per-user/$USER"
declare -gr genProfilePath="$profilesPath/home-manager"
declare -gr newGenPath="@GENERATION_DIR@";
declare -gr newGenGcPath="$gcPath/current-home"
declare -g newGenLayoutVersion
if [[ -f $newGenPath/version ]]; then
newGenLayoutVersion=$(< "$newGenPath/version")
else
newGenLayoutVersion=0
fi
readonly newGenLayoutVersion
genProfilePath="$profilesPath/home-manager"
newGenPath="@GENERATION_DIR@";
newGenGcPath="$gcPath/current-home"
local greatestGenNum
greatestGenNum=$( \
@@ -31,14 +23,7 @@ function setupVars() {
fi
if [[ -e $profilesPath/home-manager ]] ; then
declare -g oldGenPath oldGenLayoutVersion
oldGenPath="$(readlink -e "$profilesPath/home-manager")"
if [[ -f $oldGenPath/version ]]; then
oldGenLayoutVersion=$(< "$oldGenPath/version")
else
oldGenLayoutVersion=0
fi
readonly oldGenPath oldGenLayoutVersion
fi
$VERBOSE_ECHO "Sanity checking oldGenNum and oldGenPath"
-11
View File
@@ -132,15 +132,6 @@ in {
'';
};
generatedConfigViml = mkOption {
type = types.lines;
visible = true;
readOnly = true;
description = ''
Generated vimscript config.
'';
};
package = mkOption {
type = types.package;
default = pkgs.neovim-unwrapped;
@@ -289,8 +280,6 @@ in {
configure.customRC -> programs.neovim.extraConfig
'';
programs.neovim.generatedConfigViml = neovimConfig.neovimRcContent;
home.packages = [ cfg.finalPackage ];
xdg.configFile."nvim/init.vim" = mkIf (neovimConfig.neovimRcContent != "") {