Merge "Remove REST endpoint to rebuild individual groups in NoteDb"
diff --git a/java/com/google/gerrit/server/restapi/group/Module.java b/java/com/google/gerrit/server/restapi/group/Module.java
index 7410ee2..fa1e5c7 100644
--- a/java/com/google/gerrit/server/restapi/group/Module.java
+++ b/java/com/google/gerrit/server/restapi/group/Module.java
@@ -60,7 +60,6 @@
     get(GROUP_KIND, "options").to(GetOptions.class);
     put(GROUP_KIND, "options").to(PutOptions.class);
     get(GROUP_KIND, "log.audit").to(GetAuditLog.class);
-    post(GROUP_KIND, "rebuild").to(Rebuild.class);
 
     child(GROUP_KIND, "members").to(MembersCollection.class);
     get(MEMBER_KIND).to(GetMember.class);
diff --git a/java/com/google/gerrit/server/restapi/group/Rebuild.java b/java/com/google/gerrit/server/restapi/group/Rebuild.java
deleted file mode 100644
index 9e8cb3f..0000000
--- a/java/com/google/gerrit/server/restapi/group/Rebuild.java
+++ /dev/null
@@ -1,117 +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.restapi.group;
-
-import static com.google.common.base.MoreObjects.firstNonNull;
-import static java.util.stream.Collectors.joining;
-
-import com.google.gerrit.common.data.GlobalCapability;
-import com.google.gerrit.extensions.annotations.RequiresCapability;
-import com.google.gerrit.extensions.restapi.BinaryResult;
-import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
-import com.google.gerrit.extensions.restapi.ResourceConflictException;
-import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.extensions.restapi.RestModifyView;
-import com.google.gerrit.reviewdb.client.AccountGroup;
-import com.google.gerrit.reviewdb.client.RefNames;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.config.AllUsersName;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.group.GroupResource;
-import com.google.gerrit.server.group.db.GroupBundle;
-import com.google.gerrit.server.group.db.GroupRebuilder;
-import com.google.gerrit.server.notedb.GroupsMigration;
-import com.google.gerrit.server.restapi.group.Rebuild.Input;
-import com.google.gerrit.server.update.RefUpdateUtil;
-import com.google.gwtorm.server.OrmDuplicateKeyException;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import com.google.inject.Singleton;
-import java.io.IOException;
-import java.util.List;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.lib.Repository;
-
-@RequiresCapability(GlobalCapability.ADMINISTRATE_SERVER)
-@Singleton
-public class Rebuild implements RestModifyView<GroupResource, Input> {
-  public static class Input {
-    public Boolean force;
-  }
-
-  private final AllUsersName allUsers;
-  private final GitRepositoryManager repoManager;
-  private final GroupBundle.Factory bundleFactory;
-  private final GroupRebuilder rebuilder;
-  private final GroupsMigration migration;
-  private final Provider<ReviewDb> db;
-
-  @Inject
-  Rebuild(
-      AllUsersName allUsers,
-      GitRepositoryManager repoManager,
-      GroupBundle.Factory bundleFactory,
-      GroupRebuilder rebuilder,
-      GroupsMigration migration,
-      Provider<ReviewDb> db) {
-    this.allUsers = allUsers;
-    this.repoManager = repoManager;
-    this.bundleFactory = bundleFactory;
-    this.rebuilder = rebuilder;
-    this.migration = migration;
-    this.db = db;
-  }
-
-  @Override
-  public BinaryResult apply(GroupResource rsrc, Input input)
-      throws RestApiException, ConfigInvalidException, OrmException, IOException {
-    boolean force = firstNonNull(input.force, false);
-    if (!migration.writeToNoteDb()) {
-      throw new MethodNotAllowedException("NoteDb writes must be enabled");
-    }
-    if (migration.readFromNoteDb() && force) {
-      throw new MethodNotAllowedException("NoteDb reads must not be enabled when force=true");
-    }
-    if (!rsrc.isInternalGroup()) {
-      throw new MethodNotAllowedException("Not an internal group");
-    }
-
-    AccountGroup.UUID uuid = rsrc.getGroup().getGroupUUID();
-    try (Repository repo = repoManager.openRepository(allUsers)) {
-      if (force) {
-        RefUpdateUtil.deleteChecked(repo, RefNames.refsGroups(uuid));
-      }
-      GroupBundle reviewDbBundle =
-          bundleFactory.fromReviewDb(db.get(), rsrc.asInternalGroup().get().getId());
-      try {
-        rebuilder.rebuild(repo, reviewDbBundle, null);
-      } catch (OrmDuplicateKeyException e) {
-        throw new ResourceConflictException("Group already exists in NoteDb");
-      }
-
-      GroupBundle noteDbBundle = bundleFactory.fromNoteDb(repo, uuid);
-
-      List<String> diffs = GroupBundle.compareWithAudits(reviewDbBundle, noteDbBundle);
-      if (diffs.isEmpty()) {
-        return BinaryResult.create("No differences between ReviewDb and NoteDb");
-      }
-      return BinaryResult.create(
-          diffs
-              .stream()
-              .collect(joining("\n", "Differences between ReviewDb and NoteDb:\n", "\n")));
-    }
-  }
-}
diff --git a/javatests/com/google/gerrit/acceptance/rest/group/GroupsIT.java b/javatests/com/google/gerrit/acceptance/rest/group/GroupsIT.java
index a52dd6d..e153e561 100644
--- a/javatests/com/google/gerrit/acceptance/rest/group/GroupsIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/group/GroupsIT.java
@@ -15,27 +15,12 @@
 package com.google.gerrit.acceptance.rest.group;
 
 import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.TruthJUnit.assume;
 
 import com.google.gerrit.acceptance.AbstractDaemonTest;
 import com.google.gerrit.acceptance.RestResponse;
