#!/usr/bin/env bash set -e source argparse.bash functions=; def_arg functions f value default "${XDG_CONFIG_HOME:-"$HOME/.config"}/mgmt/functions" modules=; def_arg modules m value default "${XDG_CONFIG_HOME:-"$HOME/.config"}/mgmt/modules" positional=(); parse_args "$@" while IFS= read -rd '' fnfile; do source "$fnfile" done < <(find "$functions" -type f -print0) PREFIX="" grey() { printf "\33[37;2m%s\33[0;m" "$*"; } red() { printf "\33[31;1m%s\33[0;m" "$*"; } diag() { >&2 printf "\33[2K\r%s" "$(grey "$PREFIX")" >&2 echo "$@" } join_by() { local IFS="$1"; shift; echo "$*"; } filter_by_args() { grep -E "$(join_by '|' "${positional[@]}")"; } ##### # Gather dependencies of (filtered) modules ##### declare -a found_modules mapfile -t filtered_mods < <(find "$modules" -type f | filter_by_args) set -- "${filtered_mods[@]}" while [ $# -gt 0 ]; do unset deps; declare -a deps for mod; do if echo "${found_modules[@]}" | grep -q "$mod"; then continue fi found_modules+=( "$mod" ) unset DEPENDS source "$mod" for dep in "${DEPENDS[@]}"; do if echo "${found_modules[@]}" | grep -qv "$dep"; then if echo "${deps[@]}" | grep -qv "$dep"; then deps+=( "$dep" ) fi fi done done set -- "${deps[@]}" done ##### # Resolve dependency ordering ##### declare -a ordered_modules set -- "${found_modules[@]}" while [ $# -gt 0 ]; do unset remaining; declare -a remaining for mod; do unset DEPENDS source "$mod" if [[ -n "$(comm -23 <(printf -- '%s\n' "${DEPENDS[@]}" | sort) <(printf -- '%s\n' "${ordered_modules[@]}" | sort))" ]]; then remaining+=( "$mod" ) else ordered_modules+=( "$mod" ) fi done if [ $# -eq ${#remaining[@]} ]; then diag "$(red "Error: dependency loop involving ${remaining[*]}")" exit 1 fi set -- "${remaining[@]}" done ##### # Apply modules ##### sudo -v set -- "${ordered_modules[@]}" for mod; do diag -e "\nApplying $mod" PREFIX="[$mod] " unset check_setup setup check_apply apply source "$modules/$mod" test "$(declare -F check_setup)" || { check_setup() { false ; } } test "$(declare -F check_apply)" || { check_apply() { false ; } } test "$(declare -F setup)" || { setup() { true; } } test "$(declare -F apply)" || { apply() { true; } } check_setup || setup check_apply || apply PREFIX="" done