Add detection for when the installed gt binary is out of date with the source repository. This helps catch issues where commands fail mysteriously because the installed binary doesn't have recent fixes. Changes: - Add internal/version package with stale binary detection logic - Add startup warning in PersistentPreRunE when binary is stale - Add gt doctor check for stale-binary - Use prefix matching for commit comparison (handles short vs full hash) The warning is non-blocking and only shows once per shell session via the GT_STALE_WARNED environment variable. Resolves: gt-ud912 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
84 lines
2.2 KiB
Go
84 lines
2.2 KiB
Go
package doctor
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/steveyegge/gastown/internal/version"
|
|
)
|
|
|
|
// StaleBinaryCheck verifies the installed gt binary is up to date with the repo.
|
|
type StaleBinaryCheck struct {
|
|
FixableCheck
|
|
}
|
|
|
|
// NewStaleBinaryCheck creates a new stale binary check.
|
|
func NewStaleBinaryCheck() *StaleBinaryCheck {
|
|
return &StaleBinaryCheck{
|
|
FixableCheck: FixableCheck{
|
|
BaseCheck: BaseCheck{
|
|
CheckName: "stale-binary",
|
|
CheckDescription: "Check if gt binary is up to date with repo",
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
// Run checks if the binary is stale.
|
|
func (c *StaleBinaryCheck) Run(ctx *CheckContext) *CheckResult {
|
|
repoRoot, err := version.GetRepoRoot()
|
|
if err != nil {
|
|
return &CheckResult{
|
|
Name: c.Name(),
|
|
Status: StatusOK,
|
|
Message: "Cannot locate gt source repo (not a development environment)",
|
|
Details: []string{err.Error()},
|
|
}
|
|
}
|
|
|
|
info := version.CheckStaleBinary(repoRoot)
|
|
if info.Error != nil {
|
|
return &CheckResult{
|
|
Name: c.Name(),
|
|
Status: StatusOK,
|
|
Message: "Cannot determine binary version (dev build?)",
|
|
Details: []string{info.Error.Error()},
|
|
}
|
|
}
|
|
|
|
if info.IsStale {
|
|
msg := fmt.Sprintf("Binary is stale (built from %s, repo at %s)",
|
|
version.ShortCommit(info.BinaryCommit), version.ShortCommit(info.RepoCommit))
|
|
if info.CommitsBehind > 0 {
|
|
msg = fmt.Sprintf("Binary is %d commits behind (built from %s, repo at %s)",
|
|
info.CommitsBehind, version.ShortCommit(info.BinaryCommit), version.ShortCommit(info.RepoCommit))
|
|
}
|
|
|
|
return &CheckResult{
|
|
Name: c.Name(),
|
|
Status: StatusWarning,
|
|
Message: msg,
|
|
FixHint: "Run 'gt install' to rebuild and install",
|
|
}
|
|
}
|
|
|
|
return &CheckResult{
|
|
Name: c.Name(),
|
|
Status: StatusOK,
|
|
Message: fmt.Sprintf("Binary is up to date (%s)", version.ShortCommit(info.BinaryCommit)),
|
|
}
|
|
}
|
|
|
|
// Fix rebuilds and installs gt.
|
|
func (c *StaleBinaryCheck) Fix(ctx *CheckContext) error {
|
|
// Note: We don't auto-fix this because:
|
|
// 1. It requires building and installing, which takes time
|
|
// 2. It modifies system files outside the workspace
|
|
// 3. User should explicitly run 'gt install'
|
|
return fmt.Errorf("run 'gt install' manually to rebuild")
|
|
}
|
|
|
|
// CanFix returns false - stale binary should be fixed manually.
|
|
func (c *StaleBinaryCheck) CanFix() bool {
|
|
return false
|
|
}
|