From f82246171b253801021c6f98cc50fa461cd972e5 Mon Sep 17 00:00:00 2001 From: Judson Date: Wed, 17 Apr 2019 12:15:38 -0700 Subject: [PATCH] files: backup file collisions When a configuration file would be written to an existing file, rather than failing switch (and having the user have to move or delete those files), move the files automatically to a new path. Closes #585 --- home-manager/home-manager | 6 +++++- modules/files.nix | 20 +++++++++++++++++--- modules/misc/news.nix | 16 ++++++++++++++++ 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/home-manager/home-manager b/home-manager/home-manager index 85feaae40..b6ea92edb 100644 --- a/home-manager/home-manager +++ b/home-manager/home-manager @@ -416,6 +416,7 @@ function doHelp() { echo " -A ATTRIBUTE Optional attribute that selects a configuration" echo " expression in the configuration file." echo " -I PATH Add a path to the Nix expression search path." + echo " -b EXT Move existing files to new path rather than fail." echo " -v Verbose output" echo " -n Do a dry run, only prints what actions would be taken" echo " -h Print this help" @@ -460,7 +461,7 @@ for arg in "$@"; do fi done -while getopts 2f:I:A:vnh opt; do +while getopts 2f:I:A:b:vnh opt; do case $opt in 2) USE_NIX2_COMMAND=1 @@ -474,6 +475,9 @@ while getopts 2f:I:A:vnh opt; do A) HOME_MANAGER_CONFIG_ATTRIBUTE="$OPTARG" ;; + b) + export HOME_MANAGER_BACKUP_EXT="$OPTARG" + ;; v) export VERBOSE=1 ;; diff --git a/modules/files.nix b/modules/files.nix index 0e8297f79..ac946976f 100644 --- a/modules/files.nix +++ b/modules/files.nix @@ -59,13 +59,23 @@ in targetPath="$HOME/$relativePath" if [[ -e "$targetPath" \ && ! "$(readlink "$targetPath")" == ${homeFilePattern} ]] ; then - errorEcho "Existing file '$targetPath' is in the way" - collision=1 + if [[ ! -L "$targetPath" && -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'" + collision=1 + else + warnEcho "Existing file '$targetPath' is in the way, will be moved to '$backup'" + fi + else + errorEcho "Existing file '$targetPath' is in the way" + collision=1 + fi fi done if [[ -v collision ]] ; then - errorEcho "Please move the above files and try again" + errorEcho "Please move the above files and try again or use -b to move automatically." exit 1 fi ''; @@ -111,6 +121,10 @@ in for sourcePath in "$@" ; do 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 diff --git a/modules/misc/news.nix b/modules/misc/news.nix index d6c526873..1953354d6 100644 --- a/modules/misc/news.nix +++ b/modules/misc/news.nix @@ -1106,6 +1106,22 @@ in A new module is available: 'programs.gpg'. ''; } + + { + time = "2019-06-09T12:19:18+00:00"; + message = '' + Collisions between unmanaged and managed files can now be + automatically resolved by moving the target file to a new + path instead of failing the switch operation. To enable + this, use the new '-b' command line argument. For example, + + home-manager -b bck switch + + where 'bck' is the suffix to give the moved file. In this + case a colliding file 'foo.conf' will be moved to + 'foo.conf.bck'. + ''; + } ]; }; }