diff options
Diffstat (limited to 'link/lib.sh')
| -rw-r--r-- | link/lib.sh | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/link/lib.sh b/link/lib.sh new file mode 100644 index 0000000..1899f00 --- /dev/null +++ b/link/lib.sh @@ -0,0 +1,122 @@ +# shellcheck shell=bash +# shellcheck disable=SC2034 # the paths below are for whichever script sources this +# +# Shared by link.sh and the link/*.sh parts: the dry-run flag, colours, link and +# link_all, and the paths they all use. Source it with the script's own +# arguments: +# +# source "$(dirname "$0")/lib.sh" "$@" +# +# Dry run unless the first argument is `yes`. +# +# Other repos' link.sh source this file instead of keeping copies, finding it +# through $DOT_LINK_LIB, which link.sh exports for them. Keep these names and +# the `yes` convention stable, or change them there as well. + +is_dry_run="y" +if [[ "${1:-}" == "yes" ]] +then + is_dry_run="" +fi + +color() { + color_code="$1" + shift + # Black 0;30 Dark Gray 1;30 + # Red 0;31 Light Red 1;31 + # Green 0;32 Light Green 1;32 + # Brown/Orange 0;33 Yellow 1;33 + # Blue 0;34 Light Blue 1;34 + # Purple 0;35 Light Purple 1;35 + # Cyan 0;36 Light Cyan 1;36 + # Light Gray 0;37 White 1;37 + yes_color="\033[${color_code}m" + no_color='\033[0m' + echo -e "${yes_color}$*${no_color}" +} + +green() { + color '0;32' "$@" +} + +yellow() { + color '1;33' "$@" +} + +red() { + color '0;31' "$@" +} + +# Link up dotfiles +link() { + local target="$1" + local link="$2" + if [[ -z "$1" ]] + then + >&2 echo "Error: need valid target" + return 1 + fi + if [[ -z "$2" ]] + then + >&2 echo "Error: need valid link" + return 1 + fi + target="$(realpath "${target}")" + + if [[ -n "${is_dry_run}" ]] + then + local actual + actual="$(readlink "$link" || true)" + if [[ -n "${actual}" ]] ; then + actual="$(realpath "$actual" || true)" + fi + + if [[ -L "$link" && "$target" == "$actual" ]] + then + green "$link already exists and is correct" + return + elif [[ -e "$link" ]] + then + if diff "$link" "$target" > /dev/null + then + yellow "$link already exists and will be deleted first but contents are the same. $target != $actual" + else + red "$link WILL CHANGE" + fi + else + yellow "$link will be created" + fi + else + mkdir -p "$(dirname "$2")" + rm -rf "$2" + ln -sf "$1" "$2" + fi +} + +link_all() { + from="$1" + to="$2" + # Process substitution rather than a pipe, so `link` runs in this shell and + # not a subshell; NUL-delimited so names with spaces survive (SC2044/SC2086). + while IFS= read -r -d '' f + do + link "$f" "$to/$(basename "$f")" + done < <(find "$from" -mindepth 1 -maxdepth 1 -print0) +} + +# Run another script with this interface, dry or not as this one is. +run_link() { + if [[ -n "${is_dry_run}" ]] + then + "$1" + else + "$1" yes + fi +} + +dotfiles_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +config_dir="$dotfiles_dir/config" +xdg_config_dir="${XDG_CONFIG_HOME:-$HOME/.config}" + +# iCloud Drive, on a Mac signed into it; absent everywhere else. +icloud_dir="$HOME/Library/Mobile Documents/com~apple~CloudDocs" |
