138 lines
3.9 KiB
Bash
Executable File
138 lines
3.9 KiB
Bash
Executable File
#!/bin/bash
|
|
#
|
|
# Purpose : Install and manage MiniServer sibling projects
|
|
#
|
|
# A sibling is a git repository cloned into ~/.local/share/siblings/<name>.
|
|
# If it has an install.sh, that runs once when the sibling is added.
|
|
# Every `update` pulls each sibling and runs its update.sh, if it has one
|
|
# (see updates.d/71-siblings.sh). Ports listed in a sibling's firewall.conf
|
|
# are opened when it's added and closed when it's removed.
|
|
|
|
SIBLINGS="$HOME/.local/share/siblings"
|
|
|
|
# Provides setup_firewall
|
|
source "$HOME/.local/share/MiniServer/utils.sh"
|
|
|
|
usage() {
|
|
cat << EOF
|
|
Usage: sibling [command]
|
|
|
|
add [url] Install a sibling project from a git repository (default)
|
|
list Show installed sibling projects
|
|
remove <name> Uninstall a sibling project
|
|
EOF
|
|
}
|
|
|
|
# Derive a directory name from a git URL, e.g.
|
|
# https://host/user/my-project.git -> my-project
|
|
sibling_name() {
|
|
local name="${1%/}"
|
|
name="${name##*/}"
|
|
name="${name##*:}"
|
|
echo "${name%.git}"
|
|
}
|
|
|
|
add_sibling() {
|
|
local url="$1" name dir
|
|
|
|
if [ -z "$url" ]; then
|
|
read -rp "Git repository URL for the sibling project: " url
|
|
fi
|
|
if [ -z "$url" ]; then
|
|
echo "No URL given."
|
|
return 1
|
|
fi
|
|
|
|
name="$(sibling_name "$url")"
|
|
if [[ -z "$name" || "$name" == .* ]]; then
|
|
echo "Could not work out a project name from: $url"
|
|
return 1
|
|
fi
|
|
dir="$SIBLINGS/$name"
|
|
|
|
mkdir -p "$SIBLINGS"
|
|
if [ -d "$dir/.git" ]; then
|
|
local existing
|
|
existing="$(git -C "$dir" remote get-url origin 2>/dev/null)"
|
|
if [ "$existing" != "$url" ]; then
|
|
echo "A different sibling named '$name' is already installed from: $existing"
|
|
return 1
|
|
fi
|
|
echo "$name is already installed; pulling the latest version..."
|
|
git -C "$dir" pull --ff-only || return 1
|
|
else
|
|
echo "Cloning $name..."
|
|
git clone "$url" "$dir" || return 1
|
|
fi
|
|
|
|
if [ -f "$dir/install.sh" ]; then
|
|
echo "Running $name's install.sh..."
|
|
if ! (cd "$dir" && bash install.sh); then
|
|
echo "$name's install.sh failed. Fix the problem and run 'sibling add $url' again."
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
# Open the ports listed in the sibling's firewall.conf
|
|
if [ -f "$dir/firewall.conf" ]; then
|
|
echo "Applying $name's firewall.conf..."
|
|
if ! setup_firewall; then
|
|
echo "Some firewall rules could not be applied, see above. Fix the problem and run 'sibling add $url' again."
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
# Confirm the install
|
|
if [ -d "$dir/.git" ] && git -C "$dir" rev-parse --verify --quiet HEAD > /dev/null; then
|
|
echo "Installed $name at $dir ($(git -C "$dir" log -1 --format='%h %s'))."
|
|
echo "'update' will keep it up to date."
|
|
else
|
|
echo "$name does not look installed correctly at $dir."
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
list_siblings() {
|
|
local dir found=0
|
|
for dir in "$SIBLINGS"/*/; do
|
|
[ -d "$dir/.git" ] || continue
|
|
found=1
|
|
printf '%-24s %s (%s)\n' "$(basename "$dir")" \
|
|
"$(git -C "$dir" remote get-url origin 2>/dev/null)" \
|
|
"$(git -C "$dir" log -1 --format='%h, %cr' 2>/dev/null)"
|
|
done
|
|
[ $found -eq 1 ] || echo "No sibling projects installed."
|
|
}
|
|
|
|
remove_sibling() {
|
|
local name="$1"
|
|
if [[ -z "$name" || "$name" == */* || "$name" == .* ]]; then
|
|
usage
|
|
return 1
|
|
fi
|
|
if [ ! -d "$SIBLINGS/$name" ]; then
|
|
echo "No sibling named '$name' is installed."
|
|
return 1
|
|
fi
|
|
read -rp "Remove $SIBLINGS/$name? [y/N] " response
|
|
case "$response" in
|
|
[yY][eE][sS]|[yY])
|
|
rm -rf "${SIBLINGS:?}/$name"
|
|
# Close the ports only this sibling's firewall.conf asked for
|
|
setup_firewall || echo "Some firewall rules could not be updated, see above. 'update' will retry."
|
|
echo "Removed $name. Anything its install.sh set up outside that folder is still there."
|
|
;;
|
|
*)
|
|
echo "Nothing removed."
|
|
;;
|
|
esac
|
|
}
|
|
|
|
case "$1" in
|
|
""|add) add_sibling "$2" ;;
|
|
list|ls) list_siblings ;;
|
|
remove|rm) remove_sibling "$2" ;;
|
|
-h|--help|help) usage ;;
|
|
*) usage; exit 1 ;;
|
|
esac
|