Merge "Merge branch 'stable-2.16'"
diff --git a/java/com/google/gerrit/pgm/ProtobufImport.java b/java/com/google/gerrit/pgm/ProtobufImport.java
deleted file mode 100644
index 0335cbb..0000000
--- a/java/com/google/gerrit/pgm/ProtobufImport.java
+++ /dev/null
@@ -1,146 +0,0 @@
-// Copyright (C) 2015 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;
-
-import static com.google.common.base.Preconditions.checkState;
-import static java.util.Objects.requireNonNull;
-
-import com.google.auto.value.AutoValue;
-import com.google.common.collect.Iterables;
-import com.google.gerrit.lifecycle.LifecycleManager;
-import com.google.gerrit.pgm.util.RuntimeShutdown;
-import com.google.gerrit.pgm.util.SiteProgram;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gwtorm.protobuf.CodecFactory;
-import com.google.gwtorm.protobuf.ProtobufCodec;
-import com.google.gwtorm.schema.RelationModel;
-import com.google.gwtorm.schema.java.JavaSchemaModel;
-import com.google.gwtorm.server.Access;
-import com.google.gwtorm.server.OrmDuplicateKeyException;
-import com.google.gwtorm.server.OrmException;
-import com.google.gwtorm.server.SchemaFactory;
-import com.google.inject.Inject;
-import com.google.inject.Injector;
-import com.google.protobuf.ByteString;
-import com.google.protobuf.Parser;
-import com.google.protobuf.UnknownFieldSet;
-import java.io.BufferedInputStream;
-import java.io.File;
-import java.io.InputStream;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.nio.file.Files;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import org.eclipse.jgit.lib.ProgressMonitor;
-import org.eclipse.jgit.lib.TextProgressMonitor;
-import org.kohsuke.args4j.Option;
-
-/**
- * Import data from a protocol buffer dump into the database.
- *
- * <p>Takes as input a file containing protocol buffers concatenated together with varint length
- * encoding, as in {@link Parser#parseDelimitedFrom(InputStream)}. Each message contains a single
- * field with a tag corresponding to the relation ID in the {@link
- * com.google.gwtorm.server.Relation} annotation.
- *
- * <p><strong>Warning</strong>: This method blindly upserts data into the database. It should only
- * be used to restore a protobuf-formatted backup into a new, empty site.
- */
-// TODO(dborowitz): Delete this program.
-public class ProtobufImport extends SiteProgram {
-  @Option(
-      name = "--file",
-      aliases = {"-f"},
-      required = true,
-      metaVar = "FILE",
-      usage = "File to import from")
-  private File file;
-
-  private final LifecycleManager manager = new LifecycleManager();
-  private final Map<Integer, Relation> relations = new HashMap<>();
-
-  @Inject private SchemaFactory<ReviewDb> schemaFactory;
-
-  @Override
-  public int run() throws Exception {
-    mustHaveValidSite();
-
-    Injector dbInjector = createDbInjector();
-    manager.add(dbInjector);
-    manager.start();
-    RuntimeShutdown.add(manager::stop);
-    dbInjector.injectMembers(this);
-
-    ProgressMonitor progress = new TextProgressMonitor();
-    progress.beginTask("Importing entities", ProgressMonitor.UNKNOWN);
-    try (ReviewDb db = schemaFactory.open()) {
-      for (RelationModel model : new JavaSchemaModel(ReviewDb.class).getRelations()) {
-        relations.put(model.getRelationID(), Relation.create(model, db));
-      }
-
-      Parser<UnknownFieldSet> parser = UnknownFieldSet.getDefaultInstance().getParserForType();
-      try (InputStream in = new BufferedInputStream(Files.newInputStream(file.toPath()))) {
-        UnknownFieldSet msg;
-        while ((msg = parser.parseDelimitedFrom(in)) != null) {
-          Map.Entry<Integer, UnknownFieldSet.Field> e =
-              Iterables.getOnlyElement(msg.asMap().entrySet());
-          Relation rel =
-              requireNonNull(
-                  relations.get(e.getKey()),
-                  String.format("unknown relation ID %s in message: %s", e.getKey(), msg));
-          List<ByteString> values = e.getValue().getLengthDelimitedList();
-          checkState(values.size() == 1, "expected one string field in message: %s", msg);
-          upsert(rel, values.get(0));
-          progress.update(1);
-        }
-      }
-      progress.endTask();
-    }
-
-    return 0;
-  }
-
-  @SuppressWarnings({"rawtypes", "unchecked"})
-  private static void upsert(Relation rel, ByteString s) throws OrmException {
-    Collection ents = Collections.singleton(rel.codec().decode(s));
-    try {
-      // Not all relations support update; fall back manually.
-      rel.access().insert(ents);
-    } catch (OrmDuplicateKeyException e) {
-      rel.access().delete(ents);
-      rel.access().insert(ents);
-    }
-  }
-
-  @AutoValue
-  abstract static class Relation {
-    private static Relation create(RelationModel model, ReviewDb db)
-        throws IllegalAccessException, InvocationTargetException, NoSuchMethodException,
-            ClassNotFoundException {
-      Method m = db.getClass().getMethod(model.getMethodName());
-      Class<?> clazz = Class.forName(model.getEntityTypeClassName());
-      return new AutoValue_ProtobufImport_Relation(
-          (Access<?, ?>) m.invoke(db), CodecFactory.encoder(clazz));
-    }
-
-    abstract Access<?, ?> access();
-
-    abstract ProtobufCodec<?> codec();
-  }
-}
diff --git a/java/com/google/gerrit/reviewdb/client/Comment.java b/java/com/google/gerrit/reviewdb/client/Comment.java
index 207643e..ce51dde 100644
--- a/java/com/google/gerrit/reviewdb/client/Comment.java
+++ b/java/com/google/gerrit/reviewdb/client/Comment.java
@@ -283,15 +283,41 @@
 
   @Override
   public boolean equals(Object o) {
-    if (o instanceof Comment) {
-      return Objects.equals(key, ((Comment) o).key);
+    if (!(o instanceof Comment)) {
+      return false;
     }
-    return false;
+    Comment c = (Comment) o;
+    return Objects.equals(key, c.key)
+        && lineNbr == c.lineNbr
+        && Objects.equals(author, c.author)
+        && Objects.equals(realAuthor, c.realAuthor)
+        && Objects.equals(writtenOn, c.writtenOn)
+        && side == c.side
+        && Objects.equals(message, c.message)
+        && Objects.equals(parentUuid, c.parentUuid)
+        && Objects.equals(range, c.range)
+        && Objects.equals(tag, c.tag)
+        && Objects.equals(revId, c.revId)
+        && Objects.equals(serverId, c.serverId)
+        && unresolved == c.unresolved;
   }
 
   @Override
   public int hashCode() {
-    return key.hashCode();
+    return Objects.hash(
+        key,
+        lineNbr,
+        author,
+        realAuthor,
+        writtenOn,
+        side,
+        message,
+        parentUuid,
+        range,
+        tag,
+        revId,
+        serverId,
+        unresolved);
   }
 
   @Override