Merge branch 'stable-2.16' into stable-3.0
* stable-2.16:
Change log messages of noteDb case to match reviewDb case
Add error handling if rename was not successful
Upgrade bazlets to latest stable-2.16 to build with 2.16.13 API
Add support for NoteDb
Change-Id: Icb56d3bddff6c217af1f53722f41548949f87144
diff --git a/README.md b/README.md
index 1ed0bf5..e14491a 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,6 @@
# Rename project plugin for Gerrit Code Review
-This plugin currently supports Gerrit version 2.14.X and 2.15.X with changes in reviewDb, noteDB is not yet supported.
+This plugin currently supports Gerrit version 2.14.X and 2.15.X with changes in reviewDb.
+Also supported is the noteDb alternative for Gerrit versions 2.15.X and above.
For more information, see: `src/main/resources/Documentation/about.md`
diff --git a/src/main/java/com/googlesource/gerrit/plugins/renameproject/RenameProject.java b/src/main/java/com/googlesource/gerrit/plugins/renameproject/RenameProject.java
index 8d4f7ca..17ec0a7 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/renameproject/RenameProject.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/renameproject/RenameProject.java
@@ -152,7 +152,7 @@
}
void doRename(List<Change.Id> changeIds, ProjectResource rsrc, Input input, ProgressMonitor pm)
- throws InterruptedException, ConfigInvalidException, IOException {
+ throws InterruptedException, ConfigInvalidException, IOException, RenameRevertException {
Project.NameKey oldProjectKey = rsrc.getNameKey();
Project.NameKey newProjectKey = new Project.NameKey(input.name);
Exception ex = null;
@@ -161,8 +161,7 @@
log.debug("Renamed the git repo to {} successfully.", newProjectKey.get());
cacheHandler.update(rsrc.getProjectState().getProject(), newProjectKey);
- List<Change.Id> updatedChangeIds =
- dbHandler.rename(changeIds, newProjectKey, pm);
+ List<Change.Id> updatedChangeIds = dbHandler.rename(changeIds, newProjectKey, pm);
log.debug("Updated the changes in DB successfully for project {}.", oldProjectKey.get());
// if the DB update is successful, update the secondary index
diff --git a/src/main/java/com/googlesource/gerrit/plugins/renameproject/RenameRevertException.java b/src/main/java/com/googlesource/gerrit/plugins/renameproject/RenameRevertException.java
new file mode 100644
index 0000000..d6252b9
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/renameproject/RenameRevertException.java
@@ -0,0 +1,23 @@
+// Copyright (C) 2019 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.googlesource.gerrit.plugins.renameproject;
+
+/** Add cause for exception during revert operation */
+public class RenameRevertException extends Exception {
+ public RenameRevertException(Throwable revertException, Throwable cause) {
+ super(
+ "Failed to revert after failed rename. Revert cause: " + cause.getMessage(),
+ revertException.initCause(cause));
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/renameproject/database/DatabaseRenameHandler.java b/src/main/java/com/googlesource/gerrit/plugins/renameproject/database/DatabaseRenameHandler.java
index 8c57dfc..97cd59f 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/renameproject/database/DatabaseRenameHandler.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/renameproject/database/DatabaseRenameHandler.java
@@ -19,7 +19,6 @@
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.ServerInitiated;
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.account.AccountsUpdate;
@@ -28,16 +27,14 @@
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.ChangeNotes.Factory.ChangeNotesResult;
-import com.google.gerrit.server.notedb.ChangeUpdate;
import com.google.gerrit.server.query.account.InternalAccountQuery;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
+import com.googlesource.gerrit.plugins.renameproject.RenameRevertException;
import com.googlesource.gerrit.plugins.renameproject.monitor.ProgressMonitor;
import java.io.IOException;
-import java.time.Instant;
import java.util.ArrayList;
-import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -53,28 +50,21 @@
private static final Logger log = LoggerFactory.getLogger(DatabaseRenameHandler.class);
private final ChangeNotes.Factory schemaFactory;
- private final ChangeUpdate.Factory updateFactory;
private final GitRepositoryManager repoManager;
- private final Provider<CurrentUser> userProvider;
private final Provider<InternalAccountQuery> accountQueryProvider;
private final Provider<AccountsUpdate> accountsUpdateProvider;
- private final Map<Change.Id, ChangeNotes> changeNotes = new HashMap<>();
private Project.NameKey oldProjectKey;
@Inject
public DatabaseRenameHandler(
ChangeNotes.Factory schemaFactory,
- ChangeUpdate.Factory updateFactory,
GitRepositoryManager repoManager,
- Provider<CurrentUser> userProvider,
Provider<InternalAccountQuery> accountQueryProvider,
@ServerInitiated Provider<AccountsUpdate> accountsUpdateProvider) {
this.accountQueryProvider = accountQueryProvider;
this.schemaFactory = schemaFactory;
- this.updateFactory = updateFactory;
this.repoManager = repoManager;
- this.userProvider = userProvider;
this.accountsUpdateProvider = accountsUpdateProvider;
}
@@ -90,10 +80,9 @@
ChangeNotesResult change = iterator.next();
Change.Id changeId = change.id();
changeIds.add(changeId);
- changeNotes.put(changeId, change.notes());
}
log.debug(
- "Number of changes related to the project {} are {}",
+ "Number of changes in noteDb related to project {} are {}",
oldProjectKey.get(),
changeIds.size());
return changeIds;
@@ -101,62 +90,36 @@
public List<Change.Id> rename(
List<Change.Id> changes, Project.NameKey newProjectKey, ProgressMonitor pm)
- throws IOException {
+ throws RenameRevertException, IOException, ConfigInvalidException {
pm.beginTask("Updating changes in the database");
- log.debug("Updating the changes in the DB related to project {}", oldProjectKey.get());
- List<ChangeUpdate> updates = getChangeUpdates(changes, newProjectKey);
- updateWatchEntries(newProjectKey);
- List<Change> updated = new ArrayList<>();
+ log.debug("Updating the changes in noteDb related to project {}", oldProjectKey.get());
try {
- for (ChangeUpdate update : updates) {
- update.commit();
- updated.add(update.getChange());
- }
- } catch (IOException e) {
- // TODO(mmiller): Consider covering this path with tests, albeit exceptional.
+ updateWatchEntries(newProjectKey);
+ } catch (Exception e) {
log.error(
- "Failed to update changes in the DB for the project {}, rolling back the operation.",
- oldProjectKey.get());
- rollback(updated, newProjectKey);
+ "Failed to update changes in noteDb for project {}, exception caught: {}. Rolling back the operation.",
+ oldProjectKey.get(),
+ e.toString());
+ try {
+ updateWatchEntries(newProjectKey);
+ } catch (Exception revertEx) {
+ log.error(
+ "Failed to rollback changes in noteDb from project {} to project {}, exception caught: {}",
+ newProjectKey.get(),
+ oldProjectKey.get(),
+ revertEx.toString());
+ throw new RenameRevertException(revertEx, e);
+ }
throw e;
}
+
log.debug(
- "Successfully updated the changes in the DB related to project {}", oldProjectKey.get());
+ "Successfully updated the changes in noteDb related to project {}", oldProjectKey.get());
return changes;
}
- private List<ChangeUpdate> getChangeUpdates(List<Change.Id> changeIds, Project.NameKey nameKey) {
- List<ChangeUpdate> updates = new ArrayList<>();
- Date from = Date.from(Instant.now());
- changeIds.forEach(
- changeId -> {
- ChangeNotes notes = schemaFactory.create(nameKey, changeId);
- ChangeUpdate update = updateFactory.create(notes, userProvider.get(), from);
- updates.add(update);
- });
- return updates;
- }
-
- private void rollback(List<Change> changes, Project.NameKey newProjectKey) {
- Date from = Date.from(Instant.now());
- changes.forEach(
- change -> {
- ChangeNotes notes = changeNotes.get(change.getId());
- ChangeUpdate revert = updateFactory.create(notes, userProvider.get(), from);
- revert.setRevertOf(change.getChangeId());
- try {
- revert.commit();
- } catch (IOException ex) {
- log.error(
- "Failed to rollback change {} in DB from project {} to {}; rolling back others still.",
- change.getChangeId(),
- newProjectKey.get(),
- oldProjectKey.get());
- }
- });
- }
-
- private void updateWatchEntries(Project.NameKey newProjectKey) {
+ private void updateWatchEntries(Project.NameKey newProjectKey)
+ throws IOException, ConfigInvalidException {
for (AccountState a : accountQueryProvider.get().byWatchedProject(oldProjectKey)) {
Account.Id accountId = a.getAccount().getId();
ImmutableMap<ProjectWatchKey, ImmutableSet<NotifyType>> projectWatches =
@@ -190,12 +153,14 @@
a.getUserName(),
newProjectKey.get(),
e);
+ throw e;
} catch (IOException e) {
log.error(
"Updating watch entry for user {} in project {} failed.",
a.getUserName(),
newProjectKey.get(),
e);
+ throw e;
}
}
}