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
24 changes: 22 additions & 2 deletions cmd/gencopy/gencopy.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"os"
"path/filepath"
"strconv"
"strings"

"github.com/google/go-cmp/cmp"
)
Expand Down Expand Up @@ -105,7 +106,7 @@ func readFileAsString(filename string) (string, error) {
return string(bytes), nil
}

func check(_ *Config, pkg *PackageConfig, pairs []*SrcDst) error {
func check(cfg *Config, pkg *PackageConfig, pairs []*SrcDst) error {
for _, pair := range pairs {
expected, err := readFileAsString(pair.Src)
if err != nil {
Expand All @@ -117,7 +118,10 @@ func check(_ *Config, pkg *PackageConfig, pairs []*SrcDst) error {
}

if diff := cmp.Diff(expected, actual); diff != "" {
return fmt.Errorf("gencopy mismatch %q vs. %q (-want +got):\n%s", pair.Src, pair.Dst, diff)
return fmt.Errorf(
"gencopy mismatch %q vs. %q (-want +got):\n%s\n%s",
pair.Src, pair.Dst, diff, regenerateProTip(pkg.TargetLabel, cfg.UpdateTargetLabelName),
)
}
}

Expand All @@ -129,6 +133,22 @@ func check(_ *Config, pkg *PackageConfig, pairs []*SrcDst) error {
return nil
}

// regenerateProTip returns a friendly hint pointing the developer at the
// `.update` target that regenerates the checked-in copies. targetLabel is the
// proto_compile rule's label (e.g. "//proto:foo_proto_compile" or
// "@@repo//proto:foo_proto_compile"); updateName is the .update target's
// rule name (e.g. "foo_proto_compile.update").
func regenerateProTip(targetLabel, updateName string) string {
if updateName == "" {
return ""
}
updateLabel := updateName
if idx := strings.LastIndex(targetLabel, ":"); idx >= 0 {
updateLabel = targetLabel[:idx+1] + updateName
}
return fmt.Sprintf("\nProTip: to regenerate, run:\n bazel run %s\n", updateLabel)
}

func update(cfg *Config, pkg *PackageConfig, pairs []*SrcDst) error {
for _, pair := range pairs {
pair.Dst += cfg.Extension
Expand Down
36 changes: 36 additions & 0 deletions cmd/gencopy/gencopy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,42 @@ func TestRunPkg(t *testing.T) {
}
}

func TestRegenerateProTip(t *testing.T) {
for name, tc := range map[string]struct {
targetLabel string
updateName string
want string
}{
"empty update name": {
targetLabel: "//proto:foo_proto_compile",
updateName: "",
want: "",
},
"local target": {
targetLabel: "//proto:foo_proto_compile",
updateName: "foo_proto_compile.update",
want: "\nProTip: to regenerate, run:\n bazel run //proto:foo_proto_compile.update\n",
},
"external repo target": {
targetLabel: "@@some_repo//pkg:foo_proto_compile",
updateName: "foo_proto_compile.update",
want: "\nProTip: to regenerate, run:\n bazel run @@some_repo//pkg:foo_proto_compile.update\n",
},
"target with no colon": {
targetLabel: "raw_label_no_colon",
updateName: "foo_proto_compile.update",
want: "\nProTip: to regenerate, run:\n bazel run foo_proto_compile.update\n",
},
} {
t.Run(name, func(t *testing.T) {
got := regenerateProTip(tc.targetLabel, tc.updateName)
if got != tc.want {
t.Errorf("regenerateProTip: got %q, want %q", got, tc.want)
}
})
}
}

// listFiles - convenience debugging function to log the files under a given dir
func listFiles(t *testing.T, dir string) error {
return filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
Expand Down
2 changes: 1 addition & 1 deletion example/thing/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ proto_library(
name = "thing_proto",
srcs = ["thing.proto"],
visibility = ["//visibility:public"],
deps = ["@protobufapis//google/protobuf:timestamp_proto"],
deps = ["@com_google_protobuf//:timestamp_proto"],
)

proto_cc_library(
Expand Down
2 changes: 2 additions & 0 deletions pkg/language/protobuf/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ go_library(
go_test(
name = "protobuf_test",
srcs = [
"config_filemode_test.go",
"generate_test.go",
"override_test.go",
],
Expand All @@ -37,6 +38,7 @@ go_test(
"@bazel_gazelle//config",
"@bazel_gazelle//label",
"@bazel_gazelle//language",
"@bazel_gazelle//language/proto",
"@bazel_gazelle//resolve",
"@bazel_gazelle//rule",
"@bazel_gazelle//testtools",
Expand Down
8 changes: 8 additions & 0 deletions pkg/language/protobuf/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,18 @@ func (pl *protobufLang) Configure(c *config.Config, rel string, f *rule.File) {

// getOrCreatePackageConfig either inserts a new config into the map under the
// language name or replaces it with a clone.
//
// When cloning from the parent directory's config we must overwrite the
// embedded *config.Config pointer to the current directory's config. Without
// this, lookups that walk `cfg.Config.Exts[...]` (e.g.
// `IsProtoFileMode` reading the standard proto language's per-directory mode)
// resolve against the parent's `Exts` and miss directives like
// `# gazelle:proto file` that were applied to the child only.
func (pl *protobufLang) getOrCreatePackageConfig(config *config.Config) *protoc.PackageConfig {
var cfg *protoc.PackageConfig
if existingExt, ok := config.Exts[pl.name]; ok {
cfg = existingExt.(*protoc.PackageConfig).Clone()
cfg.Config = config
} else {
cfg = protoc.NewPackageConfig(config)
}
Expand Down
37 changes: 37 additions & 0 deletions pkg/language/protobuf/config_filemode_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package protobuf

import (
"testing"

"github.com/bazelbuild/bazel-gazelle/config"
gproto "github.com/bazelbuild/bazel-gazelle/language/proto"
)

// Regression: getOrCreatePackageConfig must point the cloned PackageConfig's
// embedded *config.Config at the CURRENT directory's config, not the parent's.
// Otherwise IsProtoFileMode reads the parent's proto-language config and
// misses a child directory that opted into `# gazelle:proto file`.
func TestGetOrCreatePackageConfig_RebindsConfig(t *testing.T) {
pl := &protobufLang{name: "protobuf"}

// Parent: default mode.
parent := &config.Config{Exts: map[string]interface{}{}}
parent.Exts["proto"] = &gproto.ProtoConfig{Mode: gproto.DefaultMode}
pl.getOrCreatePackageConfig(parent)

// Child: clone via gazelle's Config.Clone, then proto-lang flips mode to FileMode
// for this dir only.
child := parent.Clone()
childProto := &gproto.ProtoConfig{Mode: gproto.FileMode}
child.Exts["proto"] = childProto

cfg := pl.getOrCreatePackageConfig(child)
if cfg.Config != child {
t.Fatalf("cloned PackageConfig.Config not rebound to child: got %p, want %p", cfg.Config, child)
}

// IsProtoFileMode-equivalent check.
if gproto.GetProtoConfig(cfg.Config).Mode != gproto.FileMode {
t.Errorf("expected FileMode via cfg.Config, got %v", gproto.GetProtoConfig(cfg.Config).Mode)
}
}
6 changes: 5 additions & 1 deletion pkg/plugin/neoeinstein/prost/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,21 @@ go_library(
"//pkg/protoc",
"@bazel_gazelle//label",
"@bazel_gazelle//rule",
"@com_github_emicklei_proto//:proto",
],
)

go_test(
name = "prost_test",
srcs = [
"extern_paths_test.go",
"needs_cwkt_test.go",
"nested_type_path_test.go",
"protoc-gen-prost_test.go",
"register_nested_test.go",
],
embed = [":prost"],
deps = [
":prost",
"//pkg/plugintest",
"//pkg/protoc",
"@bazel_gazelle//label",
Expand Down
Loading
Loading