1+ #! /bin/sh
2+
3+ # ================================================================#
4+ # GitSSH Auto-Installer
5+ # Automatically clones and installs GitSSH from GitHub
6+ # POSIX Compliant - Fixed for curl | sh usage
7+ # ================================================================#
8+
9+ set -e # Exit on any error
10+
11+ # Configuration
12+ REPO_URL=" https://github.com/gitssh-cli/gitssh"
13+ TEMP_DIR=" /tmp/gitssh-install-$$ "
14+ INSTALL_DIR=" $TEMP_DIR /gitssh"
15+
16+ # ================================================================#
17+ # UTILITY FUNCTIONS
18+ # ================================================================#
19+
20+ show_banner () {
21+ cat << 'EOF '
22+ ╔═══════════════════════════════════════════════════════════════╗
23+ ║ ║
24+ ║ ██████╗ ███████╗███████╗██╗ ██╗ ║
25+ ║ ██╔════╝ ██╗ ██╗ ██╔════╝██╔════╝██║ ██║ ║
26+ ║ ██║ ███╗══╝████║███████╗███████╗███████║ ║
27+ ║ ██║ ██║██║ ██║ ╚════██║╚════██║██╔══██║ ║
28+ ║ ██████╔╝██║ ██║ ███████║███████║██║ ██║ ║
29+ ║ ╚═════╝ ╚═╝ ╚═╝ ╚══════╝╚══════╝╚═╝ ╚═╝v0.1.0-Oz ║
30+ ║ <-POSIX Compliant-> ║
31+ ║ ║
32+ ╚═══════════════════════════════════════════════════════════════╝
33+ Manage Multiple SSH Git and GitHub Account Sessions With Ease!
34+
35+ EOF
36+ }
37+
38+ show_progress () {
39+ current=" $1 "
40+ total=" $2 "
41+ message=" $3 "
42+ width=50
43+
44+ # POSIX arithmetic
45+ percentage=$(( current * 100 / total))
46+ filled=$(( current * width / total))
47+ empty=$(( width - filled))
48+
49+ printf " \r\033[0;34m[\033[0m"
50+
51+ # Print filled portion
52+ i=0
53+ while [ $i -lt $filled ]; do
54+ printf " █"
55+ i=$(( i + 1 ))
56+ done
57+
58+ # Print empty portion
59+ i=0
60+ while [ $i -lt $empty ]; do
61+ printf " "
62+ i=$(( i + 1 ))
63+ done
64+
65+ printf " \033[0;34m] %d%% - %s\033[0m" " $percentage " " $message "
66+
67+ if [ " $current " -eq " $total " ]; then
68+ printf " \n"
69+ fi
70+ }
71+
72+ log_info () {
73+ printf " \033[0;34m[INFO]\033[0m %s\n" " $1 "
74+ }
75+
76+ log_success () {
77+ printf " \033[0;32m[SUCCESS]\033[0m %s\n" " $1 "
78+ }
79+
80+ log_error () {
81+ printf " \033[0;31m[ERROR]\033[0m %s\n" " $1 " >&2
82+ }
83+
84+ log_warning () {
85+ printf " \033[1;33m[WARNING]\033[0m %s\n" " $1 "
86+ }
87+
88+ cleanup_on_error () {
89+ if [ -d " $TEMP_DIR " ]; then
90+ log_info " Cleaning up temporary files due to error..."
91+ rm -rf " $TEMP_DIR "
92+ fi
93+ }
94+
95+ cleanup_final () {
96+ if [ -d " $TEMP_DIR " ]; then
97+ log_info " Cleaning up temporary files..."
98+ rm -rf " $TEMP_DIR "
99+ fi
100+ }
101+
102+ check_dependencies () {
103+ missing_deps=" "
104+
105+ # Check for git
106+ if ! command -v git > /dev/null 2>&1 ; then
107+ missing_deps=" $missing_deps git"
108+ fi
109+
110+ # Check for chmod
111+ if ! command -v chmod > /dev/null 2>&1 ; then
112+ missing_deps=" $missing_deps chmod"
113+ fi
114+
115+ if [ -n " $missing_deps " ]; then
116+ log_error " Missing required dependencies:$missing_deps "
117+ log_error " Please install them and try again."
118+ exit 1
119+ fi
120+ }
121+
122+ # POSIX Compliant sleep alternative using read with timeout where available
123+ posix_sleep () {
124+ duration=" $1 "
125+ # Try different sleep methods
126+ if command -v sleep > /dev/null 2>&1 ; then
127+ sleep " $duration "
128+ elif command -v ping > /dev/null 2>&1 ; then
129+ # Use ping as timer (works on most systems)
130+ ping -c 1 -W " ${duration} 000" 127.0.0.1 > /dev/null 2>&1 || true
131+ else
132+ # Fallback: busy wait (not ideal but POSIX Compliant)
133+ start_time=$( date +%s)
134+ while [ $(( $(date +% s) - start_time)) -lt " $duration " ]; do
135+ continue
136+ done
137+ fi
138+ }
139+
140+ # Function to detect if we're running via pipe (curl | sh)
141+ is_piped_execution () {
142+ # Check if stdin is a pipe
143+ [ ! -t 0 ]
144+ }
145+
146+ # Function to read user input that works with both direct execution and piped execution
147+ read_user_input () {
148+ printf " \033[1;33mContinue anyway? (y/N): \033[0m"
149+
150+ if is_piped_execution; then
151+ # When piped, read from terminal directly via /dev/tty
152+ if [ -r /dev/tty ]; then
153+ read response < /dev/tty
154+ else
155+ # If /dev/tty is not available, try other methods
156+ if command -v tty > /dev/null 2>&1 ; then
157+ tty_device=$( tty)
158+ if [ " $tty_device " != " not a tty" ] && [ -r " $tty_device " ]; then
159+ read response < " $tty_device "
160+ else
161+ # Fallback: assume 'y' for automated environments
162+ log_warning " No terminal available, proceeding automatically..."
163+ response=" y"
164+ fi
165+ else
166+ # Final fallback
167+ log_warning " No terminal available, proceeding automatically..."
168+ response=" y"
169+ fi
170+ fi
171+ else
172+ # Normal execution - read from stdin
173+ read response
174+ fi
175+
176+ echo " $response "
177+ }
178+
179+ # Function to wait for user confirmation that works with piped execution
180+ wait_for_confirmation () {
181+ if is_piped_execution; then
182+ # When piped, read from terminal directly
183+ printf " \033[1;33mPress Enter to continue with installation...\033[0m"
184+ if [ -r /dev/tty ]; then
185+ # Read a single line from the terminal
186+ head -n 1 < /dev/tty > /dev/null
187+ else
188+ # If no terminal available, add a short delay and continue
189+ log_warning " No terminal available for confirmation, continuing automatically..."
190+ posix_sleep 2
191+ fi
192+ else
193+ # Normal execution
194+ printf " \033[1;33mPress Enter to continue with installation...\033[0m"
195+ read dummy
196+ fi
197+ }
198+
199+ # ================================================================#
200+ # MAIN INSTALLATION PROCESS
201+ # ================================================================#
202+
203+ main () {
204+ # Set up cleanup trap ONLY for errors and interrupts (not normal exit)
205+ trap cleanup_on_error INT TERM
206+
207+ # Show banner
208+ show_banner
209+
210+ # Check dependencies
211+ log_info " Checking system dependencies..."
212+ check_dependencies
213+ show_progress 1 6 " Dependencies checked"
214+ posix_sleep 1
215+
216+ # Create temporary directory
217+ log_info " Creating temporary directory..."
218+ mkdir -p " $TEMP_DIR "
219+ show_progress 2 6 " Temporary directory created"
220+ posix_sleep 1
221+
222+ # Clone repository
223+ log_info " Cloning GitSSH repository..."
224+ if git clone " $REPO_URL " " $INSTALL_DIR " > /dev/null 2>&1 ; then
225+ show_progress 3 6 " Repository cloned successfully"
226+ else
227+ show_progress 3 6 " Repository clone failed"
228+ log_error " Failed to clone repository from $REPO_URL "
229+ log_error " Please check your internet connection and try again."
230+ cleanup_on_error
231+ exit 1
232+ fi
233+ posix_sleep 1
234+
235+ # Change to install directory
236+ log_info " Entering installation directory..."
237+ cd " $INSTALL_DIR "
238+ show_progress 4 6 " Changed to install directory"
239+ posix_sleep 1
240+
241+ # Make install script executable
242+ log_info " Making install script executable..."
243+ if [ -f " install" ]; then
244+ chmod +x install
245+ show_progress 5 6 " Install script made executable"
246+ else
247+ show_progress 5 6 " Install script not found"
248+ log_error " Install script not found in repository"
249+ log_error " Expected file: $INSTALL_DIR /install"
250+ cleanup_on_error
251+ exit 1
252+ fi
253+ posix_sleep 1
254+
255+ # Complete preparation
256+ show_progress 6 6 " Installation preparation complete"
257+ printf " \n"
258+
259+ # Run installer
260+ log_success " Repository downloaded and prepared successfully!"
261+ printf " \n"
262+ log_info " Starting GitSSH installation..."
263+
264+ # Use the new confirmation function that handles piped execution
265+ wait_for_confirmation
266+
267+ # Clear the trap before running installer (so installer can manage its own cleanup)
268+ trap - INT TERM
269+
270+ # Execute the install script with proper stdin handling
271+ if is_piped_execution; then
272+ # When script was piped, we need to ensure the install script can also access terminal
273+ if [ -r /dev/tty ]; then
274+ # Redirect the install script's stdin to the terminal
275+ ./install < /dev/tty
276+ else
277+ # If no terminal, run without interactive input
278+ log_warning " Running installation in non-interactive mode..."
279+ ./install
280+ fi
281+ else
282+ # Normal execution
283+ ./install
284+ fi
285+
286+ # Always cleanup after install script finishes, regardless of outcome
287+ cleanup_final
288+ }
289+
290+ # ================================================================#
291+ # ENTRY POINT
292+ # ================================================================#
293+
294+ # Check if running as root (optional warning)
295+ if [ " $( id -u) " -eq 0 ]; then
296+ log_warning " Running as root. GitSSH is typically installed for individual users."
297+
298+ # Use the new input function that handles piped execution
299+ response=$( read_user_input)
300+
301+ case " $response " in
302+ [yY]|[yY][eE][sS])
303+ log_info " Proceeding with root installation..."
304+ ;;
305+ * )
306+ log_info " Installation cancelled."
307+ exit 0
308+ ;;
309+ esac
310+ fi
311+
312+ # Run main installation
313+ main " $@ "
0 commit comments