|
|
#!/bin/bash |
|
|
set -e |
|
|
set -u |
|
|
set -o pipefail |
|
|
|
|
|
|
|
|
RED='\033[0;31m' |
|
|
GREEN='\033[0;32m' |
|
|
YELLOW='\033[1;33m' |
|
|
BLUE='\033[0;34m' |
|
|
NC='\033[0m' |
|
|
|
|
|
|
|
|
log_info() { |
|
|
echo -e "${GREEN}[INFO]${NC} $1" |
|
|
} |
|
|
|
|
|
log_error() { |
|
|
echo -e "${RED}[ERROR]${NC} $1" >&2 |
|
|
} |
|
|
|
|
|
log_warn() { |
|
|
echo -e "${YELLOW}[WARN]${NC} $1" |
|
|
} |
|
|
|
|
|
log_debug() { |
|
|
echo -e "${BLUE}[DEBUG]${NC} $1" |
|
|
} |
|
|
|
|
|
|
|
|
cleanup() { |
|
|
local exit_code=$? |
|
|
if [ $exit_code -ne 0 ]; then |
|
|
log_error "Installation failed with exit code $exit_code" |
|
|
fi |
|
|
exit $exit_code |
|
|
} |
|
|
|
|
|
trap cleanup EXIT |
|
|
|
|
|
|
|
|
detect_os() { |
|
|
log_info "Detecting operating system..." |
|
|
|
|
|
if [[ "$OSTYPE" == "linux-gnu"* ]]; then |
|
|
if [ -f /etc/os-release ]; then |
|
|
. /etc/os-release |
|
|
OS_NAME=$ID |
|
|
OS_VERSION=$VERSION_ID |
|
|
log_info "Detected: $NAME $VERSION_ID" |
|
|
elif [ -f /etc/lsb-release ]; then |
|
|
. /etc/lsb-release |
|
|
OS_NAME=$DISTRIB_ID |
|
|
OS_VERSION=$DISTRIB_RELEASE |
|
|
log_info "Detected: $DISTRIB_ID $DISTRIB_RELEASE" |
|
|
else |
|
|
OS_NAME="linux" |
|
|
OS_VERSION="unknown" |
|
|
log_warn "Could not determine specific Linux distribution" |
|
|
fi |
|
|
elif [[ "$OSTYPE" == "darwin"* ]]; then |
|
|
OS_NAME="macos" |
|
|
OS_VERSION=$(sw_vers -productVersion) |
|
|
log_info "Detected: macOS $OS_VERSION" |
|
|
elif [[ "$OSTYPE" == "freebsd"* ]]; then |
|
|
OS_NAME="freebsd" |
|
|
OS_VERSION=$(freebsd-version) |
|
|
log_info "Detected: FreeBSD $OS_VERSION" |
|
|
else |
|
|
log_error "Unsupported operating system: $OSTYPE" |
|
|
exit 1 |
|
|
fi |
|
|
} |
|
|
|
|
|
|
|
|
check_root_if_needed() { |
|
|
if [[ "$OS_NAME" == "ubuntu" ]] || [[ "$OS_NAME" == "debian" ]] || [[ "$OS_NAME" == "linuxmint" ]] || [[ "$OS_NAME" == "kali" ]]; then |
|
|
if [ "$EUID" -ne 0 ]; then |
|
|
log_error "This script requires root privileges for apt. Please run with sudo." |
|
|
exit 1 |
|
|
fi |
|
|
elif [[ "$OS_NAME" == "fedora" ]] || [[ "$OS_NAME" == "rhel" ]] || [[ "$OS_NAME" == "centos" ]] || [[ "$OS_NAME" == "rocky" ]] || [[ "$OS_NAME" == "almalinux" ]]; then |
|
|
if [ "$EUID" -ne 0 ]; then |
|
|
log_error "This script requires root privileges for dnf/yum. Please run with sudo." |
|
|
exit 1 |
|
|
fi |
|
|
elif [[ "$OS_NAME" == "arch" ]] || [[ "$OS_NAME" == "manjaro" ]]; then |
|
|
if [ "$EUID" -ne 0 ]; then |
|
|
log_error "This script requires root privileges for pacman. Please run with sudo." |
|
|
exit 1 |
|
|
fi |
|
|
fi |
|
|
} |
|
|
|
|
|
|
|
|
update_packages() { |
|
|
log_info "Updating package manager..." |
|
|
|
|
|
case "$OS_NAME" in |
|
|
ubuntu|debian|linuxmint|kali|pop) |
|
|
if ! apt update; then |
|
|
log_error "Failed to update apt package lists" |
|
|
exit 1 |
|
|
fi |
|
|
;; |
|
|
fedora|rhel|centos|rocky|almalinux) |
|
|
if command -v dnf &> /dev/null; then |
|
|
if ! dnf check-update; then |
|
|
|
|
|
if [ $? -ne 100 ]; then |
|
|
log_warn "dnf check-update returned non-standard exit code" |
|
|
fi |
|
|
fi |
|
|
else |
|
|
if ! yum check-update; then |
|
|
if [ $? -ne 100 ]; then |
|
|
log_warn "yum check-update returned non-standard exit code" |
|
|
fi |
|
|
fi |
|
|
fi |
|
|
;; |
|
|
arch|manjaro) |
|
|
if ! pacman -Syu; then |
|
|
log_error "Failed to update pacman database" |
|
|
exit 1 |
|
|
fi |
|
|
;; |
|
|
macos) |
|
|
if command -v brew &> /dev/null; then |
|
|
log_info "Updating Homebrew..." |
|
|
brew update |
|
|
else |
|
|
log_warn "Homebrew not installed. Skipping package manager update." |
|
|
fi |
|
|
;; |
|
|
*) |
|
|
log_warn "Unknown package manager for $OS_NAME. Skipping update." |
|
|
;; |
|
|
esac |
|
|
} |
|
|
|
|
|
|
|
|
install_git() { |
|
|
if ! command -v git &> /dev/null; then |
|
|
log_info "Installing git..." |
|
|
|
|
|
case "$OS_NAME" in |
|
|
ubuntu|debian|linuxmint|kali|pop) |
|
|
if ! apt install git -y; then |
|
|
log_error "Failed to install git" |
|
|
exit 1 |
|
|
fi |
|
|
;; |
|
|
fedora|rhel|centos|rocky|almalinux) |
|
|
if command -v dnf &> /dev/null; then |
|
|
if ! dnf install git -y; then |
|
|
log_error "Failed to install git" |
|
|
exit 1 |
|
|
fi |
|
|
else |
|
|
if ! yum install git -y; then |
|
|
log_error "Failed to install git" |
|
|
exit 1 |
|
|
fi |
|
|
fi |
|
|
;; |
|
|
arch|manjaro) |
|
|
if ! pacman -S git --noconfirm; then |
|
|
log_error "Failed to install git" |
|
|
exit 1 |
|
|
fi |
|
|
;; |
|
|
macos) |
|
|
if command -v brew &> /dev/null; then |
|
|
if ! brew install git; then |
|
|
log_error "Failed to install git" |
|
|
exit 1 |
|
|
fi |
|
|
else |
|
|
log_error "Homebrew is required for macOS. Install from https://brew.sh/" |
|
|
exit 1 |
|
|
fi |
|
|
;; |
|
|
*) |
|
|
log_error "Don't know how to install git on $OS_NAME" |
|
|
exit 1 |
|
|
;; |
|
|
esac |
|
|
else |
|
|
log_info "Git is already installed ($(git --version))" |
|
|
fi |
|
|
} |
|
|
|
|
|
|
|
|
detect_os |
|
|
|
|
|
|
|
|
check_root_if_needed |
|
|
|
|
|
log_info "Starting installation process..." |
|
|
|
|
|
|
|
|
update_packages |
|
|
|
|
|
|
|
|
install_git |
|
|
|
|
|
|
|
|
if ! command -v uv &> /dev/null; then |
|
|
log_info "Installing uv package manager..." |
|
|
if ! curl -Ls https://astral.sh/uv/install.sh | sh; then |
|
|
log_error "Failed to install uv" |
|
|
exit 1 |
|
|
fi |
|
|
|
|
|
|
|
|
if [ -f "$HOME/.local/bin/env" ]; then |
|
|
source "$HOME/.local/bin/env" |
|
|
elif [ -f "$HOME/.cargo/env" ]; then |
|
|
source "$HOME/.cargo/env" |
|
|
fi |
|
|
|
|
|
|
|
|
if ! command -v uv &> /dev/null; then |
|
|
log_error "uv installation failed - command not found after install" |
|
|
exit 1 |
|
|
fi |
|
|
else |
|
|
log_info "uv is already installed" |
|
|
fi |
|
|
|
|
|
|
|
|
log_info "Checking project directory..." |
|
|
if [ -f "./web.py" ]; then |
|
|
log_info "Already in target directory" |
|
|
elif [ -f "./gcli2api/web.py" ]; then |
|
|
log_info "Changing to gcli2api directory" |
|
|
cd ./gcli2api || exit 1 |
|
|
else |
|
|
log_info "Cloning repository..." |
|
|
if [ -d "./gcli2api" ]; then |
|
|
log_warn "gcli2api directory exists but web.py not found. Removing and re-cloning..." |
|
|
rm -rf ./gcli2api |
|
|
fi |
|
|
|
|
|
if ! git clone https://github.com/su-kaka/gcli2api.git; then |
|
|
log_error "Failed to clone repository" |
|
|
exit 1 |
|
|
fi |
|
|
|
|
|
cd ./gcli2api || exit 1 |
|
|
fi |
|
|
|
|
|
|
|
|
if [ -d ".git" ]; then |
|
|
log_info "Updating repository..." |
|
|
if ! git pull; then |
|
|
log_warn "Git pull failed, continuing anyway..." |
|
|
fi |
|
|
else |
|
|
log_warn "Not a git repository, skipping update" |
|
|
fi |
|
|
|
|
|
|
|
|
log_info "Creating relocatable virtual environment..." |
|
|
export UV_VENV_CLEAR=1 |
|
|
if ! uv venv --relocatable; then |
|
|
log_error "Failed to create virtual environment" |
|
|
exit 1 |
|
|
fi |
|
|
|
|
|
|
|
|
log_info "Syncing dependencies with uv..." |
|
|
if ! uv sync; then |
|
|
log_error "Failed to sync dependencies" |
|
|
exit 1 |
|
|
fi |
|
|
|
|
|
|
|
|
log_info "Activating virtual environment..." |
|
|
if [ -f ".venv/bin/activate" ]; then |
|
|
source .venv/bin/activate |
|
|
else |
|
|
log_error "Virtual environment not found at .venv/bin/activate" |
|
|
exit 1 |
|
|
fi |
|
|
|
|
|
|
|
|
if ! command -v python3 &> /dev/null; then |
|
|
log_error "python3 not found in virtual environment" |
|
|
exit 1 |
|
|
fi |
|
|
|
|
|
|
|
|
if [ ! -f "web.py" ]; then |
|
|
log_error "web.py not found in current directory" |
|
|
exit 1 |
|
|
fi |
|
|
|
|
|
|
|
|
log_info "Starting application..." |
|
|
python3 web.py |