// Package build provides project type detection and cross-compilation for the Core build system. package build import ( "crypto/sha256" "encoding/hex" "fmt" "io" "path/filepath" io_interface "github.com/host-uk/core/pkg/io" "sort" "strings" ) // Checksum computes SHA256 for an artifact and returns the artifact with the Checksum field filled. func Checksum(fs io_interface.Medium, artifact Artifact) (Artifact, error) { if artifact.Path == "" { return Artifact{}, fmt.Errorf("build.Checksum: artifact path is empty") } // Open the file file, err := fs.Open(artifact.Path) if err != nil { return Artifact{}, fmt.Errorf("build.Checksum: failed to open file: %w", err) } defer func() { _ = file.Close() }() // Compute SHA256 hash hasher := sha256.New() if _, err := io.Copy(hasher, file); err != nil { return Artifact{}, fmt.Errorf("build.Checksum: failed to hash file: %w", err) } checksum := hex.EncodeToString(hasher.Sum(nil)) return Artifact{ Path: artifact.Path, OS: artifact.OS, Arch: artifact.Arch, Checksum: checksum, }, nil } // ChecksumAll computes checksums for all artifacts. // Returns a slice of artifacts with their Checksum fields filled. func ChecksumAll(fs io_interface.Medium, artifacts []Artifact) ([]Artifact, error) { if len(artifacts) == 0 { return nil, nil } var checksummed []Artifact for _, artifact := range artifacts { cs, err := Checksum(fs, artifact) if err != nil { return checksummed, fmt.Errorf("build.ChecksumAll: failed to checksum %s: %w", artifact.Path, err) } checksummed = append(checksummed, cs) } return checksummed, nil } // WriteChecksumFile writes a CHECKSUMS.txt file with the format: // // sha256hash filename1 // sha256hash filename2 // // The artifacts should have their Checksum fields filled (call ChecksumAll first). // Filenames are relative to the output directory (just the basename). func WriteChecksumFile(fs io_interface.Medium, artifacts []Artifact, path string) error { if len(artifacts) == 0 { return nil } // Build the content var lines []string for _, artifact := range artifacts { if artifact.Checksum == "" { return fmt.Errorf("build.WriteChecksumFile: artifact %s has no checksum", artifact.Path) } filename := filepath.Base(artifact.Path) lines = append(lines, fmt.Sprintf("%s %s", artifact.Checksum, filename)) } // Sort lines for consistent output sort.Strings(lines) content := strings.Join(lines, "\n") + "\n" // Write the file using the medium (which handles directory creation in Write) if err := fs.Write(path, content); err != nil { return fmt.Errorf("build.WriteChecksumFile: failed to write file: %w", err) } return nil }