From cb8d7869a87affceddd1d1da29add03111c0b917 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 19 Apr 2026 09:26:02 +0000 Subject: [PATCH] refactor: remove unused exported symbols from internal packages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - brew: delete GetInstalledLeaves and GetInstalledTaps (never called outside tests; snapshot capture uses GetInstalledPackages instead) - system: delete Architecture, HomebrewPrefix, IsHomebrewInstalled, IsXcodeCliInstalled, IsGumInstalled, and InstallHomebrew — none are referenced by any production call site; clean up the five imports (crypto/sha256, encoding/hex, io, net/http, httputil) that existed only to support InstallHomebrew - npm: unexport GetNodeVersion → getNodeVersion; it is only ever called by the package-internal warnIfNodeVersionTooLow helper - ui: delete empty ui_test.go (contained only the package declaration) https://claude.ai/code/session_01R5q9fGs8dJR7uD5xaxCutN --- internal/brew/brew.go | 32 ---------- internal/brew/brew_extra_test.go | 86 ------------------------- internal/npm/npm.go | 4 +- internal/npm/npm_command_test.go | 2 +- internal/npm/npm_extra_test.go | 12 ++-- internal/npm/npm_test.go | 2 +- internal/system/system.go | 104 ------------------------------- internal/system/system_test.go | 91 --------------------------- internal/ui/ui_test.go | 1 - 9 files changed, 10 insertions(+), 324 deletions(-) delete mode 100644 internal/ui/ui_test.go diff --git a/internal/brew/brew.go b/internal/brew/brew.go index cf2da8a..ad2a95a 100644 --- a/internal/brew/brew.go +++ b/internal/brew/brew.go @@ -176,38 +176,6 @@ func UninstallCask(packages []string, dryRun bool) error { return nil } -// GetInstalledLeaves returns top-level formulae (not dependencies) as a set. -// This matches what `brew leaves` reports and is consistent with snapshot captures. -func GetInstalledLeaves() (map[string]bool, error) { - output, err := currentRunner().Output("leaves") - if err != nil { - return nil, fmt.Errorf("brew leaves: %w", err) - } - - leaves := make(map[string]bool) - for _, name := range strings.Split(strings.TrimSpace(string(output)), "\n") { - if name != "" { - leaves[name] = true - } - } - return leaves, nil -} - -func GetInstalledTaps() ([]string, error) { - output, err := currentRunner().Output("tap") - if err != nil { - return nil, fmt.Errorf("brew tap: %w", err) - } - var taps []string - for _, line := range strings.Split(strings.TrimSpace(string(output)), "\n") { - line = strings.TrimSpace(line) - if line != "" { - taps = append(taps, line) - } - } - return taps, nil -} - func Untap(taps []string, dryRun bool) error { if len(taps) == 0 { return nil diff --git a/internal/brew/brew_extra_test.go b/internal/brew/brew_extra_test.go index a37cf19..8d1cf4b 100644 --- a/internal/brew/brew_extra_test.go +++ b/internal/brew/brew_extra_test.go @@ -8,92 +8,6 @@ import ( "github.com/stretchr/testify/require" ) -// --------------------------------------------------------------------------- -// GetInstalledLeaves -// --------------------------------------------------------------------------- - -func TestGetInstalledLeaves_ParsesOutput(t *testing.T) { - withFakeBrew(t, func(args []string) ([]byte, error) { - if len(args) == 1 && args[0] == "leaves" { - return []byte("git\ncurl\nripgrep\n"), nil - } - return nil, nil - }) - - leaves, err := GetInstalledLeaves() - require.NoError(t, err) - assert.True(t, leaves["git"]) - assert.True(t, leaves["curl"]) - assert.True(t, leaves["ripgrep"]) - assert.Len(t, leaves, 3) -} - -func TestGetInstalledLeaves_EmptyOutput(t *testing.T) { - withFakeBrew(t, func(args []string) ([]byte, error) { - if len(args) == 1 && args[0] == "leaves" { - return []byte("\n"), nil - } - return nil, nil - }) - - leaves, err := GetInstalledLeaves() - require.NoError(t, err) - assert.Empty(t, leaves) -} - -func TestGetInstalledLeaves_RunnerError(t *testing.T) { - withFakeBrew(t, func(args []string) ([]byte, error) { - return nil, errors.New("brew not found") - }) - - _, err := GetInstalledLeaves() - require.Error(t, err) - assert.Contains(t, err.Error(), "brew leaves") -} - -// --------------------------------------------------------------------------- -// GetInstalledTaps -// --------------------------------------------------------------------------- - -func TestGetInstalledTaps_ParsesOutput(t *testing.T) { - withFakeBrew(t, func(args []string) ([]byte, error) { - if len(args) == 1 && args[0] == "tap" { - return []byte("homebrew/cask\nhashicorp/tap\nopenbootdotdev/tap\n"), nil - } - return nil, nil - }) - - taps, err := GetInstalledTaps() - require.NoError(t, err) - require.Len(t, taps, 3) - assert.Equal(t, "homebrew/cask", taps[0]) - assert.Equal(t, "hashicorp/tap", taps[1]) - assert.Equal(t, "openbootdotdev/tap", taps[2]) -} - -func TestGetInstalledTaps_EmptyOutput(t *testing.T) { - withFakeBrew(t, func(args []string) ([]byte, error) { - if len(args) == 1 && args[0] == "tap" { - return []byte(""), nil - } - return nil, nil - }) - - taps, err := GetInstalledTaps() - require.NoError(t, err) - assert.Empty(t, taps) -} - -func TestGetInstalledTaps_RunnerError(t *testing.T) { - withFakeBrew(t, func(args []string) ([]byte, error) { - return nil, errors.New("exit status 1") - }) - - _, err := GetInstalledTaps() - require.Error(t, err) - assert.Contains(t, err.Error(), "brew tap") -} - // --------------------------------------------------------------------------- // Untap // --------------------------------------------------------------------------- diff --git a/internal/npm/npm.go b/internal/npm/npm.go index c7b542b..13a5813 100644 --- a/internal/npm/npm.go +++ b/internal/npm/npm.go @@ -21,7 +21,7 @@ var nodeVersionOutput = func() ([]byte, error) { return exec.Command("node", "--version").Output() } -func GetNodeVersion() (int, error) { +func getNodeVersion() (int, error) { output, err := nodeVersionOutput() if err != nil { return 0, err @@ -142,7 +142,7 @@ func Install(packages []string, dryRun bool) error { // warnIfNodeVersionTooLow prints a warning when packages that require Node.js // v22+ are requested but the installed version is older. func warnIfNodeVersionTooLow(packages []string) { - nodeVersion, err := GetNodeVersion() + nodeVersion, err := getNodeVersion() if err != nil || nodeVersion <= 0 { return } diff --git a/internal/npm/npm_command_test.go b/internal/npm/npm_command_test.go index f9d6f16..3cf468b 100644 --- a/internal/npm/npm_command_test.go +++ b/internal/npm/npm_command_test.go @@ -52,7 +52,7 @@ func TestGetNodeVersion_ParsesVersion(t *testing.T) { t.Cleanup(func() { nodeVersionOutput = orig }) nodeVersionOutput = func() ([]byte, error) { return []byte("v22.1.0\n"), nil } - version, err := GetNodeVersion() + version, err := getNodeVersion() require.NoError(t, err) assert.Equal(t, 22, version) } diff --git a/internal/npm/npm_extra_test.go b/internal/npm/npm_extra_test.go index b7fea4d..0744b2a 100644 --- a/internal/npm/npm_extra_test.go +++ b/internal/npm/npm_extra_test.go @@ -11,7 +11,7 @@ import ( ) // --------------------------------------------------------------------------- -// GetNodeVersion — error paths +// getNodeVersion — error paths // --------------------------------------------------------------------------- func TestGetNodeVersion_ExecError(t *testing.T) { @@ -21,7 +21,7 @@ func TestGetNodeVersion_ExecError(t *testing.T) { return nil, errors.New("node not found") } - _, err := GetNodeVersion() + _, err := getNodeVersion() require.Error(t, err) } @@ -32,7 +32,7 @@ func TestGetNodeVersion_InvalidFormat(t *testing.T) { return []byte("not-a-version\n"), nil } - _, err := GetNodeVersion() + _, err := getNodeVersion() require.Error(t, err) } @@ -43,7 +43,7 @@ func TestGetNodeVersion_EmptyOutput(t *testing.T) { return []byte(""), nil } - _, err := GetNodeVersion() + _, err := getNodeVersion() require.Error(t, err) } @@ -340,7 +340,7 @@ func TestGetInstalledPackages_EmptyOutput(t *testing.T) { } // --------------------------------------------------------------------------- -// GetNodeVersion — major-only version string edge case +// getNodeVersion — major-only version string edge case // --------------------------------------------------------------------------- func TestGetNodeVersion_MajorOnly(t *testing.T) { @@ -348,7 +348,7 @@ func TestGetNodeVersion_MajorOnly(t *testing.T) { t.Cleanup(func() { nodeVersionOutput = orig }) nodeVersionOutput = func() ([]byte, error) { return []byte("v20\n"), nil } - ver, err := GetNodeVersion() + ver, err := getNodeVersion() require.NoError(t, err) assert.Equal(t, 20, ver) } diff --git a/internal/npm/npm_test.go b/internal/npm/npm_test.go index cae2bc8..2711b76 100644 --- a/internal/npm/npm_test.go +++ b/internal/npm/npm_test.go @@ -100,7 +100,7 @@ func TestGetNodeVersion(t *testing.T) { if !IsAvailable() { t.Skip("node not available") } - ver, err := GetNodeVersion() + ver, err := getNodeVersion() assert.NoError(t, err) assert.Greater(t, ver, 0) } diff --git a/internal/system/system.go b/internal/system/system.go index 4db71c0..2fb3737 100644 --- a/internal/system/system.go +++ b/internal/system/system.go @@ -1,17 +1,10 @@ package system import ( - "crypto/sha256" - "encoding/hex" "fmt" - "io" - "net/http" "os" "os/exec" - "runtime" "strings" - - "github.com/openbootdotdev/openboot/internal/httputil" ) func HomeDir() (string, error) { @@ -22,32 +15,6 @@ func HomeDir() (string, error) { return home, nil } -func Architecture() string { - return runtime.GOARCH -} - -func HomebrewPrefix() string { - if Architecture() == "arm64" { - return "/opt/homebrew" - } - return "/usr/local" -} - -func IsHomebrewInstalled() bool { - _, err := exec.LookPath("brew") - return err == nil -} - -func IsXcodeCliInstalled() bool { - cmd := exec.Command("xcode-select", "-p") - return cmd.Run() == nil -} - -func IsGumInstalled() bool { - _, err := exec.LookPath("gum") - return err == nil -} - func RunCommand(name string, args ...string) error { cmd := exec.Command(name, args...) //nolint:gosec // intentional generic runner; callers are responsible for validating name and args cmd.Stdout = os.Stdout @@ -70,77 +37,6 @@ func RunCommandOutput(name string, args ...string) (string, error) { return strings.TrimSpace(string(output)), err } -// knownBrewInstallHash is the SHA256 of the Homebrew install script pinned on -// 2026-04-19 (Homebrew/install HEAD as of that date). Update this constant -// whenever the installer script changes upstream by running: -// -// curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh | sha256sum -const knownBrewInstallHash = "dfd5145fe2aa5956a600e35848765273f5798ce6def01bd08ecec088a1268d91" - -const brewInstallURL = "https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh" - -// brewHTTPClient is a var so tests can inject a mock transport. -var brewHTTPClient *http.Client = http.DefaultClient - -func InstallHomebrew() error { - // Download the installer via httputil.Do so rate-limit handling is applied. - req, err := http.NewRequest(http.MethodGet, brewInstallURL, nil) - if err != nil { - return fmt.Errorf("create homebrew install request: %w", err) - } - resp, err := httputil.Do(brewHTTPClient, req) - if err != nil { - return fmt.Errorf("download homebrew install script: %w", err) - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - return fmt.Errorf("download homebrew install script: unexpected status %d", resp.StatusCode) - } - - scriptBytes, err := io.ReadAll(resp.Body) - if err != nil { - return fmt.Errorf("read homebrew install script: %w", err) - } - - // Verify SHA256 before executing anything. - sum := sha256.Sum256(scriptBytes) - got := hex.EncodeToString(sum[:]) - if got != knownBrewInstallHash { - return fmt.Errorf("homebrew installer SHA256 mismatch: refusing to execute") - } - - // Write verified script to a temp file, execute, then clean up. - tmpFile, err := os.CreateTemp("", "homebrew-install-*.sh") - if err != nil { - return fmt.Errorf("create temp file for homebrew install: %w", err) - } - defer os.Remove(tmpFile.Name()) - - if _, err := tmpFile.Write(scriptBytes); err != nil { - tmpFile.Close() //nolint:gosec,errcheck // error-path cleanup; original write error takes precedence - return fmt.Errorf("write homebrew install script: %w", err) - } - if err := tmpFile.Close(); err != nil { - return fmt.Errorf("close homebrew install script: %w", err) - } - - if err := os.Chmod(tmpFile.Name(), 0700); err != nil { //nolint:gosec // install script must be executable - return fmt.Errorf("chmod homebrew install script: %w", err) - } - - tty, opened := OpenTTY() - if opened { - defer tty.Close() //nolint:errcheck // best-effort TTY cleanup - } - - cmd := exec.Command(tmpFile.Name()) //nolint:gosec // script content is SHA256-verified before execution - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - cmd.Stdin = tty - return cmd.Run() -} - func GetGitConfig(key string) string { // Try global first (most common) output, err := RunCommandSilent("git", "config", "--global", key) diff --git a/internal/system/system_test.go b/internal/system/system_test.go index bf19094..7d5d7bf 100644 --- a/internal/system/system_test.go +++ b/internal/system/system_test.go @@ -1,49 +1,14 @@ package system import ( - "net/http" - "net/http/httptest" "os" "os/exec" - "runtime" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) -type sysMockRT struct{ handler http.Handler } - -func (m *sysMockRT) RoundTrip(req *http.Request) (*http.Response, error) { - rec := httptest.NewRecorder() - m.handler.ServeHTTP(rec, req) - return rec.Result(), nil -} - -// withMockBrewClient patches brewHTTPClient without binding any port. -func withMockBrewClient(t *testing.T, handler http.Handler) { - t.Helper() - orig := brewHTTPClient - brewHTTPClient = &http.Client{Transport: &sysMockRT{handler: handler}} - t.Cleanup(func() { brewHTTPClient = orig }) -} - -func TestArchitecture(t *testing.T) { - arch := Architecture() - assert.Equal(t, runtime.GOARCH, arch) - assert.NotEmpty(t, arch) -} - -func TestHomebrewPrefix(t *testing.T) { - prefix := HomebrewPrefix() - - if runtime.GOARCH == "arm64" { - assert.Equal(t, "/opt/homebrew", prefix) - } else { - assert.Equal(t, "/usr/local", prefix) - } -} - func TestRunCommandSilent_Success(t *testing.T) { output, err := RunCommandSilent("echo", "hello", "world") require.NoError(t, err) @@ -242,21 +207,6 @@ func TestOpenTTY_SequentialCaskSimulation(t *testing.T) { assert.NoError(t, cmd2.Run(), "retry should still have a working TTY") } -func TestIsHomebrewInstalled(t *testing.T) { - result := IsHomebrewInstalled() - assert.IsType(t, true, result) -} - -func TestIsXcodeCliInstalled(t *testing.T) { - result := IsXcodeCliInstalled() - assert.IsType(t, true, result) -} - -func TestIsGumInstalled(t *testing.T) { - result := IsGumInstalled() - assert.IsType(t, true, result) -} - func TestGetGitConfig_NonExistentKey(t *testing.T) { value := GetGitConfig("user.nonexistentkey12345") assert.Equal(t, "", value) @@ -357,22 +307,6 @@ func TestHomeDir_MatchesEnv(t *testing.T) { assert.Equal(t, tmpDir, home) } -// --------------------------------------------------------------------------- -// HomebrewPrefix — both arch branches covered via table -// --------------------------------------------------------------------------- - -func TestHomebrewPrefix_MatchesArch(t *testing.T) { - prefix := HomebrewPrefix() - assert.NotEmpty(t, prefix) - - switch runtime.GOARCH { - case "arm64": - assert.Equal(t, "/opt/homebrew", prefix) - default: - assert.Equal(t, "/usr/local", prefix) - } -} - // --------------------------------------------------------------------------- // RunCommandOutput // --------------------------------------------------------------------------- @@ -406,31 +340,6 @@ func TestRunCommandOutput_CommandNotFound(t *testing.T) { assert.Error(t, err) } -// --------------------------------------------------------------------------- -// InstallHomebrew — hermetic paths via httptest -// --------------------------------------------------------------------------- - -func TestInstallHomebrew_HTTPError(t *testing.T) { - withMockBrewClient(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusInternalServerError) - })) - - err := InstallHomebrew() - require.Error(t, err) - assert.Contains(t, err.Error(), "unexpected status") -} - -func TestInstallHomebrew_SHA256Mismatch(t *testing.T) { - withMockBrewClient(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusOK) - w.Write([]byte("#!/bin/bash\necho fake-script")) //nolint:errcheck - })) - - err := InstallHomebrew() - require.Error(t, err) - assert.Contains(t, err.Error(), "SHA256 mismatch") -} - // --------------------------------------------------------------------------- // HasTTY — ensure all branches are exercised // --------------------------------------------------------------------------- diff --git a/internal/ui/ui_test.go b/internal/ui/ui_test.go deleted file mode 100644 index 5b1faa2..0000000 --- a/internal/ui/ui_test.go +++ /dev/null @@ -1 +0,0 @@ -package ui