Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8a1297444b |
+91
-116
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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 != "") {
|
||||
|
||||
Reference in New Issue
Block a user