From 7f976da06840c268cc291a021bab7532b923713c Mon Sep 17 00:00:00 2001 From: piegames Date: Tue, 19 May 2020 14:44:44 +0200 Subject: [PATCH] files: ignore conflict when files are identical When the target file exists but has the exact same content then we will now skip creation of the link from the source file. Fixes #1213 --- modules/files.nix | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/modules/files.nix b/modules/files.nix index 1ecc1821..6106d815 100644 --- a/modules/files.nix +++ b/modules/files.nix @@ -106,7 +106,12 @@ in $VERBOSE_ECHO "Skipping collision check for $targetPath" elif [[ -e "$targetPath" \ && ! "$(readlink "$targetPath")" == $homeFilePattern ]] ; then - if [[ ! -L "$targetPath" && -n "$HOME_MANAGER_BACKUP_EXT" ]] ; then + # The target file already exists and it isn't a symlink owned by Home Manager. + if cmp -s $sourcePath $targetPath; then + # First compare the files' content. If they're equal, we're fine. + warnEcho "Existing file '$targetPath' is in the way of '$sourcePath', will be skipped since they are the same" + elif [[ ! -L "$targetPath" && -n "$HOME_MANAGER_BACKUP_EXT" ]] ; then + # Next, try to move the file to a backup location if configured and possible backup="$targetPath.$HOME_MANAGER_BACKUP_EXT" if [[ -e "$backup" ]]; then errorEcho "Existing file '$backup' would be clobbered by backing up '$targetPath'" @@ -115,6 +120,7 @@ in warnEcho "Existing file '$targetPath' is in the way of '$sourcePath', will be moved to '$backup'" fi else + # Fail if nothing else works errorEcho "Existing file '$targetPath' is in the way of '$sourcePath'" collision=1 fi @@ -169,11 +175,19 @@ in relativePath="''${sourcePath#$newGenFiles/}" targetPath="$HOME/$relativePath" if [[ -e "$targetPath" && ! -L "$targetPath" && -n "$HOME_MANAGER_BACKUP_EXT" ]] ; then + # The target exists, back it up 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" + + if [[ -e "$targetPath" && ! -L "$targetPath" ]] && cmp -s $sourcePath $targetPath ; then + # The target exists but is identical – don't do anything. + $VERBOSE_ECHO "Skipping '$targetPath' as it is identical to '$sourcePath'" + else + # Place that symlink, --force + $DRY_RUN_CMD mkdir -p $VERBOSE_ARG "$(dirname "$targetPath")" + $DRY_RUN_CMD ln -nsf $VERBOSE_ARG "$sourcePath" "$targetPath" + fi done '';