From 2f65e9b95e60fb8056d37a27eb8e58fc790823ad Mon Sep 17 00:00:00 2001 From: Edward McFarlane Date: Sat, 29 Mar 2025 09:18:53 +0100 Subject: [PATCH] Fix exclude_type on non imported package This fixes exclude_type for a package exclude when no includes are set. --- CHANGELOG.md | 2 +- .../bufimageutil/bufimageutil_test.go | 4 + .../bufimage/bufimageutil/image_filter.go | 8 +- .../testdata/options/pkg.Pkg.exclude.txtar | 513 ++++++++++++++++++ 4 files changed, 525 insertions(+), 2 deletions(-) create mode 100644 private/bufpkg/bufimage/bufimageutil/testdata/options/pkg.Pkg.exclude.txtar diff --git a/CHANGELOG.md b/CHANGELOG.md index c35d07541b..b3cddd4d74 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## [Unreleased] -- No changes yet. +- Fix `exclude_type` on a non imported package. ## [v1.51.0] - 2025-03-28 diff --git a/private/bufpkg/bufimage/bufimageutil/bufimageutil_test.go b/private/bufpkg/bufimage/bufimageutil/bufimageutil_test.go index 6ff80ef10b..6279ac9e6f 100644 --- a/private/bufpkg/bufimage/bufimageutil/bufimageutil_test.go +++ b/private/bufpkg/bufimage/bufimageutil/bufimageutil_test.go @@ -101,6 +101,10 @@ func TestTypes(t *testing.T) { t.Parallel() runDiffTest(t, "testdata/options", "pkg.FooService.Do.exclude.txtar", WithExcludeTypes("pkg.FooService.Do")) }) + t.Run("exclude-package", func(t *testing.T) { + t.Parallel() + runDiffTest(t, "testdata/options", "pkg.Pkg.exclude.txtar", WithExcludeTypes("pkg")) + }) t.Run("exclude-all", func(t *testing.T) { t.Parallel() runDiffTest(t, "testdata/options", "all.exclude.txtar", WithExcludeTypes("pkg.Foo", "pkg.FooEnum", "pkg.FooService")) diff --git a/private/bufpkg/bufimage/bufimageutil/image_filter.go b/private/bufpkg/bufimage/bufimageutil/image_filter.go index 00335ea863..181c46acbe 100644 --- a/private/bufpkg/bufimage/bufimageutil/image_filter.go +++ b/private/bufpkg/bufimage/bufimageutil/image_filter.go @@ -56,7 +56,13 @@ func filterImage(image bufimage.Image, options *imageFilterOptions) (bufimage.Im if file.IsImport() { continue } - if err := closure.addElement(file.FileDescriptorProto(), "", false, imageIndex, options); err != nil { + // Check if target package is filtered, this is not an error. + // These includes are implicitly added to the closure. + fileDescriptorProto := file.FileDescriptorProto() + if mode := closure.elements[fileDescriptorProto]; mode == inclusionModeExcluded { + continue + } + if err := closure.addElement(fileDescriptorProto, "", false, imageIndex, options); err != nil { return nil, err } } diff --git a/private/bufpkg/bufimage/bufimageutil/testdata/options/pkg.Pkg.exclude.txtar b/private/bufpkg/bufimage/bufimageutil/testdata/options/pkg.Pkg.exclude.txtar new file mode 100644 index 0000000000..d0d5c46f43 --- /dev/null +++ b/private/bufpkg/bufimage/bufimageutil/testdata/options/pkg.Pkg.exclude.txtar @@ -0,0 +1,513 @@ +-- google/protobuf/descriptor.proto -- +syntax = "proto2"; +package google.protobuf; +option cc_enable_arenas = true; +option csharp_namespace = "Google.Protobuf.Reflection"; +option go_package = "google.golang.org/protobuf/types/descriptorpb"; +option java_outer_classname = "DescriptorProtos"; +option java_package = "com.google.protobuf"; +option objc_class_prefix = "GPB"; +option optimize_for = SPEED; +message DescriptorProto { + optional string name = 1; + repeated FieldDescriptorProto field = 2; + repeated DescriptorProto nested_type = 3; + repeated EnumDescriptorProto enum_type = 4; + repeated ExtensionRange extension_range = 5; + repeated FieldDescriptorProto extension = 6; + optional MessageOptions options = 7; + repeated OneofDescriptorProto oneof_decl = 8; + repeated ReservedRange reserved_range = 9; + repeated string reserved_name = 10; + message ExtensionRange { + optional int32 start = 1; + optional int32 end = 2; + optional ExtensionRangeOptions options = 3; + } + message ReservedRange { + optional int32 start = 1; + optional int32 end = 2; + } +} +message EnumDescriptorProto { + optional string name = 1; + repeated EnumValueDescriptorProto value = 2; + optional EnumOptions options = 3; + repeated EnumReservedRange reserved_range = 4; + repeated string reserved_name = 5; + message EnumReservedRange { + optional int32 start = 1; + optional int32 end = 2; + } +} +message EnumOptions { + optional bool allow_alias = 2; + optional bool deprecated = 3 [default = false]; + optional bool deprecated_legacy_json_field_conflicts = 6 [deprecated = true]; + optional FeatureSet features = 7; + repeated UninterpretedOption uninterpreted_option = 999; + extensions 1000 to max; + reserved 5; +} +message EnumValueDescriptorProto { + optional string name = 1; + optional int32 number = 2; + optional EnumValueOptions options = 3; +} +message EnumValueOptions { + optional bool deprecated = 1 [default = false]; + optional FeatureSet features = 2; + optional bool debug_redact = 3 [default = false]; + optional FieldOptions.FeatureSupport feature_support = 4; + repeated UninterpretedOption uninterpreted_option = 999; + extensions 1000 to max; +} +message ExtensionRangeOptions { + repeated Declaration declaration = 2 [retention = RETENTION_SOURCE]; + optional VerificationState verification = 3 [default = UNVERIFIED, retention = RETENTION_SOURCE]; + optional FeatureSet features = 50; + repeated UninterpretedOption uninterpreted_option = 999; + message Declaration { + optional int32 number = 1; + optional string full_name = 2; + optional string type = 3; + optional bool reserved = 5; + optional bool repeated = 6; + reserved 4; + } + enum VerificationState { + DECLARATION = 0; + UNVERIFIED = 1; + } + extensions 1000 to max; +} +message FeatureSet { + optional FieldPresence field_presence = 1 [ + edition_defaults = { value: "EXPLICIT", edition: EDITION_LEGACY }, + edition_defaults = { value: "IMPLICIT", edition: EDITION_PROTO3 }, + edition_defaults = { value: "EXPLICIT", edition: EDITION_2023 }, + feature_support = { edition_introduced: EDITION_2023 }, + retention = RETENTION_RUNTIME, + targets = TARGET_TYPE_FIELD, + targets = TARGET_TYPE_FILE + ]; + optional EnumType enum_type = 2 [ + edition_defaults = { value: "CLOSED", edition: EDITION_LEGACY }, + edition_defaults = { value: "OPEN", edition: EDITION_PROTO3 }, + feature_support = { edition_introduced: EDITION_2023 }, + retention = RETENTION_RUNTIME, + targets = TARGET_TYPE_ENUM, + targets = TARGET_TYPE_FILE + ]; + optional RepeatedFieldEncoding repeated_field_encoding = 3 [ + edition_defaults = { value: "EXPANDED", edition: EDITION_LEGACY }, + edition_defaults = { value: "PACKED", edition: EDITION_PROTO3 }, + feature_support = { edition_introduced: EDITION_2023 }, + retention = RETENTION_RUNTIME, + targets = TARGET_TYPE_FIELD, + targets = TARGET_TYPE_FILE + ]; + optional Utf8Validation utf8_validation = 4 [ + edition_defaults = { value: "NONE", edition: EDITION_LEGACY }, + edition_defaults = { value: "VERIFY", edition: EDITION_PROTO3 }, + feature_support = { edition_introduced: EDITION_2023 }, + retention = RETENTION_RUNTIME, + targets = TARGET_TYPE_FIELD, + targets = TARGET_TYPE_FILE + ]; + optional MessageEncoding message_encoding = 5 [ + edition_defaults = { value: "LENGTH_PREFIXED", edition: EDITION_LEGACY }, + feature_support = { edition_introduced: EDITION_2023 }, + retention = RETENTION_RUNTIME, + targets = TARGET_TYPE_FIELD, + targets = TARGET_TYPE_FILE + ]; + optional JsonFormat json_format = 6 [ + edition_defaults = { value: "LEGACY_BEST_EFFORT", edition: EDITION_LEGACY }, + edition_defaults = { value: "ALLOW", edition: EDITION_PROTO3 }, + feature_support = { edition_introduced: EDITION_2023 }, + retention = RETENTION_RUNTIME, + targets = TARGET_TYPE_MESSAGE, + targets = TARGET_TYPE_ENUM, + targets = TARGET_TYPE_FILE + ]; + enum EnumType { + ENUM_TYPE_UNKNOWN = 0; + OPEN = 1; + CLOSED = 2; + } + enum FieldPresence { + FIELD_PRESENCE_UNKNOWN = 0; + EXPLICIT = 1; + IMPLICIT = 2; + LEGACY_REQUIRED = 3; + } + enum JsonFormat { + JSON_FORMAT_UNKNOWN = 0; + ALLOW = 1; + LEGACY_BEST_EFFORT = 2; + } + enum MessageEncoding { + MESSAGE_ENCODING_UNKNOWN = 0; + LENGTH_PREFIXED = 1; + DELIMITED = 2; + } + enum RepeatedFieldEncoding { + REPEATED_FIELD_ENCODING_UNKNOWN = 0; + PACKED = 1; + EXPANDED = 2; + } + enum Utf8Validation { + UTF8_VALIDATION_UNKNOWN = 0; + VERIFY = 2; + NONE = 3; + reserved 1; + } + extensions 1000 to 9994 [ + declaration = { + number: 1000, + full_name: ".pb.cpp", + type: ".pb.CppFeatures" + }, + declaration = { + number: 1001, + full_name: ".pb.java", + type: ".pb.JavaFeatures" + }, + declaration = { + number: 1002, + full_name: ".pb.go", + type: ".pb.GoFeatures" + }, + declaration = { + number: 9990, + full_name: ".pb.proto1", + type: ".pb.Proto1Features" + } + ]; + extensions 9995 to 9999, 10000; + reserved 999; +} +message FeatureSetDefaults { + repeated FeatureSetEditionDefault defaults = 1; + optional Edition minimum_edition = 4; + optional Edition maximum_edition = 5; + message FeatureSetEditionDefault { + optional Edition edition = 3; + optional FeatureSet overridable_features = 4; + optional FeatureSet fixed_features = 5; + reserved 1, 2; + reserved "features"; + } +} +message FieldDescriptorProto { + optional string name = 1; + optional string extendee = 2; + optional int32 number = 3; + optional Label label = 4; + optional Type type = 5; + optional string type_name = 6; + optional string default_value = 7; + optional FieldOptions options = 8; + optional int32 oneof_index = 9; + optional string json_name = 10; + optional bool proto3_optional = 17; + enum Label { + LABEL_OPTIONAL = 1; + LABEL_REQUIRED = 2; + LABEL_REPEATED = 3; + } + enum Type { + TYPE_DOUBLE = 1; + TYPE_FLOAT = 2; + TYPE_INT64 = 3; + TYPE_UINT64 = 4; + TYPE_INT32 = 5; + TYPE_FIXED64 = 6; + TYPE_FIXED32 = 7; + TYPE_BOOL = 8; + TYPE_STRING = 9; + TYPE_GROUP = 10; + TYPE_MESSAGE = 11; + TYPE_BYTES = 12; + TYPE_UINT32 = 13; + TYPE_ENUM = 14; + TYPE_SFIXED32 = 15; + TYPE_SFIXED64 = 16; + TYPE_SINT32 = 17; + TYPE_SINT64 = 18; + } +} +message FieldOptions { + optional CType ctype = 1 [default = STRING]; + optional bool packed = 2; + optional bool deprecated = 3 [default = false]; + optional bool lazy = 5 [default = false]; + optional JSType jstype = 6 [default = JS_NORMAL]; + optional bool weak = 10 [default = false]; + optional bool unverified_lazy = 15 [default = false]; + optional bool debug_redact = 16 [default = false]; + optional OptionRetention retention = 17; + repeated OptionTargetType targets = 19; + repeated EditionDefault edition_defaults = 20; + optional FeatureSet features = 21; + optional FeatureSupport feature_support = 22; + repeated UninterpretedOption uninterpreted_option = 999; + message EditionDefault { + optional string value = 2; + optional Edition edition = 3; + } + message FeatureSupport { + optional Edition edition_introduced = 1; + optional Edition edition_deprecated = 2; + optional string deprecation_warning = 3; + optional Edition edition_removed = 4; + } + enum CType { + STRING = 0; + CORD = 1; + STRING_PIECE = 2; + } + enum JSType { + JS_NORMAL = 0; + JS_STRING = 1; + JS_NUMBER = 2; + } + enum OptionRetention { + RETENTION_UNKNOWN = 0; + RETENTION_RUNTIME = 1; + RETENTION_SOURCE = 2; + } + enum OptionTargetType { + TARGET_TYPE_UNKNOWN = 0; + TARGET_TYPE_FILE = 1; + TARGET_TYPE_EXTENSION_RANGE = 2; + TARGET_TYPE_MESSAGE = 3; + TARGET_TYPE_FIELD = 4; + TARGET_TYPE_ONEOF = 5; + TARGET_TYPE_ENUM = 6; + TARGET_TYPE_ENUM_ENTRY = 7; + TARGET_TYPE_SERVICE = 8; + TARGET_TYPE_METHOD = 9; + } + extensions 1000 to max; + reserved 4, 18; +} +message FileDescriptorProto { + optional string name = 1; + optional string package = 2; + repeated string dependency = 3; + repeated DescriptorProto message_type = 4; + repeated EnumDescriptorProto enum_type = 5; + repeated ServiceDescriptorProto service = 6; + repeated FieldDescriptorProto extension = 7; + optional FileOptions options = 8; + optional SourceCodeInfo source_code_info = 9; + repeated int32 public_dependency = 10; + repeated int32 weak_dependency = 11; + optional string syntax = 12; + optional Edition edition = 14; +} +message FileDescriptorSet { + repeated FileDescriptorProto file = 1; + extensions 536000000 [ + declaration = { + number: 536000000, + full_name: ".buf.descriptor.v1.buf_file_descriptor_set_extension", + type: ".buf.descriptor.v1.FileDescriptorSetExtension" + } + ]; +} +message FileOptions { + optional string java_package = 1; + optional string java_outer_classname = 8; + optional OptimizeMode optimize_for = 9 [default = SPEED]; + optional bool java_multiple_files = 10 [default = false]; + optional string go_package = 11; + optional bool cc_generic_services = 16 [default = false]; + optional bool java_generic_services = 17 [default = false]; + optional bool py_generic_services = 18 [default = false]; + optional bool java_generate_equals_and_hash = 20 [deprecated = true]; + optional bool deprecated = 23 [default = false]; + optional bool java_string_check_utf8 = 27 [default = false]; + optional bool cc_enable_arenas = 31 [default = true]; + optional string objc_class_prefix = 36; + optional string csharp_namespace = 37; + optional string swift_prefix = 39; + optional string php_class_prefix = 40; + optional string php_namespace = 41; + optional string php_metadata_namespace = 44; + optional string ruby_package = 45; + optional FeatureSet features = 50; + repeated UninterpretedOption uninterpreted_option = 999; + enum OptimizeMode { + SPEED = 1; + CODE_SIZE = 2; + LITE_RUNTIME = 3; + } + extensions 1000 to max; + reserved 38, 42; + reserved "php_generic_services"; +} +message GeneratedCodeInfo { + repeated Annotation annotation = 1; + message Annotation { + repeated int32 path = 1 [packed = true]; + optional string source_file = 2; + optional int32 begin = 3; + optional int32 end = 4; + optional Semantic semantic = 5; + enum Semantic { + NONE = 0; + SET = 1; + ALIAS = 2; + } + } +} +message MessageOptions { + optional bool message_set_wire_format = 1 [default = false]; + optional bool no_standard_descriptor_accessor = 2 [default = false]; + optional bool deprecated = 3 [default = false]; + optional bool map_entry = 7; + optional bool deprecated_legacy_json_field_conflicts = 11 [deprecated = true]; + optional FeatureSet features = 12; + repeated UninterpretedOption uninterpreted_option = 999; + extensions 1000 to max; + reserved 4, 5, 6, 8, 9; +} +message MethodDescriptorProto { + optional string name = 1; + optional string input_type = 2; + optional string output_type = 3; + optional MethodOptions options = 4; + optional bool client_streaming = 5 [default = false]; + optional bool server_streaming = 6 [default = false]; +} +message MethodOptions { + optional bool deprecated = 33 [default = false]; + optional IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN]; + optional FeatureSet features = 35; + repeated UninterpretedOption uninterpreted_option = 999; + enum IdempotencyLevel { + IDEMPOTENCY_UNKNOWN = 0; + NO_SIDE_EFFECTS = 1; + IDEMPOTENT = 2; + } + extensions 1000 to max; +} +message OneofDescriptorProto { + optional string name = 1; + optional OneofOptions options = 2; +} +message OneofOptions { + optional FeatureSet features = 1; + repeated UninterpretedOption uninterpreted_option = 999; + extensions 1000 to max; +} +message ServiceDescriptorProto { + optional string name = 1; + repeated MethodDescriptorProto method = 2; + optional ServiceOptions options = 3; +} +message ServiceOptions { + optional bool deprecated = 33 [default = false]; + optional FeatureSet features = 34; + repeated UninterpretedOption uninterpreted_option = 999; + extensions 1000 to max; +} +message SourceCodeInfo { + repeated Location location = 1; + message Location { + repeated int32 path = 1 [packed = true]; + repeated int32 span = 2 [packed = true]; + optional string leading_comments = 3; + optional string trailing_comments = 4; + repeated string leading_detached_comments = 6; + } + extensions 536000000 [ + declaration = { + number: 536000000, + full_name: ".buf.descriptor.v1.buf_source_code_info_extension", + type: ".buf.descriptor.v1.SourceCodeInfoExtension" + } + ]; +} +message UninterpretedOption { + repeated NamePart name = 2; + optional string identifier_value = 3; + optional uint64 positive_int_value = 4; + optional int64 negative_int_value = 5; + optional double double_value = 6; + optional bytes string_value = 7; + optional string aggregate_value = 8; + message NamePart { + required string name_part = 1; + required bool is_extension = 2; + } +} +enum Edition { + EDITION_UNKNOWN = 0; + EDITION_1_TEST_ONLY = 1; + EDITION_2_TEST_ONLY = 2; + EDITION_LEGACY = 900; + EDITION_PROTO2 = 998; + EDITION_PROTO3 = 999; + EDITION_2023 = 1000; + EDITION_2024 = 1001; + EDITION_99997_TEST_ONLY = 99997; + EDITION_99998_TEST_ONLY = 99998; + EDITION_99999_TEST_ONLY = 99999; + EDITION_MAX = 2147483647; +} +-- options.proto -- +syntax = "proto3"; +import "google/protobuf/descriptor.proto"; +message Files { + google.protobuf.FileDescriptorSet files = 1; +} +message UnusedOption { + string foo = 1; +} +message UsedOption { + string foo = 1; + extend google.protobuf.FileOptions { + UsedOption file_foo = 50000; + UnusedOption file_bar = 50001; + string file_baz = 50002; + } +} +extend google.protobuf.EnumOptions { + UsedOption enum_foo = 50000; + UnusedOption enum_bar = 50001; + string enum_baz = 50002; +} +extend google.protobuf.EnumValueOptions { + UsedOption enum_value_foo = 50000; + UnusedOption enum_value_bar = 50001; + string enum_value_baz = 50002; +} +extend google.protobuf.FieldOptions { + UsedOption field_foo = 50000; + UnusedOption field_bar = 50001; + string field_baz = 50002; +} +extend google.protobuf.MessageOptions { + UsedOption message_foo = 50000; + UnusedOption message_bar = 50001; + string message_baz = 50002; +} +extend google.protobuf.MethodOptions { + UsedOption method_foo = 50000; + UnusedOption method_bar = 50001; + string method_baz = 50002; +} +extend google.protobuf.OneofOptions { + UsedOption oneof_foo = 50000; + UnusedOption oneof_bar = 50001; + string oneof_baz = 50002; +} +extend google.protobuf.ServiceOptions { + UsedOption service_foo = 50000; + UnusedOption service_bar = 50001; + string service_baz = 50002; +}