Skip to content

Commit 0e35760

Browse files
committed
Fix version fetching and appimage location
This commit replays the PR of @mablr jorcelinojunior#15 and fixes the version fetchting problem. Additional changes: * Move AppImage to $HOME/Applications * Bump gum version to 0.16.0
1 parent 0451d53 commit 0e35760

File tree

1 file changed

+56
-19
lines changed

1 file changed

+56
-19
lines changed

cursor_setup.sh

Lines changed: 56 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@ set -euo pipefail
44

55
# Constants
66
readonly SCRIPT_ALIAS_NAME="cursor-setup"
7-
readonly DOWNLOAD_DIR="$HOME/.AppImage"
7+
readonly DOWNLOAD_DIR="$HOME/Applications"
88
readonly ICON_DIR="$HOME/.local/share/icons"
99
readonly USER_DESKTOP_FILE="$HOME/Desktop/cursor.desktop"
10-
readonly DOWNLOAD_URL="https://downloader.cursor.sh/linux/appImage/x64"
10+
readonly API_URL="https://www.cursor.com/api/download?platform=linux-x64&releaseTrack=latest"
1111
readonly ICON_URL="https://mintlify.s3-us-west-1.amazonaws.com/cursor/images/logo/app-logo.svg"
1212
readonly VERSION_CHECK_TIMEOUT=5 # in seconds | if you have a slow connection, increase this value to 10, 15, or more
1313
readonly SPINNERS=("meter" "line" "dot" "minidot" "jump" "pulse" "points" "globe" "moon" "monkey" "hamburger")
1414
readonly SPINNER="${SPINNERS[0]}"
15-
readonly DEPENDENCIES=("gum" "curl" "wget" "pv" "bc" "find:findutils" "chmod:coreutils" "timeout:coreutils" "mkdir:coreutils" "apparmor_parser:apparmor-utils")
16-
readonly GUM_VERSION_REQUIRED="0.14.5"
15+
readonly DEPENDENCIES=("gum" "curl" "wget" "pv" "bc" "find:findutils" "chmod:coreutils" "timeout:coreutils" "mkdir:coreutils" "apparmor_parser:apparmor-utils" "jq:jq")
16+
readonly GUM_VERSION_REQUIRED="0.16.0"
1717
readonly SYSTEM_DESKTOP_FILE="$HOME/.local/share/applications/cursor.desktop"
1818
readonly APPARMOR_PROFILE="/etc/apparmor.d/cursor-appimage"
1919
readonly RC_FILES=("bash:$HOME/.bashrc" "zsh:$HOME/.zshrc")
@@ -40,6 +40,7 @@ remote_name=""
4040
remote_size=""
4141
remote_version=""
4242
remote_md5=""
43+
download_url=""
4344