-import com.google.gerrit.extensions.common.GroupInfo;
-import com.google.gerrit.reviewdb.client.AccountGroup;
-import com.google.gerrit.reviewdb.client.RefNames;
-import com.google.gerrit.server.group.db.GroupBundle;
-import com.google.gerrit.server.notedb.GroupsMigration;
-import com.google.gerrit.server.restapi.group.Rebuild;
-import com.google.inject.Inject;
-import org.eclipse.jgit.junit.TestRepository;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.Ref;
-import org.eclipse.jgit.lib.Repository;
 import org.junit.Test;
 
 public class GroupsIT extends AbstractDaemonTest {
-  @Inject private GroupsMigration groupsMigration;
-  @Inject private GroupBundle.Factory bundleFactory;
-
   @Test
   public void invalidQueryOptions() throws Exception {
     RestResponse r = adminRestSession.put("/groups/?query=foo&query2=bar");
@@ -43,138 +28,4 @@
     assertThat(r.getEntityContent())
         .isEqualTo("\"query\" and \"query2\" options are mutually exclusive");
   }
-
-  @Test
-  public void rebuild() throws Exception {
-    assume().that(groupsMigration.writeToNoteDb()).isTrue();
-    assume().that(groupsMigration.readFromNoteDb()).isFalse();
-
-    GroupInfo g = gApi.groups().create(name("group")).get();
-    AccountGroup.UUID uuid = new AccountGroup.UUID(g.id);
-    String refName = RefNames.refsGroups(uuid);
-    ObjectId oldId;
-    GroupBundle oldBundle;
-    try (Repository repo = repoManager.openRepository(allUsers)) {
-      oldId = repo.exactRef(refName).getObjectId();
-      oldBundle = bundleFactory.fromNoteDb(repo, uuid);
-      new TestRepository<>(repo).delete(refName);
-    }
-
-    assertThat(
-            adminRestSession.postOK("/groups/" + uuid + "/rebuild", input(null)).getEntityContent())
-        .isEqualTo("No differences between ReviewDb and NoteDb");
-
-    try (Repository repo = repoManager.openRepository(allUsers)) {
-      Ref ref = repo.exactRef(refName);
-      assertThat(ref).isNotNull();
-
-      // An artifact of the migration process makes the SHA-1 different, but it's actually ok
-      // because the bundles are equal.
-      assertThat(ref.getObjectId()).isNotEqualTo(oldId);
-
-      assertNoDifferences(oldBundle, bundleFactory.fromNoteDb(repo, uuid));
-    }
-  }
-
-  @Test
-  public void rebuildFailsWithWritesDisabled() throws Exception {
-    assume().that(groupsMigration.writeToNoteDb()).isFalse();
-
-    GroupInfo g = gApi.groups().create(name("group")).get();
-    AccountGroup.UUID uuid = new AccountGroup.UUID(g.id);
-
-    RestResponse res = adminRestSession.post("/groups/" + uuid + "/rebuild", input(null));
-    assertThat(res.getStatusCode()).isEqualTo(405);
-    assertThat(res.getEntityContent()).isEqualTo("NoteDb writes must be enabled");
-  }
-
-  @Test
-  public void rebuildForceRequiresReadsDisabled() throws Exception {
-    assume().that(groupsMigration.writeToNoteDb()).isTrue();
-    assume().that(groupsMigration.readFromNoteDb()).isTrue();
-
-    GroupInfo g = gApi.groups().create(name("group")).get();
-    AccountGroup.UUID uuid = new AccountGroup.UUID(g.id);
-
-    RestResponse res = adminRestSession.post("/groups/" + uuid + "/rebuild", input(true));
-    assertThat(res.getStatusCode()).isEqualTo(405);
-    assertThat(res.getEntityContent())
-        .isEqualTo("NoteDb reads must not be enabled when force=true");
-  }
-
-  @Test
-  public void rebuildWithoutForceFailsIfRefExists() throws Exception {
-    assume().that(groupsMigration.writeToNoteDb()).isTrue();
-    assume().that(groupsMigration.readFromNoteDb()).isFalse();
-
-    GroupInfo g = gApi.groups().create(name("group")).get();
-    AccountGroup.UUID uuid = new AccountGroup.UUID(g.id);
-    String refName = RefNames.refsGroups(uuid);
-
-    try (Repository repo = repoManager.openRepository(allUsers)) {
-      new TestRepository<>(repo)
-          .branch(refName)
-          .commit()
-          .add("somefile", "contents")
-          .create()
-          .copy();
-    }
-
-    RestResponse res = adminRestSession.post("/groups/" + uuid + "/rebuild", input(null));
-    assertThat(res.getStatusCode()).isEqualTo(409);
-    assertThat(res.getEntityContent()).isEqualTo("Group already exists in NoteDb");
-  }
-
-  @Test
-  public void rebuildForce() throws Exception {
-    assume().that(groupsMigration.writeToNoteDb()).isTrue();
-    assume().that(groupsMigration.readFromNoteDb()).isFalse();
-
-    GroupInfo g = gApi.groups().create(name("group")).get();
-    AccountGroup.UUID uuid = new AccountGroup.UUID(g.id);
-    String refName = RefNames.refsGroups(uuid);
-
-    ObjectId oldId;
-    GroupBundle oldBundle;
-    try (Repository repo = repoManager.openRepository(allUsers)) {
-      oldBundle = bundleFactory.fromNoteDb(repo, uuid);
-
-      oldId =
-          new TestRepository<>(repo)
-              .branch(refName)
-              .commit()
-              .add("somefile", "contents")
-              .create()
-              .copy();
-    }
-
-    assertThat(
-            adminRestSession.postOK("/groups/" + uuid + "/rebuild", input(true)).getEntityContent())
-        .isEqualTo("No differences between ReviewDb and NoteDb");
-
-    try (Repository repo = repoManager.openRepository(allUsers)) {
-      Ref ref = repo.exactRef(refName);
-      assertThat(ref).isNotNull();
-
-      // oldId contains some garbage, so rebuilt value should definitely be different.
-      assertThat(ref.getObjectId()).isNotEqualTo(oldId);
-
-      assertNoDifferences(oldBundle, bundleFactory.fromNoteDb(repo, uuid));
-    }
-  }
-
-  private static void assertNoDifferences(GroupBundle expected, GroupBundle actual) {
-    // Comparing NoteDb to NoteDb, so compare fields instead of using static compare method.
-    assertThat(actual.group()).isEqualTo(expected.group());
-    assertThat(actual.members()).isEqualTo(expected.members());
-    assertThat(actual.memberAudit()).isEqualTo(expected.memberAudit());
-    assertThat(actual.byId()).isEqualTo(expected.byId());
-    assertThat(actual.byIdAudit()).isEqualTo(expected.byIdAudit());
-  }
-
-  private static Rebuild.Input input(Boolean force) {
-    Rebuild.Input input = new Rebuild.Input();
-    input.force = force;
-    return input;
-  }
 }