Files
tty7/.github/scripts/bundle-linux.sh
T
l0ng-ai 0c9f4baa3a fix(cli): make the PATH install reversible, honest, and safe to migrate
Follow-up on the review of #277. Seven fixes, no change to what the feature
is for.

An AppImage copy is now claimed with a marker file instead of being inferred
from "am I an AppImage right now". Keying off the runtime meant that a user
who moved from the AppImage to the tarball hit their own copy, read it as
somebody else's binary, and never got another install for as long as that file
sat there.

The Windows uninstaller takes {app} back out of HKCU\Environment. Nothing did
before: the entry is written by the app at runtime, so Inno never knew it
existed and every uninstall grew the user's PATH by one dead entry. Unix has no
equivalent hook and still leaves its symlink behind; that is now stated in the
module docs rather than left to be discovered.

An occupied candidate directory no longer ends the scan, and every platform now
reports whether the install actually wins the lookup. `Occupied` on
/opt/homebrew/bin used to mean giving up while ~/.local/bin sat free, and
Windows — which appends to PATH and so never collides — reported `Installed`
even when an existing tty7 earlier on PATH kept beating it. A new
`InstalledShadowed` names the winner.

`cargo run --release` no longer repoints the developer's real tty7 at a build
tree. `cfg!(debug_assertions)` only covered the debug half of that.

The Windows registry PATH is read, matched, and written as UTF-16 throughout.
It went through `to_string_lossy` before, so a value the registry holds but
Rust cannot represent as a String would have been written back with U+FFFD in
place of its characters — the exact PATH corruption the surrounding code is
careful to avoid.

Two tests mutated $HOME and $PATH while the rest of the binary's tests ran
beside them, and src/ui/home.rs mutates $HOME too. `candidate_dirs` takes home
as a parameter, `place` takes its mode, and the PATH-joining and registry-
joining rules are pure functions — so no test in this module touches the
environment any more. 5 tests become 11, and the Windows joining logic is
covered on every platform.

Also: the config flag reaches Settings → About and both features docs instead
of being config.json-only, startup reads config.json once instead of twice, and
the CLI's strip failure warns like its sibling instead of being swallowed.
2026-07-31 16:49:22 +08:00

48 lines
1.9 KiB
Bash
Executable File

#!/bin/bash
# Usage: bundle-linux.sh <target-triple> <arch-label>
# Package the release binary into a tarball:
# dist/tty7-<version>-linux-<arch>.tar.gz
#
# Fonts and the app icon are embedded via include_bytes!, so the archive is the
# stripped executable plus a sibling completions/ dir (loaded at runtime — see
# terminal::signature) and the license/readme. gpui's x11/wayland backends still
# dynamic-link the usual system libs at runtime — see the README's Linux
# build-dependency list — so this is an unsigned build, not a
# portable AppImage.
set -euo pipefail
TARGET="$1"
ARCH="$2"
# Anchored on `= "` — see the note in bundle-macos.sh: the root manifest leads
# with `version.workspace = true`, which a bare `^version` match would return
# verbatim as the "version" and bake into every asset filename.
VERSION="$(grep -m1 '^version = "' Cargo.toml | sed -E 's/.*"([^"]+)".*/\1/')"
if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+ ]]; then
echo "bundle-linux: could not read a version from Cargo.toml (got '$VERSION')" >&2
exit 1
fi
NAME="tty7-${VERSION}-linux-${ARCH}"
STAGE="dist/${NAME}"
rm -rf dist
mkdir -p "$STAGE"
cp "target/${TARGET}/release/tty7-app" "$STAGE/tty7-app"
chmod +x "$STAGE/tty7-app"
# The CLI ships beside the GUI, which symlinks it onto PATH at launch (see
# core::cli_install) by resolving it relative to its own executable.
cp "target/${TARGET}/release/tty7" "$STAGE/tty7"
chmod +x "$STAGE/tty7"
# Release builds keep symbols (thin LTO, no profile strip); drop them here so
# the archive isn't ~100 MB of debug info.
strip "$STAGE/tty7-app" || echo "⚠️ strip unavailable — shipping unstripped binary"
strip "$STAGE/tty7" || echo "⚠️ strip unavailable — shipping unstripped CLI"
mkdir -p "$STAGE/completions"
cp assets/completions/*.json "$STAGE/completions/"
cp LICENSE "$STAGE/LICENSE"
cp README.md "$STAGE/README.md"
tar -C dist -czf "dist/${NAME}.tar.gz" "$NAME"
rm -rf "$STAGE"
echo "✅ dist/${NAME}.tar.gz"