Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/buf/internal/command/alpha/protoc/protoc.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ func run(
return err
}
}
if err := responseWriter.Close(); err != nil {
if err := responseWriter.Close(ctx); err != nil {
return err
}
return nil
Expand Down
2 changes: 1 addition & 1 deletion cmd/buf/internal/command/generate/generate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ func TestOutputFlag(t *testing.T) {
}
}

func TestSkipWriteWhenUnchanged(t *testing.T) {
func TestSmartCleanPreservesMtime(t *testing.T) {
t.Parallel()
tempDirPath := t.TempDir()
template := filepath.Join("testdata", "simple", "buf.gen.yaml")
Expand Down
48 changes: 12 additions & 36 deletions private/buf/bufgen/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,49 +104,32 @@ func (g *generator) Generate(
if generateOptions.deleteOuts != nil {
shouldDeleteOuts = *generateOptions.deleteOuts
}
responseWriterOptions := []bufprotopluginos.ResponseWriterOption{
bufprotopluginos.ResponseWriterWithCreateOutDirIfNotExists(),
}
if shouldDeleteOuts {
if err := g.deleteOuts(
ctx,
generateOptions.baseOutDirPath,
config.GeneratePluginConfigs(),
); err != nil {
return err
}
responseWriterOptions = append(responseWriterOptions, bufprotopluginos.ResponseWriterWithDeleteOuts())
}
responseWriter := bufprotopluginos.NewResponseWriter(
g.logger,
g.storageosProvider,
responseWriterOptions...,
)
for _, image := range images {
if err := g.generateCode(
ctx,
container,
image,
generateOptions.baseOutDirPath,
config.GeneratePluginConfigs(),
responseWriter,
generateOptions.includeImportsOverride,
generateOptions.includeWellKnownTypesOverride,
); err != nil {
return err
}
}
return nil
}

func (g *generator) deleteOuts(
ctx context.Context,
baseOutDir string,
pluginConfigs []bufconfig.GeneratePluginConfig,
) error {
return bufprotopluginos.NewCleaner(g.storageosProvider).DeleteOuts(
ctx,
xslices.Map(
pluginConfigs,
func(pluginConfig bufconfig.GeneratePluginConfig) string {
out := pluginConfig.Out()
if baseOutDir != "" && baseOutDir != "." {
return filepath.Join(baseOutDir, out)
}
return out
},
),
)
return responseWriter.Close(ctx)
}

func (g *generator) generateCode(
Expand All @@ -155,6 +138,7 @@ func (g *generator) generateCode(
inputImage bufimage.Image,
baseOutDir string,
pluginConfigs []bufconfig.GeneratePluginConfig,
responseWriter bufprotopluginos.ResponseWriter,
includeImportsOverride *bool,
includeWellKnownTypesOverride *bool,
) error {
Expand All @@ -170,11 +154,6 @@ func (g *generator) generateCode(
return err
}
// Apply the CodeGeneratorResponses in the order they were specified.
responseWriter := bufprotopluginos.NewResponseWriter(
g.logger,
g.storageosProvider,
bufprotopluginos.ResponseWriterWithCreateOutDirIfNotExists(),
)
for i, pluginConfig := range pluginConfigs {
out := pluginConfig.Out()
if baseOutDir != "" && baseOutDir != "." {
Expand All @@ -192,9 +171,6 @@ func (g *generator) generateCode(
return fmt.Errorf("plugin %s: %v", pluginConfig.Name(), err)
}
}
if err := responseWriter.Close(); err != nil {
return err
}
return nil
}

Expand Down
30 changes: 15 additions & 15 deletions private/bufpkg/bufprotoplugin/bufprotopluginos/bufprotopluginos.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ package bufprotopluginos

import (
"context"
"io"
"log/slog"

"github.com/bufbuild/buf/private/pkg/storage/storageos"
Expand All @@ -26,9 +25,11 @@ import (

// ResponseWriter writes CodeGeneratorResponses to the OS filesystem.
type ResponseWriter interface {
// Close writes all of the responses to disk. No further calls can be
// made to the ResponseWriter after this call.
io.Closer
// Close writes all of the responses to disk and, when
// ResponseWriterWithDeleteOuts is enabled, removes stale files from
// output directories. No further calls can be made to the
// ResponseWriter after this call.
Close(ctx context.Context) error

// AddResponse adds the response to the writer, switching on the file extension.
// If there is a .jar extension, this generates a jar. If there is a .zip
Expand Down Expand Up @@ -67,15 +68,14 @@ func ResponseWriterWithCreateOutDirIfNotExists() ResponseWriterOption {
}
}

// Cleaner deletes output locations prior to generation.
//
// This must be done before any interaction with ResponseWriters, as multiple plugins may output to a single
// location.
type Cleaner interface {
DeleteOuts(ctx context.Context, pluginOuts []string) error
}

// NewCleaner returns a new Cleaner.
func NewCleaner(storageosProvider storageos.Provider) Cleaner {
return newCleaner(storageosProvider)
// ResponseWriterWithDeleteOuts returns a ResponseWriterOption that deletes files
// on Close that were not written during generation. For directory outputs, any
// file on disk that was not part of the generated output is deleted after all
// new content is written, and empty directories are removed. For zip/jar outputs,
// the file is only rewritten when the generated content differs from what is
// already on disk.
func ResponseWriterWithDeleteOuts() ResponseWriterOption {
return func(responseWriterOptions *responseWriterOptions) {
responseWriterOptions.deleteOuts = true
}
}
124 changes: 0 additions & 124 deletions private/bufpkg/bufprotoplugin/bufprotopluginos/cleaner.go

This file was deleted.

Loading
Loading