Forked from jorcelinojunior/cursor_appimage_manager.sh
Created
September 25, 2024 05:59
-
-
Save Malaeu/804b4f0339604e72bb94b3c2e7ed6063 to your computer and use it in GitHub Desktop.
Automate the integration of Cursor .AppImage on Linux: updates .desktop, manages icons, ensures the latest version, and configures AppArmor (Required for Ubuntu 24.04).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Temporary comment to avoid abrupt exit | |
# set -euo pipefail | |
# Definition of colors for terminal output | |
readonly RED_COLOR="\e[31m" | |
readonly GREEN_COLOR="\e[32m" | |
readonly YELLOW_COLOR="\e[33m" | |
readonly BLUE_COLOR="\e[34m" | |
readonly RESET_COLOR="\e[0m" | |
# General settings | |
readonly DOWNLOAD_APP_DIR="$HOME/Downloads/.AppImage" | |
readonly ICON_DIR="$HOME/.local/share/icons" | |
readonly ICON_URL="https://www.cursor.com/brand/icon.svg" | |
readonly DESKTOP_FILE_PATH="$HOME/.local/share/applications/cursor.desktop" | |
readonly APPARMOR_PROFILE="/etc/apparmor.d/cursor-appimage" | |
readonly DOWNLOAD_URL="https://downloader.cursor.sh/linux/appImage/x64" | |
readonly TEMP_DIR="/tmp/AppImage" | |
cursor_appimage_path="" | |
cursor_icon_path="" | |
# Support function to print steps | |
print_step() { | |
echo -e "${YELLOW_COLOR}$1${RESET_COLOR}" | |
} | |
# Support function to print success | |
print_success() { | |
echo -e "${GREEN_COLOR}$1${RESET_COLOR}" | |
} | |
# Support function for error handling | |
error_exit() { | |
echo -e "${RED_COLOR}$1${RESET_COLOR}" >&2 | |
exit 1 | |
} | |
# Check necessary dependencies | |
check_dependencies() { | |
print_step "Checking necessary dependencies..." | |
for cmd in curl chmod find mkdir wget; do | |
if ! command -v "$cmd" >/dev/null 2>&1; then | |
error_exit "This script requires $cmd, but it is not installed.\nPlease install it with 'sudo apt install $cmd' and try again." | |
fi | |
done | |
print_success "All necessary dependencies are installed." | |
} | |
# Function to get the latest version of the AppImage in the local directory | |
get_latest_local_version() { | |
local appimage_files | |
mapfile -t appimage_files < <(find "$DOWNLOAD_APP_DIR" -name 'cursor-*.AppImage' -print0 | xargs -0 ls -t) | |
if [ "${#appimage_files[@]}" -eq 0 ]; then | |
error_exit "No cursor.sh AppImage files found in $DOWNLOAD_APP_DIR" | |
fi | |
echo "${appimage_files[0]}" | |
} | |
# Search for the most recent AppImage file path | |
fetch_app_path() { | |
print_step "Searching for the most recent AppImage path of cursor.sh" | |
local appimage_files | |
mapfile -t appimage_files < <(find "$DOWNLOAD_APP_DIR" -name "cursor-*.AppImage" -printf '%T@ %p\n' | sort -rn | cut -d' ' -f2-) | |
if [ "${#appimage_files[@]}" -eq 0 ]; then | |
echo -e "${RED_COLOR}No cursor.sh AppImage files found in $DOWNLOAD_APP_DIR/${RESET_COLOR}" | |
error_exit "You need to download the latest version first (OPTION 1) and run this script again." | |
fi | |
cursor_appimage_path=${appimage_files[0]} | |
print_success "Path found: $cursor_appimage_path" | |
} | |
# Download the application icon | |
download_logo() { | |
print_step "Downloading the logo" | |
mkdir -p "$ICON_DIR" | |
if ! curl -s -o "$ICON_DIR/cursor-icon.svg" "$ICON_URL"; then | |
error_exit "Failed to download the logo from $ICON_URL" | |
fi | |
print_success "Logo downloaded: $ICON_DIR/cursor-icon.svg" | |
} | |
# Create the .desktop file for the application | |
create_desktop_file() { | |
print_step "Creating the .desktop file" | |
cat <<-EOF >"$DESKTOP_FILE_PATH" | |
[Desktop Entry] | |
Name=Cursor | |
Type=Application | |
Name=Cursor | |
Exec=$cursor_appimage_path | |
Icon=$cursor_icon_path | |
Categories=Utility;Development | |
Terminal=false | |
StartupWMClass=Cursor | |
X-AppImage-Version=latest | |
Comment=Cursor is an AI-first coding environment. | |
MimeType=x-scheme-handler/cursor; | |
EOF | |
if ! chmod +x "$DESKTOP_FILE_PATH"; then | |
error_exit "Failed to make the .desktop file executable" | |
fi | |
print_success "Desktop file created: $DESKTOP_FILE_PATH" | |
} | |
# Configure the AppArmor profile for the application | |
create_apparmor_profile() { | |
local appimage_path=$1 | |
if [[ -z $appimage_path ]]; then | |
appimage_path=$(get_latest_local_version) | |
fi | |
print_step "Configuring the AppArmor profile..." | |
cat <<-EOF | sudo tee $APPARMOR_PROFILE > /dev/null | |
# This profile allows everything and only exists to give the | |
# application a name instead of having the label "unconfined" | |
abi <abi/4.0>, | |
include <tunables/global> | |
profile cursor $appimage_path flags=(unconfined) { | |
userns, | |
# Site-specific additions and overrides. See local/README for details. | |
include if exists <local/cursor> | |
} | |
EOF | |
sudo apparmor_parser -r $APPARMOR_PROFILE || error_exit "Failed to apply the AppArmor profile." | |
print_success "AppArmor profile successfully configured for $appimage_path" | |
} | |
make_executable() { | |
print_step "Making the .desktop file executable" | |
if ! chmod +x "$DESKTOP_FILE_PATH"; then | |
error_exit "Failed to make the .desktop file executable" | |
fi | |
print_success "Desktop file is now executable." | |
} | |
# Main function that checks and downloads the latest version if it is not yet locally present | |
check_and_download_version() { | |
local latest_local_version=$(get_latest_local_version) | |
local latest_local_filename=$(basename "$latest_local_version") | |
echo -e "${BLUE_COLOR}Latest local version: $(basename "$latest_local_version")${RESET_COLOR}" | |
# Ensures that the temporary directory exists | |
mkdir -p "$TEMP_DIR" | |
# cd "$TEMP_DIR" || exit | |
# Starts a download with wget in a temporary directory | |
wget -q --content-disposition --trust-server-names --directory-prefix="$TEMP_DIR" "$DOWNLOAD_URL" & | |
local wget_pid=$! | |
# Waits a few seconds to allow the connection to establish and the header to be read | |
echo -e "${YELLOW_COLOR}Searching for the latest version. Please wait...${RESET_COLOR}" | |
sleep 5 | |
# Kills the wget process after obtaining the file name | |
kill $wget_pid 2>/dev/null | |
wait $wget_pid 2>/dev/null | |
# Finds the file name that would start to be downloaded | |
local temp_online_filename=$(ls -t "$TEMP_DIR"/* | head -n 1) | |
local online_filename=$(basename "$temp_online_filename") | |
# Compares versions and downloads if necessary | |
if [[ "$latest_local_filename" == "$online_filename" ]]; then | |
echo -e "${GREEN_COLOR}The latest version ($online_filename) is already downloaded.${RESET_COLOR}" | |
rm -f "$TEMP_DIR/$temp_online_filename" # Remove the partial file if it was created | |
else | |
echo -e "${BLUE_COLOR}A new version is available: $online_filename${RESET_COLOR}" | |
cd "$DOWNLOAD_APP_DIR" || exit | |
wget --quiet --show-progress --content-disposition -P "$DOWNLOAD_APP_DIR" --trust-server-names "$DOWNLOAD_URL" | |
echo -e "${GREEN_COLOR}Download completed: $DOWNLOAD_APP_DIR/$online_filename${RESET_COLOR}" | |
fi | |
# Cleans up the temporary directory | |
rm -rf "$TEMP_DIR" | |
} | |
# Function to search and prepare the AppImage | |
fetch_and_prepare_appimage() { | |
check_dependencies | |
fetch_app_path | |
download_logo | |
create_desktop_file | |
make_executable | |
create_apparmor_profile | |
echo -e "${GREEN_COLOR}Application installed and ready to use.${RESET_COLOR}" | |
} | |
# Function to create the AppArmor profile | |
setup_apparmor_profile() { | |
check_dependencies | |
fetch_app_path | |
create_apparmor_profile | |
} | |
# Interactive menu | |
PS3='Please choose an option: ' | |
options=( | |
"Fetch the latest version and download (if not already present)" | |
"Re/Install the latest downloaded version" | |
"Just configure AppArmor (Required for Ubuntu 24.04)" | |
"Exit" | |
) | |
select opt in "${options[@]}" | |
do | |
case $opt in | |
"Fetch the latest version and download (if not already present)") | |
check_and_download_version | |
;; | |
"Re/Install the latest downloaded version") | |
fetch_and_prepare_appimage | |
;; | |
"Just configure AppArmor (Required for Ubuntu 24.04)") | |
setup_apparmor_profile | |
;; | |
"Exit") | |
break | |
;; | |
*) echo "Invalid option $REPLY";; | |
esac | |
done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment