%define _enable_debug_packages 0
%define debug_package %{nil}
%define __strip /bin/true
%global __brp_strip %{nil}
%global __brp_strip_comment_note %{nil}
%global __brp_strip_static_archive %{nil}
Name: eagle
Version: 4.0.3
Release: 1%{?dist}
Summary: Digital asset manager for designers (Linux Port)
License: Proprietary
URL: https://eagle.cool
# Everything the build needs must be declared here. An SRPM only carries
# files listed as SourceN, so anything merely copied into the source
# directory by .copr/Makefile disappears when COPR rebuilds from the SRPM in
# a fresh chroot. patches/ is a directory, so it travels as a tarball.
Source0: ensure-extracted-app.sh
Source1: extract-installer.py
Source2: eagle-unpacked-layout.json
Source3: patch.js
Source4: ensure-electron.sh
Source5: eagle.metainfo.xml
Source6: patches.tar.gz
BuildRequires: python3, curl, bash, unzip
Requires: python3, zstd, xdotool, ffmpeg, dbus-tools
%description
Eagle helps you collect, search, and organize your design files in one place.
%prep
%build
# Ensure app payload exists (extract if missing, e.g. COPR or mock chroots)
SRC_DIR="%{_sourcedir}"
if [ ! -d "${SRC_DIR}/app" ] || [ ! -f "${SRC_DIR}/app/run.jsc" ]; then
SCRIPT=""
for candidate in \
"${SRC_DIR}/ensure-extracted-app.sh" \
"${SRC_DIR}/packaging/ensure-extracted-app.sh" \
"$(dirname ${SRC_DIR})/packaging/ensure-extracted-app.sh"; do
if [ -f "$candidate" ]; then
SCRIPT="$candidate"
break
fi
done
if [ -n "$SCRIPT" ]; then
bash "$SCRIPT"
fi
fi
%install
rm -rf %{buildroot}
mkdir -p %{buildroot}/usr/share/eagle
mkdir -p %{buildroot}/usr/bin
mkdir -p %{buildroot}/usr/share/applications
mkdir -p %{buildroot}/usr/share/icons/hicolor/512x512/apps
mkdir -p %{buildroot}/usr/share/pixmaps
mkdir -p %{buildroot}/lib/udev/rules.d
app=""
PATCH_JS=""
PATCHES_DIR=""
for candidate in \
"%{_sourcedir}/app" \
"%{_sourcedir}/../app" \
"$(dirname %{_sourcedir})/app" \
"$(dirname $(dirname %{_sourcedir}))/app"; do
if [ -d "$candidate" ] && [ -f "$candidate/run.jsc" ]; then
app="$candidate"
break
fi
done
# app/ is far too large to travel as a Source, so it is extracted in %build
# and located here. Everything else comes from a SourceN macro, which rpm
# guarantees is present whether we build locally or from an SRPM in a clean
# COPR chroot.
if [ -z "$app" ]; then
echo "[ERROR] Could not locate the extracted app/ payload"
exit 1
fi
cp -r "${app}" %{buildroot}/usr/share/eagle/
# Bundle the Electron runtime rather than bootstrapping it via npx at first
# launch (npm >= 12 / Node >= 26 break that path).
bash %{SOURCE4} %{buildroot}/usr/share/eagle/electron
cp %{SOURCE3} %{buildroot}/usr/share/eagle/patch.js
# patch.js is a one-line shim around patches/index.js, so patches/ is just as
# mandatory -- without it the package installs cleanly and then crashes on
# launch.
tar -xzf %{SOURCE6} -C %{buildroot}/usr/share/eagle/
if [ ! -f %{buildroot}/usr/share/eagle/patches/index.js ]; then
echo "[ERROR] patches/ did not unpack from %{SOURCE6}"
exit 1
fi
cp "${app}/assets/icon.png" %{buildroot}/usr/share/icons/hicolor/512x512/apps/eagle.png
cp "${app}/assets/icon.png" %{buildroot}/usr/share/pixmaps/eagle.png
# AppStream metadata so software centres (Discover, GNOME Software) show the
# app with a description, categories and release history rather than a bare
# desktop entry.
mkdir -p %{buildroot}/usr/share/metainfo
cp %{SOURCE5} %{buildroot}/usr/share/metainfo/cool.eagle.Eagle.metainfo.xml
cat << 'EOF' > %{buildroot}/usr/bin/eagle
#!/bin/sh
export GTK_USE_PORTAL=1
export NODE_PATH="/usr/share/eagle/app/node_modules:${NODE_PATH:-}"
PATCH="/usr/share/eagle/patch.js"
APP="/usr/share/eagle/app"
# Prefer the Electron bundled with this package. Bootstrapping via npx is
# unreliable on current distros (npm >= 12 blocks install scripts; Node >= 26
# breaks Electron's extract-zip), so it is only a fallback now.
ELECTRON_BIN=""
for candidate in /usr/share/eagle/electron/electron /app/electron/electron; do
if [ -x "${candidate}" ]; then
ELECTRON_BIN="${candidate}"
break
fi
done
if [ -n "${ELECTRON_BIN}" ]; then
:
elif command -v electron22 >/dev/null 2>&1; then
ELECTRON_BIN="$(command -v electron22)"
elif command -v npx >/dev/null 2>&1; then
# Prime the npx cache before healing it. npm >= 12 blocks postinstall
# scripts via its allowScripts policy and --ignore-scripts=false no longer
# overrides that, so this first call may leave electron unpacked but
# without its binary. The heal loop below then runs install.js directly.
# Without priming, a cold cache has nothing to heal and the launch fails.
npx --yes --ignore-scripts=false electron@22.3.7 --version >/dev/null 2>&1 || true
for cache_dir in "${HOME}/.npm/_npx/"*/node_modules/electron; do
if [ -d "${cache_dir}" ] && [ ! -f "${cache_dir}/path.txt" ]; then
if [ -f "${cache_dir}/install.js" ]; then
(cd "${cache_dir}" && node install.js 2>/dev/null || true)
fi
if [ ! -f "${cache_dir}/path.txt" ]; then
rm -rf "${cache_dir%/*/*}" 2>/dev/null || true
fi
fi
done
ELECTRON_BIN="npx --yes --ignore-scripts=false electron@22.3.7"
elif command -v electron >/dev/null 2>&1; then
ELECTRON_BIN="$(command -v electron)"
else
echo "[ERROR] No Electron runtime or nodejs/npm found. Please install nodejs & npm."
exit 1
fi
exec ${ELECTRON_BIN} -r "${PATCH}" "${APP}" --no-sandbox "$@"
EOF
chmod +x %{buildroot}/usr/bin/eagle
cat << 'EOF' > %{buildroot}/usr/share/applications/eagle.desktop
[Desktop Entry]
Categories=Graphics;Utility;
Comment=Digital asset manager for designers
Exec=eagle %u
Icon=eagle
MimeType=application/x-eaglepack;application/x-eagleplugin;application/x-eaglelibrary;x-scheme-handler/eagle;
Name=Eagle
StartupNotify=true
StartupWMClass=Eagle
Terminal=false
Type=Application
Version=1.5
EOF
mkdir -p %{buildroot}/usr/share/mime/packages
cat << 'EOF' > %{buildroot}/usr/share/mime/packages/eagle.xml
Eagle Pack
Eagle Plugin
Eagle Library
EOF
cat << 'EOF' > %{buildroot}/lib/udev/rules.d/99-eagle-dmi.rules
SUBSYSTEM=="dmi", KERNEL=="product_uuid", MODE="0444"
EOF
%files
/usr/bin/eagle
/usr/share/eagle/
/usr/share/applications/eagle.desktop
/usr/share/icons/hicolor/512x512/apps/eagle.png
/usr/share/pixmaps/eagle.png
/usr/share/mime/packages/eagle.xml
/usr/share/metainfo/cool.eagle.Eagle.metainfo.xml
/lib/udev/rules.d/99-eagle-dmi.rules
%changelog
* Wed Sep 02 2026 Naitrate - 4.0.3-1
- Fix the main window failing to open on a clean install: the native-module
interceptor matched substrings, so Eagle's own default-preferences.js was
replaced by a stub and createWindow threw
- Declare patches, ensure-electron.sh and the metainfo as rpm Sources, so
they survive a rebuild from the SRPM in a clean COPR chroot
- Ship AppStream metadata and screenshots for software centres
* Tue Sep 01 2026 Naitrate - 4.0.2-1
- Migrate compatibility layer from stubs.js to modular patch.js + patches/
- Require patches/ at build time; a missing tree now fails instead of
producing a package that crashes on launch
- Restore main-window minimize/maximize/close controls
- Correct anti-tamper digests for the app_patches XDG screen-capture build
- Bundle the Electron runtime at build time instead of bootstrapping it via
npx at first launch, which fails on npm >= 12 (install scripts blocked by
allowScripts) and Node >= 26 (extract-zip silently fails)
- Drop nodejs and npm from the runtime requirements
* Mon Aug 31 2026 Naitrate - 4.0.0-1
- Initial Fedora / RHEL package for Eagle Linux Port