Initial development by Claude

This commit is contained in:
2025-12-09 22:40:12 +02:00
parent 652e09ccdf
commit 6479b24195
6 changed files with 1280 additions and 1 deletions

169
build_app.sh Normal file
View File

@@ -0,0 +1,169 @@
#!/bin/bash
#
# Build script for Path Juggler
# Creates a standalone macOS .app bundle with ad-hoc code signing
#
set -e
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
APP_NAME="Path Juggler"
BUNDLE_ID="com.pathjuggler.app"
VENV_DIR="$SCRIPT_DIR/.build_venv"
DIST_DIR="$SCRIPT_DIR/dist"
echo "=== Path Juggler - Build Script ==="
echo ""
# Check for Python 3
if ! command -v python3 &> /dev/null; then
echo "Error: python3 is required but not found"
exit 1
fi
PYTHON_VERSION=$(python3 -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')
echo "Using Python $PYTHON_VERSION"
# Create virtual environment
echo ""
echo "=== Creating virtual environment ==="
if [ -d "$VENV_DIR" ]; then
echo "Removing existing build environment..."
rm -rf "$VENV_DIR"
fi
python3 -m venv "$VENV_DIR"
source "$VENV_DIR/bin/activate"
# Upgrade pip
echo ""
echo "=== Installing build dependencies ==="
pip install --upgrade pip --quiet
pip install pyinstaller watchdog --quiet
echo "Installed:"
pip list | grep -E "(pyinstaller|watchdog)"
# Create PyInstaller spec file for more control
echo ""
echo "=== Creating build configuration ==="
cat > "$SCRIPT_DIR/path_juggler.spec" << 'SPEC'
# -*- mode: python ; coding: utf-8 -*-
import sys
from pathlib import Path
block_cipher = None
a = Analysis(
['path_juggler_gui.py'],
pathex=[],
binaries=[],
datas=[],
hiddenimports=[
'watchdog.observers',
'watchdog.observers.fsevents',
'watchdog.events',
],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False,
)
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
exe = EXE(
pyz,
a.scripts,
[],
exclude_binaries=True,
name='Path Juggler',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
console=False, # No terminal window
disable_windowed_traceback=False,
argv_emulation=True, # Important for macOS
target_arch=None,
codesign_identity=None,
entitlements_file=None,
)
coll = COLLECT(
exe,
a.binaries,
a.zipfiles,
a.datas,
strip=False,
upx=True,
upx_exclude=[],
name='Path Juggler',
)
app = BUNDLE(
coll,
name='Path Juggler.app',
icon=None,
bundle_identifier='com.pathjuggler.app',
info_plist={
'CFBundleName': 'Path Juggler',
'CFBundleDisplayName': 'Path Juggler',
'CFBundleVersion': '1.0.0',
'CFBundleShortVersionString': '1.0.0',
'NSHighResolutionCapable': True,
'LSMinimumSystemVersion': '10.13.0',
'NSAppleEventsUsageDescription': 'Path Juggler needs to access files.',
},
)
SPEC
# Build the app
echo ""
echo "=== Building application ==="
pyinstaller --clean --noconfirm path_juggler.spec
# Sign the app with ad-hoc signature
echo ""
echo "=== Signing application (ad-hoc) ==="
APP_PATH="$DIST_DIR/Path Juggler.app"
if [ -d "$APP_PATH" ]; then
# Remove any existing signatures
codesign --remove-signature "$APP_PATH" 2>/dev/null || true
# Sign with ad-hoc signature (dash means ad-hoc)
codesign --force --deep --sign - "$APP_PATH"
echo "Signature applied"
codesign -dv "$APP_PATH" 2>&1 | head -5
else
echo "Error: App bundle not found at $APP_PATH"
exit 1
fi
# Clean up
echo ""
echo "=== Cleaning up ==="
rm -rf "$SCRIPT_DIR/build"
rm -f "$SCRIPT_DIR/path_juggler.spec"
deactivate
rm -rf "$VENV_DIR"
echo ""
echo "=== Build complete ==="
echo ""
echo "Application created at:"
echo " $APP_PATH"
echo ""
echo "To install, drag the app to your Applications folder:"
echo " open \"$DIST_DIR\""
echo ""
echo "Note: On first launch, you may need to right-click and select 'Open'"
echo "to bypass Gatekeeper since this is a self-signed app."