feat(proxy-client): добавлен самостоятельный установщик
- Зачем: - пакет должен устанавливаться отдельно от dotfiles без ручной раскладки и опасных замен. - Что: - добавлен безопасный установщик со Stow и прямыми симлинками. - добавлены идемпотентная настройка Bash и защита машинных файлов. - обновлены инструкция и полный набор интеграционных проверок. - Проверка: - env XDG_STATE_HOME=<временный каталог> bash tests/test_proxy_client_full.sh.
This commit is contained in:
1 parent
43404d374f
commit
f679515a8f
5 files changed
+645
-12
No files matched your search
Executable
+216
@@ -0,0 +1,216 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
PACKAGE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
|
||||
STOW_BIN="${STOW_BIN:-stow}"
|
||||
SETUP_SHELL=1
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Использование: ./install.sh [--no-shell-setup]
|
||||
|
||||
--no-shell-setup не изменять ~/.bashrc
|
||||
EOF
|
||||
}
|
||||
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "$1" in
|
||||
--no-shell-setup)
|
||||
SETUP_SHELL=0
|
||||
;;
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Ошибка: неизвестный параметр: $1" >&2
|
||||
usage >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
SOURCES=(
|
||||
"$PACKAGE_DIR/.local/bin/proxy-client"
|
||||
"$PACKAGE_DIR/.config/proxy-client/shell.bash"
|
||||
"$PACKAGE_DIR/.config/proxy-client/examples"
|
||||
)
|
||||
TARGETS=(
|
||||
"$HOME/.local/bin/proxy-client"
|
||||
"$HOME/.config/proxy-client/shell.bash"
|
||||
"$HOME/.config/proxy-client/examples"
|
||||
)
|
||||
STOW_IGNORE_PATTERNS=(
|
||||
'^\.local/bin/proxy-client$'
|
||||
'^\.config/proxy-client/shell\.bash$'
|
||||
'^\.config/proxy-client/examples$'
|
||||
)
|
||||
|
||||
source_errors=()
|
||||
[ -x "${SOURCES[0]}" ] || source_errors+=("${SOURCES[0]}")
|
||||
[ -f "${SOURCES[1]}" ] || source_errors+=("${SOURCES[1]}")
|
||||
[ -d "${SOURCES[2]}" ] || source_errors+=("${SOURCES[2]}")
|
||||
if [ "${#source_errors[@]}" -gt 0 ]; then
|
||||
echo "Ошибка: отсутствуют обязательные файлы исходного пакета:" >&2
|
||||
printf ' %s\n' "${source_errors[@]}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
"${SOURCES[0]}" --help >/dev/null
|
||||
bash -n "${SOURCES[1]}"
|
||||
|
||||
SHELL_BLOCK_START='# >>> proxy-client >>>'
|
||||
SHELL_BLOCK_END='# <<< proxy-client <<<'
|
||||
SHELL_SETUP_NEEDED=0
|
||||
BASH_CUSTOM_HAS_MODULE=0
|
||||
SHELL_PATH_NEEDED=1
|
||||
SHELL_SOURCE_NEEDED=1
|
||||
SHELL_BLOCK_CONFLICT=0
|
||||
if [ "$SETUP_SHELL" -eq 1 ]; then
|
||||
if [ -f "$HOME/.bash_custom" ] \
|
||||
&& grep -Fq 'proxy-client/shell.bash' "$HOME/.bash_custom"; then
|
||||
BASH_CUSTOM_HAS_MODULE=1
|
||||
SHELL_SOURCE_NEEDED=0
|
||||
fi
|
||||
|
||||
bashrc_start_count=0
|
||||
bashrc_end_count=0
|
||||
if [ -f "$HOME/.bashrc" ]; then
|
||||
bashrc_start_count="$(
|
||||
grep -Fxc "$SHELL_BLOCK_START" "$HOME/.bashrc" || true
|
||||
)"
|
||||
bashrc_end_count="$(
|
||||
grep -Fxc "$SHELL_BLOCK_END" "$HOME/.bashrc" || true
|
||||
)"
|
||||
if grep -Fq 'export PATH="$HOME/.local/bin:$PATH"' "$HOME/.bashrc"; then
|
||||
SHELL_PATH_NEEDED=0
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$bashrc_start_count" -eq 0 ] && [ "$bashrc_end_count" -eq 0 ]; then
|
||||
if [ "$SHELL_PATH_NEEDED" -eq 1 ] \
|
||||
|| [ "$SHELL_SOURCE_NEEDED" -eq 1 ]; then
|
||||
SHELL_SETUP_NEEDED=1
|
||||
fi
|
||||
elif [ "$bashrc_start_count" -eq 1 ] \
|
||||
&& [ "$bashrc_end_count" -eq 1 ] \
|
||||
&& [ "$SHELL_PATH_NEEDED" -eq 0 ] \
|
||||
&& { [ "$BASH_CUSTOM_HAS_MODULE" -eq 1 ] \
|
||||
|| grep -Fq 'proxy-client/shell.bash' "$HOME/.bashrc"; }; then
|
||||
:
|
||||
else
|
||||
SHELL_BLOCK_CONFLICT=1
|
||||
fi
|
||||
fi
|
||||
|
||||
conflicts=()
|
||||
missing_targets=0
|
||||
stow_ignore_args=()
|
||||
PARENT_DIRS=(
|
||||
"$HOME/.local"
|
||||
"$HOME/.local/bin"
|
||||
"$HOME/.config"
|
||||
"$HOME/.config/proxy-client"
|
||||
)
|
||||
for parent_dir in "${PARENT_DIRS[@]}"; do
|
||||
if { [ -e "$parent_dir" ] || [ -L "$parent_dir" ]; } \
|
||||
&& { [ ! -d "$parent_dir" ] || [ -L "$parent_dir" ]; }; then
|
||||
conflicts+=("$parent_dir")
|
||||
fi
|
||||
done
|
||||
|
||||
for index in "${!TARGETS[@]}"; do
|
||||
target="${TARGETS[$index]}"
|
||||
source_path="${SOURCES[$index]}"
|
||||
if [ -e "$target" ] || [ -L "$target" ]; then
|
||||
if [ ! -L "$target" ] \
|
||||
|| [ "$(readlink -f "$target" 2>/dev/null || true)" != "$source_path" ]; then
|
||||
conflicts+=("$target")
|
||||
else
|
||||
stow_ignore_args+=("--ignore=${STOW_IGNORE_PATTERNS[$index]}")
|
||||
fi
|
||||
else
|
||||
missing_targets=$((missing_targets + 1))
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$SHELL_SETUP_NEEDED" -eq 1 ] \
|
||||
&& { [ -e "$HOME/.bashrc" ] || [ -L "$HOME/.bashrc" ]; } \
|
||||
&& [ ! -f "$HOME/.bashrc" ]; then
|
||||
conflicts+=("$HOME/.bashrc")
|
||||
fi
|
||||
if [ "$SHELL_BLOCK_CONFLICT" -eq 1 ]; then
|
||||
conflicts+=("$HOME/.bashrc")
|
||||
fi
|
||||
|
||||
if [ "${#conflicts[@]}" -gt 0 ]; then
|
||||
echo "Ошибка: найдены конфликтующие пути:" >&2
|
||||
printf ' %s\n' "${conflicts[@]}" >&2
|
||||
echo "Разберите их вручную и повторите установку." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "$HOME/.local/bin" "$HOME/.config/proxy-client"
|
||||
|
||||
if command -v "$STOW_BIN" >/dev/null 2>&1; then
|
||||
echo "Установка с помощью Stow."
|
||||
if [ "$missing_targets" -gt 0 ]; then
|
||||
"$STOW_BIN" --dir="$(dirname "$PACKAGE_DIR")" --target="$HOME" \
|
||||
"${stow_ignore_args[@]}" \
|
||||
"$(basename "$PACKAGE_DIR")"
|
||||
fi
|
||||
else
|
||||
echo "Установка без Stow: создаю символические ссылки напрямую."
|
||||
for index in "${!TARGETS[@]}"; do
|
||||
target="${TARGETS[$index]}"
|
||||
source_path="${SOURCES[$index]}"
|
||||
if [ ! -L "$target" ]; then
|
||||
ln -s "$source_path" "$target"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
"$HOME/.local/bin/proxy-client" --help >/dev/null
|
||||
bash -n "$HOME/.config/proxy-client/shell.bash"
|
||||
|
||||
if [ "$SHELL_SETUP_NEEDED" -eq 1 ]; then
|
||||
cat >> "$HOME/.bashrc" <<'EOF'
|
||||
|
||||
# >>> proxy-client >>>
|
||||
EOF
|
||||
if [ "$SHELL_PATH_NEEDED" -eq 1 ]; then
|
||||
cat >> "$HOME/.bashrc" <<'EOF'
|
||||
case ":$PATH:" in
|
||||
*":$HOME/.local/bin:"*) ;;
|
||||
*)
|
||||
export PATH="$HOME/.local/bin:$PATH"
|
||||
;;
|
||||
esac
|
||||
EOF
|
||||
fi
|
||||
if [ "$SHELL_SOURCE_NEEDED" -eq 1 ]; then
|
||||
cat >> "$HOME/.bashrc" <<'EOF'
|
||||
[ -f "$HOME/.config/proxy-client/shell.bash" ] && source "$HOME/.config/proxy-client/shell.bash"
|
||||
EOF
|
||||
fi
|
||||
cat >> "$HOME/.bashrc" <<'EOF'
|
||||
# <<< proxy-client <<<
|
||||
EOF
|
||||
elif [ "$SETUP_SHELL" -eq 0 ]; then
|
||||
echo "Настройка Bash пропущена (--no-shell-setup)."
|
||||
fi
|
||||
|
||||
if [ "$SETUP_SHELL" -eq 1 ]; then
|
||||
RELOAD_COMMAND='source ~/.bashrc'
|
||||
else
|
||||
RELOAD_COMMAND='source ~/.config/proxy-client/shell.bash'
|
||||
fi
|
||||
|
||||
cat <<EOF
|
||||
proxy-client установлен.
|
||||
Исходный каталог должен оставаться по постоянному пути:
|
||||
$PACKAGE_DIR
|
||||
Примените настройки в текущей сессии: $RELOAD_COMMAND
|
||||
Настройка режима описана в $PACKAGE_DIR/README.md.
|
||||
EOF
|
||||
Reference in new issue
Block a user