|
16 | 16 | # aicommit -m|--model <name> # optional model override for the chosen provider |
17 | 17 | # aicommit --pull # auto pull origin branch with --no-rebase before commit |
18 | 18 | # aicommit -r|--release [bump|ver] # release: patch, minor, major, X.Y.Z, or auto |
| 19 | +# aicommit --update # update aicommit to the latest release |
19 | 20 | # aicommit -h|--help # show this help |
20 | 21 | # aicommit -v|-V|--version # show version information |
21 | 22 | # ---------------------------------------------------------------------- |
@@ -91,6 +92,7 @@ show_help() { |
91 | 92 | echo -e " ${C_GREEN}--pull${C_RESET} Auto pull from origin with --no-rebase before committing." |
92 | 93 | echo -e " ${C_GREEN}--release${C_RESET}, ${C_GREEN}-r${C_RESET} ${C_DIM}[type]${C_RESET} Create a release. Type: patch, minor, major, or X.Y.Z." |
93 | 94 | echo -e " ${C_DIM}If omitted, AI auto-detects the bump type.${C_RESET}" |
| 95 | + echo -e " ${C_GREEN}--update${C_RESET} Update aicommit to the latest release from GitHub." |
94 | 96 | echo -e " ${C_GREEN}-v${C_RESET}, ${C_GREEN}-V${C_RESET}, ${C_GREEN}--version${C_RESET} Show version information." |
95 | 97 | echo -e " ${C_GREEN}-h${C_RESET}, ${C_GREEN}--help${C_RESET} Show this help message." |
96 | 98 | echo |
@@ -199,6 +201,87 @@ show_help() { |
199 | 201 | echo -e " aicommit ${C_GREEN}--provider${C_RESET} anthropic ${C_GREEN}--model${C_RESET} claude-3-5-sonnet-latest" |
200 | 202 | } |
201 | 203 |
|
| 204 | +# ---------- Self-update ---------- |
| 205 | +GITHUB_REPO="apertacodex/aicommit" |
| 206 | +GITHUB_RAW_URL="https://raw.githubusercontent.com/${GITHUB_REPO}/main/aicommit" |
| 207 | +GITHUB_API_URL="https://api.github.com/repos/${GITHUB_REPO}/releases/latest" |
| 208 | + |
| 209 | +self_update() { |
| 210 | + echo -e "${C_CYAN}${C_BOLD}Checking for updates...${C_RESET}" |
| 211 | + |
| 212 | + # Fetch latest release version from GitHub |
| 213 | + local latest_version |
| 214 | + latest_version=$(curl -sfL "$GITHUB_API_URL" | jq -r '.tag_name // empty' 2>/dev/null | sed 's/^v//') |
| 215 | + |
| 216 | + if [[ -z "$latest_version" ]]; then |
| 217 | + echo -e "${C_RED}Error: Could not fetch the latest release from GitHub.${C_RESET}" |
| 218 | + echo -e "${C_DIM}Check your network connection or try again later.${C_RESET}" |
| 219 | + exit 1 |
| 220 | + fi |
| 221 | + |
| 222 | + echo -e " Installed version: ${C_BOLD}v${VERSION}${C_RESET}" |
| 223 | + echo -e " Latest version: ${C_BOLD}v${latest_version}${C_RESET}" |
| 224 | + |
| 225 | + # Compare versions |
| 226 | + if [[ "$VERSION" == "$latest_version" ]]; then |
| 227 | + echo -e "\n${C_GREEN}✅ You are already running the latest version.${C_RESET}" |
| 228 | + exit 0 |
| 229 | + fi |
| 230 | + |
| 231 | + echo -e "\n${C_YELLOW}⬆ New version available: v${latest_version}${C_RESET}" |
| 232 | + |
| 233 | + # Find where the current binary lives |
| 234 | + local current_bin |
| 235 | + current_bin=$(command -v aicommit 2>/dev/null || true) |
| 236 | + |
| 237 | + if [[ -z "$current_bin" ]]; then |
| 238 | + echo -e "${C_RED}Error: Cannot locate the aicommit binary in PATH.${C_RESET}" |
| 239 | + exit 1 |
| 240 | + fi |
| 241 | + |
| 242 | + # Resolve symlinks to get the actual file |
| 243 | + local actual_bin |
| 244 | + if command -v readlink &>/dev/null; then |
| 245 | + actual_bin=$(readlink -f "$current_bin" 2>/dev/null || echo "$current_bin") |
| 246 | + else |
| 247 | + actual_bin="$current_bin" |
| 248 | + fi |
| 249 | + |
| 250 | + echo -e " Updating: ${C_DIM}${actual_bin}${C_RESET}" |
| 251 | + |
| 252 | + # Download to a temp file first |
| 253 | + local tmp_file |
| 254 | + tmp_file=$(mktemp /tmp/aicommit-update-XXXXXX) |
| 255 | + |
| 256 | + if ! curl -fsSL "$GITHUB_RAW_URL" -o "$tmp_file"; then |
| 257 | + echo -e "${C_RED}Error: Failed to download the latest version.${C_RESET}" |
| 258 | + rm -f "$tmp_file" |
| 259 | + exit 1 |
| 260 | + fi |
| 261 | + |
| 262 | + # Verify the download looks like the aicommit script |
| 263 | + if ! head -1 "$tmp_file" | grep -q '#!/usr/bin/env bash'; then |
| 264 | + echo -e "${C_RED}Error: Downloaded file does not appear to be a valid aicommit script.${C_RESET}" |
| 265 | + rm -f "$tmp_file" |
| 266 | + exit 1 |
| 267 | + fi |
| 268 | + |
| 269 | + chmod +x "$tmp_file" |
| 270 | + |
| 271 | + # Install — use sudo if we can't write to the target directly |
| 272 | + if [[ -w "$actual_bin" ]]; then |
| 273 | + mv "$tmp_file" "$actual_bin" |
| 274 | + elif sudo -n true 2>/dev/null; then |
| 275 | + sudo mv "$tmp_file" "$actual_bin" |
| 276 | + else |
| 277 | + echo -e "${C_YELLOW}Elevated permissions required to update ${actual_bin}${C_RESET}" |
| 278 | + sudo mv "$tmp_file" "$actual_bin" |
| 279 | + fi |
| 280 | + |
| 281 | + echo -e "\n${C_GREEN}✅ Successfully updated aicommit: v${VERSION} → v${latest_version}${C_RESET}" |
| 282 | + exit 0 |
| 283 | +} |
| 284 | + |
202 | 285 | set -euo pipefail |
203 | 286 |
|
204 | 287 | # ---------- Provider constants ---------- |
@@ -245,6 +328,10 @@ while (( "$#" )); do |
245 | 328 | shift |
246 | 329 | fi |
247 | 330 | ;; |
| 331 | + --update) |
| 332 | + show_banner |
| 333 | + self_update |
| 334 | + ;; |
248 | 335 | -v|-V|--version) |
249 | 336 | show_banner |
250 | 337 | exit 0 |
|
0 commit comments