Package the portable DSH profiles, local plugins, desktop integration, Firefox wrapper, and ownership-aware installer lifecycle. Bundle checksum-pinned OpenVSCode, editor extensions, translation assets, and cloudflared so unreliable upstream artifact downloads cannot break a clean installation.
88 lines
3.4 KiB
Bash
Executable file
88 lines
3.4 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
repository_directory=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
|
|
dsh_home="$HOME/.dsh"
|
|
profile_directory="$dsh_home/profiles/web"
|
|
state_directory=${XDG_STATE_HOME:-"$HOME/.local/state"}/dsh-arch-setup
|
|
managed_manifest="$state_directory/managed.tsv"
|
|
backup_manifest="$state_directory/backups.tsv"
|
|
skip_host_integration=${DSH_SETUP_SKIP_HOST_INTEGRATION:-0}
|
|
|
|
for argument in "$@"; do
|
|
case "$argument" in
|
|
--test-mode) skip_host_integration=1 ;;
|
|
*) printf 'Unknown option: %s\n' "$argument" >&2; exit 2 ;;
|
|
esac
|
|
done
|
|
|
|
if [[ ! -f "$managed_manifest" && ! -f "$state_directory/partial.tsv" ]]; then
|
|
printf 'No DSH Arch Setup installation is recorded for this user. Nothing was removed.\n'
|
|
exit 0
|
|
fi
|
|
|
|
if [[ "$skip_host_integration" != 1 ]]; then
|
|
systemctl --user disable --now dsh-web.service >/dev/null 2>&1 || true
|
|
fi
|
|
|
|
if [[ ! -f "$state_directory/editor-preexisting" ]]; then
|
|
rm -rf "$dsh_home/touched-git/editor/extensions"
|
|
fi
|
|
if [[ ! -f "$state_directory/runtime-preexisting" ]]; then
|
|
rm -rf "$repository_directory/plugins/dsh-touched-git/runtime"
|
|
fi
|
|
if [[ ! -f "$state_directory/plugin-dependencies-preexisting" ]]; then
|
|
rm -rf "$repository_directory/plugins/dsh-touched-git/node_modules"
|
|
fi
|
|
|
|
if [[ ! -f "$state_directory/profile-preexisting" ]]; then
|
|
rm -rf "$profile_directory/node_modules"
|
|
fi
|
|
|
|
partial_manifest="$state_directory/partial.tsv"
|
|
if [[ -f "$managed_manifest" || -f "$partial_manifest" ]]; then
|
|
{ [[ ! -f "$managed_manifest" ]] || cat "$managed_manifest"; [[ ! -f "$partial_manifest" ]] || cat "$partial_manifest"; } | tac | awk -F '\t' '!seen[$2]++' | while IFS=$'\t' read -r kind destination expected; do
|
|
case "$kind" in
|
|
link)
|
|
if [[ -L "$destination" && "$(readlink -f "$destination")" == "$(readlink -f "$expected")" ]]; then
|
|
rm "$destination"
|
|
else
|
|
printf 'Preserved changed path: %s\n' "$destination"
|
|
fi
|
|
;;
|
|
file)
|
|
if [[ -f "$destination" && "$(sha256sum "$destination" | cut -d ' ' -f 1)" == "$expected" ]]; then
|
|
rm "$destination"
|
|
elif [[ -e "$destination" || -L "$destination" ]]; then
|
|
printf 'Preserved modified file: %s\n' "$destination"
|
|
fi
|
|
;;
|
|
esac
|
|
done
|
|
fi
|
|
|
|
if [[ -f "$backup_manifest" ]]; then
|
|
tac "$backup_manifest" | while IFS=$'\t' read -r destination backup; do
|
|
if [[ ! -e "$destination" && ! -L "$destination" && ( -e "$backup" || -L "$backup" ) ]]; then
|
|
mkdir -p "$(dirname "$destination")"
|
|
mv "$backup" "$destination"
|
|
fi
|
|
done
|
|
fi
|
|
|
|
if [[ ! -f "$state_directory/dsh-preexisting" ]] && command -v npm >/dev/null 2>&1; then
|
|
npm uninstall --global --prefix "$HOME/.local" @deepseek-ai/dsh >/dev/null 2>&1 || true
|
|
fi
|
|
|
|
if [[ "$skip_host_integration" != 1 ]]; then
|
|
systemctl --user daemon-reload
|
|
command -v update-desktop-database >/dev/null 2>&1 && update-desktop-database "$HOME/.local/share/applications"
|
|
command -v gtk-update-icon-cache >/dev/null 2>&1 && gtk-update-icon-cache --force "$HOME/.local/share/icons/hicolor" >/dev/null 2>&1 || true
|
|
fi
|
|
if [[ -d "$state_directory/backups" ]] && find "$state_directory/backups" \( -type f -o -type l \) -print -quit | grep -q .; then
|
|
printf 'Some backups remain in %s because their destinations were modified.\n' "$state_directory/backups"
|
|
else
|
|
rm -rf "$state_directory"
|
|
fi
|
|
|
|
printf 'DSH managed installation removed. Credentials, sessions, and user data were preserved.\n'
|