#!/bin/sh export STOW_DIR=${BOSUN_DIR:-/etc/portage/stow} err() { printf "bosun: %s\n" "$@" >&2 } errx() { err "$@" exit 1 } usage() { printf "usage: bosun add role ...\n" >&2 printf " bosun flush\n" >&2 printf " bosun [list [type ...]]\n" >&2 printf " bosun rebuild [role ...]\n" >&2 printf " bosun remove [role ...]\n" >&2 exit 1 } need_role() { test $# -gt 0 || errx "this command requires at least one role" for dir in "$@"; do test -d "$STOW_DIR/$dir" || errx "no such role '$dir' in $STOW_DIR" done } add() { need_role "$@" stow -S "$@" } remove() { need_role "$@" stow -D "$@" } flush() { list active | xargs -r -- stow -D } rebuild() { if test $# -gt 0; then need_role "$@" stow -R "$@" else list active | xargs -r -- stow -R fi } list() { subcmd="${1:-active}" case $subcmd in active) list_active;; all) list_all;; available) list_available;; *) errx "no such list type '$subcmd'. Try: active, all, available" esac } list_active() { real=$(realpath "$STOW_DIR") cd "$STOW_DIR/.." || exit 1 # XXX: GNU extensions: -print0 for find, -r -0 for xargs # XXX: GNU only: realpath find . -type l -print0 2>/dev/null \ | xargs -r0 realpath -e --relative-base "$real" 2>/dev/null \ | sed '/^\//d' | cut -d/ -f1 | sort -u } list_all() { ls -1 "$STOW_DIR" } list_available() { tmp="$(mktemp)" || exit 1 list_active > "$tmp" list_all | comm -13 "$tmp" - rm -f "$tmp" } cmd="${1:-list}" test $# -gt 0 && shift case $cmd in add) add "$@";; flush) flush;; list) list "$@";; rebuild) rebuild "$@";; del|delete|remove) remove "$@";; *) err "no such command '$cmd'"; usage;; esac