Add schema migration to populate gpg subkey to master key map

Change-Id: I342413df1730395745cda837c90e71a09003d24c
diff --git a/java/com/google/gerrit/gpg/BUILD b/java/com/google/gerrit/gpg/BUILD
index fb93b03..06e44d6 100644
--- a/java/com/google/gerrit/gpg/BUILD
+++ b/java/com/google/gerrit/gpg/BUILD
@@ -3,6 +3,7 @@
     srcs = glob(["**/*.java"]),
     visibility = ["//visibility:public"],
     deps = [
+        "//java/com/google/gerrit/common:annotations",
         "//java/com/google/gerrit/common:server",
         "//java/com/google/gerrit/exceptions",
         "//java/com/google/gerrit/extensions:api",
diff --git a/java/com/google/gerrit/gpg/PublicKeyStore.java b/java/com/google/gerrit/gpg/PublicKeyStore.java
index 4c14049..6051d2f 100644
--- a/java/com/google/gerrit/gpg/PublicKeyStore.java
+++ b/java/com/google/gerrit/gpg/PublicKeyStore.java
@@ -272,6 +272,25 @@
     }
   }
 
+  public void rebuildSubkeyMasterKeyMap()
+      throws MissingObjectException, IncorrectObjectTypeException, IOException, PGPException {
+    if (reader == null) {
+      load();
+    }
+    if (notes != null) {
+      try (ObjectInserter ins = repo.newObjectInserter()) {
+        for (Note note : notes) {
+          for (PGPPublicKeyRing keyRing :
+              new PGPPublicKeyRingCollection(readKeysFromNote(note, null))) {
+            long masterKeyId = keyRing.getPublicKey().getKeyID();
+            ObjectId masterKeyObjectId = keyObjectId(masterKeyId);
+            saveSubkeyMaping(ins, keyRing, masterKeyId, masterKeyObjectId);
+          }
+        }
+      }
+    }
+  }
+
   /**
    * Add a public key to the store.
    *
diff --git a/java/com/google/gerrit/server/schema/BUILD b/java/com/google/gerrit/server/schema/BUILD
index 2f0b649..6a97954 100644
--- a/java/com/google/gerrit/server/schema/BUILD
+++ b/java/com/google/gerrit/server/schema/BUILD
@@ -10,6 +10,7 @@
         "//java/com/google/gerrit/exceptions",
         "//java/com/google/gerrit/extensions:api",
         "//java/com/google/gerrit/git",
+        "//java/com/google/gerrit/gpg",
         "//java/com/google/gerrit/lifecycle",
         "//java/com/google/gerrit/metrics",
         "//java/com/google/gerrit/reviewdb:server",
diff --git a/java/com/google/gerrit/server/schema/NoteDbSchemaVersion.java b/java/com/google/gerrit/server/schema/NoteDbSchemaVersion.java
index 75a1de2..b6a7a1c 100644
--- a/java/com/google/gerrit/server/schema/NoteDbSchemaVersion.java
+++ b/java/com/google/gerrit/server/schema/NoteDbSchemaVersion.java
@@ -15,6 +15,7 @@
 package com.google.gerrit.server.schema;
 
 import com.google.gerrit.server.config.AllProjectsName;
+import com.google.gerrit.server.config.AllUsersName;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
@@ -30,11 +31,14 @@
   class Arguments {
     final GitRepositoryManager repoManager;
     final AllProjectsName allProjects;
+    final AllUsersName allUsers;
 
     @Inject
-    Arguments(GitRepositoryManager repoManager, AllProjectsName allProjects) {
+    Arguments(
+        GitRepositoryManager repoManager, AllProjectsName allProjects, AllUsersName allUsers) {
       this.repoManager = repoManager;
       this.allProjects = allProjects;
+      this.allUsers = allUsers;
     }
   }
 
diff --git a/java/com/google/gerrit/server/schema/NoteDbSchemaVersions.java b/java/com/google/gerrit/server/schema/NoteDbSchemaVersions.java
index 3f7c989..02250f2 100644
--- a/java/com/google/gerrit/server/schema/NoteDbSchemaVersions.java
+++ b/java/com/google/gerrit/server/schema/NoteDbSchemaVersions.java
@@ -28,7 +28,7 @@
 public class NoteDbSchemaVersions {
   static final ImmutableSortedMap<Integer, Class<? extends NoteDbSchemaVersion>> ALL =
       // List all supported NoteDb schema versions here.
-      Stream.of(Schema_180.class)
+      Stream.of(Schema_180.class, Schema_181.class)
           .collect(toImmutableSortedMap(naturalOrder(), v -> guessVersion(v).get(), v -> v));
 
   public static final int FIRST = ALL.firstKey();
diff --git a/java/com/google/gerrit/server/schema/Schema_181.java b/java/com/google/gerrit/server/schema/Schema_181.java
new file mode 100644
index 0000000..3054ad3
--- /dev/null
+++ b/java/com/google/gerrit/server/schema/Schema_181.java
@@ -0,0 +1,29 @@
+// 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.schema;
+
+import com.google.gerrit.gpg.PublicKeyStore;
+import org.eclipse.jgit.lib.Repository;
+
+public class Schema_181 implements NoteDbSchemaVersion {
+  @Override
+  public void upgrade(Arguments args, UpdateUI ui) throws Exception {
+    ui.message("Rebuild GPGP note map to build subkey to master key map");
+    try (Repository repo = args.repoManager.openRepository(args.allUsers);
+        PublicKeyStore store = new PublicKeyStore(repo)) {
+      store.rebuildSubkeyMasterKeyMap();
+    }
+  }
+}
diff --git a/javatests/com/google/gerrit/server/schema/NoteDbSchemaUpdaterTest.java b/javatests/com/google/gerrit/server/schema/NoteDbSchemaUpdaterTest.java
index bbbcff6..b6887cf 100644
--- a/javatests/com/google/gerrit/server/schema/NoteDbSchemaUpdaterTest.java
+++ b/javatests/com/google/gerrit/server/schema/NoteDbSchemaUpdaterTest.java
@@ -99,7 +99,7 @@
       allUsersName = new AllUsersName("The-Users");
       repoManager = new InMemoryRepositoryManager();
 
-      args = new NoteDbSchemaVersion.Arguments(repoManager, allProjectsName);
+      args = new NoteDbSchemaVersion.Arguments(repoManager, allProjectsName, allUsersName);
       NoteDbSchemaVersionManager versionManager =
           new NoteDbSchemaVersionManager(allProjectsName, repoManager);
       updater =