11#! /bin/bash
22
3- set -e
3+ set -eu
44
55# =============================================================================
66# Q CLI Installation Script
@@ -32,7 +32,7 @@ log() {
3232}
3333
3434success () {
35- echo " ✅ $1 " >&2
35+ echo " 🎉 $1 " >&2
3636}
3737
3838error () {
@@ -107,7 +107,7 @@ check_dependencies() {
107107# Download function that works with both curl and wget
108108download_file () {
109109 local url=" $1 "
110- local output=" $2 "
110+ local output=" ${2 :- } "
111111
112112 if command -v curl > /dev/null 2>&1 ; then
113113 if [[ -n " $output " ]]; then
@@ -164,8 +164,29 @@ detect_platform() {
164164 arm64|aarch64) arch=" aarch64" ;;
165165 * ) error " Unsupported architecture: $( uname -m) " ;;
166166 esac
167+ }
168+
169+ # Minimum required glibc version
170+ GLIBC_MIN_MAJOR=2
171+ GLIBC_MIN_MINOR=34
172+
173+ # Check if a glibc version meets the minimum requirement
174+ is_glibc_version_sufficient () {
175+ local version=" $1 "
176+ local major minor
177+
178+ IFS=' .' read -r major minor << EOF
179+ $version
180+ EOF
181+ if [[ -z " $minor " ]]; then
182+ minor=0
183+ fi
167184
168- log " Detected platform: $os -$arch "
185+ if (( major > GLIBC_MIN_MAJOR || (major == GLIBC_MIN_MAJOR && minor >= GLIBC_MIN_MINOR) )) ; then
186+ return 0
187+ else
188+ return 1
189+ fi
169190}
170191
171192# Check glibc version for Linux
@@ -175,94 +196,103 @@ check_glibc() {
175196 fi
176197
177198 local glibc_version
199+
200+ # Method 1: Try common libc.so.6 locations
201+ for LIBC_PATH in /lib64/libc.so.6 /lib/libc.so.6 /usr/lib/x86_64-linux-gnu/libc.so.6 \
202+ /lib/aarch64-linux-gnu/libc.so.6; do
203+ if [[ -f " $LIBC_PATH " ]]; then
204+ glibc_version=$( " $LIBC_PATH " | sed -n ' s/^GNU C Library (.*) stable release version \([0-9]*\)\.\([0-9]*\).*$/\1.\2/p' )
205+ if [[ -n " $glibc_version " ]]; then
206+ if is_glibc_version_sufficient " $glibc_version " ; then
207+ return 0
208+ else
209+ use_musl=true
210+ return 0
211+ fi
212+ fi
213+ fi
214+ done
215+
216+ # Method 2: Try ldd --version as a more reliable alternative
178217 if command -v ldd > /dev/null 2>&1 ; then
179- glibc_version=$( ldd --version 2> /dev/null | head -1 | grep -o ' [0-9]\+\.[0-9]\+' | head -1)
180- log " Detected glibc version: $glibc_version "
181-
182- # Check if we need musl version (glibc < 2.34)
218+ glibc_version=$( ldd --version 2> /dev/null | head -n 1 | grep -o ' [0-9]\+\.[0-9]\+' | head -n 1)
183219 if [[ -n " $glibc_version " ]]; then
184- local major minor
185- IFS= ' . ' read -r major minor <<< " $glibc_version "
186- if (( major < 2 || (major == 2 && minor < 34 ) )) ; then
220+ if is_glibc_version_sufficient " $glibc_version " ; then
221+ return 0
222+ else
187223 use_musl=true
188- log " Using musl version for older glibc "
224+ return 0
189225 fi
190226 fi
191- else
192- # Check for musl directly
193- if [[ -f /lib/libc.musl-x86_64.so.1 ]] || [[ -f /lib/libc.musl-aarch64.so.1 ]] || \
194- ldd /bin/ls 2>&1 | grep -q musl; then
195- use_musl=true
196- log " Detected musl system"
227+ fi
228+
229+ # Method 3: Try getconf as a fallback
230+ if command -v getconf > /dev/null 2>&1 ; then
231+ glibc_version=$( getconf GNU_LIBC_VERSION 2> /dev/null | awk ' {print $2}' )
232+ if [[ -n " $glibc_version " ]]; then
233+ if is_glibc_version_sufficient " $glibc_version " ; then
234+ return 0
235+ else
236+ use_musl=true
237+ return 0
238+ fi
197239 fi
198240 fi
241+
242+ # Check for musl directly
243+ if [[ -f /lib/libc.musl-x86_64.so.1 ]] || [[ -f /lib/libc.musl-aarch64.so.1 ]] || \
244+ ldd /bin/ls 2>&1 | grep -q musl; then
245+ use_musl=true
246+ return 0
247+ fi
248+
249+ use_musl=true
250+ return 0
199251}
200252
201253# =============================================================================
202254# Download and Installation Functions
203255# =============================================================================
204256
205- # Get download URL and filename based on platform
206- get_download_info () {
207- if [[ " $os " == " darwin" ]]; then
208- filename=" Amazon Q.dmg"
209- download_url=" ${BASE_URL} /latest/Amazon%20Q.dmg"
210- else
211- # Linux
212- if [[ " $use_musl " == " true" ]]; then
213- filename=" q-${arch} -linux-musl.zip"
214- else
215- filename=" q-${arch} -linux.zip"
216- fi
217- download_url=" ${BASE_URL} /latest/$filename "
218- fi
219-
220- log " Download URL: $download_url "
221- log " Filename: $filename "
222- }
223-
224257# Download and verify file
225258download_and_verify () {
259+ local download_url=" $1 "
260+ local filename=" $2 "
261+
226262 mkdir -p " $DOWNLOAD_DIR "
227-
263+
228264 local file_path=" $DOWNLOAD_DIR /$filename "
229265 downloaded_files+=(" $file_path " )
230-
231- log " Downloading $CLI_NAME to $file_path ..."
266+
267+ log " Downloading $CLI_NAME ..."
232268 download_file " $download_url " " $file_path "
233-
234- log " Downloading index for verification ..."
269+
270+ log " Verifying download ..."
235271 local index_json
236272 index_json=$( download_file " $INDEX_URL " )
237-
238- log " Verifying checksum..."
273+
239274 local expected_checksum
240275 expected_checksum=$( get_checksum " $index_json " " $filename " )
241-
276+
242277 if [[ -z " $expected_checksum " ]] || [[ ! " $expected_checksum " =~ ^[a-f0-9]{64}$ ]]; then
243278 error " Could not find valid checksum for $filename "
244279 fi
245-
280+
246281 local actual_checksum
247282 if [[ " $os " == " darwin" ]]; then
248283 actual_checksum=$( shasum -a 256 " $file_path " | cut -d' ' -f1)
249284 else
250285 actual_checksum=$( sha256sum " $file_path " | cut -d' ' -f1)
251286 fi
252-
287+
253288 if [[ " $actual_checksum " != " $expected_checksum " ]]; then
254289 rm -f " $file_path "
255290 error " Checksum verification failed. Expected: $expected_checksum , Got: $actual_checksum "
256291 fi
257-
258- success " Checksum verified successfully"
259-
260- echo " $file_path "
261292}
262293
263294# Install on macOS
264295install_macos () {
265- log " Mounting DMG..."
266296 local dmg_path=" $1 "
267297 if [[ ! -f " $dmg_path " ]]; then
268298 error " DMG file not found: $dmg_path "
@@ -276,7 +306,6 @@ install_macos() {
276306
277307 # Find the .app bundle
278308 local app_bundle
279- echo " Mount Point: $mount_path "
280309 app_bundle=$( find " $mount_path " -name " *.app" -maxdepth 1 -type d | head -1)
281310
282311 if [[ -z " $app_bundle " ]]; then
@@ -287,8 +316,6 @@ install_macos() {
287316 local app_name
288317 app_name=$( basename " $app_bundle " )
289318
290- log " Installing $app_name to $MACOS_APP_DIR ..."
291-
292319 # Check if app already exists and warn user
293320 if [[ -d " $MACOS_APP_DIR /$app_name " ]]; then
294321 warning " Existing $app_name found in $MACOS_APP_DIR "
@@ -298,18 +325,14 @@ install_macos() {
298325 hdiutil detach " $mount_path " -quiet
299326 error " Installation cancelled by user"
300327 fi
301- log " Removing existing $app_name ..."
328+ log " Replacing existing $app_name ..."
302329 rm -rf " $MACOS_APP_DIR /$app_name "
303330 fi
304331
305332 cp -R " $app_bundle " " $MACOS_APP_DIR /"
306-
307- success " $CLI_NAME installed successfully to $MACOS_APP_DIR "
308333
309- log " Unmounting DMG..."
310334 hdiutil detach " $mount_path " -quiet
311335
312- log " Starting $app_name ..."
313336 open " $MACOS_APP_DIR /$app_name "
314337}
315338
@@ -354,30 +377,31 @@ install_linux() {
354377
355378# Cleanup function - only removes files/dirs we created
356379cleanup () {
357- log " Cleaning up temporary files..."
358-
359380 # Remove downloaded files
360- for file in " ${downloaded_files[@]} " ; do
361- if [[ -f " $file " ]]; then
362- rm -f " $file "
363- fi
364- done
381+ if [[ ${# downloaded_files[@]} -gt 0 ]]; then
382+ for file in " ${downloaded_files[@]} " ; do
383+ if [[ -f " $file " ]]; then
384+ rm -f " $file "
385+ fi
386+ done
387+ fi
365388
366389 # Remove temporary directories we created
367- for dir in " ${temp_dirs[@]} " ; do
368- if [[ -d " $dir " ]]; then
369- rm -rf " $dir "
370- fi
371- done
390+ if [[ ${# temp_dirs[@]} -gt 0 ]]; then
391+ for dir in " ${temp_dirs[@]} " ; do
392+ if [[ -d " $dir " ]]; then
393+ rm -rf " $dir "
394+ fi
395+ done
396+ fi
372397}
373398
374399# =============================================================================
375400# Main Installation Process
376401# =============================================================================
377402
378403main () {
379- echo " 🚀 Installing $CLI_NAME ..."
380- echo
404+ log " Installing $CLI_NAME ..."
381405
382406 # Parse command line arguments
383407 parse_args " $@ "
@@ -391,11 +415,23 @@ main() {
391415 check_glibc
392416
393417 # Get download information
394- get_download_info
418+ local download_url filename
419+ if [[ " $os " == " darwin" ]]; then
420+ filename=" Amazon Q.dmg"
421+ download_url=" ${BASE_URL} /latest/Amazon%20Q.dmg"
422+ else
423+ # Linux
424+ if [[ " $use_musl " == " true" ]]; then
425+ filename=" q-${arch} -linux-musl.zip"
426+ else
427+ filename=" q-${arch} -linux.zip"
428+ fi
429+ download_url=" ${BASE_URL} /latest/$filename "
430+ fi
395431
396432 # Download and verify
397- download_and_verify
398- downloaded_file=" $DOWNLOAD_DIR /$filename "
433+ download_and_verify " $download_url " " $filename "
434+ local downloaded_file=" $DOWNLOAD_DIR /$filename "
399435
400436 # Install based on platform
401437 if [[ " $os " == " darwin" ]]; then
@@ -406,7 +442,7 @@ main() {
406442
407443
408444 echo
409- success " 🎉 $CLI_NAME installation completed successfully!"
445+ success " $CLI_NAME installation completed successfully!"
410446 echo
411447 echo " Next steps:"
412448 echo " 1. Run: $COMMAND_NAME --help to get started"
0 commit comments