summaryrefslogtreecommitdiffstats
path: root/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/Submit.java
diff options
context:
space:
mode:
Diffstat (limited to 'gerrit-server/src/main/java/com/google/gerrit/server/changedetail/Submit.java')
-rw-r--r--gerrit-server/src/main/java/com/google/gerrit/server/changedetail/Submit.java189
1 files changed, 189 insertions, 0 deletions
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/Submit.java b/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/Submit.java
new file mode 100644
index 0000000000..abd358292f
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/Submit.java
@@ -0,0 +1,189 @@
+// Copyright (C) 2012 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.changedetail;
+
+import static com.google.gerrit.reviewdb.client.ApprovalCategory.SUBMIT;
+
+import com.google.gerrit.common.data.ReviewResult;
+import com.google.gerrit.common.data.SubmitRecord;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
+import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gerrit.server.ChangeUtil;
+import com.google.gerrit.server.IdentifiedUser;
+import com.google.gerrit.server.git.MergeOp;
+import com.google.gerrit.server.git.MergeQueue;
+import com.google.gerrit.server.project.ChangeControl;
+import com.google.gerrit.server.project.InvalidChangeOperationException;
+import com.google.gerrit.server.project.NoSuchChangeException;
+import com.google.gwtorm.server.AtomicUpdate;
+import com.google.gwtorm.server.OrmException;
+import com.google.inject.Inject;
+import com.google.inject.assistedinject.Assisted;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.Callable;
+
+public class Submit implements Callable<ReviewResult> {
+
+ public interface Factory {
+ Submit create(PatchSet.Id patchSetId);
+ }
+
+ private final ChangeControl.Factory changeControlFactory;
+ private final MergeOp.Factory opFactory;
+ private final MergeQueue merger;
+ private final ReviewDb db;
+ private final IdentifiedUser currentUser;
+
+ private final PatchSet.Id patchSetId;
+
+ @Inject
+ Submit(final ChangeControl.Factory changeControlFactory,
+ final MergeOp.Factory opFactory, final MergeQueue merger,
+ final ReviewDb db, final IdentifiedUser currentUser,
+ @Assisted final PatchSet.Id patchSetId) {
+ this.changeControlFactory = changeControlFactory;
+ this.opFactory = opFactory;
+ this.merger = merger;
+ this.db = db;
+ this.currentUser = currentUser;
+
+ this.patchSetId = patchSetId;
+ }
+
+ @Override
+ public ReviewResult call() throws IllegalStateException,
+ InvalidChangeOperationException, NoSuchChangeException, OrmException {
+ final ReviewResult result = new ReviewResult();
+
+ final PatchSet patch = db.patchSets().get(patchSetId);
+ final Change.Id changeId = patchSetId.getParentKey();
+ final ChangeControl control = changeControlFactory.validateFor(changeId);
+ result.setChangeId(changeId);
+ if (patch == null) {
+ throw new NoSuchChangeException(changeId);
+ }
+
+ List<SubmitRecord> submitResult = control.canSubmit(db, patchSetId);
+ if (submitResult.isEmpty()) {
+ throw new IllegalStateException(
+ "ChangeControl.canSubmit returned empty list");
+ }
+
+ for (SubmitRecord submitRecord : submitResult) {
+ switch (submitRecord.status) {
+ case OK:
+ if (!control.getRefControl().canSubmit()) {
+ result.addError(new ReviewResult.Error(
+ ReviewResult.Error.Type.SUBMIT_NOT_PERMITTED));
+ }
+ break;
+
+ case NOT_READY:
+ StringBuilder errMsg = new StringBuilder();
+ for (SubmitRecord.Label lbl : submitRecord.labels) {
+ switch (lbl.status) {
+ case OK:
+ break;
+
+ case REJECT:
+ if (errMsg.length() > 0) errMsg.append("; ");
+ errMsg.append("change " + changeId + ": blocked by "
+ + lbl.label);
+ break;
+
+ case NEED:
+ if (errMsg.length() > 0) errMsg.append("; ");
+ errMsg.append("change " + changeId + ": needs " + lbl.label);
+ break;
+
+ case IMPOSSIBLE:
+ if (errMsg.length() > 0) errMsg.append("; ");
+ errMsg.append("change " + changeId + ": needs " + lbl.label
+ + " (check project access)");
+ break;
+
+ default:
+ throw new IllegalArgumentException(
+ "Unsupported SubmitRecord.Label.status (" + lbl.status
+ + ")");
+ }
+ }
+ result.addError(new ReviewResult.Error(
+ ReviewResult.Error.Type.SUBMIT_NOT_READY, errMsg.toString()));
+ break;
+
+ case CLOSED:
+ result.addError(new ReviewResult.Error(
+ ReviewResult.Error.Type.CHANGE_IS_CLOSED));
+ break;
+
+ case RULE_ERROR:
+ result.addError(new ReviewResult.Error(
+ ReviewResult.Error.Type.RULE_ERROR,
+ submitResult.get(0).errorMessage));
+ break;
+
+ default:
+ throw new IllegalStateException(
+ "Unsupported SubmitRecord.status + (" + submitRecord.status
+ + ")");
+ }
+ }
+
+ // Submit the change if we can
+ if (result.getErrors().isEmpty()) {
+ final List<PatchSetApproval> allApprovals =
+ new ArrayList<PatchSetApproval>(db.patchSetApprovals().byPatchSet(
+ patchSetId).toList());
+
+ final PatchSetApproval.Key akey =
+ new PatchSetApproval.Key(patchSetId, currentUser.getAccountId(),
+ SUBMIT);
+
+ PatchSetApproval approval = new PatchSetApproval(akey, (short) 1);
+ for (final PatchSetApproval candidateApproval : allApprovals) {
+ if (akey.equals(candidateApproval.getKey())) {
+ candidateApproval.setValue((short) 1);
+ candidateApproval.setGranted();
+ approval = candidateApproval;
+ break;
+ }
+ }
+ db.patchSetApprovals().upsert(Collections.singleton(approval));
+
+ final Change updatedChange = db.changes().atomicUpdate(changeId,
+ new AtomicUpdate<Change>() {
+ @Override
+ public Change update(Change change) {
+ if (change.getStatus() == Change.Status.NEW) {
+ change.setStatus(Change.Status.SUBMITTED);
+ ChangeUtil.updated(change);
+ }
+ return change;
+ }
+ });
+
+ if (updatedChange.getStatus() == Change.Status.SUBMITTED) {
+ merger.merge(opFactory, updatedChange.getDest());
+ }
+ }
+ return result;
+ }
+}