Exposes CheckStaleBinary() via CLI for scripting. Supports --json for machine-readable output and --quiet for exit-code-only mode (0=stale, 1=fresh, 2=error). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
123 lines
3.1 KiB
Go
123 lines
3.1 KiB
Go
package cmd
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
|
|
"github.com/spf13/cobra"
|
|
"github.com/steveyegge/gastown/internal/style"
|
|
"github.com/steveyegge/gastown/internal/version"
|
|
)
|
|
|
|
var staleJSON bool
|
|
var staleQuiet bool
|
|
|
|
var staleCmd = &cobra.Command{
|
|
Use: "stale",
|
|
GroupID: GroupDiag,
|
|
Short: "Check if the gt binary is stale",
|
|
Long: `Check if the gt binary was built from an older commit than the current repo HEAD.
|
|
|
|
This command compares the commit hash embedded in the binary at build time
|
|
with the current HEAD of the gastown repository.
|
|
|
|
Examples:
|
|
gt stale # Human-readable output
|
|
gt stale --json # Machine-readable JSON output
|
|
gt stale --quiet # Exit code only (0=stale, 1=fresh)
|
|
|
|
Exit codes:
|
|
0 - Binary is stale (needs rebuild)
|
|
1 - Binary is fresh (up to date)
|
|
2 - Error (could not determine staleness)`,
|
|
RunE: runStale,
|
|
}
|
|
|
|
func init() {
|
|
staleCmd.Flags().BoolVar(&staleJSON, "json", false, "Output as JSON")
|
|
staleCmd.Flags().BoolVarP(&staleQuiet, "quiet", "q", false, "Exit code only (0=stale, 1=fresh)")
|
|
rootCmd.AddCommand(staleCmd)
|
|
}
|
|
|
|
// StaleOutput represents the JSON output structure.
|
|
type StaleOutput struct {
|
|
Stale bool `json:"stale"`
|
|
BinaryCommit string `json:"binary_commit"`
|
|
RepoCommit string `json:"repo_commit"`
|
|
CommitsBehind int `json:"commits_behind,omitempty"`
|
|
Error string `json:"error,omitempty"`
|
|
}
|
|
|
|
func runStale(cmd *cobra.Command, args []string) error {
|
|
// Find the gastown repo
|
|
repoRoot, err := version.GetRepoRoot()
|
|
if err != nil {
|
|
if staleQuiet {
|
|
os.Exit(2)
|
|
}
|
|
if staleJSON {
|
|
return outputStaleJSON(StaleOutput{Error: err.Error()})
|
|
}
|
|
return fmt.Errorf("cannot find gastown repo: %w", err)
|
|
}
|
|
|
|
// Check staleness
|
|
info := version.CheckStaleBinary(repoRoot)
|
|
|
|
// Handle errors
|
|
if info.Error != nil {
|
|
if staleQuiet {
|
|
os.Exit(2)
|
|
}
|
|
if staleJSON {
|
|
return outputStaleJSON(StaleOutput{Error: info.Error.Error()})
|
|
}
|
|
return fmt.Errorf("staleness check failed: %w", info.Error)
|
|
}
|
|
|
|
// Quiet mode: just exit with appropriate code
|
|
if staleQuiet {
|
|
if info.IsStale {
|
|
os.Exit(0)
|
|
}
|
|
os.Exit(1)
|
|
}
|
|
|
|
// Build output
|
|
output := StaleOutput{
|
|
Stale: info.IsStale,
|
|
BinaryCommit: info.BinaryCommit,
|
|
RepoCommit: info.RepoCommit,
|
|
CommitsBehind: info.CommitsBehind,
|
|
}
|
|
|
|
if staleJSON {
|
|
return outputStaleJSON(output)
|
|
}
|
|
|
|
return outputStaleText(output)
|
|
}
|
|
|
|
func outputStaleJSON(output StaleOutput) error {
|
|
enc := json.NewEncoder(os.Stdout)
|
|
enc.SetIndent("", " ")
|
|
return enc.Encode(output)
|
|
}
|
|
|
|
func outputStaleText(output StaleOutput) error {
|
|
if output.Stale {
|
|
fmt.Printf("%s Binary is stale\n", style.Warning.Render("⚠"))
|
|
fmt.Printf(" Binary: %s\n", version.ShortCommit(output.BinaryCommit))
|
|
fmt.Printf(" Repo: %s\n", version.ShortCommit(output.RepoCommit))
|
|
if output.CommitsBehind > 0 {
|
|
fmt.Printf(" %s\n", style.Dim.Render(fmt.Sprintf("(%d commits behind)", output.CommitsBehind)))
|
|
}
|
|
fmt.Printf("\n Run 'go install ./cmd/gt' to rebuild\n")
|
|
} else {
|
|
fmt.Printf("%s Binary is fresh\n", style.Success.Render("✓"))
|
|
fmt.Printf(" Commit: %s\n", version.ShortCommit(output.BinaryCommit))
|
|
}
|
|
return nil
|
|
}
|