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.
This commit is contained in:
parent
f6f6990fc8
commit
8a1297444b
|
@ -106,7 +106,8 @@ in
|
||||||
$VERBOSE_ECHO "Skipping collision check for $targetPath"
|
$VERBOSE_ECHO "Skipping collision check for $targetPath"
|
||||||
elif [[ -e "$targetPath" \
|
elif [[ -e "$targetPath" \
|
||||||
&& ! "$(readlink "$targetPath")" == $homeFilePattern ]] ; then
|
&& ! "$(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"
|
backup="$targetPath.$HOME_MANAGER_BACKUP_EXT"
|
||||||
if [[ -e "$backup" ]]; then
|
if [[ -e "$backup" ]]; then
|
||||||
errorEcho "Existing file '$backup' would be clobbered by backing up '$targetPath'"
|
errorEcho "Existing file '$backup' would be clobbered by backing up '$targetPath'"
|
||||||
|
@ -160,101 +161,101 @@ in
|
||||||
# and a failure during the intermediate state FA ∩ FB will not
|
# and a failure during the intermediate state FA ∩ FB will not
|
||||||
# result in lost links because this set of links are in both the
|
# result in lost links because this set of links are in both the
|
||||||
# source and target generation.
|
# source and target generation.
|
||||||
home.activation.linkGeneration = hm.dag.entryAfter ["writeBoundary"] (
|
home.activation.linkGeneration = hm.dag.entryAfter ["writeBoundary"] (''
|
||||||
let
|
function clean() {
|
||||||
link = pkgs.writeShellScript "link" ''
|
# A symbolic link whose target path matches this pattern will be
|
||||||
newGenFiles="$1"
|
# considered part of a Home Manager generation.
|
||||||
shift
|
local homeFilePattern
|
||||||
for sourcePath in "$@" ; do
|
homeFilePattern="$(readlink -e ${escapeShellArg builtins.storeDir})/*-home-manager-files/*"
|
||||||
relativePath="''${sourcePath#$newGenFiles/}"
|
|
||||||
targetPath="$HOME/$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
|
|
||||||
'';
|
|
||||||
|
|
||||||
cleanup = pkgs.writeShellScript "cleanup" ''
|
local newGenFiles="$1"
|
||||||
. ${./lib-bash/color-echo.sh}
|
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
|
# Recursively delete empty parent directories.
|
||||||
# considered part of a Home Manager generation.
|
targetDir="$(dirname "$relativePath")"
|
||||||
homeFilePattern="$(readlink -e ${escapeShellArg builtins.storeDir})/*-home-manager-files/*"
|
if [[ "$targetDir" != "." ]] ; then
|
||||||
|
pushd "$HOME" > /dev/null
|
||||||
|
|
||||||
newGenFiles="$1"
|
# Call rmdir with a relative path excluding $HOME.
|
||||||
shift 1
|
# Otherwise, it might try to delete $HOME and exit
|
||||||
for relativePath in "$@" ; do
|
# with a permission error.
|
||||||
targetPath="$HOME/$relativePath"
|
$DRY_RUN_CMD rmdir $VERBOSE_ARG \
|
||||||
if [[ -e "$newGenFiles/$relativePath" ]] ; then
|
-p --ignore-fail-on-non-empty \
|
||||||
$VERBOSE_ECHO "Checking $targetPath: exists"
|
"$targetDir"
|
||||||
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"
|
|
||||||
|
|
||||||
# Recursively delete empty parent directories.
|
popd > /dev/null
|
||||||
targetDir="$(dirname "$relativePath")"
|
|
||||||
if [[ "$targetDir" != "." ]] ; then
|
|
||||||
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 in $HOME"
|
|
||||||
|
|
||||||
local newGenFiles
|
|
||||||
newGenFiles="$(readlink -e "$newGenPath/home-files")"
|
|
||||||
find "$newGenFiles" \( -type f -or -type l \) \
|
|
||||||
-exec bash ${link} "$newGenFiles" {} +
|
|
||||||
}
|
|
||||||
|
|
||||||
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' \
|
|
||||||
| xargs -0 bash ${cleanup} "$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"
|
|
||||||
fi
|
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"] (
|
home.activation.checkFilesChanged = hm.dag.entryBefore ["linkGeneration"] (
|
||||||
let
|
let
|
||||||
|
|
Loading…
Reference in a new issue