configfiles/dotstow.sh

172 lines
4.7 KiB
Bash
Executable File

#!/usr/bin/env bash
if [ -z "$(which realpath)" ]; then
realpath() {
rpath=$1
if [ "${rpath[0]}" == "/" ]; then
echo $rpath;
elif [ "${rpath:0:1}" == "~" ]; then
echo $HOME/${rpath:2}
elif [ "${rpath:0:2}" == ".." ]; then
echo $(dirname $(pwd))/${rpath:3}
elif [ "${rpath:0:1}" == "." ]; then
echo $(pwd)/${rpath:2}
else
echo $(pwd)/$rpath
fi
}
fi
stow() {
local stowrepo=$1
local stowtarget=$2
[ "$VERBOSE" -gt 1 ] && echo "Entering $stowrepo..."
local files=()
while read line; do
if [ "$line" != "." -a "$line" != ".." ]; then
files+=("$line")
fi
done < <(ls -a $stowrepo)
[ "$VERBOSE" -gt 1 ] && echo "Filelist: ${files[@]}"
for file in "${files[@]}"; do
local file=$(basename "$file")
local ctarget="$stowtarget/$file"
local csource="$stowrepo/$file"
if [ -e "$ctarget" ]; then
if [ -L "$ctarget" -a "$(readlink -f "$ctarget")" == "$(realpath "$csource")" ]; then # Link already exists. Skip
[ $VERBOSE -gt 0 ] && echo "Skipping $ctarget..."
elif [ ! -L "$ctarget" -a -d "$ctarget" -a -d "$csource" ]; then # Dictionary exists. Enter
stow "$csource" "$ctarget"
else # No can do.
echo "Aborting. $ctarget exists, but is not owned by dotstow"; exit 1
fi
else
if [ "$SIMULATE" -gt 0 ] || ln -s "$(realpath "$csource")" "$ctarget"; then
[ $VERBOSE -gt 0 ] && echo "Linking $ctarget to $csource"
else
echo "Could not link $ctarget to $csource"; exit 1
fi
fi
done
[ "$VERBOSE" -gt 1 ] && echo "Leaving $stowrepo..."
}
destow() {
local stowrepo=$1
local stowtarget=$2
[ "$VERBOSE" -gt 1 ] && echo "Entering $stowrepo..."
local files=()
while read line; do
if [ "$line" != "." -a "$line" != ".." ]; then
files+=("$line")
fi
done < <(ls -a $stowrepo)
[ "$VERBOSE" -gt 1 ] && echo "Filelist: ${files[@]}"
for file in "${files[@]}"; do
local file=$(basename "$file")
local ctarget="$stowtarget/$file"
local csource="$stowrepo/$file"
if [ ! -e "$ctarget" ]; then # Target doesn't exists. skip
[ $VERBOSE -gt 0 ] && echo "$ctarget does not exist. Skipping..."
elif [ ! -L "$ctarget" ]; then
if [ -d "$ctarget" -a -d "$csource" ]; then
destow "$csource" "$ctarget"
else
echo "$ctarget exists, but is not owned by dotstow (Not a link)"; exit 1
fi
elif [ "$(readlink -f "$ctarget")" != "$(realpath "$csource")" ]; then
[ "$VERBOSE" -gt 0 ] && echo "$(readlink -f "$ctarget")" != "$(realpath "$csource")"
echo "$ctarget exists, but is not owned by dotstow (Wrong link)"; exit 1
else
if [ "$SIMULATE" -gt 0 ] || rm -f "$ctarget"; then
[ $VERBOSE -gt 0 ] && echo "Unlinking $ctarget"
else
echo "Could not unlink $ctarget"; exit 1
fi
fi
done
[ "$VERBOSE" -gt 1 ] && echo "Leaving $stowrepo..."
}
restow() {
destow "$1" "$2"
stow "$1" "$2"
}
TARGET="$HOME"
VERBOSE=0
REPO="$(dirname $0)"
COMMAND=stow
HELP=0
SIMULATE=0
while getopts DSRvhnt: opt; do
case $opt in
D)
COMMAND=destow
;;
S)
COMMAND=stow
;;
R)
COMMAND=restow
;;
t)
TARGET="$OPTARG"
;;
v)
let VERBOSE++
;;
h)
HELP=1
;;
n)
SIMULATE=1
;;
\?)
echo "Invalid option: -$OPTARG" >&2
exit 1
;;
:)
echo "Option -$OPTARG required an argument." >&2
;;
esac
done
shift $[ $OPTIND-1 ]
TARGET=${TARGET/%\//} # Remove trailing slashes
if [ "$HELP" -eq 1 -o "${#@}" -eq 0 ]; then
echo -e "Usage: ./dotstow.sh [-DSRvhn] [-t target] stows..."
echo -e "\t-D: Destow"
echo -e "\t-S: Stow"
echo -e "\t-R: Restow"
echo -e "\t-t: target folder (default ~)"
echo -e "\t-v: verbose"
echo -e "\t-h: show this help"
echo -e "\t-n: simulated/dry-run"
echo -e "\tstows: stow folders relative to dotstow.sh"
fi
for stow in $@; do
if [ ! -d "$REPO/$stow" ]; then
echo "Stow $stow not found." >&2
exit 2
fi
$COMMAND "$REPO/$stow" "$TARGET"
done
[ "$SIMULATE" -gt 0 ] && echo "Warning: Simulated. No actual changes to the filesystem have been done."