Merge "GetRelatedIT.getRelatedManyGroups: Remove unused commit list"
diff --git a/Documentation/metrics.txt b/Documentation/metrics.txt
index db6f883..ced4609 100644
--- a/Documentation/metrics.txt
+++ b/Documentation/metrics.txt
@@ -140,9 +140,6 @@
* `notedb/stage_update_latency`: Latency for staging updates to NoteDb by table.
* `notedb/read_latency`: NoteDb read latency by table.
* `notedb/parse_latency`: NoteDb parse latency by table.
-* `notedb/auto_rebuild_latency`: NoteDb auto-rebuilding latency by table.
-* `notedb/auto_rebuild_failure_count`: NoteDb auto-rebuilding attempts that
-failed by table.
* `notedb/external_id_update_count`: Total number of external ID updates.
* `notedb/read_all_external_ids_latency`: Latency for reading all
external ID's from NoteDb.
diff --git a/java/com/google/gerrit/acceptance/AbstractDaemonTest.java b/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
index eae3e6b..6e3b100 100644
--- a/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
+++ b/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
@@ -112,9 +112,10 @@
import com.google.gerrit.server.index.change.ChangeIndexCollection;
import com.google.gerrit.server.index.change.ChangeIndexer;
import com.google.gerrit.server.index.group.GroupIndexer;
+import com.google.gerrit.server.notedb.AbstractChangeNotes;
import com.google.gerrit.server.notedb.ChangeNoteUtil;
import com.google.gerrit.server.notedb.ChangeNotes;
-import com.google.gerrit.server.notedb.MutableNotesMigration;
+import com.google.gerrit.server.notedb.NotesMigration;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectConfig;
import com.google.gerrit.server.project.testing.Util;
@@ -126,7 +127,6 @@
import com.google.gerrit.testing.FakeEmailSender;
import com.google.gerrit.testing.FakeEmailSender.Message;
import com.google.gerrit.testing.FakeGroupAuditService;
-import com.google.gerrit.testing.NoteDbMode;
import com.google.gerrit.testing.SshMode;
import com.google.gson.Gson;
import com.google.gwtorm.server.OrmException;
@@ -261,7 +261,7 @@
@Inject protected PluginConfigFactory pluginConfig;
@Inject protected Revisions revisions;
@Inject protected SystemGroupBackend systemGroupBackend;
- @Inject protected MutableNotesMigration notesMigration;
+ @Inject protected NotesMigration notesMigration;
@Inject protected ChangeNotes.Factory notesFactory;
@Inject protected BatchAbandon batchAbandon;
@Inject protected TestSshKeys sshKeys;
@@ -293,6 +293,7 @@
@Inject private AccountIndexer accountIndexer;
@Inject private Groups groups;
@Inject private GroupIndexer groupIndexer;
+ @Inject private AbstractChangeNotes.Args changeNotesArgs;
private ProjectResetter resetter;
private List<Repository> toClose;
@@ -596,7 +597,6 @@
server.close();
server = null;
}
- NoteDbMode.resetFromEnv(notesMigration);
}
protected void closeSsh() {
@@ -837,12 +837,12 @@
}
protected Context disableDb() {
- notesMigration.setFailOnLoadForTest(true);
+ changeNotesArgs.failOnLoadForTest.set(true);
return atrScope.disableDb();
}
protected void enableDb(Context preDisableContext) {
- notesMigration.setFailOnLoadForTest(false);
+ changeNotesArgs.failOnLoadForTest.set(false);
atrScope.set(preDisableContext);
}
@@ -1184,11 +1184,6 @@
}
@Nullable
- protected RevCommit getRemoteHead(String project, String branch) throws Exception {
- return getRemoteHead(new Project.NameKey(project), branch);
- }
-
- @Nullable
protected RevCommit getRemoteHead() throws Exception {
return getRemoteHead(project, "master");
}
diff --git a/java/com/google/gerrit/acceptance/GerritServer.java b/java/com/google/gerrit/acceptance/GerritServer.java
index 4788ab7..077dd65 100644
--- a/java/com/google/gerrit/acceptance/GerritServer.java
+++ b/java/com/google/gerrit/acceptance/GerritServer.java
@@ -45,7 +45,6 @@
import com.google.gerrit.testing.FakeEmailSender;
import com.google.gerrit.testing.FakeGroupAuditService;
import com.google.gerrit.testing.InMemoryRepositoryManager;
-import com.google.gerrit.testing.NoteDbMode;
import com.google.gerrit.testing.SshMode;
import com.google.inject.AbstractModule;
import com.google.inject.Injector;
@@ -482,8 +481,6 @@
cfg.setInt("receive", null, "threadPoolSize", 1);
cfg.setInt("index", null, "threads", 1);
cfg.setBoolean("index", null, "reindexAfterRefUpdate", false);
-
- NoteDbMode.newNotesMigrationFromEnv().setConfigValues(cfg);
}
private static Injector createTestInjector(Daemon daemon) throws Exception {
diff --git a/java/com/google/gerrit/acceptance/InMemoryTestingDatabaseModule.java b/java/com/google/gerrit/acceptance/InMemoryTestingDatabaseModule.java
index e15d162..9c4b6b7 100644
--- a/java/com/google/gerrit/acceptance/InMemoryTestingDatabaseModule.java
+++ b/java/com/google/gerrit/acceptance/InMemoryTestingDatabaseModule.java
@@ -28,7 +28,6 @@
import com.google.gerrit.server.config.TrackingFooters;
import com.google.gerrit.server.config.TrackingFootersProvider;
import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.notedb.NotesMigration;
import com.google.gerrit.server.schema.NotesMigrationSchemaFactory;
import com.google.gerrit.server.schema.ReviewDbFactory;
import com.google.gerrit.server.schema.ReviewDbSchemaModule;
@@ -75,7 +74,6 @@
bind(MetricMaker.class).to(DisabledMetricMaker.class);
- install(new NotesMigration.Module());
TypeLiteral<SchemaFactory<ReviewDb>> schemaFactory =
new TypeLiteral<SchemaFactory<ReviewDb>>() {};
bind(schemaFactory).to(NotesMigrationSchemaFactory.class);
diff --git a/java/com/google/gerrit/acceptance/PushOneCommit.java b/java/com/google/gerrit/acceptance/PushOneCommit.java
index d0735c8..99e07ea 100644
--- a/java/com/google/gerrit/acceptance/PushOneCommit.java
+++ b/java/com/google/gerrit/acceptance/PushOneCommit.java
@@ -141,7 +141,6 @@
private final ChangeNotes.Factory notesFactory;
private final ApprovalsUtil approvalsUtil;
private final Provider<InternalChangeQuery> queryProvider;
- private final ReviewDb db;
private final TestRepository<?> testRepo;
private final String subject;
@@ -265,14 +264,14 @@
ChangeNotes.Factory notesFactory,
ApprovalsUtil approvalsUtil,
Provider<InternalChangeQuery> queryProvider,
- ReviewDb db,
+ // TODO(ekempin): Remove unused ReviewDb
+ @SuppressWarnings("unused") ReviewDb db,
PersonIdent i,
TestRepository<?> testRepo,
String subject,
Map<String, String> files,
String changeId)
throws Exception {
- this.db = db;
this.testRepo = testRepo;
this.notesFactory = notesFactory;
this.approvalsUtil = approvalsUtil;
@@ -419,7 +418,7 @@
Change c, ReviewerStateInternal state, List<TestAccount> expectedReviewers)
throws OrmException {
Iterable<Account.Id> actualIds =
- approvalsUtil.getReviewers(notesFactory.createChecked(db, c)).byState(state);
+ approvalsUtil.getReviewers(notesFactory.createChecked(c)).byState(state);
assertThat(actualIds)
.containsExactlyElementsIn(Sets.newHashSet(TestAccount.ids(expectedReviewers)));
}
diff --git a/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java b/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java
index 3b589b2..cbfd1ca 100644
--- a/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java
+++ b/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java
@@ -15,15 +15,15 @@
package com.google.gerrit.elasticsearch;
import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.gson.FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES;
import static java.nio.charset.StandardCharsets.UTF_8;
-import static org.apache.commons.codec.binary.Base64.decodeBase64;
import com.google.common.collect.ArrayListMultimap;
-import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Lists;
+import com.google.common.collect.Streams;
import com.google.common.flogger.FluentLogger;
import com.google.common.io.CharStreams;
import com.google.gerrit.common.Nullable;
@@ -40,6 +40,8 @@
import com.google.gerrit.index.query.FieldBundle;
import com.google.gerrit.index.query.Predicate;
import com.google.gerrit.index.query.QueryParseException;
+import com.google.gerrit.proto.Protos;
+import com.google.gerrit.reviewdb.converter.ProtoConverter;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.index.IndexUtils;
import com.google.gson.Gson;
@@ -48,9 +50,9 @@
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
-import com.google.gwtorm.protobuf.ProtobufCodec;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.ResultSet;
+import com.google.protobuf.MessageLite;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@@ -85,14 +87,22 @@
protected static final String SETTINGS = "settings";
protected static <T> List<T> decodeProtos(
- JsonObject doc, String fieldName, ProtobufCodec<T> codec) {
+ JsonObject doc, String fieldName, ProtoConverter<?, T> converter) {
JsonArray field = doc.getAsJsonArray(fieldName);
if (field == null) {
return null;
}
- return FluentIterable.from(field)
- .transform(i -> codec.decode(decodeBase64(i.toString())))
- .toList();
+ return Streams.stream(field)
+ .map(JsonElement::toString)
+ .map(Base64::decodeBase64)
+ .map(bytes -> parseProtoFrom(bytes, converter))
+ .collect(toImmutableList());
+ }
+
+ private static <P extends MessageLite, T> T parseProtoFrom(
+ byte[] bytes, ProtoConverter<P, T> converter) {
+ P message = Protos.parseUnchecked(converter.getParser(), bytes);
+ return converter.fromProto(message);
}
static String getContent(Response response) throws IOException {
diff --git a/java/com/google/gerrit/elasticsearch/BUILD b/java/com/google/gerrit/elasticsearch/BUILD
index 8d23051..d5c586b 100644
--- a/java/com/google/gerrit/elasticsearch/BUILD
+++ b/java/com/google/gerrit/elasticsearch/BUILD
@@ -9,6 +9,7 @@
"//java/com/google/gerrit/index:query_exception",
"//java/com/google/gerrit/index/project",
"//java/com/google/gerrit/lifecycle",
+ "//java/com/google/gerrit/proto",
"//java/com/google/gerrit/reviewdb:server",
"//java/com/google/gerrit/server",
"//lib:gson",
diff --git a/java/com/google/gerrit/elasticsearch/ElasticChangeIndex.java b/java/com/google/gerrit/elasticsearch/ElasticChangeIndex.java
index 1224c61..9aa65a7 100644
--- a/java/com/google/gerrit/elasticsearch/ElasticChangeIndex.java
+++ b/java/com/google/gerrit/elasticsearch/ElasticChangeIndex.java
@@ -14,9 +14,7 @@
package com.google.gerrit.elasticsearch;
-import static com.google.gerrit.reviewdb.server.ReviewDbCodecs.APPROVAL_CODEC;
import static com.google.gerrit.reviewdb.server.ReviewDbCodecs.CHANGE_CODEC;
-import static com.google.gerrit.reviewdb.server.ReviewDbCodecs.PATCH_SET_CODEC;
import static com.google.gerrit.server.index.change.ChangeIndexRewriter.CLOSED_STATUSES;
import static com.google.gerrit.server.index.change.ChangeIndexRewriter.OPEN_STATUSES;
import static java.nio.charset.StandardCharsets.UTF_8;
@@ -45,6 +43,8 @@
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Change.Id;
import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.converter.PatchSetApprovalProtoConverter;
+import com.google.gerrit.reviewdb.converter.PatchSetProtoConverter;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.ReviewerByEmailSet;
import com.google.gerrit.server.ReviewerSet;
@@ -230,11 +230,14 @@
// Any decoding that is done here must also be done in {@link LuceneChangeIndex}.
// Patch sets.
- cd.setPatchSets(decodeProtos(source, ChangeField.PATCH_SET.getName(), PATCH_SET_CODEC));
+ cd.setPatchSets(
+ decodeProtos(source, ChangeField.PATCH_SET.getName(), PatchSetProtoConverter.INSTANCE));
// Approvals.
if (source.get(ChangeField.APPROVAL.getName()) != null) {
- cd.setCurrentApprovals(decodeProtos(source, ChangeField.APPROVAL.getName(), APPROVAL_CODEC));
+ cd.setCurrentApprovals(
+ decodeProtos(
+ source, ChangeField.APPROVAL.getName(), PatchSetApprovalProtoConverter.INSTANCE));
} else if (fields.contains(ChangeField.APPROVAL.getName())) {
cd.setCurrentApprovals(Collections.emptyList());
}
diff --git a/java/com/google/gerrit/extensions/api/groups/GroupApi.java b/java/com/google/gerrit/extensions/api/groups/GroupApi.java
index fe85eaa..067f120 100644
--- a/java/com/google/gerrit/extensions/api/groups/GroupApi.java
+++ b/java/com/google/gerrit/extensions/api/groups/GroupApi.java
@@ -20,6 +20,7 @@
import com.google.gerrit.extensions.common.GroupOptionsInfo;
import com.google.gerrit.extensions.restapi.NotImplementedException;
import com.google.gerrit.extensions.restapi.RestApiException;
+import java.util.Arrays;
import java.util.List;
public interface GroupApi {
@@ -97,7 +98,18 @@
* com.google.gerrit.extensions.api.accounts.Accounts#id(String)}
* @throws RestApiException
*/
- void addMembers(String... members) throws RestApiException;
+ void addMembers(List<String> members) throws RestApiException;
+
+ /**
+ * Add members to a group.
+ *
+ * @param members list of member identifiers, in any format accepted by {@link
+ * com.google.gerrit.extensions.api.accounts.Accounts#id(String)}
+ * @throws RestApiException
+ */
+ default void addMembers(String... members) throws RestApiException {
+ addMembers(Arrays.asList(members));
+ }
/**
* Remove members from a group.
@@ -106,7 +118,18 @@
* com.google.gerrit.extensions.api.accounts.Accounts#id(String)}
* @throws RestApiException
*/
- void removeMembers(String... members) throws RestApiException;
+ void removeMembers(List<String> members) throws RestApiException;
+
+ /**
+ * Remove members from a group.
+ *
+ * @param members list of member identifiers, in any format accepted by {@link
+ * com.google.gerrit.extensions.api.accounts.Accounts#id(String)}
+ * @throws RestApiException
+ */
+ default void removeMembers(String... members) throws RestApiException {
+ removeMembers(Arrays.asList(members));
+ }
/**
* Lists the subgroups of this group.
@@ -122,7 +145,17 @@
* @param groups list of group identifiers, in any format accepted by {@link Groups#id(String)}
* @throws RestApiException
*/
- void addGroups(String... groups) throws RestApiException;
+ void addGroups(List<String> groups) throws RestApiException;
+
+ /**
+ * Adds subgroups to this group.
+ *
+ * @param groups list of group identifiers, in any format accepted by {@link Groups#id(String)}
+ * @throws RestApiException
+ */
+ default void addGroups(String... groups) throws RestApiException {
+ addGroups(Arrays.asList(groups));
+ }
/**
* Removes subgroups from this group.
@@ -130,7 +163,17 @@
* @param groups list of group identifiers, in any format accepted by {@link Groups#id(String)}
* @throws RestApiException
*/
- void removeGroups(String... groups) throws RestApiException;
+ void removeGroups(List<String> groups) throws RestApiException;
+
+ /**
+ * Removes subgroups from this group.
+ *
+ * @param groups list of group identifiers, in any format accepted by {@link Groups#id(String)}
+ * @throws RestApiException
+ */
+ default void removeGroups(String... groups) throws RestApiException {
+ removeGroups(Arrays.asList(groups));
+ }
/**
* Returns the audit log of the group.
@@ -215,12 +258,12 @@
}
@Override
- public void addMembers(String... members) throws RestApiException {
+ public void addMembers(List<String> members) throws RestApiException {
throw new NotImplementedException();
}
@Override
- public void removeMembers(String... members) throws RestApiException {
+ public void removeMembers(List<String> members) throws RestApiException {
throw new NotImplementedException();
}
@@ -230,12 +273,12 @@
}
@Override
- public void addGroups(String... groups) throws RestApiException {
+ public void addGroups(List<String> groups) throws RestApiException {
throw new NotImplementedException();
}
@Override
- public void removeGroups(String... groups) throws RestApiException {
+ public void removeGroups(List<String> groups) throws RestApiException {
throw new NotImplementedException();
}
diff --git a/java/com/google/gerrit/httpd/init/WebAppInitializer.java b/java/com/google/gerrit/httpd/init/WebAppInitializer.java
index 8b113b2..9f6049e 100644
--- a/java/com/google/gerrit/httpd/init/WebAppInitializer.java
+++ b/java/com/google/gerrit/httpd/init/WebAppInitializer.java
@@ -78,7 +78,6 @@
import com.google.gerrit.server.mail.receive.MailReceiver;
import com.google.gerrit.server.mail.send.SmtpEmailSender;
import com.google.gerrit.server.mime.MimeUtil2Module;
-import com.google.gerrit.server.notedb.NotesMigration;
import com.google.gerrit.server.patch.DiffExecutorModule;
import com.google.gerrit.server.permissions.DefaultPermissionBackendModule;
import com.google.gerrit.server.plugins.PluginGuiceEnvironment;
@@ -277,7 +276,6 @@
modules.add(new GerritServerConfigModule());
}
modules.add(new DatabaseModule());
- modules.add(new NotesMigration.Module());
modules.add(new DropWizardMetricMaker.ApiModule());
return Guice.createInjector(PRODUCTION, modules);
}
diff --git a/java/com/google/gerrit/lucene/BUILD b/java/com/google/gerrit/lucene/BUILD
index 9c6ba74..3b18f2c 100644
--- a/java/com/google/gerrit/lucene/BUILD
+++ b/java/com/google/gerrit/lucene/BUILD
@@ -31,11 +31,13 @@
"//java/com/google/gerrit/index:query_exception",
"//java/com/google/gerrit/index/project",
"//java/com/google/gerrit/lifecycle",
+ "//java/com/google/gerrit/proto",
"//java/com/google/gerrit/reviewdb:server",
"//java/com/google/gerrit/server",
"//java/com/google/gerrit/server/logging",
"//lib:guava",
"//lib:gwtorm",
+ "//lib:protobuf",
"//lib/flogger:api",
"//lib/guice",
"//lib/guice:guice-assistedinject",
diff --git a/java/com/google/gerrit/lucene/LuceneChangeIndex.java b/java/com/google/gerrit/lucene/LuceneChangeIndex.java
index b208a31..51e95ed 100644
--- a/java/com/google/gerrit/lucene/LuceneChangeIndex.java
+++ b/java/com/google/gerrit/lucene/LuceneChangeIndex.java
@@ -14,10 +14,9 @@
package com.google.gerrit.lucene;
+import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.gerrit.lucene.AbstractLuceneIndex.sortFieldName;
-import static com.google.gerrit.reviewdb.server.ReviewDbCodecs.APPROVAL_CODEC;
import static com.google.gerrit.reviewdb.server.ReviewDbCodecs.CHANGE_CODEC;
-import static com.google.gerrit.reviewdb.server.ReviewDbCodecs.PATCH_SET_CODEC;
import static com.google.gerrit.server.git.QueueProvider.QueueType.INTERACTIVE;
import static com.google.gerrit.server.index.change.ChangeField.LEGACY_ID;
import static com.google.gerrit.server.index.change.ChangeField.PROJECT;
@@ -42,10 +41,14 @@
import com.google.gerrit.index.query.FieldBundle;
import com.google.gerrit.index.query.Predicate;
import com.google.gerrit.index.query.QueryParseException;
+import com.google.gerrit.proto.Protos;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.converter.PatchSetApprovalProtoConverter;
+import com.google.gerrit.reviewdb.converter.PatchSetProtoConverter;
+import com.google.gerrit.reviewdb.converter.ProtoConverter;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.StarredChangesUtil;
import com.google.gerrit.server.config.GerritServerConfig;
@@ -58,18 +61,17 @@
import com.google.gerrit.server.project.SubmitRuleOptions;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.ChangeDataSource;
-import com.google.gwtorm.protobuf.ProtobufCodec;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.OrmRuntimeException;
import com.google.gwtorm.server.ResultSet;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.assistedinject.Assisted;
+import com.google.protobuf.MessageLite;
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
@@ -511,7 +513,7 @@
}
private void decodePatchSets(ListMultimap<String, IndexableField> doc, ChangeData cd) {
- List<PatchSet> patchSets = decodeProtos(doc, PATCH_SET_FIELD, PATCH_SET_CODEC);
+ List<PatchSet> patchSets = decodeProtos(doc, PATCH_SET_FIELD, PatchSetProtoConverter.INSTANCE);
if (!patchSets.isEmpty()) {
// Will be an empty list for schemas prior to when this field was stored;
// this cannot be valid since a change needs at least one patch set.
@@ -520,7 +522,8 @@
}
private void decodeApprovals(ListMultimap<String, IndexableField> doc, ChangeData cd) {
- cd.setCurrentApprovals(decodeProtos(doc, APPROVAL_FIELD, APPROVAL_CODEC));
+ cd.setCurrentApprovals(
+ decodeProtos(doc, APPROVAL_FIELD, PatchSetApprovalProtoConverter.INSTANCE));
}
private void decodeChangedLines(ListMultimap<String, IndexableField> doc, ChangeData cd) {
@@ -652,18 +655,20 @@
}
private static <T> List<T> decodeProtos(
- ListMultimap<String, IndexableField> doc, String fieldName, ProtobufCodec<T> codec) {
- Collection<IndexableField> fields = doc.get(fieldName);
- if (fields.isEmpty()) {
- return Collections.emptyList();
- }
+ ListMultimap<String, IndexableField> doc, String fieldName, ProtoConverter<?, T> converter) {
+ return doc.get(fieldName)
+ .stream()
+ .map(IndexableField::binaryValue)
+ .map(bytesRef -> parseProtoFrom(bytesRef, converter))
+ .collect(toImmutableList());
+ }
- List<T> result = new ArrayList<>(fields.size());
- for (IndexableField f : fields) {
- BytesRef r = f.binaryValue();
- result.add(codec.decode(r.bytes, r.offset, r.length));
- }
- return result;
+ private static <P extends MessageLite, T> T parseProtoFrom(
+ BytesRef bytesRef, ProtoConverter<P, T> converter) {
+ P message =
+ Protos.parseUnchecked(
+ converter.getParser(), bytesRef.bytes, bytesRef.offset, bytesRef.length);
+ return converter.fromProto(message);
}
private static List<byte[]> copyAsBytes(Collection<IndexableField> fields) {
diff --git a/java/com/google/gerrit/pgm/init/InitModule.java b/java/com/google/gerrit/pgm/init/InitModule.java
index 75145de..f2fc001 100644
--- a/java/com/google/gerrit/pgm/init/InitModule.java
+++ b/java/com/google/gerrit/pgm/init/InitModule.java
@@ -42,7 +42,6 @@
// Steps are executed in the order listed here.
//
step().to(InitGitManager.class);
- step().to(InitNoteDb.class);
step().to(InitLogging.class);
step().to(InitIndex.class);
step().to(InitAuth.class);
diff --git a/java/com/google/gerrit/pgm/init/InitNoteDb.java b/java/com/google/gerrit/pgm/init/InitNoteDb.java
deleted file mode 100644
index dc52868..0000000
--- a/java/com/google/gerrit/pgm/init/InitNoteDb.java
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (C) 2018 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.pgm.init;
-
-import static com.google.gerrit.server.notedb.NoteDbTable.CHANGES;
-import static com.google.gerrit.server.notedb.NotesMigration.SECTION_NOTE_DB;
-
-import com.google.gerrit.pgm.init.api.InitStep;
-import com.google.gerrit.pgm.init.api.Section;
-import com.google.gerrit.server.notedb.NotesMigrationState;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
-import org.eclipse.jgit.lib.Config;
-
-/** Initialize the NoteDb in gerrit site. */
-@Singleton
-class InitNoteDb implements InitStep {
-
- private final Section noteDbChanges;
-
- @Inject
- InitNoteDb(Section.Factory sections) {
- this.noteDbChanges = sections.get(SECTION_NOTE_DB, CHANGES.key());
- }
-
- @Override
- public void run() {
- initNoteDb();
- }
-
- private void initNoteDb() {
- Config defaultConfig = new Config();
- NotesMigrationState.FINAL.setConfigValues(defaultConfig);
- for (String name : defaultConfig.getNames(SECTION_NOTE_DB, CHANGES.key())) {
- noteDbChanges.set(name, defaultConfig.getString(SECTION_NOTE_DB, CHANGES.key(), name));
- }
- }
-}
diff --git a/java/com/google/gerrit/pgm/util/SiteProgram.java b/java/com/google/gerrit/pgm/util/SiteProgram.java
index e273c02..a889277f 100644
--- a/java/com/google/gerrit/pgm/util/SiteProgram.java
+++ b/java/com/google/gerrit/pgm/util/SiteProgram.java
@@ -25,7 +25,6 @@
import com.google.gerrit.server.config.GerritServerConfigModule;
import com.google.gerrit.server.config.SitePath;
import com.google.gerrit.server.git.GitRepositoryManagerModule;
-import com.google.gerrit.server.notedb.NotesMigration;
import com.google.gerrit.server.schema.DatabaseModule;
import com.google.gerrit.server.schema.ReviewDbSchemaModule;
import com.google.gerrit.server.securestore.SecureStoreClassName;
@@ -123,7 +122,6 @@
modules.add(new DatabaseModule());
modules.add(new ReviewDbSchemaModule());
modules.add(cfgInjector.getInstance(GitRepositoryManagerModule.class));
- modules.add(new NotesMigration.Module());
try {
return Guice.createInjector(PRODUCTION, modules);
diff --git a/java/com/google/gerrit/proto/BUILD b/java/com/google/gerrit/proto/BUILD
index 48185d6..b831e92 100644
--- a/java/com/google/gerrit/proto/BUILD
+++ b/java/com/google/gerrit/proto/BUILD
@@ -12,3 +12,13 @@
"//lib/jgit/org.eclipse.jgit:jgit",
],
)
+
+java_library(
+ name = "proto",
+ srcs = ["Protos.java"],
+ visibility = ["//visibility:public"],
+ deps = [
+ "//lib:gwtorm",
+ "//lib:protobuf",
+ ],
+)
diff --git a/java/com/google/gerrit/proto/Protos.java b/java/com/google/gerrit/proto/Protos.java
new file mode 100644
index 0000000..f8c63a3
--- /dev/null
+++ b/java/com/google/gerrit/proto/Protos.java
@@ -0,0 +1,143 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.proto;
+
+import com.google.gwtorm.protobuf.ProtobufCodec;
+import com.google.protobuf.ByteString;
+import com.google.protobuf.CodedOutputStream;
+import com.google.protobuf.MessageLite;
+import com.google.protobuf.Parser;
+import java.io.IOException;
+
+/** Static utilities for dealing with protobuf-based objects. */
+public class Protos {
+ /**
+ * Serializes a proto to a byte array.
+ *
+ * <p>Guarantees deterministic serialization. No matter whether the use case cares about
+ * determinism or not, always use this method in preference to {@link MessageLite#toByteArray()},
+ * which is not guaranteed deterministic.
+ *
+ * @param message the proto message to serialize.
+ * @return a byte array with the message contents.
+ */
+ public static byte[] toByteArray(MessageLite message) {
+ byte[] bytes = new byte[message.getSerializedSize()];
+ CodedOutputStream cout = CodedOutputStream.newInstance(bytes);
+ cout.useDeterministicSerialization();
+ try {
+ message.writeTo(cout);
+ cout.checkNoSpaceLeft();
+ return bytes;
+ } catch (IOException e) {
+ throw new IllegalStateException("exception writing to byte array", e);
+ }
+ }
+
+ /**
+ * Serializes a proto to a {@code ByteString}.
+ *
+ * <p>Guarantees deterministic serialization. No matter whether the use case cares about
+ * determinism or not, always use this method in preference to {@link MessageLite#toByteString()},
+ * which is not guaranteed deterministic.
+ *
+ * @param message the proto message to serialize
+ * @return a {@code ByteString} with the message contents
+ */
+ public static ByteString toByteString(MessageLite message) {
+ try (ByteString.Output bout = ByteString.newOutput(message.getSerializedSize())) {
+ CodedOutputStream outputStream = CodedOutputStream.newInstance(bout);
+ outputStream.useDeterministicSerialization();
+ message.writeTo(outputStream);
+ outputStream.flush();
+ return bout.toByteString();
+ } catch (IOException e) {
+ throw new IllegalStateException("exception writing to ByteString", e);
+ }
+ }
+
+ /**
+ * Serializes an object to a {@link ByteString} using a protobuf codec.
+ *
+ * <p>Guarantees deterministic serialization. No matter whether the use case cares about
+ * determinism or not, always use this method in preference to {@link
+ * ProtobufCodec#encodeToByteString(Object)}, which is not guaranteed deterministic.
+ *
+ * @param object the object to serialize.
+ * @param codec codec for serializing.
+ * @return a {@code ByteString} with the message contents.
+ */
+ public static <T> ByteString toByteString(T object, ProtobufCodec<T> codec) {
+ try (ByteString.Output bout = ByteString.newOutput()) {
+ CodedOutputStream cout = CodedOutputStream.newInstance(bout);
+ cout.useDeterministicSerialization();
+ codec.encode(object, cout);
+ cout.flush();
+ return bout.toByteString();
+ } catch (IOException e) {
+ throw new IllegalStateException("exception writing to ByteString", e);
+ }
+ }
+
+ /**
+ * Parses a byte array to a protobuf message.
+ *
+ * @param parser parser for the proto type.
+ * @param in byte array with the message contents.
+ * @return parsed proto.
+ */
+ public static <M extends MessageLite> M parseUnchecked(Parser<M> parser, byte[] in) {
+ try {
+ return parser.parseFrom(in);
+ } catch (IOException e) {
+ throw new IllegalArgumentException("exception parsing byte array to proto", e);
+ }
+ }
+
+ /**
+ * Parses a specific segment of a byte array to a protobuf message.
+ *
+ * @param parser parser for the proto type
+ * @param in byte array with the message contents
+ * @param offset offset in the byte array to start reading from
+ * @param length amount of read bytes
+ * @return parsed proto
+ */
+ public static <M extends MessageLite> M parseUnchecked(
+ Parser<M> parser, byte[] in, int offset, int length) {
+ try {
+ return parser.parseFrom(in, offset, length);
+ } catch (IOException e) {
+ throw new IllegalArgumentException("exception parsing byte array to proto", e);
+ }
+ }
+
+ /**
+ * Parses a {@code ByteString} to a protobuf message.
+ *
+ * @param parser parser for the proto type
+ * @param byteString {@code ByteString} with the message contents
+ * @return parsed proto
+ */
+ public static <M extends MessageLite> M parseUnchecked(Parser<M> parser, ByteString byteString) {
+ try {
+ return parser.parseFrom(byteString);
+ } catch (IOException e) {
+ throw new IllegalArgumentException("exception parsing ByteString to proto", e);
+ }
+ }
+
+ private Protos() {}
+}
diff --git a/java/com/google/gerrit/proto/testing/BUILD b/java/com/google/gerrit/proto/testing/BUILD
new file mode 100644
index 0000000..5f64c85
--- /dev/null
+++ b/java/com/google/gerrit/proto/testing/BUILD
@@ -0,0 +1,13 @@
+package(default_testonly = 1)
+
+java_library(
+ name = "testing",
+ srcs = glob(["*.java"]),
+ visibility = ["//visibility:public"],
+ deps = [
+ "//java/com/google/gerrit/server/cache/serialize",
+ "//lib:guava",
+ "//lib/commons:lang3",
+ "//lib/truth",
+ ],
+)
diff --git a/java/com/google/gerrit/server/cache/testing/SerializedClassSubject.java b/java/com/google/gerrit/proto/testing/SerializedClassSubject.java
similarity index 90%
rename from java/com/google/gerrit/server/cache/testing/SerializedClassSubject.java
rename to java/com/google/gerrit/proto/testing/SerializedClassSubject.java
index b902c1c..9ca6c9b 100644
--- a/java/com/google/gerrit/server/cache/testing/SerializedClassSubject.java
+++ b/java/com/google/gerrit/proto/testing/SerializedClassSubject.java
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.server.cache.testing;
+package com.google.gerrit.proto.testing;
import static com.google.common.collect.ImmutableMap.toImmutableMap;
import static com.google.common.truth.Truth.assertAbout;
@@ -30,13 +30,14 @@
import org.apache.commons.lang3.reflect.FieldUtils;
/**
- * Subject about classes that are serialized into persistent caches.
+ * Subject about classes that are serialized into persistent caches or indices.
*
* <p>Hand-written {@link com.google.gerrit.server.cache.serialize.CacheSerializer CacheSerializer}
- * implementations depend on the exact representation of the data stored in a class, so it is
- * important to verify any assumptions about the structure of the serialized classes. This class
- * contains assertions about serialized classes, and should be used for every class that has a
- * custom serializer implementation.
+ * and {@link com.google.gerrit.reviewdb.converter.ProtoConverter ProtoConverter} implementations
+ * depend on the exact representation of the data stored in a class, so it is important to verify
+ * any assumptions about the structure of the serialized classes. This class contains assertions
+ * about serialized classes, and should be used for every class that has a custom serializer
+ * implementation.
*
* <p>Changing fields of a serialized class (or abstract methods, in the case of {@code @AutoValue}
* classes) will likely require changes to the serializer implementation, and may require bumping
diff --git a/java/com/google/gerrit/reviewdb/BUILD b/java/com/google/gerrit/reviewdb/BUILD
index 76e35a1..9afa258 100644
--- a/java/com/google/gerrit/reviewdb/BUILD
+++ b/java/com/google/gerrit/reviewdb/BUILD
@@ -10,5 +10,7 @@
"//java/com/google/gerrit/extensions:api",
"//lib:guava",
"//lib:gwtorm",
+ "//lib:protobuf",
+ "//proto:reviewdb_java_proto",
],
)
diff --git a/java/com/google/gerrit/reviewdb/client/PatchSet.java b/java/com/google/gerrit/reviewdb/client/PatchSet.java
index 849fd75..a249a12 100644
--- a/java/com/google/gerrit/reviewdb/client/PatchSet.java
+++ b/java/com/google/gerrit/reviewdb/client/PatchSet.java
@@ -39,7 +39,7 @@
return isChangeRef(name);
}
- static String joinGroups(List<String> groups) {
+ public static String joinGroups(List<String> groups) {
if (groups == null) {
throw new IllegalArgumentException("groups may not be null");
}
diff --git a/java/com/google/gerrit/reviewdb/converter/AccountIdProtoConverter.java b/java/com/google/gerrit/reviewdb/converter/AccountIdProtoConverter.java
new file mode 100644
index 0000000..4209d10
--- /dev/null
+++ b/java/com/google/gerrit/reviewdb/converter/AccountIdProtoConverter.java
@@ -0,0 +1,38 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.reviewdb.converter;
+
+import com.google.gerrit.proto.reviewdb.Reviewdb;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.protobuf.Parser;
+
+public enum AccountIdProtoConverter implements ProtoConverter<Reviewdb.Account_Id, Account.Id> {
+ INSTANCE;
+
+ @Override
+ public Reviewdb.Account_Id toProto(Account.Id accountId) {
+ return Reviewdb.Account_Id.newBuilder().setId(accountId.get()).build();
+ }
+
+ @Override
+ public Account.Id fromProto(Reviewdb.Account_Id proto) {
+ return new Account.Id(proto.getId());
+ }
+
+ @Override
+ public Parser<Reviewdb.Account_Id> getParser() {
+ return Reviewdb.Account_Id.parser();
+ }
+}
diff --git a/java/com/google/gerrit/reviewdb/converter/ChangeIdProtoConverter.java b/java/com/google/gerrit/reviewdb/converter/ChangeIdProtoConverter.java
new file mode 100644
index 0000000..6eb3359
--- /dev/null
+++ b/java/com/google/gerrit/reviewdb/converter/ChangeIdProtoConverter.java
@@ -0,0 +1,38 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.reviewdb.converter;
+
+import com.google.gerrit.proto.reviewdb.Reviewdb;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.protobuf.Parser;
+
+public enum ChangeIdProtoConverter implements ProtoConverter<Reviewdb.Change_Id, Change.Id> {
+ INSTANCE;
+
+ @Override
+ public Reviewdb.Change_Id toProto(Change.Id changeId) {
+ return Reviewdb.Change_Id.newBuilder().setId(changeId.get()).build();
+ }
+
+ @Override
+ public Change.Id fromProto(Reviewdb.Change_Id proto) {
+ return new Change.Id(proto.getId());
+ }
+
+ @Override
+ public Parser<Reviewdb.Change_Id> getParser() {
+ return Reviewdb.Change_Id.parser();
+ }
+}
diff --git a/java/com/google/gerrit/reviewdb/converter/ChangeMessageKeyProtoConverter.java b/java/com/google/gerrit/reviewdb/converter/ChangeMessageKeyProtoConverter.java
new file mode 100644
index 0000000..f8667f1
--- /dev/null
+++ b/java/com/google/gerrit/reviewdb/converter/ChangeMessageKeyProtoConverter.java
@@ -0,0 +1,46 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.reviewdb.converter;
+
+import com.google.gerrit.proto.reviewdb.Reviewdb;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.ChangeMessage;
+import com.google.protobuf.Parser;
+
+public enum ChangeMessageKeyProtoConverter
+ implements ProtoConverter<Reviewdb.ChangeMessage_Key, ChangeMessage.Key> {
+ INSTANCE;
+
+ private final ProtoConverter<Reviewdb.Change_Id, Change.Id> changeIdConverter =
+ ChangeIdProtoConverter.INSTANCE;
+
+ @Override
+ public Reviewdb.ChangeMessage_Key toProto(ChangeMessage.Key messageKey) {
+ return Reviewdb.ChangeMessage_Key.newBuilder()
+ .setChangeId(changeIdConverter.toProto(messageKey.getParentKey()))
+ .setUuid(messageKey.get())
+ .build();
+ }
+
+ @Override
+ public ChangeMessage.Key fromProto(Reviewdb.ChangeMessage_Key proto) {
+ return new ChangeMessage.Key(changeIdConverter.fromProto(proto.getChangeId()), proto.getUuid());
+ }
+
+ @Override
+ public Parser<Reviewdb.ChangeMessage_Key> getParser() {
+ return Reviewdb.ChangeMessage_Key.parser();
+ }
+}
diff --git a/java/com/google/gerrit/reviewdb/converter/ChangeMessageProtoConverter.java b/java/com/google/gerrit/reviewdb/converter/ChangeMessageProtoConverter.java
new file mode 100644
index 0000000..99d9ca7
--- /dev/null
+++ b/java/com/google/gerrit/reviewdb/converter/ChangeMessageProtoConverter.java
@@ -0,0 +1,97 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.reviewdb.converter;
+
+import com.google.gerrit.proto.reviewdb.Reviewdb;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.ChangeMessage;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.protobuf.Parser;
+import java.sql.Timestamp;
+import java.util.Objects;
+
+public enum ChangeMessageProtoConverter
+ implements ProtoConverter<Reviewdb.ChangeMessage, ChangeMessage> {
+ INSTANCE;
+
+ private final ProtoConverter<Reviewdb.ChangeMessage_Key, ChangeMessage.Key>
+ changeMessageKeyConverter = ChangeMessageKeyProtoConverter.INSTANCE;
+ private final ProtoConverter<Reviewdb.Account_Id, Account.Id> accountIdConverter =
+ AccountIdProtoConverter.INSTANCE;
+ private final ProtoConverter<Reviewdb.PatchSet_Id, PatchSet.Id> patchSetIdConverter =
+ PatchSetIdProtoConverter.INSTANCE;
+
+ @Override
+ public Reviewdb.ChangeMessage toProto(ChangeMessage changeMessage) {
+ Reviewdb.ChangeMessage.Builder builder =
+ Reviewdb.ChangeMessage.newBuilder()
+ .setKey(changeMessageKeyConverter.toProto(changeMessage.getKey()));
+ Account.Id author = changeMessage.getAuthor();
+ if (author != null) {
+ builder.setAuthorId(accountIdConverter.toProto(author));
+ }
+ Timestamp writtenOn = changeMessage.getWrittenOn();
+ if (writtenOn != null) {
+ builder.setWrittenOn(writtenOn.getTime());
+ }
+ String message = changeMessage.getMessage();
+ if (message != null) {
+ builder.setMessage(message);
+ }
+ PatchSet.Id patchSetId = changeMessage.getPatchSetId();
+ if (patchSetId != null) {
+ builder.setPatchset(patchSetIdConverter.toProto(patchSetId));
+ }
+ String tag = changeMessage.getTag();
+ if (tag != null) {
+ builder.setTag(tag);
+ }
+ Account.Id realAuthor = changeMessage.getRealAuthor();
+ // ChangeMessage#getRealAuthor automatically delegates to ChangeMessage#getAuthor if the real
+ // author is not set. However, the previous protobuf representation kept 'realAuthor' empty if
+ // it wasn't set. To ensure binary compatibility, simulate the previous behavior.
+ if (realAuthor != null && !Objects.equals(realAuthor, author)) {
+ builder.setRealAuthor(accountIdConverter.toProto(realAuthor));
+ }
+ return builder.build();
+ }
+
+ @Override
+ public ChangeMessage fromProto(Reviewdb.ChangeMessage proto) {
+ ChangeMessage.Key key =
+ proto.hasKey() ? changeMessageKeyConverter.fromProto(proto.getKey()) : null;
+ Account.Id author =
+ proto.hasAuthorId() ? accountIdConverter.fromProto(proto.getAuthorId()) : null;
+ Timestamp writtenOn = proto.hasWrittenOn() ? new Timestamp(proto.getWrittenOn()) : null;
+ PatchSet.Id patchSetId =
+ proto.hasPatchset() ? patchSetIdConverter.fromProto(proto.getPatchset()) : null;
+ ChangeMessage changeMessage = new ChangeMessage(key, author, writtenOn, patchSetId);
+ if (proto.hasMessage()) {
+ changeMessage.setMessage(proto.getMessage());
+ }
+ if (proto.hasTag()) {
+ changeMessage.setTag(proto.getTag());
+ }
+ if (proto.hasRealAuthor()) {
+ changeMessage.setRealAuthor(accountIdConverter.fromProto(proto.getRealAuthor()));
+ }
+ return changeMessage;
+ }
+
+ @Override
+ public Parser<Reviewdb.ChangeMessage> getParser() {
+ return Reviewdb.ChangeMessage.parser();
+ }
+}
diff --git a/java/com/google/gerrit/reviewdb/converter/LabelIdProtoConverter.java b/java/com/google/gerrit/reviewdb/converter/LabelIdProtoConverter.java
new file mode 100644
index 0000000..7f71f56
--- /dev/null
+++ b/java/com/google/gerrit/reviewdb/converter/LabelIdProtoConverter.java
@@ -0,0 +1,38 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.reviewdb.converter;
+
+import com.google.gerrit.proto.reviewdb.Reviewdb;
+import com.google.gerrit.reviewdb.client.LabelId;
+import com.google.protobuf.Parser;
+
+public enum LabelIdProtoConverter implements ProtoConverter<Reviewdb.LabelId, LabelId> {
+ INSTANCE;
+
+ @Override
+ public Reviewdb.LabelId toProto(LabelId labelId) {
+ return Reviewdb.LabelId.newBuilder().setId(labelId.get()).build();
+ }
+
+ @Override
+ public LabelId fromProto(Reviewdb.LabelId proto) {
+ return new LabelId(proto.getId());
+ }
+
+ @Override
+ public Parser<Reviewdb.LabelId> getParser() {
+ return Reviewdb.LabelId.parser();
+ }
+}
diff --git a/java/com/google/gerrit/reviewdb/converter/PatchSetApprovalKeyProtoConverter.java b/java/com/google/gerrit/reviewdb/converter/PatchSetApprovalKeyProtoConverter.java
new file mode 100644
index 0000000..a37ddf7
--- /dev/null
+++ b/java/com/google/gerrit/reviewdb/converter/PatchSetApprovalKeyProtoConverter.java
@@ -0,0 +1,56 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.reviewdb.converter;
+
+import com.google.gerrit.proto.reviewdb.Reviewdb;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.LabelId;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
+import com.google.protobuf.Parser;
+
+public enum PatchSetApprovalKeyProtoConverter
+ implements ProtoConverter<Reviewdb.PatchSetApproval_Key, PatchSetApproval.Key> {
+ INSTANCE;
+
+ private final ProtoConverter<Reviewdb.PatchSet_Id, PatchSet.Id> patchSetIdConverter =
+ PatchSetIdProtoConverter.INSTANCE;
+ private final ProtoConverter<Reviewdb.Account_Id, Account.Id> accountIdConverter =
+ AccountIdProtoConverter.INSTANCE;
+ private final ProtoConverter<Reviewdb.LabelId, LabelId> labelIdConverter =
+ LabelIdProtoConverter.INSTANCE;
+
+ @Override
+ public Reviewdb.PatchSetApproval_Key toProto(PatchSetApproval.Key key) {
+ return Reviewdb.PatchSetApproval_Key.newBuilder()
+ .setPatchSetId(patchSetIdConverter.toProto(key.getParentKey()))
+ .setAccountId(accountIdConverter.toProto(key.getAccountId()))
+ .setCategoryId(labelIdConverter.toProto(key.getLabelId()))
+ .build();
+ }
+
+ @Override
+ public PatchSetApproval.Key fromProto(Reviewdb.PatchSetApproval_Key proto) {
+ return new PatchSetApproval.Key(
+ patchSetIdConverter.fromProto(proto.getPatchSetId()),
+ accountIdConverter.fromProto(proto.getAccountId()),
+ labelIdConverter.fromProto(proto.getCategoryId()));
+ }
+
+ @Override
+ public Parser<Reviewdb.PatchSetApproval_Key> getParser() {
+ return Reviewdb.PatchSetApproval_Key.parser();
+ }
+}
diff --git a/java/com/google/gerrit/reviewdb/converter/PatchSetApprovalProtoConverter.java b/java/com/google/gerrit/reviewdb/converter/PatchSetApprovalProtoConverter.java
new file mode 100644
index 0000000..fbaff10
--- /dev/null
+++ b/java/com/google/gerrit/reviewdb/converter/PatchSetApprovalProtoConverter.java
@@ -0,0 +1,81 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.reviewdb.converter;
+
+import com.google.gerrit.proto.reviewdb.Reviewdb;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
+import com.google.protobuf.Parser;
+import java.sql.Timestamp;
+import java.util.Objects;
+
+public enum PatchSetApprovalProtoConverter
+ implements ProtoConverter<Reviewdb.PatchSetApproval, PatchSetApproval> {
+ INSTANCE;
+
+ private final ProtoConverter<Reviewdb.PatchSetApproval_Key, PatchSetApproval.Key>
+ patchSetApprovalKeyProtoConverter = PatchSetApprovalKeyProtoConverter.INSTANCE;
+ private final ProtoConverter<Reviewdb.Account_Id, Account.Id> accountIdConverter =
+ AccountIdProtoConverter.INSTANCE;
+
+ @Override
+ public Reviewdb.PatchSetApproval toProto(PatchSetApproval patchSetApproval) {
+ Reviewdb.PatchSetApproval.Builder builder =
+ Reviewdb.PatchSetApproval.newBuilder()
+ .setKey(patchSetApprovalKeyProtoConverter.toProto(patchSetApproval.getKey()))
+ .setValue(patchSetApproval.getValue())
+ .setGranted(patchSetApproval.getGranted().getTime())
+ .setPostSubmit(patchSetApproval.isPostSubmit());
+
+ String tag = patchSetApproval.getTag();
+ if (tag != null) {
+ builder.setTag(tag);
+ }
+ Account.Id realAccountId = patchSetApproval.getRealAccountId();
+ // PatchSetApproval#getRealAccountId automatically delegates to PatchSetApproval#getAccountId if
+ // the real author is not set. However, the previous protobuf representation kept
+ // 'realAccountId' empty if it wasn't set. To ensure binary compatibility, simulate the previous
+ // behavior.
+ if (realAccountId != null && !Objects.equals(realAccountId, patchSetApproval.getAccountId())) {
+ builder.setRealAccountId(accountIdConverter.toProto(realAccountId));
+ }
+
+ return builder.build();
+ }
+
+ @Override
+ public PatchSetApproval fromProto(Reviewdb.PatchSetApproval proto) {
+ PatchSetApproval patchSetApproval =
+ new PatchSetApproval(
+ patchSetApprovalKeyProtoConverter.fromProto(proto.getKey()),
+ (short) proto.getValue(),
+ new Timestamp(proto.getGranted()));
+ if (proto.hasTag()) {
+ patchSetApproval.setTag(proto.getTag());
+ }
+ if (proto.hasRealAccountId()) {
+ patchSetApproval.setRealAccountId(accountIdConverter.fromProto(proto.getRealAccountId()));
+ }
+ if (proto.hasPostSubmit()) {
+ patchSetApproval.setPostSubmit(proto.getPostSubmit());
+ }
+ return patchSetApproval;
+ }
+
+ @Override
+ public Parser<Reviewdb.PatchSetApproval> getParser() {
+ return Reviewdb.PatchSetApproval.parser();
+ }
+}
diff --git a/java/com/google/gerrit/reviewdb/converter/PatchSetIdProtoConverter.java b/java/com/google/gerrit/reviewdb/converter/PatchSetIdProtoConverter.java
new file mode 100644
index 0000000..f518a54
--- /dev/null
+++ b/java/com/google/gerrit/reviewdb/converter/PatchSetIdProtoConverter.java
@@ -0,0 +1,45 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.reviewdb.converter;
+
+import com.google.gerrit.proto.reviewdb.Reviewdb;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.protobuf.Parser;
+
+public enum PatchSetIdProtoConverter implements ProtoConverter<Reviewdb.PatchSet_Id, PatchSet.Id> {
+ INSTANCE;
+
+ private final ProtoConverter<Reviewdb.Change_Id, Change.Id> changeIdConverter =
+ ChangeIdProtoConverter.INSTANCE;
+
+ @Override
+ public Reviewdb.PatchSet_Id toProto(PatchSet.Id patchSetId) {
+ return Reviewdb.PatchSet_Id.newBuilder()
+ .setChangeId(changeIdConverter.toProto(patchSetId.getParentKey()))
+ .setPatchSetId(patchSetId.get())
+ .build();
+ }
+
+ @Override
+ public PatchSet.Id fromProto(Reviewdb.PatchSet_Id proto) {
+ return new PatchSet.Id(changeIdConverter.fromProto(proto.getChangeId()), proto.getPatchSetId());
+ }
+
+ @Override
+ public Parser<Reviewdb.PatchSet_Id> getParser() {
+ return Reviewdb.PatchSet_Id.parser();
+ }
+}
diff --git a/java/com/google/gerrit/reviewdb/converter/PatchSetProtoConverter.java b/java/com/google/gerrit/reviewdb/converter/PatchSetProtoConverter.java
new file mode 100644
index 0000000..ffdc346
--- /dev/null
+++ b/java/com/google/gerrit/reviewdb/converter/PatchSetProtoConverter.java
@@ -0,0 +1,93 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.reviewdb.converter;
+
+import com.google.gerrit.proto.reviewdb.Reviewdb;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.RevId;
+import com.google.protobuf.Parser;
+import java.sql.Timestamp;
+import java.util.List;
+
+public enum PatchSetProtoConverter implements ProtoConverter<Reviewdb.PatchSet, PatchSet> {
+ INSTANCE;
+
+ private final ProtoConverter<Reviewdb.PatchSet_Id, PatchSet.Id> patchSetIdConverter =
+ PatchSetIdProtoConverter.INSTANCE;
+ private final ProtoConverter<Reviewdb.RevId, RevId> revIdConverter = RevIdProtoConverter.INSTANCE;
+ private final ProtoConverter<Reviewdb.Account_Id, Account.Id> accountIdConverter =
+ AccountIdProtoConverter.INSTANCE;
+
+ @Override
+ public Reviewdb.PatchSet toProto(PatchSet patchSet) {
+ Reviewdb.PatchSet.Builder builder =
+ Reviewdb.PatchSet.newBuilder().setId(patchSetIdConverter.toProto(patchSet.getId()));
+ RevId revision = patchSet.getRevision();
+ if (revision != null) {
+ builder.setRevision(revIdConverter.toProto(revision));
+ }
+ Account.Id uploader = patchSet.getUploader();
+ if (uploader != null) {
+ builder.setUploaderAccountId(accountIdConverter.toProto(uploader));
+ }
+ Timestamp createdOn = patchSet.getCreatedOn();
+ if (createdOn != null) {
+ builder.setCreatedOn(createdOn.getTime());
+ }
+ List<String> groups = patchSet.getGroups();
+ if (!groups.isEmpty()) {
+ builder.setGroups(PatchSet.joinGroups(groups));
+ }
+ String pushCertificate = patchSet.getPushCertificate();
+ if (pushCertificate != null) {
+ builder.setPushCertificate(pushCertificate);
+ }
+ String description = patchSet.getDescription();
+ if (description != null) {
+ builder.setDescription(description);
+ }
+ return builder.build();
+ }
+
+ @Override
+ public PatchSet fromProto(Reviewdb.PatchSet proto) {
+ PatchSet patchSet = new PatchSet(patchSetIdConverter.fromProto(proto.getId()));
+ if (proto.hasRevision()) {
+ patchSet.setRevision(revIdConverter.fromProto(proto.getRevision()));
+ }
+ if (proto.hasUploaderAccountId()) {
+ patchSet.setUploader(accountIdConverter.fromProto(proto.getUploaderAccountId()));
+ }
+ if (proto.hasCreatedOn()) {
+ patchSet.setCreatedOn(new Timestamp(proto.getCreatedOn()));
+ }
+ if (proto.hasGroups()) {
+ patchSet.setGroups(PatchSet.splitGroups(proto.getGroups()));
+ }
+ if (proto.hasPushCertificate()) {
+ patchSet.setPushCertificate(proto.getPushCertificate());
+ }
+ if (proto.hasDescription()) {
+ patchSet.setDescription(proto.getDescription());
+ }
+ return patchSet;
+ }
+
+ @Override
+ public Parser<Reviewdb.PatchSet> getParser() {
+ return Reviewdb.PatchSet.parser();
+ }
+}
diff --git a/java/com/google/gerrit/reviewdb/converter/ProtoConverter.java b/java/com/google/gerrit/reviewdb/converter/ProtoConverter.java
new file mode 100644
index 0000000..568759c
--- /dev/null
+++ b/java/com/google/gerrit/reviewdb/converter/ProtoConverter.java
@@ -0,0 +1,27 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.reviewdb.converter;
+
+import com.google.protobuf.MessageLite;
+import com.google.protobuf.Parser;
+
+public interface ProtoConverter<P extends MessageLite, C> {
+
+ P toProto(C valueClass);
+
+ C fromProto(P proto);
+
+ Parser<P> getParser();
+}
diff --git a/java/com/google/gerrit/reviewdb/converter/RevIdProtoConverter.java b/java/com/google/gerrit/reviewdb/converter/RevIdProtoConverter.java
new file mode 100644
index 0000000..6402b6b
--- /dev/null
+++ b/java/com/google/gerrit/reviewdb/converter/RevIdProtoConverter.java
@@ -0,0 +1,38 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.reviewdb.converter;
+
+import com.google.gerrit.proto.reviewdb.Reviewdb;
+import com.google.gerrit.reviewdb.client.RevId;
+import com.google.protobuf.Parser;
+
+public enum RevIdProtoConverter implements ProtoConverter<Reviewdb.RevId, RevId> {
+ INSTANCE;
+
+ @Override
+ public Reviewdb.RevId toProto(RevId revId) {
+ return Reviewdb.RevId.newBuilder().setId(revId.get()).build();
+ }
+
+ @Override
+ public RevId fromProto(Reviewdb.RevId proto) {
+ return new RevId(proto.getId());
+ }
+
+ @Override
+ public Parser<Reviewdb.RevId> getParser() {
+ return Reviewdb.RevId.parser();
+ }
+}
diff --git a/java/com/google/gerrit/reviewdb/server/ReviewDbCodecs.java b/java/com/google/gerrit/reviewdb/server/ReviewDbCodecs.java
index 2958464..7ff2284 100644
--- a/java/com/google/gerrit/reviewdb/server/ReviewDbCodecs.java
+++ b/java/com/google/gerrit/reviewdb/server/ReviewDbCodecs.java
@@ -15,24 +15,12 @@
package com.google.gerrit.reviewdb.server;
import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.ChangeMessage;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.client.PatchSetApproval;
import com.google.gwtorm.protobuf.CodecFactory;
import com.google.gwtorm.protobuf.ProtobufCodec;
/** {@link ProtobufCodec} instances for ReviewDb types. */
public class ReviewDbCodecs {
- public static final ProtobufCodec<PatchSetApproval> APPROVAL_CODEC =
- CodecFactory.encoder(PatchSetApproval.class);
-
public static final ProtobufCodec<Change> CHANGE_CODEC = CodecFactory.encoder(Change.class);
- public static final ProtobufCodec<ChangeMessage> MESSAGE_CODEC =
- CodecFactory.encoder(ChangeMessage.class);
-
- public static final ProtobufCodec<PatchSet> PATCH_SET_CODEC =
- CodecFactory.encoder(PatchSet.class);
-
private ReviewDbCodecs() {}
}
diff --git a/java/com/google/gerrit/server/BUILD b/java/com/google/gerrit/server/BUILD
index 8401852..df3308c 100644
--- a/java/com/google/gerrit/server/BUILD
+++ b/java/com/google/gerrit/server/BUILD
@@ -40,6 +40,7 @@
"//java/com/google/gerrit/mail",
"//java/com/google/gerrit/metrics",
"//java/com/google/gerrit/prettify:server",
+ "//java/com/google/gerrit/proto",
"//java/com/google/gerrit/reviewdb:server",
"//java/com/google/gerrit/server/cache/serialize",
"//java/com/google/gerrit/server/ioutil",
diff --git a/java/com/google/gerrit/server/account/externalids/AllExternalIds.java b/java/com/google/gerrit/server/account/externalids/AllExternalIds.java
index bb1ade7..bfe46d2 100644
--- a/java/com/google/gerrit/server/account/externalids/AllExternalIds.java
+++ b/java/com/google/gerrit/server/account/externalids/AllExternalIds.java
@@ -21,12 +21,12 @@
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.SetMultimap;
+import com.google.gerrit.proto.Protos;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.server.cache.proto.Cache.AllExternalIdsProto;
import com.google.gerrit.server.cache.proto.Cache.AllExternalIdsProto.ExternalIdProto;
import com.google.gerrit.server.cache.serialize.CacheSerializer;
-import com.google.gerrit.server.cache.serialize.ProtoCacheSerializers;
-import com.google.gerrit.server.cache.serialize.ProtoCacheSerializers.ObjectIdConverter;
+import com.google.gerrit.server.cache.serialize.ObjectIdConverter;
import java.util.Collection;
/** Cache value containing all external IDs. */
@@ -68,7 +68,7 @@
.stream()
.map(extId -> toProto(idConverter, extId))
.forEach(allBuilder::addExternalId);
- return ProtoCacheSerializers.toByteArray(allBuilder.build());
+ return Protos.toByteArray(allBuilder.build());
}
private static ExternalIdProto toProto(ObjectIdConverter idConverter, ExternalId externalId) {
@@ -92,7 +92,7 @@
public AllExternalIds deserialize(byte[] in) {
ObjectIdConverter idConverter = ObjectIdConverter.create();
return create(
- ProtoCacheSerializers.parseUnchecked(AllExternalIdsProto.parser(), in)
+ Protos.parseUnchecked(AllExternalIdsProto.parser(), in)
.getExternalIdList()
.stream()
.map(proto -> toExternalId(idConverter, proto))
diff --git a/java/com/google/gerrit/server/api/groups/GroupApiImpl.java b/java/com/google/gerrit/server/api/groups/GroupApiImpl.java
index 9909ed7..b70a029 100644
--- a/java/com/google/gerrit/server/api/groups/GroupApiImpl.java
+++ b/java/com/google/gerrit/server/api/groups/GroupApiImpl.java
@@ -47,7 +47,6 @@
import com.google.gerrit.server.restapi.group.PutOwner;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
-import java.util.Arrays;
import java.util.List;
class GroupApiImpl implements GroupApi {
@@ -217,18 +216,18 @@
}
@Override
- public void addMembers(String... members) throws RestApiException {
+ public void addMembers(List<String> members) throws RestApiException {
try {
- addMembers.apply(rsrc, AddMembers.Input.fromMembers(Arrays.asList(members)));
+ addMembers.apply(rsrc, AddMembers.Input.fromMembers(members));
} catch (Exception e) {
throw asRestApiException("Cannot add group members", e);
}
}
@Override
- public void removeMembers(String... members) throws RestApiException {
+ public void removeMembers(List<String> members) throws RestApiException {
try {
- deleteMembers.apply(rsrc, AddMembers.Input.fromMembers(Arrays.asList(members)));
+ deleteMembers.apply(rsrc, AddMembers.Input.fromMembers(members));
} catch (Exception e) {
throw asRestApiException("Cannot remove group members", e);
}
@@ -244,18 +243,18 @@
}
@Override
- public void addGroups(String... groups) throws RestApiException {
+ public void addGroups(List<String> groups) throws RestApiException {
try {
- addSubgroups.apply(rsrc, AddSubgroups.Input.fromGroups(Arrays.asList(groups)));
+ addSubgroups.apply(rsrc, AddSubgroups.Input.fromGroups(groups));
} catch (Exception e) {
throw asRestApiException("Cannot add subgroups", e);
}
}
@Override
- public void removeGroups(String... groups) throws RestApiException {
+ public void removeGroups(List<String> groups) throws RestApiException {
try {
- deleteSubgroups.apply(rsrc, AddSubgroups.Input.fromGroups(Arrays.asList(groups)));
+ deleteSubgroups.apply(rsrc, AddSubgroups.Input.fromGroups(groups));
} catch (Exception e) {
throw asRestApiException("Cannot remove subgroups", e);
}
diff --git a/java/com/google/gerrit/server/auth/oauth/OAuthTokenCache.java b/java/com/google/gerrit/server/auth/oauth/OAuthTokenCache.java
index 3a6be0c..0980116 100644
--- a/java/com/google/gerrit/server/auth/oauth/OAuthTokenCache.java
+++ b/java/com/google/gerrit/server/auth/oauth/OAuthTokenCache.java
@@ -22,12 +22,12 @@
import com.google.gerrit.extensions.auth.oauth.OAuthToken;
import com.google.gerrit.extensions.auth.oauth.OAuthTokenEncrypter;
import com.google.gerrit.extensions.registration.DynamicItem;
+import com.google.gerrit.proto.Protos;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.server.cache.CacheModule;
import com.google.gerrit.server.cache.proto.Cache.OAuthTokenProto;
import com.google.gerrit.server.cache.serialize.CacheSerializer;
import com.google.gerrit.server.cache.serialize.IntKeyCacheSerializer;
-import com.google.gerrit.server.cache.serialize.ProtoCacheSerializers;
import com.google.inject.Inject;
import com.google.inject.Module;
import com.google.inject.Singleton;
@@ -57,7 +57,7 @@
static class Serializer implements CacheSerializer<OAuthToken> {
@Override
public byte[] serialize(OAuthToken object) {
- return ProtoCacheSerializers.toByteArray(
+ return Protos.toByteArray(
OAuthTokenProto.newBuilder()
.setToken(object.getToken())
.setSecret(object.getSecret())
@@ -69,7 +69,7 @@
@Override
public OAuthToken deserialize(byte[] in) {
- OAuthTokenProto proto = ProtoCacheSerializers.parseUnchecked(OAuthTokenProto.parser(), in);
+ OAuthTokenProto proto = Protos.parseUnchecked(OAuthTokenProto.parser(), in);
return new OAuthToken(
proto.getToken(),
proto.getSecret(),
diff --git a/java/com/google/gerrit/server/cache/serialize/BUILD b/java/com/google/gerrit/server/cache/serialize/BUILD
index 957a153..cd9912c 100644
--- a/java/com/google/gerrit/server/cache/serialize/BUILD
+++ b/java/com/google/gerrit/server/cache/serialize/BUILD
@@ -4,6 +4,7 @@
visibility = ["//visibility:public"],
deps = [
"//java/com/google/gerrit/common:annotations",
+ "//java/com/google/gerrit/proto",
"//lib:guava",
"//lib:gwtorm",
"//lib:protobuf",
diff --git a/java/com/google/gerrit/server/cache/serialize/ObjectIdConverter.java b/java/com/google/gerrit/server/cache/serialize/ObjectIdConverter.java
new file mode 100644
index 0000000..eb946a9
--- /dev/null
+++ b/java/com/google/gerrit/server/cache/serialize/ObjectIdConverter.java
@@ -0,0 +1,56 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.cache.serialize;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static org.eclipse.jgit.lib.Constants.OBJECT_ID_LENGTH;
+
+import com.google.protobuf.ByteString;
+import org.eclipse.jgit.lib.ObjectId;
+
+/**
+ * Helper for serializing {@link ObjectId} instances to/from protobuf fields.
+ *
+ * <p>Reuse a single instance's {@link #toByteString(ObjectId)} and {@link
+ * #fromByteString(ByteString)} within a single {@link CacheSerializer#serialize} or {@link
+ * CacheSerializer#deserialize} method body to minimize allocation of temporary buffers.
+ *
+ * <p><strong>Note:</strong> This class is not threadsafe. Instances must not be stored in {@link
+ * CacheSerializer} fields if the serializer instances will be used from multiple threads.
+ */
+public class ObjectIdConverter {
+ public static ObjectIdConverter create() {
+ return new ObjectIdConverter();
+ }
+
+ private final byte[] buf = new byte[OBJECT_ID_LENGTH];
+
+ private ObjectIdConverter() {}
+
+ public ByteString toByteString(ObjectId id) {
+ id.copyRawTo(buf, 0);
+ return ByteString.copyFrom(buf);
+ }
+
+ public ObjectId fromByteString(ByteString in) {
+ checkArgument(
+ in.size() == OBJECT_ID_LENGTH,
+ "expected ByteString of length %s: %s",
+ OBJECT_ID_LENGTH,
+ in);
+ in.copyTo(buf, 0);
+ return ObjectId.fromRaw(buf);
+ }
+}
diff --git a/java/com/google/gerrit/server/cache/serialize/ProtoCacheSerializers.java b/java/com/google/gerrit/server/cache/serialize/ProtoCacheSerializers.java
deleted file mode 100644
index 4e0b106..0000000
--- a/java/com/google/gerrit/server/cache/serialize/ProtoCacheSerializers.java
+++ /dev/null
@@ -1,127 +0,0 @@
-// Copyright (C) 2018 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.server.cache.serialize;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static org.eclipse.jgit.lib.Constants.OBJECT_ID_LENGTH;
-
-import com.google.gwtorm.protobuf.ProtobufCodec;
-import com.google.protobuf.ByteString;
-import com.google.protobuf.CodedOutputStream;
-import com.google.protobuf.MessageLite;
-import com.google.protobuf.Parser;
-import java.io.IOException;
-import org.eclipse.jgit.lib.ObjectId;
-
-/** Static utilities for writing protobuf-based {@link CacheSerializer} implementations. */
-public class ProtoCacheSerializers {
- /**
- * Serializes a proto to a byte array.
- *
- * <p>Guarantees deterministic serialization and thus is suitable for use in persistent caches.
- * Should be used in preference to {@link MessageLite#toByteArray()}, which is not guaranteed
- * deterministic.
- *
- * @param message the proto message to serialize.
- * @return a byte array with the message contents.
- */
- public static byte[] toByteArray(MessageLite message) {
- byte[] bytes = new byte[message.getSerializedSize()];
- CodedOutputStream cout = CodedOutputStream.newInstance(bytes);
- cout.useDeterministicSerialization();
- try {
- message.writeTo(cout);
- cout.checkNoSpaceLeft();
- return bytes;
- } catch (IOException e) {
- throw new IllegalStateException("exception writing to byte array", e);
- }
- }
-
- /**
- * Serializes an object to a {@link ByteString} using a protobuf codec.
- *
- * <p>Guarantees deterministic serialization and thus is suitable for use in persistent caches.
- * Should be used in preference to {@link ProtobufCodec#encodeToByteString(Object)}, which is not
- * guaranteed deterministic.
- *
- * @param object the object to serialize.
- * @param codec codec for serializing.
- * @return a {@code ByteString} with the message contents.
- */
- public static <T> ByteString toByteString(T object, ProtobufCodec<T> codec) {
- try (ByteString.Output bout = ByteString.newOutput()) {
- CodedOutputStream cout = CodedOutputStream.newInstance(bout);
- cout.useDeterministicSerialization();
- codec.encode(object, cout);
- cout.flush();
- return bout.toByteString();
- } catch (IOException e) {
- throw new IllegalStateException("exception writing to ByteString", e);
- }
- }
-
- /**
- * Parses a byte array to a protobuf message.
- *
- * @param parser parser for the proto type.
- * @param in byte array with the message contents.
- * @return parsed proto.
- */
- public static <M extends MessageLite> M parseUnchecked(Parser<M> parser, byte[] in) {
- try {
- return parser.parseFrom(in);
- } catch (IOException e) {
- throw new IllegalArgumentException("exception parsing byte array to proto", e);
- }
- }
-
- /**
- * Helper for serializing {@link ObjectId} instances to/from protobuf fields.
- *
- * <p>Reuse a single instance's {@link #toByteString(ObjectId)} and {@link
- * #fromByteString(ByteString)} within a single {@link CacheSerializer#serialize} or {@link
- * CacheSerializer#deserialize} method body to minimize allocation of temporary buffers.
- *
- * <p><strong>Note:</strong> This class is not threadsafe. Instances must not be stored in {@link
- * CacheSerializer} fields if the serializer instances will be used from multiple threads.
- */
- public static class ObjectIdConverter {
- public static ObjectIdConverter create() {
- return new ObjectIdConverter();
- }
-
- private final byte[] buf = new byte[OBJECT_ID_LENGTH];
-
- private ObjectIdConverter() {}
-
- public ByteString toByteString(ObjectId id) {
- id.copyRawTo(buf, 0);
- return ByteString.copyFrom(buf);
- }
-
- public ObjectId fromByteString(ByteString in) {
- checkArgument(
- in.size() == OBJECT_ID_LENGTH,
- "expected ByteString of length %s: %s",
- OBJECT_ID_LENGTH,
- in);
- in.copyTo(buf, 0);
- return ObjectId.fromRaw(buf);
- }
- }
-
- private ProtoCacheSerializers() {}
-}
diff --git a/java/com/google/gerrit/server/cache/testing/BUILD b/java/com/google/gerrit/server/cache/testing/BUILD
index 9a9f1ef..f7f7eb6 100644
--- a/java/com/google/gerrit/server/cache/testing/BUILD
+++ b/java/com/google/gerrit/server/cache/testing/BUILD
@@ -5,10 +5,6 @@
srcs = glob(["*.java"]),
visibility = ["//visibility:public"],
deps = [
- "//java/com/google/gerrit/server/cache/serialize",
- "//lib:guava",
"//lib:protobuf",
- "//lib/commons:lang3",
- "//lib/truth",
],
)
diff --git a/java/com/google/gerrit/server/change/ChangeFinder.java b/java/com/google/gerrit/server/change/ChangeFinder.java
index 41d89ed..5e7a9bf 100644
--- a/java/com/google/gerrit/server/change/ChangeFinder.java
+++ b/java/com/google/gerrit/server/change/ChangeFinder.java
@@ -30,7 +30,6 @@
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RevId;
-import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.cache.CacheModule;
import com.google.gerrit.server.config.ConfigUtil;
import com.google.gerrit.server.config.GerritServerConfig;
@@ -77,7 +76,6 @@
private final IndexConfig indexConfig;
private final Cache<Change.Id, String> changeIdProjectCache;
private final Provider<InternalChangeQuery> queryProvider;
- private final Provider<ReviewDb> reviewDb;
private final ChangeNotes.Factory changeNotesFactory;
private final Counter1<ChangeIdType> changeIdCounter;
private final ImmutableSet<ChangeIdType> allowedIdTypes;
@@ -87,14 +85,12 @@
IndexConfig indexConfig,
@Named(CACHE_NAME) Cache<Change.Id, String> changeIdProjectCache,
Provider<InternalChangeQuery> queryProvider,
- Provider<ReviewDb> reviewDb,
ChangeNotes.Factory changeNotesFactory,
MetricMaker metricMaker,
@GerritServerConfig Config config) {
this.indexConfig = indexConfig;
this.changeIdProjectCache = changeIdProjectCache;
this.queryProvider = queryProvider;
- this.reviewDb = reviewDb;
this.changeNotesFactory = changeNotesFactory;
this.changeIdCounter =
metricMaker.newCounter(
@@ -203,7 +199,7 @@
Change.Id cId = new Change.Id(changeNumber);
try {
return ImmutableList.of(
- changeNotesFactory.createChecked(reviewDb.get(), Project.NameKey.parse(project), cId));
+ changeNotesFactory.createChecked(Project.NameKey.parse(project), cId));
} catch (NoSuchChangeException e) {
return Collections.emptyList();
} catch (OrmException e) {
diff --git a/java/com/google/gerrit/server/change/ChangeJson.java b/java/com/google/gerrit/server/change/ChangeJson.java
index 889a20c..b39d716 100644
--- a/java/com/google/gerrit/server/change/ChangeJson.java
+++ b/java/com/google/gerrit/server/change/ChangeJson.java
@@ -323,7 +323,7 @@
Project.NameKey project, Change.Id id, Supplier<I> changeInfoSupplier) throws OrmException {
ChangeNotes notes;
try {
- notes = notesFactory.createChecked(db.get(), project, id);
+ notes = notesFactory.createChecked(project, id);
} catch (OrmException e) {
if (!has(CHECK)) {
throw e;
diff --git a/java/com/google/gerrit/server/change/ChangeKindCacheImpl.java b/java/com/google/gerrit/server/change/ChangeKindCacheImpl.java
index a6786d8..a57a9a4 100644
--- a/java/com/google/gerrit/server/change/ChangeKindCacheImpl.java
+++ b/java/com/google/gerrit/server/change/ChangeKindCacheImpl.java
@@ -24,6 +24,7 @@
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.extensions.client.ChangeKind;
+import com.google.gerrit.proto.Protos;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.Project;
@@ -32,8 +33,7 @@
import com.google.gerrit.server.cache.proto.Cache.ChangeKindKeyProto;
import com.google.gerrit.server.cache.serialize.CacheSerializer;
import com.google.gerrit.server.cache.serialize.EnumCacheSerializer;
-import com.google.gerrit.server.cache.serialize.ProtoCacheSerializers;
-import com.google.gerrit.server.cache.serialize.ProtoCacheSerializers.ObjectIdConverter;
+import com.google.gerrit.server.cache.serialize.ObjectIdConverter;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.InMemoryInserter;
@@ -146,7 +146,7 @@
@Override
public byte[] serialize(Key object) {
ObjectIdConverter idConverter = ObjectIdConverter.create();
- return ProtoCacheSerializers.toByteArray(
+ return Protos.toByteArray(
ChangeKindKeyProto.newBuilder()
.setPrior(idConverter.toByteString(object.prior()))
.setNext(idConverter.toByteString(object.next()))
@@ -156,8 +156,7 @@
@Override
public Key deserialize(byte[] in) {
- ChangeKindKeyProto proto =
- ProtoCacheSerializers.parseUnchecked(ChangeKindKeyProto.parser(), in);
+ ChangeKindKeyProto proto = Protos.parseUnchecked(ChangeKindKeyProto.parser(), in);
ObjectIdConverter idConverter = ObjectIdConverter.create();
return create(
idConverter.fromByteString(proto.getPrior()),
diff --git a/java/com/google/gerrit/server/change/ConsistencyChecker.java b/java/com/google/gerrit/server/change/ConsistencyChecker.java
index b29f42a..f38d670 100644
--- a/java/com/google/gerrit/server/change/ConsistencyChecker.java
+++ b/java/com/google/gerrit/server/change/ConsistencyChecker.java
@@ -413,9 +413,7 @@
}
try {
Change c =
- notesFactory
- .createChecked(db.get(), change().getProject(), psId.getParentKey())
- .getChange();
+ notesFactory.createChecked(change().getProject(), psId.getParentKey()).getChange();
if (!c.getDest().equals(change().getDest())) {
continue;
}
@@ -544,7 +542,7 @@
bu.addOp(notes.getChangeId(), new FixMergedOp(notFound));
bu.execute();
}
- notes = notesFactory.createChecked(db.get(), inserter.getChange());
+ notes = notesFactory.createChecked(inserter.getChange());
insertPatchSetProblem.status = Status.FIXED;
insertPatchSetProblem.outcome = "Inserted as patch set " + psId.get();
} catch (OrmException | IOException | UpdateException | RestApiException e) {
diff --git a/java/com/google/gerrit/server/change/MergeabilityCacheImpl.java b/java/com/google/gerrit/server/change/MergeabilityCacheImpl.java
index 131f3a1..1ac558b 100644
--- a/java/com/google/gerrit/server/change/MergeabilityCacheImpl.java
+++ b/java/com/google/gerrit/server/change/MergeabilityCacheImpl.java
@@ -25,13 +25,13 @@
import com.google.common.flogger.FluentLogger;
import com.google.common.util.concurrent.UncheckedExecutionException;
import com.google.gerrit.extensions.client.SubmitType;
+import com.google.gerrit.proto.Protos;
import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.server.cache.CacheModule;
import com.google.gerrit.server.cache.proto.Cache.MergeabilityKeyProto;
import com.google.gerrit.server.cache.serialize.BooleanCacheSerializer;
import com.google.gerrit.server.cache.serialize.CacheSerializer;
-import com.google.gerrit.server.cache.serialize.ProtoCacheSerializers;
-import com.google.gerrit.server.cache.serialize.ProtoCacheSerializers.ObjectIdConverter;
+import com.google.gerrit.server.cache.serialize.ObjectIdConverter;
import com.google.gerrit.server.git.CodeReviewCommit;
import com.google.gerrit.server.git.CodeReviewCommit.CodeReviewRevWalk;
import com.google.gerrit.server.submit.SubmitDryRun;
@@ -143,7 +143,7 @@
@Override
public byte[] serialize(EntryKey object) {
ObjectIdConverter idConverter = ObjectIdConverter.create();
- return ProtoCacheSerializers.toByteArray(
+ return Protos.toByteArray(
MergeabilityKeyProto.newBuilder()
.setCommit(idConverter.toByteString(object.getCommit()))
.setInto(idConverter.toByteString(object.getInto()))
@@ -154,8 +154,7 @@
@Override
public EntryKey deserialize(byte[] in) {
- MergeabilityKeyProto proto =
- ProtoCacheSerializers.parseUnchecked(MergeabilityKeyProto.parser(), in);
+ MergeabilityKeyProto proto = Protos.parseUnchecked(MergeabilityKeyProto.parser(), in);
ObjectIdConverter idConverter = ObjectIdConverter.create();
return new EntryKey(
idConverter.fromByteString(proto.getCommit()),
diff --git a/java/com/google/gerrit/server/change/PureRevert.java b/java/com/google/gerrit/server/change/PureRevert.java
index 14829ea..0135683 100644
--- a/java/com/google/gerrit/server/change/PureRevert.java
+++ b/java/com/google/gerrit/server/change/PureRevert.java
@@ -19,7 +19,6 @@
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.PatchSetUtil;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.MergeUtil;
@@ -27,7 +26,6 @@
import com.google.gerrit.server.project.ProjectCache;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
-import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -49,7 +47,6 @@
private final GitRepositoryManager repoManager;
private final ProjectCache projectCache;
private final ChangeNotes.Factory notesFactory;
- private final Provider<ReviewDb> dbProvider;
private final PatchSetUtil psUtil;
@Inject
@@ -58,13 +55,11 @@
GitRepositoryManager repoManager,
ProjectCache projectCache,
ChangeNotes.Factory notesFactory,
- Provider<ReviewDb> dbProvider,
PatchSetUtil psUtil) {
this.mergeUtilFactory = mergeUtilFactory;
this.repoManager = repoManager;
this.projectCache = projectCache;
this.notesFactory = notesFactory;
- this.dbProvider = dbProvider;
this.psUtil = psUtil;
}
@@ -81,8 +76,7 @@
}
PatchSet ps =
psUtil.current(
- notesFactory.createChecked(
- dbProvider.get(), notes.getProjectName(), notes.getChange().getRevertOf()));
+ notesFactory.createChecked(notes.getProjectName(), notes.getChange().getRevertOf()));
claimedOriginal = ps.getRevision().get();
}
diff --git a/java/com/google/gerrit/server/change/RebaseUtil.java b/java/com/google/gerrit/server/change/RebaseUtil.java
index 8b7c36e..6cb61c1 100644
--- a/java/com/google/gerrit/server/change/RebaseUtil.java
+++ b/java/com/google/gerrit/server/change/RebaseUtil.java
@@ -25,7 +25,6 @@
import com.google.gerrit.reviewdb.client.Change.Status;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.RevId;
-import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.PatchSetUtil;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.query.change.ChangeData;
@@ -46,18 +45,15 @@
private final Provider<InternalChangeQuery> queryProvider;
private final ChangeNotes.Factory notesFactory;
- private final Provider<ReviewDb> dbProvider;
private final PatchSetUtil psUtil;
@Inject
RebaseUtil(
Provider<InternalChangeQuery> queryProvider,
ChangeNotes.Factory notesFactory,
- Provider<ReviewDb> dbProvider,
PatchSetUtil psUtil) {
this.queryProvider = queryProvider;
this.notesFactory = notesFactory;
- this.dbProvider = dbProvider;
this.psUtil = psUtil;
}
@@ -128,7 +124,7 @@
if (rsrc.getChange().getId().equals(id)) {
return rsrc.getNotes();
}
- return notesFactory.createChecked(dbProvider.get(), rsrc.getProject(), id);
+ return notesFactory.createChecked(rsrc.getProject(), id);
}
/**
diff --git a/java/com/google/gerrit/server/events/EventBroker.java b/java/com/google/gerrit/server/events/EventBroker.java
index 94e9bb1..cf07bf6 100644
--- a/java/com/google/gerrit/server/events/EventBroker.java
+++ b/java/com/google/gerrit/server/events/EventBroker.java
@@ -177,7 +177,7 @@
try {
permissionBackend
.user(user)
- .change(notesFactory.createChecked(db, change))
+ .change(notesFactory.createChecked(change))
.database(db)
.check(ChangePermission.READ);
return true;
@@ -209,10 +209,7 @@
if (PatchSet.isChangeRef(ref)) {
Change.Id cid = PatchSet.Id.fromRef(ref).getParentKey();
try {
- Change change =
- notesFactory
- .createChecked(dbProvider.get(), refEvent.getProjectNameKey(), cid)
- .getChange();
+ Change change = notesFactory.createChecked(refEvent.getProjectNameKey(), cid).getChange();
return isVisibleTo(change, user);
} catch (NoSuchChangeException e) {
logger.atFine().log(
diff --git a/java/com/google/gerrit/server/git/GroupCollector.java b/java/com/google/gerrit/server/git/GroupCollector.java
index 88632e6..e40f296 100644
--- a/java/com/google/gerrit/server/git/GroupCollector.java
+++ b/java/com/google/gerrit/server/git/GroupCollector.java
@@ -106,7 +106,6 @@
public static GroupCollector create(
ListMultimap<ObjectId, Ref> changeRefsById,
- ReviewDb db,
PatchSetUtil psUtil,
ChangeNotes.Factory notesFactory,
Project.NameKey project) {
@@ -116,7 +115,7 @@
@Override
public List<String> lookup(PatchSet.Id psId) throws OrmException {
// TODO(dborowitz): Reuse open repository from caller.
- ChangeNotes notes = notesFactory.createChecked(db, project, psId.getParentKey());
+ ChangeNotes notes = notesFactory.createChecked(project, psId.getParentKey());
PatchSet ps = psUtil.get(notes, psId);
return ps != null ? ps.getGroups() : null;
}
diff --git a/java/com/google/gerrit/server/git/MergeUtil.java b/java/com/google/gerrit/server/git/MergeUtil.java
index cc3b415..9cfca88 100644
--- a/java/com/google/gerrit/server/git/MergeUtil.java
+++ b/java/com/google/gerrit/server/git/MergeUtil.java
@@ -348,7 +348,7 @@
for (Map.Entry<String, MergeResult<? extends Sequence>> entry : mergeResults.entrySet()) {
MergeResult<? extends Sequence> p = entry.getValue();
try (TemporaryBuffer buf = new TemporaryBuffer.LocalFile(null, 10 * 1024 * 1024)) {
- fmt.formatMerge(buf, p, "BASE", oursNameFormatted, theirsNameFormatted, UTF_8.name());
+ fmt.formatMerge(buf, p, "BASE", oursNameFormatted, theirsNameFormatted, UTF_8);
buf.close();
try (InputStream in = buf.openInputStream()) {
diff --git a/java/com/google/gerrit/server/git/TagSet.java b/java/com/google/gerrit/server/git/TagSet.java
index ce8814f..57637c89 100644
--- a/java/com/google/gerrit/server/git/TagSet.java
+++ b/java/com/google/gerrit/server/git/TagSet.java
@@ -24,7 +24,7 @@
import com.google.gerrit.server.cache.proto.Cache.TagSetHolderProto.TagSetProto;
import com.google.gerrit.server.cache.proto.Cache.TagSetHolderProto.TagSetProto.CachedRefProto;
import com.google.gerrit.server.cache.proto.Cache.TagSetHolderProto.TagSetProto.TagProto;
-import com.google.gerrit.server.cache.serialize.ProtoCacheSerializers.ObjectIdConverter;
+import com.google.gerrit.server.cache.serialize.ObjectIdConverter;
import com.google.protobuf.ByteString;
import java.io.IOException;
import java.util.BitSet;
diff --git a/java/com/google/gerrit/server/git/TagSetHolder.java b/java/com/google/gerrit/server/git/TagSetHolder.java
index 4c0c035..194283e 100644
--- a/java/com/google/gerrit/server/git/TagSetHolder.java
+++ b/java/com/google/gerrit/server/git/TagSetHolder.java
@@ -17,10 +17,10 @@
import static java.util.stream.Collectors.toList;
import com.google.gerrit.common.Nullable;
+import com.google.gerrit.proto.Protos;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.cache.proto.Cache.TagSetHolderProto;
import com.google.gerrit.server.cache.serialize.CacheSerializer;
-import com.google.gerrit.server.cache.serialize.ProtoCacheSerializers;
import java.util.Collection;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
@@ -111,13 +111,12 @@
if (tags != null) {
b.setTags(tags.toProto());
}
- return ProtoCacheSerializers.toByteArray(b.build());
+ return Protos.toByteArray(b.build());
}
@Override
public TagSetHolder deserialize(byte[] in) {
- TagSetHolderProto proto =
- ProtoCacheSerializers.parseUnchecked(TagSetHolderProto.parser(), in);
+ TagSetHolderProto proto = Protos.parseUnchecked(TagSetHolderProto.parser(), in);
TagSetHolder holder = new TagSetHolder(new Project.NameKey(proto.getProjectName()));
if (proto.hasTags()) {
holder.tags = TagSet.fromProto(proto.getTags());
diff --git a/java/com/google/gerrit/server/git/receive/AsyncReceiveCommits.java b/java/com/google/gerrit/server/git/receive/AsyncReceiveCommits.java
index 882f208..abbba86 100644
--- a/java/com/google/gerrit/server/git/receive/AsyncReceiveCommits.java
+++ b/java/com/google/gerrit/server/git/receive/AsyncReceiveCommits.java
@@ -39,6 +39,7 @@
import com.google.gerrit.server.git.MultiProgressMonitor;
import com.google.gerrit.server.git.ProjectRunnable;
import com.google.gerrit.server.git.TransferConfig;
+import com.google.gerrit.server.git.receive.ResultChangeIds.Key;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackend.RefFilterOptions;
import com.google.gerrit.server.permissions.PermissionBackendException;
@@ -341,17 +342,21 @@
long deltaNanos = System.nanoTime() - startNanos;
int totalChanges = 0;
- for (ResultChangeIds.Key key : ResultChangeIds.Key.values()) {
- List<Change.Id> ids = resultChangeIds.get(key);
- metrics.changes.record(key, ids.size());
- totalChanges += ids.size();
+
+ if (resultChangeIds.isMagicPush()) {
+ List<Change.Id> created = resultChangeIds.get(Key.CREATED);
+ metrics.changes.record(Key.CREATED, created.size());
+ List<Change.Id> replaced = resultChangeIds.get(Key.REPLACED);
+ metrics.changes.record(Key.REPLACED, replaced.size());
+ totalChanges += replaced.size() + created.size();
+ } else {
+ List<Change.Id> autoclosed = resultChangeIds.get(Key.AUTOCLOSED);
+ metrics.changes.record(Key.AUTOCLOSED, autoclosed.size());
}
if (totalChanges > 0) {
metrics.latencyPerChange.record(
- resultChangeIds.get(ResultChangeIds.Key.AUTOCLOSED).isEmpty()
- ? "CREATE_REPLACE"
- : ResultChangeIds.Key.AUTOCLOSED.name(),
+ resultChangeIds.isMagicPush() ? "CREATE_REPLACE" : ResultChangeIds.Key.AUTOCLOSED.name(),
deltaNanos / totalChanges,
NANOSECONDS);
}
diff --git a/java/com/google/gerrit/server/git/receive/ReceiveCommits.java b/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
index 32fbd36..7f9e7a1 100644
--- a/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
+++ b/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
@@ -631,6 +631,7 @@
private void handleRegularCommands(List<ReceiveCommand> cmds, MultiProgressMonitor progress)
throws PermissionBackendException, IOException, NoSuchProjectException {
+ resultChangeIds.setMagicPush(false);
for (ReceiveCommand cmd : cmds) {
parseRegularCommand(cmd);
}
@@ -1825,6 +1826,7 @@
if (validateConnected(magicBranch.cmd, magicBranch.dest, tip)) {
this.magicBranch = magicBranch;
+ this.resultChangeIds.setMagicPush(true);
}
}
@@ -1909,7 +1911,7 @@
Change changeEnt;
try {
- changeEnt = notesFactory.createChecked(db, project.getNameKey(), changeId).getChange();
+ changeEnt = notesFactory.createChecked(project.getNameKey(), changeId).getChange();
} catch (NoSuchChangeException e) {
logger.atSevere().withCause(e).log("Change not found %s", changeId);
reject(cmd, "change " + changeId + " not found");
@@ -1989,7 +1991,7 @@
ListMultimap<ObjectId, Ref> existing = changeRefsById();
GroupCollector groupCollector =
- GroupCollector.create(changeRefsById(), db, psUtil, notesFactory, project.getNameKey());
+ GroupCollector.create(changeRefsById(), psUtil, notesFactory, project.getNameKey());
BranchCommitValidator validator =
commitValidatorFactory.create(projectState, magicBranch.dest, user);
@@ -2253,7 +2255,7 @@
private boolean foundInExistingRef(Collection<Ref> existingRefs) throws OrmException {
for (Ref ref : existingRefs) {
ChangeNotes notes =
- notesFactory.create(db, project.getNameKey(), Change.Id.fromRef(ref.getName()));
+ notesFactory.create(project.getNameKey(), Change.Id.fromRef(ref.getName()));
Change change = notes.getChange();
if (change.getDest().equals(magicBranch.dest)) {
logger.atFine().log("Found change %s from existing refs.", change.getKey());
@@ -2562,7 +2564,7 @@
private void readChangesForReplace() throws OrmException {
Collection<ChangeNotes> allNotes =
notesFactory.create(
- db, replaceByChange.values().stream().map(r -> r.ontoChange).collect(toList()));
+ replaceByChange.values().stream().map(r -> r.ontoChange).collect(toList()));
for (ChangeNotes notes : allNotes) {
replaceByChange.get(notes.getChangeId()).notes = notes;
}
@@ -3212,7 +3214,7 @@
private Optional<ChangeNotes> getChangeNotes(Change.Id changeId) throws OrmException {
try {
- return Optional.of(notesFactory.createChecked(db, project.getNameKey(), changeId));
+ return Optional.of(notesFactory.createChecked(project.getNameKey(), changeId));
} catch (NoSuchChangeException e) {
return Optional.empty();
}
diff --git a/java/com/google/gerrit/server/git/receive/ResultChangeIds.java b/java/com/google/gerrit/server/git/receive/ResultChangeIds.java
index bbf8d95..e326141 100644
--- a/java/com/google/gerrit/server/git/receive/ResultChangeIds.java
+++ b/java/com/google/gerrit/server/git/receive/ResultChangeIds.java
@@ -33,6 +33,7 @@
AUTOCLOSED,
}
+ private boolean isMagicPush;
private final Map<Key, List<Change.Id>> ids;
ResultChangeIds() {
@@ -43,16 +44,24 @@
}
/** Record a change ID update as having completed. Thread-safe. */
- public void add(Key key, Change.Id id) {
- synchronized (this) {
- ids.get(key).add(id);
- }
+ public synchronized void add(Key key, Change.Id id) {
+ ids.get(key).add(id);
}
- /** Returns change IDs of the given type for which the BatchUpdate succeeded. Thread-safe. */
- public List<Change.Id> get(Key key) {
- synchronized (this) {
- return ImmutableList.copyOf(ids.get(key));
- }
+ /** Indicate that the ReceiveCommits call involved a magic branch. */
+ public synchronized void setMagicPush(boolean magic) {
+ isMagicPush = magic;
+ }
+
+ public synchronized boolean isMagicPush() {
+ return isMagicPush;
+ }
+
+ /**
+ * Returns change IDs of the given type for which the BatchUpdate succeeded, or empty list if
+ * there are none. Thread-safe.
+ */
+ public synchronized List<Change.Id> get(Key key) {
+ return ImmutableList.copyOf(ids.get(key));
}
}
diff --git a/java/com/google/gerrit/server/index/change/ChangeField.java b/java/com/google/gerrit/server/index/change/ChangeField.java
index b79a1c2..bae3377 100644
--- a/java/com/google/gerrit/server/index/change/ChangeField.java
+++ b/java/com/google/gerrit/server/index/change/ChangeField.java
@@ -15,6 +15,7 @@
package com.google.gerrit.server.index.change;
import static com.google.common.base.MoreObjects.firstNonNull;
+import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.gerrit.index.FieldDef.exact;
import static com.google.gerrit.index.FieldDef.fullText;
import static com.google.gerrit.index.FieldDef.intRange;
@@ -22,9 +23,7 @@
import static com.google.gerrit.index.FieldDef.prefix;
import static com.google.gerrit.index.FieldDef.storedOnly;
import static com.google.gerrit.index.FieldDef.timestamp;
-import static com.google.gerrit.reviewdb.server.ReviewDbCodecs.APPROVAL_CODEC;
import static com.google.gerrit.reviewdb.server.ReviewDbCodecs.CHANGE_CODEC;
-import static com.google.gerrit.reviewdb.server.ReviewDbCodecs.PATCH_SET_CODEC;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toSet;
@@ -46,6 +45,7 @@
import com.google.gerrit.index.RefState;
import com.google.gerrit.index.SchemaUtil;
import com.google.gerrit.mail.Address;
+import com.google.gerrit.proto.Protos;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.ChangeMessage;
@@ -53,6 +53,9 @@
import com.google.gerrit.reviewdb.client.PatchSetApproval;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
+import com.google.gerrit.reviewdb.converter.PatchSetApprovalProtoConverter;
+import com.google.gerrit.reviewdb.converter.PatchSetProtoConverter;
+import com.google.gerrit.reviewdb.converter.ProtoConverter;
import com.google.gerrit.server.OutputFormat;
import com.google.gerrit.server.ReviewerByEmailSet;
import com.google.gerrit.server.ReviewerSet;
@@ -68,10 +71,7 @@
import com.google.gerrit.server.query.change.ChangeQueryBuilder;
import com.google.gerrit.server.query.change.ChangeStatusPredicate;
import com.google.gson.Gson;
-import com.google.gwtorm.protobuf.ProtobufCodec;
import com.google.gwtorm.server.OrmException;
-import com.google.protobuf.CodedOutputStream;
-import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.ArrayList;
@@ -474,7 +474,8 @@
/** Serialized approvals for the current patch set, used for pre-populating results. */
public static final FieldDef<ChangeData, Iterable<byte[]>> APPROVAL =
storedOnly("_approval")
- .buildRepeatable(cd -> toProtos(APPROVAL_CODEC, cd.currentApprovals()));
+ .buildRepeatable(
+ cd -> toProtos(PatchSetApprovalProtoConverter.INSTANCE, cd.currentApprovals()));
public static String formatLabel(String label, int value) {
return formatLabel(label, value, null);
@@ -596,7 +597,8 @@
/** Serialized patch set object, used for pre-populating results. */
public static final FieldDef<ChangeData, Iterable<byte[]>> PATCH_SET =
- storedOnly("_patch_set").buildRepeatable(cd -> toProtos(PATCH_SET_CODEC, cd.patchSets()));
+ storedOnly("_patch_set")
+ .buildRepeatable(cd -> toProtos(PatchSetProtoConverter.INSTANCE, cd.patchSets()));
/** Users who have edits on this change. */
public static final FieldDef<ChangeData, Iterable<Integer>> EDITBY =
@@ -856,22 +858,12 @@
return firstNonNull(c.getTopic(), "");
}
- private static <T> List<byte[]> toProtos(ProtobufCodec<T> codec, Collection<T> objs)
- throws OrmException {
- List<byte[]> result = Lists.newArrayListWithCapacity(objs.size());
- ByteArrayOutputStream out = new ByteArrayOutputStream(256);
- try {
- for (T obj : objs) {
- out.reset();
- CodedOutputStream cos = CodedOutputStream.newInstance(out);
- codec.encode(obj, cos);
- cos.flush();
- result.add(out.toByteArray());
- }
- } catch (IOException e) {
- throw new OrmException(e);
- }
- return result;
+ private static <T> List<byte[]> toProtos(ProtoConverter<?, T> converter, Collection<T> objects) {
+ return objects
+ .stream()
+ .map(converter::toProto)
+ .map(Protos::toByteArray)
+ .collect(toImmutableList());
}
private static <T> FieldDef.Getter<ChangeData, T> changeGetter(Function<Change, T> func) {
diff --git a/java/com/google/gerrit/server/index/change/ReindexAfterRefUpdate.java b/java/com/google/gerrit/server/index/change/ReindexAfterRefUpdate.java
index 609432b..e3fb740 100644
--- a/java/com/google/gerrit/server/index/change/ReindexAfterRefUpdate.java
+++ b/java/com/google/gerrit/server/index/change/ReindexAfterRefUpdate.java
@@ -185,9 +185,7 @@
ReviewDb db = ctx.getReviewDbProvider().get();
try {
Change c =
- notesFactory
- .createChecked(db, new Project.NameKey(event.getProjectName()), id)
- .getChange();
+ notesFactory.createChecked(new Project.NameKey(event.getProjectName()), id).getChange();
indexerFactory.create(executor, indexes).index(db, c);
} catch (NoSuchChangeException e) {
indexerFactory.create(executor, indexes).delete(id);
diff --git a/java/com/google/gerrit/server/index/change/StalenessChecker.java b/java/com/google/gerrit/server/index/change/StalenessChecker.java
index cf7db6f..d5d6b05 100644
--- a/java/com/google/gerrit/server/index/change/StalenessChecker.java
+++ b/java/com/google/gerrit/server/index/change/StalenessChecker.java
@@ -36,9 +36,9 @@
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gerrit.reviewdb.server.ReviewDbUtil;
import com.google.gerrit.server.UsedAt;
import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gwtorm.server.OrmException;
@@ -100,7 +100,7 @@
repoManager,
id,
cd.change(),
- ChangeNotes.readOneReviewDbChange(db.get(), id),
+ ReviewDbUtil.unwrapDb(db.get()).changes().get(id),
parseStates(cd),
parsePatterns(cd));
}
diff --git a/java/com/google/gerrit/server/notedb/AbstractChangeNotes.java b/java/com/google/gerrit/server/notedb/AbstractChangeNotes.java
index 32d086c..d3ab0e0 100644
--- a/java/com/google/gerrit/server/notedb/AbstractChangeNotes.java
+++ b/java/com/google/gerrit/server/notedb/AbstractChangeNotes.java
@@ -14,7 +14,6 @@
package com.google.gerrit.server.notedb;
-import static com.google.common.base.Preconditions.checkState;
import static com.google.gerrit.server.notedb.NoteDbTable.CHANGES;
import static java.util.Objects.requireNonNull;
@@ -34,6 +33,7 @@
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
+import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
@@ -44,8 +44,10 @@
@VisibleForTesting
@Singleton
public static class Args {
+ // TODO(dborowitz): Some less smelly way of disabling NoteDb in tests.
+ public final AtomicBoolean failOnLoadForTest;
+
final GitRepositoryManager repoManager;
- final NotesMigration migration;
final AllUsersName allUsers;
final ChangeNoteJson changeNoteJson;
final LegacyChangeNoteRead legacyChangeNoteRead;
@@ -60,15 +62,14 @@
@Inject
Args(
GitRepositoryManager repoManager,
- NotesMigration migration,
AllUsersName allUsers,
ChangeNoteJson changeNoteJson,
LegacyChangeNoteRead legacyChangeNoteRead,
NoteDbMetrics metrics,
Provider<ReviewDb> db,
Provider<ChangeNotesCache> cache) {
+ this.failOnLoadForTest = new AtomicBoolean();
this.repoManager = repoManager;
- this.migration = migration;
this.allUsers = allUsers;
this.legacyChangeNoteRead = legacyChangeNoteRead;
this.changeNoteJson = changeNoteJson;
@@ -132,8 +133,7 @@
return self();
}
- checkState(args.migration.readChanges(), "NoteDb is required to read changes");
- if (args.migration.failOnLoadForTest()) {
+ if (args.failOnLoadForTest.get()) {
throw new OrmException("Reading from NoteDb is disabled");
}
try (Timer1.Context timer = args.metrics.readLatency.start(CHANGES);
@@ -181,8 +181,6 @@
public ObjectId loadRevision() throws OrmException {
if (loaded) {
return getRevision();
- } else if (!args.migration.readChanges()) {
- return null;
}
try (Repository repo = args.repoManager.openRepository(getProjectName())) {
Ref ref = repo.getRefDatabase().exactRef(getRefName());
diff --git a/java/com/google/gerrit/server/notedb/AbstractChangeUpdate.java b/java/com/google/gerrit/server/notedb/AbstractChangeUpdate.java
index e0cc771..1e90447 100644
--- a/java/com/google/gerrit/server/notedb/AbstractChangeUpdate.java
+++ b/java/com/google/gerrit/server/notedb/AbstractChangeUpdate.java
@@ -215,10 +215,6 @@
return null;
}
- // Allow this method to proceed even if migration.failChangeWrites() = true.
- // This may be used by an auto-rebuilding step that the caller does not plan
- // to actually store.
-
checkArgument(rw.getObjectReader().getCreatedFromInserter() == ins);
checkNotReadOnly();
diff --git a/java/com/google/gerrit/server/notedb/ChangeNotes.java b/java/com/google/gerrit/server/notedb/ChangeNotes.java
index e5e0d51..37de143 100644
--- a/java/com/google/gerrit/server/notedb/ChangeNotes.java
+++ b/java/com/google/gerrit/server/notedb/ChangeNotes.java
@@ -47,8 +47,6 @@
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.reviewdb.client.RevId;
import com.google.gerrit.reviewdb.client.RobotComment;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.reviewdb.server.ReviewDbUtil;
import com.google.gerrit.server.ReviewerByEmailSet;
import com.google.gerrit.server.ReviewerSet;
import com.google.gerrit.server.ReviewerStatusUpdate;
@@ -92,11 +90,6 @@
return new ConfigInvalidException("Change " + changeId + ": " + String.format(fmt, args));
}
- @Nullable
- public static Change readOneReviewDbChange(ReviewDb db, Change.Id id) throws OrmException {
- return ReviewDbUtil.unwrapDb(db).changes().get(id);
- }
-
@Singleton
public static class Factory {
private final Args args;
@@ -112,23 +105,14 @@
this.projectCache = projectCache;
}
- public ChangeNotes createChecked(ReviewDb db, Change c) throws OrmException {
- return createChecked(db, c.getProject(), c.getId());
+ public ChangeNotes createChecked(Change c) throws OrmException {
+ return createChecked(c.getProject(), c.getId());
}
- public ChangeNotes createChecked(ReviewDb db, Project.NameKey project, Change.Id changeId)
+ public ChangeNotes createChecked(Project.NameKey project, Change.Id changeId)
throws OrmException {
- Change change = readOneReviewDbChange(db, changeId);
- if (change == null) {
- if (!args.migration.readChanges()) {
- throw new NoSuchChangeException(changeId);
- }
- // Change isn't in ReviewDb, but its primary storage might be in NoteDb.
- // Prepopulate the change exists with proper noteDbState field.
- change = newNoteDbOnlyChange(project, changeId);
- } else if (!change.getProject().equals(project)) {
- throw new NoSuchChangeException(changeId);
- }
+ // Prepopulate the change exists with proper noteDbState field.
+ Change change = newChange(project, changeId);
return new ChangeNotes(args, change).load();
}
@@ -145,7 +129,7 @@
return changes.get(0).notes();
}
- public static Change newNoteDbOnlyChange(Project.NameKey project, Change.Id changeId) {
+ public static Change newChange(Project.NameKey project, Change.Id changeId) {
Change change =
new Change(
null, changeId, null, new Branch.NameKey(project, "INVALID_NOTE_DB_ONLY"), null);
@@ -153,29 +137,9 @@
return change;
}
- private Change loadChangeFromDb(ReviewDb db, Project.NameKey project, Change.Id changeId)
- throws OrmException {
+ public ChangeNotes create(Project.NameKey project, Change.Id changeId) throws OrmException {
checkArgument(project != null, "project is required");
- Change change = readOneReviewDbChange(db, changeId);
-
- if (change == null) {
- if (args.migration.readChanges()) {
- return newNoteDbOnlyChange(project, changeId);
- }
- throw new NoSuchChangeException(changeId);
- }
- checkArgument(
- change.getProject().equals(project),
- "passed project %s when creating ChangeNotes for %s, but actual project is %s",
- project,
- changeId,
- change.getProject());
- return change;
- }
-
- public ChangeNotes create(ReviewDb db, Project.NameKey project, Change.Id changeId)
- throws OrmException {
- return new ChangeNotes(args, loadChangeFromDb(db, project, changeId)).load();
+ return new ChangeNotes(args, newChange(project, changeId)).load();
}
/**
@@ -198,91 +162,48 @@
return new ChangeNotes(args, change, true, refs).load();
}
- // TODO(ekempin): Remove when database backend is deleted
- /**
- * Instantiate ChangeNotes for a change that has been loaded by a batch read from the database.
- */
- private ChangeNotes createFromChangeOnlyWhenNoteDbDisabled(Change change) throws OrmException {
- checkState(
- !args.migration.readChanges(),
- "do not call createFromChangeWhenNoteDbDisabled when NoteDb is enabled");
- return new ChangeNotes(args, change).load();
- }
-
- public List<ChangeNotes> create(ReviewDb db, Collection<Change.Id> changeIds)
- throws OrmException {
+ public List<ChangeNotes> create(Collection<Change.Id> changeIds) throws OrmException {
List<ChangeNotes> notes = new ArrayList<>();
- if (args.migration.readChanges()) {
- for (Change.Id changeId : changeIds) {
- try {
- notes.add(createChecked(changeId));
- } catch (NoSuchChangeException e) {
- // Ignore missing changes to match Access#get(Iterable) behavior.
- }
+ for (Change.Id changeId : changeIds) {
+ try {
+ notes.add(createChecked(changeId));
+ } catch (NoSuchChangeException e) {
+ // Ignore missing changes to match Access#get(Iterable) behavior.
}
- return notes;
- }
-
- for (Change c : ReviewDbUtil.unwrapDb(db).changes().get(changeIds)) {
- notes.add(createFromChangeOnlyWhenNoteDbDisabled(c));
}
return notes;
}
public List<ChangeNotes> create(
- ReviewDb db,
- Project.NameKey project,
- Collection<Change.Id> changeIds,
- Predicate<ChangeNotes> predicate)
+ Project.NameKey project, Collection<Change.Id> changeIds, Predicate<ChangeNotes> predicate)
throws OrmException {
List<ChangeNotes> notes = new ArrayList<>();
- if (args.migration.readChanges()) {
- for (Change.Id cid : changeIds) {
- try {
- ChangeNotes cn = create(db, project, cid);
- if (cn.getChange() != null && predicate.test(cn)) {
- notes.add(cn);
- }
- } catch (NoSuchChangeException e) {
- // Match ReviewDb behavior, returning not found; maybe the caller learned about it from
- // a dangling patch set ref or something.
- continue;
- }
- }
- return notes;
- }
-
- for (Change c : ReviewDbUtil.unwrapDb(db).changes().get(changeIds)) {
- if (c != null && project.equals(c.getDest().getParentKey())) {
- ChangeNotes cn = createFromChangeOnlyWhenNoteDbDisabled(c);
- if (predicate.test(cn)) {
+ for (Change.Id cid : changeIds) {
+ try {
+ ChangeNotes cn = create(project, cid);
+ if (cn.getChange() != null && predicate.test(cn)) {
notes.add(cn);
}
+ } catch (NoSuchChangeException e) {
+ // Match ReviewDb behavior, returning not found; maybe the caller learned about it from
+ // a dangling patch set ref or something.
+ continue;
}
}
return notes;
}
- public ListMultimap<Project.NameKey, ChangeNotes> create(
- ReviewDb db, Predicate<ChangeNotes> predicate) throws IOException, OrmException {
+ public ListMultimap<Project.NameKey, ChangeNotes> create(Predicate<ChangeNotes> predicate)
+ throws IOException {
ListMultimap<Project.NameKey, ChangeNotes> m =
MultimapBuilder.hashKeys().arrayListValues().build();
- if (args.migration.readChanges()) {
- for (Project.NameKey project : projectCache.all()) {
- try (Repository repo = args.repoManager.openRepository(project)) {
- scan(repo, project)
- .filter(r -> !r.error().isPresent())
- .map(ChangeNotesResult::notes)
- .filter(predicate)
- .forEach(n -> m.put(n.getProjectName(), n));
- }
- }
- } else {
- for (Change change : ReviewDbUtil.unwrapDb(db).changes().all()) {
- ChangeNotes notes = createFromChangeOnlyWhenNoteDbDisabled(change);
- if (predicate.test(notes)) {
- m.put(change.getProject(), notes);
- }
+ for (Project.NameKey project : projectCache.all()) {
+ try (Repository repo = args.repoManager.openRepository(project)) {
+ scan(repo, project)
+ .filter(r -> !r.error().isPresent())
+ .map(ChangeNotesResult::notes)
+ .filter(predicate)
+ .forEach(n -> m.put(n.getProjectName(), n));
}
}
return ImmutableListMultimap.copyOf(m);
@@ -302,16 +223,16 @@
return null;
}
- // TODO(dborowitz): See discussion in NoteDbBatchUpdate#newChangeContext.
- Change change = ChangeNotes.Factory.newNoteDbOnlyChange(project, id);
+ // TODO(dborowitz): See discussion in BatchUpdate#newChangeContext.
+ Change change = ChangeNotes.Factory.newChange(project, id);
logger.atFine().log("adding change %s found in project %s", id, project);
return toResult(change);
}
@Nullable
- private ChangeNotesResult toResult(Change rawChangeFromReviewDbOrNoteDb) {
- ChangeNotes n = new ChangeNotes(args, rawChangeFromReviewDbOrNoteDb);
+ private ChangeNotesResult toResult(Change rawChangeFromNoteDb) {
+ ChangeNotes n = new ChangeNotes(args, rawChangeFromNoteDb);
try {
n.load();
} catch (OrmException e) {
@@ -594,9 +515,10 @@
protected void onLoad(LoadHandle handle) throws NoSuchChangeException, IOException {
ObjectId rev = handle.id();
if (rev == null) {
- if (args.migration.readChanges()
- && PrimaryStorage.of(change) == PrimaryStorage.NOTE_DB
- && shouldExist) {
+ // TODO(ekempin): Remove the primary storage check. At the moment it is still needed for the
+ // ChangeNotesParserTest which still runs with ReviewDb changes (see TODO in
+ // TestUpdate#newChange).
+ if (PrimaryStorage.of(change) == PrimaryStorage.NOTE_DB && shouldExist) {
throw new NoSuchChangeException(getChangeId());
}
loadDefaults();
diff --git a/java/com/google/gerrit/server/notedb/ChangeNotesCache.java b/java/com/google/gerrit/server/notedb/ChangeNotesCache.java
index cc316e5..add5803 100644
--- a/java/com/google/gerrit/server/notedb/ChangeNotesCache.java
+++ b/java/com/google/gerrit/server/notedb/ChangeNotesCache.java
@@ -20,6 +20,7 @@
import com.google.common.collect.Table;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
+import com.google.gerrit.proto.Protos;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
@@ -28,8 +29,7 @@
import com.google.gerrit.server.cache.CacheModule;
import com.google.gerrit.server.cache.proto.Cache.ChangeNotesKeyProto;
import com.google.gerrit.server.cache.serialize.CacheSerializer;
-import com.google.gerrit.server.cache.serialize.ProtoCacheSerializers;
-import com.google.gerrit.server.cache.serialize.ProtoCacheSerializers.ObjectIdConverter;
+import com.google.gerrit.server.cache.serialize.ObjectIdConverter;
import com.google.gerrit.server.notedb.AbstractChangeNotes.Args;
import com.google.gerrit.server.notedb.ChangeNotesCommit.ChangeNotesRevWalk;
import com.google.inject.Inject;
@@ -85,7 +85,7 @@
@Override
public byte[] serialize(Key object) {
- return ProtoCacheSerializers.toByteArray(
+ return Protos.toByteArray(
ChangeNotesKeyProto.newBuilder()
.setProject(object.project().get())
.setChangeId(object.changeId().get())
@@ -95,8 +95,7 @@
@Override
public Key deserialize(byte[] in) {
- ChangeNotesKeyProto proto =
- ProtoCacheSerializers.parseUnchecked(ChangeNotesKeyProto.parser(), in);
+ ChangeNotesKeyProto proto = Protos.parseUnchecked(ChangeNotesKeyProto.parser(), in);
return Key.create(
new Project.NameKey(proto.getProject()),
new Change.Id(proto.getChangeId()),
diff --git a/java/com/google/gerrit/server/notedb/ChangeNotesState.java b/java/com/google/gerrit/server/notedb/ChangeNotesState.java
index ca579ae..7ce7e66 100644
--- a/java/com/google/gerrit/server/notedb/ChangeNotesState.java
+++ b/java/com/google/gerrit/server/notedb/ChangeNotesState.java
@@ -19,10 +19,6 @@
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.ImmutableListMultimap.toImmutableListMultimap;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
-import static com.google.gerrit.reviewdb.server.ReviewDbCodecs.APPROVAL_CODEC;
-import static com.google.gerrit.reviewdb.server.ReviewDbCodecs.MESSAGE_CODEC;
-import static com.google.gerrit.reviewdb.server.ReviewDbCodecs.PATCH_SET_CODEC;
-import static com.google.gerrit.server.cache.serialize.ProtoCacheSerializers.toByteString;
import static java.util.Objects.requireNonNull;
import com.google.auto.value.AutoValue;
@@ -40,6 +36,7 @@
import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.data.SubmitRecord;
import com.google.gerrit.mail.Address;
+import com.google.gerrit.proto.Protos;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.reviewdb.client.Change;
@@ -49,6 +46,10 @@
import com.google.gerrit.reviewdb.client.PatchSetApproval;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RevId;
+import com.google.gerrit.reviewdb.converter.ChangeMessageProtoConverter;
+import com.google.gerrit.reviewdb.converter.PatchSetApprovalProtoConverter;
+import com.google.gerrit.reviewdb.converter.PatchSetProtoConverter;
+import com.google.gerrit.reviewdb.converter.ProtoConverter;
import com.google.gerrit.server.OutputFormat;
import com.google.gerrit.server.ReviewerByEmailSet;
import com.google.gerrit.server.ReviewerSet;
@@ -59,11 +60,12 @@
import com.google.gerrit.server.cache.proto.Cache.ChangeNotesStateProto.ReviewerSetEntryProto;
import com.google.gerrit.server.cache.proto.Cache.ChangeNotesStateProto.ReviewerStatusUpdateProto;
import com.google.gerrit.server.cache.serialize.CacheSerializer;
-import com.google.gerrit.server.cache.serialize.ProtoCacheSerializers;
-import com.google.gerrit.server.cache.serialize.ProtoCacheSerializers.ObjectIdConverter;
+import com.google.gerrit.server.cache.serialize.ObjectIdConverter;
import com.google.gerrit.server.index.change.ChangeField.StoredSubmitRecord;
import com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage;
import com.google.gson.Gson;
+import com.google.protobuf.ByteString;
+import com.google.protobuf.MessageLite;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.List;
@@ -455,8 +457,15 @@
object.pastAssignees().forEach(a -> b.addPastAssignee(a.get()));
object.hashtags().forEach(b::addHashtag);
- object.patchSets().forEach(e -> b.addPatchSet(toByteString(e.getValue(), PATCH_SET_CODEC)));
- object.approvals().forEach(e -> b.addApproval(toByteString(e.getValue(), APPROVAL_CODEC)));
+ object
+ .patchSets()
+ .forEach(e -> b.addPatchSet(toByteString(e.getValue(), PatchSetProtoConverter.INSTANCE)));
+ object
+ .approvals()
+ .forEach(
+ e ->
+ b.addApproval(
+ toByteString(e.getValue(), PatchSetApprovalProtoConverter.INSTANCE)));
object.reviewers().asTable().cellSet().forEach(c -> b.addReviewer(toReviewerSetEntry(c)));
object
@@ -480,14 +489,22 @@
object
.submitRecords()
.forEach(r -> b.addSubmitRecord(GSON.toJson(new StoredSubmitRecord(r))));
- object.changeMessages().forEach(m -> b.addChangeMessage(toByteString(m, MESSAGE_CODEC)));
+ object
+ .changeMessages()
+ .forEach(m -> b.addChangeMessage(toByteString(m, ChangeMessageProtoConverter.INSTANCE)));
object.publishedComments().values().forEach(c -> b.addPublishedComment(GSON.toJson(c)));
if (object.readOnlyUntil() != null) {
b.setReadOnlyUntil(object.readOnlyUntil().getTime()).setHasReadOnlyUntil(true);
}
- return ProtoCacheSerializers.toByteArray(b.build());
+ return Protos.toByteArray(b.build());
+ }
+
+ @VisibleForTesting
+ static <T> ByteString toByteString(T object, ProtoConverter<?, T> converter) {
+ MessageLite message = converter.toProto(object);
+ return Protos.toByteString(message);
}
private static ChangeColumnsProto toChangeColumnsProto(ChangeColumns cols) {
@@ -555,8 +572,7 @@
@Override
public ChangeNotesState deserialize(byte[] in) {
- ChangeNotesStateProto proto =
- ProtoCacheSerializers.parseUnchecked(ChangeNotesStateProto.parser(), in);
+ ChangeNotesStateProto proto = Protos.parseUnchecked(ChangeNotesStateProto.parser(), in);
Change.Id changeId = new Change.Id(proto.getChangeId());
ChangeNotesState.Builder b =
@@ -575,14 +591,14 @@
proto
.getPatchSetList()
.stream()
- .map(PATCH_SET_CODEC::decode)
+ .map(bytes -> parseProtoFrom(PatchSetProtoConverter.INSTANCE, bytes))
.map(ps -> Maps.immutableEntry(ps.getId(), ps))
.collect(toImmutableList()))
.approvals(
proto
.getApprovalList()
.stream()
- .map(APPROVAL_CODEC::decode)
+ .map(bytes -> parseProtoFrom(PatchSetApprovalProtoConverter.INSTANCE, bytes))
.map(a -> Maps.immutableEntry(a.getPatchSetId(), a))
.collect(toImmutableList()))
.reviewers(toReviewerSet(proto.getReviewerList()))
@@ -606,7 +622,7 @@
proto
.getChangeMessageList()
.stream()
- .map(MESSAGE_CODEC::decode)
+ .map(bytes -> parseProtoFrom(ChangeMessageProtoConverter.INSTANCE, bytes))
.collect(toImmutableList()))
.publishedComments(
proto
@@ -620,6 +636,12 @@
return b.build();
}
+ private static <P extends MessageLite, T> T parseProtoFrom(
+ ProtoConverter<P, T> converter, ByteString byteString) {
+ P message = Protos.parseUnchecked(converter.getParser(), byteString);
+ return converter.fromProto(message);
+ }
+
private static ChangeColumns toChangeColumns(Change.Id changeId, ChangeColumnsProto proto) {
ChangeColumns.Builder b =
ChangeColumns.builder()
diff --git a/java/com/google/gerrit/server/notedb/MutableNotesMigration.java b/java/com/google/gerrit/server/notedb/MutableNotesMigration.java
deleted file mode 100644
index eb41cbc..0000000
--- a/java/com/google/gerrit/server/notedb/MutableNotesMigration.java
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright (C) 2017 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.server.notedb;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
-import java.util.function.Function;
-import org.eclipse.jgit.lib.Config;
-
-/**
- * {@link NotesMigration} with additional methods for altering the migration state at runtime.
- *
- * <p>Almost all callers care only about inspecting the migration state, and for safety should not
- * have access to mutation methods, which must be used with extreme care. Those callers should
- * inject {@link NotesMigration}.
- *
- * <p>Some callers, namely the NoteDb migration pipeline and tests, do need to alter the migration
- * state at runtime, and those callers are expected to take the necessary precautions such as
- * keeping the in-memory and on-disk config state in sync. Those callers use this class.
- *
- * <p>Mutations to the {@link MutableNotesMigration} are guaranteed to be instantly visible to all
- * callers that use the non-mutable {@link NotesMigration}. The current implementation accomplishes
- * this by always binding {@link NotesMigration} to {@link MutableNotesMigration} in Guice, so there
- * is just one {@link NotesMigration} instance process-wide.
- */
-@Singleton
-public class MutableNotesMigration extends NotesMigration {
- public static MutableNotesMigration newDisabled() {
- return new MutableNotesMigration(new Config());
- }
-
- public static MutableNotesMigration fromConfig(Config cfg) {
- return new MutableNotesMigration(cfg);
- }
-
- @Inject
- MutableNotesMigration(@GerritServerConfig Config cfg) {
- super(Snapshot.create(cfg));
- }
-
- public MutableNotesMigration setReadChanges(boolean readChanges) {
- return set(b -> b.setReadChanges(readChanges));
- }
-
- public MutableNotesMigration setWriteChanges(boolean writeChanges) {
- return set(b -> b.setWriteChanges(writeChanges));
- }
-
- public MutableNotesMigration setReadChangeSequence(boolean readChangeSequence) {
- return set(b -> b.setReadChangeSequence(readChangeSequence));
- }
-
- public MutableNotesMigration setChangePrimaryStorage(PrimaryStorage changePrimaryStorage) {
- return set(b -> b.setChangePrimaryStorage(changePrimaryStorage));
- }
-
- public MutableNotesMigration setDisableChangeReviewDb(boolean disableChangeReviewDb) {
- return set(b -> b.setDisableChangeReviewDb(disableChangeReviewDb));
- }
-
- public MutableNotesMigration setFailOnLoadForTest(boolean failOnLoadForTest) {
- return set(b -> b.setFailOnLoadForTest(failOnLoadForTest));
- }
-
- /**
- * Set the in-memory values returned by this instance to match the given state.
- *
- * <p>This method is only intended for use by tests.
- *
- * <p>This <em>only</em> modifies the in-memory state; if this instance was initialized from a
- * file-based config, the underlying storage is not updated. Callers are responsible for managing
- * the underlying storage on their own.
- */
- @VisibleForTesting
- public MutableNotesMigration setFrom(NotesMigrationState state) {
- snapshot.set(state.snapshot());
- return this;
- }
-
- private MutableNotesMigration set(Function<Snapshot.Builder, Snapshot.Builder> f) {
- snapshot.updateAndGet(s -> f.apply(s.toBuilder()).build());
- return this;
- }
-}
diff --git a/java/com/google/gerrit/server/notedb/NoteDbMetrics.java b/java/com/google/gerrit/server/notedb/NoteDbMetrics.java
index be06d11..61f475f 100644
--- a/java/com/google/gerrit/server/notedb/NoteDbMetrics.java
+++ b/java/com/google/gerrit/server/notedb/NoteDbMetrics.java
@@ -14,7 +14,6 @@
package com.google.gerrit.server.notedb;
-import com.google.gerrit.metrics.Counter1;
import com.google.gerrit.metrics.Description;
import com.google.gerrit.metrics.Description.Units;
import com.google.gerrit.metrics.Field;
@@ -44,16 +43,6 @@
*/
final Timer1<NoteDbTable> parseLatency;
- /**
- * Latency due to auto-rebuilding entities when out of date.
- *
- * <p>Excludes latency from reading ref to check whether the entity is up to date.
- */
- final Timer1<NoteDbTable> autoRebuildLatency;
-
- /** Count of auto-rebuild attempts that failed. */
- final Counter1<NoteDbTable> autoRebuildFailureCount;
-
@Inject
NoteDbMetrics(MetricMaker metrics) {
Field<NoteDbTable> view = Field.ofEnum(NoteDbTable.class, "table");
@@ -89,19 +78,5 @@
.setCumulative()
.setUnit(Units.MICROSECONDS),
view);
-
- autoRebuildLatency =
- metrics.newTimer(
- "notedb/auto_rebuild_latency",
- new Description("NoteDb auto-rebuilding latency by table")
- .setCumulative()
- .setUnit(Units.MILLISECONDS),
- view);
-
- autoRebuildFailureCount =
- metrics.newCounter(
- "notedb/auto_rebuild_failure_count",
- new Description("NoteDb auto-rebuilding attempts that failed by table").setCumulative(),
- view);
}
}
diff --git a/java/com/google/gerrit/server/notedb/NoteDbUpdateManager.java b/java/com/google/gerrit/server/notedb/NoteDbUpdateManager.java
index 046757d..35cd402 100644
--- a/java/com/google/gerrit/server/notedb/NoteDbUpdateManager.java
+++ b/java/com/google/gerrit/server/notedb/NoteDbUpdateManager.java
@@ -614,10 +614,6 @@
@Nullable
public BatchRefUpdate execute(boolean dryrun) throws OrmException, IOException {
- // Check before even inspecting the list, as this is a programmer error.
- if (migration.failChangeWrites()) {
- throw new OrmException(CHANGES_READ_ONLY);
- }
if (isEmpty()) {
return null;
}
diff --git a/java/com/google/gerrit/server/notedb/NotesMigration.java b/java/com/google/gerrit/server/notedb/NotesMigration.java
index 28754a6..26e764a 100644
--- a/java/com/google/gerrit/server/notedb/NotesMigration.java
+++ b/java/com/google/gerrit/server/notedb/NotesMigration.java
@@ -14,129 +14,22 @@
package com.google.gerrit.server.notedb;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.gerrit.server.notedb.NoteDbTable.CHANGES;
-
-import com.google.auto.value.AutoValue;
-import com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage;
-import com.google.inject.AbstractModule;
-import java.util.concurrent.atomic.AtomicReference;
-import org.eclipse.jgit.lib.Config;
+import com.google.inject.Singleton;
+import java.util.Objects;
/**
* Current low-level settings of the NoteDb migration for changes.
*
- * <p>This class only describes the migration state of the {@link
- * com.google.gerrit.reviewdb.client.Change Change} entity group, since it is possible for a given
- * site to be in different states of the Change NoteDb migration process while staying at the same
- * ReviewDb schema version. It does <em>not</em> describe the migration state of non-Change tables;
- * those are automatically migrated using the ReviewDb schema migration process, so the NoteDb
- * migration state at a given ReviewDb schema cannot vary.
- *
- * <p>In many places, core Gerrit code should not directly care about the NoteDb migration state,
- * and should prefer high-level APIs like {@link com.google.gerrit.server.ApprovalsUtil
- * ApprovalsUtil} that don't require callers to inspect the migration state. The
- * <em>implementation</em> of those utilities does care about the state, and should query the {@code
- * NotesMigration} for the properties of the migration, for example, {@link #changePrimaryStorage()
- * where new changes should be stored}.
- *
- * <p>Core Gerrit code is mostly interested in one facet of the migration at a time (reading or
- * writing, say), but not all combinations of return values are supported or even make sense.
- *
- * <p>This class controls the state of the migration according to options in {@code gerrit.config}.
- * In general, any changes to these options should only be made by adventurous administrators, who
- * know what they're doing, on non-production data, for the purposes of testing the NoteDb
- * implementation.
- *
- * <p><strong>Note:</strong> Callers should not assume the values returned by {@code
- * NotesMigration}'s methods will not change in a running server.
+ * <p>This class is a stub and will be removed soon; NoteDb is the only mode.
*/
-public abstract class NotesMigration {
+@Singleton
+public class NotesMigration {
public static final String SECTION_NOTE_DB = "noteDb";
- public static final String READ = "read";
- public static final String WRITE = "write";
- public static final String DISABLE_REVIEW_DB = "disableReviewDb";
- public static final String PRIMARY_STORAGE = "primaryStorage";
- public static final String SEQUENCE = "sequence";
-
- public static class Module extends AbstractModule {
- @Override
- public void configure() {
- bind(MutableNotesMigration.class);
- bind(NotesMigration.class).to(MutableNotesMigration.class);
- }
- }
-
- @AutoValue
- abstract static class Snapshot {
- static Builder builder() {
- // Default values are defined as what we would read from an empty config.
- return create(new Config()).toBuilder();
- }
-
- static Snapshot create(Config cfg) {
- return new AutoValue_NotesMigration_Snapshot.Builder()
- .setWriteChanges(cfg.getBoolean(SECTION_NOTE_DB, CHANGES.key(), WRITE, false))
- .setReadChanges(cfg.getBoolean(SECTION_NOTE_DB, CHANGES.key(), READ, false))
- .setReadChangeSequence(cfg.getBoolean(SECTION_NOTE_DB, CHANGES.key(), SEQUENCE, false))
- .setChangePrimaryStorage(
- cfg.getEnum(
- SECTION_NOTE_DB, CHANGES.key(), PRIMARY_STORAGE, PrimaryStorage.REVIEW_DB))
- .setDisableChangeReviewDb(
- cfg.getBoolean(SECTION_NOTE_DB, CHANGES.key(), DISABLE_REVIEW_DB, false))
- .setFailOnLoadForTest(false) // Only set in tests, can't be set via config.
- .build();
- }
-
- abstract boolean writeChanges();
-
- abstract boolean readChanges();
-
- abstract boolean readChangeSequence();
-
- abstract PrimaryStorage changePrimaryStorage();
-
- abstract boolean disableChangeReviewDb();
-
- abstract boolean failOnLoadForTest();
-
- abstract Builder toBuilder();
-
- void setConfigValues(Config cfg) {
- cfg.setBoolean(SECTION_NOTE_DB, CHANGES.key(), WRITE, writeChanges());
- cfg.setBoolean(SECTION_NOTE_DB, CHANGES.key(), READ, readChanges());
- cfg.setBoolean(SECTION_NOTE_DB, CHANGES.key(), SEQUENCE, readChangeSequence());
- cfg.setEnum(SECTION_NOTE_DB, CHANGES.key(), PRIMARY_STORAGE, changePrimaryStorage());
- cfg.setBoolean(SECTION_NOTE_DB, CHANGES.key(), DISABLE_REVIEW_DB, disableChangeReviewDb());
- }
-
- @AutoValue.Builder
- abstract static class Builder {
- abstract Builder setWriteChanges(boolean writeChanges);
-
- abstract Builder setReadChanges(boolean readChanges);
-
- abstract Builder setReadChangeSequence(boolean readChangeSequence);
-
- abstract Builder setChangePrimaryStorage(PrimaryStorage changePrimaryStorage);
-
- abstract Builder setDisableChangeReviewDb(boolean disableChangeReviewDb);
-
- abstract Builder setFailOnLoadForTest(boolean failOnLoadForTest);
-
- abstract Snapshot autoBuild();
-
- Snapshot build() {
- Snapshot s = autoBuild();
- checkArgument(
- !(s.disableChangeReviewDb() && s.changePrimaryStorage() != PrimaryStorage.NOTE_DB),
- "cannot disable ReviewDb for changes if default change primary storage is ReviewDb");
- return s;
- }
- }
- }
-
- protected final AtomicReference<Snapshot> snapshot;
+ private static final String READ = "read";
+ private static final String WRITE = "write";
+ private static final String DISABLE_REVIEW_DB = "disableReviewDb";
+ private static final String PRIMARY_STORAGE = "primaryStorage";
+ private static final String SEQUENCE = "sequence";
/**
* Read changes from NoteDb.
@@ -149,100 +42,22 @@
* attempts to write will generate an error.
*/
public final boolean readChanges() {
- return snapshot.get().readChanges();
- }
-
- /**
- * Write changes to NoteDb.
- *
- * <p>This method is awkwardly named because you should be using either {@link
- * #commitChangeWrites()} or {@link #failChangeWrites()} instead.
- *
- * <p>Updates to change data are written to NoteDb refs, but ReviewDb is still the source of
- * truth. Change data will not be written unless the NoteDb refs are already up to date, and the
- * write path will attempt to rebuild the change if not.
- *
- * <p>If false, the behavior when attempting to write depends on {@code readChanges()}. If {@code
- * readChanges() = false}, writes to NoteDb are simply ignored; if {@code true}, any attempts to
- * write will generate an error.
- */
- public final boolean rawWriteChangesSetting() {
- return snapshot.get().writeChanges();
- }
-
- /**
- * Read sequential change ID numbers from NoteDb.
- *
- * <p>If true, change IDs are read from {@code refs/sequences/changes} in All-Projects. If false,
- * change IDs are read from ReviewDb's native sequences.
- */
- public final boolean readChangeSequence() {
- return snapshot.get().readChangeSequence();
- }
-
- /** @return default primary storage for new changes. */
- public final PrimaryStorage changePrimaryStorage() {
- return snapshot.get().changePrimaryStorage();
- }
-
- /**
- * Disable ReviewDb access for changes.
- *
- * <p>When set, ReviewDb operations involving the Changes table become no-ops. Lookups return no
- * results; updates do nothing, as does opening, committing, or rolling back a transaction on the
- * Changes table.
- */
- public final boolean disableChangeReviewDb() {
- return snapshot.get().disableChangeReviewDb();
- }
-
- /**
- * Whether to fail when reading any data from NoteDb.
- *
- * <p>Used in conjunction with {@link #readChanges()} for tests.
- */
- public boolean failOnLoadForTest() {
- return snapshot.get().failOnLoadForTest();
+ return true;
}
public final boolean commitChangeWrites() {
- // It may seem odd that readChanges() without writeChanges() means we should
- // attempt to commit writes. However, this method is used by callers to know
- // whether or not they should short-circuit and skip attempting to read or
- // write NoteDb refs.
- //
- // It is possible for commitChangeWrites() to return true and
- // failChangeWrites() to also return true, causing an error later in the
- // same codepath. This specific condition is used by the auto-rebuilding
- // path to rebuild a change and stage the results, but not commit them due
- // to failChangeWrites().
- return rawWriteChangesSetting() || readChanges();
- }
-
- public final boolean failChangeWrites() {
- return !rawWriteChangesSetting() && readChanges();
- }
-
- public final void setConfigValues(Config cfg) {
- snapshot.get().setConfigValues(cfg);
+ return true;
}
@Override
public final boolean equals(Object o) {
- return o instanceof NotesMigration
- && snapshot.get().equals(((NotesMigration) o).snapshot.get());
+ return o instanceof NotesMigration;
}
@Override
public final int hashCode() {
- return snapshot.get().hashCode();
+ return Objects.hash();
}
- protected NotesMigration(Snapshot snapshot) {
- this.snapshot = new AtomicReference<>(snapshot);
- }
-
- final Snapshot snapshot() {
- return snapshot.get();
- }
+ public NotesMigration() {}
}
diff --git a/java/com/google/gerrit/server/notedb/NotesMigrationState.java b/java/com/google/gerrit/server/notedb/NotesMigrationState.java
deleted file mode 100644
index c682aed..0000000
--- a/java/com/google/gerrit/server/notedb/NotesMigrationState.java
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright (C) 2017 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.server.notedb;
-
-import com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage;
-import com.google.gerrit.server.notedb.NotesMigration.Snapshot;
-import java.util.Optional;
-import java.util.stream.Stream;
-import org.eclipse.jgit.lib.Config;
-
-/**
- * Possible high-level states of the NoteDb migration for changes.
- *
- * <p>This class describes the series of states required to migrate a site from ReviewDb-only to
- * NoteDb-only. This process has several steps, and covers only a small subset of the theoretically
- * possible combinations of {@link NotesMigration} return values.
- *
- * <p>These states are ordered: a one-way migration from ReviewDb to NoteDb will pass through states
- * in the order in which they are defined.
- */
-public enum NotesMigrationState {
- REVIEW_DB(false, false, false, PrimaryStorage.REVIEW_DB, false),
-
- WRITE(false, true, false, PrimaryStorage.REVIEW_DB, false),
-
- READ_WRITE_NO_SEQUENCE(true, true, false, PrimaryStorage.REVIEW_DB, false),
-
- READ_WRITE_WITH_SEQUENCE_REVIEW_DB_PRIMARY(true, true, true, PrimaryStorage.REVIEW_DB, false),
-
- READ_WRITE_WITH_SEQUENCE_NOTE_DB_PRIMARY(true, true, true, PrimaryStorage.NOTE_DB, false),
-
- NOTE_DB(true, true, true, PrimaryStorage.NOTE_DB, true);
-
- public static final NotesMigrationState FINAL = NOTE_DB;
-
- public static Optional<NotesMigrationState> forConfig(Config cfg) {
- return forSnapshot(Snapshot.create(cfg));
- }
-
- public static Optional<NotesMigrationState> forNotesMigration(NotesMigration migration) {
- return forSnapshot(migration.snapshot());
- }
-
- private static Optional<NotesMigrationState> forSnapshot(Snapshot s) {
- return Stream.of(values()).filter(v -> v.snapshot.equals(s)).findFirst();
- }
-
- private final Snapshot snapshot;
-
- NotesMigrationState(
- // Arguments match abstract methods in NotesMigration.
- boolean readChanges,
- boolean rawWriteChangesSetting,
- boolean readChangeSequence,
- PrimaryStorage changePrimaryStorage,
- boolean disableChangeReviewDb) {
- this.snapshot =
- Snapshot.builder()
- .setReadChanges(readChanges)
- .setWriteChanges(rawWriteChangesSetting)
- .setReadChangeSequence(readChangeSequence)
- .setChangePrimaryStorage(changePrimaryStorage)
- .setDisableChangeReviewDb(disableChangeReviewDb)
- .build();
- }
-
- public void setConfigValues(Config cfg) {
- snapshot.setConfigValues(cfg);
- }
-
- public String toText() {
- Config cfg = new Config();
- setConfigValues(cfg);
- return cfg.toText();
- }
-
- Snapshot snapshot() {
- return snapshot;
- }
-}
diff --git a/java/com/google/gerrit/server/permissions/ChangeControl.java b/java/com/google/gerrit/server/permissions/ChangeControl.java
index f4e659e..b15854d 100644
--- a/java/com/google/gerrit/server/permissions/ChangeControl.java
+++ b/java/com/google/gerrit/server/permissions/ChangeControl.java
@@ -55,10 +55,9 @@
this.notesFactory = notesFactory;
}
- ChangeControl create(
- RefControl refControl, ReviewDb db, Project.NameKey project, Change.Id changeId)
+ ChangeControl create(RefControl refControl, Project.NameKey project, Change.Id changeId)
throws OrmException {
- return create(refControl, notesFactory.create(db, project, changeId));
+ return create(refControl, notesFactory.create(project, changeId));
}
ChangeControl create(RefControl refControl, ChangeNotes notes) {
diff --git a/java/com/google/gerrit/server/permissions/DefaultRefFilter.java b/java/com/google/gerrit/server/permissions/DefaultRefFilter.java
index 249c872..ea4073d 100644
--- a/java/com/google/gerrit/server/permissions/DefaultRefFilter.java
+++ b/java/com/google/gerrit/server/permissions/DefaultRefFilter.java
@@ -133,9 +133,10 @@
refs = addUsersSelfSymref(refs);
}
+ boolean hasReadOnRefsStar =
+ checkProjectPermission(permissionBackendForProject, ProjectPermission.READ);
if (skipFullRefEvaluationIfAllRefsAreVisible && !projectState.isAllUsers()) {
- if (projectState.statePermitsRead()
- && checkProjectPermission(permissionBackendForProject, ProjectPermission.READ)) {
+ if (projectState.statePermitsRead() && hasReadOnRefsStar) {
skipFilterCount.increment();
return refs;
} else if (projectControl.allRefsAreVisible(ImmutableSet.of(RefNames.REFS_CONFIG))) {
@@ -197,9 +198,22 @@
result.put(name, ref);
}
} else if (isTag(ref)) {
- // If its a tag, consider it later.
- if (ref.getObjectId() != null) {
- deferredTags.add(ref);
+ if (hasReadOnRefsStar) {
+ // The user has READ on refs/*. This is the broadest permission one can assign. There is
+ // no way to grant access to (specific) tags in Gerrit, so we have to assume that these
+ // users can see all tags because there could be tags that aren't reachable by any visible
+ // ref while the user can see all non-Gerrit refs. This matches Gerrit's historic
+ // behavior.
+ // This makes it so that these users could see commits that they can't see otherwise
+ // (e.g. a private change ref) if a tag was attached to it. Tags are meant to be used on
+ // the regular Git tree that users interact with, not on any of the Gerrit trees, so this
+ // is a negligible risk.
+ result.put(name, ref);
+ } else {
+ // If its a tag, consider it later.
+ if (ref.getObjectId() != null) {
+ deferredTags.add(ref);
+ }
}
} else if (name.startsWith(RefNames.REFS_SEQUENCES)) {
// Sequences are internal database implementation details.
diff --git a/java/com/google/gerrit/server/permissions/ProjectControl.java b/java/com/google/gerrit/server/permissions/ProjectControl.java
index 787bee4..445e577 100644
--- a/java/com/google/gerrit/server/permissions/ProjectControl.java
+++ b/java/com/google/gerrit/server/permissions/ProjectControl.java
@@ -27,7 +27,6 @@
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
-import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.account.GroupMembership;
import com.google.gerrit.server.config.GitReceivePackGroups;
@@ -98,9 +97,9 @@
return new ForProjectImpl();
}
- ChangeControl controlFor(ReviewDb db, Change change) throws OrmException {
+ ChangeControl controlFor(Change change) throws OrmException {
return changeControlFactory.create(
- controlForRef(change.getDest()), db, change.getProject(), change.getId());
+ controlForRef(change.getDest()), change.getProject(), change.getId());
}
ChangeControl controlFor(ChangeNotes notes) {
diff --git a/java/com/google/gerrit/server/permissions/RefControl.java b/java/com/google/gerrit/server/permissions/RefControl.java
index 83ea7f8..e445eb8 100644
--- a/java/com/google/gerrit/server/permissions/RefControl.java
+++ b/java/com/google/gerrit/server/permissions/RefControl.java
@@ -442,9 +442,7 @@
public ForChange change(ChangeData cd) {
try {
// TODO(hiesel) Force callers to call database() and use db instead of cd.db()
- return getProjectControl()
- .controlFor(cd.db(), cd.change())
- .asForChange(cd, Providers.of(cd.db()));
+ return getProjectControl().controlFor(cd.change()).asForChange(cd, Providers.of(cd.db()));
} catch (OrmException e) {
return FailedPermissionBackend.change("unavailable", e);
}
diff --git a/java/com/google/gerrit/server/query/change/ChangeData.java b/java/com/google/gerrit/server/query/change/ChangeData.java
index 4df953e..c12201f 100644
--- a/java/com/google/gerrit/server/query/change/ChangeData.java
+++ b/java/com/google/gerrit/server/query/change/ChangeData.java
@@ -139,7 +139,7 @@
if (missing.isEmpty()) {
return;
}
- for (ChangeNotes notes : first.notesFactory.create(first.db, missing.keySet())) {
+ for (ChangeNotes notes : first.notesFactory.create(missing.keySet())) {
missing.get(notes.getChangeId()).change = notes.getChange();
}
}
@@ -571,7 +571,7 @@
public Change reloadChange() throws OrmException {
try {
- notes = notesFactory.createChecked(db, project, legacyId);
+ notes = notesFactory.createChecked(project, legacyId);
} catch (NoSuchChangeException e) {
throw new OrmException("Unable to load change " + legacyId, e);
}
@@ -598,7 +598,7 @@
if (!lazyLoad) {
throw new OrmException("ChangeNotes not available, lazyLoad = false");
}
- notes = notesFactory.create(db, project(), legacyId);
+ notes = notesFactory.create(project(), legacyId);
}
return notes;
}
diff --git a/java/com/google/gerrit/server/query/change/ConflictKey.java b/java/com/google/gerrit/server/query/change/ConflictKey.java
index 42f5b13..01fdbfa 100644
--- a/java/com/google/gerrit/server/query/change/ConflictKey.java
+++ b/java/com/google/gerrit/server/query/change/ConflictKey.java
@@ -20,10 +20,10 @@
import com.google.common.base.Enums;
import com.google.common.collect.Ordering;
import com.google.gerrit.extensions.client.SubmitType;
+import com.google.gerrit.proto.Protos;
import com.google.gerrit.server.cache.proto.Cache.ConflictKeyProto;
import com.google.gerrit.server.cache.serialize.CacheSerializer;
-import com.google.gerrit.server.cache.serialize.ProtoCacheSerializers;
-import com.google.gerrit.server.cache.serialize.ProtoCacheSerializers.ObjectIdConverter;
+import com.google.gerrit.server.cache.serialize.ObjectIdConverter;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.ObjectId;
@@ -70,7 +70,7 @@
@Override
public byte[] serialize(ConflictKey object) {
ObjectIdConverter idConverter = ObjectIdConverter.create();
- return ProtoCacheSerializers.toByteArray(
+ return Protos.toByteArray(
ConflictKeyProto.newBuilder()
.setCommit(idConverter.toByteString(object.commit()))
.setOtherCommit(idConverter.toByteString(object.otherCommit()))
@@ -81,7 +81,7 @@
@Override
public ConflictKey deserialize(byte[] in) {
- ConflictKeyProto proto = ProtoCacheSerializers.parseUnchecked(ConflictKeyProto.parser(), in);
+ ConflictKeyProto proto = Protos.parseUnchecked(ConflictKeyProto.parser(), in);
ObjectIdConverter idConverter = ObjectIdConverter.create();
return create(
idConverter.fromByteString(proto.getCommit()),
diff --git a/java/com/google/gerrit/server/query/change/InternalChangeQuery.java b/java/com/google/gerrit/server/query/change/InternalChangeQuery.java
index 495d27c..23993ef 100644
--- a/java/com/google/gerrit/server/query/change/InternalChangeQuery.java
+++ b/java/com/google/gerrit/server/query/change/InternalChangeQuery.java
@@ -215,7 +215,6 @@
List<ChangeNotes> notes =
notesFactory.create(
- db,
branch.getParentKey(),
changeIds,
cn -> {
diff --git a/java/com/google/gerrit/server/quota/DefaultQuotaBackend.java b/java/com/google/gerrit/server/quota/DefaultQuotaBackend.java
index baa7677..c6e67ca 100644
--- a/java/com/google/gerrit/server/quota/DefaultQuotaBackend.java
+++ b/java/com/google/gerrit/server/quota/DefaultQuotaBackend.java
@@ -74,8 +74,12 @@
responses.add(enforcer.call(p -> p.dryRun(quotaGroup, requestContext, numTokens)));
}
} catch (RuntimeException e) {
- logger.atSevere().withCause(e).log("exception while enforcing quota");
- responses.add(QuotaResponse.error("failed to request quota tokens"));
+ // Roll back the quota request for all enforcers that deducted the quota. Rethrow the
+ // exception to adhere to the API contract.
+ if (deduct) {
+ refillAfterErrorOrException(enforcers, responses, quotaGroup, requestContext, numTokens);
+ }
+ throw e;
}
}
@@ -83,11 +87,7 @@
// Roll back the quota request for all enforcers that deducted the quota (= the request
// succeeded). Don't touch failed enforcers as the interface contract said that failed
// requests should not be deducted.
- for (int i = 0; i < responses.size(); i++) {
- if (responses.get(i).status().isOk()) {
- enforcers.get(i).run(p -> p.refill(quotaGroup, requestContext, numTokens));
- }
- }
+ refillAfterErrorOrException(enforcers, responses, quotaGroup, requestContext, numTokens);
}
logger.atFine().log(
@@ -100,6 +100,19 @@
return QuotaResponse.Aggregated.create(ImmutableList.copyOf(responses));
}
+ private static void refillAfterErrorOrException(
+ List<PluginSetEntryContext<QuotaEnforcer>> enforcers,
+ List<QuotaResponse> collectedResponses,
+ String quotaGroup,
+ QuotaRequestContext requestContext,
+ long numTokens) {
+ for (int i = 0; i < collectedResponses.size(); i++) {
+ if (collectedResponses.get(i).status().isOk()) {
+ enforcers.get(i).run(p -> p.refill(quotaGroup, requestContext, numTokens));
+ }
+ }
+ }
+
static class WithUser extends WithResource implements QuotaBackend.WithUser {
WithUser(PluginSetContext<QuotaEnforcer> quotaEnforcers, CurrentUser user) {
super(quotaEnforcers, QuotaRequestContext.builder().user(user).build());
diff --git a/java/com/google/gerrit/server/restapi/account/DeleteDraftComments.java b/java/com/google/gerrit/server/restapi/account/DeleteDraftComments.java
index 16ab812..96b9519 100644
--- a/java/com/google/gerrit/server/restapi/account/DeleteDraftComments.java
+++ b/java/com/google/gerrit/server/restapi/account/DeleteDraftComments.java
@@ -151,7 +151,7 @@
// Currently there's no way to let some updates succeed even if others fail. Even if there were,
// all updates from this operation only happen in All-Users and thus are fully atomic, so
// allowing partial failure would have little value.
- batchUpdateFactory.execute(updates.values(), BatchUpdateListener.NONE, false);
+ BatchUpdate.execute(updates.values(), BatchUpdateListener.NONE, false);
return ops.stream().map(Op::getResult).filter(Objects::nonNull).collect(toImmutableList());
}
diff --git a/java/com/google/gerrit/server/restapi/change/CherryPickChange.java b/java/com/google/gerrit/server/restapi/change/CherryPickChange.java
index c7a8a96..4c34e62 100644
--- a/java/com/google/gerrit/server/restapi/change/CherryPickChange.java
+++ b/java/com/google/gerrit/server/restapi/change/CherryPickChange.java
@@ -360,8 +360,7 @@
.setAccountsToNotify(notifyUtil.resolveAccounts(input.notifyDetails));
if (input.keepReviewers && sourceChange != null) {
ReviewerSet reviewerSet =
- approvalsUtil.getReviewers(
- changeNotesFactory.createChecked(dbProvider.get(), sourceChange));
+ approvalsUtil.getReviewers(changeNotesFactory.createChecked(sourceChange));
Set<Account.Id> reviewers =
new HashSet<>(reviewerSet.byState(ReviewerStateInternal.REVIEWER));
reviewers.add(sourceChange.getOwner());
diff --git a/java/com/google/gerrit/server/restapi/change/Submit.java b/java/com/google/gerrit/server/restapi/change/Submit.java
index d426df3..e46085d 100644
--- a/java/com/google/gerrit/server/restapi/change/Submit.java
+++ b/java/com/google/gerrit/server/restapi/change/Submit.java
@@ -215,8 +215,7 @@
ReviewDb db = dbProvider.get();
op.merge(db, change, submitter, true, input, false);
try {
- change =
- changeNotesFactory.createChecked(db, change.getProject(), change.getId()).getChange();
+ change = changeNotesFactory.createChecked(change.getProject(), change.getId()).getChange();
} catch (NoSuchChangeException e) {
throw new ResourceConflictException("change is deleted");
}
diff --git a/java/com/google/gerrit/server/restapi/config/GetServerInfo.java b/java/com/google/gerrit/server/restapi/config/GetServerInfo.java
index 98ef220..c03c4c5 100644
--- a/java/com/google/gerrit/server/restapi/config/GetServerInfo.java
+++ b/java/com/google/gerrit/server/restapi/config/GetServerInfo.java
@@ -53,7 +53,6 @@
import com.google.gerrit.server.documentation.QueryDocumentationExecutor;
import com.google.gerrit.server.index.change.ChangeField;
import com.google.gerrit.server.index.change.ChangeIndexCollection;
-import com.google.gerrit.server.notedb.NotesMigration;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.plugincontext.PluginItemContext;
import com.google.gerrit.server.plugincontext.PluginMapContext;
@@ -91,7 +90,6 @@
private final PluginItemContext<AvatarProvider> avatar;
private final boolean enableSignedPush;
private final QueryDocumentationExecutor docSearcher;
- private final NotesMigration migration;
private final ProjectCache projectCache;
private final AgreementJson agreementJson;
private final ChangeIndexCollection indexes;
@@ -114,7 +112,6 @@
PluginItemContext<AvatarProvider> avatar,
@EnableSignedPush boolean enableSignedPush,
QueryDocumentationExecutor docSearcher,
- NotesMigration migration,
ProjectCache projectCache,
AgreementJson agreementJson,
ChangeIndexCollection indexes,
@@ -134,7 +131,6 @@
this.avatar = avatar;
this.enableSignedPush = enableSignedPush;
this.docSearcher = docSearcher;
- this.migration = migration;
this.projectCache = projectCache;
this.agreementJson = agreementJson;
this.indexes = indexes;
@@ -149,7 +145,7 @@
info.change = getChangeInfo();
info.download = getDownloadInfo();
info.gerrit = getGerritInfo();
- info.noteDbEnabled = toBoolean(isNoteDbEnabled());
+ info.noteDbEnabled = true;
info.plugin = getPluginInfo();
info.defaultTheme = getDefaultTheme();
info.sshd = getSshdInfo();
@@ -313,10 +309,6 @@
return CharMatcher.is('/').trimTrailingFrom(docUrl) + '/';
}
- private boolean isNoteDbEnabled() {
- return migration.readChanges();
- }
-
private PluginConfigInfo getPluginInfo() {
PluginConfigInfo info = new PluginConfigInfo();
info.hasAvatars = toBoolean(avatar.hasImplementation());
diff --git a/java/com/google/gerrit/server/schema/AllProjectsCreator.java b/java/com/google/gerrit/server/schema/AllProjectsCreator.java
index 14da9eb..78324fa 100644
--- a/java/com/google/gerrit/server/schema/AllProjectsCreator.java
+++ b/java/com/google/gerrit/server/schema/AllProjectsCreator.java
@@ -264,8 +264,7 @@
}
private void initSequences(Repository git, BatchRefUpdate bru) throws IOException {
- if (notesMigration.readChangeSequence()
- && git.exactRef(REFS_SEQUENCES + Sequences.NAME_CHANGES) == null) {
+ if (git.exactRef(REFS_SEQUENCES + Sequences.NAME_CHANGES) == null) {
// Can't easily reuse the inserter from MetaDataUpdate, but this shouldn't slow down site
// initialization unduly.
try (ObjectInserter ins = git.newObjectInserter()) {
diff --git a/java/com/google/gerrit/server/schema/NoteDbSchemaUpdater.java b/java/com/google/gerrit/server/schema/NoteDbSchemaUpdater.java
index 602b639..73deb3e 100644
--- a/java/com/google/gerrit/server/schema/NoteDbSchemaUpdater.java
+++ b/java/com/google/gerrit/server/schema/NoteDbSchemaUpdater.java
@@ -15,12 +15,6 @@
package com.google.gerrit.server.schema;
import static com.google.common.collect.ImmutableList.toImmutableList;
-import static com.google.gerrit.server.notedb.NoteDbTable.CHANGES;
-import static com.google.gerrit.server.notedb.NotesMigration.DISABLE_REVIEW_DB;
-import static com.google.gerrit.server.notedb.NotesMigration.PRIMARY_STORAGE;
-import static com.google.gerrit.server.notedb.NotesMigration.READ;
-import static com.google.gerrit.server.notedb.NotesMigration.SECTION_NOTE_DB;
-import static com.google.gerrit.server.notedb.NotesMigration.WRITE;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
@@ -144,11 +138,11 @@
// * Completed the change migration to NoteDB.
// * Ran schema upgrades from a 2.16 final release.
- if (!cfg.getBoolean(SECTION_NOTE_DB, CHANGES.key(), WRITE, false)
- || !cfg.getBoolean(SECTION_NOTE_DB, CHANGES.key(), READ, false)
- || cfg.getEnum(SECTION_NOTE_DB, CHANGES.key(), PRIMARY_STORAGE, PrimaryStorage.REVIEW_DB)
+ if (!cfg.getBoolean("noteDb", "changes", "write", false)
+ || !cfg.getBoolean("noteDb", "changes", "read", false)
+ || cfg.getEnum("noteDb", "changes", "primaryStorage", PrimaryStorage.REVIEW_DB)
!= PrimaryStorage.NOTE_DB
- || !cfg.getBoolean(SECTION_NOTE_DB, CHANGES.key(), DISABLE_REVIEW_DB, false)) {
+ || !cfg.getBoolean("noteDb", "changes", "disableReviewDb", false)) {
throw new OrmException(
"You appear to be upgrading from a 2.x site, but the NoteDb change migration was"
+ " not completed. See documentation:\n"
diff --git a/java/com/google/gerrit/server/schema/NotesMigrationSchemaFactory.java b/java/com/google/gerrit/server/schema/NotesMigrationSchemaFactory.java
index c533619..63b3eaa 100644
--- a/java/com/google/gerrit/server/schema/NotesMigrationSchemaFactory.java
+++ b/java/com/google/gerrit/server/schema/NotesMigrationSchemaFactory.java
@@ -14,8 +14,6 @@
package com.google.gerrit.server.schema;
-import static com.google.common.base.Preconditions.checkState;
-
import com.google.gerrit.reviewdb.server.DisallowedReviewDb;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.notedb.NotesMigration;
@@ -60,8 +58,6 @@
// do nothing. This implementation is not a public class and callers couldn't do anything
// useful with it even if it were.
- // First create the underlying stub.
- checkState(migration.readChanges() && migration.disableChangeReviewDb());
// Disable writes to change tables in ReviewDb (ReviewDb access for changes are No-Ops); all
// other table accesses throw runtime exceptions.
ReviewDb db = new NoChangesReviewDb();
diff --git a/java/com/google/gerrit/server/submit/MergeOp.java b/java/com/google/gerrit/server/submit/MergeOp.java
index 81e2661..13affc3 100644
--- a/java/com/google/gerrit/server/submit/MergeOp.java
+++ b/java/com/google/gerrit/server/submit/MergeOp.java
@@ -607,7 +607,7 @@
SubmoduleOp submoduleOp = subOpFactory.create(branches, orm);
List<SubmitStrategy> strategies = getSubmitStrategies(toSubmit, submoduleOp, dryrun);
this.allProjects = submoduleOp.getProjectsInOrder();
- batchUpdateFactory.execute(
+ BatchUpdate.execute(
orm.batchUpdates(allProjects),
new SubmitStrategyListener(submitInput, strategies, commitStatus),
dryrun);
diff --git a/java/com/google/gerrit/server/submit/SubmoduleOp.java b/java/com/google/gerrit/server/submit/SubmoduleOp.java
index 50be62a..3fefed3 100644
--- a/java/com/google/gerrit/server/submit/SubmoduleOp.java
+++ b/java/com/google/gerrit/server/submit/SubmoduleOp.java
@@ -101,39 +101,29 @@
private final Provider<PersonIdent> serverIdent;
private final Config cfg;
private final ProjectCache projectCache;
- private final BatchUpdate.Factory batchUpdateFactory;
@Inject
Factory(
GitModules.Factory gitmodulesFactory,
@GerritPersonIdent Provider<PersonIdent> serverIdent,
@GerritServerConfig Config cfg,
- ProjectCache projectCache,
- BatchUpdate.Factory batchUpdateFactory) {
+ ProjectCache projectCache) {
this.gitmodulesFactory = gitmodulesFactory;
this.serverIdent = serverIdent;
this.cfg = cfg;
this.projectCache = projectCache;
- this.batchUpdateFactory = batchUpdateFactory;
}
public SubmoduleOp create(Set<Branch.NameKey> updatedBranches, MergeOpRepoManager orm)
throws SubmoduleException {
return new SubmoduleOp(
- gitmodulesFactory,
- serverIdent.get(),
- cfg,
- projectCache,
- batchUpdateFactory,
- updatedBranches,
- orm);
+ gitmodulesFactory, serverIdent.get(), cfg, projectCache, updatedBranches, orm);
}
}
private final GitModules.Factory gitmodulesFactory;
private final PersonIdent myIdent;
private final ProjectCache projectCache;
- private final BatchUpdate.Factory batchUpdateFactory;
private final VerboseSuperprojectUpdate verboseSuperProject;
private final boolean enableSuperProjectSubscriptions;
private final long maxCombinedCommitMessageSize;
@@ -173,14 +163,12 @@
PersonIdent myIdent,
Config cfg,
ProjectCache projectCache,
- BatchUpdate.Factory batchUpdateFactory,
Set<Branch.NameKey> updatedBranches,
MergeOpRepoManager orm)
throws SubmoduleException {
this.gitmodulesFactory = gitmodulesFactory;
this.myIdent = myIdent;
this.projectCache = projectCache;
- this.batchUpdateFactory = batchUpdateFactory;
this.verboseSuperProject =
cfg.getEnum("submodule", null, "verboseSuperprojectUpdate", VerboseSuperprojectUpdate.TRUE);
this.enableSuperProjectSubscriptions =
@@ -420,7 +408,7 @@
}
}
}
- batchUpdateFactory.execute(orm.batchUpdates(superProjects), BatchUpdateListener.NONE, false);
+ BatchUpdate.execute(orm.batchUpdates(superProjects), BatchUpdateListener.NONE, false);
} catch (RestApiException | UpdateException | IOException | NoSuchProjectException e) {
throw new SubmoduleException("Cannot update gitlinks", e);
}
diff --git a/java/com/google/gerrit/server/update/BatchUpdate.java b/java/com/google/gerrit/server/update/BatchUpdate.java
index a768888..2c1824c 100644
--- a/java/com/google/gerrit/server/update/BatchUpdate.java
+++ b/java/com/google/gerrit/server/update/BatchUpdate.java
@@ -17,7 +17,10 @@
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableMultiset.toImmutableMultiset;
+import static com.google.common.flogger.LazyArgs.lazy;
+import static java.util.Comparator.comparing;
import static java.util.Objects.requireNonNull;
+import static java.util.stream.Collectors.toSet;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
@@ -32,20 +35,28 @@
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CurrentUser;
+import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.account.AccountState;
+import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.validators.OnSubmitValidators;
+import com.google.gerrit.server.index.change.ChangeIndexer;
import com.google.gerrit.server.logging.RequestId;
+import com.google.gerrit.server.notedb.ChangeNotes;
+import com.google.gerrit.server.notedb.ChangeUpdate;
+import com.google.gerrit.server.notedb.NoteDbUpdateManager;
import com.google.gerrit.server.project.InvalidChangeOperationException;
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.project.NoSuchProjectException;
import com.google.gerrit.server.project.NoSuchRefException;
+import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Module;
-import com.google.inject.Singleton;
+import com.google.inject.assistedinject.Assisted;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.ArrayList;
@@ -55,6 +66,7 @@
import java.util.Map;
import java.util.Optional;
import java.util.TimeZone;
+import java.util.TreeMap;
import org.eclipse.jgit.lib.BatchRefUpdate;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.PersonIdent;
@@ -64,81 +76,145 @@
import org.eclipse.jgit.transport.ReceiveCommand;
/**
- * Helper for a set of updates that should be applied for a site.
+ * Helper for a set of change updates that should be applied to the NoteDb database.
*
* <p>An update operation can be divided into three phases:
*
* <ol>
* <li>Git reference updates
- * <li>Database updates
+ * <li>Review metadata updates
* <li>Post-update steps
* <li>
* </ol>
*
* A single conceptual operation, such as a REST API call or a merge operation, may make multiple
* changes at each step, which all need to be serialized relative to each other. Moreover, for
- * consistency, <em>all</em> git ref updates must be performed before <em>any</em> database updates,
- * since database updates might refer to newly-created patch set refs. And all post-update steps,
- * such as hooks, should run only after all storage mutations have completed.
+ * consistency, the git ref updates must be visible to the review metadata updates, since for
+ * example the metadata might refer to newly-created patch set refs. In NoteDb, this is accomplished
+ * by combining these two phases into a single {@link BatchRefUpdate}.
*
- * <p>Depending on the backend used, each step might support batching, for example in a {@code
- * BatchRefUpdate} or one or more database transactions. All operations in one phase must complete
- * successfully before proceeding to the next phase.
+ * <p>Similarly, all post-update steps, such as sending email, must run only after all storage
+ * mutations have completed.
*/
-public abstract class BatchUpdate implements AutoCloseable {
+public class BatchUpdate implements AutoCloseable {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
public static Module module() {
return new FactoryModule() {
@Override
public void configure() {
- factory(NoteDbBatchUpdate.AssistedFactory.class);
+ factory(BatchUpdate.Factory.class);
}
};
}
- @Singleton
- public static class Factory {
- private final NoteDbBatchUpdate.AssistedFactory noteDbBatchUpdateFactory;
+ // TODO(dborowitz): Make this package-private to force all callers to use RetryHelper.
+ public interface Factory {
+ BatchUpdate create(ReviewDb db, Project.NameKey project, CurrentUser user, Timestamp when);
+ }
- // TODO(dborowitz): Make this non-injectable to force all callers to use RetryHelper.
- @Inject
- Factory(NoteDbBatchUpdate.AssistedFactory noteDbBatchUpdateFactory) {
- this.noteDbBatchUpdateFactory = noteDbBatchUpdateFactory;
+ public static void execute(
+ Collection<BatchUpdate> updates, BatchUpdateListener listener, boolean dryrun)
+ throws UpdateException, RestApiException {
+ requireNonNull(listener);
+ if (updates.isEmpty()) {
+ return;
}
- public BatchUpdate create(
- ReviewDb db, Project.NameKey project, CurrentUser user, Timestamp when) {
- return noteDbBatchUpdateFactory.create(db, project, user, when);
- }
+ checkDifferentProject(updates);
- @SuppressWarnings({"rawtypes", "unchecked"})
- public void execute(
- Collection<BatchUpdate> updates, BatchUpdateListener listener, boolean dryRun)
- throws UpdateException, RestApiException {
- requireNonNull(listener);
- checkDifferentProject(updates);
- // It's safe to downcast all members of the input collection in this case, because the only
- // way a caller could have gotten any BatchUpdates in the first place is to call the create
- // method above, which always returns instances of the type we expect. Just to be safe,
- // copy them into an ImmutableList so there is no chance the callee can pollute the input
- // collection.
- ImmutableList<NoteDbBatchUpdate> noteDbUpdates =
- (ImmutableList) ImmutableList.copyOf(updates);
- NoteDbBatchUpdate.execute(noteDbUpdates, listener, dryRun);
- }
+ try {
+ @SuppressWarnings("deprecation")
+ List<com.google.common.util.concurrent.CheckedFuture<?, IOException>> indexFutures =
+ new ArrayList<>();
+ List<ChangesHandle> handles = new ArrayList<>(updates.size());
+ Order order = getOrder(updates, listener);
+ try {
+ switch (order) {
+ case REPO_BEFORE_DB:
+ for (BatchUpdate u : updates) {
+ u.executeUpdateRepo();
+ }
+ listener.afterUpdateRepos();
+ for (BatchUpdate u : updates) {
+ handles.add(u.executeChangeOps(dryrun));
+ }
+ for (ChangesHandle h : handles) {
+ h.execute();
+ indexFutures.addAll(h.startIndexFutures());
+ }
+ listener.afterUpdateRefs();
+ listener.afterUpdateChanges();
+ break;
- private static void checkDifferentProject(Collection<BatchUpdate> updates) {
- Multiset<Project.NameKey> projectCounts =
- updates.stream().map(u -> u.project).collect(toImmutableMultiset());
- checkArgument(
- projectCounts.entrySet().size() == updates.size(),
- "updates must all be for different projects, got: %s",
- projectCounts);
+ case DB_BEFORE_REPO:
+ // Call updateChange for each op before updateRepo, but defer executing the
+ // NoteDbUpdateManager until after calling updateRepo. They share an inserter and
+ // BatchRefUpdate, so it will all execute as a single batch. But we have to let
+ // NoteDbUpdateManager actually execute the update, since it has to interleave it
+ // properly with All-Users updates.
+ //
+ // TODO(dborowitz): This may still result in multiple updates to All-Users, but that's
+ // currently not a big deal because multi-change batches generally aren't affecting
+ // drafts anyway.
+ for (BatchUpdate u : updates) {
+ handles.add(u.executeChangeOps(dryrun));
+ }
+ for (BatchUpdate u : updates) {
+ u.executeUpdateRepo();
+ }
+ for (ChangesHandle h : handles) {
+ // TODO(dborowitz): This isn't quite good enough: in theory updateRepo may want to
+ // see the results of change meta commands, but they aren't actually added to the
+ // BatchUpdate until the body of execute. To fix this, execute needs to be split up
+ // into a method that returns a BatchRefUpdate before execution. Not a big deal at the
+ // moment, because this order is only used for deleting changes, and those updateRepo
+ // implementations definitely don't need to observe the updated change meta refs.
+ h.execute();
+ indexFutures.addAll(h.startIndexFutures());
+ }
+ break;
+ default:
+ throw new IllegalStateException("invalid execution order: " + order);
+ }
+ } finally {
+ for (ChangesHandle h : handles) {
+ h.close();
+ }
+ }
+
+ ChangeIndexer.allAsList(indexFutures).get();
+
+ // Fire ref update events only after all mutations are finished, since callers may assume a
+ // patch set ref being created means the change was created, or a branch advancing meaning
+ // some changes were closed.
+ updates
+ .stream()
+ .filter(u -> u.batchRefUpdate != null)
+ .forEach(
+ u -> u.gitRefUpdated.fire(u.project, u.batchRefUpdate, u.getAccount().orElse(null)));
+
+ if (!dryrun) {
+ for (BatchUpdate u : updates) {
+ u.executePostOps();
+ }
+ }
+ } catch (Exception e) {
+ wrapAndThrowException(e);
}
}
- static Order getOrder(Collection<? extends BatchUpdate> updates, BatchUpdateListener listener) {
+ private static void checkDifferentProject(Collection<BatchUpdate> updates) {
+ Multiset<Project.NameKey> projectCounts =
+ updates.stream().map(u -> u.project).collect(toImmutableMultiset());
+ checkArgument(
+ projectCounts.entrySet().size() == updates.size(),
+ "updates must all be for different projects, got: %s",
+ projectCounts);
+ }
+
+ private static Order getOrder(
+ Collection<? extends BatchUpdate> updates, BatchUpdateListener listener) {
Order o = null;
for (BatchUpdate u : updates) {
if (o == null) {
@@ -156,7 +232,7 @@
return o;
}
- static void wrapAndThrowException(Exception e) throws UpdateException, RestApiException {
+ private static void wrapAndThrowException(Exception e) throws UpdateException, RestApiException {
Throwables.throwIfUnchecked(e);
// Propagate REST API exceptions thrown by operations; they commonly throw exceptions like
@@ -178,32 +254,155 @@
throw new UpdateException(e);
}
- protected GitRepositoryManager repoManager;
+ class ContextImpl implements Context {
+ @Override
+ public RepoView getRepoView() throws IOException {
+ return BatchUpdate.this.getRepoView();
+ }
- protected final Project.NameKey project;
- protected final CurrentUser user;
- protected final Timestamp when;
- protected final TimeZone tz;
+ @Override
+ public RevWalk getRevWalk() throws IOException {
+ return getRepoView().getRevWalk();
+ }
- protected final ListMultimap<Change.Id, BatchUpdateOp> ops =
+ @Override
+ public Project.NameKey getProject() {
+ return project;
+ }
+
+ @Override
+ public Timestamp getWhen() {
+ return when;
+ }
+
+ @Override
+ public TimeZone getTimeZone() {
+ return tz;
+ }
+
+ @Override
+ public ReviewDb getDb() {
+ return db;
+ }
+
+ @Override
+ public CurrentUser getUser() {
+ return user;
+ }
+
+ @Override
+ public Order getOrder() {
+ return order;
+ }
+ }
+
+ private class RepoContextImpl extends ContextImpl implements RepoContext {
+ @Override
+ public ObjectInserter getInserter() throws IOException {
+ return getRepoView().getInserterWrapper();
+ }
+
+ @Override
+ public void addRefUpdate(ReceiveCommand cmd) throws IOException {
+ getRepoView().getCommands().add(cmd);
+ }
+ }
+
+ private class ChangeContextImpl extends ContextImpl implements ChangeContext {
+ private final ChangeNotes notes;
+ private final Map<PatchSet.Id, ChangeUpdate> updates;
+
+ private boolean deleted;
+
+ ChangeContextImpl(ChangeNotes notes) {
+ this.notes = requireNonNull(notes);
+ updates = new TreeMap<>(comparing(PatchSet.Id::get));
+ }
+
+ @Override
+ public ChangeUpdate getUpdate(PatchSet.Id psId) {
+ ChangeUpdate u = updates.get(psId);
+ if (u == null) {
+ u = changeUpdateFactory.create(notes, user, when);
+ if (newChanges.containsKey(notes.getChangeId())) {
+ u.setAllowWriteToNewRef(true);
+ }
+ u.setPatchSetId(psId);
+ updates.put(psId, u);
+ }
+ return u;
+ }
+
+ @Override
+ public ChangeNotes getNotes() {
+ return notes;
+ }
+
+ @Override
+ public void dontBumpLastUpdatedOn() {
+ // Do nothing; NoteDb effectively updates timestamp if and only if a commit was written to the
+ // change meta ref.
+ }
+
+ @Override
+ public void deleteChange() {
+ deleted = true;
+ }
+ }
+
+ /** Per-change result status from {@link #executeChangeOps}. */
+ private enum ChangeResult {
+ SKIPPED,
+ UPSERTED,
+ DELETED;
+ }
+
+ private GitRepositoryManager repoManager;
+
+ private final ChangeNotes.Factory changeNotesFactory;
+ private final ChangeUpdate.Factory changeUpdateFactory;
+ private final NoteDbUpdateManager.Factory updateManagerFactory;
+ private final ChangeIndexer indexer;
+ private final GitReferenceUpdated gitRefUpdated;
+
+ private final ReviewDb db;
+ private final Project.NameKey project;
+ private final CurrentUser user;
+ private final Timestamp when;
+ private final TimeZone tz;
+
+ private final ListMultimap<Change.Id, BatchUpdateOp> ops =
MultimapBuilder.linkedHashKeys().arrayListValues().build();
- protected final Map<Change.Id, Change> newChanges = new HashMap<>();
- protected final List<RepoOnlyOp> repoOnlyOps = new ArrayList<>();
+ private final Map<Change.Id, Change> newChanges = new HashMap<>();
+ private final List<RepoOnlyOp> repoOnlyOps = new ArrayList<>();
- protected RepoView repoView;
- protected BatchRefUpdate batchRefUpdate;
- protected Order order;
- protected OnSubmitValidators onSubmitValidators;
- protected PushCertificate pushCert;
- protected String refLogMessage;
+ private RepoView repoView;
+ private BatchRefUpdate batchRefUpdate;
+ private Order order;
+ private OnSubmitValidators onSubmitValidators;
+ private PushCertificate pushCert;
+ private String refLogMessage;
- protected BatchUpdate(
+ @Inject
+ BatchUpdate(
GitRepositoryManager repoManager,
- PersonIdent serverIdent,
- Project.NameKey project,
- CurrentUser user,
- Timestamp when) {
+ @GerritPersonIdent PersonIdent serverIdent,
+ ChangeNotes.Factory changeNotesFactory,
+ ChangeUpdate.Factory changeUpdateFactory,
+ NoteDbUpdateManager.Factory updateManagerFactory,
+ ChangeIndexer indexer,
+ GitReferenceUpdated gitRefUpdated,
+ @Assisted ReviewDb db,
+ @Assisted Project.NameKey project,
+ @Assisted CurrentUser user,
+ @Assisted Timestamp when) {
this.repoManager = repoManager;
+ this.changeNotesFactory = changeNotesFactory;
+ this.changeUpdateFactory = changeUpdateFactory;
+ this.updateManagerFactory = updateManagerFactory;
+ this.indexer = indexer;
+ this.gitRefUpdated = gitRefUpdated;
+ this.db = db;
this.project = project;
this.user = user;
this.when = when;
@@ -218,15 +417,14 @@
}
}
- public abstract void execute(BatchUpdateListener listener)
- throws UpdateException, RestApiException;
+ public void execute(BatchUpdateListener listener) throws UpdateException, RestApiException {
+ execute(ImmutableList.of(this), listener, false);
+ }
public void execute() throws UpdateException, RestApiException {
execute(BatchUpdateListener.NONE);
}
- protected abstract Context newContext();
-
public BatchUpdate setRepository(Repository repo, RevWalk revWalk, ObjectInserter inserter) {
checkState(this.repoView == null, "repo already set");
repoView = new RepoView(repo, revWalk, inserter);
@@ -257,32 +455,23 @@
return this;
}
- protected void initRepository() throws IOException {
+ private void initRepository() throws IOException {
if (repoView == null) {
repoView = new RepoView(repoManager, project);
}
}
- protected RepoView getRepoView() throws IOException {
+ private RepoView getRepoView() throws IOException {
initRepository();
return repoView;
}
- protected CurrentUser getUser() {
- return user;
- }
-
- protected Optional<AccountState> getAccount() {
+ private Optional<AccountState> getAccount() {
return user.isIdentifiedUser()
? Optional.of(user.asIdentifiedUser().state())
: Optional.empty();
}
- protected RevWalk getRevWalk() throws IOException {
- initRepository();
- return repoView.getRevWalk();
- }
-
public Map<String, ReceiveCommand> getRefUpdates() {
return repoView != null ? repoView.getCommands().getCommands() : ImmutableMap.of();
}
@@ -301,7 +490,7 @@
}
public BatchUpdate insertChange(InsertChangeOp op) throws IOException {
- Context ctx = newContext();
+ Context ctx = new ContextImpl();
Change c = op.createChange(ctx);
checkArgument(
!newChanges.containsKey(c.getId()), "only one op allowed to create change %s", c.getId());
@@ -310,16 +499,165 @@
return this;
}
- protected static void logDebug(String msg, Throwable t) {
- // Only log if there is a requestId assigned, since those are the
- // expensive/complicated requests like MergeOp. Doing it every time would be
- // noisy.
- if (RequestId.isSet()) {
- logger.atFine().withCause(t).log("%s", msg);
+ private void executeUpdateRepo() throws UpdateException, RestApiException {
+ try {
+ logDebug("Executing updateRepo on %d ops", ops.size());
+ RepoContextImpl ctx = new RepoContextImpl();
+ for (BatchUpdateOp op : ops.values()) {
+ op.updateRepo(ctx);
+ }
+
+ logDebug("Executing updateRepo on %d RepoOnlyOps", repoOnlyOps.size());
+ for (RepoOnlyOp op : repoOnlyOps) {
+ op.updateRepo(ctx);
+ }
+
+ if (onSubmitValidators != null && !getRefUpdates().isEmpty()) {
+ // Validation of refs has to take place here and not at the beginning of executeRefUpdates.
+ // Otherwise, failing validation in a second BatchUpdate object will happen *after* the
+ // first update's executeRefUpdates has finished, hence after first repo's refs have been
+ // updated, which is too late.
+ onSubmitValidators.validate(
+ project, ctx.getRevWalk().getObjectReader(), repoView.getCommands());
+ }
+ } catch (Exception e) {
+ Throwables.throwIfInstanceOf(e, RestApiException.class);
+ throw new UpdateException(e);
}
}
- protected static void logDebug(String msg) {
+ private class ChangesHandle implements AutoCloseable {
+ private final NoteDbUpdateManager manager;
+ private final boolean dryrun;
+ private final Map<Change.Id, ChangeResult> results;
+
+ ChangesHandle(NoteDbUpdateManager manager, boolean dryrun) {
+ this.manager = manager;
+ this.dryrun = dryrun;
+ results = new HashMap<>();
+ }
+
+ @Override
+ public void close() {
+ manager.close();
+ }
+
+ void setResult(Change.Id id, ChangeResult result) {
+ ChangeResult old = results.putIfAbsent(id, result);
+ checkArgument(old == null, "result for change %s already set: %s", id, old);
+ }
+
+ void execute() throws OrmException, IOException {
+ BatchUpdate.this.batchRefUpdate = manager.execute(dryrun);
+ }
+
+ @SuppressWarnings("deprecation")
+ List<com.google.common.util.concurrent.CheckedFuture<?, IOException>> startIndexFutures() {
+ if (dryrun) {
+ return ImmutableList.of();
+ }
+ logDebug("Reindexing %d changes", results.size());
+ List<com.google.common.util.concurrent.CheckedFuture<?, IOException>> indexFutures =
+ new ArrayList<>(results.size());
+ for (Map.Entry<Change.Id, ChangeResult> e : results.entrySet()) {
+ Change.Id id = e.getKey();
+ switch (e.getValue()) {
+ case UPSERTED:
+ indexFutures.add(indexer.indexAsync(project, id));
+ break;
+ case DELETED:
+ indexFutures.add(indexer.deleteAsync(id));
+ break;
+ case SKIPPED:
+ break;
+ default:
+ throw new IllegalStateException("unexpected result: " + e.getValue());
+ }
+ }
+ return indexFutures;
+ }
+ }
+
+ private ChangesHandle executeChangeOps(boolean dryrun) throws Exception {
+ logDebug("Executing change ops");
+ initRepository();
+ Repository repo = repoView.getRepository();
+ checkState(
+ repo.getRefDatabase().performsAtomicTransactions(),
+ "cannot use NoteDb with a repository that does not support atomic batch ref updates: %s",
+ repo);
+
+ ChangesHandle handle =
+ new ChangesHandle(
+ updateManagerFactory
+ .create(project)
+ .setChangeRepo(
+ repo, repoView.getRevWalk(), repoView.getInserter(), repoView.getCommands()),
+ dryrun);
+ if (user.isIdentifiedUser()) {
+ handle.manager.setRefLogIdent(user.asIdentifiedUser().newRefLogIdent(when, tz));
+ }
+ handle.manager.setRefLogMessage(refLogMessage);
+ handle.manager.setPushCertificate(pushCert);
+ for (Map.Entry<Change.Id, Collection<BatchUpdateOp>> e : ops.asMap().entrySet()) {
+ Change.Id id = e.getKey();
+ ChangeContextImpl ctx = newChangeContext(id);
+ boolean dirty = false;
+ logDebug(
+ "Applying %d ops for change %s: %s",
+ e.getValue().size(),
+ id,
+ lazy(() -> e.getValue().stream().map(op -> op.getClass().getName()).collect(toSet())));
+ for (BatchUpdateOp op : e.getValue()) {
+ dirty |= op.updateChange(ctx);
+ }
+ if (!dirty) {
+ logDebug("No ops reported dirty, short-circuiting");
+ handle.setResult(id, ChangeResult.SKIPPED);
+ continue;
+ }
+ for (ChangeUpdate u : ctx.updates.values()) {
+ handle.manager.add(u);
+ }
+ if (ctx.deleted) {
+ logDebug("Change %s was deleted", id);
+ handle.manager.deleteChange(id);
+ handle.setResult(id, ChangeResult.DELETED);
+ } else {
+ handle.setResult(id, ChangeResult.UPSERTED);
+ }
+ }
+ return handle;
+ }
+
+ private ChangeContextImpl newChangeContext(Change.Id id) throws OrmException {
+ logDebug("Opening change %s for update", id);
+ Change c = newChanges.get(id);
+ boolean isNew = c != null;
+ if (!isNew) {
+ // Pass a synthetic change into ChangeNotes.Factory, which will take care of checking for
+ // existence and populating columns from the parsed notes state.
+ // TODO(dborowitz): This dance made more sense when using Reviewdb; consider a nicer way.
+ c = ChangeNotes.Factory.newChange(project, id);
+ } else {
+ logDebug("Change %s is new", id);
+ }
+ ChangeNotes notes = changeNotesFactory.createForBatchUpdate(c, !isNew);
+ return new ChangeContextImpl(notes);
+ }
+
+ private void executePostOps() throws Exception {
+ ContextImpl ctx = new ContextImpl();
+ for (BatchUpdateOp op : ops.values()) {
+ op.postUpdate(ctx);
+ }
+
+ for (RepoOnlyOp op : repoOnlyOps) {
+ op.postUpdate(ctx);
+ }
+ }
+
+ private static void logDebug(String msg) {
// Only log if there is a requestId assigned, since those are the
// expensive/complicated requests like MergeOp. Doing it every time would be
// noisy.
@@ -328,7 +666,7 @@
}
}
- protected static void logDebug(String msg, @Nullable Object arg) {
+ private static void logDebug(String msg, @Nullable Object arg) {
// Only log if there is a requestId assigned, since those are the
// expensive/complicated requests like MergeOp. Doing it every time would be
// noisy.
@@ -337,16 +675,7 @@
}
}
- protected static void logDebug(String msg, @Nullable Object arg1, @Nullable Object arg2) {
- // Only log if there is a requestId assigned, since those are the
- // expensive/complicated requests like MergeOp. Doing it every time would be
- // noisy.
- if (RequestId.isSet()) {
- logger.atFine().log(msg, arg1, arg2);
- }
- }
-
- protected static void logDebug(
+ private static void logDebug(
String msg, @Nullable Object arg1, @Nullable Object arg2, @Nullable Object arg3) {
// Only log if there is a requestId assigned, since those are the
// expensive/complicated requests like MergeOp. Doing it every time would be
diff --git a/java/com/google/gerrit/server/update/NoteDbBatchUpdate.java b/java/com/google/gerrit/server/update/NoteDbBatchUpdate.java
deleted file mode 100644
index d881b0f..0000000
--- a/java/com/google/gerrit/server/update/NoteDbBatchUpdate.java
+++ /dev/null
@@ -1,457 +0,0 @@
-// Copyright (C) 2017 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.server.update;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.flogger.LazyArgs.lazy;
-import static java.util.Comparator.comparing;
-import static java.util.Objects.requireNonNull;
-import static java.util.stream.Collectors.toSet;
-
-import com.google.common.base.Throwables;
-import com.google.common.collect.ImmutableList;
-import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.CurrentUser;
-import com.google.gerrit.server.GerritPersonIdent;
-import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.index.change.ChangeIndexer;
-import com.google.gerrit.server.notedb.ChangeNotes;
-import com.google.gerrit.server.notedb.ChangeUpdate;
-import com.google.gerrit.server.notedb.NoteDbUpdateManager;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.assistedinject.Assisted;
-import java.io.IOException;
-import java.sql.Timestamp;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.TimeZone;
-import java.util.TreeMap;
-import org.eclipse.jgit.lib.ObjectInserter;
-import org.eclipse.jgit.lib.PersonIdent;
-import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.revwalk.RevWalk;
-import org.eclipse.jgit.transport.ReceiveCommand;
-
-/**
- * {@link BatchUpdate} implementation using only NoteDb that updates code refs and meta refs in a
- * single {@link org.eclipse.jgit.lib.BatchRefUpdate}.
- *
- * <p>Used when {@code noteDb.changes.disableReviewDb=true}, at which point ReviewDb is not
- * consulted during updates.
- */
-public class NoteDbBatchUpdate extends BatchUpdate {
- public interface AssistedFactory {
- NoteDbBatchUpdate create(
- ReviewDb db, Project.NameKey project, CurrentUser user, Timestamp when);
- }
-
- static void execute(
- ImmutableList<NoteDbBatchUpdate> updates, BatchUpdateListener listener, boolean dryrun)
- throws UpdateException, RestApiException {
- if (updates.isEmpty()) {
- return;
- }
-
- try {
- @SuppressWarnings("deprecation")
- List<com.google.common.util.concurrent.CheckedFuture<?, IOException>> indexFutures =
- new ArrayList<>();
- List<ChangesHandle> handles = new ArrayList<>(updates.size());
- Order order = getOrder(updates, listener);
- try {
- switch (order) {
- case REPO_BEFORE_DB:
- for (NoteDbBatchUpdate u : updates) {
- u.executeUpdateRepo();
- }
- listener.afterUpdateRepos();
- for (NoteDbBatchUpdate u : updates) {
- handles.add(u.executeChangeOps(dryrun));
- }
- for (ChangesHandle h : handles) {
- h.execute();
- indexFutures.addAll(h.startIndexFutures());
- }
- listener.afterUpdateRefs();
- listener.afterUpdateChanges();
- break;
-
- case DB_BEFORE_REPO:
- // Call updateChange for each op before updateRepo, but defer executing the
- // NoteDbUpdateManager until after calling updateRepo. They share an inserter and
- // BatchRefUpdate, so it will all execute as a single batch. But we have to let
- // NoteDbUpdateManager actually execute the update, since it has to interleave it
- // properly with All-Users updates.
- //
- // TODO(dborowitz): This may still result in multiple updates to All-Users, but that's
- // currently not a big deal because multi-change batches generally aren't affecting
- // drafts anyway.
- for (NoteDbBatchUpdate u : updates) {
- handles.add(u.executeChangeOps(dryrun));
- }
- for (NoteDbBatchUpdate u : updates) {
- u.executeUpdateRepo();
- }
- for (ChangesHandle h : handles) {
- // TODO(dborowitz): This isn't quite good enough: in theory updateRepo may want to
- // see the results of change meta commands, but they aren't actually added to the
- // BatchUpdate until the body of execute. To fix this, execute needs to be split up
- // into a method that returns a BatchRefUpdate before execution. Not a big deal at the
- // moment, because this order is only used for deleting changes, and those updateRepo
- // implementations definitely don't need to observe the updated change meta refs.
- h.execute();
- indexFutures.addAll(h.startIndexFutures());
- }
- break;
- default:
- throw new IllegalStateException("invalid execution order: " + order);
- }
- } finally {
- for (ChangesHandle h : handles) {
- h.close();
- }
- }
-
- ChangeIndexer.allAsList(indexFutures).get();
-
- // Fire ref update events only after all mutations are finished, since callers may assume a
- // patch set ref being created means the change was created, or a branch advancing meaning
- // some changes were closed.
- updates
- .stream()
- .filter(u -> u.batchRefUpdate != null)
- .forEach(
- u -> u.gitRefUpdated.fire(u.project, u.batchRefUpdate, u.getAccount().orElse(null)));
-
- if (!dryrun) {
- for (NoteDbBatchUpdate u : updates) {
- u.executePostOps();
- }
- }
- } catch (Exception e) {
- wrapAndThrowException(e);
- }
- }
-
- class ContextImpl implements Context {
- @Override
- public RepoView getRepoView() throws IOException {
- return NoteDbBatchUpdate.this.getRepoView();
- }
-
- @Override
- public RevWalk getRevWalk() throws IOException {
- return getRepoView().getRevWalk();
- }
-
- @Override
- public Project.NameKey getProject() {
- return project;
- }
-
- @Override
- public Timestamp getWhen() {
- return when;
- }
-
- @Override
- public TimeZone getTimeZone() {
- return tz;
- }
-
- @Override
- public ReviewDb getDb() {
- return db;
- }
-
- @Override
- public CurrentUser getUser() {
- return user;
- }
-
- @Override
- public Order getOrder() {
- return order;
- }
- }
-
- private class RepoContextImpl extends ContextImpl implements RepoContext {
- @Override
- public ObjectInserter getInserter() throws IOException {
- return getRepoView().getInserterWrapper();
- }
-
- @Override
- public void addRefUpdate(ReceiveCommand cmd) throws IOException {
- getRepoView().getCommands().add(cmd);
- }
- }
-
- private class ChangeContextImpl extends ContextImpl implements ChangeContext {
- private final ChangeNotes notes;
- private final Map<PatchSet.Id, ChangeUpdate> updates;
-
- private boolean deleted;
-
- protected ChangeContextImpl(ChangeNotes notes) {
- this.notes = requireNonNull(notes);
- updates = new TreeMap<>(comparing(PatchSet.Id::get));
- }
-
- @Override
- public ChangeUpdate getUpdate(PatchSet.Id psId) {
- ChangeUpdate u = updates.get(psId);
- if (u == null) {
- u = changeUpdateFactory.create(notes, user, when);
- if (newChanges.containsKey(notes.getChangeId())) {
- u.setAllowWriteToNewRef(true);
- }
- u.setPatchSetId(psId);
- updates.put(psId, u);
- }
- return u;
- }
-
- @Override
- public ChangeNotes getNotes() {
- return notes;
- }
-
- @Override
- public void dontBumpLastUpdatedOn() {
- // Do nothing; NoteDb effectively updates timestamp if and only if a commit was written to the
- // change meta ref.
- }
-
- @Override
- public void deleteChange() {
- deleted = true;
- }
- }
-
- /** Per-change result status from {@link #executeChangeOps}. */
- private enum ChangeResult {
- SKIPPED,
- UPSERTED,
- DELETED;
- }
-
- private final ChangeNotes.Factory changeNotesFactory;
- private final ChangeUpdate.Factory changeUpdateFactory;
- private final NoteDbUpdateManager.Factory updateManagerFactory;
- private final ChangeIndexer indexer;
- private final GitReferenceUpdated gitRefUpdated;
- private final ReviewDb db;
-
- @Inject
- NoteDbBatchUpdate(
- GitRepositoryManager repoManager,
- @GerritPersonIdent PersonIdent serverIdent,
- ChangeNotes.Factory changeNotesFactory,
- ChangeUpdate.Factory changeUpdateFactory,
- NoteDbUpdateManager.Factory updateManagerFactory,
- ChangeIndexer indexer,
- GitReferenceUpdated gitRefUpdated,
- @Assisted ReviewDb db,
- @Assisted Project.NameKey project,
- @Assisted CurrentUser user,
- @Assisted Timestamp when) {
- super(repoManager, serverIdent, project, user, when);
- this.changeNotesFactory = changeNotesFactory;
- this.changeUpdateFactory = changeUpdateFactory;
- this.updateManagerFactory = updateManagerFactory;
- this.indexer = indexer;
- this.gitRefUpdated = gitRefUpdated;
- this.db = db;
- }
-
- @Override
- public void execute(BatchUpdateListener listener) throws UpdateException, RestApiException {
- execute(ImmutableList.of(this), listener, false);
- }
-
- @Override
- protected Context newContext() {
- return new ContextImpl();
- }
-
- private void executeUpdateRepo() throws UpdateException, RestApiException {
- try {
- logDebug("Executing updateRepo on %d ops", ops.size());
- RepoContextImpl ctx = new RepoContextImpl();
- for (BatchUpdateOp op : ops.values()) {
- op.updateRepo(ctx);
- }
-
- logDebug("Executing updateRepo on %d RepoOnlyOps", repoOnlyOps.size());
- for (RepoOnlyOp op : repoOnlyOps) {
- op.updateRepo(ctx);
- }
-
- if (onSubmitValidators != null && !getRefUpdates().isEmpty()) {
- // Validation of refs has to take place here and not at the beginning of executeRefUpdates.
- // Otherwise, failing validation in a second BatchUpdate object will happen *after* the
- // first update's executeRefUpdates has finished, hence after first repo's refs have been
- // updated, which is too late.
- onSubmitValidators.validate(
- project, ctx.getRevWalk().getObjectReader(), repoView.getCommands());
- }
- } catch (Exception e) {
- Throwables.throwIfInstanceOf(e, RestApiException.class);
- throw new UpdateException(e);
- }
- }
-
- private class ChangesHandle implements AutoCloseable {
- private final NoteDbUpdateManager manager;
- private final boolean dryrun;
- private final Map<Change.Id, ChangeResult> results;
-
- ChangesHandle(NoteDbUpdateManager manager, boolean dryrun) {
- this.manager = manager;
- this.dryrun = dryrun;
- results = new HashMap<>();
- }
-
- @Override
- public void close() {
- manager.close();
- }
-
- void setResult(Change.Id id, ChangeResult result) {
- ChangeResult old = results.putIfAbsent(id, result);
- checkArgument(old == null, "result for change %s already set: %s", id, old);
- }
-
- void execute() throws OrmException, IOException {
- NoteDbBatchUpdate.this.batchRefUpdate = manager.execute(dryrun);
- }
-
- @SuppressWarnings("deprecation")
- List<com.google.common.util.concurrent.CheckedFuture<?, IOException>> startIndexFutures() {
- if (dryrun) {
- return ImmutableList.of();
- }
- logDebug("Reindexing %d changes", results.size());
- List<com.google.common.util.concurrent.CheckedFuture<?, IOException>> indexFutures =
- new ArrayList<>(results.size());
- for (Map.Entry<Change.Id, ChangeResult> e : results.entrySet()) {
- Change.Id id = e.getKey();
- switch (e.getValue()) {
- case UPSERTED:
- indexFutures.add(indexer.indexAsync(project, id));
- break;
- case DELETED:
- indexFutures.add(indexer.deleteAsync(id));
- break;
- case SKIPPED:
- break;
- default:
- throw new IllegalStateException("unexpected result: " + e.getValue());
- }
- }
- return indexFutures;
- }
- }
-
- private ChangesHandle executeChangeOps(boolean dryrun) throws Exception {
- logDebug("Executing change ops");
- initRepository();
- Repository repo = repoView.getRepository();
- checkState(
- repo.getRefDatabase().performsAtomicTransactions(),
- "cannot use NoteDb with a repository that does not support atomic batch ref updates: %s",
- repo);
-
- ChangesHandle handle =
- new ChangesHandle(
- updateManagerFactory
- .create(project)
- .setChangeRepo(
- repo, repoView.getRevWalk(), repoView.getInserter(), repoView.getCommands()),
- dryrun);
- if (user.isIdentifiedUser()) {
- handle.manager.setRefLogIdent(user.asIdentifiedUser().newRefLogIdent(when, tz));
- }
- handle.manager.setRefLogMessage(refLogMessage);
- handle.manager.setPushCertificate(pushCert);
- for (Map.Entry<Change.Id, Collection<BatchUpdateOp>> e : ops.asMap().entrySet()) {
- Change.Id id = e.getKey();
- ChangeContextImpl ctx = newChangeContext(id);
- boolean dirty = false;
- logDebug(
- "Applying %d ops for change %s: %s",
- e.getValue().size(),
- id,
- lazy(() -> e.getValue().stream().map(op -> op.getClass().getName()).collect(toSet())));
- for (BatchUpdateOp op : e.getValue()) {
- dirty |= op.updateChange(ctx);
- }
- if (!dirty) {
- logDebug("No ops reported dirty, short-circuiting");
- handle.setResult(id, ChangeResult.SKIPPED);
- continue;
- }
- for (ChangeUpdate u : ctx.updates.values()) {
- handle.manager.add(u);
- }
- if (ctx.deleted) {
- logDebug("Change %s was deleted", id);
- handle.manager.deleteChange(id);
- handle.setResult(id, ChangeResult.DELETED);
- } else {
- handle.setResult(id, ChangeResult.UPSERTED);
- }
- }
- return handle;
- }
-
- private ChangeContextImpl newChangeContext(Change.Id id) throws OrmException {
- logDebug("Opening change %s for update", id);
- Change c = newChanges.get(id);
- boolean isNew = c != null;
- if (!isNew) {
- // Pass a synthetic change into ChangeNotes.Factory, which will take care of checking for
- // existence and populating columns from the parsed notes state.
- // TODO(dborowitz): This dance made more sense when using Reviewdb; consider a nicer way.
- c = ChangeNotes.Factory.newNoteDbOnlyChange(project, id);
- } else {
- logDebug("Change %s is new", id);
- }
- ChangeNotes notes = changeNotesFactory.createForBatchUpdate(c, !isNew);
- return new ChangeContextImpl(notes);
- }
-
- private void executePostOps() throws Exception {
- ContextImpl ctx = new ContextImpl();
- for (BatchUpdateOp op : ops.values()) {
- op.postUpdate(ctx);
- }
-
- for (RepoOnlyOp op : repoOnlyOps) {
- op.postUpdate(ctx);
- }
- }
-}
diff --git a/java/com/google/gerrit/server/update/RetryHelper.java b/java/com/google/gerrit/server/update/RetryHelper.java
index 9bdf293..d2bccf1 100644
--- a/java/com/google/gerrit/server/update/RetryHelper.java
+++ b/java/com/google/gerrit/server/update/RetryHelper.java
@@ -147,21 +147,18 @@
@Nullable private final Consumer<RetryerBuilder<?>> overwriteDefaultRetryerStrategySetup;
@Inject
- RetryHelper(
- @GerritServerConfig Config cfg,
- Metrics metrics,
- NoteDbBatchUpdate.AssistedFactory noteDbBatchUpdateFactory) {
- this(cfg, metrics, noteDbBatchUpdateFactory, null);
+ RetryHelper(@GerritServerConfig Config cfg, Metrics metrics, BatchUpdate.Factory updateFactory) {
+ this(cfg, metrics, updateFactory, null);
}
@VisibleForTesting
public RetryHelper(
@GerritServerConfig Config cfg,
Metrics metrics,
- NoteDbBatchUpdate.AssistedFactory noteDbBatchUpdateFactory,
+ BatchUpdate.Factory updateFactory,
@Nullable Consumer<RetryerBuilder<?>> overwriteDefaultRetryerStrategySetup) {
this.metrics = metrics;
- this.updateFactory = new BatchUpdate.Factory(noteDbBatchUpdateFactory);
+ this.updateFactory = updateFactory;
Duration defaultTimeout =
Duration.ofMillis(
diff --git a/java/com/google/gerrit/sshd/ChangeArgumentParser.java b/java/com/google/gerrit/sshd/ChangeArgumentParser.java
index 7a9f298..b402533 100644
--- a/java/com/google/gerrit/sshd/ChangeArgumentParser.java
+++ b/java/com/google/gerrit/sshd/ChangeArgumentParser.java
@@ -121,7 +121,7 @@
}
private List<ChangeNotes> changeFromNotesFactory(String id) throws OrmException, UnloggedFailure {
- return changeNotesFactory.create(db, parseId(id));
+ return changeNotesFactory.create(parseId(id));
}
private List<Change.Id> parseId(String id) throws UnloggedFailure {
diff --git a/java/com/google/gerrit/sshd/commands/PatchSetParser.java b/java/com/google/gerrit/sshd/commands/PatchSetParser.java
index a1e8f07..d174561 100644
--- a/java/com/google/gerrit/sshd/commands/PatchSetParser.java
+++ b/java/com/google/gerrit/sshd/commands/PatchSetParser.java
@@ -19,7 +19,6 @@
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RevId;
-import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.PatchSetUtil;
import com.google.gerrit.server.change.ChangeFinder;
import com.google.gerrit.server.notedb.ChangeNotes;
@@ -37,7 +36,6 @@
@Singleton
public class PatchSetParser {
- private final Provider<ReviewDb> db;
private final Provider<InternalChangeQuery> queryProvider;
private final ChangeNotes.Factory notesFactory;
private final PatchSetUtil psUtil;
@@ -45,12 +43,10 @@
@Inject
PatchSetParser(
- Provider<ReviewDb> db,
Provider<InternalChangeQuery> queryProvider,
ChangeNotes.Factory notesFactory,
PatchSetUtil psUtil,
ChangeFinder changeFinder) {
- this.db = db;
this.queryProvider = queryProvider;
this.notesFactory = notesFactory;
this.psUtil = psUtil;
@@ -129,11 +125,11 @@
private ChangeNotes getNotes(@Nullable ProjectState projectState, Change.Id changeId)
throws OrmException, UnloggedFailure {
if (projectState != null) {
- return notesFactory.create(db.get(), projectState.getNameKey(), changeId);
+ return notesFactory.create(projectState.getNameKey(), changeId);
}
try {
ChangeNotes notes = changeFinder.findOne(changeId);
- return notesFactory.create(db.get(), notes.getProjectName(), changeId);
+ return notesFactory.create(notes.getProjectName(), changeId);
} catch (NoSuchChangeException e) {
throw error("\"" + changeId + "\" no such change");
}
diff --git a/java/com/google/gerrit/testing/GerritServerTests.java b/java/com/google/gerrit/testing/GerritServerTests.java
index 69806e1..75479d2 100644
--- a/java/com/google/gerrit/testing/GerritServerTests.java
+++ b/java/com/google/gerrit/testing/GerritServerTests.java
@@ -14,7 +14,7 @@
package com.google.gerrit.testing;
-import com.google.gerrit.server.notedb.MutableNotesMigration;
+import com.google.gerrit.server.notedb.NotesMigration;
import org.eclipse.jgit.lib.Config;
import org.junit.Rule;
import org.junit.rules.TestRule;
@@ -28,7 +28,7 @@
@ConfigSuite.Name private String configName;
- protected MutableNotesMigration notesMigration;
+ protected NotesMigration notesMigration;
@Rule
public TestRule testRunner =
@@ -39,21 +39,13 @@
@Override
public void evaluate() throws Throwable {
beforeTest();
- try {
- base.evaluate();
- } finally {
- afterTest();
- }
+ base.evaluate();
}
};
}
};
- public void beforeTest() throws Exception {
- notesMigration = NoteDbMode.newNotesMigrationFromEnv();
- }
-
- public void afterTest() {
- NoteDbMode.resetFromEnv(notesMigration);
+ public void beforeTest() {
+ notesMigration = new NotesMigration();
}
}
diff --git a/java/com/google/gerrit/testing/InMemoryModule.java b/java/com/google/gerrit/testing/InMemoryModule.java
index 682e8c2..ac7224f 100644
--- a/java/com/google/gerrit/testing/InMemoryModule.java
+++ b/java/com/google/gerrit/testing/InMemoryModule.java
@@ -73,8 +73,6 @@
import com.google.gerrit.server.index.group.GroupIndexCollection;
import com.google.gerrit.server.index.group.GroupSchemaDefinitions;
import com.google.gerrit.server.mail.SignedTokenEmailTokenVerifier;
-import com.google.gerrit.server.notedb.MutableNotesMigration;
-import com.google.gerrit.server.notedb.NotesMigration;
import com.google.gerrit.server.patch.DiffExecutor;
import com.google.gerrit.server.permissions.DefaultPermissionBackendModule;
import com.google.gerrit.server.plugins.ServerInformationImpl;
@@ -135,15 +133,13 @@
}
private final Config cfg;
- private final MutableNotesMigration notesMigration;
public InMemoryModule() {
- this(newDefaultConfig(), NoteDbMode.newNotesMigrationFromEnv());
+ this(newDefaultConfig());
}
- public InMemoryModule(Config cfg, MutableNotesMigration notesMigration) {
+ public InMemoryModule(Config cfg) {
this.cfg = cfg;
- this.notesMigration = notesMigration;
}
public void inject(Object instance) {
@@ -191,8 +187,6 @@
bind(GitRepositoryManager.class).to(InMemoryRepositoryManager.class);
bind(InMemoryRepositoryManager.class).in(SINGLETON);
bind(TrackingFooters.class).toProvider(TrackingFootersProvider.class).in(SINGLETON);
- bind(MutableNotesMigration.class).toInstance(notesMigration);
- bind(NotesMigration.class).to(MutableNotesMigration.class);
bind(ListeningExecutorService.class)
.annotatedWith(ChangeUpdateExecutor.class)
.toInstance(MoreExecutors.newDirectExecutorService());
diff --git a/java/com/google/gerrit/testing/InMemoryTestEnvironment.java b/java/com/google/gerrit/testing/InMemoryTestEnvironment.java
index f665015..a8afdb3 100644
--- a/java/com/google/gerrit/testing/InMemoryTestEnvironment.java
+++ b/java/com/google/gerrit/testing/InMemoryTestEnvironment.java
@@ -108,8 +108,7 @@
Config cfg = configProvider.get();
InMemoryModule.setDefaults(cfg);
- Injector injector =
- Guice.createInjector(new InMemoryModule(cfg, NoteDbMode.newNotesMigrationFromEnv()));
+ Injector injector = Guice.createInjector(new InMemoryModule(cfg));
injector.injectMembers(this);
lifecycle = new LifecycleManager();
lifecycle.add(injector);
diff --git a/java/com/google/gerrit/testing/NoteDbMode.java b/java/com/google/gerrit/testing/NoteDbMode.java
deleted file mode 100644
index f901cce..0000000
--- a/java/com/google/gerrit/testing/NoteDbMode.java
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright (C) 2016 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.testing;
-
-import static com.google.common.base.Preconditions.checkArgument;
-
-import com.google.common.base.Enums;
-import com.google.common.base.Strings;
-import com.google.gerrit.server.notedb.MutableNotesMigration;
-import com.google.gerrit.server.notedb.NotesMigrationState;
-
-public enum NoteDbMode {
- /** NoteDb is disabled. */
- OFF(NotesMigrationState.REVIEW_DB),
-
- /** Writing data to NoteDb is enabled. */
- WRITE(NotesMigrationState.WRITE),
-
- /** Reading and writing all data to NoteDb is enabled. */
- READ_WRITE(NotesMigrationState.READ_WRITE_WITH_SEQUENCE_REVIEW_DB_PRIMARY),
-
- /** Changes are created with their primary storage as NoteDb. */
- PRIMARY(NotesMigrationState.READ_WRITE_WITH_SEQUENCE_NOTE_DB_PRIMARY),
-
- /** All change tables are entirely disabled, and code/meta ref updates are fused. */
- ON(NotesMigrationState.NOTE_DB);
-
- private static final String ENV_VAR = "GERRIT_NOTEDB";
- private static final String SYS_PROP = "gerrit.notedb";
-
- public static NoteDbMode get() {
- String value = System.getenv(ENV_VAR);
- if (Strings.isNullOrEmpty(value)) {
- value = System.getProperty(SYS_PROP);
- }
- if (Strings.isNullOrEmpty(value)) {
- return ON;
- }
- value = value.toUpperCase().replace("-", "_");
- NoteDbMode mode = Enums.getIfPresent(NoteDbMode.class, value).orNull();
- if (!Strings.isNullOrEmpty(System.getenv(ENV_VAR))) {
- checkArgument(
- mode != null, "Invalid value for env variable %s: %s", ENV_VAR, System.getenv(ENV_VAR));
- } else {
- checkArgument(
- mode != null,
- "Invalid value for system property %s: %s",
- SYS_PROP,
- System.getProperty(SYS_PROP));
- }
- return mode;
- }
-
- public static MutableNotesMigration newNotesMigrationFromEnv() {
- MutableNotesMigration m = MutableNotesMigration.newDisabled();
- resetFromEnv(m);
- return m;
- }
-
- public static void resetFromEnv(MutableNotesMigration migration) {
- migration.setFrom(get().state);
- }
-
- private final NotesMigrationState state;
-
- private NoteDbMode(NotesMigrationState state) {
- this.state = state;
- }
-}
diff --git a/java/com/google/gerrit/testing/TestChanges.java b/java/com/google/gerrit/testing/TestChanges.java
index 0c87b38..fe4f3e7 100644
--- a/java/com/google/gerrit/testing/TestChanges.java
+++ b/java/com/google/gerrit/testing/TestChanges.java
@@ -53,6 +53,7 @@
public static Change newChange(Project.NameKey project, Account.Id userId, int id) {
Change.Id changeId = new Change.Id(id);
+ // TODO(ekempin): Create NoteDb change.
Change c =
new Change(
new Change.Key("Iabcd1234abcd1234abcd1234abcd1234abcd1234"),
diff --git a/javatests/com/google/gerrit/acceptance/api/project/ProjectIT.java b/javatests/com/google/gerrit/acceptance/api/project/ProjectIT.java
index aa1ad7b..87c63e1 100644
--- a/javatests/com/google/gerrit/acceptance/api/project/ProjectIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/project/ProjectIT.java
@@ -32,6 +32,7 @@
import com.google.gerrit.acceptance.NoHttpd;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
+import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.data.Permission;
import com.google.gerrit.extensions.api.projects.BranchInput;
import com.google.gerrit.extensions.api.projects.CommentLinkInfo;
@@ -715,4 +716,9 @@
clear();
}
}
+
+ @Nullable
+ protected RevCommit getRemoteHead(String project, String branch) throws Exception {
+ return getRemoteHead(new Project.NameKey(project), branch);
+ }
}
diff --git a/javatests/com/google/gerrit/acceptance/git/RefAdvertisementIT.java b/javatests/com/google/gerrit/acceptance/git/RefAdvertisementIT.java
index d2fd331..aa03d90 100644
--- a/javatests/com/google/gerrit/acceptance/git/RefAdvertisementIT.java
+++ b/javatests/com/google/gerrit/acceptance/git/RefAdvertisementIT.java
@@ -46,14 +46,13 @@
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.server.Sequences;
import com.google.gerrit.server.config.AllUsersName;
-import com.google.gerrit.server.config.AnonymousCowardName;
import com.google.gerrit.server.git.receive.ReceiveCommitsAdvertiseRefsHook;
import com.google.gerrit.server.notedb.ChangeNoteUtil;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackend.RefFilterOptions;
import com.google.gerrit.server.project.testing.Util;
import com.google.gerrit.server.query.change.ChangeData;
-import com.google.gerrit.testing.NoteDbMode;
+import com.google.gerrit.testing.ConfigSuite;
import com.google.inject.Inject;
import java.io.IOException;
import java.util.ArrayList;
@@ -63,6 +62,7 @@
import java.util.function.Predicate;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.junit.TestRepository;
+import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
@@ -76,7 +76,6 @@
public class RefAdvertisementIT extends AbstractDaemonTest {
@Inject private PermissionBackend permissionBackend;
@Inject private ChangeNoteUtil noteUtil;
- @Inject @AnonymousCowardName private String anonymousCowardName;
@Inject private AllUsersName allUsersName;
private AccountGroup.UUID admins;
@@ -91,6 +90,13 @@
private String r3;
private String r4;
+ @ConfigSuite.Config
+ public static Config enableFullRefEvaluation() {
+ Config cfg = new Config();
+ cfg.setBoolean("auth", null, "skipFullRefEvaluationIfAllRefsAreVisible", false);
+ return cfg;
+ }
+
@Before
public void setUp() throws Exception {
admins = adminGroupUuid();
@@ -253,7 +259,7 @@
public void uploadPackSubsetOfBranchesVisibleWithEdit() throws Exception {
allow("refs/heads/master", Permission.READ, REGISTERED_USERS);
- Change c = notesFactory.createChecked(db, project, c3.getId()).getChange();
+ Change c = notesFactory.createChecked(project, c3.getId()).getChange();
String changeId = c.getKey().get();
// Admin's edit is not visible.
@@ -281,9 +287,9 @@
allow("refs/heads/master", Permission.READ, REGISTERED_USERS);
allow("refs/*", Permission.VIEW_PRIVATE_CHANGES, REGISTERED_USERS);
- Change change3 = notesFactory.createChecked(db, project, c3.getId()).getChange();
+ Change change3 = notesFactory.createChecked(project, c3.getId()).getChange();
String changeId3 = change3.getKey().get();
- Change change4 = notesFactory.createChecked(db, project, c4.getId()).getChange();
+ Change change4 = notesFactory.createChecked(project, c4.getId()).getChange();
String changeId4 = change4.getKey().get();
// Admin's edit on change3 is visible.
@@ -369,7 +375,6 @@
@Test
public void uploadPackSequencesWithAccessDatabase() throws Exception {
- assume().that(notesMigration.readChangeSequence()).isTrue();
try (Repository repo = repoManager.openRepository(allProjects)) {
assertRefs(repo, newFilter(allProjects, user), true);
@@ -379,6 +384,28 @@
}
@Test
+ public void uploadPackAllRefsAreVisibleOrphanedTag() throws Exception {
+ allow("refs/*", Permission.READ, REGISTERED_USERS);
+ // Delete the pending change on 'branch' and 'branch' itself so that the tag gets orphaned
+ gApi.changes().id(c4.getId().id).delete();
+ gApi.projects().name(project.get()).branch("refs/heads/branch").delete();
+
+ setApiUser(user);
+ assertUploadPackRefs(
+ "HEAD",
+ "refs/meta/config",
+ r1 + "1",
+ r1 + "meta",
+ r2 + "1",
+ r2 + "meta",
+ r3 + "1",
+ r3 + "meta",
+ "refs/heads/master",
+ "refs/tags/branch-tag",
+ "refs/tags/master-tag");
+ }
+
+ @Test
public void receivePackListsOpenChangesAsAdditionalHaves() throws Exception {
ReceiveCommitsAdvertiseRefsHook.Result r = getReceivePackRefs();
assertThat(r.allRefs().keySet())
@@ -567,6 +594,9 @@
@Test
public void advertisedReferencesIncludePrivateChangesWhenAllRefsMayBeRead() throws Exception {
+ assume()
+ .that(baseConfig.getBoolean("auth", "skipFullRefEvaluationIfAllRefsAreVisible", true))
+ .isTrue();
allow("refs/*", Permission.READ, REGISTERED_USERS);
TestRepository<?> userTestRepository = cloneProject(project, user);
@@ -665,9 +695,7 @@
List<String> expectedMetaRefs =
new ArrayList<>(ImmutableList.of(mr.getPatchSetId().toRefName()));
- if (NoteDbMode.get() != NoteDbMode.OFF) {
- expectedMetaRefs.add(changeRefPrefix(mr.getChange().getId()) + "meta");
- }
+ expectedMetaRefs.add(changeRefPrefix(mr.getChange().getId()) + "meta");
List<String> expectedAllRefs = new ArrayList<>(expectedNonMetaRefs);
expectedAllRefs.addAll(expectedMetaRefs);
diff --git a/javatests/com/google/gerrit/acceptance/git/SubmitOnPushIT.java b/javatests/com/google/gerrit/acceptance/git/SubmitOnPushIT.java
index cf22a0a..dd9f08f 100644
--- a/javatests/com/google/gerrit/acceptance/git/SubmitOnPushIT.java
+++ b/javatests/com/google/gerrit/acceptance/git/SubmitOnPushIT.java
@@ -317,7 +317,7 @@
}
private PatchSetApproval getSubmitter(PatchSet.Id patchSetId) throws Exception {
- ChangeNotes notes = notesFactory.createChecked(db, project, patchSetId.getParentKey()).load();
+ ChangeNotes notes = notesFactory.createChecked(project, patchSetId.getParentKey()).load();
return approvalsUtil.getSubmitter(notes, patchSetId);
}
diff --git a/javatests/com/google/gerrit/acceptance/git/SubmoduleSubscriptionsWholeTopicMergeIT.java b/javatests/com/google/gerrit/acceptance/git/SubmoduleSubscriptionsWholeTopicMergeIT.java
index f72df99..0bbe769 100644
--- a/javatests/com/google/gerrit/acceptance/git/SubmoduleSubscriptionsWholeTopicMergeIT.java
+++ b/javatests/com/google/gerrit/acceptance/git/SubmoduleSubscriptionsWholeTopicMergeIT.java
@@ -839,13 +839,13 @@
sub1.git().fetch().call();
RevWalk rw1 = sub1.getRevWalk();
- RevCommit master1 = rw1.parseCommit(getRemoteHead(subKey1.get(), "master"));
+ RevCommit master1 = rw1.parseCommit(getRemoteHead(subKey1, "master"));
RevCommit change1Ps = parseCurrentRevision(rw1, changeId1);
assertThat(rw1.isMergedInto(change1Ps, master1)).isTrue();
sub2.git().fetch().call();
RevWalk rw2 = sub2.getRevWalk();
- RevCommit master2 = rw2.parseCommit(getRemoteHead(subKey2.get(), "master"));
+ RevCommit master2 = rw2.parseCommit(getRemoteHead(subKey2, "master"));
RevCommit change2Ps = parseCurrentRevision(rw2, changeId2);
assertThat(rw2.isMergedInto(change2Ps, master2)).isTrue();
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java b/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java
index a4d9a24..8bfcc84 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java
@@ -1276,7 +1276,7 @@
protected void assertSubmitter(String changeId, int psId, TestAccount user) throws Exception {
Change c = getOnlyElement(queryProvider.get().byKeyPrefix(changeId)).change();
- ChangeNotes cn = notesFactory.createChecked(db, c);
+ ChangeNotes cn = notesFactory.createChecked(c);
PatchSetApproval submitter =
approvalsUtil.getSubmitter(cn, new PatchSet.Id(cn.getChangeId(), psId));
assertThat(submitter).isNotNull();
@@ -1286,7 +1286,7 @@
protected void assertNoSubmitter(String changeId, int psId) throws Exception {
Change c = getOnlyElement(queryProvider.get().byKeyPrefix(changeId)).change();
- ChangeNotes cn = notesFactory.createChecked(db, c);
+ ChangeNotes cn = notesFactory.createChecked(c);
PatchSetApproval submitter =
approvalsUtil.getSubmitter(cn, new PatchSet.Id(cn.getChangeId(), psId));
assertThat(submitter).isNull();
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/ChangeReviewersByEmailIT.java b/javatests/com/google/gerrit/acceptance/rest/change/ChangeReviewersByEmailIT.java
index 2a397e4..7b302c4 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/ChangeReviewersByEmailIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/ChangeReviewersByEmailIT.java
@@ -21,6 +21,7 @@
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.gerrit.acceptance.AbstractDaemonTest;
+import com.google.gerrit.acceptance.AcceptanceTestRequestScope.Context;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.acceptance.RestResponse;
import com.google.gerrit.extensions.api.changes.AddReviewerInput;
@@ -319,14 +320,14 @@
input.state = state;
gApi.changes().id(r.getChangeId()).addReviewer(input);
- notesMigration.setFailOnLoadForTest(true);
+ Context oldCtx = disableDb();
try {
ChangeInfo info =
Iterables.getOnlyElement(
gApi.changes().query(r.getChangeId()).withOption(DETAILED_LABELS).get());
assertThat(info.reviewers).isEqualTo(ImmutableMap.of(state, ImmutableList.of(acc)));
} finally {
- notesMigration.setFailOnLoadForTest(false);
+ enableDb(oldCtx);
}
}
}
diff --git a/javatests/com/google/gerrit/acceptance/rest/config/ServerInfoIT.java b/javatests/com/google/gerrit/acceptance/rest/config/ServerInfoIT.java
index 6c0b707..14521cc 100644
--- a/javatests/com/google/gerrit/acceptance/rest/config/ServerInfoIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/config/ServerInfoIT.java
@@ -127,10 +127,7 @@
assertThat(i.user.anonymousCowardName).isEqualTo("Unnamed User");
// notedb
- notesMigration.setReadChanges(true);
assertThat(gApi.config().server().getInfo().noteDbEnabled).isTrue();
- notesMigration.setReadChanges(false);
- assertThat(gApi.config().server().getInfo().noteDbEnabled).isNull();
}
@Test
diff --git a/javatests/com/google/gerrit/acceptance/server/change/CommentsIT.java b/javatests/com/google/gerrit/acceptance/server/change/CommentsIT.java
index a352baa..5d97347 100644
--- a/javatests/com/google/gerrit/acceptance/server/change/CommentsIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/change/CommentsIT.java
@@ -950,7 +950,7 @@
addComment(result.getChangeId(), "comment");
Collection<com.google.gerrit.reviewdb.client.Comment> comments =
- notesFactory.createChecked(db, project, changeId).getComments().values();
+ notesFactory.createChecked(project, changeId).getComments().values();
assertThat(comments).hasSize(1);
com.google.gerrit.reviewdb.client.Comment comment = comments.iterator().next();
assertThat(comment.message).isEqualTo("comment");
diff --git a/javatests/com/google/gerrit/acceptance/server/change/ConsistencyCheckerIT.java b/javatests/com/google/gerrit/acceptance/server/change/ConsistencyCheckerIT.java
index 460cd30..9b19b22 100644
--- a/javatests/com/google/gerrit/acceptance/server/change/ConsistencyCheckerIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/change/ConsistencyCheckerIT.java
@@ -261,7 +261,7 @@
+ rev
+ "\n");
indexer.index(db, c.getProject(), c.getId());
- ChangeNotes notes = changeNotesFactory.create(db, c.getProject(), c.getId());
+ ChangeNotes notes = changeNotesFactory.create(c.getProject(), c.getId());
FixInput fix = new FixInput();
fix.deletePatchSetIfCommitMissing = true;
@@ -760,7 +760,7 @@
.setSendMail(false);
bu.insertChange(ins).execute();
}
- return changeNotesFactory.create(db, project, ins.getChange().getId());
+ return changeNotesFactory.create(project, ins.getChange().getId());
}
private PatchSet.Id nextPatchSetId(ChangeNotes notes) throws Exception {
@@ -787,7 +787,7 @@
}
private ChangeNotes reload(ChangeNotes notes) throws Exception {
- return changeNotesFactory.create(db, notes.getChange().getProject(), notes.getChangeId());
+ return changeNotesFactory.create(notes.getChange().getProject(), notes.getChangeId());
}
private RevCommit patchSetCommit(PatchSet.Id psId) throws Exception {
diff --git a/javatests/com/google/gerrit/acceptance/server/notedb/NoteDbOnlyIT.java b/javatests/com/google/gerrit/acceptance/server/notedb/NoteDbOnlyIT.java
index 5047b73..7af0ff8 100644
--- a/javatests/com/google/gerrit/acceptance/server/notedb/NoteDbOnlyIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/notedb/NoteDbOnlyIT.java
@@ -189,8 +189,8 @@
@Test
public void missingChange() throws Exception {
Change.Id changeId = new Change.Id(1234567);
- assertNoSuchChangeException(() -> notesFactory.create(db, project, changeId));
- assertNoSuchChangeException(() -> notesFactory.createChecked(db, project, changeId));
+ assertNoSuchChangeException(() -> notesFactory.create(project, changeId));
+ assertNoSuchChangeException(() -> notesFactory.createChecked(project, changeId));
}
private void assertNoSuchChangeException(Callable<?> callable) throws Exception {
diff --git a/javatests/com/google/gerrit/acceptance/server/quota/DefaultQuotaBackendIT.java b/javatests/com/google/gerrit/acceptance/server/quota/DefaultQuotaBackendIT.java
index f60d301..dea83ca 100644
--- a/javatests/com/google/gerrit/acceptance/server/quota/DefaultQuotaBackendIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/quota/DefaultQuotaBackendIT.java
@@ -139,17 +139,13 @@
}
@Test
- public void requestTokenPluginThrowsResultsInError() throws Exception {
+ public void requestTokenPluginThrowsAndRethrows() {
QuotaRequestContext ctx = QuotaRequestContext.builder().user(identifiedAdmin).build();
expect(quotaEnforcer.requestTokens("testGroup", ctx, 1)).andThrow(new NullPointerException());
replay(quotaEnforcer);
- QuotaResponse.Aggregated result = quotaBackend.user(identifiedAdmin).requestToken("testGroup");
- assertThat(result)
- .isEqualTo(singletonAggregation(QuotaResponse.error("failed to request quota tokens")));
- exception.expect(QuotaException.class);
- exception.expectMessage("failed to request quota tokens");
- result.throwOnError();
+ exception.expect(NullPointerException.class);
+ quotaBackend.user(identifiedAdmin).requestToken("testGroup");
}
private static QuotaResponse.Aggregated singletonAggregation(QuotaResponse response) {
diff --git a/javatests/com/google/gerrit/acceptance/server/quota/MultipleQuotaPluginsIT.java b/javatests/com/google/gerrit/acceptance/server/quota/MultipleQuotaPluginsIT.java
index ba69d7c..31a8808 100644
--- a/javatests/com/google/gerrit/acceptance/server/quota/MultipleQuotaPluginsIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/quota/MultipleQuotaPluginsIT.java
@@ -19,6 +19,7 @@
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.resetToStrict;
+import static org.easymock.EasyMock.verify;
import com.google.common.collect.ImmutableList;
import com.google.gerrit.acceptance.AbstractDaemonTest;
@@ -87,20 +88,24 @@
@Test
public void refillsOnException() {
+ NullPointerException exception = new NullPointerException();
QuotaRequestContext ctx = QuotaRequestContext.builder().user(identifiedAdmin).build();
- expect(quotaEnforcerA.requestTokens("testGroup", ctx, 1)).andReturn(QuotaResponse.ok());
- expect(quotaEnforcerB.requestTokens("testGroup", ctx, 1)).andThrow(new NullPointerException());
- quotaEnforcerA.refill("testGroup", ctx, 1);
+ expect(quotaEnforcerA.requestTokens("testGroup", ctx, 1)).andThrow(exception);
+ expect(quotaEnforcerB.requestTokens("testGroup", ctx, 1)).andReturn(QuotaResponse.ok());
+ quotaEnforcerB.refill("testGroup", ctx, 1);
expectLastCall();
replay(quotaEnforcerA);
replay(quotaEnforcerB);
- assertThat(quotaBackend.user(identifiedAdmin).requestToken("testGroup"))
- .isEqualTo(
- QuotaResponse.Aggregated.create(
- ImmutableList.of(
- QuotaResponse.ok(), QuotaResponse.error("failed to request quota tokens"))));
+ try {
+ quotaBackend.user(identifiedAdmin).requestToken("testGroup");
+ fail("expected a NullPointerException");
+ } catch (NullPointerException e) {
+ assertThat(exception).isEqualTo(e);
+ }
+
+ verify(quotaEnforcerA);
}
@Test
diff --git a/javatests/com/google/gerrit/elasticsearch/ElasticV5QueryAccountsTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticV5QueryAccountsTest.java
index c8ce54a..27868d2 100644
--- a/javatests/com/google/gerrit/elasticsearch/ElasticV5QueryAccountsTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticV5QueryAccountsTest.java
@@ -65,6 +65,6 @@
String indicesPrefix = getSanitizedMethodName();
ElasticTestUtils.configure(
elasticsearchConfig, nodeInfo.port, indicesPrefix, ElasticVersion.V5_6);
- return Guice.createInjector(new InMemoryModule(elasticsearchConfig, notesMigration));
+ return Guice.createInjector(new InMemoryModule(elasticsearchConfig));
}
}
diff --git a/javatests/com/google/gerrit/elasticsearch/ElasticV5QueryChangesTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticV5QueryChangesTest.java
index cfdfa98..2e4e22a 100644
--- a/javatests/com/google/gerrit/elasticsearch/ElasticV5QueryChangesTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticV5QueryChangesTest.java
@@ -65,6 +65,6 @@
String indicesPrefix = getSanitizedMethodName();
ElasticTestUtils.configure(
elasticsearchConfig, nodeInfo.port, indicesPrefix, ElasticVersion.V5_6);
- return Guice.createInjector(new InMemoryModule(elasticsearchConfig, notesMigration));
+ return Guice.createInjector(new InMemoryModule(elasticsearchConfig));
}
}
diff --git a/javatests/com/google/gerrit/elasticsearch/ElasticV5QueryGroupsTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticV5QueryGroupsTest.java
index 832a7bd..98c4321 100644
--- a/javatests/com/google/gerrit/elasticsearch/ElasticV5QueryGroupsTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticV5QueryGroupsTest.java
@@ -65,6 +65,6 @@
String indicesPrefix = getSanitizedMethodName();
ElasticTestUtils.configure(
elasticsearchConfig, nodeInfo.port, indicesPrefix, ElasticVersion.V5_6);
- return Guice.createInjector(new InMemoryModule(elasticsearchConfig, notesMigration));
+ return Guice.createInjector(new InMemoryModule(elasticsearchConfig));
}
}
diff --git a/javatests/com/google/gerrit/elasticsearch/ElasticV5QueryProjectsTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticV5QueryProjectsTest.java
index 29d3fa4..6b4b58c 100644
--- a/javatests/com/google/gerrit/elasticsearch/ElasticV5QueryProjectsTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticV5QueryProjectsTest.java
@@ -65,6 +65,6 @@
String indicesPrefix = getSanitizedMethodName();
ElasticTestUtils.configure(
elasticsearchConfig, nodeInfo.port, indicesPrefix, ElasticVersion.V5_6);
- return Guice.createInjector(new InMemoryModule(elasticsearchConfig, notesMigration));
+ return Guice.createInjector(new InMemoryModule(elasticsearchConfig));
}
}
diff --git a/javatests/com/google/gerrit/elasticsearch/ElasticV6QueryAccountsTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticV6QueryAccountsTest.java
index 8833907..53593ef 100644
--- a/javatests/com/google/gerrit/elasticsearch/ElasticV6QueryAccountsTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticV6QueryAccountsTest.java
@@ -64,6 +64,6 @@
InMemoryModule.setDefaults(elasticsearchConfig);
String indicesPrefix = getSanitizedMethodName();
ElasticTestUtils.configure(elasticsearchConfig, nodeInfo.port, indicesPrefix);
- return Guice.createInjector(new InMemoryModule(elasticsearchConfig, notesMigration));
+ return Guice.createInjector(new InMemoryModule(elasticsearchConfig));
}
}
diff --git a/javatests/com/google/gerrit/elasticsearch/ElasticV6QueryChangesTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticV6QueryChangesTest.java
index 8ba753c..6429431 100644
--- a/javatests/com/google/gerrit/elasticsearch/ElasticV6QueryChangesTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticV6QueryChangesTest.java
@@ -64,6 +64,6 @@
InMemoryModule.setDefaults(elasticsearchConfig);
String indicesPrefix = getSanitizedMethodName();
ElasticTestUtils.configure(elasticsearchConfig, nodeInfo.port, indicesPrefix);
- return Guice.createInjector(new InMemoryModule(elasticsearchConfig, notesMigration));
+ return Guice.createInjector(new InMemoryModule(elasticsearchConfig));
}
}
diff --git a/javatests/com/google/gerrit/elasticsearch/ElasticV6QueryGroupsTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticV6QueryGroupsTest.java
index cecb085..de0af97 100644
--- a/javatests/com/google/gerrit/elasticsearch/ElasticV6QueryGroupsTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticV6QueryGroupsTest.java
@@ -64,6 +64,6 @@
InMemoryModule.setDefaults(elasticsearchConfig);
String indicesPrefix = getSanitizedMethodName();
ElasticTestUtils.configure(elasticsearchConfig, nodeInfo.port, indicesPrefix);
- return Guice.createInjector(new InMemoryModule(elasticsearchConfig, notesMigration));
+ return Guice.createInjector(new InMemoryModule(elasticsearchConfig));
}
}
diff --git a/javatests/com/google/gerrit/elasticsearch/ElasticV6QueryProjectsTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticV6QueryProjectsTest.java
index 47e9b10..0ce66e8 100644
--- a/javatests/com/google/gerrit/elasticsearch/ElasticV6QueryProjectsTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticV6QueryProjectsTest.java
@@ -64,6 +64,6 @@
InMemoryModule.setDefaults(elasticsearchConfig);
String indicesPrefix = getSanitizedMethodName();
ElasticTestUtils.configure(elasticsearchConfig, nodeInfo.port, indicesPrefix);
- return Guice.createInjector(new InMemoryModule(elasticsearchConfig, notesMigration));
+ return Guice.createInjector(new InMemoryModule(elasticsearchConfig));
}
}
diff --git a/javatests/com/google/gerrit/elasticsearch/ElasticV7QueryAccountsTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticV7QueryAccountsTest.java
index bddbbc9..6972a18 100644
--- a/javatests/com/google/gerrit/elasticsearch/ElasticV7QueryAccountsTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticV7QueryAccountsTest.java
@@ -64,6 +64,6 @@
InMemoryModule.setDefaults(elasticsearchConfig);
String indicesPrefix = getSanitizedMethodName();
ElasticTestUtils.configure(elasticsearchConfig, nodeInfo.port, indicesPrefix);
- return Guice.createInjector(new InMemoryModule(elasticsearchConfig, notesMigration));
+ return Guice.createInjector(new InMemoryModule(elasticsearchConfig));
}
}
diff --git a/javatests/com/google/gerrit/elasticsearch/ElasticV7QueryChangesTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticV7QueryChangesTest.java
index 5dcf159..988abca 100644
--- a/javatests/com/google/gerrit/elasticsearch/ElasticV7QueryChangesTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticV7QueryChangesTest.java
@@ -82,6 +82,6 @@
InMemoryModule.setDefaults(elasticsearchConfig);
String indicesPrefix = getSanitizedMethodName();
ElasticTestUtils.configure(elasticsearchConfig, nodeInfo.port, indicesPrefix);
- return Guice.createInjector(new InMemoryModule(elasticsearchConfig, notesMigration));
+ return Guice.createInjector(new InMemoryModule(elasticsearchConfig));
}
}
diff --git a/javatests/com/google/gerrit/elasticsearch/ElasticV7QueryGroupsTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticV7QueryGroupsTest.java
index 54be7b9..534bc36 100644
--- a/javatests/com/google/gerrit/elasticsearch/ElasticV7QueryGroupsTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticV7QueryGroupsTest.java
@@ -64,6 +64,6 @@
InMemoryModule.setDefaults(elasticsearchConfig);
String indicesPrefix = getSanitizedMethodName();
ElasticTestUtils.configure(elasticsearchConfig, nodeInfo.port, indicesPrefix);
- return Guice.createInjector(new InMemoryModule(elasticsearchConfig, notesMigration));
+ return Guice.createInjector(new InMemoryModule(elasticsearchConfig));
}
}
diff --git a/javatests/com/google/gerrit/elasticsearch/ElasticV7QueryProjectsTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticV7QueryProjectsTest.java
index e8b4a2c..1f4653c 100644
--- a/javatests/com/google/gerrit/elasticsearch/ElasticV7QueryProjectsTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticV7QueryProjectsTest.java
@@ -64,6 +64,6 @@
InMemoryModule.setDefaults(elasticsearchConfig);
String indicesPrefix = getSanitizedMethodName();
ElasticTestUtils.configure(elasticsearchConfig, nodeInfo.port, indicesPrefix);
- return Guice.createInjector(new InMemoryModule(elasticsearchConfig, notesMigration));
+ return Guice.createInjector(new InMemoryModule(elasticsearchConfig));
}
}
diff --git a/javatests/com/google/gerrit/gpg/GerritPublicKeyCheckerTest.java b/javatests/com/google/gerrit/gpg/GerritPublicKeyCheckerTest.java
index d5add7d..e5578e1 100644
--- a/javatests/com/google/gerrit/gpg/GerritPublicKeyCheckerTest.java
+++ b/javatests/com/google/gerrit/gpg/GerritPublicKeyCheckerTest.java
@@ -47,7 +47,6 @@
import com.google.gerrit.testing.GerritBaseTests;
import com.google.gerrit.testing.InMemoryDatabase;
import com.google.gerrit.testing.InMemoryModule;
-import com.google.gerrit.testing.NoteDbMode;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
@@ -103,8 +102,7 @@
ImmutableList.of(
Fingerprint.toString(keyB().getPublicKey().getFingerprint()),
Fingerprint.toString(keyD().getPublicKey().getFingerprint())));
- Injector injector =
- Guice.createInjector(new InMemoryModule(cfg, NoteDbMode.newNotesMigrationFromEnv()));
+ Injector injector = Guice.createInjector(new InMemoryModule(cfg));
lifecycle = new LifecycleManager();
lifecycle.add(injector);
diff --git a/javatests/com/google/gerrit/mail/AbstractParserTest.java b/javatests/com/google/gerrit/mail/AbstractParserTest.java
index c375aff..bcff6a7 100644
--- a/javatests/com/google/gerrit/mail/AbstractParserTest.java
+++ b/javatests/com/google/gerrit/mail/AbstractParserTest.java
@@ -41,7 +41,7 @@
String message, MailComment comment, Comment inReplyTo) {
assertThat(comment.fileName).isNull();
assertThat(comment.message).isEqualTo(message);
- assertThat(comment.inReplyTo).isEqualTo(inReplyTo);
+ assertThat(comment.inReplyTo.key).isEqualTo(inReplyTo.key);
assertThat(comment.type).isEqualTo(MailComment.CommentType.INLINE_COMMENT);
}
diff --git a/javatests/com/google/gerrit/proto/BUILD b/javatests/com/google/gerrit/proto/BUILD
index a249638..c7d3aca 100644
--- a/javatests/com/google/gerrit/proto/BUILD
+++ b/javatests/com/google/gerrit/proto/BUILD
@@ -4,15 +4,13 @@
name = "proto_tests",
srcs = glob(["*.java"]),
deps = [
+ "//java/com/google/gerrit/proto",
"//java/com/google/gerrit/testing:gerrit-test-util",
- "//lib/truth:truth-proto-extension",
- "//proto:reviewdb_java_proto",
-
- # TODO(dborowitz): These are already runtime_deps of
- # truth-proto-extension, but either omitting them or adding them as
- # runtime_deps to this target fails with:
- # class file for com.google.common.collect.Multimap not found
"//lib:guava",
+ "//lib:protobuf",
"//lib/truth",
+ "//lib/truth:truth-proto-extension",
+ "//proto:cache_java_proto",
+ "//proto:reviewdb_java_proto",
],
)
diff --git a/javatests/com/google/gerrit/proto/ProtosTest.java b/javatests/com/google/gerrit/proto/ProtosTest.java
new file mode 100644
index 0000000..29e8fe0
--- /dev/null
+++ b/javatests/com/google/gerrit/proto/ProtosTest.java
@@ -0,0 +1,156 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.proto;
+
+import static com.google.common.truth.Truth.assert_;
+import static com.google.common.truth.extensions.proto.ProtoTruth.assertThat;
+
+import com.google.gerrit.server.cache.proto.Cache.ChangeNotesKeyProto;
+import com.google.gerrit.server.cache.proto.Cache.ChangeNotesStateProto;
+import com.google.gerrit.testing.GerritBaseTests;
+import com.google.protobuf.ByteString;
+import java.util.Arrays;
+import org.junit.Test;
+
+public class ProtosTest extends GerritBaseTests {
+ @Test
+ public void parseUncheckedByteArrayWrongProtoType() {
+ ChangeNotesKeyProto proto =
+ ChangeNotesKeyProto.newBuilder()
+ .setProject("project")
+ .setChangeId(1234)
+ .setId(ByteString.copyFromUtf8("foo"))
+ .build();
+ byte[] bytes = Protos.toByteArray(proto);
+ try {
+ Protos.parseUnchecked(ChangeNotesStateProto.parser(), bytes);
+ assert_().fail("expected IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+ }
+
+ @Test
+ public void parseUncheckedByteArrayInvalidData() {
+ byte[] bytes = new byte[] {0x00};
+ try {
+ Protos.parseUnchecked(ChangeNotesStateProto.parser(), bytes);
+ assert_().fail("expected IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+ }
+
+ @Test
+ public void parseUncheckedByteArray() {
+ ChangeNotesKeyProto proto =
+ ChangeNotesKeyProto.newBuilder()
+ .setProject("project")
+ .setChangeId(1234)
+ .setId(ByteString.copyFromUtf8("foo"))
+ .build();
+ byte[] bytes = Protos.toByteArray(proto);
+ assertThat(Protos.parseUnchecked(ChangeNotesKeyProto.parser(), bytes)).isEqualTo(proto);
+ }
+
+ @Test
+ public void parseUncheckedSegmentOfByteArrayWrongProtoType() {
+ ChangeNotesKeyProto proto =
+ ChangeNotesKeyProto.newBuilder()
+ .setProject("project")
+ .setChangeId(1234)
+ .setId(ByteString.copyFromUtf8("foo"))
+ .build();
+ byte[] bytes = Protos.toByteArray(proto);
+ try {
+ Protos.parseUnchecked(ChangeNotesStateProto.parser(), bytes, 0, bytes.length);
+ assert_().fail("expected IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+ }
+
+ @Test
+ public void parseUncheckedSegmentOfByteArrayInvalidData() {
+ byte[] bytes = new byte[] {0x00};
+ try {
+ Protos.parseUnchecked(ChangeNotesStateProto.parser(), bytes, 0, bytes.length);
+ assert_().fail("expected IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+ }
+
+ @Test
+ public void parseUncheckedSegmentOfByteArray() {
+ ChangeNotesKeyProto proto =
+ ChangeNotesKeyProto.newBuilder()
+ .setProject("project")
+ .setChangeId(1234)
+ .setId(ByteString.copyFromUtf8("foo"))
+ .build();
+ byte[] protoBytes = Protos.toByteArray(proto);
+ int offset = 3;
+ int length = protoBytes.length;
+ byte[] bytes = new byte[length + 20];
+ Arrays.fill(bytes, (byte) 1);
+ System.arraycopy(protoBytes, 0, bytes, offset, length);
+
+ ChangeNotesKeyProto parsedProto =
+ Protos.parseUnchecked(ChangeNotesKeyProto.parser(), bytes, offset, length);
+
+ assertThat(parsedProto).isEqualTo(proto);
+ }
+
+ @Test
+ public void parseUncheckedByteStringWrongProtoType() {
+ ChangeNotesKeyProto proto =
+ ChangeNotesKeyProto.newBuilder()
+ .setProject("project")
+ .setChangeId(1234)
+ .setId(ByteString.copyFromUtf8("foo"))
+ .build();
+ ByteString byteString = Protos.toByteString(proto);
+ try {
+ Protos.parseUnchecked(ChangeNotesStateProto.parser(), byteString);
+ assert_().fail("expected IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+ }
+
+ @Test
+ public void parseUncheckedByteStringInvalidData() {
+ ByteString byteString = ByteString.copyFrom(new byte[] {0x00});
+ try {
+ Protos.parseUnchecked(ChangeNotesStateProto.parser(), byteString);
+ assert_().fail("expected IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+ }
+
+ @Test
+ public void parseUncheckedByteString() {
+ ChangeNotesKeyProto proto =
+ ChangeNotesKeyProto.newBuilder()
+ .setProject("project")
+ .setChangeId(1234)
+ .setId(ByteString.copyFromUtf8("foo"))
+ .build();
+ ByteString byteString = Protos.toByteString(proto);
+ assertThat(Protos.parseUnchecked(ChangeNotesKeyProto.parser(), byteString)).isEqualTo(proto);
+ }
+}
diff --git a/javatests/com/google/gerrit/reviewdb/converter/AccountIdProtoConverterTest.java b/javatests/com/google/gerrit/reviewdb/converter/AccountIdProtoConverterTest.java
new file mode 100644
index 0000000..38d4195
--- /dev/null
+++ b/javatests/com/google/gerrit/reviewdb/converter/AccountIdProtoConverterTest.java
@@ -0,0 +1,67 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.reviewdb.converter;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.extensions.proto.ProtoTruth.assertThat;
+import static com.google.gerrit.proto.testing.SerializedClassSubject.assertThatSerializedClass;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.gerrit.proto.reviewdb.Reviewdb;
+import com.google.gerrit.proto.testing.SerializedClassSubject;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.protobuf.Parser;
+import org.junit.Test;
+
+public class AccountIdProtoConverterTest {
+ private final AccountIdProtoConverter accountIdProtoConverter = AccountIdProtoConverter.INSTANCE;
+
+ @Test
+ public void allValuesConvertedToProto() {
+ Account.Id accountId = new Account.Id(24);
+
+ Reviewdb.Account_Id proto = accountIdProtoConverter.toProto(accountId);
+
+ Reviewdb.Account_Id expectedProto = Reviewdb.Account_Id.newBuilder().setId(24).build();
+ assertThat(proto).isEqualTo(expectedProto);
+ }
+
+ @Test
+ public void allValuesConvertedToProtoAndBackAgain() {
+ Account.Id accountId = new Account.Id(34832);
+
+ Account.Id convertedAccountId =
+ accountIdProtoConverter.fromProto(accountIdProtoConverter.toProto(accountId));
+
+ assertThat(convertedAccountId).isEqualTo(accountId);
+ }
+
+ @Test
+ public void protoCanBeParsedFromBytes() throws Exception {
+ Reviewdb.Account_Id proto = Reviewdb.Account_Id.newBuilder().setId(24).build();
+ byte[] bytes = proto.toByteArray();
+
+ Parser<Reviewdb.Account_Id> parser = accountIdProtoConverter.getParser();
+ Reviewdb.Account_Id parsedProto = parser.parseFrom(bytes);
+
+ assertThat(parsedProto).isEqualTo(proto);
+ }
+
+ /** See {@link SerializedClassSubject} for background and what to do if this test fails. */
+ @Test
+ public void fieldsExistAsExpected() {
+ assertThatSerializedClass(Account.Id.class).hasFields(ImmutableMap.of("id", int.class));
+ }
+}
diff --git a/javatests/com/google/gerrit/reviewdb/converter/BUILD b/javatests/com/google/gerrit/reviewdb/converter/BUILD
new file mode 100644
index 0000000..7c15910
--- /dev/null
+++ b/javatests/com/google/gerrit/reviewdb/converter/BUILD
@@ -0,0 +1,33 @@
+load("//tools/bzl:junit.bzl", "junit_tests")
+
+COMPATIBLITY_TEST_SRCS = glob(["*CompatibilityTest.java"])
+
+junit_tests(
+ name = "proto_converter_tests",
+ srcs = glob(
+ ["*.java"],
+ exclude = COMPATIBLITY_TEST_SRCS,
+ ),
+ deps = [
+ "//java/com/google/gerrit/proto/testing",
+ "//java/com/google/gerrit/reviewdb:server",
+ "//lib:guava",
+ "//lib:protobuf",
+ "//lib/truth",
+ "//lib/truth:truth-proto-extension",
+ "//proto:reviewdb_java_proto",
+ ],
+)
+
+junit_tests(
+ name = "compatibility_tests",
+ srcs = COMPATIBLITY_TEST_SRCS,
+ deps = [
+ "//java/com/google/gerrit/proto",
+ "//java/com/google/gerrit/reviewdb:server",
+ "//lib:guava",
+ "//lib:gwtorm-client",
+ "//lib:protobuf",
+ "//lib/truth",
+ ],
+)
diff --git a/javatests/com/google/gerrit/reviewdb/converter/ChangeIdProtoConverterTest.java b/javatests/com/google/gerrit/reviewdb/converter/ChangeIdProtoConverterTest.java
new file mode 100644
index 0000000..d5f055b
--- /dev/null
+++ b/javatests/com/google/gerrit/reviewdb/converter/ChangeIdProtoConverterTest.java
@@ -0,0 +1,67 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.reviewdb.converter;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.extensions.proto.ProtoTruth.assertThat;
+import static com.google.gerrit.proto.testing.SerializedClassSubject.assertThatSerializedClass;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.gerrit.proto.reviewdb.Reviewdb;
+import com.google.gerrit.proto.testing.SerializedClassSubject;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.protobuf.Parser;
+import org.junit.Test;
+
+public class ChangeIdProtoConverterTest {
+ private final ChangeIdProtoConverter changeIdProtoConverter = ChangeIdProtoConverter.INSTANCE;
+
+ @Test
+ public void allValuesConvertedToProto() {
+ Change.Id changeId = new Change.Id(94);
+
+ Reviewdb.Change_Id proto = changeIdProtoConverter.toProto(changeId);
+
+ Reviewdb.Change_Id expectedProto = Reviewdb.Change_Id.newBuilder().setId(94).build();
+ assertThat(proto).isEqualTo(expectedProto);
+ }
+
+ @Test
+ public void allValuesConvertedToProtoAndBackAgain() {
+ Change.Id changeId = new Change.Id(2903482);
+
+ Change.Id convertedChangeId =
+ changeIdProtoConverter.fromProto(changeIdProtoConverter.toProto(changeId));
+
+ assertThat(convertedChangeId).isEqualTo(changeId);
+ }
+
+ @Test
+ public void protoCanBeParsedFromBytes() throws Exception {
+ Reviewdb.Change_Id proto = Reviewdb.Change_Id.newBuilder().setId(94).build();
+ byte[] bytes = proto.toByteArray();
+
+ Parser<Reviewdb.Change_Id> parser = changeIdProtoConverter.getParser();
+ Reviewdb.Change_Id parsedProto = parser.parseFrom(bytes);
+
+ assertThat(parsedProto).isEqualTo(proto);
+ }
+
+ /** See {@link SerializedClassSubject} for background and what to do if this test fails. */
+ @Test
+ public void fieldsExistAsExpected() {
+ assertThatSerializedClass(Change.Id.class).hasFields(ImmutableMap.of("id", int.class));
+ }
+}
diff --git a/javatests/com/google/gerrit/reviewdb/converter/ChangeMessageConverterCompatibilityTest.java b/javatests/com/google/gerrit/reviewdb/converter/ChangeMessageConverterCompatibilityTest.java
new file mode 100644
index 0000000..a194ec6
--- /dev/null
+++ b/javatests/com/google/gerrit/reviewdb/converter/ChangeMessageConverterCompatibilityTest.java
@@ -0,0 +1,195 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.reviewdb.converter;
+
+import static com.google.common.collect.ImmutableList.toImmutableList;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.gerrit.proto.Protos;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.ChangeMessage;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gwtorm.protobuf.CodecFactory;
+import com.google.gwtorm.protobuf.ProtobufCodec;
+import com.google.gwtorm.server.OrmException;
+import com.google.protobuf.ByteString;
+import com.google.protobuf.CodedOutputStream;
+import com.google.protobuf.MessageLite;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.sql.Timestamp;
+import java.util.Collection;
+import java.util.List;
+import org.junit.Test;
+
+// TODO(aliceks): Delete after proving binary compatibility.
+public class ChangeMessageConverterCompatibilityTest {
+
+ private final ProtobufCodec<ChangeMessage> changeMessageCodec =
+ CodecFactory.encoder(ChangeMessage.class);
+ private final ChangeMessageProtoConverter changeMessageProtoConverter =
+ ChangeMessageProtoConverter.INSTANCE;
+
+ @Test
+ public void changeIndexFieldWithAllValuesIsBinaryCompatible() throws Exception {
+ ChangeMessage changeMessage =
+ new ChangeMessage(
+ new ChangeMessage.Key(new Change.Id(543), "change-message-21"),
+ new Account.Id(63),
+ new Timestamp(9876543),
+ new PatchSet.Id(new Change.Id(34), 13));
+ changeMessage.setMessage("This is a change message.");
+ changeMessage.setTag("An arbitrary tag.");
+ changeMessage.setRealAuthor(new Account.Id(10003));
+ ImmutableList<ChangeMessage> changeMessages = ImmutableList.of(changeMessage);
+
+ byte[] resultOfOldConverter =
+ getOnlyElement(convertToProtos_old(changeMessageCodec, changeMessages));
+ byte[] resultOfNewConverter =
+ getOnlyElement(convertToProtos_new(changeMessageProtoConverter, changeMessages));
+
+ assertThat(resultOfNewConverter).isEqualTo(resultOfOldConverter);
+ }
+
+ @Test
+ public void changeIndexFieldWithMandatoryValuesIsBinaryCompatible() throws Exception {
+ ChangeMessage changeMessage =
+ new ChangeMessage(
+ new ChangeMessage.Key(new Change.Id(543), "change-message-21"), null, null, null);
+ ImmutableList<ChangeMessage> changeMessages = ImmutableList.of(changeMessage);
+
+ byte[] resultOfOldConverter =
+ getOnlyElement(convertToProtos_old(changeMessageCodec, changeMessages));
+ byte[] resultOfNewConverter =
+ getOnlyElement(convertToProtos_new(changeMessageProtoConverter, changeMessages));
+
+ assertThat(resultOfNewConverter).isEqualTo(resultOfOldConverter);
+ }
+
+ @Test
+ public void changeNotesFieldWithAllValuesIsBinaryCompatible() {
+ ChangeMessage changeMessage =
+ new ChangeMessage(
+ new ChangeMessage.Key(new Change.Id(543), "change-message-21"),
+ new Account.Id(63),
+ new Timestamp(9876543),
+ new PatchSet.Id(new Change.Id(34), 13));
+ changeMessage.setMessage("This is a change message.");
+ changeMessage.setTag("An arbitrary tag.");
+ changeMessage.setRealAuthor(new Account.Id(10003));
+
+ ByteString resultOfOldConverter = Protos.toByteString(changeMessage, changeMessageCodec);
+ ByteString resultOfNewConverter = toByteString(changeMessage, changeMessageProtoConverter);
+
+ assertThat(resultOfNewConverter).isEqualTo(resultOfOldConverter);
+ }
+
+ @Test
+ public void changeNotesFieldWithMainValuesIsBinaryCompatible() {
+ ChangeMessage changeMessage =
+ new ChangeMessage(
+ new ChangeMessage.Key(new Change.Id(543), "change-message-21"),
+ new Account.Id(63),
+ new Timestamp(9876543),
+ new PatchSet.Id(new Change.Id(34), 13));
+
+ ByteString resultOfOldConverter = Protos.toByteString(changeMessage, changeMessageCodec);
+ ByteString resultOfNewConverter = toByteString(changeMessage, changeMessageProtoConverter);
+
+ assertThat(resultOfNewConverter).isEqualTo(resultOfOldConverter);
+ }
+
+ @Test
+ public void changeNotesFieldWithoutRealAuthorButAuthorIsBinaryCompatible() {
+ ChangeMessage changeMessage =
+ new ChangeMessage(
+ new ChangeMessage.Key(new Change.Id(543), "change-message-21"),
+ new Account.Id(63),
+ null,
+ null);
+
+ ByteString resultOfOldConverter = Protos.toByteString(changeMessage, changeMessageCodec);
+ ByteString resultOfNewConverter = toByteString(changeMessage, changeMessageProtoConverter);
+
+ assertThat(resultOfNewConverter).isEqualTo(resultOfOldConverter);
+ }
+
+ @Test
+ public void changeNotesFieldWithoutSameRealAuthorAndAuthorIsBinaryCompatible() {
+ ChangeMessage changeMessage =
+ new ChangeMessage(
+ new ChangeMessage.Key(new Change.Id(543), "change-message-21"),
+ new Account.Id(63),
+ null,
+ null);
+ changeMessage.setRealAuthor(new Account.Id(63));
+
+ ByteString resultOfOldConverter = Protos.toByteString(changeMessage, changeMessageCodec);
+ ByteString resultOfNewConverter = toByteString(changeMessage, changeMessageProtoConverter);
+
+ assertThat(resultOfNewConverter).isEqualTo(resultOfOldConverter);
+ }
+
+ @Test
+ public void changeNotesFieldWithMandatoryValuesIsBinaryCompatible() {
+ ChangeMessage changeMessage =
+ new ChangeMessage(
+ new ChangeMessage.Key(new Change.Id(543), "change-message-21"), null, null, null);
+
+ ByteString resultOfOldConverter = Protos.toByteString(changeMessage, changeMessageCodec);
+ ByteString resultOfNewConverter = toByteString(changeMessage, changeMessageProtoConverter);
+
+ assertThat(resultOfNewConverter).isEqualTo(resultOfOldConverter);
+ }
+
+ // Copied from ChangeField.
+ private static <T> List<byte[]> convertToProtos_old(ProtobufCodec<T> codec, Collection<T> objs)
+ throws OrmException {
+ List<byte[]> result = Lists.newArrayListWithCapacity(objs.size());
+ ByteArrayOutputStream out = new ByteArrayOutputStream(256);
+ try {
+ for (T obj : objs) {
+ out.reset();
+ CodedOutputStream cos = CodedOutputStream.newInstance(out);
+ codec.encode(obj, cos);
+ cos.flush();
+ result.add(out.toByteArray());
+ }
+ } catch (IOException e) {
+ throw new OrmException(e);
+ }
+ return result;
+ }
+
+ // Copied from ChangeField.
+ private static <T> List<byte[]> convertToProtos_new(
+ ProtoConverter<?, T> converter, Collection<T> objects) {
+ return objects
+ .stream()
+ .map(converter::toProto)
+ .map(Protos::toByteArray)
+ .collect(toImmutableList());
+ }
+
+ // Copied from ChangeNotesState.Serializer.
+ private static <T> ByteString toByteString(T object, ProtoConverter<?, T> converter) {
+ MessageLite message = converter.toProto(object);
+ return Protos.toByteString(message);
+ }
+}
diff --git a/javatests/com/google/gerrit/reviewdb/converter/ChangeMessageKeyProtoConverterTest.java b/javatests/com/google/gerrit/reviewdb/converter/ChangeMessageKeyProtoConverterTest.java
new file mode 100644
index 0000000..9874737
--- /dev/null
+++ b/javatests/com/google/gerrit/reviewdb/converter/ChangeMessageKeyProtoConverterTest.java
@@ -0,0 +1,83 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.reviewdb.converter;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.extensions.proto.ProtoTruth.assertThat;
+import static com.google.gerrit.proto.testing.SerializedClassSubject.assertThatSerializedClass;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.gerrit.proto.reviewdb.Reviewdb;
+import com.google.gerrit.proto.testing.SerializedClassSubject;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.ChangeMessage;
+import com.google.protobuf.Parser;
+import java.lang.reflect.Type;
+import org.junit.Test;
+
+public class ChangeMessageKeyProtoConverterTest {
+ private final ChangeMessageKeyProtoConverter messageKeyProtoConverter =
+ ChangeMessageKeyProtoConverter.INSTANCE;
+
+ @Test
+ public void allValuesConvertedToProto() {
+ ChangeMessage.Key messageKey = new ChangeMessage.Key(new Change.Id(704), "aabbcc");
+
+ Reviewdb.ChangeMessage_Key proto = messageKeyProtoConverter.toProto(messageKey);
+
+ Reviewdb.ChangeMessage_Key expectedProto =
+ Reviewdb.ChangeMessage_Key.newBuilder()
+ .setChangeId(Reviewdb.Change_Id.newBuilder().setId(704))
+ .setUuid("aabbcc")
+ .build();
+ assertThat(proto).isEqualTo(expectedProto);
+ }
+
+ @Test
+ public void allValuesConvertedToProtoAndBackAgain() {
+ ChangeMessage.Key messageKey = new ChangeMessage.Key(new Change.Id(704), "aabbcc");
+
+ ChangeMessage.Key convertedMessageKey =
+ messageKeyProtoConverter.fromProto(messageKeyProtoConverter.toProto(messageKey));
+
+ assertThat(convertedMessageKey).isEqualTo(messageKey);
+ }
+
+ @Test
+ public void protoCanBeParsedFromBytes() throws Exception {
+ Reviewdb.ChangeMessage_Key proto =
+ Reviewdb.ChangeMessage_Key.newBuilder()
+ .setChangeId(Reviewdb.Change_Id.newBuilder().setId(704))
+ .setUuid("aabbcc")
+ .build();
+ byte[] bytes = proto.toByteArray();
+
+ Parser<Reviewdb.ChangeMessage_Key> parser = messageKeyProtoConverter.getParser();
+ Reviewdb.ChangeMessage_Key parsedProto = parser.parseFrom(bytes);
+
+ assertThat(parsedProto).isEqualTo(proto);
+ }
+
+ /** See {@link SerializedClassSubject} for background and what to do if this test fails. */
+ @Test
+ public void fieldsExistAsExpected() {
+ assertThatSerializedClass(ChangeMessage.Key.class)
+ .hasFields(
+ ImmutableMap.<String, Type>builder()
+ .put("changeId", Change.Id.class)
+ .put("uuid", String.class)
+ .build());
+ }
+}
diff --git a/javatests/com/google/gerrit/reviewdb/converter/ChangeMessageProtoConverterTest.java b/javatests/com/google/gerrit/reviewdb/converter/ChangeMessageProtoConverterTest.java
new file mode 100644
index 0000000..f478deb
--- /dev/null
+++ b/javatests/com/google/gerrit/reviewdb/converter/ChangeMessageProtoConverterTest.java
@@ -0,0 +1,214 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.reviewdb.converter;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.extensions.proto.ProtoTruth.assertThat;
+import static com.google.gerrit.proto.testing.SerializedClassSubject.assertThatSerializedClass;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.gerrit.proto.reviewdb.Reviewdb;
+import com.google.gerrit.proto.testing.SerializedClassSubject;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.ChangeMessage;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.protobuf.Parser;
+import java.lang.reflect.Type;
+import java.sql.Timestamp;
+import org.junit.Test;
+
+public class ChangeMessageProtoConverterTest {
+ private final ChangeMessageProtoConverter changeMessageProtoConverter =
+ ChangeMessageProtoConverter.INSTANCE;
+
+ @Test
+ public void allValuesConvertedToProto() {
+ ChangeMessage changeMessage =
+ new ChangeMessage(
+ new ChangeMessage.Key(new Change.Id(543), "change-message-21"),
+ new Account.Id(63),
+ new Timestamp(9876543),
+ new PatchSet.Id(new Change.Id(34), 13));
+ changeMessage.setMessage("This is a change message.");
+ changeMessage.setTag("An arbitrary tag.");
+ changeMessage.setRealAuthor(new Account.Id(10003));
+
+ Reviewdb.ChangeMessage proto = changeMessageProtoConverter.toProto(changeMessage);
+
+ Reviewdb.ChangeMessage expectedProto =
+ Reviewdb.ChangeMessage.newBuilder()
+ .setKey(
+ Reviewdb.ChangeMessage_Key.newBuilder()
+ .setChangeId(Reviewdb.Change_Id.newBuilder().setId(543))
+ .setUuid("change-message-21"))
+ .setAuthorId(Reviewdb.Account_Id.newBuilder().setId(63))
+ .setWrittenOn(9876543)
+ .setMessage("This is a change message.")
+ .setPatchset(
+ Reviewdb.PatchSet_Id.newBuilder()
+ .setChangeId(Reviewdb.Change_Id.newBuilder().setId(34))
+ .setPatchSetId(13))
+ .setTag("An arbitrary tag.")
+ .setRealAuthor(Reviewdb.Account_Id.newBuilder().setId(10003))
+ .build();
+ assertThat(proto).isEqualTo(expectedProto);
+ }
+
+ @Test
+ public void mainValuesConvertedToProto() {
+ ChangeMessage changeMessage =
+ new ChangeMessage(
+ new ChangeMessage.Key(new Change.Id(543), "change-message-21"),
+ new Account.Id(63),
+ new Timestamp(9876543),
+ new PatchSet.Id(new Change.Id(34), 13));
+
+ Reviewdb.ChangeMessage proto = changeMessageProtoConverter.toProto(changeMessage);
+
+ Reviewdb.ChangeMessage expectedProto =
+ Reviewdb.ChangeMessage.newBuilder()
+ .setKey(
+ Reviewdb.ChangeMessage_Key.newBuilder()
+ .setChangeId(Reviewdb.Change_Id.newBuilder().setId(543))
+ .setUuid("change-message-21"))
+ .setAuthorId(Reviewdb.Account_Id.newBuilder().setId(63))
+ .setWrittenOn(9876543)
+ .setPatchset(
+ Reviewdb.PatchSet_Id.newBuilder()
+ .setChangeId(Reviewdb.Change_Id.newBuilder().setId(34))
+ .setPatchSetId(13))
+ .build();
+ assertThat(proto).isEqualTo(expectedProto);
+ }
+
+ // This test documents a special behavior which is necessary to ensure binary compatibility.
+ @Test
+ public void realAuthorIsNotAutomaticallySetToAuthorWhenConvertedToProto() {
+ ChangeMessage changeMessage =
+ new ChangeMessage(
+ new ChangeMessage.Key(new Change.Id(543), "change-message-21"),
+ new Account.Id(63),
+ null,
+ null);
+
+ Reviewdb.ChangeMessage proto = changeMessageProtoConverter.toProto(changeMessage);
+
+ Reviewdb.ChangeMessage expectedProto =
+ Reviewdb.ChangeMessage.newBuilder()
+ .setKey(
+ Reviewdb.ChangeMessage_Key.newBuilder()
+ .setChangeId(Reviewdb.Change_Id.newBuilder().setId(543))
+ .setUuid("change-message-21"))
+ .setAuthorId(Reviewdb.Account_Id.newBuilder().setId(63))
+ .build();
+ assertThat(proto).isEqualTo(expectedProto);
+ }
+
+ @Test
+ public void mandatoryValuesConvertedToProto() {
+ // writtenOn may not be null according to the column definition but it's optional for the
+ // protobuf definition. -> assume as optional and hence test null
+ ChangeMessage changeMessage =
+ new ChangeMessage(
+ new ChangeMessage.Key(new Change.Id(543), "change-message-21"), null, null, null);
+
+ Reviewdb.ChangeMessage proto = changeMessageProtoConverter.toProto(changeMessage);
+
+ Reviewdb.ChangeMessage expectedProto =
+ Reviewdb.ChangeMessage.newBuilder()
+ .setKey(
+ Reviewdb.ChangeMessage_Key.newBuilder()
+ .setChangeId(Reviewdb.Change_Id.newBuilder().setId(543))
+ .setUuid("change-message-21"))
+ .build();
+ assertThat(proto).isEqualTo(expectedProto);
+ }
+
+ @Test
+ public void allValuesConvertedToProtoAndBackAgain() {
+ ChangeMessage changeMessage =
+ new ChangeMessage(
+ new ChangeMessage.Key(new Change.Id(543), "change-message-21"),
+ new Account.Id(63),
+ new Timestamp(9876543),
+ new PatchSet.Id(new Change.Id(34), 13));
+ changeMessage.setMessage("This is a change message.");
+ changeMessage.setTag("An arbitrary tag.");
+ changeMessage.setRealAuthor(new Account.Id(10003));
+
+ ChangeMessage convertedChangeMessage =
+ changeMessageProtoConverter.fromProto(changeMessageProtoConverter.toProto(changeMessage));
+ assertThat(convertedChangeMessage).isEqualTo(changeMessage);
+ }
+
+ @Test
+ public void mainValuesConvertedToProtoAndBackAgain() {
+ ChangeMessage changeMessage =
+ new ChangeMessage(
+ new ChangeMessage.Key(new Change.Id(543), "change-message-21"),
+ new Account.Id(63),
+ new Timestamp(9876543),
+ new PatchSet.Id(new Change.Id(34), 13));
+
+ ChangeMessage convertedChangeMessage =
+ changeMessageProtoConverter.fromProto(changeMessageProtoConverter.toProto(changeMessage));
+ assertThat(convertedChangeMessage).isEqualTo(changeMessage);
+ }
+
+ @Test
+ public void mandatoryValuesConvertedToProtoAndBackAgain() {
+ ChangeMessage changeMessage =
+ new ChangeMessage(
+ new ChangeMessage.Key(new Change.Id(543), "change-message-21"), null, null, null);
+
+ ChangeMessage convertedChangeMessage =
+ changeMessageProtoConverter.fromProto(changeMessageProtoConverter.toProto(changeMessage));
+ assertThat(convertedChangeMessage).isEqualTo(changeMessage);
+ }
+
+ @Test
+ public void protoCanBeParsedFromBytes() throws Exception {
+ Reviewdb.ChangeMessage proto =
+ Reviewdb.ChangeMessage.newBuilder()
+ .setKey(
+ Reviewdb.ChangeMessage_Key.newBuilder()
+ .setChangeId(Reviewdb.Change_Id.newBuilder().setId(543))
+ .setUuid("change-message-21"))
+ .build();
+ byte[] bytes = proto.toByteArray();
+
+ Parser<Reviewdb.ChangeMessage> parser = changeMessageProtoConverter.getParser();
+ Reviewdb.ChangeMessage parsedProto = parser.parseFrom(bytes);
+
+ assertThat(parsedProto).isEqualTo(proto);
+ }
+
+ /** See {@link SerializedClassSubject} for background and what to do if this test fails. */
+ @Test
+ public void fieldsExistAsExpected() {
+ assertThatSerializedClass(ChangeMessage.class)
+ .hasFields(
+ ImmutableMap.<String, Type>builder()
+ .put("key", ChangeMessage.Key.class)
+ .put("author", Account.Id.class)
+ .put("writtenOn", Timestamp.class)
+ .put("message", String.class)
+ .put("patchset", PatchSet.Id.class)
+ .put("tag", String.class)
+ .put("realAuthor", Account.Id.class)
+ .build());
+ }
+}
diff --git a/javatests/com/google/gerrit/reviewdb/converter/LabelIdProtoConverterTest.java b/javatests/com/google/gerrit/reviewdb/converter/LabelIdProtoConverterTest.java
new file mode 100644
index 0000000..a6aebd2
--- /dev/null
+++ b/javatests/com/google/gerrit/reviewdb/converter/LabelIdProtoConverterTest.java
@@ -0,0 +1,67 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.reviewdb.converter;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.extensions.proto.ProtoTruth.assertThat;
+import static com.google.gerrit.proto.testing.SerializedClassSubject.assertThatSerializedClass;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.gerrit.proto.reviewdb.Reviewdb;
+import com.google.gerrit.proto.testing.SerializedClassSubject;
+import com.google.gerrit.reviewdb.client.LabelId;
+import com.google.protobuf.Parser;
+import org.junit.Test;
+
+public class LabelIdProtoConverterTest {
+ private final LabelIdProtoConverter labelIdProtoConverter = LabelIdProtoConverter.INSTANCE;
+
+ @Test
+ public void allValuesConvertedToProto() {
+ LabelId labelId = new LabelId("Label ID 42");
+
+ Reviewdb.LabelId proto = labelIdProtoConverter.toProto(labelId);
+
+ Reviewdb.LabelId expectedProto = Reviewdb.LabelId.newBuilder().setId("Label ID 42").build();
+ assertThat(proto).isEqualTo(expectedProto);
+ }
+
+ @Test
+ public void allValuesConvertedToProtoAndBackAgain() {
+ LabelId labelId = new LabelId("label-5");
+
+ LabelId convertedLabelId =
+ labelIdProtoConverter.fromProto(labelIdProtoConverter.toProto(labelId));
+
+ assertThat(convertedLabelId).isEqualTo(labelId);
+ }
+
+ @Test
+ public void protoCanBeParsedFromBytes() throws Exception {
+ Reviewdb.LabelId proto = Reviewdb.LabelId.newBuilder().setId("label-23").build();
+ byte[] bytes = proto.toByteArray();
+
+ Parser<Reviewdb.LabelId> parser = labelIdProtoConverter.getParser();
+ Reviewdb.LabelId parsedProto = parser.parseFrom(bytes);
+
+ assertThat(parsedProto).isEqualTo(proto);
+ }
+
+ /** See {@link SerializedClassSubject} for background and what to do if this test fails. */
+ @Test
+ public void fieldsExistAsExpected() {
+ assertThatSerializedClass(LabelId.class).hasFields(ImmutableMap.of("id", String.class));
+ }
+}
diff --git a/javatests/com/google/gerrit/reviewdb/converter/PatchSetApprovalConverterCompatibilityTest.java b/javatests/com/google/gerrit/reviewdb/converter/PatchSetApprovalConverterCompatibilityTest.java
new file mode 100644
index 0000000..9da37da
--- /dev/null
+++ b/javatests/com/google/gerrit/reviewdb/converter/PatchSetApprovalConverterCompatibilityTest.java
@@ -0,0 +1,166 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.reviewdb.converter;
+
+import static com.google.common.collect.ImmutableList.toImmutableList;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.gerrit.proto.Protos;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.LabelId;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
+import com.google.gwtorm.protobuf.CodecFactory;
+import com.google.gwtorm.protobuf.ProtobufCodec;
+import com.google.gwtorm.server.OrmException;
+import com.google.protobuf.ByteString;
+import com.google.protobuf.CodedOutputStream;
+import com.google.protobuf.MessageLite;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import org.junit.Test;
+
+// TODO(aliceks): Delete after proving binary compatibility.
+public class PatchSetApprovalConverterCompatibilityTest {
+
+ private final ProtobufCodec<PatchSetApproval> patchSetApprovalCodec =
+ CodecFactory.encoder(PatchSetApproval.class);
+ private final PatchSetApprovalProtoConverter patchSetApprovalProtoConverter =
+ PatchSetApprovalProtoConverter.INSTANCE;
+
+ @Test
+ public void changeIndexFieldWithAllValuesIsBinaryCompatible() throws Exception {
+ PatchSetApproval patchSetApproval =
+ new PatchSetApproval(
+ new PatchSetApproval.Key(
+ new PatchSet.Id(new Change.Id(42), 14),
+ new Account.Id(100013),
+ new LabelId("label-8")),
+ (short) 456,
+ new Date(987654L));
+ patchSetApproval.setTag("tag-21");
+ patchSetApproval.setRealAccountId(new Account.Id(612));
+ patchSetApproval.setPostSubmit(true);
+ ImmutableList<PatchSetApproval> patchSetApprovals = ImmutableList.of(patchSetApproval);
+
+ byte[] resultOfOldConverter =
+ getOnlyElement(convertToProtos_old(patchSetApprovalCodec, patchSetApprovals));
+ byte[] resultOfNewConverter =
+ getOnlyElement(convertToProtos_new(patchSetApprovalProtoConverter, patchSetApprovals));
+
+ assertThat(resultOfNewConverter).isEqualTo(resultOfOldConverter);
+ }
+
+ @Test
+ public void changeIndexFieldWithMandatoryValuesIsBinaryCompatible() throws Exception {
+ PatchSetApproval patchSetApproval =
+ new PatchSetApproval(
+ new PatchSetApproval.Key(
+ new PatchSet.Id(new Change.Id(42), 14),
+ new Account.Id(100013),
+ new LabelId("label-8")),
+ (short) 456,
+ new Date(987654L));
+ ImmutableList<PatchSetApproval> patchSetApprovals = ImmutableList.of(patchSetApproval);
+
+ byte[] resultOfOldConverter =
+ getOnlyElement(convertToProtos_old(patchSetApprovalCodec, patchSetApprovals));
+ byte[] resultOfNewConverter =
+ getOnlyElement(convertToProtos_new(patchSetApprovalProtoConverter, patchSetApprovals));
+
+ assertThat(resultOfNewConverter).isEqualTo(resultOfOldConverter);
+ }
+
+ @Test
+ public void changeNotesFieldWithAllValuesIsBinaryCompatible() {
+ PatchSetApproval patchSetApproval =
+ new PatchSetApproval(
+ new PatchSetApproval.Key(
+ new PatchSet.Id(new Change.Id(42), 14),
+ new Account.Id(100013),
+ new LabelId("label-8")),
+ (short) 456,
+ new Date(987654L));
+ patchSetApproval.setTag("tag-21");
+ patchSetApproval.setRealAccountId(new Account.Id(612));
+ patchSetApproval.setPostSubmit(true);
+
+ ByteString resultOfOldConverter = Protos.toByteString(patchSetApproval, patchSetApprovalCodec);
+ ByteString resultOfNewConverter =
+ toByteString(patchSetApproval, patchSetApprovalProtoConverter);
+
+ assertThat(resultOfNewConverter).isEqualTo(resultOfOldConverter);
+ }
+
+ @Test
+ public void changeNotesFieldWithMandatoryValuesIsBinaryCompatible() {
+ PatchSetApproval patchSetApproval =
+ new PatchSetApproval(
+ new PatchSetApproval.Key(
+ new PatchSet.Id(new Change.Id(42), 14),
+ new Account.Id(100013),
+ new LabelId("label-8")),
+ (short) 456,
+ new Date(987654L));
+
+ ByteString resultOfOldConverter = Protos.toByteString(patchSetApproval, patchSetApprovalCodec);
+ ByteString resultOfNewConverter =
+ toByteString(patchSetApproval, patchSetApprovalProtoConverter);
+
+ assertThat(resultOfNewConverter).isEqualTo(resultOfOldConverter);
+ }
+
+ // Copied from ChangeField.
+ private static <T> List<byte[]> convertToProtos_old(ProtobufCodec<T> codec, Collection<T> objs)
+ throws OrmException {
+ List<byte[]> result = Lists.newArrayListWithCapacity(objs.size());
+ ByteArrayOutputStream out = new ByteArrayOutputStream(256);
+ try {
+ for (T obj : objs) {
+ out.reset();
+ CodedOutputStream cos = CodedOutputStream.newInstance(out);
+ codec.encode(obj, cos);
+ cos.flush();
+ result.add(out.toByteArray());
+ }
+ } catch (IOException e) {
+ throw new OrmException(e);
+ }
+ return result;
+ }
+
+ // Copied from ChangeField.
+ private static <T> List<byte[]> convertToProtos_new(
+ ProtoConverter<?, T> converter, Collection<T> objects) {
+ return objects
+ .stream()
+ .map(converter::toProto)
+ .map(Protos::toByteArray)
+ .collect(toImmutableList());
+ }
+
+ // Copied from ChangeNotesState.Serializer.
+ private static <T> ByteString toByteString(T object, ProtoConverter<?, T> converter) {
+ MessageLite message = converter.toProto(object);
+ return Protos.toByteString(message);
+ }
+}
diff --git a/javatests/com/google/gerrit/reviewdb/converter/PatchSetApprovalKeyProtoConverterTest.java b/javatests/com/google/gerrit/reviewdb/converter/PatchSetApprovalKeyProtoConverterTest.java
new file mode 100644
index 0000000..0ed84fd
--- /dev/null
+++ b/javatests/com/google/gerrit/reviewdb/converter/PatchSetApprovalKeyProtoConverterTest.java
@@ -0,0 +1,98 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.reviewdb.converter;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.extensions.proto.ProtoTruth.assertThat;
+import static com.google.gerrit.proto.testing.SerializedClassSubject.assertThatSerializedClass;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.gerrit.proto.reviewdb.Reviewdb;
+import com.google.gerrit.proto.testing.SerializedClassSubject;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.LabelId;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
+import com.google.protobuf.Parser;
+import java.lang.reflect.Type;
+import org.junit.Test;
+
+public class PatchSetApprovalKeyProtoConverterTest {
+ private final PatchSetApprovalKeyProtoConverter protoConverter =
+ PatchSetApprovalKeyProtoConverter.INSTANCE;
+
+ @Test
+ public void allValuesConvertedToProto() {
+ PatchSetApproval.Key key =
+ new PatchSetApproval.Key(
+ new PatchSet.Id(new Change.Id(42), 14), new Account.Id(100013), new LabelId("label-8"));
+
+ Reviewdb.PatchSetApproval_Key proto = protoConverter.toProto(key);
+
+ Reviewdb.PatchSetApproval_Key expectedProto =
+ Reviewdb.PatchSetApproval_Key.newBuilder()
+ .setPatchSetId(
+ Reviewdb.PatchSet_Id.newBuilder()
+ .setChangeId(Reviewdb.Change_Id.newBuilder().setId(42))
+ .setPatchSetId(14))
+ .setAccountId(Reviewdb.Account_Id.newBuilder().setId(100013))
+ .setCategoryId(Reviewdb.LabelId.newBuilder().setId("label-8"))
+ .build();
+ assertThat(proto).isEqualTo(expectedProto);
+ }
+
+ @Test
+ public void allValuesConvertedToProtoAndBackAgain() {
+ PatchSetApproval.Key key =
+ new PatchSetApproval.Key(
+ new PatchSet.Id(new Change.Id(42), 14), new Account.Id(100013), new LabelId("label-8"));
+
+ PatchSetApproval.Key convertedKey = protoConverter.fromProto(protoConverter.toProto(key));
+
+ assertThat(convertedKey).isEqualTo(key);
+ }
+
+ @Test
+ public void protoCanBeParsedFromBytes() throws Exception {
+ Reviewdb.PatchSetApproval_Key proto =
+ Reviewdb.PatchSetApproval_Key.newBuilder()
+ .setPatchSetId(
+ Reviewdb.PatchSet_Id.newBuilder()
+ .setChangeId(Reviewdb.Change_Id.newBuilder().setId(42))
+ .setPatchSetId(14))
+ .setAccountId(Reviewdb.Account_Id.newBuilder().setId(100013))
+ .setCategoryId(Reviewdb.LabelId.newBuilder().setId("label-8"))
+ .build();
+ byte[] bytes = proto.toByteArray();
+
+ Parser<Reviewdb.PatchSetApproval_Key> parser = protoConverter.getParser();
+ Reviewdb.PatchSetApproval_Key parsedProto = parser.parseFrom(bytes);
+
+ assertThat(parsedProto).isEqualTo(proto);
+ }
+
+ /** See {@link SerializedClassSubject} for background and what to do if this test fails. */
+ @Test
+ public void fieldsExistAsExpected() {
+ assertThatSerializedClass(PatchSetApproval.Key.class)
+ .hasFields(
+ ImmutableMap.<String, Type>builder()
+ .put("patchSetId", PatchSet.Id.class)
+ .put("accountId", Account.Id.class)
+ .put("categoryId", LabelId.class)
+ .build());
+ }
+}
diff --git a/javatests/com/google/gerrit/reviewdb/converter/PatchSetApprovalProtoConverterTest.java b/javatests/com/google/gerrit/reviewdb/converter/PatchSetApprovalProtoConverterTest.java
new file mode 100644
index 0000000..831696c
--- /dev/null
+++ b/javatests/com/google/gerrit/reviewdb/converter/PatchSetApprovalProtoConverterTest.java
@@ -0,0 +1,203 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.reviewdb.converter;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.extensions.proto.ProtoTruth.assertThat;
+import static com.google.gerrit.proto.testing.SerializedClassSubject.assertThatSerializedClass;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.gerrit.proto.reviewdb.Reviewdb;
+import com.google.gerrit.proto.testing.SerializedClassSubject;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.LabelId;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
+import com.google.protobuf.Parser;
+import java.lang.reflect.Type;
+import java.sql.Timestamp;
+import java.util.Date;
+import org.junit.Test;
+
+public class PatchSetApprovalProtoConverterTest {
+ private final PatchSetApprovalProtoConverter protoConverter =
+ PatchSetApprovalProtoConverter.INSTANCE;
+
+ @Test
+ public void allValuesConvertedToProto() {
+ PatchSetApproval patchSetApproval =
+ new PatchSetApproval(
+ new PatchSetApproval.Key(
+ new PatchSet.Id(new Change.Id(42), 14),
+ new Account.Id(100013),
+ new LabelId("label-8")),
+ (short) 456,
+ new Date(987654L));
+ patchSetApproval.setTag("tag-21");
+ patchSetApproval.setRealAccountId(new Account.Id(612));
+ patchSetApproval.setPostSubmit(true);
+
+ Reviewdb.PatchSetApproval proto = protoConverter.toProto(patchSetApproval);
+
+ Reviewdb.PatchSetApproval expectedProto =
+ Reviewdb.PatchSetApproval.newBuilder()
+ .setKey(
+ Reviewdb.PatchSetApproval_Key.newBuilder()
+ .setPatchSetId(
+ Reviewdb.PatchSet_Id.newBuilder()
+ .setChangeId(Reviewdb.Change_Id.newBuilder().setId(42))
+ .setPatchSetId(14))
+ .setAccountId(Reviewdb.Account_Id.newBuilder().setId(100013))
+ .setCategoryId(Reviewdb.LabelId.newBuilder().setId("label-8")))
+ .setValue(456)
+ .setGranted(987654L)
+ .setTag("tag-21")
+ .setRealAccountId(Reviewdb.Account_Id.newBuilder().setId(612))
+ .setPostSubmit(true)
+ .build();
+ assertThat(proto).isEqualTo(expectedProto);
+ }
+
+ @Test
+ public void mandatoryValuesConvertedToProto() {
+ PatchSetApproval patchSetApproval =
+ new PatchSetApproval(
+ new PatchSetApproval.Key(
+ new PatchSet.Id(new Change.Id(42), 14),
+ new Account.Id(100013),
+ new LabelId("label-8")),
+ (short) 456,
+ new Date(987654L));
+
+ Reviewdb.PatchSetApproval proto = protoConverter.toProto(patchSetApproval);
+
+ Reviewdb.PatchSetApproval expectedProto =
+ Reviewdb.PatchSetApproval.newBuilder()
+ .setKey(
+ Reviewdb.PatchSetApproval_Key.newBuilder()
+ .setPatchSetId(
+ Reviewdb.PatchSet_Id.newBuilder()
+ .setChangeId(Reviewdb.Change_Id.newBuilder().setId(42))
+ .setPatchSetId(14))
+ .setAccountId(Reviewdb.Account_Id.newBuilder().setId(100013))
+ .setCategoryId(Reviewdb.LabelId.newBuilder().setId("label-8")))
+ .setValue(456)
+ .setGranted(987654L)
+ // This value can't be unset when our entity class is given.
+ .setPostSubmit(false)
+ .build();
+ assertThat(proto).isEqualTo(expectedProto);
+ }
+
+ @Test
+ public void allValuesConvertedToProtoAndBackAgain() {
+ PatchSetApproval patchSetApproval =
+ new PatchSetApproval(
+ new PatchSetApproval.Key(
+ new PatchSet.Id(new Change.Id(42), 14),
+ new Account.Id(100013),
+ new LabelId("label-8")),
+ (short) 456,
+ new Date(987654L));
+ patchSetApproval.setTag("tag-21");
+ patchSetApproval.setRealAccountId(new Account.Id(612));
+ patchSetApproval.setPostSubmit(true);
+
+ PatchSetApproval convertedPatchSetApproval =
+ protoConverter.fromProto(protoConverter.toProto(patchSetApproval));
+ assertThat(convertedPatchSetApproval).isEqualTo(patchSetApproval);
+ }
+
+ @Test
+ public void mandatoryValuesConvertedToProtoAndBackAgain() {
+ PatchSetApproval patchSetApproval =
+ new PatchSetApproval(
+ new PatchSetApproval.Key(
+ new PatchSet.Id(new Change.Id(42), 14),
+ new Account.Id(100013),
+ new LabelId("label-8")),
+ (short) 456,
+ new Date(987654L));
+
+ PatchSetApproval convertedPatchSetApproval =
+ protoConverter.fromProto(protoConverter.toProto(patchSetApproval));
+ assertThat(convertedPatchSetApproval).isEqualTo(patchSetApproval);
+ }
+
+ // We need this special test as some values are only optional in the protobuf definition but can
+ // never be unset in our entity object.
+ @Test
+ public void protoWithOnlyRequiredValuesCanBeConvertedBack() {
+ Reviewdb.PatchSetApproval proto =
+ Reviewdb.PatchSetApproval.newBuilder()
+ .setKey(
+ Reviewdb.PatchSetApproval_Key.newBuilder()
+ .setPatchSetId(
+ Reviewdb.PatchSet_Id.newBuilder()
+ .setChangeId(Reviewdb.Change_Id.newBuilder().setId(42))
+ .setPatchSetId(14))
+ .setAccountId(Reviewdb.Account_Id.newBuilder().setId(100013))
+ .setCategoryId(Reviewdb.LabelId.newBuilder().setId("label-8")))
+ .build();
+ PatchSetApproval patchSetApproval = protoConverter.fromProto(proto);
+
+ assertThat(patchSetApproval.getPatchSetId()).isEqualTo(new PatchSet.Id(new Change.Id(42), 14));
+ assertThat(patchSetApproval.getAccountId()).isEqualTo(new Account.Id(100013));
+ assertThat(patchSetApproval.getLabelId()).isEqualTo(new LabelId("label-8"));
+ // Default values for unset protobuf fields which can't be unset in the entity object.
+ assertThat(patchSetApproval.getValue()).isEqualTo(0);
+ assertThat(patchSetApproval.getGranted()).isEqualTo(new Timestamp(0));
+ assertThat(patchSetApproval.isPostSubmit()).isEqualTo(false);
+ }
+
+ @Test
+ public void protoCanBeParsedFromBytes() throws Exception {
+ Reviewdb.PatchSetApproval proto =
+ Reviewdb.PatchSetApproval.newBuilder()
+ .setKey(
+ Reviewdb.PatchSetApproval_Key.newBuilder()
+ .setPatchSetId(
+ Reviewdb.PatchSet_Id.newBuilder()
+ .setChangeId(Reviewdb.Change_Id.newBuilder().setId(42))
+ .setPatchSetId(14))
+ .setAccountId(Reviewdb.Account_Id.newBuilder().setId(100013))
+ .setCategoryId(Reviewdb.LabelId.newBuilder().setId("label-8")))
+ .setValue(456)
+ .setGranted(987654L)
+ .build();
+ byte[] bytes = proto.toByteArray();
+
+ Parser<Reviewdb.PatchSetApproval> parser = protoConverter.getParser();
+ Reviewdb.PatchSetApproval parsedProto = parser.parseFrom(bytes);
+
+ assertThat(parsedProto).isEqualTo(proto);
+ }
+
+ /** See {@link SerializedClassSubject} for background and what to do if this test fails. */
+ @Test
+ public void fieldsExistAsExpected() {
+ assertThatSerializedClass(PatchSetApproval.class)
+ .hasFields(
+ ImmutableMap.<String, Type>builder()
+ .put("key", PatchSetApproval.Key.class)
+ .put("value", short.class)
+ .put("granted", Timestamp.class)
+ .put("tag", String.class)
+ .put("realAccountId", Account.Id.class)
+ .put("postSubmit", boolean.class)
+ .build());
+ }
+}
diff --git a/javatests/com/google/gerrit/reviewdb/converter/PatchSetConverterCompatibilityTest.java b/javatests/com/google/gerrit/reviewdb/converter/PatchSetConverterCompatibilityTest.java
new file mode 100644
index 0000000..8d8960c
--- /dev/null
+++ b/javatests/com/google/gerrit/reviewdb/converter/PatchSetConverterCompatibilityTest.java
@@ -0,0 +1,137 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.reviewdb.converter;
+
+import static com.google.common.collect.ImmutableList.toImmutableList;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.gerrit.proto.Protos;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.RevId;
+import com.google.gwtorm.protobuf.CodecFactory;
+import com.google.gwtorm.protobuf.ProtobufCodec;
+import com.google.gwtorm.server.OrmException;
+import com.google.protobuf.ByteString;
+import com.google.protobuf.CodedOutputStream;
+import com.google.protobuf.MessageLite;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.sql.Timestamp;
+import java.util.Collection;
+import java.util.List;
+import org.junit.Test;
+
+// TODO(aliceks): Delete after proving binary compatibility.
+public class PatchSetConverterCompatibilityTest {
+
+ private final ProtobufCodec<PatchSet> patchSetCodec = CodecFactory.encoder(PatchSet.class);
+ private final PatchSetProtoConverter patchSetProtoConverter = PatchSetProtoConverter.INSTANCE;
+
+ @Test
+ public void changeIndexFieldWithAllValuesIsBinaryCompatible() throws Exception {
+ PatchSet patchSet = new PatchSet(new PatchSet.Id(new Change.Id(103), 73));
+ patchSet.setRevision(new RevId("aabbccddeeff"));
+ patchSet.setUploader(new Account.Id(452));
+ patchSet.setCreatedOn(new Timestamp(930349320L));
+ patchSet.setGroups(ImmutableList.of("group1, group2"));
+ patchSet.setPushCertificate("my push certificate");
+ patchSet.setDescription("This is a patch set description.");
+ ImmutableList<PatchSet> patchSets = ImmutableList.of(patchSet);
+
+ byte[] resultOfOldConverter = getOnlyElement(convertToProtos_old(patchSetCodec, patchSets));
+ byte[] resultOfNewConverter =
+ getOnlyElement(convertToProtos_new(patchSetProtoConverter, patchSets));
+
+ assertThat(resultOfNewConverter).isEqualTo(resultOfOldConverter);
+ }
+
+ @Test
+ public void changeIndexFieldWithMandatoryValuesIsBinaryCompatible() throws Exception {
+ PatchSet patchSet = new PatchSet(new PatchSet.Id(new Change.Id(103), 73));
+ ImmutableList<PatchSet> patchSets = ImmutableList.of(patchSet);
+
+ byte[] resultOfOldConverter = getOnlyElement(convertToProtos_old(patchSetCodec, patchSets));
+ byte[] resultOfNewConverter =
+ getOnlyElement(convertToProtos_new(patchSetProtoConverter, patchSets));
+
+ assertThat(resultOfNewConverter).isEqualTo(resultOfOldConverter);
+ }
+
+ @Test
+ public void changeNotesFieldWithAllValuesIsBinaryCompatible() {
+ PatchSet patchSet = new PatchSet(new PatchSet.Id(new Change.Id(103), 73));
+ patchSet.setRevision(new RevId("aabbccddeeff"));
+ patchSet.setUploader(new Account.Id(452));
+ patchSet.setCreatedOn(new Timestamp(930349320L));
+ patchSet.setGroups(ImmutableList.of("group1, group2"));
+ patchSet.setPushCertificate("my push certificate");
+ patchSet.setDescription("This is a patch set description.");
+
+ ByteString resultOfOldConverter = Protos.toByteString(patchSet, patchSetCodec);
+ ByteString resultOfNewConverter = toByteString(patchSet, patchSetProtoConverter);
+
+ assertThat(resultOfNewConverter).isEqualTo(resultOfOldConverter);
+ }
+
+ @Test
+ public void changeNotesFieldWithMandatoryValuesIsBinaryCompatible() {
+ PatchSet patchSet = new PatchSet(new PatchSet.Id(new Change.Id(103), 73));
+
+ ByteString resultOfOldConverter = Protos.toByteString(patchSet, patchSetCodec);
+ ByteString resultOfNewConverter = toByteString(patchSet, patchSetProtoConverter);
+
+ assertThat(resultOfNewConverter).isEqualTo(resultOfOldConverter);
+ }
+
+ // Copied from ChangeField.
+ private static <T> List<byte[]> convertToProtos_old(ProtobufCodec<T> codec, Collection<T> objs)
+ throws OrmException {
+ List<byte[]> result = Lists.newArrayListWithCapacity(objs.size());
+ ByteArrayOutputStream out = new ByteArrayOutputStream(256);
+ try {
+ for (T obj : objs) {
+ out.reset();
+ CodedOutputStream cos = CodedOutputStream.newInstance(out);
+ codec.encode(obj, cos);
+ cos.flush();
+ result.add(out.toByteArray());
+ }
+ } catch (IOException e) {
+ throw new OrmException(e);
+ }
+ return result;
+ }
+
+ // Copied from ChangeField.
+ private static <T> List<byte[]> convertToProtos_new(
+ ProtoConverter<?, T> converter, Collection<T> objects) {
+ return objects
+ .stream()
+ .map(converter::toProto)
+ .map(Protos::toByteArray)
+ .collect(toImmutableList());
+ }
+
+ // Copied from ChangeNotesState.Serializer.
+ private static <T> ByteString toByteString(T object, ProtoConverter<?, T> converter) {
+ MessageLite message = converter.toProto(object);
+ return Protos.toByteString(message);
+ }
+}
diff --git a/javatests/com/google/gerrit/reviewdb/converter/PatchSetIdProtoConverterTest.java b/javatests/com/google/gerrit/reviewdb/converter/PatchSetIdProtoConverterTest.java
new file mode 100644
index 0000000..3869ab3
--- /dev/null
+++ b/javatests/com/google/gerrit/reviewdb/converter/PatchSetIdProtoConverterTest.java
@@ -0,0 +1,83 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.reviewdb.converter;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.extensions.proto.ProtoTruth.assertThat;
+import static com.google.gerrit.proto.testing.SerializedClassSubject.assertThatSerializedClass;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.gerrit.proto.reviewdb.Reviewdb;
+import com.google.gerrit.proto.testing.SerializedClassSubject;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.protobuf.Parser;
+import java.lang.reflect.Type;
+import org.junit.Test;
+
+public class PatchSetIdProtoConverterTest {
+ private final PatchSetIdProtoConverter patchSetIdProtoConverter =
+ PatchSetIdProtoConverter.INSTANCE;
+
+ @Test
+ public void allValuesConvertedToProto() {
+ PatchSet.Id patchSetId = new PatchSet.Id(new Change.Id(103), 73);
+
+ Reviewdb.PatchSet_Id proto = patchSetIdProtoConverter.toProto(patchSetId);
+
+ Reviewdb.PatchSet_Id expectedProto =
+ Reviewdb.PatchSet_Id.newBuilder()
+ .setChangeId(Reviewdb.Change_Id.newBuilder().setId(103))
+ .setPatchSetId(73)
+ .build();
+ assertThat(proto).isEqualTo(expectedProto);
+ }
+
+ @Test
+ public void allValuesConvertedToProtoAndBackAgain() {
+ PatchSet.Id patchSetId = new PatchSet.Id(new Change.Id(20), 13);
+
+ PatchSet.Id convertedPatchSetId =
+ patchSetIdProtoConverter.fromProto(patchSetIdProtoConverter.toProto(patchSetId));
+
+ assertThat(convertedPatchSetId).isEqualTo(patchSetId);
+ }
+
+ @Test
+ public void protoCanBeParsedFromBytes() throws Exception {
+ Reviewdb.PatchSet_Id proto =
+ Reviewdb.PatchSet_Id.newBuilder()
+ .setChangeId(Reviewdb.Change_Id.newBuilder().setId(103))
+ .setPatchSetId(73)
+ .build();
+ byte[] bytes = proto.toByteArray();
+
+ Parser<Reviewdb.PatchSet_Id> parser = patchSetIdProtoConverter.getParser();
+ Reviewdb.PatchSet_Id parsedProto = parser.parseFrom(bytes);
+
+ assertThat(parsedProto).isEqualTo(proto);
+ }
+
+ /** See {@link SerializedClassSubject} for background and what to do if this test fails. */
+ @Test
+ public void fieldsExistAsExpected() {
+ assertThatSerializedClass(PatchSet.Id.class)
+ .hasFields(
+ ImmutableMap.<String, Type>builder()
+ .put("changeId", Change.Id.class)
+ .put("patchSetId", int.class)
+ .build());
+ }
+}
diff --git a/javatests/com/google/gerrit/reviewdb/converter/PatchSetProtoConverterTest.java b/javatests/com/google/gerrit/reviewdb/converter/PatchSetProtoConverterTest.java
new file mode 100644
index 0000000..00ccf82
--- /dev/null
+++ b/javatests/com/google/gerrit/reviewdb/converter/PatchSetProtoConverterTest.java
@@ -0,0 +1,137 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.reviewdb.converter;
+
+import static com.google.common.truth.extensions.proto.ProtoTruth.assertThat;
+import static com.google.gerrit.proto.testing.SerializedClassSubject.assertThatSerializedClass;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.truth.Truth;
+import com.google.gerrit.proto.reviewdb.Reviewdb;
+import com.google.gerrit.proto.testing.SerializedClassSubject;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.RevId;
+import com.google.protobuf.Parser;
+import java.lang.reflect.Type;
+import java.sql.Timestamp;
+import org.junit.Test;
+
+public class PatchSetProtoConverterTest {
+ private final PatchSetProtoConverter patchSetProtoConverter = PatchSetProtoConverter.INSTANCE;
+
+ @Test
+ public void allValuesConvertedToProto() {
+ PatchSet patchSet = new PatchSet(new PatchSet.Id(new Change.Id(103), 73));
+ patchSet.setRevision(new RevId("aabbccddeeff"));
+ patchSet.setUploader(new Account.Id(452));
+ patchSet.setCreatedOn(new Timestamp(930349320L));
+ patchSet.setGroups(ImmutableList.of("group1, group2"));
+ patchSet.setPushCertificate("my push certificate");
+ patchSet.setDescription("This is a patch set description.");
+
+ Reviewdb.PatchSet proto = patchSetProtoConverter.toProto(patchSet);
+
+ Reviewdb.PatchSet expectedProto =
+ Reviewdb.PatchSet.newBuilder()
+ .setId(
+ Reviewdb.PatchSet_Id.newBuilder()
+ .setChangeId(Reviewdb.Change_Id.newBuilder().setId(103))
+ .setPatchSetId(73))
+ .setRevision(Reviewdb.RevId.newBuilder().setId("aabbccddeeff"))
+ .setUploaderAccountId(Reviewdb.Account_Id.newBuilder().setId(452))
+ .setCreatedOn(930349320L)
+ .setGroups("group1, group2")
+ .setPushCertificate("my push certificate")
+ .setDescription("This is a patch set description.")
+ .build();
+ assertThat(proto).isEqualTo(expectedProto);
+ }
+
+ @Test
+ public void mandatoryValuesConvertedToProto() {
+ PatchSet patchSet = new PatchSet(new PatchSet.Id(new Change.Id(103), 73));
+
+ Reviewdb.PatchSet proto = patchSetProtoConverter.toProto(patchSet);
+
+ Reviewdb.PatchSet expectedProto =
+ Reviewdb.PatchSet.newBuilder()
+ .setId(
+ Reviewdb.PatchSet_Id.newBuilder()
+ .setChangeId(Reviewdb.Change_Id.newBuilder().setId(103))
+ .setPatchSetId(73))
+ .build();
+ assertThat(proto).isEqualTo(expectedProto);
+ }
+
+ @Test
+ public void allValuesConvertedToProtoAndBackAgain() {
+ PatchSet patchSet = new PatchSet(new PatchSet.Id(new Change.Id(103), 73));
+ patchSet.setRevision(new RevId("aabbccddeeff"));
+ patchSet.setUploader(new Account.Id(452));
+ patchSet.setCreatedOn(new Timestamp(930349320L));
+ patchSet.setGroups(ImmutableList.of("group1, group2"));
+ patchSet.setPushCertificate("my push certificate");
+ patchSet.setDescription("This is a patch set description.");
+
+ PatchSet convertedPatchSet =
+ patchSetProtoConverter.fromProto(patchSetProtoConverter.toProto(patchSet));
+ Truth.assertThat(convertedPatchSet).isEqualTo(patchSet);
+ }
+
+ @Test
+ public void mandatoryValuesConvertedToProtoAndBackAgain() {
+ PatchSet patchSet = new PatchSet(new PatchSet.Id(new Change.Id(103), 73));
+
+ PatchSet convertedPatchSet =
+ patchSetProtoConverter.fromProto(patchSetProtoConverter.toProto(patchSet));
+ Truth.assertThat(convertedPatchSet).isEqualTo(patchSet);
+ }
+
+ @Test
+ public void protoCanBeParsedFromBytes() throws Exception {
+ Reviewdb.PatchSet proto =
+ Reviewdb.PatchSet.newBuilder()
+ .setId(
+ Reviewdb.PatchSet_Id.newBuilder()
+ .setChangeId(Reviewdb.Change_Id.newBuilder().setId(103))
+ .setPatchSetId(73))
+ .build();
+ byte[] bytes = proto.toByteArray();
+
+ Parser<Reviewdb.PatchSet> parser = patchSetProtoConverter.getParser();
+ Reviewdb.PatchSet parsedProto = parser.parseFrom(bytes);
+
+ assertThat(parsedProto).isEqualTo(proto);
+ }
+
+ /** See {@link SerializedClassSubject} for background and what to do if this test fails. */
+ @Test
+ public void fieldsExistAsExpected() {
+ assertThatSerializedClass(PatchSet.class)
+ .hasFields(
+ ImmutableMap.<String, Type>builder()
+ .put("id", PatchSet.Id.class)
+ .put("revision", RevId.class)
+ .put("uploader", Account.Id.class)
+ .put("createdOn", Timestamp.class)
+ .put("groups", String.class)
+ .put("pushCertificate", String.class)
+ .put("description", String.class)
+ .build());
+ }
+}
diff --git a/javatests/com/google/gerrit/reviewdb/converter/RevIdProtoConverterTest.java b/javatests/com/google/gerrit/reviewdb/converter/RevIdProtoConverterTest.java
new file mode 100644
index 0000000..2aa3a84
--- /dev/null
+++ b/javatests/com/google/gerrit/reviewdb/converter/RevIdProtoConverterTest.java
@@ -0,0 +1,66 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.reviewdb.converter;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.extensions.proto.ProtoTruth.assertThat;
+import static com.google.gerrit.proto.testing.SerializedClassSubject.assertThatSerializedClass;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.gerrit.proto.reviewdb.Reviewdb;
+import com.google.gerrit.proto.testing.SerializedClassSubject;
+import com.google.gerrit.reviewdb.client.RevId;
+import com.google.protobuf.Parser;
+import org.junit.Test;
+
+public class RevIdProtoConverterTest {
+ private final RevIdProtoConverter revIdProtoConverter = RevIdProtoConverter.INSTANCE;
+
+ @Test
+ public void allValuesConvertedToProto() {
+ RevId revId = new RevId("9903402f303249e");
+
+ Reviewdb.RevId proto = revIdProtoConverter.toProto(revId);
+
+ Reviewdb.RevId expectedProto = Reviewdb.RevId.newBuilder().setId("9903402f303249e").build();
+ assertThat(proto).isEqualTo(expectedProto);
+ }
+
+ @Test
+ public void allValuesConvertedToProtoAndBackAgain() {
+ RevId revId = new RevId("ff3934a320bb");
+
+ RevId convertedRevId = revIdProtoConverter.fromProto(revIdProtoConverter.toProto(revId));
+
+ assertThat(convertedRevId).isEqualTo(revId);
+ }
+
+ @Test
+ public void protoCanBeParsedFromBytes() throws Exception {
+ Reviewdb.RevId proto = Reviewdb.RevId.newBuilder().setId("9903402f303249e").build();
+ byte[] bytes = proto.toByteArray();
+
+ Parser<Reviewdb.RevId> parser = revIdProtoConverter.getParser();
+ Reviewdb.RevId parsedProto = parser.parseFrom(bytes);
+
+ assertThat(parsedProto).isEqualTo(proto);
+ }
+
+ /** See {@link SerializedClassSubject} for background and what to do if this test fails. */
+ @Test
+ public void fieldsExistAsExpected() {
+ assertThatSerializedClass(RevId.class).hasFields(ImmutableMap.of("id", String.class));
+ }
+}
diff --git a/javatests/com/google/gerrit/server/BUILD b/javatests/com/google/gerrit/server/BUILD
index 88edc2e..e705ec5 100644
--- a/javatests/com/google/gerrit/server/BUILD
+++ b/javatests/com/google/gerrit/server/BUILD
@@ -44,6 +44,8 @@
"//java/com/google/gerrit/lifecycle",
"//java/com/google/gerrit/mail",
"//java/com/google/gerrit/metrics",
+ "//java/com/google/gerrit/proto",
+ "//java/com/google/gerrit/proto/testing",
"//java/com/google/gerrit/reviewdb:server",
"//java/com/google/gerrit/server",
"//java/com/google/gerrit/server/cache/serialize",
diff --git a/javatests/com/google/gerrit/server/account/externalids/AllExternalIdsTest.java b/javatests/com/google/gerrit/server/account/externalids/AllExternalIdsTest.java
index edf6bdd..d757f71 100644
--- a/javatests/com/google/gerrit/server/account/externalids/AllExternalIdsTest.java
+++ b/javatests/com/google/gerrit/server/account/externalids/AllExternalIdsTest.java
@@ -16,8 +16,8 @@
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.extensions.proto.ProtoTruth.assertThat;
+import static com.google.gerrit.proto.testing.SerializedClassSubject.assertThatSerializedClass;
import static com.google.gerrit.server.cache.testing.CacheSerializerTestUtil.byteString;
-import static com.google.gerrit.server.cache.testing.SerializedClassSubject.assertThatSerializedClass;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSetMultimap;
diff --git a/javatests/com/google/gerrit/server/auth/oauth/OAuthTokenCacheTest.java b/javatests/com/google/gerrit/server/auth/oauth/OAuthTokenCacheTest.java
index 81fd6d7..e4f8ba8 100644
--- a/javatests/com/google/gerrit/server/auth/oauth/OAuthTokenCacheTest.java
+++ b/javatests/com/google/gerrit/server/auth/oauth/OAuthTokenCacheTest.java
@@ -2,10 +2,11 @@
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.extensions.proto.ProtoTruth.assertThat;
-import static com.google.gerrit.server.cache.testing.SerializedClassSubject.assertThatSerializedClass;
+import static com.google.gerrit.proto.testing.SerializedClassSubject.assertThatSerializedClass;
import com.google.common.collect.ImmutableMap;
import com.google.gerrit.extensions.auth.oauth.OAuthToken;
+import com.google.gerrit.proto.testing.SerializedClassSubject;
import com.google.gerrit.server.cache.proto.Cache.OAuthTokenProto;
import com.google.gerrit.server.cache.serialize.CacheSerializer;
import java.lang.reflect.Type;
@@ -56,10 +57,7 @@
assertThat(s.deserialize(serializedWithEmptyString)).isEqualTo(tokenWithNull);
}
- /**
- * See {@link com.google.gerrit.server.cache.testing.SerializedClassSubject} for background and
- * what to do if this test fails.
- */
+ /** See {@link SerializedClassSubject} for background and what to do if this test fails. */
@Test
public void oAuthTokenFields() throws Exception {
assertThatSerializedClass(OAuthToken.class)
diff --git a/javatests/com/google/gerrit/server/cache/serialize/ProtoCacheSerializersTest.java b/javatests/com/google/gerrit/server/cache/serialize/ObjectIdConverterTest.java
similarity index 62%
rename from javatests/com/google/gerrit/server/cache/serialize/ProtoCacheSerializersTest.java
rename to javatests/com/google/gerrit/server/cache/serialize/ObjectIdConverterTest.java
index 8a02af2..c5ea2ea 100644
--- a/javatests/com/google/gerrit/server/cache/serialize/ProtoCacheSerializersTest.java
+++ b/javatests/com/google/gerrit/server/cache/serialize/ObjectIdConverterTest.java
@@ -16,18 +16,14 @@
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assert_;
-import static com.google.common.truth.extensions.proto.ProtoTruth.assertThat;
import static com.google.gerrit.server.cache.testing.CacheSerializerTestUtil.byteString;
-import com.google.gerrit.server.cache.proto.Cache.ChangeNotesKeyProto;
-import com.google.gerrit.server.cache.proto.Cache.ChangeNotesStateProto;
-import com.google.gerrit.server.cache.serialize.ProtoCacheSerializers.ObjectIdConverter;
import com.google.gerrit.testing.GerritBaseTests;
import com.google.protobuf.ByteString;
import org.eclipse.jgit.lib.ObjectId;
import org.junit.Test;
-public class ProtoCacheSerializersTest extends GerritBaseTests {
+public class ObjectIdConverterTest extends GerritBaseTests {
@Test
public void objectIdFromByteString() {
ObjectIdConverter idConverter = ObjectIdConverter.create();
@@ -73,45 +69,4 @@
0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb));
}
-
- @Test
- public void parseUncheckedWrongProtoType() {
- ChangeNotesKeyProto proto =
- ChangeNotesKeyProto.newBuilder()
- .setProject("project")
- .setChangeId(1234)
- .setId(ByteString.copyFromUtf8("foo"))
- .build();
- byte[] bytes = ProtoCacheSerializers.toByteArray(proto);
- try {
- ProtoCacheSerializers.parseUnchecked(ChangeNotesStateProto.parser(), bytes);
- assert_().fail("expected IllegalArgumentException");
- } catch (IllegalArgumentException e) {
- // Expected.
- }
- }
-
- @Test
- public void parseUncheckedInvalidData() {
- byte[] bytes = new byte[] {0x00};
- try {
- ProtoCacheSerializers.parseUnchecked(ChangeNotesStateProto.parser(), bytes);
- assert_().fail("expected IllegalArgumentException");
- } catch (IllegalArgumentException e) {
- // Expected.
- }
- }
-
- @Test
- public void parseUnchecked() {
- ChangeNotesKeyProto proto =
- ChangeNotesKeyProto.newBuilder()
- .setProject("project")
- .setChangeId(1234)
- .setId(ByteString.copyFromUtf8("foo"))
- .build();
- byte[] bytes = ProtoCacheSerializers.toByteArray(proto);
- assertThat(ProtoCacheSerializers.parseUnchecked(ChangeNotesKeyProto.parser(), bytes))
- .isEqualTo(proto);
- }
}
diff --git a/javatests/com/google/gerrit/server/change/ChangeKindCacheImplTest.java b/javatests/com/google/gerrit/server/change/ChangeKindCacheImplTest.java
index 335ff12..fffb1da 100644
--- a/javatests/com/google/gerrit/server/change/ChangeKindCacheImplTest.java
+++ b/javatests/com/google/gerrit/server/change/ChangeKindCacheImplTest.java
@@ -16,10 +16,11 @@
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.extensions.proto.ProtoTruth.assertThat;
+import static com.google.gerrit.proto.testing.SerializedClassSubject.assertThatSerializedClass;
import static com.google.gerrit.server.cache.testing.CacheSerializerTestUtil.byteString;
-import static com.google.gerrit.server.cache.testing.SerializedClassSubject.assertThatSerializedClass;
import com.google.common.collect.ImmutableMap;
+import com.google.gerrit.proto.testing.SerializedClassSubject;
import com.google.gerrit.server.cache.proto.Cache.ChangeKindKeyProto;
import com.google.gerrit.server.cache.serialize.CacheSerializer;
import com.google.gerrit.server.change.ChangeKindCacheImpl.Key;
@@ -50,10 +51,7 @@
assertThat(s.deserialize(serialized)).isEqualTo(key);
}
- /**
- * See {@link com.google.gerrit.server.cache.testing.SerializedClassSubject} for background and
- * what to do if this test fails.
- */
+ /** See {@link SerializedClassSubject} for background and what to do if this test fails. */
@Test
public void keyFields() throws Exception {
assertThatSerializedClass(ChangeKindCacheImpl.Key.class)
diff --git a/javatests/com/google/gerrit/server/change/LabelNormalizerTest.java b/javatests/com/google/gerrit/server/change/LabelNormalizerTest.java
index cc15b1b..b852bfb 100644
--- a/javatests/com/google/gerrit/server/change/LabelNormalizerTest.java
+++ b/javatests/com/google/gerrit/server/change/LabelNormalizerTest.java
@@ -135,7 +135,7 @@
input.newBranch = true;
input.subject = "Test change";
ChangeInfo info = gApi.changes().create(input).get();
- notes = changeNotesFactory.createChecked(db, allProjects, new Change.Id(info._number));
+ notes = changeNotesFactory.createChecked(allProjects, new Change.Id(info._number));
change = notes.getChange();
}
diff --git a/javatests/com/google/gerrit/server/change/MergeabilityCacheImplTest.java b/javatests/com/google/gerrit/server/change/MergeabilityCacheImplTest.java
index c5d35f6..46ddbc2 100644
--- a/javatests/com/google/gerrit/server/change/MergeabilityCacheImplTest.java
+++ b/javatests/com/google/gerrit/server/change/MergeabilityCacheImplTest.java
@@ -16,11 +16,12 @@
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.extensions.proto.ProtoTruth.assertThat;
+import static com.google.gerrit.proto.testing.SerializedClassSubject.assertThatSerializedClass;
import static com.google.gerrit.server.cache.testing.CacheSerializerTestUtil.byteString;
-import static com.google.gerrit.server.cache.testing.SerializedClassSubject.assertThatSerializedClass;
import com.google.common.collect.ImmutableMap;
import com.google.gerrit.extensions.client.SubmitType;
+import com.google.gerrit.proto.testing.SerializedClassSubject;
import com.google.gerrit.server.cache.proto.Cache.MergeabilityKeyProto;
import com.google.gerrit.testing.GerritBaseTests;
import org.eclipse.jgit.lib.ObjectId;
@@ -54,10 +55,7 @@
.isEqualTo(key);
}
- /**
- * See {@link com.google.gerrit.server.cache.testing.SerializedClassSubject} for background and
- * what to do if this test fails.
- */
+ /** See {@link SerializedClassSubject} for background and what to do if this test fails. */
@Test
public void keyFields() throws Exception {
assertThatSerializedClass(MergeabilityCacheImpl.EntryKey.class)
diff --git a/javatests/com/google/gerrit/server/git/TagSetHolderTest.java b/javatests/com/google/gerrit/server/git/TagSetHolderTest.java
index 705139a..87ddc75 100644
--- a/javatests/com/google/gerrit/server/git/TagSetHolderTest.java
+++ b/javatests/com/google/gerrit/server/git/TagSetHolderTest.java
@@ -16,7 +16,7 @@
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.extensions.proto.ProtoTruth.assertThat;
-import static com.google.gerrit.server.cache.testing.SerializedClassSubject.assertThatSerializedClass;
+import static com.google.gerrit.proto.testing.SerializedClassSubject.assertThatSerializedClass;
import com.google.common.collect.ImmutableMap;
import com.google.gerrit.reviewdb.client.Project;
diff --git a/javatests/com/google/gerrit/server/git/TagSetTest.java b/javatests/com/google/gerrit/server/git/TagSetTest.java
index 1314ce6..3ac72be 100644
--- a/javatests/com/google/gerrit/server/git/TagSetTest.java
+++ b/javatests/com/google/gerrit/server/git/TagSetTest.java
@@ -17,8 +17,8 @@
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static com.google.common.truth.extensions.proto.ProtoTruth.assertThat;
+import static com.google.gerrit.proto.testing.SerializedClassSubject.assertThatSerializedClass;
import static com.google.gerrit.server.cache.testing.CacheSerializerTestUtil.byteString;
-import static com.google.gerrit.server.cache.testing.SerializedClassSubject.assertThatSerializedClass;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSortedSet;
diff --git a/javatests/com/google/gerrit/server/notedb/AbstractChangeNotesTest.java b/javatests/com/google/gerrit/server/notedb/AbstractChangeNotesTest.java
index ed4aacb..138635e 100644
--- a/javatests/com/google/gerrit/server/notedb/AbstractChangeNotesTest.java
+++ b/javatests/com/google/gerrit/server/notedb/AbstractChangeNotesTest.java
@@ -161,10 +161,6 @@
bind(GitReferenceUpdated.class).toInstance(GitReferenceUpdated.DISABLED);
bind(MetricMaker.class).to(DisabledMetricMaker.class);
bind(ReviewDb.class).toProvider(Providers.<ReviewDb>of(null));
- MutableNotesMigration migration = MutableNotesMigration.newDisabled();
- migration.setFrom(NotesMigrationState.FINAL);
- bind(MutableNotesMigration.class).toInstance(migration);
- bind(NotesMigration.class).to(MutableNotesMigration.class);
// Tests don't support ReviewDb at all, but bindings are required via NoteDbModule.
bind(new TypeLiteral<SchemaFactory<ReviewDb>>() {})
diff --git a/javatests/com/google/gerrit/server/notedb/ChangeNotesCacheTest.java b/javatests/com/google/gerrit/server/notedb/ChangeNotesCacheTest.java
index 7b140b7..b4d9738 100644
--- a/javatests/com/google/gerrit/server/notedb/ChangeNotesCacheTest.java
+++ b/javatests/com/google/gerrit/server/notedb/ChangeNotesCacheTest.java
@@ -16,8 +16,8 @@
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.extensions.proto.ProtoTruth.assertThat;
+import static com.google.gerrit.proto.testing.SerializedClassSubject.assertThatSerializedClass;
import static com.google.gerrit.server.cache.testing.CacheSerializerTestUtil.byteString;
-import static com.google.gerrit.server.cache.testing.SerializedClassSubject.assertThatSerializedClass;
import com.google.common.collect.ImmutableMap;
import com.google.gerrit.reviewdb.client.Change;
diff --git a/javatests/com/google/gerrit/server/notedb/ChangeNotesStateTest.java b/javatests/com/google/gerrit/server/notedb/ChangeNotesStateTest.java
index 1bd6fbe..0ea1bea 100644
--- a/javatests/com/google/gerrit/server/notedb/ChangeNotesStateTest.java
+++ b/javatests/com/google/gerrit/server/notedb/ChangeNotesStateTest.java
@@ -16,11 +16,8 @@
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.extensions.proto.ProtoTruth.assertThat;
-import static com.google.gerrit.reviewdb.server.ReviewDbCodecs.APPROVAL_CODEC;
-import static com.google.gerrit.reviewdb.server.ReviewDbCodecs.MESSAGE_CODEC;
-import static com.google.gerrit.reviewdb.server.ReviewDbCodecs.PATCH_SET_CODEC;
-import static com.google.gerrit.server.cache.serialize.ProtoCacheSerializers.toByteString;
-import static com.google.gerrit.server.cache.testing.SerializedClassSubject.assertThatSerializedClass;
+import static com.google.gerrit.proto.testing.SerializedClassSubject.assertThatSerializedClass;
+import static com.google.gerrit.server.notedb.ChangeNotesState.Serializer.toByteString;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
@@ -39,6 +36,9 @@
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.PatchSetApproval;
import com.google.gerrit.reviewdb.client.RevId;
+import com.google.gerrit.reviewdb.converter.ChangeMessageProtoConverter;
+import com.google.gerrit.reviewdb.converter.PatchSetApprovalProtoConverter;
+import com.google.gerrit.reviewdb.converter.PatchSetProtoConverter;
import com.google.gerrit.server.ReviewerByEmailSet;
import com.google.gerrit.server.ReviewerSet;
import com.google.gerrit.server.ReviewerStatusUpdate;
@@ -47,7 +47,7 @@
import com.google.gerrit.server.cache.proto.Cache.ChangeNotesStateProto.ReviewerByEmailSetEntryProto;
import com.google.gerrit.server.cache.proto.Cache.ChangeNotesStateProto.ReviewerSetEntryProto;
import com.google.gerrit.server.cache.proto.Cache.ChangeNotesStateProto.ReviewerStatusUpdateProto;
-import com.google.gerrit.server.cache.serialize.ProtoCacheSerializers.ObjectIdConverter;
+import com.google.gerrit.server.cache.serialize.ObjectIdConverter;
import com.google.gerrit.server.notedb.ChangeNotesState.ChangeColumns;
import com.google.gerrit.server.notedb.ChangeNotesState.Serializer;
import com.google.gerrit.testing.GerritBaseTests;
@@ -340,14 +340,14 @@
ps1.setUploader(new Account.Id(2000));
ps1.setRevision(new RevId("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
ps1.setCreatedOn(cols.createdOn());
- ByteString ps1Bytes = toByteString(ps1, PATCH_SET_CODEC);
+ ByteString ps1Bytes = toByteString(ps1, PatchSetProtoConverter.INSTANCE);
assertThat(ps1Bytes.size()).isEqualTo(66);
PatchSet ps2 = new PatchSet(new PatchSet.Id(ID, 2));
ps2.setUploader(new Account.Id(3000));
ps2.setRevision(new RevId("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"));
ps2.setCreatedOn(cols.lastUpdatedOn());
- ByteString ps2Bytes = toByteString(ps2, PATCH_SET_CODEC);
+ ByteString ps2Bytes = toByteString(ps2, PatchSetProtoConverter.INSTANCE);
assertThat(ps2Bytes.size()).isEqualTo(66);
assertThat(ps2Bytes).isNotEqualTo(ps1Bytes);
@@ -372,7 +372,7 @@
new PatchSet.Id(ID, 1), new Account.Id(2001), new LabelId("Code-Review")),
(short) 1,
new Timestamp(1212L));
- ByteString a1Bytes = toByteString(a1, APPROVAL_CODEC);
+ ByteString a1Bytes = toByteString(a1, PatchSetApprovalProtoConverter.INSTANCE);
assertThat(a1Bytes.size()).isEqualTo(43);
PatchSetApproval a2 =
@@ -381,7 +381,7 @@
new PatchSet.Id(ID, 1), new Account.Id(2002), new LabelId("Verified")),
(short) -1,
new Timestamp(3434L));
- ByteString a2Bytes = toByteString(a2, APPROVAL_CODEC);
+ ByteString a2Bytes = toByteString(a2, PatchSetApprovalProtoConverter.INSTANCE);
assertThat(a2Bytes.size()).isEqualTo(49);
assertThat(a2Bytes).isNotEqualTo(a1Bytes);
@@ -639,7 +639,7 @@
new Account.Id(1000),
new Timestamp(1212L),
new PatchSet.Id(ID, 1));
- ByteString m1Bytes = toByteString(m1, MESSAGE_CODEC);
+ ByteString m1Bytes = toByteString(m1, ChangeMessageProtoConverter.INSTANCE);
assertThat(m1Bytes.size()).isEqualTo(35);
ChangeMessage m2 =
@@ -648,7 +648,7 @@
new Account.Id(2000),
new Timestamp(3434L),
new PatchSet.Id(ID, 2));
- ByteString m2Bytes = toByteString(m2, MESSAGE_CODEC);
+ ByteString m2Bytes = toByteString(m2, ChangeMessageProtoConverter.INSTANCE);
assertThat(m2Bytes.size()).isEqualTo(35);
assertThat(m2Bytes).isNotEqualTo(m1Bytes);
diff --git a/javatests/com/google/gerrit/server/query/account/LuceneQueryAccountsTest.java b/javatests/com/google/gerrit/server/query/account/LuceneQueryAccountsTest.java
index 660c1d8..e36b79e 100644
--- a/javatests/com/google/gerrit/server/query/account/LuceneQueryAccountsTest.java
+++ b/javatests/com/google/gerrit/server/query/account/LuceneQueryAccountsTest.java
@@ -44,6 +44,6 @@
protected Injector createInjector() {
Config luceneConfig = new Config(config);
InMemoryModule.setDefaults(luceneConfig);
- return Guice.createInjector(new InMemoryModule(luceneConfig, notesMigration));
+ return Guice.createInjector(new InMemoryModule(luceneConfig));
}
}
diff --git a/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java b/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
index fb20a05..7d8f3c6 100644
--- a/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
+++ b/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
@@ -1303,7 +1303,7 @@
assertQuery("status:new", change2, change1);
gApi.changes().id(change1.getId().get()).topic("new-topic");
- change1 = notesFactory.create(db, change1.getProject(), change1.getId()).getChange();
+ change1 = notesFactory.create(change1.getProject(), change1.getId()).getChange();
assertThat(lastUpdatedMs(change1)).isGreaterThan(lastUpdatedMs(change2));
assertThat(lastUpdatedMs(change1) - lastUpdatedMs(change2))
@@ -2276,7 +2276,7 @@
TestRepository<Repo> repo = createProject(project.get());
Change change = insert(repo, newChange(repo));
String changeId = change.getKey().get();
- ChangeNotes notes = notesFactory.create(db, change.getProject(), change.getId());
+ ChangeNotes notes = notesFactory.create(change.getProject(), change.getId());
PatchSet ps = psUtil.get(notes, change.currentPatchSetId());
requestContext.setContext(newRequestContext(user));
@@ -2985,7 +2985,7 @@
PatchSetInserter inserter =
patchSetFactory
- .create(changeNotesFactory.createChecked(db, c), new PatchSet.Id(c.getId(), n), commit)
+ .create(changeNotesFactory.createChecked(c), new PatchSet.Id(c.getId(), n), commit)
.setNotify(NotifyHandling.NONE)
.setFireRevisionCreated(false)
.setValidate(false);
diff --git a/javatests/com/google/gerrit/server/query/change/BUILD b/javatests/com/google/gerrit/server/query/change/BUILD
index c27be68..7419405 100644
--- a/javatests/com/google/gerrit/server/query/change/BUILD
+++ b/javatests/com/google/gerrit/server/query/change/BUILD
@@ -61,6 +61,7 @@
visibility = ["//visibility:public"],
deps = [
"//java/com/google/gerrit/extensions:api",
+ "//java/com/google/gerrit/proto/testing",
"//java/com/google/gerrit/reviewdb:server",
"//java/com/google/gerrit/server",
"//java/com/google/gerrit/server/cache/testing",
diff --git a/javatests/com/google/gerrit/server/query/change/ConflictKeyTest.java b/javatests/com/google/gerrit/server/query/change/ConflictKeyTest.java
index 1683b56..e550f8e 100644
--- a/javatests/com/google/gerrit/server/query/change/ConflictKeyTest.java
+++ b/javatests/com/google/gerrit/server/query/change/ConflictKeyTest.java
@@ -18,11 +18,12 @@
import static com.google.common.truth.extensions.proto.ProtoTruth.assertThat;
import static com.google.gerrit.extensions.client.SubmitType.FAST_FORWARD_ONLY;
import static com.google.gerrit.extensions.client.SubmitType.MERGE_IF_NECESSARY;
+import static com.google.gerrit.proto.testing.SerializedClassSubject.assertThatSerializedClass;
import static com.google.gerrit.server.cache.testing.CacheSerializerTestUtil.byteString;
-import static com.google.gerrit.server.cache.testing.SerializedClassSubject.assertThatSerializedClass;
import com.google.common.collect.ImmutableMap;
import com.google.gerrit.extensions.client.SubmitType;
+import com.google.gerrit.proto.testing.SerializedClassSubject;
import com.google.gerrit.server.cache.proto.Cache.ConflictKeyProto;
import com.google.gerrit.testing.GerritBaseTests;
import org.eclipse.jgit.lib.ObjectId;
@@ -82,10 +83,7 @@
assertThat(ConflictKey.Serializer.INSTANCE.deserialize(serialized)).isEqualTo(key);
}
- /**
- * See {@link com.google.gerrit.server.cache.testing.SerializedClassSubject} for background and
- * what to do if this test fails.
- */
+ /** See {@link SerializedClassSubject} for background and what to do if this test fails. */
@Test
public void methods() throws Exception {
assertThatSerializedClass(ConflictKey.class)
diff --git a/javatests/com/google/gerrit/server/query/change/LuceneQueryChangesTest.java b/javatests/com/google/gerrit/server/query/change/LuceneQueryChangesTest.java
index 1dfe7df..2ea198f 100644
--- a/javatests/com/google/gerrit/server/query/change/LuceneQueryChangesTest.java
+++ b/javatests/com/google/gerrit/server/query/change/LuceneQueryChangesTest.java
@@ -49,7 +49,7 @@
protected Injector createInjector() {
Config luceneConfig = new Config(config);
InMemoryModule.setDefaults(luceneConfig);
- return Guice.createInjector(new InMemoryModule(luceneConfig, notesMigration));
+ return Guice.createInjector(new InMemoryModule(luceneConfig));
}
@Test
diff --git a/javatests/com/google/gerrit/server/query/group/LuceneQueryGroupsTest.java b/javatests/com/google/gerrit/server/query/group/LuceneQueryGroupsTest.java
index 83835c1..2a453a0 100644
--- a/javatests/com/google/gerrit/server/query/group/LuceneQueryGroupsTest.java
+++ b/javatests/com/google/gerrit/server/query/group/LuceneQueryGroupsTest.java
@@ -43,6 +43,6 @@
protected Injector createInjector() {
Config luceneConfig = new Config(config);
InMemoryModule.setDefaults(luceneConfig);
- return Guice.createInjector(new InMemoryModule(luceneConfig, notesMigration));
+ return Guice.createInjector(new InMemoryModule(luceneConfig));
}
}
diff --git a/javatests/com/google/gerrit/server/query/project/LuceneQueryProjectsTest.java b/javatests/com/google/gerrit/server/query/project/LuceneQueryProjectsTest.java
index 42964fa..77a56ed 100644
--- a/javatests/com/google/gerrit/server/query/project/LuceneQueryProjectsTest.java
+++ b/javatests/com/google/gerrit/server/query/project/LuceneQueryProjectsTest.java
@@ -45,6 +45,6 @@
protected Injector createInjector() {
Config luceneConfig = new Config(config);
InMemoryModule.setDefaults(luceneConfig);
- return Guice.createInjector(new InMemoryModule(luceneConfig, notesMigration));
+ return Guice.createInjector(new InMemoryModule(luceneConfig));
}
}
diff --git a/javatests/com/google/gerrit/server/schema/NoteDbSchemaUpdaterTest.java b/javatests/com/google/gerrit/server/schema/NoteDbSchemaUpdaterTest.java
index 6018d85..eeefd75 100644
--- a/javatests/com/google/gerrit/server/schema/NoteDbSchemaUpdaterTest.java
+++ b/javatests/com/google/gerrit/server/schema/NoteDbSchemaUpdaterTest.java
@@ -29,9 +29,8 @@
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.notedb.IntBlob;
-import com.google.gerrit.server.notedb.MutableNotesMigration;
import com.google.gerrit.server.notedb.NoteDbSchemaVersionManager;
-import com.google.gerrit.server.notedb.NotesMigrationState;
+import com.google.gerrit.server.notedb.NotesMigration;
import com.google.gerrit.server.notedb.RepoSequence;
import com.google.gerrit.testing.GerritBaseTests;
import com.google.gerrit.testing.InMemoryRepositoryManager;
@@ -117,8 +116,6 @@
args = new NoteDbSchemaVersion.Arguments(repoManager, allProjectsName);
NoteDbSchemaVersionManager versionManager =
new NoteDbSchemaVersionManager(allProjectsName, repoManager);
- MutableNotesMigration notesMigration = MutableNotesMigration.newDisabled();
- notesMigration.setFrom(NotesMigrationState.NOTE_DB);
updater =
new NoteDbSchemaUpdater(
cfg,
@@ -126,7 +123,7 @@
allUsersName,
repoManager,
schemaCreator,
- notesMigration,
+ new NotesMigration(),
versionManager,
args,
ImmutableSortedMap.of(10, TestSchema_10.class, 11, TestSchema_11.class));
diff --git a/plugins/delete-project b/plugins/delete-project
index d8fdd55..5f3fe72 160000
--- a/plugins/delete-project
+++ b/plugins/delete-project
@@ -1 +1 @@
-Subproject commit d8fdd5596181cc06707665051f0e03a49e5c3a97
+Subproject commit 5f3fe725b6f943f9acf63270cf8a432f9e7fd97a
diff --git a/plugins/reviewnotes b/plugins/reviewnotes
index fdbadf3..b98d892 160000
--- a/plugins/reviewnotes
+++ b/plugins/reviewnotes
@@ -1 +1 @@
-Subproject commit fdbadf312d829990d3a4be3491d13a79d6c0cf5b
+Subproject commit b98d8920345aa6183fe98ea9bc15ae0fea5d9b58
diff --git a/proto/BUILD b/proto/BUILD
index 88445c1..7f02a81 100644
--- a/proto/BUILD
+++ b/proto/BUILD
@@ -11,14 +11,11 @@
proto_library(
name = "reviewdb_proto",
- srcs = [":reviewdb.proto"],
+ srcs = ["reviewdb.proto"],
)
java_proto_library(
name = "reviewdb_java_proto",
- visibility = [
- "//javatests/com/google/gerrit/proto:__pkg__",
- "//tools/eclipse:__pkg__",
- ],
+ visibility = ["//visibility:public"],
deps = [":reviewdb_proto"],
)