From 9952e36f92cfff9ca0ec4d43a5ff146d26f64a01 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Sat, 16 May 2020 16:42:02 -0700 Subject: [PATCH] Merge release branch into master. (#7517) * Added background information about proto3 presence. (#7501) * Fixed bug in map key sorting for Java TextFormat. (#7508) Fixes: https://github.com/protocolbuffers/protobuf/issues/7505 * Update protobuf version * Added a changelog entry about the Java fix. (#7516) --- CHANGES.txt | 1 + Protobuf-C++.podspec | 2 +- Protobuf.podspec | 2 +- configure.ac | 2 +- csharp/Google.Protobuf.Tools.nuspec | 2 +- .../Google.Protobuf/Google.Protobuf.csproj | 2 +- docs/implementing_proto3_presence.md | 50 +++++++++++++++++++ java/bom/pom.xml | 2 +- java/core/pom.xml | 2 +- .../java/com/google/protobuf/TextFormat.java | 22 ++------ .../com/google/protobuf/TextFormatTest.java | 21 ++++++++ java/lite/pom.xml | 2 +- java/pom.xml | 2 +- java/util/pom.xml | 2 +- js/package.json | 2 +- php/ext/google/protobuf/package.xml | 24 +++++++-- php/ext/google/protobuf/protobuf.h | 2 +- protoc-artifacts/pom.xml | 2 +- python/google/protobuf/__init__.py | 2 +- ruby/google-protobuf.gemspec | 2 +- 20 files changed, 109 insertions(+), 39 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 317930626e16..6234f1635d1d 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -44,6 +44,7 @@ * Mark java enum _VALUE constants as @Deprecated if the enum field is deprecated * reduce size for enums with allow_alias set to true. * Sort map fields alphabetically by the field's key when printing textproto. + * Fixed a bug in map sorting that appeared in -rc1 and -rc2 (#7508). * TextFormat.merge() handles Any as top level type. * Throw a descriptive IllegalArgumentException when calling getValueDescriptor() on enum special value UNRECOGNIZED instead of diff --git a/Protobuf-C++.podspec b/Protobuf-C++.podspec index f6536fd095ca..a472bf57e404 100644 --- a/Protobuf-C++.podspec +++ b/Protobuf-C++.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'Protobuf-C++' - s.version = '3.12.0-rc2' + s.version = '3.12.0' s.summary = 'Protocol Buffers v3 runtime library for C++.' s.homepage = 'https://github.com/google/protobuf' s.license = '3-Clause BSD License' diff --git a/Protobuf.podspec b/Protobuf.podspec index 5fe982a7f760..5ff3597e0ee2 100644 --- a/Protobuf.podspec +++ b/Protobuf.podspec @@ -5,7 +5,7 @@ # dependent projects use the :git notation to refer to the library. Pod::Spec.new do |s| s.name = 'Protobuf' - s.version = '3.12.0-rc2' + s.version = '3.12.0' s.summary = 'Protocol Buffers v.3 runtime library for Objective-C.' s.homepage = 'https://github.com/protocolbuffers/protobuf' s.license = '3-Clause BSD License' diff --git a/configure.ac b/configure.ac index b94fe1006a7f..d05b327ec3b7 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ AC_PREREQ(2.59) # In the SVN trunk, the version should always be the next anticipated release # version with the "-pre" suffix. (We used to use "-SNAPSHOT" but this pushed # the size of one file name in the dist tarfile over the 99-char limit.) -AC_INIT([Protocol Buffers],[3.12.0-rc-2],[protobuf@googlegroups.com],[protobuf]) +AC_INIT([Protocol Buffers],[3.12.0],[protobuf@googlegroups.com],[protobuf]) AM_MAINTAINER_MODE([enable]) diff --git a/csharp/Google.Protobuf.Tools.nuspec b/csharp/Google.Protobuf.Tools.nuspec index e2a46ce4fe7e..d28a44e0ef87 100644 --- a/csharp/Google.Protobuf.Tools.nuspec +++ b/csharp/Google.Protobuf.Tools.nuspec @@ -5,7 +5,7 @@ Google Protocol Buffers tools Tools for Protocol Buffers - Google's data interchange format. See project site for more info. - 3.12.0-rc2 + 3.12.0 Google Inc. protobuf-packages https://github.com/protocolbuffers/protobuf/blob/master/LICENSE diff --git a/csharp/src/Google.Protobuf/Google.Protobuf.csproj b/csharp/src/Google.Protobuf/Google.Protobuf.csproj index 5c5b4e7b0b04..3ceb832cc715 100644 --- a/csharp/src/Google.Protobuf/Google.Protobuf.csproj +++ b/csharp/src/Google.Protobuf/Google.Protobuf.csproj @@ -4,7 +4,7 @@ C# runtime library for Protocol Buffers - Google's data interchange format. Copyright 2015, Google Inc. Google Protocol Buffers - 3.12.0-rc2 + 3.12.0 7.2 Google Inc. diff --git a/docs/implementing_proto3_presence.md b/docs/implementing_proto3_presence.md index 08f9c513211e..fae2eb589ab7 100644 --- a/docs/implementing_proto3_presence.md +++ b/docs/implementing_proto3_presence.md @@ -5,6 +5,8 @@ proto3. Proto3 optional fields track presence like in proto2. For background information about what presence tracking means, please see [docs/field_presence](field_presence.md). +## Document Summary + This document is targeted at developers who own or maintain protobuf code generators. All code generators will need to be updated to support proto3 optional fields. First-party code generators developed by Google are being @@ -14,6 +16,7 @@ independently by their authors. This includes: - implementations of Protocol Buffers for other languges. - alternate implementations of Protocol Buffers that target specialized use cases. +- RPC code generators that create generated APIs for service calls. - code generators that implement some utility code on top of protobuf generated classes. @@ -21,6 +24,53 @@ While this document speaks in terms of "code generators", these same principles apply to implementations that dynamically generate a protocol buffer API "on the fly", directly from a descriptor, in languages that support this kind of usage. +## Background + +Presence tracking was added to proto3 in response to user feedback, both from +inside Google and [from open-source +users](https://github.com/protocolbuffers/protobuf/issues/1606). The [proto3 +wrapper +types](https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/wrappers.proto) +were previously the only supported presence mechanism for proto3. Users have +pointed to both efficiency and usability issues with the wrapper types. + +Presence in proto3 uses exactly the same syntax and semantics as in proto2. +Proto3 Fields marked `optional` will track presence like proto2, while fields +without any label (known as "singular fields"), will continue to omit presence +information. The `optional` keyword was chosen to minimize differences with +proto2. + +Unfortunately, for the current descriptor protos and `Descriptor` API (as of +3.11.4) it is not possible to use the same representation as proto2. Proto3 +descriptors already use `LABEL_OPTIONAL` for proto3 singular fields, which do +not track presence. There is a lot of existing code that reflects over proto3 +protos and assumes that `LABEL_OPTIONAL` in proto3 means "no presence." Changing +the semantics now would be risky, since old software would likely drop proto3 +presence information, which would be a data loss bug. + +To minimize this risk we chose a descriptor representation that is semantically +compatible with existing proto3 reflection. Every proto3 optional field is +placed into a one-field `oneof`. We call this a "synthetic" oneof, as it was not +present in the source `.proto` file. + +Since oneof fields in proto3 already track presence, existing proto3 +reflection-based algorithms should correctly preserve presence for proto3 +optional fields with no code changes. For example, the JSON and TextFormat +parsers/serializers in C++ and Java did not require any changes to support +proto3 presence. This is the major benefit of synthetic oneofs. + +This design does leave some cruft in descriptors. Synthetic oneofs are a +compatibility measure that we can hopefully clean up in the future. For now +though, it is important to preserve them across different descriptor formats and +APIs. It is never safe to drop synthetic oneofs from a proto schema. Code +generators can (and should) skip synthetic oneofs when generating a user-facing +API or user-facing documentation. But for any schema representation that is +consumed programmatically, it is important to keep the synthetic oneofs around. + +In APIs it can be helpful to offer separate accessors that refer to "real" +oneofs (see [API Changes](#api-changes) below). This is a convenient way to omit +synthetic oneofs in code generators. + ## Updating a Code Generator When a user adds an `optional` field to proto3, this is internally rewritten as diff --git a/java/bom/pom.xml b/java/bom/pom.xml index 04bd3f5bda8a..6fca4aa45b03 100644 --- a/java/bom/pom.xml +++ b/java/bom/pom.xml @@ -4,7 +4,7 @@ com.google.protobuf protobuf-bom - 3.12.0-rc-2 + 3.12.0 pom Protocol Buffers [BOM] diff --git a/java/core/pom.xml b/java/core/pom.xml index 5fb50459555d..1bbf90e0e95f 100644 --- a/java/core/pom.xml +++ b/java/core/pom.xml @@ -4,7 +4,7 @@ com.google.protobuf protobuf-parent - 3.12.0-rc-2 + 3.12.0 protobuf-java diff --git a/java/core/src/main/java/com/google/protobuf/TextFormat.java b/java/core/src/main/java/com/google/protobuf/TextFormat.java index 673343d4ea05..bec9623fe81b 100644 --- a/java/core/src/main/java/com/google/protobuf/TextFormat.java +++ b/java/core/src/main/java/com/google/protobuf/TextFormat.java @@ -490,27 +490,11 @@ public int compareTo(MapEntryAdapter b) { } switch (fieldType) { case BOOLEAN: - boolean aBoolean = (boolean) getKey(); - boolean bBoolean = (boolean) b.getKey(); - if (aBoolean == bBoolean) { - return 0; - } else if (aBoolean) { - return 1; - } else { - return -1; - } + return Boolean.compare((boolean) getKey(), (boolean) b.getKey()); case LONG: - long aLong = (long) getKey(); - long bLong = (long) b.getKey(); - if (aLong < bLong) { - return -1; - } else if (aLong > bLong) { - return 1; - } else { - return 0; - } + return Long.compare((long) getKey(), (long) b.getKey()); case INT: - return (int) getKey() - (int) b.getKey(); + return Integer.compare((int) getKey(), (int) b.getKey()); case STRING: String aString = (String) getKey(); String bString = (String) b.getKey(); diff --git a/java/core/src/test/java/com/google/protobuf/TextFormatTest.java b/java/core/src/test/java/com/google/protobuf/TextFormatTest.java index 6ca3ae111fff..dc75f842ef49 100644 --- a/java/core/src/test/java/com/google/protobuf/TextFormatTest.java +++ b/java/core/src/test/java/com/google/protobuf/TextFormatTest.java @@ -1404,6 +1404,27 @@ public void testMapTextFormat() throws Exception { } } + public void testMapDuplicateKeys() throws Exception { + String input = + "int32_to_int32_field: {\n" + + " key: 1\n" + + " value: 1\n" + + "}\n" + + "int32_to_int32_field: {\n" + + " key: -2147483647\n" + + " value: 5\n" + + "}\n" + + "int32_to_int32_field: {\n" + + " key: 1\n" + + " value: -1\n" + + "}\n"; + TestMap msg = TextFormat.parse(input, TestMap.class); + int val1 = msg.getInt32ToInt32Field().get(1); + TestMap msg2 = TextFormat.parse(msg.toString(), TestMap.class); + int val2 = msg2.getInt32ToInt32Field().get(1); + assertEquals(val1, val2); + } + public void testMapShortForm() throws Exception { String text = "string_to_int32_field [{ key: 'x' value: 10 }, { key: 'y' value: 20 }]\n" diff --git a/java/lite/pom.xml b/java/lite/pom.xml index 6ce28ee5e137..c5901a2c3f16 100644 --- a/java/lite/pom.xml +++ b/java/lite/pom.xml @@ -4,7 +4,7 @@ com.google.protobuf protobuf-parent - 3.12.0-rc-2 + 3.12.0 protobuf-javalite diff --git a/java/pom.xml b/java/pom.xml index eb15314247f1..706e43dd8b2b 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -4,7 +4,7 @@ com.google.protobuf protobuf-parent - 3.12.0-rc-2 + 3.12.0 pom Protocol Buffers [Parent] diff --git a/java/util/pom.xml b/java/util/pom.xml index b7d96766f710..5d2cbc008183 100644 --- a/java/util/pom.xml +++ b/java/util/pom.xml @@ -4,7 +4,7 @@ com.google.protobuf protobuf-parent - 3.12.0-rc-2 + 3.12.0 protobuf-java-util diff --git a/js/package.json b/js/package.json index 0b2adb81a1e8..766052ebe6c5 100644 --- a/js/package.json +++ b/js/package.json @@ -1,6 +1,6 @@ { "name": "google-protobuf", - "version": "3.12.0-rc.2", + "version": "3.12.0", "description": "Protocol Buffers for JavaScript", "main": "google-protobuf.js", "files": [ diff --git a/php/ext/google/protobuf/package.xml b/php/ext/google/protobuf/package.xml index 4b9066a32d7e..687c43de0f75 100644 --- a/php/ext/google/protobuf/package.xml +++ b/php/ext/google/protobuf/package.xml @@ -10,15 +10,15 @@ protobuf-opensource@google.com yes - 2020-05-12 - + 2020-05-15 + - 3.12.0RC2 + 3.12.0 3.12.0 - beta - beta + stable + stable 3-Clause BSD License GA release. @@ -557,5 +557,19 @@ G A release. 3-Clause BSD License GA release. + + + 3.12.0 + 3.12.0 + + + stable + stable + + 2020-05-15 + + 3-Clause BSD License + GA release. + diff --git a/php/ext/google/protobuf/protobuf.h b/php/ext/google/protobuf/protobuf.h index bc293b8030d8..4f40ec224b9c 100644 --- a/php/ext/google/protobuf/protobuf.h +++ b/php/ext/google/protobuf/protobuf.h @@ -37,7 +37,7 @@ #include "upb.h" #define PHP_PROTOBUF_EXTNAME "protobuf" -#define PHP_PROTOBUF_VERSION "3.12.0RC2" +#define PHP_PROTOBUF_VERSION "3.12.0" #define MAX_LENGTH_OF_INT64 20 #define SIZEOF_INT64 8 diff --git a/protoc-artifacts/pom.xml b/protoc-artifacts/pom.xml index ae72dbbfa6c9..c64afb1d7d45 100644 --- a/protoc-artifacts/pom.xml +++ b/protoc-artifacts/pom.xml @@ -8,7 +8,7 @@ com.google.protobuf protoc - 3.12.0-rc-2 + 3.12.0 pom Protobuf Compiler diff --git a/python/google/protobuf/__init__.py b/python/google/protobuf/__init__.py index cee24d7ab1f5..7861888ae5ee 100644 --- a/python/google/protobuf/__init__.py +++ b/python/google/protobuf/__init__.py @@ -30,7 +30,7 @@ # Copyright 2007 Google Inc. All Rights Reserved. -__version__ = '3.12.0rc2' +__version__ = '3.12.0' if __name__ != '__main__': try: diff --git a/ruby/google-protobuf.gemspec b/ruby/google-protobuf.gemspec index 29af94801a18..17df6fec5008 100644 --- a/ruby/google-protobuf.gemspec +++ b/ruby/google-protobuf.gemspec @@ -1,6 +1,6 @@ Gem::Specification.new do |s| s.name = "google-protobuf" - s.version = "3.12.0.rc.2" + s.version = "3.12.0" git_tag = "v#{s.version.to_s.sub('.rc.', '-rc')}" # Converts X.Y.Z.rc.N to vX.Y.Z-rcN, used for the git tag s.licenses = ["BSD-3-Clause"] s.summary = "Protocol Buffers"