From e23a4d5d877ebb5b349dd8f2d0739aba813f1186 Mon Sep 17 00:00:00 2001 From: Amolith Date: Fri, 28 Nov 2025 19:53:52 -0700 Subject: [PATCH] refactor: split platform-specific update code into build-tagged files Moves binary validation and binaryName const into platform-specific files (update_unix.go, update_darwin.go, update_windows.go) to avoid compiling debug/elf, debug/macho, debug/pe on platforms that don't need them. Assisted-by: Claude Opus 4.5 via Crush --- internal/update/update.go | 60 ------------------------------- internal/update/update_darwin.go | 23 ++++++++++++ internal/update/update_unix.go | 23 ++++++++++++ internal/update/update_windows.go | 21 +++++++++++ 4 files changed, 67 insertions(+), 60 deletions(-) create mode 100644 internal/update/update_darwin.go create mode 100644 internal/update/update_unix.go create mode 100644 internal/update/update_windows.go diff --git a/internal/update/update.go b/internal/update/update.go index 42b440df8760a77268d53250569a268125dfde8e..969d10028b7662231571a41fd2f3122ce06a0891 100644 --- a/internal/update/update.go +++ b/internal/update/update.go @@ -7,9 +7,6 @@ import ( "compress/gzip" "context" "crypto/sha256" - "debug/elf" - "debug/macho" - "debug/pe" "encoding/hex" "encoding/json" "fmt" @@ -285,53 +282,6 @@ func Download(ctx context.Context, asset *Asset, release *Release) (string, erro return binaryPath, nil } -// validateBinary checks that the file at path is a valid executable binary -// for the current platform using the standard library debug packages. -func validateBinary(path string) error { - switch runtime.GOOS { - case "windows": - return validatePE(path) - case "darwin": - return validateMachO(path) - default: - return validateELF(path) - } -} - -func validateELF(path string) error { - f, err := elf.Open(path) - if err != nil { - return fmt.Errorf("not a valid ELF binary: %w", err) - } - defer f.Close() - if f.Type != elf.ET_EXEC && f.Type != elf.ET_DYN { - return fmt.Errorf("ELF file is not an executable (type: %v)", f.Type) - } - return nil -} - -func validateMachO(path string) error { - f, err := macho.Open(path) - if err != nil { - return fmt.Errorf("not a valid Mach-O binary: %w", err) - } - defer f.Close() - if f.Type != macho.TypeExec { - return fmt.Errorf("Mach-O file is not an executable (type: %v)", f.Type) - } - return nil -} - -func validatePE(path string) error { - f, err := pe.Open(path) - if err != nil { - return fmt.Errorf("not a valid PE binary: %w", err) - } - defer f.Close() - // PE files opened successfully are valid executables. - return nil -} - // downloadChecksums downloads and parses the checksums.txt file. // Returns a map of filename to sha256 checksum. func downloadChecksums(ctx context.Context, client *http.Client, asset *Asset) (map[string]string, error) { @@ -396,11 +346,6 @@ func extractZip(archivePath string) (string, error) { } defer r.Close() - binaryName := "crush" - if runtime.GOOS == "windows" { - binaryName = "crush.exe" - } - for _, f := range r.File { // Path traversal protection. cleanName := filepath.Clean(f.Name) @@ -477,11 +422,6 @@ func extractTarGz(archivePath string) (string, error) { tr := tar.NewReader(gzr) - binaryName := "crush" - if runtime.GOOS == "windows" { - binaryName = "crush.exe" - } - for { header, err := tr.Next() if err == io.EOF { diff --git a/internal/update/update_darwin.go b/internal/update/update_darwin.go new file mode 100644 index 0000000000000000000000000000000000000000..7b88c3dc22bae5484c62d765cdbf43413b4c22fd --- /dev/null +++ b/internal/update/update_darwin.go @@ -0,0 +1,23 @@ +//go:build darwin + +package update + +import ( + "debug/macho" + "fmt" +) + +const binaryName = "crush" + +// validateBinary checks that the file at path is a valid Mach-O executable. +func validateBinary(path string) error { + f, err := macho.Open(path) + if err != nil { + return fmt.Errorf("not a valid Mach-O binary: %w", err) + } + defer f.Close() + if f.Type != macho.TypeExec { + return fmt.Errorf("Mach-O file is not an executable (type: %v)", f.Type) + } + return nil +} diff --git a/internal/update/update_unix.go b/internal/update/update_unix.go new file mode 100644 index 0000000000000000000000000000000000000000..369ce171c359a78140b856212ee3eca69bd93927 --- /dev/null +++ b/internal/update/update_unix.go @@ -0,0 +1,23 @@ +//go:build !windows && !darwin + +package update + +import ( + "debug/elf" + "fmt" +) + +const binaryName = "crush" + +// validateBinary checks that the file at path is a valid ELF executable. +func validateBinary(path string) error { + f, err := elf.Open(path) + if err != nil { + return fmt.Errorf("not a valid ELF binary: %w", err) + } + defer f.Close() + if f.Type != elf.ET_EXEC && f.Type != elf.ET_DYN { + return fmt.Errorf("ELF file is not an executable (type: %v)", f.Type) + } + return nil +} diff --git a/internal/update/update_windows.go b/internal/update/update_windows.go new file mode 100644 index 0000000000000000000000000000000000000000..9270f4f840e2295e9286bde218c3d9a25da554c4 --- /dev/null +++ b/internal/update/update_windows.go @@ -0,0 +1,21 @@ +//go:build windows + +package update + +import ( + "debug/pe" + "fmt" +) + +const binaryName = "crush.exe" + +// validateBinary checks that the file at path is a valid PE executable. +func validateBinary(path string) error { + f, err := pe.Open(path) + if err != nil { + return fmt.Errorf("not a valid PE binary: %w", err) + } + defer f.Close() + // PE files opened successfully are valid executables. + return nil +}