From 3b4e536a669d1ce240e34983b50ea05a1bdf8808 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Sun, 6 Sep 2026 09:29:35 +0000 Subject: [PATCH 1/2] install.sh: banner, step-by-step output and highlighted next steps Co-Authored-By: Daniel Trugman --- install.sh | 120 +++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 103 insertions(+), 17 deletions(-) diff --git a/install.sh b/install.sh index 14364e6..794f848 100755 --- a/install.sh +++ b/install.sh @@ -11,6 +11,7 @@ # REQUESTY_HOME Data directory (default: $HOME/.requesty) # REQUESTY_INSTALL_DIR Directory for the binary (default: $REQUESTY_HOME/bin) # REQUESTY_VERSION Release tag to install (default: latest) +# NO_COLOR Disable colored output # # A marker file is created in the temporary directory while installing and # removed once the installation completes, so an interrupted run leaves a trace. @@ -30,15 +31,70 @@ BINARY="requesty" MARKER_BEGIN="# >>> requesty cli installer >>>" MARKER_END="# <<< requesty cli installer <<<" +# Colors are used when stdout is a terminal and NO_COLOR is unset. The script +# is normally piped into sh, but stdout still points at the terminal. +setup_style() { + BOLD="" DIM="" RED="" GREEN="" YELLOW="" CYAN="" RESET="" + if [ -t 1 ] && [ -z "${NO_COLOR:-}" ] && [ "${TERM:-dumb}" != "dumb" ]; then + BOLD="$(printf '\033[1m')" + DIM="$(printf '\033[2m')" + RED="$(printf '\033[31m')" + GREEN="$(printf '\033[32m')" + YELLOW="$(printf '\033[33m')" + CYAN="$(printf '\033[36m')" + RESET="$(printf '\033[0m')" + fi + + TICK="*" CROSS="x" BAR="|" + case "${LC_ALL:-${LC_CTYPE:-${LANG:-}}}" in + *UTF-8* | *utf8* | *UTF8* | *utf-8*) + TICK="✓" CROSS="✗" BAR="│" + ;; + esac +} + +banner() { + printf '%s' "$CYAN" + cat <<'EOF' + + ____ _ + | _ \ ___ __ _ _ _ ___ ___| |_ _ _ + | |_) / _ \/ _` | | | |/ _ \/ __| __| | | | + | _ < __/ (_| | |_| | __/\__ \ |_| |_| | + |_| \_\___|\__, |\__,_|\___||___/\__|\__, | + |_| |___/ +EOF + printf '%s\n' "$RESET" + printf ' %sRequesty CLI installer%s\n\n' "$BOLD" "$RESET" +} + +# step prints a completed installation step. +step() { + printf ' %s%s%s %s\n' "$GREEN" "$TICK" "$RESET" "$1" +} + +warn() { + printf ' %s!%s %s\n' "$YELLOW" "$RESET" "$1" +} + info() { - printf '%s\n' "$1" + printf ' %s\n' "$1" +} + +# action prints one line inside the highlighted "next steps" block. +action() { + printf ' %s%s%s %s\n' "$CYAN" "$BAR" "$RESET" "$1" +} + +command_hint() { + printf '%s%s%s' "$BOLD" "$1" "$RESET" } fail() { - printf 'error: %s\n' "$1" >&2 + printf '\n %s%s error:%s %s\n' "$RED" "$CROSS" "$RESET" "$1" >&2 if [ -f "${MARKER_FILE:-}" ]; then - printf 'the installation did not complete, %s was left behind\n' "$MARKER_FILE" >&2 + printf ' %sthe installation did not complete, %s was left behind%s\n' "$DIM" "$MARKER_FILE" "$RESET" >&2 fi exit 1 @@ -103,13 +159,14 @@ verify_checksum() { elif command -v shasum >/dev/null 2>&1; then checksum="$(shasum -a 256 "$dir/$file" | cut -d ' ' -f 1)" else - info "Neither sha256sum nor shasum is available, skipping checksum verification" + warn "Neither sha256sum nor shasum is available, skipping checksum verification" return 0 fi expected="$(grep " $file\$" "$dir/checksums.txt" | cut -d ' ' -f 1)" [ -n "$expected" ] || fail "$file is missing from checksums.txt" [ "$checksum" = "$expected" ] || fail "checksum mismatch for $file: expected $expected, got $checksum" + step "Verified checksum" } # latest_version resolves the tag the "latest" release points at, so the @@ -134,9 +191,9 @@ install_release() { tmp="$(mktemp -d)" trap 'rm -rf "$tmp"' EXIT INT TERM - info "Downloading $archive" download "$base/$archive" "$tmp/$archive" download "$base/checksums.txt" "$tmp/checksums.txt" + step "Downloaded $archive" verify_checksum "$tmp" "$archive" tar -xzf "$tmp/$archive" -C "$tmp" @@ -147,6 +204,7 @@ install_release() { # Replace via rename so a running binary is never written into. mv -f "$tmp/$BINARY" "$INSTALL_DIR/$BINARY" + step "Installed $BINARY to $INSTALL_DIR/$BINARY" mkdir -p "$REQUESTY_HOME" } @@ -182,8 +240,8 @@ configure_path() { esac if [ ! -f "$profile" ]; then - info "Could not configure PATH because $profile does not exist. Add this line to your shell configuration:" - info " $line" + PATH_LINE="$line" + warn "Could not configure PATH because $profile does not exist" return 0 fi @@ -201,21 +259,43 @@ configure_path() { PROFILE="$profile" PROFILE_UPDATED=true + step "Added $INSTALL_DIR to PATH in $PROFILE" +} + +# short_path replaces a leading $HOME with ~ so commands are easier to read. +short_path() { + case "$1" in + "$HOME"/*) printf '~%s\n' "${1#"$HOME"}" ;; + *) printf '%s\n' "$1" ;; + esac } summary() { - info "Installed $BINARY $VERSION to $INSTALL_DIR/$BINARY" + printf '\n %s%s%s %s%s %s is ready%s\n\n' "$GREEN" "$TICK" "$RESET" "$BOLD" "$BINARY" "$VERSION" "$RESET" if [ -f "$REQUESTY_HOME/config.json" ]; then - info "Kept your configuration in $REQUESTY_HOME/config.json" + info "${DIM}Kept your configuration in $REQUESTY_HOME/config.json${RESET}" + printf '\n' fi - if [ "${PROFILE_UPDATED:-false}" = true ]; then - info "Added $INSTALL_DIR to PATH in $PROFILE" - info "Run 'source $PROFILE' or open a new terminal, then run '$BINARY'" - else - info "Run '$BINARY' to get started" + printf ' %s%s%s %sNext steps%s\n' "$CYAN" "$BAR" "$RESET" "$BOLD" "$RESET" + action "" + + n=1 + if [ -n "${PATH_LINE:-}" ]; then + action "$n. Add this line to your shell configuration:" + action " $(command_hint "$PATH_LINE")" + n=$((n + 1)) + elif [ "${PROFILE_UPDATED:-false}" = true ]; then + action "$n. Reload your shell (or open a new terminal):" + action " $(command_hint "source $(short_path "$PROFILE")")" + n=$((n + 1)) fi + + action "$n. Start the CLI:" + action " $(command_hint "$BINARY")" + action "" + printf '\n' } main() { @@ -257,12 +337,16 @@ main() { esac done + setup_style + banner + require_command uname require_command tar RECEIPT="$REQUESTY_HOME/version" OS="$(detect_os)" ARCH="$(detect_arch)" + step "Detected $OS/$ARCH" # A leftover marker file is how a user, or we, can tell that a previous run # died halfway through. @@ -271,20 +355,22 @@ main() { if [ "$VERSION" = "latest" ]; then VERSION="$(latest_version)" + step "Resolved latest release: $VERSION" fi installed="$(installed_version)" if [ "$FORCE" = false ] && [ "$installed" = "$VERSION" ] && [ -x "$INSTALL_DIR/$BINARY" ]; then - info "$BINARY $VERSION is already installed in $INSTALL_DIR" + step "$BINARY $VERSION is already installed in $INSTALL_DIR" configure_path rm -f "$MARKER_FILE" + summary exit 0 fi if [ -n "$installed" ]; then - info "Upgrading $BINARY from $installed to $VERSION" + info "${DIM}Upgrading $BINARY from $installed to $VERSION${RESET}" else - info "Installing $BINARY $VERSION" + info "${DIM}Installing $BINARY $VERSION${RESET}" fi install_release From ed941d8fdc77ceae03b11ea6709ca270c281e8e8 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Sun, 6 Sep 2026 09:55:28 +0000 Subject: [PATCH 2/2] install.sh: drop PROFILE/PATH_LINE globals, pass summary inputs explicitly Co-Authored-By: Daniel Trugman --- install.sh | 120 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 68 insertions(+), 52 deletions(-) diff --git a/install.sh b/install.sh index 794f848..3e2b75e 100755 --- a/install.sh +++ b/install.sh @@ -209,46 +209,38 @@ install_release() { mkdir -p "$REQUESTY_HOME" } -# configure_path adds the install directory to PATH in the configuration file -# of the current shell, inside a marker block so upgrades stay idempotent. -configure_path() { - [ "$MODIFY_PATH" = true ] || return 0 - - case ":$PATH:" in - *":$INSTALL_DIR:"*) return 0 ;; - esac - - shell_name="$(basename "${SHELL:-sh}")" - case "$shell_name" in - fish) - profile="${XDG_CONFIG_HOME:-$HOME/.config}/fish/config.fish" - line="fish_add_path \"$INSTALL_DIR\"" - ;; - zsh) - profile="${ZDOTDIR:-$HOME}/.zshrc" - line="export PATH=\"$INSTALL_DIR:\$PATH\"" - ;; +# shell_profile prints the configuration file of the current shell. +shell_profile() { + case "$1" in + fish) echo "${XDG_CONFIG_HOME:-$HOME/.config}/fish/config.fish" ;; + zsh) echo "${ZDOTDIR:-$HOME}/.zshrc" ;; bash) - profile="$HOME/.bashrc" - [ -f "$profile" ] || [ ! -f "$HOME/.bash_profile" ] || profile="$HOME/.bash_profile" - line="export PATH=\"$INSTALL_DIR:\$PATH\"" - ;; - *) - profile="$HOME/.profile" - line="export PATH=\"$INSTALL_DIR:\$PATH\"" + if [ ! -f "$HOME/.bashrc" ] && [ -f "$HOME/.bash_profile" ]; then + echo "$HOME/.bash_profile" + else + echo "$HOME/.bashrc" + fi ;; + *) echo "$HOME/.profile" ;; esac +} - if [ ! -f "$profile" ]; then - PATH_LINE="$line" - warn "Could not configure PATH because $profile does not exist" - return 0 - fi +# path_line prints the line that puts the install directory on PATH. +path_line() { + case "$1" in + fish) echo "fish_add_path \"$INSTALL_DIR\"" ;; + *) echo "export PATH=\"$INSTALL_DIR:\$PATH\"" ;; + esac +} - if grep -F "$MARKER_BEGIN" "$profile" >/dev/null 2>&1; then - PROFILE="$profile" - return 0 - fi +# configure_path appends the PATH line to the profile inside a marker block so +# upgrades stay idempotent. It returns 0 only when the profile was modified. +configure_path() { + profile="$1" + line="$2" + + [ -f "$profile" ] || return 1 + grep -F "$MARKER_BEGIN" "$profile" >/dev/null 2>&1 && return 1 { echo "" @@ -256,10 +248,6 @@ configure_path() { echo "$line" echo "$MARKER_END" } >>"$profile" - - PROFILE="$profile" - PROFILE_UPDATED=true - step "Added $INSTALL_DIR to PATH in $PROFILE" } # short_path replaces a leading $HOME with ~ so commands are easier to read. @@ -270,7 +258,12 @@ short_path() { esac } +# summary prints the final report. The optional pair of arguments is a PATH +# related instruction and the command that goes with it. summary() { + path_instruction="${1:-}" + path_command="${2:-}" + printf '\n %s%s%s %s%s %s is ready%s\n\n' "$GREEN" "$TICK" "$RESET" "$BOLD" "$BINARY" "$VERSION" "$RESET" if [ -f "$REQUESTY_HOME/config.json" ]; then @@ -282,13 +275,9 @@ summary() { action "" n=1 - if [ -n "${PATH_LINE:-}" ]; then - action "$n. Add this line to your shell configuration:" - action " $(command_hint "$PATH_LINE")" - n=$((n + 1)) - elif [ "${PROFILE_UPDATED:-false}" = true ]; then - action "$n. Reload your shell (or open a new terminal):" - action " $(command_hint "source $(short_path "$PROFILE")")" + if [ -n "$path_instruction" ]; then + action "$n. $path_instruction" + action " $(command_hint "$path_command")" n=$((n + 1)) fi @@ -298,6 +287,37 @@ summary() { printf '\n' } +# finish handles PATH configuration and prints the summary. +finish() { + rm -f "$MARKER_FILE" + + if [ "$MODIFY_PATH" != true ]; then + summary + return 0 + fi + + case ":$PATH:" in + *":$INSTALL_DIR:"*) + summary + return 0 + ;; + esac + + shell_name="$(basename "${SHELL:-sh}")" + profile="$(shell_profile "$shell_name")" + line="$(path_line "$shell_name")" + + if [ ! -f "$profile" ]; then + warn "Could not configure PATH because $profile does not exist" + summary "Add this line to your shell configuration:" "$line" + elif configure_path "$profile" "$line"; then + step "Added $INSTALL_DIR to PATH in $profile" + summary "Reload your shell (or open a new terminal):" "source $(short_path "$profile")" + else + summary "Reload your shell (or open a new terminal):" "source $(short_path "$profile")" + fi +} + main() { set -eu @@ -361,9 +381,7 @@ main() { installed="$(installed_version)" if [ "$FORCE" = false ] && [ "$installed" = "$VERSION" ] && [ -x "$INSTALL_DIR/$BINARY" ]; then step "$BINARY $VERSION is already installed in $INSTALL_DIR" - configure_path - rm -f "$MARKER_FILE" - summary + finish exit 0 fi @@ -376,9 +394,7 @@ main() { install_release printf '%s\n' "$VERSION" >"$RECEIPT" - configure_path - rm -f "$MARKER_FILE" - summary + finish } main "$@"