task 4
build-binaries / build-binaries (pull_request) Successful in 2m28s
test-image / build-image (pull_request) Successful in 52s
test / test (pull_request) Successful in 1m32s

This commit is contained in:
2026-06-19 18:46:48 +02:00
parent eec439cb39
commit 6d92dc2d9c
5 changed files with 137 additions and 30 deletions
+22 -17
View File
@@ -378,16 +378,8 @@ func planOrBuildHAKs(p *project.Project, progress ProgressFunc, writeArchives bo
if err := os.MkdirAll(filepath.Dir(hakPath), 0o755); err != nil {
return BuildResult{}, fmt.Errorf("create hak archive dir: %w", err)
}
hakOutput, err := os.Create(hakPath)
if err != nil {
return BuildResult{}, fmt.Errorf("create hak archive: %w", err)
}
if err := erf.Write(hakOutput, erf.New("HAK ", resourceSlice(chunk.Assets))); err != nil {
hakOutput.Close()
return BuildResult{}, fmt.Errorf("write hak archive: %w", err)
}
if err := hakOutput.Close(); err != nil {
return BuildResult{}, fmt.Errorf("close hak archive: %w", err)
if err := writeHAKArchive(hakPath, resourceSlice(chunk.Assets)); err != nil {
return BuildResult{}, err
}
}
@@ -488,23 +480,36 @@ func buildDirectHAKs(p *project.Project, progress ProgressFunc, writeArchives bo
return result, nil
}
// writeHAKArchive writes a HAK archive, removing any partial output if the ERF
// writer or a streamed source SHA verification fails, so a corrupt input never
// leaves a completed .hak behind.
// writeHAKArchive publishes a completed HAK atomically, so a failed write never
// leaves a partial archive at the final path.
func writeHAKArchive(hakPath string, resources []erf.Resource) error {
output, err := os.Create(hakPath)
tmpPath := hakPath + ".tmp"
if err := os.Remove(tmpPath); err != nil && !errors.Is(err, os.ErrNotExist) {
return fmt.Errorf("remove stale temporary hak %s: %w", tmpPath, err)
}
output, err := os.OpenFile(tmpPath, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0o644)
if err != nil {
return fmt.Errorf("create hak archive: %w", err)
return fmt.Errorf("create temporary hak archive %s: %w", tmpPath, err)
}
if err := erf.Write(output, erf.New("HAK ", resources)); err != nil {
output.Close()
os.Remove(hakPath)
os.Remove(tmpPath)
return fmt.Errorf("write hak archive: %w", err)
}
if err := output.Sync(); err != nil {
output.Close()
os.Remove(tmpPath)
return fmt.Errorf("sync hak archive: %w", err)
}
if err := output.Close(); err != nil {
os.Remove(hakPath)
os.Remove(tmpPath)
return fmt.Errorf("close hak archive: %w", err)
}
if err := os.Rename(tmpPath, hakPath); err != nil {
os.Remove(tmpPath)
return fmt.Errorf("publish hak archive %s: %w", hakPath, err)
}
return nil
}