Instead of specifying each folder that should be included, all folders are included by default, and excluded folders can be specified.
99 lines
2.9 KiB
Bash
Executable File
99 lines
2.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Possible options:
|
|
# --dry-run -n : only show what would be done without doing anything
|
|
|
|
# config directory
|
|
config_dir="$HOME/dotfiles/"
|
|
|
|
mapping_file="$config_dir/MAPPING"
|
|
|
|
skel_dir="$config_dir/skel/"
|
|
|
|
# backup directory, files that would otherwise be overwritten go there
|
|
backup_dir="$HOME/.dotfiles.bak/"
|
|
|
|
# these folders inside $config_dir will be ignored
|
|
ignore_folders=('scripts' 'skel')
|
|
|
|
MAPPING_SEPARATOR='::'
|
|
|
|
dryrun=""
|
|
|
|
while [[ $# -gt 0 ]] ; do
|
|
case "$1" in
|
|
-n|--dry-run)
|
|
echo "dry run"
|
|
dryrun="yes"
|
|
;;
|
|
*)
|
|
echo "invalid parameters"
|
|
exit 1
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
path_combine()
|
|
{
|
|
echo "$(dirname "$1")/$(basename "$1")/$(basename "$2")"
|
|
}
|
|
|
|
DEFAULT_ROOT="$HOME"
|
|
# returns "" if no mapping necessary
|
|
# format of the MAPPING file:
|
|
# folder::root
|
|
get_mapping()
|
|
{
|
|
entry="$(grep -E "^$1$MAPPING_SEPARATOR.+$" "$mapping_file" | head -n1 | grep -Eo "$MAPPING_SEPARATOR.+$" | cut -c 3-)"
|
|
echo "$entry"
|
|
}
|
|
|
|
|
|
backup_dir="$backup_dir/$(date +%Y-%m-%dT%H:%M:%S)"
|
|
|
|
# backup the old config files, symlinks will be skipped
|
|
# then symlink the files in $config_dir into the home directory
|
|
while IFS= read -d $'\0' -r folder ; do
|
|
folder="$(basename "$folder")"
|
|
ignored=0
|
|
for ignore in "${ignore_folders[@]}" ; do
|
|
if [[ "$ignore" == "$folder" ]] ; then
|
|
ignored=1
|
|
fi
|
|
done
|
|
if (( "$ignored" )) ; then
|
|
continue
|
|
fi
|
|
mapping="$(get_mapping "$folder")"
|
|
|
|
source_folder="$(path_combine "$config_dir" "$folder")"
|
|
[[ "$(ls "$source_folder")" ]] || continue
|
|
for file in "$source_folder"/* ; do
|
|
if [[ -z "$mapping" ]]; then
|
|
destination="$(path_combine "$DEFAULT_ROOT" ".$(basename "$file")")"
|
|
else
|
|
destination="$(path_combine "$(path_combine "$HOME" "$mapping")" "$(basename "$file")")"
|
|
fi
|
|
if [[ -L "$destination" ]]; then
|
|
continue
|
|
elif [[ -e "$destination" ]]; then
|
|
backup_destination="$(path_combine "$backup_dir" "$(basename "$destination")")"
|
|
if ! [[ -d "$backup_dir" ]] ; then
|
|
echo "mkdir -p \"$backup_dir\""
|
|
[[ $dryrun ]] || mkdir -p "$backup_dir"
|
|
fi
|
|
echo "mv \"$destination\" -> \"$backup_destination\""
|
|
[[ $dryrun ]] || mv "$destination" "$backup_destination"
|
|
fi
|
|
|
|
[[ -e "$destination" ]] && [[ "$(readlink "$destination")" == "$file" ]] && continue
|
|
echo "ln -sf \"$file\" -> \"$destination\""
|
|
[[ $dryrun ]] || ln -sf "$file" "$destination"
|
|
done
|
|
done < <(find "$config_dir"/* -maxdepth 0 -mindepth 0 -type d -print0)
|
|
|
|
# copy everything from the skel directory into $HOME, but do not overwrite anything
|
|
# the /. at the end of source is some cp magic that copies the content of a directory
|
|
# instead of the directory inself
|
|
[[ $dryrun ]] || rsync --archive --verbose --ignore-existing "$skel_dir/" "$HOME"
|