4445
# Utility Functions
4546
validate_os() {
@@ -169,41 +170,73 @@ logg() {
169170

170171
fetch_remote_version() {
171172
logg prompt "Looking for the latest version online..."
172-
headers=$(spinner "Fetching version info from the server..." \
173-
"sleep 1 && timeout \"$VERSION_CHECK_TIMEOUT\" wget -S \"$DOWNLOAD_URL\" -q -O /dev/null 2>&1 || true")
174-
if [[ -z "$headers" ]]; then
175-
logg error "$(echo -e "Failed to fetch headers from the server.\n • Ensure your internet connection is active and stable.\n • Ensure that 'VERSION_CHECK_TIMEOUT' ($VERSION_CHECK_TIMEOUT sec) is set high enough to retrieve the headers.\n • Also, verify if 'DOWNLOAD_URL' is correct: $DOWNLOAD_URL.\n\n ")"
173+
local api_response
174+
if ! api_response=$(spinner "Fetching version info from the API..." \
175+
"timeout \"$VERSION_CHECK_TIMEOUT\" curl -s \"$API_URL\""); then
176+
logg error "$(echo -e "Failed to fetch data from the API server.\n • Ensure your internet connection is active and stable.\n • Ensure that 'VERSION_CHECK_TIMEOUT' ($VERSION_CHECK_TIMEOUT sec) is set high enough.\n • Also, verify if 'API_URL' is correct: $API_URL.\n\n ")"
177+
return 1
178+
fi
179+
if ! command -v jq &> /dev/null; then
180+
logg error "jq is required to parse JSON response but it's not installed. Please install jq and try again."
181+
return 1
182+
fi
183+
download_url=$(echo "$api_response" | jq -r '.downloadUrl')
184+
if [[ -z "$download_url" || "$download_url" == "null" ]]; then
185+
logg error "Failed to extract download URL from API response. Response: $api_response"
176186
return 1
177187
fi
178188
logg success "Latest version details retrieved successfully."
179-
remote_name=$(echo "$headers" | grep -oE 'filename="[^"]+"' | sed 's/filename=//g; s/\"//g') || remote_name=""
189+
headers=$(spinner "Fetching file details..." \
190+
"timeout \"$VERSION_CHECK_TIMEOUT\" wget -S \"$download_url\" -q -O /dev/null 2>&1 || true")
191+
192+
if [[ -z "$headers" ]]; then
193+
logg error "$(echo -e "Failed to fetch file details from the download server.\n • Ensure your internet connection is active and stable.\n • Check if the download URL is accessible: $download_url\n\n ")"
194+
return 1
195+
fi
196+
remote_name=$(basename "$download_url")
180197
remote_size=$(echo "$headers" | grep -oE 'Content-Length: [0-9]+' | sed 's/Content-Length: //') || remote_size="0"
181198
remote_version=$(extract_version "$remote_name")
182-
remote_md5=$(echo "$headers" | grep -oE 'ETag: "[^"]+"' | sed 's/ETag: //; s/"//g' || echo "unknown")
199+
remote_hash=$(echo "$headers" | grep -oE 'ETag: "[^"]+"' | sed 's/ETag: //; s/"//g' || echo "unknown")
183200
if [[ -z "$remote_name" ]]; then
184-
logg error "Could not fetch the filename info. Please check that the 'DOWNLOAD_URL' variable is correct and try again."
201+
logg error "Could not determine the filename from download URL. Please check the API response and try again."
185202
return 1
186203
fi
187-
logg info "$(echo -e "Latest version online:\n - name: $remote_name\n - version: $remote_version\n - size: $(convert_to_mb "$remote_size")\n - MD5 Hash: $remote_md5\n")"
204+
logg info "$(echo -e "Latest version online:\n - name: $remote_name\n - version: $remote_version\n - size: $(convert_to_mb "$remote_size")\n - Hash: $remote_hash\n - download URL: $download_url\n")"
188205
}
189206

190207
find_local_version() {
191208
show_log=${1:-false}
192209
[[ $show_log == true ]] && spinner "Searching for a local version..." "sleep 2;"
193210
mkdir -p "$DOWNLOAD_DIR"
194-
local_path=$(find "$DOWNLOAD_DIR" -maxdepth 1 -type f -name 'cursor-*.AppImage' -printf '%T@ %p\n' 2>/dev/null | sort -nr | head -n 1 | cut -d' ' -f2-)
211+
local_path=$(find "$DOWNLOAD_DIR" -maxdepth 1 -type f -name 'Cursor-*.AppImage' -printf '%T@ %p\n' 2>/dev/null | sort -nr | head -n 1 | cut -d' ' -f2-)
195212
if [[ -n "$local_path" ]]; then
196213
local_name=$(basename "$local_path")
197214
local_size=$(stat -c %s "$local_path" 2>/dev/null || echo "0")
198215
local_version=$(extract_version "$local_path")
199-
local_md5=$(md5sum "$local_path" | cut -d' ' -f1)
200-
[[ $show_log == true ]] && logg info "$(printf "Local version found:\n - name: %s\n - version: %s\n - size: %s\n - MD5 Hash: %s\n - path: %s\n" "$local_name" "$local_version" "$(convert_to_mb "$local_size")" "$local_md5" "$local_path")"
216+
local_hash=$(calculate_etag "$local_path")
217+
[[ $show_log == true ]] && logg info "$(printf "Local version found:\n - name: %s\n - version: %s\n - size: %s\n - Hash: %s\n - path: %s\n" "$local_name" "$local_version" "$(convert_to_mb "$local_size")" "$local_hash" "$local_path")"
201218
return 0
202219
fi
203220
[[ $show_log == true ]] && logg error "$(echo -e "No local version found in $DOWNLOAD_DIR\n Go back to the menu and fetch it first.")"
204221
return 1
205222
}
206223

224+
calculate_etag() {
225+
local chunk_size=5 # Cursor appimage uses 5MB chunks
226+
local file_size=$(du -b "$1" | cut -f 1)
227+
local chunks=$((file_size / (chunk_size * 1024 * 1024)))
228+
if [[ $((file_size % (chunk_size * 1024 * 1024))) -gt 0 ]]; then
229+
chunks=$((chunks + 1))
230+
fi
231+
local tmp_file=$(mktemp -t cursor-local-etag.XXXXXXXXXXXXX)
232+
for (( chunk=0; chunk<$chunks; chunk++ )); do
233+
dd bs=1M count=$chunk_size skip=$((chunk_size * chunk)) if="$1" 2> /dev/null | md5sum >> $tmp_file
234+
done
235+
local etag=$(echo "$(xxd -r -p "$tmp_file" | md5sum | cut -f 1 -d ' ')"-$chunks)
236+
rm "$tmp_file"
237+
echo "$etag"
238+
}
239+
207240
download_logo() {
208241
logg prompt "Getting the Cursor logo ready..."
209242
mkdir -p "$ICON_DIR"
@@ -217,15 +250,19 @@ download_logo() {
217250
download_appimage() {
218251
logg prompt "Starting the download of the latest version..."
219252
local output_document="$DOWNLOAD_DIR/$remote_name"
253+
if [[ -z "$download_url" ]]; then
254+
logg error "Download URL is empty. Please fetch the remote version first."
255+
return 1
256+
fi
220257
if command -v pv >/dev/null; then
221258
if [[ "$remote_size" =~ ^[0-9]+$ ]]; then
222-
wget --quiet --content-disposition -O - "$DOWNLOAD_URL" | pv -s "$remote_size" >"$output_document"
259+
wget --quiet --content-disposition -O - "$download_url" | pv -s "$remote_size" >"$output_document"
223260
else
224261
logg warn "Couldn't determine file size. Proceeding with a standard download."
225-
spinner "Downloading AppImage" "wget --quiet --content-disposition --output-document=\"$output_document\" \"$DOWNLOAD_URL\""
262+
spinner "Downloading AppImage" "wget --quiet --content-disposition --output-document=\"$output_document\" \"$download_url\""
226263
fi
227264
else
228-
if ! spinner "Downloading AppImage" "wget --quiet --show-progress --content-disposition --output-document=\"$output_document\" --trust-server-names \"$DOWNLOAD_URL\""; then
265+
if ! spinner "Downloading AppImage" "wget --quiet --show-progress --content-disposition --output-document=\"$output_document\" --trust-server-names \"$download_url\""; then
229266
logg error "AppImage download failed. Please try again."
230267
return 1
231268
fi
@@ -319,7 +356,7 @@ menu() {
319356
case "$option" in
320357
"$(nostyle "$all_in_one")")
321358
fetch_remote_version
322-
if ! find_local_version || [[ "$local_md5" != "$remote_md5" ]]; then
359+
if ! find_local_version || [[ "$local_hash" != "$remote_hash" ]]; then
323360
download_appimage
324361
download_logo
325362
setup_launchers

0 commit comments

Comments
 (0)