aboutsummaryrefslogtreecommitdiff
path: root/stowsh
diff options
context:
space:
mode:
authorAdam Hovorka <[email protected]>2017-07-10 11:39:20 -0600
committerAdam Hovorka <[email protected]>2017-07-10 11:39:20 -0600
commit6b4563f569454c12aded584db4330f707bc55c3d (patch)
tree459a19255bc73f8fbbf1dd6b4f0c8e8a82fc8523 /stowsh
Initial commit
Diffstat (limited to 'stowsh')
-rwxr-xr-xstowsh182
1 files changed, 182 insertions, 0 deletions
diff --git a/stowsh b/stowsh
new file mode 100755
index 0000000..3f9c687
--- /dev/null
+++ b/stowsh
@@ -0,0 +1,182 @@
+#!/usr/bin/env bash
+
+_runcommands() {
+ local prefix=''
+ if [[ $DRYRUN == 1 ]] || [[ $VERBOSE -gt 1 ]]; then
+ echo "$@"
+ fi
+ if [[ $DRYRUN != 1 ]]; then
+ eval "$@"
+ fi
+}
+
+echoerr() {
+ printf "%s\n" "$*" >&2;
+}
+
+deperr() {
+ echoerr "stowsh requires $1"
+}
+
+stowsh_setpaths() {
+ if command -v grealpath >/dev/null 2>&1; then
+ rpcmd="grealpath"
+ elif command -v realpath >/dev/null 2>&1; then
+ rpcmd="realpath"
+ else
+ deperr "GNU coreutils"
+ return 1
+ fi
+ if ! strings "$(which "$rpcmd")" | grep -q "GNU coreutils" ; then
+ deperr "GNU coreutils"
+ return 1
+ fi
+ if command -v gfind >/dev/null 2>&1; then
+ findcmd="gfind"
+ elif command -v find >/dev/null 2>&1; then
+ findcmd="find"
+ else
+ deperr "GNU findutils"
+ return 1
+ fi
+ if ! strings "$(which "$findcmd")" | grep -q "GNU findutils" ; then
+ deperr "GNU findutils"
+ return 1
+ fi
+}
+
+stowsh_install() {
+ stowsh_setpaths || return 1
+ local pkg=$1
+ local target
+ target=$( "$rpcmd" "${2-$PWD}" )
+ local commands=()
+
+ (
+ cd "$pkg" || return 1
+ dirs="$($findcmd . -mindepth 1 -type d | sed "s|./||")"
+ for d in $dirs ; do
+ commands+=("mkdir -p '$target/$d'")
+ done
+
+ local files
+ files="$($findcmd . -type f -or -type l | sed "s|./||")"
+ for f in $files ; do
+ local targetf="$target/$f"
+ local thisdir
+ thisdir=$(dirname "$targetf")
+ local relative
+ relative=$($rpcmd "$f" --relative-to="$thisdir" --canonicalize-missing)
+ if [[ ! -f "$targetf" ]] ; then
+ commands+=("ln -s '$relative' '$targetf'")
+ else
+ echoerr "$targetf already exists."
+ if [[ ! $SKIP -eq 1 ]]; then
+ echoerr "Aborting. Rerun with the -s flag to skip errors.";
+ return
+ fi
+ fi
+ done
+ for cmd in "${commands[@]}"; do
+ _runcommands "$cmd"
+ done;
+ )
+}
+
+stowsh_uninstall() {
+ stowsh_setpaths || return 1
+ local pkg=$1
+ local target
+ target=$( "$rpcmd" "${2-$PWD}" )
+ local commands=()
+
+ (
+ cd "$pkg" || return 1
+ local files
+ files="$($findcmd . -type f -or -type l | sed "s|./||")"
+ for f in $files ; do
+ local targetf="$target/$f"
+ if [[ $($rpcmd "$targetf") == $(realpath "$f") ]] ; then
+ commands+=("rm '$targetf'")
+ elif [[ -f "$targetf" ]] ; then
+ echoerr "$targetf does not point to to $(realpath "$f")."
+ if [[ ! $SKIP -eq 1 ]]; then
+ echoerr "Aborting. Rerun with the -s flag to skip errors.";
+ return
+ fi
+ elif [[ ! -f "$targetf" ]] ; then
+ echoerr "$targetf does not exist. Nothing to do."
+ if [[ ! $SKIP -eq 1 ]]; then
+ echoerr "Aborting. Rerun with the -s flag to skip errors.";
+ return
+ fi
+ fi
+ done
+
+ dirs="$($findcmd . -mindepth 1 -type d | sed "s|./||")"
+ for d in $dirs ; do
+ commands+=("[[ -d '$target/$d' ]] && $findcmd '$target/$d' -type d -empty -delete")
+ done
+ for cmd in "${commands[@]}"; do
+ _runcommands "$cmd"
+ done;
+ )
+}
+
+stowsh_help() {
+ echo "Usage: $0 [-D] [-n] [-s] [-v[v]] [-t TARGET] PACKAGES..."
+}
+
+if [ "$0" = "$BASH_SOURCE" ]; then
+ UNINSTALL=0
+ DRYRUN=0
+ SKIP=0
+ TARGET="$PWD"
+ PACKAGES=()
+ while [[ "$@" ]]; do
+ if [[ $1 =~ ^- ]]; then
+ OPTIND=1
+ while getopts ":vhDsnt:" opt; do
+ case $opt in
+ h)
+ stowsh_help
+ exit 0
+ ;;
+ D) UNINSTALL=1
+ ;;
+ n) DRYRUN=1
+ ;;
+ s) SKIP=1
+ ;;
+ v) VERBOSE=$((VERBOSE + 1))
+ ;;
+ t) TARGET="$OPTARG"
+ ;;
+ *) echo "'$OPTARG' is an invalid option/flag"
+ exit 1
+ ;;
+ esac
+ done
+ shift $((OPTIND-1))
+ else
+ PACKAGES+=("$1")
+ shift
+ fi
+ done
+
+ if [[ ${#PACKAGES[@]} -eq 0 ]] ; then
+ stowsh_help
+ exit 1
+ fi
+
+ for i in ${!PACKAGES[*]}; do
+ pkg=${PACKAGES[$i]}
+ if [[ $UNINSTALL -eq 1 ]]; then
+ if [[ $VERBOSE -gt 0 ]] ; then echoerr "uninstalling $pkg from $TARGET" ; fi
+ stowsh_uninstall "$pkg" "$TARGET"
+ else
+ if [[ $VERBOSE -gt 0 ]] ; then echoerr "installing $pkg to $TARGET" ; fi
+ stowsh_install "$pkg" "$TARGET"
+ fi
+ done
+fi