diff --git a/cmd/entire/cli/versioncheck/versioncheck.go b/cmd/entire/cli/versioncheck/versioncheck.go index 2b6469f4c..a70549934 100644 --- a/cmd/entire/cli/versioncheck/versioncheck.go +++ b/cmd/entire/cli/versioncheck/versioncheck.go @@ -243,9 +243,13 @@ func isOutdated(current, latest string) bool { return semver.Compare(current, latest) < 0 } +// executablePath is the function used to get the current executable path. +// It's a variable so tests can override it. +var executablePath = os.Executable + // updateCommand returns the appropriate update instruction based on how the binary was installed. func updateCommand() string { - execPath, err := os.Executable() + execPath, err := executablePath() if err != nil { return "curl -fsSL https://entire.io/install.sh | bash" } @@ -256,10 +260,14 @@ func updateCommand() string { realPath = execPath } - if strings.Contains(realPath, "/Cellar/") || strings.Contains(realPath, "/homebrew/") { + if strings.Contains(realPath, "/Cellar/") || strings.Contains(realPath, "/opt/homebrew/") || strings.Contains(realPath, "/linuxbrew/") { return "brew upgrade entire" } + if strings.Contains(realPath, "/mise/installs/") { + return "mise upgrade entire" + } + return "curl -fsSL https://entire.io/install.sh | bash" } diff --git a/cmd/entire/cli/versioncheck/versioncheck_test.go b/cmd/entire/cli/versioncheck/versioncheck_test.go index 4dcc87a18..7fa861365 100644 --- a/cmd/entire/cli/versioncheck/versioncheck_test.go +++ b/cmd/entire/cli/versioncheck/versioncheck_test.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "encoding/json" + "fmt" "net/http" "net/http/httptest" "os" @@ -233,16 +234,63 @@ func TestParseGitHubRelease(t *testing.T) { } func TestUpdateCommand(t *testing.T) { - // updateCommand should return one of the two valid update commands - cmd := updateCommand() - - validCommands := map[string]bool{ - "brew upgrade entire": true, - "curl -fsSL https://entire.io/install.sh | bash": true, + tests := []struct { + name string + execPath func() (string, error) + want string + }{ + { + name: "homebrew cellar path", + execPath: func() (string, error) { return "/opt/homebrew/Cellar/entire/1.0.0/bin/entire", nil }, + want: "brew upgrade entire", + }, + { + name: "homebrew opt path", + execPath: func() (string, error) { return "/opt/homebrew/bin/entire", nil }, + want: "brew upgrade entire", + }, + { + name: "linuxbrew path", + execPath: func() (string, error) { return "/home/linuxbrew/.linuxbrew/bin/entire", nil }, + want: "brew upgrade entire", + }, + { + name: "mise path", + execPath: func() (string, error) { return "/home/user/.local/share/mise/installs/entire/1.0.0/bin/entire", nil }, + want: "mise upgrade entire", + }, + { + name: "username mise not detected as mise install", + execPath: func() (string, error) { return "/home/mise/bin/entire", nil }, + want: "curl -fsSL https://entire.io/install.sh | bash", + }, + { + name: "username homebrew not detected as brew install", + execPath: func() (string, error) { return "/home/homebrew/bin/entire", nil }, + want: "curl -fsSL https://entire.io/install.sh | bash", + }, + { + name: "unknown path falls back to curl", + execPath: func() (string, error) { return "/usr/local/bin/entire", nil }, + want: "curl -fsSL https://entire.io/install.sh | bash", + }, + { + name: "executable error falls back to curl", + execPath: func() (string, error) { return "", fmt.Errorf("not found") }, + want: "curl -fsSL https://entire.io/install.sh | bash", + }, } - if !validCommands[cmd] { - t.Errorf("updateCommand() = %q, want one of %v", cmd, validCommands) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + original := executablePath + executablePath = tt.execPath + t.Cleanup(func() { executablePath = original }) + + if got := updateCommand(); got != tt.want { + t.Errorf("updateCommand() = %q, want %q", got, tt.want) + } + }) } }