From d7ae3a111bd75df44dda69b37da945b50d5133e2 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Thu, 3 Apr 2025 14:35:27 +0200 Subject: pkg/ifuzz: fix generate/build Currently the commands we have in go:generate first create an empty file and then write final contents. This breaks any parallel builds of the source. Even running go generate ./... does not work. Write output files atomically. --- pkg/osutil/osutil.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'pkg/osutil') diff --git a/pkg/osutil/osutil.go b/pkg/osutil/osutil.go index 8e0ed7ea3..d16a76cb7 100644 --- a/pkg/osutil/osutil.go +++ b/pkg/osutil/osutil.go @@ -257,6 +257,19 @@ func WriteFile(filename string, data []byte) error { return os.WriteFile(filename, data, DefaultFilePerm) } +// WriteFileAtomically writes data to file filename without exposing and empty/partially-written file. +// This is useful for writing generated source files. Exposing an empty file may break tools +// that run on source files in parallel. +func WriteFileAtomically(filename string, data []byte) error { + // We can't use os.CreateTemp b/c it may be on a different mount, + // and Rename can't move across mounts. + tmpFile := filename + ".tmp" + if err := WriteFile(tmpFile, data); err != nil { + return err + } + return os.Rename(tmpFile, filename) +} + func WriteJSON[T any](filename string, obj T) error { jsonData, err := json.MarshalIndent(obj, "", "\t") if err != nil { -- cgit mrf-deployment