Skip to content

Commit 910c9f4

Browse files
committed
feat: Enhance installation script with existing installation check and OS-specific default directories
1 parent efc8a57 commit 910c9f4

File tree

1 file changed

+212
-53
lines changed

1 file changed

+212
-53
lines changed

download-latest.sh

+212-53
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,16 @@ GITHUB_API="https://api.github.com/repos/$REPO_OWNER/$REPO_NAME/releases"
3030
# GitHub Release address
3131
GITHUB_REL="https://github.com/$REPO_OWNER/$REPO_NAME/releases/download"
3232

33-
# Default install directory (will be adjusted for Windows)
34-
DEFAULT_BIN_DIR="/usr/local/bin"
33+
# Default install directories will be set based on OS
34+
DEFAULT_BIN_DIR=""
3535

3636
# Default to empty (meaning get latest version)
3737
VERSION=""
3838

3939
# Is this Windows?
4040
IS_WINDOWS=0
41+
# Is this macOS?
42+
IS_MACOS=0
4143

4244
# FUNCTIONS
4345

@@ -68,6 +70,63 @@ print_warning() {
6870
printf " ${YELLOW}[WARNING]${DEFAULT} $1\n"
6971
}
7072

73+
# Check if ctx is already installed and get its location
74+
check_existing_installation() {
75+
print_header "Checking for existing installation"
76+
77+
# Get the binary name based on OS
78+
if [ "$IS_WINDOWS" -eq 1 ]; then
79+
binary_to_find="${PNAME}.exe"
80+
else
81+
binary_to_find="$PNAME"
82+
fi
83+
84+
# Try to find existing installation
85+
if command -v "$PNAME" >/dev/null 2>&1; then
86+
existing_path=$(command -v "$PNAME")
87+
existing_dir=$(dirname "$existing_path")
88+
print_success "Found existing installation at: $existing_path"
89+
90+
# Set default bin directory to the location of the existing installation
91+
DEFAULT_BIN_DIR="$existing_dir"
92+
93+
# Get current version if possible
94+
if "$existing_path" --version >/dev/null 2>&1; then
95+
current_version=$("$existing_path" --version | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' | head -1)
96+
if [ -n "$current_version" ]; then
97+
print_status "Current version: $current_version"
98+
fi
99+
fi
100+
101+
return 0
102+
else
103+
# Check common directories for the binary
104+
for check_dir in /usr/local/bin /usr/bin "$HOME/.local/bin" "$HOME/bin" "$HOME/AppData/Local/bin"; do
105+
if [ -f "$check_dir/$binary_to_find" ]; then
106+
existing_path="$check_dir/$binary_to_find"
107+
existing_dir="$check_dir"
108+
print_success "Found existing installation at: $existing_path"
109+
110+
# Set default bin directory to the location of the existing installation
111+
DEFAULT_BIN_DIR="$existing_dir"
112+
113+
# Get current version if possible
114+
if "$existing_path" --version >/dev/null 2>&1; then
115+
current_version=$("$existing_path" --version | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' | head -1)
116+
if [ -n "$current_version" ]; then
117+
print_status "Current version: $current_version"
118+
fi
119+
fi
120+
121+
return 0
122+
fi
123+
done
124+
125+
print_status "No existing installation found"
126+
return 1
127+
fi
128+
}
129+
71130
# Gets the version either from user input or latest from GitHub
72131
# Sets the $latest and $latestV variables.
73132
# Returns 0 in case of success, 1 otherwise.
@@ -107,6 +166,17 @@ get_latest() {
107166

108167
if [ -n "$latest" ]; then
109168
print_success "Latest version found: $latestV"
169+
170+
# Compare versions if we have a current version
171+
if [ -n "$current_version" ] && [ "$latest" = "$current_version" ]; then
172+
print_warning "You already have the latest version installed"
173+
if ! prompt_for_confirmation "Do you want to reinstall the same version?"; then
174+
print_status "Installation cancelled by user."
175+
exit 0
176+
fi
177+
elif [ -n "$current_version" ]; then
178+
print_status "Upgrading from version $current_version to $latestV"
179+
fi
110180
fi
111181

112182
return 0
@@ -131,16 +201,48 @@ get_os() {
131201
# ---
132202
'Darwin')
133203
os='darwin'
204+
IS_MACOS=1
134205
;;
135206

136207
# ---
137208
*)
138209
return 1
139210
;;
140211
esac
212+
213+
# Set default bin directory based on OS
214+
set_default_bin_dir
215+
141216
return 0
142217
}
143218

219+
# Sets the default bin directory based on detected OS
220+
set_default_bin_dir() {
221+
if [ "$IS_WINDOWS" -eq 1 ]; then
222+
# For Windows, we'll use AppData\Local\bin or HOME\bin
223+
if [ -d "$HOME/AppData/Local/bin" ]; then
224+
DEFAULT_BIN_DIR="$HOME/AppData/Local/bin"
225+
else
226+
DEFAULT_BIN_DIR="$HOME/bin"
227+
fi
228+
elif [ "$IS_MACOS" -eq 1 ]; then
229+
# For macOS, check if user has write access to /usr/local/bin
230+
if [ -w "/usr/local/bin" ]; then
231+
DEFAULT_BIN_DIR="/usr/local/bin"
232+
else
233+
# Otherwise use ~/.local/bin for non-sudo installation
234+
DEFAULT_BIN_DIR="$HOME/.local/bin"
235+
fi
236+
else
237+
# For Linux and other systems
238+
if [ -w "/usr/local/bin" ]; then
239+
DEFAULT_BIN_DIR="/usr/local/bin"
240+
else
241+
DEFAULT_BIN_DIR="$HOME/.local/bin"
242+
fi
243+
fi
244+
}
245+
144246
# Gets the architecture by setting the $arch variable.
145247
# Returns 0 in case of success, 1 otherwise.
146248
get_arch() {
@@ -193,12 +295,6 @@ detect_windows_dir() {
193295
}
194296

195297
ensure_bin_dir() {
196-
# Handle Windows-specific directories
197-
if [ "$IS_WINDOWS" -eq 1 ] && [ "$bin_dir" = "$DEFAULT_BIN_DIR" ]; then
198-
detect_windows_dir
199-
print_status "Windows detected. Setting installation directory to: $bin_dir"
200-
fi
201-
202298
# Create bin directory if it doesn't exist
203299
if [ ! -d "$bin_dir" ]; then
204300
print_status "Creating directory $bin_dir..."
@@ -223,6 +319,9 @@ ensure_bin_dir() {
223319
printf " ${GREEN}6. Click 'OK' on all dialogs${DEFAULT}\n\n"
224320
printf " Or in PowerShell, run:${DEFAULT}\n"
225321
printf " ${GREEN}\$env:Path += \";$bin_dir\"${DEFAULT}\n\n"
322+
elif [ "$IS_MACOS" -eq 1 ]; then
323+
printf "You might want to add the following line to your shell profile (~/.zshrc or ~/.bash_profile):\n"
324+
printf " ${GREEN}export PATH=\"\$PATH:$bin_dir\"${DEFAULT}\n\n"
226325
else
227326
printf "You might want to add the following line to your shell profile (.bashrc, .zshrc, etc.):\n"
228327
printf " ${GREEN}export PATH=\"\$PATH:$bin_dir\"${DEFAULT}\n\n"
@@ -231,39 +330,6 @@ ensure_bin_dir() {
231330
}
232331

233332
download_and_install() {
234-
# Get the latest version
235-
print_header "Checking for updates"
236-
237-
if ! get_latest; then
238-
fetch_release_failure_usage
239-
exit 1
240-
fi
241-
242-
if [ "$latest" = '' ]; then
243-
fetch_release_failure_usage
244-
exit 1
245-
fi
246-
247-
# Fill $os variable.
248-
if ! get_os; then
249-
not_available_failure_usage
250-
exit 1
251-
fi
252-
# Fill $arch variable.
253-
if ! get_arch; then
254-
not_available_failure_usage
255-
exit 1
256-
fi
257-
258-
# Add .exe extension for Windows
259-
binary_name="$PNAME"
260-
if [ "$IS_WINDOWS" -eq 1 ]; then
261-
binary_name="${PNAME}.exe"
262-
release_file="$PNAME-$latest-$os-$arch.exe"
263-
else
264-
release_file="$PNAME-$latest-$os-$arch"
265-
fi
266-
267333
# Download the binary file
268334
print_header "Downloading the latest version"
269335
print_status "Preparing download from: $GITHUB_REL/$latestV/$release_file"
@@ -286,7 +352,7 @@ download_and_install() {
286352
# Use curl with progress bar but suppress most headers
287353
if ! curl --fail -L "$GITHUB_REL/$latestV/$release_file" -o "$temp_file" \
288354
--progress-bar --write-out "%{http_code}" | grep -q "^2"; then
289-
printf "] ${RED}Failed!${DEFAULT}\n"
355+
echo "] ${RED}Failed!${DEFAULT}"
290356
print_error "Failed to download $GITHUB_REL/$latestV/$release_file"
291357
rm -f "$temp_file"
292358
exit 1
@@ -316,22 +382,61 @@ download_and_install() {
316382
print_success "Successfully replaced the binary file"
317383
print_success "Successfully installed $latestV to $bin_dir/$binary_name\n"
318384

319-
printf " You can now run it using:\n"
385+
echo " You can now run it using:"
320386
if [ "$IS_WINDOWS" -eq 1 ]; then
321-
printf " ${BOLD}$binary_name${DEFAULT}\n\n"
387+
echo " ${BOLD}$binary_name${DEFAULT}"
322388
else
323-
printf " ${BOLD}$PNAME${DEFAULT}\n\n"
389+
echo " ${BOLD}$PNAME${DEFAULT}"
390+
fi
391+
echo " 📚 Documentation: https://docs.ctxgithub.com"
392+
echo " 🚀 Happy AI coding!"
393+
}
394+
395+
# Prompt user for confirmation
396+
prompt_for_confirmation() {
397+
echo "${YELLOW}${DEFAULT} $1 [Y/n] "
398+
read -r response
399+
case "$response" in
400+
[nN])
401+
return 1
402+
;;
403+
*)
404+
return 0
405+
;;
406+
esac
407+
}
408+
409+
# Ask user for installation directory
410+
prompt_for_directory() {
411+
# If we found an existing installation, suggest that directory first
412+
if [ -n "$existing_dir" ]; then
413+
echo "${YELLOW}${DEFAULT} Install to the same location? [${GREEN}$existing_dir${DEFAULT}]: "
414+
read -r user_bin_dir
415+
if [ -z "$user_bin_dir" ]; then
416+
bin_dir="$existing_dir"
417+
else
418+
bin_dir="$user_bin_dir"
419+
fi
420+
else
421+
echo "${YELLOW}${DEFAULT} Enter installation directory [${GREEN}$DEFAULT_BIN_DIR${DEFAULT}]: "
422+
read -r user_bin_dir
423+
if [ -z "$user_bin_dir" ]; then
424+
bin_dir="$DEFAULT_BIN_DIR"
425+
else
426+
bin_dir="$user_bin_dir"
427+
fi
324428
fi
325-
printf " 📚 Documentation: https://docs.ctxgithub.com\n"
326-
printf " 🚀 Happy AI coding!\n\n"
327429
}
328430

329431
# Main script execution
330432
printf "${BOLD}Context Generator Installer${DEFAULT}\n"
331433
printf "===========================\n\n"
332434

435+
# First detect OS to set appropriate default bin directory
436+
get_os
437+
333438
# Parse arguments
334-
bin_dir="$DEFAULT_BIN_DIR"
439+
bin_dir=""
335440
while [ $# -gt 0 ]; do
336441
case "$1" in
337442
-v=*|--version=*)
@@ -361,17 +466,71 @@ if [ "$IS_WINDOWS" -eq 1 ] && echo "$SHELL" | grep -q "powershell"; then
361466
print_status "Continuing with this script, but some features might not work as expected."
362467
fi
363468

469+
# Check for existing installation before asking for directory
470+
check_existing_installation
471+
472+
# If no bin_dir was specified as argument, ask user
473+
if [ -z "$bin_dir" ]; then
474+
prompt_for_directory
475+
fi
476+
364477
print_status "Installation directory: $bin_dir"
365478
if [ -n "$VERSION" ]; then
366479
print_status "Installing version: $VERSION"
367480
else
368-
print_status "No version specified. Will install the latest version.\n"
369-
printf " ${MUTED}You can specify a different directory by running:${DEFAULT}\n"
370-
printf " ${MUTED}curl -sSL https://raw.githubusercontent.com/context-hub/generator/main/download-latest.sh | sh -s /path/to/bin${DEFAULT}\n"
371-
printf " ${MUTED}Specify a specific version with:${DEFAULT}\n"
372-
printf " ${MUTED}curl -sSL https://raw.githubusercontent.com/context-hub/generator/main/download-latest.sh | sh -s -- --version=v1.2.3 /path/to/bin${DEFAULT}\n\n"
481+
print_status "No version specified. Will install the latest version."
482+
fi
483+
484+
# Get the latest version information before showing summary
485+
if ! get_latest; then
486+
fetch_release_failure_usage
487+
exit 1
488+
fi
489+
490+
if [ "$latest" = '' ]; then
491+
fetch_release_failure_usage
492+
exit 1
493+
fi
494+
495+
# Fill $os and $arch variables
496+
if ! get_os; then
497+
not_available_failure_usage
498+
exit 1
499+
fi
500+
501+
if ! get_arch; then
502+
not_available_failure_usage
503+
exit 1
504+
fi
505+
506+
# Determine release file name
507+
if [ "$IS_WINDOWS" -eq 1 ]; then
508+
binary_name="${PNAME}.exe"
509+
release_file="$PNAME-$latest-$os-$arch.exe"
510+
else
511+
binary_name="$PNAME"
512+
release_file="$PNAME-$latest-$os-$arch"
373513
fi
374514

515+
# Ask for confirmation before proceeding
516+
printf "\n"
517+
echo "${BLUE}Summary:${DEFAULT}"
518+
printf "\n"
519+
echo " - Install location: ${bin_dir}/${binary_name}"
520+
echo " - Version: ${latestV}"
521+
if [ -n "$current_version" ]; then
522+
echo " - Current version: ${current_version}"
523+
fi
524+
echo " - Download file: ${release_file}"
525+
echo ""
526+
527+
if ! prompt_for_confirmation "Do you want to proceed with the installation?"; then
528+
print_status "Installation cancelled by user."
529+
exit 0
530+
fi
531+
532+
printf "\n"
533+
375534
# Ensure bin directory exists and is in PATH
376535
ensure_bin_dir
377536

0 commit comments

Comments
 (0)