Executing CherryPick.writeCherryPickCommit() in a transaction.
This would at least allow the partial changes to the
database to rollback and not get users in a bad state when
e.g. in the case of OrmDuplicateKeyException: patch_set_ancestors'.
Bug: issue 2034
Bug: issue 2246
Change-Id: I65e111bedc3cec033299b5b5360aaee733d4b5c6
(cherry picked from commit eb4778d079e7156c82d04c2f26c71ca89d12df16)
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/CherryPick.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/CherryPick.java
index 48f62b5..259d939 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/CherryPick.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/CherryPick.java
@@ -161,26 +161,36 @@
ps.setCreatedOn(TimeUtil.nowTs());
ps.setUploader(submitAudit.getAccountId());
ps.setRevision(new RevId(newCommit.getId().getName()));
- insertAncestors(args.db, ps.getId(), newCommit);
- args.db.patchSets().insert(Collections.singleton(ps));
- n.change.setCurrentPatchSet(patchSetInfoFactory.get(newCommit, ps.getId()));
- args.db.changes().update(Collections.singletonList(n.change));
+ final RefUpdate ru;
- final List<PatchSetApproval> approvals = Lists.newArrayList();
- for (PatchSetApproval a : args.mergeUtil.getApprovalsForCommit(n)) {
- approvals.add(new PatchSetApproval(ps.getId(), a));
- }
- args.db.patchSetApprovals().insert(approvals);
+ args.db.changes().beginTransaction(n.change.getId());
+ try {
+ insertAncestors(args.db, ps.getId(), newCommit);
+ args.db.patchSets().insert(Collections.singleton(ps));
+ n.change
+ .setCurrentPatchSet(patchSetInfoFactory.get(newCommit, ps.getId()));
+ args.db.changes().update(Collections.singletonList(n.change));
- final RefUpdate ru = args.repo.updateRef(ps.getRefName());
- ru.setExpectedOldObjectId(ObjectId.zeroId());
- ru.setNewObjectId(newCommit);
- ru.disableRefLog();
- if (ru.update(args.rw) != RefUpdate.Result.NEW) {
- throw new IOException(String.format("Failed to create ref %s in %s: %s",
- ps.getRefName(), n.change.getDest().getParentKey().get(),
- ru.getResult()));
+ final List<PatchSetApproval> approvals = Lists.newArrayList();
+ for (PatchSetApproval a : args.mergeUtil.getApprovalsForCommit(n)) {
+ approvals.add(new PatchSetApproval(ps.getId(), a));
+ }
+ args.db.patchSetApprovals().insert(approvals);
+
+ ru = args.repo.updateRef(ps.getRefName());
+ ru.setExpectedOldObjectId(ObjectId.zeroId());
+ ru.setNewObjectId(newCommit);
+ ru.disableRefLog();
+ if (ru.update(args.rw) != RefUpdate.Result.NEW) {
+ throw new IOException(String.format(
+ "Failed to create ref %s in %s: %s", ps.getRefName(), n.change
+ .getDest().getParentKey().get(), ru.getResult()));
+ }
+
+ args.db.commit();
+ } finally {
+ args.db.rollback();
}
gitRefUpdated.fire(n.change.getProject(), ru);