|
# -*- coding: utf-8 -*- |
|
|
|
import os |
|
import hashlib |
|
import urllib.request |
|
|
|
def calculate_file_hash(file_path, hash_algo='sha256'): |
|
"""Calculate the hash of a file.""" |
|
hash_func = hashlib.new(hash_algo) |
|
with open(file_path, 'rb') as f: |
|
while chunk := f.read(8192): |
|
hash_func.update(chunk) |
|
return hash_func.hexdigest() |
|
|
|
def download_file(url, target_path, headers=None): |
|
"""Download file from URL.""" |
|
req = urllib.request.Request(url, headers=headers or {}) |
|
with urllib.request.urlopen(req) as response: |
|
file_size = int(response.info().get('Content-Length', -1)) |
|
downloaded = 0 |
|
block_size = 8192 |
|
with open(target_path, 'wb') as out_file: |
|
while True: |
|
buffer = response.read(block_size) |
|
if not buffer: |
|
break |
|
downloaded += len(buffer) |
|
out_file.write(buffer) |
|
if file_size > 0: |
|
percent = downloaded * 100 / file_size |
|
print(f"\rDownload progress: {percent:.2f}%", end='', flush=True) |
|
print("\nDownload complete!") |
|
|
|
# Define the directory where the Cursor AppImage will be placed |
|
target_dir = "/opt/cursor" |
|
|
|
# Ensure the target directory exists |
|
os.makedirs(target_dir, exist_ok=True) |
|
|
|
# Cursor download URL |
|
url = "https://downloader.cursor.sh/linux/appImage/x64" |
|
headers = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'} |
|
|
|
# Path to the current AppImage (symlink) |
|
current_appimage_path = os.path.join(target_dir, "cursor.AppImage") |
|
|
|
# Check if the AppImage file exists and calculate its hash |
|
if os.path.exists(current_appimage_path): |
|
print("Checking for Cursor updates...") |
|
current_hash = calculate_file_hash(current_appimage_path) |
|
else: |
|
print("Installing Cursor for the first time...") |
|
current_hash = None |
|
|
|
# Download the new AppImage to a temporary file |
|
new_appimage_path = os.path.join(target_dir, "cursor_new.AppImage") |
|
print("Downloading the latest version of Cursor...") |
|
download_file(url, new_appimage_path, headers) |
|
|
|
# Calculate the hash of the newly downloaded AppImage |
|
new_hash = calculate_file_hash(new_appimage_path) |
|
|
|
# Compare the hashes to determine if an update is needed |
|
if current_hash == new_hash: |
|
print(f"You are already using the latest version. No update is necessary.") |
|
os.remove(new_appimage_path) # Clean up the new download if it's the same |
|
else: |
|
print(f"New version detected. Updating Cursor...") |
|
# Set executable permissions on the new AppImage |
|
os.chmod(new_appimage_path, 0o755) |
|
|
|
# Remove old AppImage if it exists |
|
if os.path.exists(current_appimage_path): |
|
os.remove(current_appimage_path) |
|
|
|
# Move the new AppImage into place |
|
os.rename(new_appimage_path, current_appimage_path) |
|
print(f"Cursor has been updated to the latest version: {current_appimage_path}") |
|
|
|
# Download and replace the icon in /opt |
|
icon_url = "https://avatars.githubusercontent.com/u/126759922?v=4" # GitHub logo |
|
icon_path = "/opt/cursor/cursor.jpg" |
|
try: |
|
urllib.request.urlretrieve(icon_url, icon_path) |
|
print(f"Icon downloaded and saved to: {icon_path}") |
|
except Exception as e: |
|
print(f"Failed to download icon: {str(e)}") |
|
|
|
# Create or update the .desktop file in /usr/share/applications (system-wide) |
|
desktop_file_path = "/usr/share/applications/cursor.desktop" |
|
desktop_content = f"""[Desktop Entry] |
|
Name=Cursor |
|
Exec={current_appimage_path} |
|
Terminal=false |
|
Type=Application |
|
Icon={icon_path} |
|
StartupWMClass=Cursor |
|
X-AppImage-Version=latest |
|
Comment=Cursor is an AI-first coding environment. |
|
MimeType=x-scheme-handler/cursor; |
|
Categories=Utility;Development; |
|
""" |
|
with open(desktop_file_path, 'w') as f: |
|
f.write(desktop_content) |
|
os.chmod(desktop_file_path, 0o755) |
|
print(f".desktop file updated: {desktop_file_path}") |
|
|
|
# Create a symbolic link to the .desktop file in the target directory (optional) |
|
desktop_symlink_path = os.path.join(target_dir, "cursor.desktop") |
|
if os.path.exists(desktop_symlink_path): |
|
os.remove(desktop_symlink_path) |
|
os.symlink(desktop_file_path, desktop_symlink_path) |