GitHub Viewer
#!/bin/sh
#================================================================#
# GitSSH Auto-Installer
# Automatically clones and installs GitSSH from GitHub
# POSIX Compliant - Fixed for curl | sh usage
#================================================================#
set -e # Exit on any error
# Configuration
REPO_URL="https://github.com/gitssh-cli/gitssh"
TEMP_DIR="/tmp/gitssh-install-$$"
INSTALL_DIR="$TEMP_DIR/gitssh"
#================================================================#
# UTILITY FUNCTIONS
#================================================================#
show_banner() {
cat &2
}
log_warning() {
printf "\033[1;33m[WARNING]\033[0m %s\n" "$1"
}
cleanup_on_error() {
if [ -d "$TEMP_DIR" ]; then
log_info "Cleaning up temporary files due to error..."
rm -rf "$TEMP_DIR"
fi
}
cleanup_final() {
if [ -d "$TEMP_DIR" ]; then
log_info "Cleaning up temporary files..."
rm -rf "$TEMP_DIR"
fi
}
check_dependencies() {
missing_deps=""
# Check for git
if ! command -v git >/dev/null 2>&1; then
missing_deps="$missing_deps git"
fi
# Check for chmod
if ! command -v chmod >/dev/null 2>&1; then
missing_deps="$missing_deps chmod"
fi
if [ -n "$missing_deps" ]; then
log_error "Missing required dependencies:$missing_deps"
log_error "Please install them and try again."
exit 1
fi
}
# POSIX Compliant sleep alternative using read with timeout where available
posix_sleep() {
duration="$1"
# Try different sleep methods
if command -v sleep >/dev/null 2>&1; then
sleep "$duration"
elif command -v ping >/dev/null 2>&1; then
# Use ping as timer (works on most systems)
ping -c 1 -W "${duration}000" 127.0.0.1 >/dev/null 2>&1 || true
else
# Fallback: busy wait (not ideal but POSIX Compliant)
start_time=$(date +%s)
while [ $(($(date +%s) - start_time)) -lt "$duration" ]; do
continue
done
fi
}
# Function to detect if we're running via pipe (curl | sh)
is_piped_execution() {
# Check if stdin is a pipe
[ ! -t 0 ]
}
# Function to read user input that works with both direct execution and piped execution
read_user_input() {
printf "\033[1;33mContinue anyway? (y/N): \033[0m"
if is_piped_execution; then
# When piped, read from terminal directly via /dev/tty
if [ -r /dev/tty ]; then
read response < /dev/tty
else
# If /dev/tty is not available, try other methods
if command -v tty >/dev/null 2>&1; then
tty_device=$(tty)
if [ "$tty_device" != "not a tty" ] && [ -r "$tty_device" ]; then
read response < "$tty_device"
else
# Fallback: assume 'y' for automated environments
log_warning "No terminal available, proceeding automatically..."
response="y"
fi
else
# Final fallback
log_warning "No terminal available, proceeding automatically..."
response="y"
fi
fi
else
# Normal execution - read from stdin
read response
fi
echo "$response"
}
# Function to wait for user confirmation that works with piped execution
wait_for_confirmation() {
if is_piped_execution; then
# When piped, read from terminal directly
printf "\033[1;33mPress Enter to continue with installation...\033[0m"
if [ -r /dev/tty ]; then
# Read a single line from the terminal
head -n 1 < /dev/tty > /dev/null
else
# If no terminal available, add a short delay and continue
log_warning "No terminal available for confirmation, continuing automatically..."
posix_sleep 2
fi
else
# Normal execution
printf "\033[1;33mPress Enter to continue with installation...\033[0m"
read dummy
fi
}
#================================================================#
# MAIN INSTALLATION PROCESS
#================================================================#
main() {
# Set up cleanup trap ONLY for errors and interrupts (not normal exit)
trap cleanup_on_error INT TERM
# Show banner
show_banner
# Check dependencies
log_info "Checking system dependencies..."
check_dependencies
show_progress 1 6 "Dependencies checked"
posix_sleep 1
# Create temporary directory
log_info "Creating temporary directory..."
mkdir -p "$TEMP_DIR"
show_progress 2 6 "Temporary directory created"
posix_sleep 1
# Clone repository
log_info "Cloning GitSSH repository..."
if git clone "$REPO_URL" "$INSTALL_DIR" >/dev/null 2>&1; then
show_progress 3 6 "Repository cloned successfully"
else
show_progress 3 6 "Repository clone failed"
log_error "Failed to clone repository from $REPO_URL"
log_error "Please check your internet connection and try again."
cleanup_on_error
exit 1
fi
posix_sleep 1
# Change to install directory
log_info "Entering installation directory..."
cd "$INSTALL_DIR"
show_progress 4 6 "Changed to install directory"
posix_sleep 1
# Make install script executable
log_info "Making install script executable..."
if [ -f "install" ]; then
chmod +x install
show_progress 5 6 "Install script made executable"
else
show_progress 5 6 "Install script not found"
log_error "Install script not found in repository"
log_error "Expected file: $INSTALL_DIR/install"
cleanup_on_error
exit 1
fi
posix_sleep 1
# Complete preparation
show_progress 6 6 "Installation preparation complete"
printf "\n"
# Run installer
log_success "Repository downloaded and prepared successfully!"
printf "\n"
log_info "Starting GitSSH installation..."
# Use the new confirmation function that handles piped execution
wait_for_confirmation
# Clear the trap before running installer (so installer can manage its own cleanup)
trap - INT TERM
# Execute the install script with proper stdin handling
if is_piped_execution; then
# When script was piped, we need to ensure the install script can also access terminal
if [ -r /dev/tty ]; then
# Redirect the install script's stdin to the terminal
./install < /dev/tty
else
# If no terminal, run without interactive input
log_warning "Running installation in non-interactive mode..."
./install
fi
else
# Normal execution
./install
fi
# Always cleanup after install script finishes, regardless of outcome
cleanup_final
}
#================================================================#
# ENTRY POINT
#================================================================#
# Check if running as root (optional warning)
if [ "$(id -u)" -eq 0 ]; then
log_warning "Running as root. GitSSH is typically installed for individual users."
# Use the new input function that handles piped execution
response=$(read_user_input)
case "$response" in
[yY]|[yY][eE][sS])
log_info "Proceeding with root installation..."
;;
*)
log_info "Installation cancelled."
exit 0
;;
esac
fi
# Run main installation
main "$@"