On this page

Output writing API

seagull.WriteFiles publishes a generation result into an output directory. It creates the directory when necessary, writes each non-empty result file atomically and optionally removes stale generated output.

Replacement and pruning

Every filename in Result.Files is an output destination. An existing file with that name is replaced regardless of its header or who wrote it. A file with identical content and permissions is left unchanged. Use a dedicated generated directory to avoid overwriting hand-written files with colliding names.

After successful writing, pruning removes files whose first line matches the selected header or a legacy header and whose names are absent from the result. The header may end with a line feed or a carriage return and line feed, so generated files checked out with CRLF line endings are still recognised; only as many bytes as the longest header and its line ending are read from each candidate. Files with other names and headers remain. Pruning considers regular files only: symbolic links, named pipes, sockets, devices and directories in the output directory are never opened or removed, so a named pipe cannot hang the writer and a link pointing outside the directory does not fail it. Filenames are restricted to plain base names, and the writer uses a sandbox rooted at the output directory.

err := seagull.WriteFiles("internal/store", result,
    seagull.WithLegacyHeaders("// Code generated by oldtool. DO NOT EDIT."),
    seagull.WithPermissions(0o644),
)
Write optionDefaultPurpose
WithPrune(bool)trueRemove stale generated files after writing.
WithHeader(string)Result.HeaderHeader identifying stale files eligible for deletion.
WithLegacyHeaders(...string)noneAdditional earlier headers eligible for stale deletion.
WithPermissions(fs.FileMode)0644Permissions of written files.

A nil result, a nil write option, an empty directory or a filename that is not a plain base name is refused with an error wrapping ErrInvalidConfig. Atomic replacement applies to individual files. Publication of a whole package is not a directory-wide transaction.

Failed and partial results

An ordinary result with error diagnostics has no files. WriteFiles refuses it and returns Result.Err() instead of pruning the previous output.

With WithSkipFailingQueries(), a result can contain a partial package and still report errors. WriteFiles accepts it when Result.Partial is true. Methods for rejected queries disappear, and wholly rejected query files may be pruned as stale output. A caller publishing partial results must make that policy deliberate and still report Result.Err().

See generator errors and reproducibility.