Abandon any open changes if a project has been removed

If the Git repository has been deleted and a change has been
submitted in that repository MergeOp will contiuously try to
submit changes in that project, failing on every attempt when
openRepository() fails.

Catch this failure and abandon all changes in the project, as the
Git data no longer exists.

Change-Id: I83087211b281c1e478c0e83b48b8f7d158a93c13
This commit is contained in:
Shawn Pearce
2013-09-11 12:33:18 -07:00
parent 94c8e1d524
commit 1eda8192c2

View File

@@ -38,6 +38,7 @@ import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.Project.SubmitType;
import com.google.gerrit.reviewdb.client.RevId;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.ApprovalsUtil;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.AccountCache;
@@ -211,7 +212,7 @@ public class MergeOp {
}
}
public void merge() throws MergeException, NoSuchProjectException {
public void merge() throws MergeException {
setDestProject();
try {
openSchema();
@@ -270,6 +271,11 @@ public class MergeOp {
message(commit.change, capable.getMessage()), false);
}
}
} catch (NoSuchProjectException noProject) {
log.warn(String.format(
"Project %s no longer exists, abandoning open changes",
destBranch.getParentKey().get()));
abandonAllOpenChanges();
} catch (OrmException e) {
throw new MergeException("Cannot query the database", e);
} finally {
@@ -343,13 +349,12 @@ public class MergeOp {
canMergeFlag, getAlreadyAccepted(branchTip), destBranch);
}
private void openRepository() throws MergeException {
private void openRepository() throws MergeException, NoSuchProjectException {
final Project.NameKey name = destBranch.getParentKey();
try {
repo = repoManager.openRepository(name);
} catch (RepositoryNotFoundException notGit) {
final String m = "Repository \"" + name.get() + "\" unknown.";
throw new MergeException(m, notGit);
} catch (RepositoryNotFoundException notFound) {
throw new NoSuchProjectException(name, notFound);
} catch (IOException err) {
final String m = "Error opening repository \"" + name.get() + '"';
throw new MergeException(m, err);
@@ -1041,4 +1046,53 @@ public class MergeOp {
}
}
}
private void abandonAllOpenChanges() {
try {
openSchema();
for (Change c : db.changes().byProjectOpenAll(destBranch.getParentKey())) {
abandonOneChange(c);
}
db.close();
db = null;
} catch (OrmException e) {
log.warn(String.format(
"Cannot abandon changes for deleted project %s",
destBranch.getParentKey().get()), e);
}
}
private void abandonOneChange(Change change) throws OrmException {
db.changes().beginTransaction(change.getId());
try {
change = db.changes().atomicUpdate(
change.getId(),
new AtomicUpdate<Change>() {
@Override
public Change update(Change change) {
if (change.getStatus().isOpen()) {
change.setStatus(Change.Status.ABANDONED);
return change;
}
return null;
}
});
if (change != null) {
ChangeMessage msg = new ChangeMessage(
new ChangeMessage.Key(
change.getId(),
ChangeUtil.messageUUID(db)),
null,
change.getLastUpdatedOn(),
change.currentPatchSetId());
msg.setMessage("Project was deleted.");
db.changeMessages().insert(Collections.singleton(msg));
new ApprovalsUtil(db).syncChangeStatus(change);
db.commit();
indexer.index(change);
}
} finally {
db.rollback();
}
}
}