diff --git a/cmd/gui/package.json b/cmd/gui/package.json index dedb7d7..ab53e97 100644 --- a/cmd/gui/package.json +++ b/cmd/gui/package.json @@ -22,7 +22,9 @@ "productName": "HomeAgent", "linux": { "target": [ - "deb" + "deb", + "rpm", + "AppImage" ], "category": "Utility", "icon": "icon.svg" diff --git a/cmd/waiter/rawmode_linux.go b/cmd/waiter/rawmode_linux.go deleted file mode 100644 index 692d931..0000000 --- a/cmd/waiter/rawmode_linux.go +++ /dev/null @@ -1,25 +0,0 @@ -//go:build linux - -package main - -import ( - "syscall" - "unsafe" -) - -func setRawMode(fd int) (func(), error) { - var old termios - if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), TCGETS, uintptr(unsafe.Pointer(&old))); err != 0 { - return func() {}, err - } - new := old - new.Lflag &^= ICANON | ECHO | ISIG - new.Cc[VMIN] = 1 - new.Cc[VTIME] = 0 - if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), TCSETS, uintptr(unsafe.Pointer(&new))); err != 0 { - return func() {}, err - } - return func() { - syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), TCSETS, uintptr(unsafe.Pointer(&old))) - }, nil -} diff --git a/go.mod b/go.mod index a824350..1fa4375 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,6 @@ require ( require github.com/yanyiwu/gojieba v1.4.7 -require gitcode.com/JianFeeeee/homeagent-sdk v0.0.0-20260708004841-e9bdcf9304b0 // direct +require gitcode.com/JianFeeeee/homeagent-sdk v0.7.1 replace gitcode.com/JianFeeeee/homeagent-sdk => E:\program\homeagent\homeagentsdk diff --git a/go.sum b/go.sum index 4057385..de5505a 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= -github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +gitcode.com/JianFeeeee/homeagent-sdk v0.7.1 h1:2XEtUgV200uOqbGGEiKT5QyBmZ5aIfNiwm/Ozrm9AOg= +gitcode.com/JianFeeeee/homeagent-sdk v0.7.1/go.mod h1:G48Rgpw9ReTkCf0qBHf50jb5CSeNR2c4OWcgcEm0plo= github.com/mattn/go-sqlite3 v1.14.48 h1:7XHIgl0a8HwOaiK4E47ozLkST78rR9+OtNGx27D/TFs= github.com/mattn/go-sqlite3 v1.14.48/go.mod h1:6JTjA44L93a0QCyJef5YvlPoKXntQPjzWv5gtm9sB6w= github.com/yanyiwu/gojieba v1.4.7 h1:2YkXELcYLTE0SJetq6xv4MjpEikWga6VpFn4jIFFQ/k= diff --git a/package/linux/deb/control-client b/package/linux/deb/control-client new file mode 100644 index 0000000..9362119 --- /dev/null +++ b/package/linux/deb/control-client @@ -0,0 +1,18 @@ +Package: homeagent-client +Version: VERSION_PLACEHOLDER +Architecture: ARCH_PLACEHOLDER +Maintainer: HomeAgent Team +Installed-Size: INSTALLED_SIZE_PLACEHOLDER +Depends: libc6 (>= 2.28) +Section: utils +Priority: optional +Homepage: https://github.com/trueagent/HomeAgent +Description: HomeAgent Client (CLI + GUI, no daemon) + HomeAgent is a personal AI home assistant that integrates + large language models with system automation. + . + This package includes the client components: + - waiter: command-line client + - homeagent-gui: desktop graphical interface + . + This variant connects to a remote HomeAgent server. diff --git a/package/linux/deb/control-full b/package/linux/deb/control-full new file mode 100644 index 0000000..9cac46b --- /dev/null +++ b/package/linux/deb/control-full @@ -0,0 +1,17 @@ +Package: homeagent-full +Version: VERSION_PLACEHOLDER +Architecture: ARCH_PLACEHOLDER +Maintainer: HomeAgent Team +Installed-Size: INSTALLED_SIZE_PLACEHOLDER +Depends: libc6 (>= 2.28) +Section: utils +Priority: optional +Homepage: https://github.com/trueagent/HomeAgent +Description: HomeAgent Full Installation (Daemon + CLI + GUI) + HomeAgent is a personal AI home assistant that integrates + large language models with system automation. + . + This package includes the full suite: + - homed: the core daemon (background service) + - waiter: command-line client + - homeagent-gui: desktop graphical interface diff --git a/package/linux/deb/control-server b/package/linux/deb/control-server new file mode 100644 index 0000000..c15c858 --- /dev/null +++ b/package/linux/deb/control-server @@ -0,0 +1,16 @@ +Package: homeagent-server +Version: VERSION_PLACEHOLDER +Architecture: ARCH_PLACEHOLDER +Maintainer: HomeAgent Team +Installed-Size: INSTALLED_SIZE_PLACEHOLDER +Depends: libc6 (>= 2.28) +Section: utils +Priority: optional +Homepage: https://github.com/trueagent/HomeAgent +Description: HomeAgent Server (Daemon + CLI, no GUI) + HomeAgent is a personal AI home assistant that integrates + large language models with system automation. + . + This package includes the server components: + - homed: the core daemon (background service) + - waiter: command-line client diff --git a/package/linux/deb/postinst b/package/linux/deb/postinst new file mode 100755 index 0000000..eaf50f1 --- /dev/null +++ b/package/linux/deb/postinst @@ -0,0 +1,25 @@ +#!/bin/sh +set -e + +SERVICE_NAME="homeagent" +SERVICE_FILE="/etc/systemd/system/${SERVICE_NAME}.service" +HOMED_BIN="/usr/bin/homed" +DATA_DIR="/var/lib/homeagent" + +case "$1" in + configure) + if [ -f "$HOMED_BIN" ]; then + mkdir -p "$DATA_DIR" + + if [ -f "$SERVICE_FILE" ]; then + systemctl daemon-reload 2>/dev/null || true + fi + fi + ;; + abort-upgrade|abort-remove|abort-deconfigure) + ;; + *) + ;; +esac + +exit 0 diff --git a/package/linux/deb/prerm b/package/linux/deb/prerm new file mode 100755 index 0000000..18f4546 --- /dev/null +++ b/package/linux/deb/prerm @@ -0,0 +1,19 @@ +#!/bin/sh +set -e + +SERVICE_NAME="homeagent" + +case "$1" in + remove|deconfigure) + if command -v systemctl >/dev/null 2>&1; then + systemctl stop "$SERVICE_NAME" 2>/dev/null || true + systemctl disable "$SERVICE_NAME" 2>/dev/null || true + fi + ;; + upgrade) + ;; + *) + ;; +esac + +exit 0 diff --git a/package/linux/homeagent.spec b/package/linux/homeagent.spec new file mode 100644 index 0000000..1873be5 --- /dev/null +++ b/package/linux/homeagent.spec @@ -0,0 +1,111 @@ +# HomeAgent RPM Spec +# Build: rpmbuild -ba homeagent.spec +# +# Define variant at build time: +# rpmbuild -ba --define "variant full" homeagent.spec +# rpmbuild -ba --define "variant server" homeagent.spec +# rpmbuild -ba --define "variant client" homeagent.spec + +%define _prefix /usr +%define _bindir %{_prefix}/bin +%define _unitdir %{_prefix}/lib/systemd/system +%define _datadir %{_prefix}/share/homeagent +%define _varlibdir /var/lib/homeagent + +%if %{undefined variant} +%define variant full +%endif + +Name: homeagent-%{variant} +Version: %{_version} +Release: 1%{?dist} +Summary: HomeAgent - Personal AI Home Assistant +License: Proprietary +URL: https://github.com/trueagent/HomeAgent +Group: System Environment/Daemons +BuildArch: %{_arch} + +%if "%{variant}" == "full" || "%{variant}" == "server" +Requires: systemd +%endif +%if "%{variant}" == "full" +Requires: libX11, libxcb, libdrm, mesa-libGL, nss, nspr, atk, at-spi2-atk, cairo, cups-libs, pango, gtk3 +%endif +%if "%{variant}" == "client" +Requires: libX11, libxcb, libdrm, mesa-libGL, nss, nspr, atk, at-spi2-atk, cairo, cups-libs, pango, gtk3 +%endif + +%description +HomeAgent is a personal AI home assistant that integrates large language +models with system automation. + +%if "%{variant}" == "full" +This package includes the full suite: homed (daemon), waiter (CLI), +and homeagent-gui (desktop GUI). +%else +%if "%{variant}" == "server" +This package includes the server components: homed (daemon) and waiter (CLI). +%else +%if "%{variant}" == "client" +This package includes the client components: waiter (CLI) and +homeagent-gui (desktop GUI). Connects to a remote HomeAgent server. +%endif +%endif +%endif + +%install +mkdir -p %{buildroot}%{_bindir} +mkdir -p %{buildroot}%{_unitdir} +mkdir -p %{buildroot}%{_varlibdir} + +%if "%{variant}" == "full" || "%{variant}" == "server" +install -m 755 %{_sourcedir}/homed %{buildroot}%{_bindir}/homed +install -m 644 %{_sourcedir}/homeagent.service %{buildroot}%{_unitdir}/homeagent.service +%endif + +%if "%{variant}" == "full" || "%{variant}" == "client" +install -m 755 %{_sourcedir}/waiter %{buildroot}%{_bindir}/waiter +%endif + +%if "%{variant}" == "full" || "%{variant}" == "client" +mkdir -p %{buildroot}%{_datadir}/homeagent-gui +cp -r %{_sourcedir}/homeagent-gui-linux-*/* %{buildroot}%{_datadir}/homeagent-gui/ +%endif + +%files +%defattr(-,root,root,-) + +%if "%{variant}" == "full" || "%{variant}" == "server" +%{_bindir}/homed +%{_unitdir}/homeagent.service +%dir %{_varlibdir} +%endif + +%if "%{variant}" == "full" || "%{variant}" == "client" +%{_bindir}/waiter +%endif + +%if "%{variant}" == "full" || "%{variant}" == "client" +%dir %{_datadir}/homeagent-gui +%{_datadir}/homeagent-gui/* +%endif + +%post +%if "%{variant}" == "full" || "%{variant}" == "server" +mkdir -p %{_varlibdir} +%systemd_post homeagent.service +%endif + +%preun +%if "%{variant}" == "full" || "%{variant}" == "server" +%systemd_preun homeagent.service +%endif + +%postun +%if "%{variant}" == "full" || "%{variant}" == "server" +%systemd_postun_with_restart homeagent.service +%endif + +%changelog +* Mon Jul 20 2026 HomeAgent Team - %{version}-1 +- Initial Linux packaging diff --git a/package/package-linux.sh b/package/package-linux.sh new file mode 100755 index 0000000..1cfd6ad --- /dev/null +++ b/package/package-linux.sh @@ -0,0 +1,376 @@ +#!/usr/bin/env bash +set -euo pipefail + +PROJECT_ROOT="$(cd "$(dirname "$0")/.." && pwd)" +BUILD_DIR="${PROJECT_ROOT}/build" +DIST_DIR="${PROJECT_ROOT}/dist/linux" +VERSION="${VERSION:-$(git -C "$PROJECT_ROOT" describe --tags --dirty 2>/dev/null || echo "0.7.1")}" +PACKAGE_ROOT="${PROJECT_ROOT}/package/linux" +GO="${GO:-$(command -v go 2>/dev/null || echo "/home/jianf/go1.26.5/go/bin/go")}" + +ARCH="${1:-amd64}" # amd64 or arm64 +ACTION="${2:-all}" # all, build, deb, tar, rpm + +DEB_ARCH="$ARCH" +RPM_ARCH="$ARCH" +TAR_ARCH="$ARCH" +case "$ARCH" in + amd64) DEB_ARCH="amd64"; RPM_ARCH="x86_64"; TAR_ARCH="amd64" ;; + arm64) DEB_ARCH="arm64"; RPM_ARCH="aarch64"; TAR_ARCH="arm64" ;; + *) echo "Unknown arch: $ARCH (use amd64 or arm64)"; exit 1 ;; +esac + +echo "=== HomeAgent Linux Packager ===" +echo "Version: $VERSION" +echo "Arch: $ARCH" +echo "" + +# ---- prepare go.mod for Linux build: replace Windows SDK path with local clone ---- +prepare_gomod() { + local gomod="$PROJECT_ROOT/go.mod" + local sdk_clone="/tmp/homeagent-sdk" + local patched=0 + + if grep -q 'replace gitcode.com/JianFeeeee/homeagent-sdk' "$gomod"; then + echo ">>> Updating go.mod: replacing Windows SDK path with local clone..." + if [ ! -d "$sdk_clone" ]; then + echo ">>> Cloning SDK to $sdk_clone..." + git clone git@gitcode.com:JianFeeeee/homeagent-sdk.git "$sdk_clone" 2>/dev/null || \ + git clone https://gitcode.com/JianFeeeee/homeagent-sdk.git "$sdk_clone" 2>/dev/null || true + fi + if [ -d "$sdk_clone" ]; then + sed -i.bak "s|^replace gitcode.com/JianFeeeee/homeagent-sdk => .*|replace gitcode.com/JianFeeeee/homeagent-sdk => ${sdk_clone}|" "$gomod" + patched=1 + else + echo "WARNING: Cannot clone SDK. Build may fail." + fi + fi + return $patched +} + +restore_gomod() { + if [ -f "$PROJECT_ROOT/go.mod.bak" ]; then + echo ">>> Restoring original go.mod..." + mv "$PROJECT_ROOT/go.mod.bak" "$PROJECT_ROOT/go.mod" + fi +} + +# ---- temporarily move .syso files (Windows COFF objects) for Linux builds ---- +hide_syso() { + echo ">>> Hiding .syso files (Windows-only object files)..." + for dir in homed waiter; do + if [ -f "$PROJECT_ROOT/cmd/$dir/$dir.syso" ]; then + mv "$PROJECT_ROOT/cmd/$dir/$dir.syso" "$PROJECT_ROOT/cmd/$dir/$dir.syso.bak" + fi + done +} + +restore_syso() { + for dir in homed waiter; do + if [ -f "$PROJECT_ROOT/cmd/$dir/$dir.syso.bak" ]; then + mv "$PROJECT_ROOT/cmd/$dir/$dir.syso.bak" "$PROJECT_ROOT/cmd/$dir/$dir.syso" + fi + done +} + +# ensure both are always restored on exit +restore_all() { restore_gomod; restore_syso; } +trap restore_all EXIT + +# ---- build Go binaries via existing build.sh ---- +build_go() { + echo ">>> Building Go binaries for linux/$ARCH..." + + prepare_gomod || true + hide_syso + + bash "$PROJECT_ROOT/package/build.sh" "linux/$ARCH" "homed" 2>&1 || { + echo "WARNING: homed build failed (CGO/sqlite3 issue). Server/full packages may be incomplete." + } + bash "$PROJECT_ROOT/package/build.sh" "linux/$ARCH" "waiter" 2>&1 || { + echo "WARNING: waiter build failed." + } + + local suffix="linux_${ARCH}" + local homed_bin="$BUILD_DIR/homed_$suffix" + local waiter_bin="$BUILD_DIR/waiter_$suffix" + + if [ ! -f "$homed_bin" ]; then + echo "ERROR: homed binary not found at $homed_bin" + exit 1 + fi + if [ ! -f "$waiter_bin" ]; then + echo "ERROR: waiter binary not found at $waiter_bin" + exit 1 + fi + + echo " homed: $homed_bin ($(du -h "$homed_bin" | cut -f1))" + echo " waiter: $waiter_bin ($(du -h "$waiter_bin" | cut -f1))" + echo "" +} + +# ---- build GUI (manual directory assembly, avoids electron-packager network issues) ---- +build_gui() { + local gui_dir="$PROJECT_ROOT/cmd/gui" + local gui_out="$BUILD_DIR/homeagent-gui-linux-${TAR_ARCH}" + + if [ -d "$gui_out" ]; then + echo ">>> GUI already built at $gui_out (delete to rebuild)" + return + fi + + echo ">>> Building GUI directory for linux/$ARCH..." + + if [ ! -d "$gui_dir/node_modules" ]; then + echo " npm install..." + (cd "$gui_dir" && npm install --production) + fi + + local electron_dir="$gui_dir/node_modules/electron/dist" + if [ ! -f "$electron_dir/electron" ]; then + echo " WARNING: electron binary not found at $electron_dir. GUI will be skipped." + return + fi + + mkdir -p "$gui_out/resources/app/node_modules" + mkdir -p "$gui_out/resources/app/renderer" + + # copy electron runtime (binary + shared libs) + cp -r "$electron_dir"/* "$gui_out/" 2>/dev/null + rm -f "$gui_out/resources/default_app.asar" 2>/dev/null + + # copy app source + cp "$gui_dir/main.js" "$gui_out/resources/app/" + cp "$gui_dir/preload.js" "$gui_out/resources/app/" + cp "$gui_dir/package.json" "$gui_out/resources/app/" + cp "$gui_dir/renderer/index.html" "$gui_out/resources/app/renderer/" + cp "$gui_dir/renderer/app.js" "$gui_out/resources/app/renderer/" + cp "$gui_dir/renderer/style.css" "$gui_out/resources/app/renderer/" 2>/dev/null || true + cp "$gui_dir/renderer/mascot.svg" "$gui_out/resources/app/renderer/" 2>/dev/null || true + + # production node_modules for app + if [ -d "$gui_dir/node_modules" ]; then + for mod in icojs; do + if [ -d "$gui_dir/node_modules/$mod" ]; then + cp -r "$gui_dir/node_modules/$mod" "$gui_out/resources/app/node_modules/" + fi + done + fi + + # create desktop entry and symlink + cat > "$gui_out/resources/app/homeagent-gui.desktop" << DESKTOP +[Desktop Entry] +Name=HomeAgent +Comment=HomeAgent Desktop GUI +Exec=$gui_out/homeagent-gui +Terminal=false +Type=Application +Categories=Utility; +Icon=$gui_out/resources/app/icon.svg +DESKTOP + + # create launcher script + cat > "$gui_out/homeagent-gui" << 'LAUNCHER' +#!/bin/sh +DIR="$(cd "$(dirname "$0")" && pwd)" +exec "$DIR/electron" "$DIR/resources/app" "$@" +LAUNCHER + chmod +x "$gui_out/homeagent-gui" + chmod +x "$gui_out/electron" + + echo " GUI built: $gui_out ($(du -sh "$gui_out" | cut -f1))" + echo "" +} + +# ---- stage files for a variant ---- +stage_variant() { + local variant="$1" + local staging="$2" + local suffix="linux_${ARCH}" + + echo ">>> Staging $variant..." + + mkdir -p "$staging/usr/bin" + mkdir -p "$staging/etc/systemd/system" + mkdir -p "$staging/var/lib/homeagent" + + case "$variant" in + full) + cp "$BUILD_DIR/homed_$suffix" "$staging/usr/bin/homed" + cp "$BUILD_DIR/waiter_$suffix" "$staging/usr/bin/waiter" + cp "$PROJECT_ROOT/deploy/homeagent.service" "$staging/etc/systemd/system/homeagent.service" + stage_gui "$staging" + ;; + server) + cp "$BUILD_DIR/homed_$suffix" "$staging/usr/bin/homed" + cp "$BUILD_DIR/waiter_$suffix" "$staging/usr/bin/waiter" + cp "$PROJECT_ROOT/deploy/homeagent.service" "$staging/etc/systemd/system/homeagent.service" + ;; + client) + cp "$BUILD_DIR/waiter_$suffix" "$staging/usr/bin/waiter" + stage_gui "$staging" + ;; + esac + + chmod 755 "$staging/usr/bin/"* 2>/dev/null || true + echo " OK" +} + +stage_gui() { + local staging="$1" + local gui_src="$BUILD_DIR/homeagent-gui-linux-${TAR_ARCH}" + if [ -d "$gui_src" ]; then + mkdir -p "$staging/usr/lib/homeagent-gui" + cp -r "$gui_src"/* "$staging/usr/lib/homeagent-gui/" + cat > "$staging/usr/bin/homeagent-gui" << 'SCRIPT' +#!/bin/sh +exec /usr/lib/homeagent-gui/homeagent-gui "$@" +SCRIPT + chmod 755 "$staging/usr/bin/homeagent-gui" + else + echo " WARNING: GUI not built, skipping GUI staging" + fi +} + +# ---- create .deb ---- +build_deb() { + local variant="$1" + local staging="$2" + local deb_dir="${DIST_DIR}/deb" + mkdir -p "$deb_dir" + + local pkg_name="homeagent-${variant}_${VERSION}_${DEB_ARCH}.deb" + local deb_root + deb_root="$(mktemp -d)" + + mkdir -p "$deb_root/DEBIAN" + + local control_file="$PACKAGE_ROOT/deb/control-${variant}" + local installed_size_kb + installed_size_kb=$(du -sk "$staging" | cut -f1) + + sed -e "s/VERSION_PLACEHOLDER/$VERSION/g" \ + -e "s/ARCH_PLACEHOLDER/$DEB_ARCH/g" \ + -e "s/INSTALLED_SIZE_PLACEHOLDER/$installed_size_kb/g" \ + "$control_file" > "$deb_root/DEBIAN/control" + + if [ -f "$PACKAGE_ROOT/deb/postinst" ]; then + cp "$PACKAGE_ROOT/deb/postinst" "$deb_root/DEBIAN/postinst" + chmod 755 "$deb_root/DEBIAN/postinst" + fi + + if [ -f "$PACKAGE_ROOT/deb/prerm" ]; then + cp "$PACKAGE_ROOT/deb/prerm" "$deb_root/DEBIAN/prerm" + chmod 755 "$deb_root/DEBIAN/prerm" + fi + + cp -r "$staging"/* "$deb_root/" 2>/dev/null || true + + echo ">>> Building .deb: $pkg_name" + fakeroot dpkg-deb --build "$deb_root" "$deb_dir/$pkg_name" 2>/dev/null || \ + dpkg-deb --build "$deb_root" "$deb_dir/$pkg_name" 2>&1 + rm -rf "$deb_root" + echo " Created: $deb_dir/$pkg_name ($(du -h "$deb_dir/$pkg_name" | cut -f1))" +} + +# ---- create .tar.gz ---- +build_tar() { + local variant="$1" + local staging="$2" + local tar_dir="${DIST_DIR}/tar" + mkdir -p "$tar_dir" + + local archive_name="homeagent-${variant}_${VERSION}_linux_${TAR_ARCH}.tar.gz" + local archive_dir="homeagent-${variant}" + + echo ">>> Building .tar.gz: $archive_name" + (cd "$staging" && tar czf "$tar_dir/$archive_name" --transform "s|^\.|${archive_dir}|" .) + echo " Created: $tar_dir/$archive_name ($(du -h "$tar_dir/$archive_name" | cut -f1))" +} + +# ---- create .rpm (via fpm if available) ---- +build_rpm() { + local variant="$1" + local staging="$2" + local rpm_dir="${DIST_DIR}/rpm" + mkdir -p "$rpm_dir" + + local pkg_name="homeagent-${variant}-${VERSION}-1.${RPM_ARCH}.rpm" + + if command -v fpm &>/dev/null; then + echo ">>> Building .rpm via fpm: $pkg_name" + fpm -s dir -t rpm \ + -n "homeagent-${variant}" \ + -v "$VERSION" \ + --iteration 1 \ + -a "$RPM_ARCH" \ + --description "HomeAgent ${variant^} package" \ + --url "https://github.com/trueagent/HomeAgent" \ + --license "Proprietary" \ + -C "$staging" \ + -p "$rpm_dir/$pkg_name" \ + . + echo " Created: $rpm_dir/$pkg_name" + else + echo " SKIP .rpm: fpm not installed. Install it with: gem install fpm" + echo " Alternatively, build RPM on Fedora/RHEL using:" + echo " rpmbuild -ba package/linux/homeagent.spec" + fi +} + +# ---- main ---- +main() { + local target_arch="$ARCH" + + mkdir -p "$BUILD_DIR" + + case "$ACTION" in + all|build) + build_go + build_gui + ;; + esac + + if [ "$ACTION" = "build" ]; then + echo "" + echo "=== Build complete. Binaries in $BUILD_DIR ===" + exit 0 + fi + + mkdir -p "$DIST_DIR" + + for variant in full server client; do + echo "" + echo "==============================================" + echo " Packaging: $variant" + echo "==============================================" + + local staging + staging=$(mktemp -d) + stage_variant "$variant" "$staging" + + case "$ACTION" in + all|deb) build_deb "$variant" "$staging" ;; + esac + + case "$ACTION" in + all|tar) build_tar "$variant" "$staging" ;; + esac + + case "$ACTION" in + all|rpm) build_rpm "$variant" "$staging" ;; + esac + + rm -rf "$staging" + done + + echo "" + echo "=== Done! Packages in: $DIST_DIR ===" + echo "" + echo "Summary:" + find "$DIST_DIR" -type f -name "*.deb" -o -name "*.tar.gz" -o -name "*.rpm" 2>/dev/null | sort | while read -r f; do + echo " $(du -h "$f" | cut -f1) $f" + done +} + +main