refactor code and add fallback prompt to zsh
This commit is contained in:
95
install
95
install
@@ -1,30 +1,25 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
set -o nounset
|
||||
|
||||
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" \
|
||||
|| exit 1
|
||||
SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)
|
||||
readonly SCRIPT_DIR
|
||||
readonly PROFILES_DIR="${SCRIPT_DIR}/profiles"
|
||||
readonly -a STOW_ARGS=("--no-folding" "--adopt" "--dir" "${PROFILES_DIR}" "--target" "${HOME}")
|
||||
readonly SCRIPT_NAME="${0##*/}"
|
||||
readonly PROFILES_DIR=${SCRIPT_DIR}/profiles
|
||||
readonly -a STOW_ARGS=(--no-folding --adopt --dir "${PROFILES_DIR}" --target "${HOME}")
|
||||
readonly SCRIPT_NAME=${0##*/}
|
||||
|
||||
print_opt() {
|
||||
local -r option="$1"
|
||||
local -r description="$2"
|
||||
local -r option=$1
|
||||
local -r description=$2
|
||||
printf " %-22s %s\n" "${option}" "${description}"
|
||||
}
|
||||
|
||||
shell_quote() {
|
||||
local -r string="$1"
|
||||
local -r string=$1
|
||||
printf "'%s'" "${string//'/'\\''}"
|
||||
}
|
||||
|
||||
array_contains() {
|
||||
local -r target_item="$1"; shift
|
||||
local -a -r array=( "$@" )
|
||||
local -r target_item=$1; shift
|
||||
local -a -r array=("$@")
|
||||
local item
|
||||
for item in "${array[@]}"; do
|
||||
if [[ ${item} == "${target_item}" ]]; then
|
||||
@@ -35,13 +30,13 @@ array_contains() {
|
||||
}
|
||||
|
||||
die() {
|
||||
local -r message="$1"
|
||||
local -r message=$1
|
||||
printf "%s: %b\n" "${SCRIPT_NAME}" "${message}" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
invalid_option() {
|
||||
local -r option="$1"
|
||||
local -r option=$1
|
||||
die "invalid option $(shell_quote "${option}")\nTry '${SCRIPT_NAME} --help' for usage."
|
||||
}
|
||||
|
||||
@@ -69,7 +64,7 @@ EOF
|
||||
}
|
||||
|
||||
require_profiles_dir() {
|
||||
if [[ ! -d "${PROFILES_DIR}" ]]; then
|
||||
if [[ ! -d ${PROFILES_DIR} ]]; then
|
||||
cat >&2 <<EOF
|
||||
Error: profiles directory not found: ${PROFILES_DIR}
|
||||
|
||||
@@ -89,18 +84,14 @@ EOF
|
||||
}
|
||||
|
||||
parse_args() {
|
||||
list_profiles=""
|
||||
prune_symlinks=""
|
||||
verbose=""
|
||||
profile=""
|
||||
while (( $# > 0 )); do
|
||||
case "$1" in
|
||||
case $1 in
|
||||
-h)
|
||||
show_general_help
|
||||
exit 0
|
||||
;;
|
||||
--help)
|
||||
if (( $# >= 2 )) && [[ -n $2 ]] && [[ $2 != -* ]]; then
|
||||
if (( $# >= 2 )) && [[ $2 ]] && [[ $2 != -* ]]; then
|
||||
show_help_topic "$2"
|
||||
else
|
||||
show_general_help
|
||||
@@ -108,17 +99,17 @@ parse_args() {
|
||||
exit 0
|
||||
;;
|
||||
--help=*)
|
||||
local -r topic="${1#*=}"
|
||||
local -r topic=${1#*=}
|
||||
[[ -z ${topic} ]] && show_general_help && exit 0
|
||||
show_help_topic "${topic}"
|
||||
exit 0
|
||||
;;
|
||||
-l|--list-profiles) list_profiles="true"; shift ;;
|
||||
-P|--prune-symlinks) prune_symlinks="true"; shift ;;
|
||||
-v|--verbose) verbose="true"; shift ;;
|
||||
-l|--list-profiles) list_profiles=true; shift ;;
|
||||
-P|--prune-symlinks) prune_symlinks=true; shift ;;
|
||||
-v|--verbose) verbose=true; shift ;;
|
||||
-p|--profile)
|
||||
( (( $# < 2 )) || [[ -z "$2" ]] ) && die "--profile requires an argument"
|
||||
profile="$2"
|
||||
profile=$2
|
||||
shift 2
|
||||
;;
|
||||
*) invalid_option "$1" ;;
|
||||
@@ -131,7 +122,7 @@ validate_args() {
|
||||
die "options '--list-profiles' and others cannot be used together"
|
||||
fi
|
||||
|
||||
if [[ -n ${profile} ]] && ! array_contains "${profile}" "${PROFILES[@]}"; then
|
||||
if [[ ${profile} ]] && ! array_contains "${profile}" "${PROFILES[@]}"; then
|
||||
die "profile $(shell_quote "${profile}") cannot be found"
|
||||
fi
|
||||
}
|
||||
@@ -157,8 +148,8 @@ show_general_help() {
|
||||
}
|
||||
|
||||
show_help_topic() {
|
||||
local topic="$1"
|
||||
case "${topic}" in
|
||||
local topic=$1
|
||||
case ${topic} in
|
||||
profile)
|
||||
cat <<EOF
|
||||
A profile is a directory under 'profiles/' that groups dotfiles to be installed
|
||||
@@ -183,9 +174,9 @@ EOF
|
||||
}
|
||||
|
||||
run_pre_hooks() {
|
||||
local -r target_profile="$1"
|
||||
local -r target_profile=$1
|
||||
for hook in "${PROFILES_DIR}/${target_profile}"/hooks/pre/*; do
|
||||
if [[ -f "${hook}" && -x "${hook}" ]]; then
|
||||
if [[ -f ${hook} && -x ${hook} ]]; then
|
||||
echo "Running pre-install hook ${hook##*/}"
|
||||
"${hook}"
|
||||
fi
|
||||
@@ -193,9 +184,9 @@ run_pre_hooks() {
|
||||
}
|
||||
|
||||
run_post_hooks() {
|
||||
local -r target_profile="$1"
|
||||
local -r target_profile=$1
|
||||
for hook in "${PROFILES_DIR}/${target_profile}"/hooks/post/*; do
|
||||
if [[ -f "${hook}" && -x "${hook}" ]]; then
|
||||
if [[ -f ${hook} && -x ${hook} ]]; then
|
||||
echo "Running post-install hook ${hook##*/}"
|
||||
"${hook}"
|
||||
fi
|
||||
@@ -205,45 +196,37 @@ run_post_hooks() {
|
||||
prune_symlinks() {
|
||||
echo -n "Removing dangling symlinks in home directory... "
|
||||
|
||||
pushd "${HOME}" >/dev/null
|
||||
pushd "${HOME}" >/dev/null || exit 1
|
||||
local common_files
|
||||
local -r target_profile="$1"
|
||||
local -r target_profile=$1
|
||||
mapfile -t common_files < <(comm -12 <(find "${HOME}" -type l -printf '%P\n' 2>/dev/null | sort) \
|
||||
<(find "${PROFILES_DIR}/${target_profile}" -type f -printf '%P\n' | sort))
|
||||
local target_file
|
||||
for target_file in "${common_files[@]}"; do
|
||||
local -a rm_args=( "--force" )
|
||||
[[ ${verbose} ]] && rm_args+=( "--verbose" )
|
||||
rm "${rm_args[@]}" "${target_file}"
|
||||
local -a rm_args=(--force)
|
||||
[[ ${verbose} ]] && rm_args+=(--verbose)
|
||||
rm "${rm_args[@]}" -- "${target_file}"
|
||||
done
|
||||
popd >/dev/null
|
||||
popd >/dev/null || exit 1
|
||||
|
||||
echo "OK"
|
||||
}
|
||||
|
||||
stow_profile() {
|
||||
local -r target_profile="$1"
|
||||
local error_log
|
||||
error_log="$(stow "${STOW_ARGS[@]}" "${target_profile}" 2>&1)"
|
||||
if (( $? == 0 )); then
|
||||
local -r target_profile=$1
|
||||
if stow "${STOW_ARGS[@]}" "${target_profile}" 2>&1; then
|
||||
echo "Profile ${target_profile} has been stowed"
|
||||
else
|
||||
echo "Failed to create symlinks pointing to dotfiles in profile ${target_profile}"
|
||||
echo "Executed command: stow ${STOW_ARGS[*]} ${target_profile}"
|
||||
fi
|
||||
if [[ -n "${error_log}" ]]; then
|
||||
echo "${error_log}" > /tmp/stow-error.log
|
||||
[[ ${verbose} ]] && echo "${error_log}"
|
||||
echo "Error log has been saved into /tmp/stow-error.log"
|
||||
fi
|
||||
}
|
||||
|
||||
fetch_parents() {
|
||||
local -r target_profile="$1"
|
||||
if [[ -s "${PROFILES_DIR}/${target_profile}/parent" ]]; then
|
||||
local -r target_profile=$1
|
||||
if [[ -s ${PROFILES_DIR}/${target_profile}/parent ]]; then
|
||||
local parent
|
||||
parent=$(cat "${PROFILES_DIR}/${target_profile}/parent")
|
||||
if [[ -s "${PROFILES_DIR}/${parent}/parent" ]]; then
|
||||
if [[ -s ${PROFILES_DIR}/${parent}/parent ]]; then
|
||||
fetch_parents "${parent}"
|
||||
fi
|
||||
echo "${parent}"
|
||||
@@ -251,7 +234,7 @@ fetch_parents() {
|
||||
}
|
||||
|
||||
build_deptree() {
|
||||
local -r target_profile="$1"
|
||||
local -r target_profile=$1
|
||||
fetch_parents "${target_profile}"
|
||||
echo "${target_profile}"
|
||||
}
|
||||
@@ -272,7 +255,7 @@ main() {
|
||||
require_profiles_dir
|
||||
(( $# == 0 )) && show_general_help && exit 1
|
||||
validate_args
|
||||
[[ -n ${list_profiles} ]] && echo "${PROFILES[@]}" && exit 0
|
||||
[[ ${list_profiles} ]] && echo "${PROFILES[@]}" && exit 0
|
||||
install_dotfiles
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user