diff --git a/catalog/gcloud.json b/catalog/gcloud.json new file mode 100644 index 0000000..a4679f2 --- /dev/null +++ b/catalog/gcloud.json @@ -0,0 +1,10 @@ +{ + "name": "gcloud", + "category": "platform", + "install_method": "gcloud_installer", + "description": "Google Cloud CLI for managing Google Cloud resources", + "homepage": "https://cloud.google.com/sdk/gcloud", + "binary_name": "gcloud", + "skip_upstream": true, + "notes": "Installed via Google Cloud SDK installer; self-updates with 'gcloud components update'" +} diff --git a/catalog/golangci-lint.json b/catalog/golangci-lint.json index fadb128..1085109 100644 --- a/catalog/golangci-lint.json +++ b/catalog/golangci-lint.json @@ -6,6 +6,7 @@ "homepage": "https://github.com/golangci/golangci-lint", "github_repo": "golangci/golangci-lint", "binary_name": "golangci-lint", + "target_dir": "go_bin", "download_url_template": "https://github.com/golangci/golangci-lint/releases/download/{version}/golangci-lint-{version_nov}-linux-{arch}.tar.gz", "arch_map": { "x86_64": "amd64", diff --git a/catalog/google-workspace-cli.json b/catalog/google-workspace-cli.json new file mode 100644 index 0000000..0e633ea --- /dev/null +++ b/catalog/google-workspace-cli.json @@ -0,0 +1,14 @@ +{ + "name": "google-workspace-cli", + "category": "platform", + "install_method": "github_release_binary", + "description": "Google Workspace command-line interface", + "homepage": "https://github.com/googleworkspace/cli", + "github_repo": "googleworkspace/cli", + "binary_name": "gws", + "download_url_template": "https://github.com/googleworkspace/cli/releases/download/{version}/gws-{arch}-unknown-linux-gnu.tar.gz", + "arch_map": { + "x86_64": "x86_64", + "aarch64": "aarch64" + } +} diff --git a/catalog/gosec.json b/catalog/gosec.json index 5010e22..b5b138b 100644 --- a/catalog/gosec.json +++ b/catalog/gosec.json @@ -6,6 +6,7 @@ "homepage": "https://github.com/securego/gosec", "github_repo": "securego/gosec", "binary_name": "gosec", + "target_dir": "go_bin", "download_url_template": "https://github.com/securego/gosec/releases/download/{version}/gosec_{version_nov}_linux_{arch}.tar.gz", "arch_map": { "x86_64": "amd64", diff --git a/catalog/tree.json b/catalog/tree.json index 1651dcf..3424127 100644 --- a/catalog/tree.json +++ b/catalog/tree.json @@ -6,6 +6,7 @@ "homepage": "https://github.com/Old-Man-Programmer/tree", "github_repo": "Old-Man-Programmer/tree", "binary_name": "tree", + "version_flag": "--version", "script": "install_tree.sh", "tags": [ "file-utils" diff --git a/catalog/vhs.json b/catalog/vhs.json new file mode 100644 index 0000000..b00ee27 --- /dev/null +++ b/catalog/vhs.json @@ -0,0 +1,15 @@ +{ + "name": "vhs", + "category": "general", + "install_method": "github_release_binary", + "description": "CLI home video recorder - write terminal GIFs as code", + "homepage": "https://github.com/charmbracelet/vhs", + "github_repo": "charmbracelet/vhs", + "binary_name": "vhs", + "target_dir": "go_bin", + "download_url_template": "https://github.com/charmbracelet/vhs/releases/download/{version}/vhs_{version_nov}_Linux_{arch}.tar.gz", + "arch_map": { + "x86_64": "x86_64", + "aarch64": "arm64" + } +} diff --git a/scripts/install_go.sh b/scripts/install_go.sh index 15f2928..e14e353 100755 --- a/scripts/install_go.sh +++ b/scripts/install_go.sh @@ -70,11 +70,11 @@ install_go() { echo "Downloading Go ${FULL_VERSION} SDK..." "$FULL_BINARY" download || true - # Create symlink from go1.24 -> go1.24.12 for convenience + # Update symlink from go1.24 -> go1.24.12 GOBIN="$(go env GOPATH)/bin" - if [ -x "$GOBIN/$FULL_BINARY" ] && [ ! -e "$GOBIN/$BINARY" ]; then + if [ -x "$GOBIN/$FULL_BINARY" ]; then ln -sf "$FULL_BINARY" "$GOBIN/$BINARY" 2>/dev/null || true - echo "Created symlink: $BINARY -> $FULL_BINARY" + echo "Updated symlink: $BINARY -> $FULL_BINARY" fi fi else diff --git a/scripts/installers/gcloud_installer.sh b/scripts/installers/gcloud_installer.sh new file mode 100755 index 0000000..2a6381c --- /dev/null +++ b/scripts/installers/gcloud_installer.sh @@ -0,0 +1,72 @@ +#!/usr/bin/env bash +# Google Cloud CLI installer +set -euo pipefail + +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +. "$DIR/lib/install_strategy.sh" + +TOOL="${1:-gcloud}" +CATALOG_FILE="$DIR/../catalog/$TOOL.json" + +if [ ! -f "$CATALOG_FILE" ]; then + echo "Error: Catalog file not found: $CATALOG_FILE" >&2 + exit 1 +fi + +BINARY_NAME="$(jq -r '.binary_name' "$CATALOG_FILE")" +GCLOUD_SDK="$HOME/google-cloud-sdk" +GCLOUD_BIN="$GCLOUD_SDK/bin" + +# Ensure SDK bin is in PATH for detection and post-install +if [ -d "$GCLOUD_BIN" ]; then + export PATH="$GCLOUD_BIN:$PATH" +fi + +# Get current version +before="$(command -v "$BINARY_NAME" >/dev/null 2>&1 && "$BINARY_NAME" version 2>/dev/null | head -1 || true)" + +if command -v "$BINARY_NAME" >/dev/null 2>&1; then + # Already installed - use built-in update (quiet) + "$BINARY_NAME" components update --quiet 2>&1 | tail -1 +elif [ -d "$GCLOUD_SDK" ]; then + # SDK directory exists but gcloud not functional - try to recover + if [ -x "$GCLOUD_BIN/$BINARY_NAME" ]; then + "$GCLOUD_BIN/$BINARY_NAME" components update --quiet 2>&1 | tail -1 + else + echo "[$TOOL] Error: $GCLOUD_SDK exists but gcloud not found in $GCLOUD_BIN" >&2 + echo "[$TOOL] Remove $GCLOUD_SDK and re-run to reinstall" >&2 + exit 1 + fi +else + # Fresh install via Google Cloud SDK installer (quiet) + TMP="$(mktemp -d)" + INSTALLER_URL="https://dl.google.com/dl/cloudsdk/channels/rapid/google-cloud-sdk.tar.gz" + echo "[$TOOL] Downloading Google Cloud SDK..." + curl -fsSL "$INSTALLER_URL" -o "$TMP/google-cloud-sdk.tar.gz" + tar -xzf "$TMP/google-cloud-sdk.tar.gz" -C "$HOME" + rm -rf "$TMP" + + # Run install script quietly (no prompts, no PATH modification, no usage reporting) + "$GCLOUD_SDK/install.sh" --quiet --usage-reporting false --command-completion false --path-update false 2>&1 | tail -1 + + export PATH="$GCLOUD_BIN:$PATH" +fi + +# Symlink gcloud (and gsutil, bq) into user bin so it's in PATH without SDK-specific setup +BIN_DIR="$(get_install_dir "$BINARY_NAME")" +mkdir -p "$BIN_DIR" 2>/dev/null || true +for cmd in gcloud gsutil bq; do + if [ -x "$GCLOUD_BIN/$cmd" ]; then + ln -sf "$GCLOUD_BIN/$cmd" "$BIN_DIR/$cmd" + fi +done + +# Report +after="$(command -v "$BINARY_NAME" >/dev/null 2>&1 && "$BINARY_NAME" version 2>/dev/null | head -1 || true)" +path="$(command -v "$BINARY_NAME" 2>/dev/null || true)" +printf "[%s] before: %s\n" "$TOOL" "${before:-}" +printf "[%s] after: %s\n" "$TOOL" "${after:-}" +if [ -n "$path" ]; then printf "[%s] path: %s\n" "$TOOL" "$path"; fi + +# Refresh snapshot after successful installation +refresh_snapshot "$TOOL" diff --git a/scripts/lib/install_strategy.sh b/scripts/lib/install_strategy.sh index 418cafa..89a990a 100755 --- a/scripts/lib/install_strategy.sh +++ b/scripts/lib/install_strategy.sh @@ -10,6 +10,46 @@ get_install_dir() { local prefix="${PREFIX:-$HOME/.local}" local bin_dir="" + # Check for per-tool target_dir override from catalog + if [ -n "$tool_name" ] && [ -n "${CATALOG_FILE:-}" ] && [ -f "${CATALOG_FILE:-}" ]; then + local target_dir + target_dir="$(jq -r '.target_dir // empty' "$CATALOG_FILE" 2>/dev/null || true)" + if [ -n "$target_dir" ]; then + case "$target_dir" in + go_bin) + # Go binary convention: update in place, fresh install to best-guess GOPATH/bin + local current_path + current_path="$(command -v "$tool_name" 2>/dev/null || true)" + if [ -n "$current_path" ]; then + # Already installed - keep it where it is + echo "$(dirname "$current_path")" + else + # Fresh install - best-guess Go bin folder: + # 1. GOPATH/bin if GOPATH is set + # 2. `go env GOPATH`/bin if go is available + # 3. ~/go/bin (Go's default GOPATH) + if [ -n "${GOPATH:-}" ]; then + echo "$GOPATH/bin" + elif command -v go >/dev/null 2>&1; then + echo "$(go env GOPATH 2>/dev/null)/bin" + else + echo "$HOME/go/bin" + fi + fi + return + ;; + *) + # Generic target_dir: expand ~ and $HOME + target_dir="${target_dir/#\~/$HOME}" + target_dir="${target_dir//\$\{HOME\}/$HOME}" + target_dir="${target_dir//\$HOME/$HOME}" + echo "$target_dir" + return + ;; + esac + fi + fi + case "$strategy" in CURRENT) # Keep tool where it is currently installed