diff --git a/build-deb.sh b/build-deb.sh index 6d01d2a..cec2d15 100755 --- a/build-deb.sh +++ b/build-deb.sh @@ -31,16 +31,20 @@ fi # Check for root/sudo IS_SUDO=false +ORIGINAL_USER="" +ORIGINAL_HOME="" if [ "$EUID" -eq 0 ]; then IS_SUDO=true # Check if running via sudo (and not directly as root) if [ -n "$SUDO_USER" ]; then ORIGINAL_USER="$SUDO_USER" - ORIGINAL_HOME=$(eval echo ~$ORIGINAL_USER) + ORIGINAL_HOME=$(getent passwd "$SUDO_USER" | cut -d: -f6) # More reliable way to get home dir + echo "Running with sudo as user: $ORIGINAL_USER (Home: $ORIGINAL_HOME)" else # Running directly as root, no original user context ORIGINAL_USER="root" ORIGINAL_HOME="/root" + echo "Running directly as root." fi else echo "Please run with sudo to install dependencies" @@ -52,17 +56,19 @@ if [ "$IS_SUDO" = true ] && [ "$ORIGINAL_USER" != "root" ] && [ -d "$ORIGINAL_HO echo "Found NVM installation for user $ORIGINAL_USER, attempting to preserve npm/npx path..." # Source NVM script to set up NVM environment variables temporarily export NVM_DIR="$ORIGINAL_HOME/.nvm" - [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm + if [ -s "$NVM_DIR/nvm.sh" ]; then + \. "$NVM_DIR/nvm.sh" # This loads nvm + # Find the path to the currently active or default Node version's bin directory + NODE_BIN_PATH=$(nvm which current | xargs dirname 2>/dev/null || find "$NVM_DIR/versions/node" -maxdepth 2 -type d -name 'bin' | sort -V | tail -n 1) - # Find the path to the currently active or default Node version's bin directory - # nvm_find_node_version might not be available, try finding the latest installed version - NODE_BIN_PATH=$(find "$NVM_DIR/versions/node" -maxdepth 2 -type d -name 'bin' | sort -V | tail -n 1) - - if [ -n "$NODE_BIN_PATH" ] && [ -d "$NODE_BIN_PATH" ]; then - echo "Adding $NODE_BIN_PATH to PATH" - export PATH="$NODE_BIN_PATH:$PATH" + if [ -n "$NODE_BIN_PATH" ] && [ -d "$NODE_BIN_PATH" ]; then + echo "Adding $NODE_BIN_PATH to PATH" + export PATH="$NODE_BIN_PATH:$PATH" + else + echo "Warning: Could not determine NVM Node bin path. npm/npx might not be found." + fi else - echo "Warning: Could not determine NVM Node bin path. npm/npx might not be found." + echo "Warning: nvm.sh script not found or not sourceable." fi fi @@ -77,7 +83,8 @@ echo "Target Architecture: $ARCHITECTURE" # Display the target architecture PACKAGE_NAME="claude-desktop" MAINTAINER="Claude Desktop Linux Maintainers" DESCRIPTION="Claude Desktop for Linux" -WORK_DIR="$(pwd)/build" # Top-level build directory +PROJECT_ROOT="$(pwd)" # Save project root +WORK_DIR="$PROJECT_ROOT/build" # Top-level build directory APP_STAGING_DIR="$WORK_DIR/electron-app" # Staging for app files before packaging VERSION="" # Will be determined after download @@ -117,6 +124,43 @@ while true; do done echo "-------------------------------------" # Add separator after selection/before next steps # --- End Build Format Selection --- +# --- Cleanup Selection --- +PERFORM_CLEANUP=false # Default to keeping files +display_cleanup_menu() { + echo -e "\n\033[1;34m====== Cleanup Build Files ======\033[0m" + echo -e "This refers to the intermediate files created in the '$WORK_DIR' directory." + echo -e "\033[1;32m [1] Yes, remove intermediate build files after completion\033[0m" + echo -e "\033[1;32m [2] No, keep intermediate build files\033[0m" + echo -e "\033[1;34m=================================\033[0m" +} + +CLEANUP_CHOICE="" +while true; do + display_cleanup_menu + read -n 1 -p $'\nEnter choice (1 or 2, any other key to cancel prompt): ' CLEANUP_CHOICE + echo + + case $CLEANUP_CHOICE in + "1") + echo -e "\033[1;36m✔ Intermediate build files will be removed upon completion.\033[0m" + PERFORM_CLEANUP=true + break + ;; + "2") + echo -e "\033[1;36m✔ Intermediate build files will be kept.\033[0m" + PERFORM_CLEANUP=false + break + ;; + *) + echo # Add newline for clarity + echo -e "\033[1;33m⚠ Skipping cleanup decision. Build files will be kept.\033[0m" + PERFORM_CLEANUP=false # Default to keeping files + break + ;; + esac +done +echo "-------------------------------------" +# --- End Cleanup Selection --- # Function to check if a command exists @@ -137,7 +181,7 @@ DEPS_TO_INSTALL="" COMMON_DEPS="p7zip wget wrestool icotool convert npx" # Format specific dependencies DEB_DEPS="dpkg-dev" -APPIMAGE_DEPS="" # Add appimagetool, fuse if needed later +APPIMAGE_DEPS="" # appimagetool handled by its script ALL_DEPS_TO_CHECK="$COMMON_DEPS" if [ "$BUILD_FORMAT" = "deb" ]; then @@ -155,7 +199,6 @@ for cmd in $ALL_DEPS_TO_CHECK; do "convert") DEPS_TO_INSTALL="$DEPS_TO_INSTALL imagemagick" ;; "npx") DEPS_TO_INSTALL="$DEPS_TO_INSTALL nodejs npm" ;; "dpkg-deb") DEPS_TO_INSTALL="$DEPS_TO_INSTALL dpkg-dev" ;; - # Add cases for AppImage deps if needed esac fi done @@ -168,332 +211,315 @@ if [ ! -z "$DEPS_TO_INSTALL" ]; then echo "System dependencies installed successfully" fi -# Check for electron - first local, then global (Needed for both formats potentially) -LOCAL_ELECTRON="" # Initialize variable -# Check for local electron in node_modules -if [ -f "$(pwd)/node_modules/.bin/electron" ]; then - echo "✓ local electron found in node_modules" - LOCAL_ELECTRON="$(pwd)/node_modules/.bin/electron" - export PATH="$(pwd)/node_modules/.bin:$PATH" -elif ! check_command "electron"; then - echo "Installing electron via npm..." - # Try local installation first - if [ -f "package.json" ]; then - echo "Found package.json, installing electron locally..." - npm install --save-dev electron - if [ -f "$(pwd)/node_modules/.bin/electron" ]; then - echo "✓ Local electron installed successfully" - LOCAL_ELECTRON="$(pwd)/node_modules/.bin/electron" - export PATH="$(pwd)/node_modules/.bin:$PATH" - else - # Fall back to global installation if local fails - echo "Local electron install failed or not possible, trying global..." - npm install -g electron - # Attempt to fix permissions if installed globally - if check_command "electron"; then - ELECTRON_PATH=$(command -v electron) - echo "Attempting to fix permissions for global electron at $ELECTRON_PATH..." - chmod -R a+rx "$(dirname "$ELECTRON_PATH")/../lib/node_modules/electron" || echo "Warning: Failed to chmod global electron installation directory. Permissions might be incorrect." - fi - if ! check_command "electron"; then - echo "Failed to install electron globally. Please install it manually:" - echo "npm install -g electron # or npm install --save-dev electron in project root" - exit 1 - fi - echo "Global electron installed successfully" - fi - else - # No package.json, try global installation - echo "No package.json found, trying global electron installation..." - npm install -g electron - # Attempt to fix permissions if installed globally - if check_command "electron"; then - ELECTRON_PATH=$(command -v electron) - echo "Attempting to fix permissions for global electron at $ELECTRON_PATH..." - chmod -R a+rx "$(dirname "$ELECTRON_PATH")/../lib/node_modules/electron" || echo "Warning: Failed to chmod global electron installation directory. Permissions might be incorrect." - fi - if ! check_command "electron"; then - echo "Failed to install electron globally. Please install it manually:" - echo "npm install -g electron" - exit 1 - fi - echo "Global electron installed successfully" - fi -fi - -# Clean previous build +# Clean previous build directory FIRST rm -rf "$WORK_DIR" mkdir -p "$WORK_DIR" mkdir -p "$APP_STAGING_DIR" # Create the app staging directory explicitly -# Install asar if needed -if ! npm list -g asar > /dev/null 2>&1; then - echo "Installing asar package globally..." - npm install -g asar +# --- Electron & Asar Handling --- +CHOSEN_ELECTRON_MODULE_PATH="" # Path to the electron module directory to be copied +ASAR_EXEC="" # Path to the asar executable +TEMP_PACKAGE_JSON_CREATED=false + +# Always ensure local Electron & Asar installation in WORK_DIR +echo "Ensuring local Electron and Asar installation in $WORK_DIR..." +cd "$WORK_DIR" # Change to build dir for local install + +# Create dummy package.json if none exists in build dir +if [ ! -f "package.json" ]; then + echo "Creating temporary package.json in $WORK_DIR for local install..." + echo '{"name":"claude-desktop-build","version":"0.0.1","private":true}' > package.json + TEMP_PACKAGE_JSON_CREATED=true fi +# Install electron and asar locally if not already present +# Check for Electron dist dir and Asar binary first +ELECTRON_DIST_PATH="$WORK_DIR/node_modules/electron/dist" +ASAR_BIN_PATH="$WORK_DIR/node_modules/.bin/asar" + +INSTALL_NEEDED=false +if [ ! -d "$ELECTRON_DIST_PATH" ]; then + echo "Electron distribution not found." + INSTALL_NEEDED=true +fi +if [ ! -f "$ASAR_BIN_PATH" ]; then + echo "Asar binary not found." + INSTALL_NEEDED=true +fi + +if [ "$INSTALL_NEEDED" = true ]; then + echo "Installing Electron and Asar locally into $WORK_DIR..." + # Use --no-save to avoid modifying the temp package.json unnecessarily + if ! npm install --no-save electron asar; then + echo "❌ Failed to install Electron and/or Asar locally." + cd "$PROJECT_ROOT" + exit 1 + fi + echo "✓ Electron and Asar installation command finished." +else + echo "✓ Local Electron distribution and Asar binary already present." +fi + +# Verify Electron installation by checking for the essential 'dist' directory +if [ -d "$ELECTRON_DIST_PATH" ]; then + echo "✓ Found Electron distribution directory at $ELECTRON_DIST_PATH." + CHOSEN_ELECTRON_MODULE_PATH="$(realpath "$WORK_DIR/node_modules/electron")" + echo "✓ Setting Electron module path for copying to $CHOSEN_ELECTRON_MODULE_PATH." +else + echo "❌ Failed to find Electron distribution directory at '$ELECTRON_DIST_PATH' after installation attempt." + echo " Cannot proceed without the Electron distribution files." + cd "$PROJECT_ROOT" # Go back before exiting + exit 1 +fi + +# Verify Asar installation +if [ -f "$ASAR_BIN_PATH" ]; then + ASAR_EXEC="$(realpath "$ASAR_BIN_PATH")" + echo "✓ Found local Asar binary at $ASAR_EXEC." +else + echo "❌ Failed to find Asar binary at '$ASAR_BIN_PATH' after installation attempt." + cd "$PROJECT_ROOT" + exit 1 +fi + +cd "$PROJECT_ROOT" # Go back to project root + +# Final check for the chosen Electron module path (redundant but safe) +if [ -z "$CHOSEN_ELECTRON_MODULE_PATH" ] || [ ! -d "$CHOSEN_ELECTRON_MODULE_PATH" ]; then + echo "❌ Critical error: Could not resolve a valid Electron module path to copy." + exit 1 +fi +echo "Using Electron module path: $CHOSEN_ELECTRON_MODULE_PATH" +echo "Using asar executable: $ASAR_EXEC" +# --- End Electron & Asar Handling --- + + # Download Claude Windows installer for the target architecture echo "📥 Downloading Claude Desktop installer for $ARCHITECTURE..." -CLAUDE_EXE_PATH="$WORK_DIR/$CLAUDE_EXE_FILENAME" # Use the arch-specific filename +CLAUDE_EXE_PATH="$WORK_DIR/$CLAUDE_EXE_FILENAME" if ! wget -O "$CLAUDE_EXE_PATH" "$CLAUDE_DOWNLOAD_URL"; then echo "❌ Failed to download Claude Desktop installer from $CLAUDE_DOWNLOAD_URL" exit 1 fi echo "✓ Download complete: $CLAUDE_EXE_FILENAME" -# Extract resources -echo "📦 Extracting resources from $CLAUDE_EXE_FILENAME..." -cd "$WORK_DIR" -if ! 7z x -y "$CLAUDE_EXE_PATH"; then # Use the arch-specific path +# Extract resources into a dedicated subdirectory to avoid conflicts +echo "📦 Extracting resources from $CLAUDE_EXE_FILENAME into separate directory..." +CLAUDE_EXTRACT_DIR="$WORK_DIR/claude-extract" +mkdir -p "$CLAUDE_EXTRACT_DIR" +if ! 7z x -y "$CLAUDE_EXE_PATH" -o"$CLAUDE_EXTRACT_DIR"; then # Extract to specific dir echo "❌ Failed to extract installer" - exit 1 + cd "$PROJECT_ROOT" && exit 1 fi # Extract nupkg filename and version -# The nupkg name might differ slightly for arm64, adjust find pattern if needed -# Assuming it still starts with AnthropicClaude- for now -NUPKG_PATH=$(find . -name "AnthropicClaude-*.nupkg" | head -1) -if [ -z "$NUPKG_PATH" ]; then - echo "❌ Could not find AnthropicClaude nupkg file in $WORK_DIR" - exit 1 +cd "$CLAUDE_EXTRACT_DIR" # Change into the extract dir to find files +NUPKG_PATH_RELATIVE=$(find . -maxdepth 1 -name "AnthropicClaude-*.nupkg" | head -1) +if [ -z "$NUPKG_PATH_RELATIVE" ]; then + echo "❌ Could not find AnthropicClaude nupkg file in $CLAUDE_EXTRACT_DIR" + cd "$PROJECT_ROOT" && exit 1 fi -echo "Found nupkg: $NUPKG_PATH" +NUPKG_PATH="$CLAUDE_EXTRACT_DIR/$NUPKG_PATH_RELATIVE" # Store full path +echo "Found nupkg: $NUPKG_PATH_RELATIVE (in $CLAUDE_EXTRACT_DIR)" # Extract version from the nupkg filename (using LC_ALL=C for locale compatibility) -# Assuming version format is consistent across architectures -VERSION=$(echo "$NUPKG_PATH" | LC_ALL=C grep -oP 'AnthropicClaude-\K[0-9]+\.[0-9]+\.[0-9]+(?=-full|-arm64-full)') # Adjusted regex slightly +VERSION=$(echo "$NUPKG_PATH_RELATIVE" | LC_ALL=C grep -oP 'AnthropicClaude-\K[0-9]+\.[0-9]+\.[0-9]+(?=-full|-arm64-full)') if [ -z "$VERSION" ]; then - echo "❌ Could not extract version from nupkg filename: $NUPKG_PATH" - exit 1 + echo "❌ Could not extract version from nupkg filename: $NUPKG_PATH_RELATIVE" + cd "$PROJECT_ROOT" && exit 1 fi echo "✓ Detected Claude version: $VERSION" -if ! 7z x -y "$NUPKG_PATH"; then +# Extract nupkg within its directory +if ! 7z x -y "$NUPKG_PATH_RELATIVE"; then # Use relative path since we are in CLAUDE_EXTRACT_DIR echo "❌ Failed to extract nupkg" - exit 1 + cd "$PROJECT_ROOT" && exit 1 fi -echo "✓ Resources extracted" +echo "✓ Resources extracted from nupkg" # Extract and convert icons (needed by the packaging script later) -# Assuming claude.exe exists in the extracted structure for both archs +# Still operating within CLAUDE_EXTRACT_DIR EXE_RELATIVE_PATH="lib/net45/claude.exe" # Check if this path is correct for arm64 too if [ ! -f "$EXE_RELATIVE_PATH" ]; then - echo "❌ Cannot find claude.exe at expected path: $EXE_RELATIVE_PATH" - # Add alternative path check if needed for arm64 - # find . -name claude.exe # Uncomment to help debug if needed - exit 1 + echo "❌ Cannot find claude.exe at expected path within extraction dir: $CLAUDE_EXTRACT_DIR/$EXE_RELATIVE_PATH" + cd "$PROJECT_ROOT" && exit 1 fi echo "🎨 Processing icons from $EXE_RELATIVE_PATH..." -if ! wrestool -x -t 14 "$EXE_RELATIVE_PATH" -o claude.ico; then +# Output icons within the extraction directory +if ! wrestool -x -t 14 "$EXE_RELATIVE_PATH" -o claude.ico; then # Output relative to current dir (CLAUDE_EXTRACT_DIR) echo "❌ Failed to extract icons from exe" - exit 1 + cd "$PROJECT_ROOT" && exit 1 fi -if ! icotool -x claude.ico; then +if ! icotool -x claude.ico; then # Input relative to current dir (CLAUDE_EXTRACT_DIR) echo "❌ Failed to convert icons" - exit 1 + cd "$PROJECT_ROOT" && exit 1 fi -echo "✓ Icons processed (will be used by packaging script)" +# Copy extracted icons to WORK_DIR for packaging scripts to find easily +cp claude_*.png "$WORK_DIR/" +echo "✓ Icons processed and copied to $WORK_DIR" # Process app.asar -# Assuming app.asar structure is consistent across architectures echo "⚙️ Processing app.asar..." -cp "lib/net45/resources/app.asar" "$APP_STAGING_DIR/" -cp -r "lib/net45/resources/app.asar.unpacked" "$APP_STAGING_DIR/" +# Copy resources to staging dir first, using full paths from the extraction dir +cp "$CLAUDE_EXTRACT_DIR/lib/net45/resources/app.asar" "$APP_STAGING_DIR/" +cp -a "$CLAUDE_EXTRACT_DIR/lib/net45/resources/app.asar.unpacked" "$APP_STAGING_DIR/" # Use -a to preserve links/permissions -cd "$APP_STAGING_DIR" -npx asar extract app.asar app.asar.contents +cd "$APP_STAGING_DIR" # Change to staging dir for asar processing +"$ASAR_EXEC" extract app.asar app.asar.contents # Replace native module with stub implementation echo "Creating stub native module..." cat > app.asar.contents/node_modules/claude-native/index.js << EOF // Stub implementation of claude-native using KeyboardKey enum values -const KeyboardKey = { - Backspace: 43, - Tab: 280, - Enter: 261, - Shift: 272, - Control: 61, - Alt: 40, - CapsLock: 56, - Escape: 85, - Space: 276, - PageUp: 251, - PageDown: 250, - End: 83, - Home: 154, - LeftArrow: 175, - UpArrow: 282, - RightArrow: 262, - DownArrow: 81, - Delete: 79, - Meta: 187 -}; - +const KeyboardKey = { Backspace: 43, Tab: 280, Enter: 261, Shift: 272, Control: 61, Alt: 40, CapsLock: 56, Escape: 85, Space: 276, PageUp: 251, PageDown: 250, End: 83, Home: 154, LeftArrow: 175, UpArrow: 282, RightArrow: 262, DownArrow: 81, Delete: 79, Meta: 187 }; Object.freeze(KeyboardKey); - -module.exports = { - getWindowsVersion: () => "10.0.0", // Keep this generic? - setWindowEffect: () => {}, - removeWindowEffect: () => {}, - getIsMaximized: () => false, - flashFrame: () => {}, - clearFlashFrame: () => {}, - showNotification: () => {}, - setProgressBar: () => {}, - clearProgressBar: () => {}, - setOverlayIcon: () => {}, - clearOverlayIcon: () => {}, - KeyboardKey -}; +module.exports = { getWindowsVersion: () => "10.0.0", setWindowEffect: () => {}, removeWindowEffect: () => {}, getIsMaximized: () => false, flashFrame: () => {}, clearFlashFrame: () => {}, showNotification: () => {}, setProgressBar: () => {}, clearProgressBar: () => {}, setOverlayIcon: () => {}, clearOverlayIcon: () => {}, KeyboardKey }; EOF # Copy Tray icons mkdir -p app.asar.contents/resources mkdir -p app.asar.contents/resources/i18n - -cp ../lib/net45/resources/Tray* app.asar.contents/resources/ -# Copy only the language-specific JSON files (e.g., en-US.json) -cp ../lib/net45/resources/*-*.json app.asar.contents/resources/i18n/ +# Copy from the extraction directory (use full path for clarity) +cp "$CLAUDE_EXTRACT_DIR/lib/net45/resources/Tray"* app.asar.contents/resources/ +cp "$CLAUDE_EXTRACT_DIR/lib/net45/resources/"*-*.json app.asar.contents/resources/i18n/ echo "Downloading Main Window Fix Assets" cd app.asar.contents wget -O- https://github.com/emsi/claude-desktop/raw/refs/heads/main/assets/main_window.tgz | tar -zxvf - -cd .. +cd .. # Back to APP_STAGING_DIR # Repackage app.asar -npx asar pack app.asar.contents app.asar +"$ASAR_EXEC" pack app.asar.contents app.asar # Create native module stub within the staging area's unpacked directory mkdir -p "$APP_STAGING_DIR/app.asar.unpacked/node_modules/claude-native" cat > "$APP_STAGING_DIR/app.asar.unpacked/node_modules/claude-native/index.js" << EOF // Stub implementation of claude-native using KeyboardKey enum values -const KeyboardKey = { - Backspace: 43, - Tab: 280, - Enter: 261, - Shift: 272, - Control: 61, - Alt: 40, - CapsLock: 56, - Escape: 85, - Space: 276, - PageUp: 251, - PageDown: 250, - End: 83, - Home: 154, - LeftArrow: 175, - UpArrow: 282, - RightArrow: 262, - DownArrow: 81, - Delete: 79, - Meta: 187 -}; - +const KeyboardKey = { Backspace: 43, Tab: 280, Enter: 261, Shift: 272, Control: 61, Alt: 40, CapsLock: 56, Escape: 85, Space: 276, PageUp: 251, PageDown: 250, End: 83, Home: 154, LeftArrow: 175, UpArrow: 282, RightArrow: 262, DownArrow: 81, Delete: 79, Meta: 187 }; Object.freeze(KeyboardKey); - -module.exports = { - getWindowsVersion: () => "10.0.0", - setWindowEffect: () => {}, - removeWindowEffect: () => {}, - getIsMaximized: () => false, - flashFrame: () => {}, - clearFlashFrame: () => {}, - showNotification: () => {}, - setProgressBar: () => {}, - clearProgressBar: () => {}, - setOverlayIcon: () => {}, - clearOverlayIcon: () => {}, - KeyboardKey -}; +module.exports = { getWindowsVersion: () => "10.0.0", setWindowEffect: () => {}, removeWindowEffect: () => {}, getIsMaximized: () => false, flashFrame: () => {}, clearFlashFrame: () => {}, showNotification: () => {}, setProgressBar: () => {}, clearProgressBar: () => {}, setOverlayIcon: () => {}, clearOverlayIcon: () => {}, KeyboardKey }; EOF -# Copy local electron if available -if [ ! -z "$LOCAL_ELECTRON" ]; then - echo "Copying local electron to staging area..." - # Ensure the target node_modules directory exists in staging - mkdir -p "$APP_STAGING_DIR/node_modules" - # Copy the entire electron module directory - # Go up one level from the binary path to get the module root - ELECTRON_MODULE_PATH=$(dirname "$LOCAL_ELECTRON")/.. - echo "Copying from $ELECTRON_MODULE_PATH to $APP_STAGING_DIR/node_modules/" - cp -r "$ELECTRON_MODULE_PATH" "$APP_STAGING_DIR/node_modules/" +# Copy the chosen electron installation to the staging area +echo "Copying chosen electron installation to staging area..." +# Ensure the target node_modules directory exists in staging +mkdir -p "$APP_STAGING_DIR/node_modules/" +# Extract the directory name to copy (e.g., "electron") +ELECTRON_DIR_NAME=$(basename "$CHOSEN_ELECTRON_MODULE_PATH") +echo "Copying from $CHOSEN_ELECTRON_MODULE_PATH to $APP_STAGING_DIR/node_modules/" +# Copy the directory itself into node_modules +cp -a "$CHOSEN_ELECTRON_MODULE_PATH" "$APP_STAGING_DIR/node_modules/" # Use cp -a to preserve links/permissions + +# Explicitly set executable permission on the copied electron binary +STAGED_ELECTRON_BIN="$APP_STAGING_DIR/node_modules/$ELECTRON_DIR_NAME/dist/electron" +if [ -f "$STAGED_ELECTRON_BIN" ]; then + echo "Setting executable permission on staged Electron binary: $STAGED_ELECTRON_BIN" + chmod +x "$STAGED_ELECTRON_BIN" +else + echo "Warning: Staged Electron binary not found at expected path: $STAGED_ELECTRON_BIN" fi + echo "✓ app.asar processed and staged in $APP_STAGING_DIR" # Return to the original directory (project root) before calling the packaging script -# We were in $APP_STAGING_DIR which is $WORK_DIR/electron-app -cd .. # Go back from build/electron-app to build/ -cd .. # Go back from build/ to the project root +cd "$PROJECT_ROOT" # --- Call the appropriate packaging script --- +FINAL_OUTPUT_PATH="" # Initialize variable for final path +FINAL_DESKTOP_FILE_PATH="" # Initialize variable for desktop file path + if [ "$BUILD_FORMAT" = "deb" ]; then echo "📦 Calling Debian packaging script for $ARCHITECTURE..." - # Ensure the script is executable chmod +x scripts/build-deb-package.sh - - # Execute the script, passing necessary variables including the detected ARCHITECTURE scripts/build-deb-package.sh \ - "$VERSION" \ - "$ARCHITECTURE" \ - "$WORK_DIR" \ - "$APP_STAGING_DIR" \ - "$PACKAGE_NAME" \ - "$MAINTAINER" \ - "$DESCRIPTION" - - # Check the exit code of the packaging script - if [ $? -ne 0 ]; then - echo "❌ Debian packaging script failed." - exit 1 - fi - - # Capture the final deb file path (using the determined ARCHITECTURE) - # Find the .deb file in the work directory + "$VERSION" "$ARCHITECTURE" "$WORK_DIR" "$APP_STAGING_DIR" \ + "$PACKAGE_NAME" "$MAINTAINER" "$DESCRIPTION" + if [ $? -ne 0 ]; then echo "❌ Debian packaging script failed."; exit 1; fi DEB_FILE=$(find "$WORK_DIR" -maxdepth 1 -name "${PACKAGE_NAME}_${VERSION}_${ARCHITECTURE}.deb" | head -n 1) - echo "✓ Debian Build complete!" if [ -n "$DEB_FILE" ] && [ -f "$DEB_FILE" ]; then - echo "Package created at: $DEB_FILE" + FINAL_OUTPUT_PATH="./${PACKAGE_NAME}_${VERSION}_${ARCHITECTURE}.deb" + mv "$DEB_FILE" "$FINAL_OUTPUT_PATH" + echo "Package created at: $FINAL_OUTPUT_PATH" else echo "Warning: Could not determine final .deb file path from $WORK_DIR for ${ARCHITECTURE}." + FINAL_OUTPUT_PATH="Not Found" fi elif [ "$BUILD_FORMAT" = "appimage" ]; then echo "📦 Calling AppImage packaging script for $ARCHITECTURE..." - # Ensure the script is executable chmod +x scripts/build-appimage.sh - - # Execute the script, passing necessary variables scripts/build-appimage.sh \ - "$VERSION" \ - "$ARCHITECTURE" \ - "$WORK_DIR" \ - "$APP_STAGING_DIR" \ - "$PACKAGE_NAME" \ - "$MAINTAINER" \ - "$DESCRIPTION" # Maintainer/Desc might not be used but passed for consistency - - # Check the exit code of the packaging script - if [ $? -ne 0 ]; then - echo "❌ AppImage packaging script failed." - exit 1 - fi - - # Capture the final AppImage file path (using the determined ARCHITECTURE) - # Find the .AppImage file in the work directory (adjust pattern if needed) + "$VERSION" "$ARCHITECTURE" "$WORK_DIR" "$APP_STAGING_DIR" "$PACKAGE_NAME" + if [ $? -ne 0 ]; then echo "❌ AppImage packaging script failed."; exit 1; fi APPIMAGE_FILE=$(find "$WORK_DIR" -maxdepth 1 -name "${PACKAGE_NAME}-${VERSION}-${ARCHITECTURE}.AppImage" | head -n 1) - - echo "✓ AppImage Build complete! (Placeholder)" + echo "✓ AppImage Build complete!" if [ -n "$APPIMAGE_FILE" ] && [ -f "$APPIMAGE_FILE" ]; then - echo "Package created at: $APPIMAGE_FILE" + FINAL_OUTPUT_PATH="./${PACKAGE_NAME}-${VERSION}-${ARCHITECTURE}.AppImage" + mv "$APPIMAGE_FILE" "$FINAL_OUTPUT_PATH" + echo "Package created at: $FINAL_OUTPUT_PATH" + + # --- Generate .desktop file for AppImage --- + FINAL_DESKTOP_FILE_PATH="./${PACKAGE_NAME}-appimage.desktop" + APPIMAGE_ABS_PATH=$(realpath "$FINAL_OUTPUT_PATH") + echo "📝 Generating .desktop file for AppImage at $FINAL_DESKTOP_FILE_PATH..." + cat > "$FINAL_DESKTOP_FILE_PATH" << EOF +[Desktop Entry] +Name=Claude (AppImage) +Comment=Claude Desktop (AppImage Version $VERSION) +Exec=$APPIMAGE_ABS_PATH %u +Icon=claude-desktop +Type=Application +Terminal=false +Categories=Office;Utility;Network; +MimeType=x-scheme-handler/claude; +StartupWMClass=Claude +X-AppImage-Version=$VERSION +X-AppImage-Name=Claude Desktop (AppImage) +EOF + echo "✓ .desktop file generated." + else - echo "Note: AppImage creation is currently a placeholder." + echo "Warning: Could not determine final .AppImage file path from $WORK_DIR for ${ARCHITECTURE}." + FINAL_OUTPUT_PATH="Not Found" fi fi -# Clean up intermediate files (optional, keep for debugging if needed) -# echo "🧹 Cleaning up intermediate files..." -# rm -rf "$WORK_DIR/lib" "$WORK_DIR/claude.ico" "$WORK_DIR"/*.png "$WORK_DIR/electron-app" "$WORK_DIR/package" "$WORK_DIR/RELEASES" "$WORK_DIR/Setup.exe" "$WORK_DIR/Setup.msi" "$WORK_DIR"/*.nupkg +# --- Set Final Package Ownership --- +if [ "$IS_SUDO" = true ] && [ "$ORIGINAL_USER" != "root" ]; then + if [ "$FINAL_OUTPUT_PATH" != "Not Found" ] && [ -e "$FINAL_OUTPUT_PATH" ]; then + echo "🔒 Setting ownership of $FINAL_OUTPUT_PATH to $ORIGINAL_USER..." + chown "$ORIGINAL_USER":"$(id -gn "$ORIGINAL_USER")" "$FINAL_OUTPUT_PATH" + echo "✓ Ownership set for package." + fi + # Set ownership for generated desktop file as well + if [ -n "$FINAL_DESKTOP_FILE_PATH" ] && [ -e "$FINAL_DESKTOP_FILE_PATH" ]; then + echo "🔒 Setting ownership of $FINAL_DESKTOP_FILE_PATH to $ORIGINAL_USER..." + chown "$ORIGINAL_USER":"$(id -gn "$ORIGINAL_USER")" "$FINAL_DESKTOP_FILE_PATH" + echo "✓ Ownership set for .desktop file." + fi +fi +# --- Cleanup --- +if [ "$PERFORM_CLEANUP" = true ]; then + echo "🧹 Cleaning up intermediate build files in $WORK_DIR..." + # Be careful not to delete the final output package or desktop file + # Keep the final package and desktop file, remove everything else in WORK_DIR + find "$WORK_DIR" -mindepth 1 -maxdepth 1 \ + ! -name "$(basename "$FINAL_OUTPUT_PATH" 2>/dev/null)" \ + ! -name "$(basename "$FINAL_DESKTOP_FILE_PATH" 2>/dev/null)" \ + -exec rm -rf {} + + echo "✓ Cleanup complete." +else + echo "Skipping cleanup of intermediate build files in $WORK_DIR." +fi + +# Clean up temporary package.json if created +if [ "$TEMP_PACKAGE_JSON_CREATED" = true ] && [ -f "$WORK_DIR/package.json" ]; then + echo "Removing temporary package.json from $WORK_DIR..." + rm "$WORK_DIR/package.json" +fi + +echo "✅ Build process finished." exit 0 diff --git a/scripts/build-appimage.sh b/scripts/build-appimage.sh old mode 100644 new mode 100755 index c29d2a4..d7025a5 --- a/scripts/build-appimage.sh +++ b/scripts/build-appimage.sh @@ -25,37 +25,250 @@ mkdir -p "$APPDIR_PATH/usr/share/icons/hicolor/256x256/apps" mkdir -p "$APPDIR_PATH/usr/share/applications" echo "📦 Staging application files into AppDir..." -# Copy the core application files (asar, unpacked resources) -cp -r "$APP_STAGING_DIR/"* "$APPDIR_PATH/usr/lib/" # Copy contents into usr/lib - -# Copy the launcher script (needs modification for AppDir context) -# TODO: Create an AppRun script or adapt the existing launcher - -# Copy icons -echo "🎨 Copying icons..." -ICON_SOURCE_PATH="$WORK_DIR/claude_6_256x256x32.png" # Assuming 256x256 icon exists from previous steps -if [ -f "$ICON_SOURCE_PATH" ]; then - cp "$ICON_SOURCE_PATH" "$APPDIR_PATH/usr/share/icons/hicolor/256x256/apps/${PACKAGE_NAME}.png" - # Also copy to top-level for AppImage icon - cp "$ICON_SOURCE_PATH" "$APPDIR_PATH/${PACKAGE_NAME}.png" -else - echo "Warning: Missing 256x256 icon at $ICON_SOURCE_PATH" +# Copy the core application files (asar, unpacked resources, node_modules if present) +# Explicitly copy required components to ensure hidden files/dirs like .bin are included +if [ -f "$APP_STAGING_DIR/app.asar" ]; then + cp -a "$APP_STAGING_DIR/app.asar" "$APPDIR_PATH/usr/lib/" +fi +if [ -d "$APP_STAGING_DIR/app.asar.unpacked" ]; then + cp -a "$APP_STAGING_DIR/app.asar.unpacked" "$APPDIR_PATH/usr/lib/" +fi +if [ -d "$APP_STAGING_DIR/node_modules" ]; then + echo "Copying node_modules from staging to AppDir..." + cp -a "$APP_STAGING_DIR/node_modules" "$APPDIR_PATH/usr/lib/" fi -# Copy desktop file (needs modification for AppDir context) -echo "📝 Copying desktop file..." -DESKTOP_SOURCE_PATH="$APP_STAGING_DIR/../package/usr/share/applications/${PACKAGE_NAME}.desktop" # Assuming it was created for deb -# TODO: Adapt desktop file Exec= line for AppDir -# cp "$DESKTOP_SOURCE_PATH" "$APPDIR_PATH/" # Copy to top level +# Ensure Electron is bundled within the AppDir for portability +# Check if electron was copied into the staging dir's node_modules +# The actual executable is usually inside the 'dist' directory +BUNDLED_ELECTRON_PATH="$APPDIR_PATH/usr/lib/node_modules/electron/dist/electron" +echo "Checking for executable at: $BUNDLED_ELECTRON_PATH" +if [ ! -x "$BUNDLED_ELECTRON_PATH" ]; then # Check if it exists and is executable + echo "❌ Electron executable not found or not executable in staging area ($BUNDLED_ELECTRON_PATH)." + echo " AppImage requires Electron to be bundled. Ensure the main script copies it correctly." + exit 1 +fi +# Ensure the bundled electron is executable (redundant check, but safe) +chmod +x "$BUNDLED_ELECTRON_PATH" -echo "🚧 AppImage building logic is not fully implemented yet." -echo " - Need to create/adapt AppRun script." -echo " - Need to adapt .desktop file." -echo " - Need to download and use appimagetool." +# --- Create AppRun Script --- +echo "🚀 Creating AppRun script..." +# Note: We use $VERSION and $PACKAGE_NAME from the build script environment here +# They will be embedded into the AppRun script. +DESKTOP_FILE_BASENAME="${PACKAGE_NAME}-${VERSION}.desktop" # Unique name +cat > "$APPDIR_PATH/AppRun" << EOF +#!/bin/bash +set -e -# Example placeholder for final step: -# appimagetool "$APPDIR_PATH" "$WORK_DIR/${PACKAGE_NAME}-${VERSION}-${ARCHITECTURE}.AppImage" +# Find the location of the AppRun script and the AppImage file itself +APPDIR=\$(dirname "\$0") +# Try to get the absolute path of the AppImage file being run +# $APPIMAGE is often set by the AppImage runtime, otherwise try readlink +APPIMAGE_PATH="\${APPIMAGE:-}" +if [ -z "\$APPIMAGE_PATH" ]; then + # Find the AppRun script itself, which should be $0 + # Use readlink -f to get the absolute path, handling symlinks + # Go up one level from AppRun's dir to get the AppImage path (usually) + # This might be fragile if AppRun is not at the root, but it's standard. + APPIMAGE_PATH=\$(readlink -f "\$APPDIR/../$(basename "$APPDIR" .AppDir).AppImage" 2>/dev/null || readlink -f "\$0" 2>/dev/null) + # As a final fallback, just use $0, hoping it's the AppImage path + if [ -z "\$APPIMAGE_PATH" ] || [ ! -f "\$APPIMAGE_PATH" ]; then + APPIMAGE_PATH="\$0" + fi +fi -echo "--- AppImage Build Placeholder Finished ---" +# --- Attempt to Register claude:// URI Scheme Handler --- +register_uri_scheme() { + local desktop_file_basename="$1" + local appimage_exec_path="$2" + local scheme="claude" + + echo "AppRun: Attempting to register x-scheme-handler/$scheme..." + + # Check if necessary tools exist + if ! command -v xdg-mime >/dev/null 2>&1 || ! command -v update-desktop-database >/dev/null 2>&1; then + echo "AppRun: Warning - xdg-mime or update-desktop-database not found. Cannot register URI scheme." + return 1 + fi + + # Define user's local applications directory + local user_apps_dir="\$HOME/.local/share/applications" + mkdir -p "\$user_apps_dir" + + local desktop_file_path="\$user_apps_dir/\$desktop_file_basename" + + echo "AppRun: Creating desktop file at \$desktop_file_path" + # Create the .desktop file + # Use the determined absolute path to the AppImage for Exec + cat > "\$desktop_file_path" << DESKTOP_EOF +[Desktop Entry] +Name=Claude (AppImage $VERSION) +Comment=Claude Desktop (AppImage Version $VERSION) +Exec=$appimage_exec_path %u +Icon=$PACKAGE_NAME +Type=Application +Terminal=false +Categories=Office;Utility;Network; +MimeType=x-scheme-handler/$scheme; +StartupWMClass=Claude +X-AppImage-Version=$VERSION +X-AppImage-Name=Claude Desktop (AppImage) +DESKTOP_EOF + + echo "AppRun: Running xdg-mime default..." + xdg-mime default "\$desktop_file_basename" "x-scheme-handler/\$scheme" + + echo "AppRun: Running update-desktop-database..." + update-desktop-database "\$user_apps_dir" + + echo "AppRun: URI scheme registration attempted." +} + +# Run registration in the background to avoid delaying app start significantly +# Pass the unique desktop file name and the determined AppImage path +register_uri_scheme "$DESKTOP_FILE_BASENAME" "\$APPIMAGE_PATH" & + +# --- End URI Scheme Handler Registration --- + + +# Set up environment variables if needed (e.g., LD_LIBRARY_PATH) +# export LD_LIBRARY_PATH="\$APPDIR/usr/lib:\$LD_LIBRARY_PATH" + +# Detect if Wayland is likely running +IS_WAYLAND=false +if [ ! -z "\$WAYLAND_DISPLAY" ]; then + IS_WAYLAND=true +fi + +# Path to the bundled Electron executable +# Use the path relative to AppRun within the 'electron/dist' module directory +ELECTRON_EXEC="\$APPDIR/usr/lib/node_modules/electron/dist/electron" +APP_PATH="\$APPDIR/usr/lib/app.asar" + +# Base command arguments array +ELECTRON_ARGS=("\$APP_PATH") + +# Add Wayland flags if Wayland is detected +if [ "\$IS_WAYLAND" = true ]; then + echo "AppRun: Wayland detected, adding flags." + ELECTRON_ARGS+=("--enable-features=UseOzonePlatform,WaylandWindowDecorations" "--ozone-platform=wayland") +fi + +# Change to the application resources directory (where app.asar is) +cd "\$APPDIR/usr/lib" || exit 1 + +# Execute Electron with app path, flags, and script arguments passed to AppRun +echo "AppRun: Executing \$ELECTRON_EXEC \${ELECTRON_ARGS[@]} \$@" +exec "\$ELECTRON_EXEC" "\${ELECTRON_ARGS[@]}" "\$@" +EOF +chmod +x "$APPDIR_PATH/AppRun" +echo "✓ AppRun script created with URI scheme registration logic" + +# --- Create Desktop Entry (Bundled inside AppDir) --- +echo "📝 Creating bundled desktop entry..." +# Use package name for icon (AppImage tools expect this) +ICON_NAME=$PACKAGE_NAME +# This is the desktop file *inside* the AppImage, used by tools like appimaged +cat > "$APPDIR_PATH/$PACKAGE_NAME.desktop" << EOF +[Desktop Entry] +Name=Claude +Exec=AppRun %u +Icon=$ICON_NAME +Type=Application +Terminal=false +Categories=Office;Utility;Network; +Comment=Claude Desktop for Linux +MimeType=x-scheme-handler/claude; +StartupWMClass=Claude +X-AppImage-Version=$VERSION +X-AppImage-Name=Claude Desktop +EOF +# Also place it in the standard location for tools like appimaged +cp "$APPDIR_PATH/$PACKAGE_NAME.desktop" "$APPDIR_PATH/usr/share/applications/" +echo "✓ Bundled desktop entry created" + +# --- Copy Icons --- +echo "🎨 Copying icons..." +# Use the 256x256 icon as the main AppImage icon +ICON_SOURCE_PATH="$WORK_DIR/claude_6_256x256x32.png" +if [ -f "$ICON_SOURCE_PATH" ]; then + # Standard location within AppDir + cp "$ICON_SOURCE_PATH" "$APPDIR_PATH/usr/share/icons/hicolor/256x256/apps/${PACKAGE_NAME}.png" + # Top-level icon (used by appimagetool) + cp "$ICON_SOURCE_PATH" "$APPDIR_PATH/${ICON_NAME}.png" + echo "✓ Icon copied" +else + echo "Warning: Missing 256x256 icon at $ICON_SOURCE_PATH. AppImage icon might be missing." +fi + +# --- Get appimagetool --- +APPIMAGETOOL_PATH="" +if command -v appimagetool &> /dev/null; then + APPIMAGETOOL_PATH=$(command -v appimagetool) + echo "✓ Found appimagetool in PATH: $APPIMAGETOOL_PATH" +elif [ -f "$WORK_DIR/appimagetool-x86_64.AppImage" ]; then # Check for specific arch first + APPIMAGETOOL_PATH="$WORK_DIR/appimagetool-x86_64.AppImage" + echo "✓ Found downloaded x86_64 appimagetool: $APPIMAGETOOL_PATH" +elif [ -f "$WORK_DIR/appimagetool-aarch64.AppImage" ]; then # Check for other arch + APPIMAGETOOL_PATH="$WORK_DIR/appimagetool-aarch64.AppImage" + echo "✓ Found downloaded aarch64 appimagetool: $APPIMAGETOOL_PATH" +else + echo "🛠️ Downloading appimagetool..." + # Determine architecture for download URL + TOOL_ARCH="" + case "$ARCHITECTURE" in + "amd64") TOOL_ARCH="x86_64" ;; + "arm64") TOOL_ARCH="aarch64" ;; + *) echo "❌ Unsupported architecture for appimagetool download: $ARCHITECTURE"; exit 1 ;; + esac + + APPIMAGETOOL_URL="https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-${TOOL_ARCH}.AppImage" + APPIMAGETOOL_PATH="$WORK_DIR/appimagetool-${TOOL_ARCH}.AppImage" + + if wget -q -O "$APPIMAGETOOL_PATH" "$APPIMAGETOOL_URL"; then + chmod +x "$APPIMAGETOOL_PATH" + echo "✓ Downloaded appimagetool to $APPIMAGETOOL_PATH" + else + echo "❌ Failed to download appimagetool from $APPIMAGETOOL_URL" + rm -f "$APPIMAGETOOL_PATH" # Clean up partial download + exit 1 + fi +fi + +# --- Build AppImage --- +echo "📦 Building AppImage..." +OUTPUT_FILENAME="${PACKAGE_NAME}-${VERSION}-${ARCHITECTURE}.AppImage" +OUTPUT_PATH="$WORK_DIR/$OUTPUT_FILENAME" + +# Ensure chrome-sandbox has correct permissions within AppDir before building +SANDBOX_PATH="$APPDIR_PATH/usr/lib/node_modules/electron/dist/chrome-sandbox" +if [ -f "$SANDBOX_PATH" ]; then + echo "Setting permissions for bundled chrome-sandbox..." + # No need for chown root:root inside AppDir, just setuid + chmod 4755 "$SANDBOX_PATH" || echo "Warning: Failed to chmod chrome-sandbox" +else + # Try alternative sandbox path sometimes found directly in electron dir + SANDBOX_PATH_ALT="$APPDIR_PATH/usr/lib/node_modules/electron/chrome-sandbox" + if [ -f "$SANDBOX_PATH_ALT" ]; then + echo "Setting permissions for bundled chrome-sandbox (alternative path)..." + chmod 4755 "$SANDBOX_PATH_ALT" || echo "Warning: Failed to chmod chrome-sandbox (alternative path)" + SANDBOX_PATH="$SANDBOX_PATH_ALT" # Update SANDBOX_PATH if found here + else + echo "Warning: Bundled chrome-sandbox not found at standard or alternative paths." + fi +fi + +# Execute appimagetool +# Export ARCH instead of using env +export ARCH="$ARCHITECTURE" +echo "Using ARCH=$ARCH" # Debug output +if "$APPIMAGETOOL_PATH" "$APPDIR_PATH" "$OUTPUT_PATH"; then + echo "✓ AppImage built successfully: $OUTPUT_PATH" +else + echo "❌ Failed to build AppImage using $APPIMAGETOOL_PATH" + exit 1 +fi + +echo "--- AppImage Build Finished ---" exit 0 \ No newline at end of file diff --git a/scripts/build-deb-package.sh b/scripts/build-deb-package.sh index bd6fedb..26c9ab5 100755 --- a/scripts/build-deb-package.sh +++ b/scripts/build-deb-package.sh @@ -153,10 +153,8 @@ echo "✓ Launcher script created" echo "📄 Creating control file..." # Determine dependencies based on whether electron was packaged DEPENDS="nodejs, npm, p7zip-full" # Base dependencies -if [ ! -d "$INSTALL_DIR/lib/$PACKAGE_NAME/node_modules/electron" ]; then - DEPENDS="$DEPENDS, electron" # Add electron if not packaged locally - echo "Adding 'electron' to Depends list as it was not packaged locally." -fi +# Electron is now always packaged locally, so it's not listed as an external dependency. +echo "Electron is packaged locally; not adding to external Depends list." cat > "$PACKAGE_ROOT/DEBIAN/control" << EOF Package: $PACKAGE_NAME @@ -186,23 +184,10 @@ update-desktop-database /usr/share/applications &> /dev/null || true # Set correct permissions for chrome-sandbox if electron is installed globally or locally packaged echo "Setting chrome-sandbox permissions..." SANDBOX_PATH="" -# Check for sandbox in locally packaged electron first +# Electron is always packaged locally now, so only check the local path. LOCAL_SANDBOX_PATH="/usr/lib/$PACKAGE_NAME/node_modules/electron/dist/chrome-sandbox" if [ -f "\$LOCAL_SANDBOX_PATH" ]; then SANDBOX_PATH="\$LOCAL_SANDBOX_PATH" -# If not found locally, try to find it in the path of the globally installed electron -elif command -v electron >/dev/null 2>&1; then - ELECTRON_PATH=\$(command -v electron) - # Try to find sandbox relative to the electron binary path - # Common locations: ../lib/node_modules/electron/dist/ or directly beside electron binary - POTENTIAL_SANDBOX_1="\$(dirname "\$ELECTRON_PATH")/../lib/node_modules/electron/dist/chrome-sandbox" - POTENTIAL_SANDBOX_2="\$(dirname "\$ELECTRON_PATH")/chrome-sandbox" - - if [ -f "\$POTENTIAL_SANDBOX_1" ]; then - SANDBOX_PATH="\$POTENTIAL_SANDBOX_1" - elif [ -f "\$POTENTIAL_SANDBOX_2" ]; then - SANDBOX_PATH="\$POTENTIAL_SANDBOX_2" - fi fi if [ -n "\$SANDBOX_PATH" ] && [ -f "\$SANDBOX_PATH" ]; then @@ -211,7 +196,7 @@ if [ -n "\$SANDBOX_PATH" ] && [ -f "\$SANDBOX_PATH" ]; then chmod 4755 "\$SANDBOX_PATH" || echo "Warning: Failed to chmod chrome-sandbox" echo "Permissions set for \$SANDBOX_PATH" else - echo "Warning: chrome-sandbox binary not found (checked local package and global path). Sandbox may not function correctly." + echo "Warning: chrome-sandbox binary not found in local package at \$LOCAL_SANDBOX_PATH. Sandbox may not function correctly." fi exit 0