summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMika Hamalainen <mika.hamalainen@accenture.com>2011-08-04 11:17:01 +0300
committerMika Hamalainen <mika.hamalainen@accenture.com>2011-08-04 14:35:54 +0300
commitb845077a35fba82271c96502d33086a3156ef1d2 (patch)
treed99742ce2cb1fe618f3eab6fb76921baf2f0a9e9
parent0600ac58c13daf8062e5974cf9dd014a3a3ae504 (diff)
Integrated staging to topic reviews
Added staging feature to topic reviews. Changes include staging UI, topic merging and staging command changes. Topics can be staged as any individual changes. When creating or approving builds, topic approval is checked instead of change approval when change is part of a topic. Additional changes: - Based on v2.2.1 - Fixed StagingCommand.openChanges to check destination branch Change-Id: I52a6aec206ac2ae2e98afd8e2e60e02c9d51f6f4 Conflicts: gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeDetailFactory.java gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/topic/ChangeSetPublishDetailFactory.java gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/topic/TopicDetailFactory.java gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/StagingApprove.java
-rw-r--r--gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeDetail.java20
-rw-r--r--gerrit-common/src/main/java/com/google/gerrit/common/data/CommonDetail.java18
-rw-r--r--gerrit-common/src/main/java/com/google/gerrit/common/data/CommonPublishDetail.java18
-rw-r--r--gerrit-common/src/main/java/com/google/gerrit/common/data/PatchSetPublishDetail.java9
-rw-r--r--gerrit-common/src/main/java/com/google/gerrit/common/data/TopicManageService.java3
-rw-r--r--gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeSetComplexDisclosurePanel.java26
-rw-r--r--gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PublishCommentScreen.java2
-rw-r--r--gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PublishTopicCommentScreen.java39
-rw-r--r--gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/TopicConstants.java1
-rw-r--r--gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/TopicConstants.properties1
-rw-r--r--gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/TopicMessages.java1
-rw-r--r--gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/TopicMessages.properties2
-rw-r--r--gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeDetailFactory.java6
-rw-r--r--gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/PatchSetPublishDetailFactory.java6
-rw-r--r--gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/StagingAction.java2
-rw-r--r--gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/UnstageChange.java2
-rw-r--r--gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/patch/PatchDetailServiceImpl.java3
-rw-r--r--gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/topic/ChangeSetPublishDetailFactory.java43
-rw-r--r--gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/topic/StagingAction.java131
-rw-r--r--gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/topic/SubmitAction.java9
-rw-r--r--gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/topic/TopicDetailFactory.java2
-rw-r--r--gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/topic/TopicManageServiceImpl.java10
-rw-r--r--gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/topic/TopicModule.java1
-rw-r--r--gerrit-server/src/main/java/com/google/gerrit/server/ChangeUtil.java2
-rw-r--r--gerrit-server/src/main/java/com/google/gerrit/server/TopicUtil.java106
-rw-r--r--gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOp.java7
-rw-r--r--gerrit-server/src/main/java/com/google/gerrit/server/git/StagingMergeDelegate.java3
-rw-r--r--gerrit-server/src/main/java/com/google/gerrit/server/git/SubmitMergeDelegate.java3
-rw-r--r--gerrit-server/src/main/java/com/google/gerrit/server/project/ChangeControl.java56
-rw-r--r--gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java6
-rw-r--r--gerrit-server/src/main/java/com/google/gerrit/server/project/TopicControl.java56
-rw-r--r--gerrit-server/src/main/java/com/google/gerrit/server/workflow/CategoryFunction.java1
-rw-r--r--gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ReviewCommand.java2
-rw-r--r--gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/StagingApprove.java90
-rw-r--r--gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/StagingCommand.java6
-rw-r--r--gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/StagingListChanges.java5
-rw-r--r--gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/StagingNewBuild.java29
-rw-r--r--gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/StagingRebuild.java1
38 files changed, 557 insertions, 171 deletions
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeDetail.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeDetail.java
index e223422923..2c3f58c76d 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeDetail.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeDetail.java
@@ -14,7 +14,6 @@
package com.google.gerrit.common.data;
-import com.google.gerrit.reviewdb.ApprovalCategory;
import com.google.gerrit.reviewdb.Change;
import com.google.gerrit.reviewdb.ChangeMessage;
import com.google.gerrit.reviewdb.PatchSet;
@@ -23,12 +22,9 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
-import java.util.Set;
/** Detail necessary to display a change. */
public class ChangeDetail extends CommonDetail {
- protected boolean canStage;
- protected boolean canUnstage;
protected Change change;
protected List<PatchSet> patchSets;
protected boolean canSubmit;
@@ -41,22 +37,6 @@ public class ChangeDetail extends CommonDetail {
public ChangeDetail() {
}
- public boolean canStage() {
- return canStage;
- }
-
- public void setCanStage(final boolean a) {
- canStage = a;
- }
-
- public boolean canUnstage() {
- return canUnstage;
- }
-
- public void setCanUnstage(final boolean a) {
- canUnstage = a;
- }
-
public Change getChange() {
return change;
}
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/CommonDetail.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/CommonDetail.java
index a8aea7059f..a48b7abc72 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/CommonDetail.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/CommonDetail.java
@@ -31,6 +31,8 @@ public abstract class CommonDetail {
protected List<ChangeInfo> neededBy;
protected Set<ApprovalCategory.Id> missingApprovals;
protected boolean canSubmit;
+ protected boolean canStage;
+ protected boolean canUnstage;
public AccountInfoCache getAccounts() {
return accounts;
@@ -111,4 +113,20 @@ public abstract class CommonDetail {
public void setMissingApprovals(Set<ApprovalCategory.Id> a) {
missingApprovals = a;
}
+
+ public boolean canStage() {
+ return canStage;
+ }
+
+ public void setCanStage(final boolean a) {
+ canStage = a;
+ }
+
+ public boolean canUnstage() {
+ return canUnstage;
+ }
+
+ public void setCanUnstage(final boolean a) {
+ canUnstage = a;
+ }
}
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/CommonPublishDetail.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/CommonPublishDetail.java
index d2e5d804e6..ad0882fd4e 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/CommonPublishDetail.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/CommonPublishDetail.java
@@ -24,6 +24,8 @@ public abstract class CommonPublishDetail<T extends SetApproval<?>> {
protected List<PermissionRange> labels;
protected List<T> given;
protected boolean canSubmit;
+ protected boolean canStage;
+ protected boolean canUnstage;
public List<PermissionRange> getLabels() {
return labels;
@@ -49,6 +51,14 @@ public abstract class CommonPublishDetail<T extends SetApproval<?>> {
canSubmit = allowed;
}
+ public void setCanStage(boolean allowed) {
+ canStage = allowed;
+ }
+
+ public void setCanUnstage(boolean allowed) {
+ canUnstage = allowed;
+ }
+
public AccountInfoCache getAccounts() {
return accounts;
}
@@ -74,4 +84,12 @@ public abstract class CommonPublishDetail<T extends SetApproval<?>> {
public boolean canSubmit() {
return canSubmit;
}
+
+ public boolean canStage() {
+ return canStage;
+ }
+
+ public boolean canUnstage() {
+ return canUnstage;
+ }
}
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/PatchSetPublishDetail.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/PatchSetPublishDetail.java
index 507a37f22d..ed580fcbad 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/PatchSetPublishDetail.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/PatchSetPublishDetail.java
@@ -25,7 +25,6 @@ public class PatchSetPublishDetail extends CommonPublishDetail<PatchSetApproval>
protected PatchSetInfo patchSetInfo;
protected Change change;
protected List<PatchLineComment> drafts;
- protected boolean stagingBranchAllowed;
public void setPatchSetInfo(PatchSetInfo patchSetInfo) {
this.patchSetInfo = patchSetInfo;
@@ -39,10 +38,6 @@ public class PatchSetPublishDetail extends CommonPublishDetail<PatchSetApproval>
this.drafts = drafts;
}
- public void setStagingBranchAllowed(boolean allowed) {
- stagingBranchAllowed = allowed;
- }
-
public Change getChange() {
return change;
}
@@ -54,8 +49,4 @@ public class PatchSetPublishDetail extends CommonPublishDetail<PatchSetApproval>
public List<PatchLineComment> getDrafts() {
return drafts;
}
-
- public boolean isStagingBranchAllowed() {
- return stagingBranchAllowed;
- }
}
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/TopicManageService.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/TopicManageService.java
index b83a25710f..a12d16dc04 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/TopicManageService.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/TopicManageService.java
@@ -37,4 +37,7 @@ public interface TopicManageService extends RemoteJsonService {
@SignInRequired
void restoreTopic(ChangeSet.Id changeSetId, String message,
AsyncCallback<TopicDetail> callback);
+
+ @SignInRequired
+ void stage(ChangeSet.Id changeSetId, AsyncCallback<TopicDetail> callback);
}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeSetComplexDisclosurePanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeSetComplexDisclosurePanel.java
index 71536ef71a..ea09296e89 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeSetComplexDisclosurePanel.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeSetComplexDisclosurePanel.java
@@ -167,6 +167,32 @@ class ChangeSetComplexDisclosurePanel extends CommonComplexDisclosurePanel {
private void populateActions(final ChangeSetDetail detail) {
final boolean isOpen = topicDetail.getTopic().getStatus().isOpen();
+ final boolean isNew = topicDetail.getTopic().getStatus() == Status.NEW;
+ if (isOpen && isNew && topicDetail.canStage()) {
+ final Button b =
+ new Button(Util.TM
+ .stageChangeSet(detail.getChangeSet().getChangeSetId()));
+ b.addClickHandler(new ClickHandler() {
+ @Override
+ public void onClick(final ClickEvent event) {
+ b.setEnabled(false);
+ Util.T_MANAGE_SVC.stage(changeSet.getId(),
+ new GerritCallback<TopicDetail>() {
+ @Override
+ public void onSuccess(TopicDetail result) {
+ onSubmitResult(result);
+ }
+
+ @Override
+ public void onFailure(Throwable caught) {
+ b.setEnabled(true);
+ super.onFailure(caught);
+ }
+ });
+ }
+ });
+ actionsPanel.add(b);
+ }
if (isOpen && topicDetail.canSubmit()) {
final Button b =
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PublishCommentScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PublishCommentScreen.java
index 7783eb4016..b8323f0db1 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PublishCommentScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PublishCommentScreen.java
@@ -326,7 +326,7 @@ public class PublishCommentScreen extends AccountScreen implements
}
submit.setVisible(r.canSubmit());
- staging.setVisible(r.isStagingBranchAllowed());
+ staging.setVisible(r.canStage());
}
private void onSend(final Action action) {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PublishTopicCommentScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PublishTopicCommentScreen.java
index 63e2b56a7e..d4bfa9090b 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PublishTopicCommentScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PublishTopicCommentScreen.java
@@ -58,12 +58,15 @@ public class PublishTopicCommentScreen extends AccountScreen implements
ClickHandler, CommentEditorContainer {
private static SavedState lastState;
+ private enum Action { NOOP, SUBMIT, STAGING };
+
private final ChangeSet.Id changeSetId;
private Collection<ValueRadioButton> approvalButtons;
private TopicDescriptionBlock descBlock;
private Panel approvalPanel;
private NpTextArea message;
private Button send;
+ private Button staging;
private Button submit;
private Button cancel;
private boolean saveStateOnUnload = true;
@@ -105,6 +108,10 @@ public class PublishTopicCommentScreen extends AccountScreen implements
send.addClickHandler(this);
buttonRow.add(send);
+ staging = new Button(Util.TC.buttonPublishStaging());
+ staging.addClickHandler(this);
+ buttonRow.add(staging);
+
submit = new Button(Util.TC.buttonPublishSubmitSend());
submit.addClickHandler(this);
buttonRow.add(submit);
@@ -120,6 +127,7 @@ public class PublishTopicCommentScreen extends AccountScreen implements
}
message.setEnabled(enabled);
send.setEnabled(enabled);
+ staging.setEnabled(enabled);
submit.setEnabled(enabled);
cancel.setEnabled(enabled);
}
@@ -152,9 +160,11 @@ public class PublishTopicCommentScreen extends AccountScreen implements
public void onClick(final ClickEvent event) {
final Widget sender = (Widget) event.getSource();
if (send == sender) {
- onSend(false);
+ onSend(Action.NOOP);
} else if (submit == sender) {
- onSend(true);
+ onSend(Action.SUBMIT);
+ } else if (staging == sender) {
+ onSend(Action.STAGING);
} else if (cancel == sender) {
saveStateOnUnload = false;
goChangeSet();
@@ -253,7 +263,7 @@ public class PublishTopicCommentScreen extends AccountScreen implements
submit.setVisible(r.canSubmit());
}
- private void onSend(final boolean submit) {
+ private void onSend(final Action action) {
final Map<ApprovalCategory.Id, ApprovalCategoryValue.Id> values =
new HashMap<ApprovalCategory.Id, ApprovalCategoryValue.Id>();
for (final ValueRadioButton b : approvalButtons) {
@@ -267,9 +277,11 @@ public class PublishTopicCommentScreen extends AccountScreen implements
new HashSet<ApprovalCategoryValue.Id>(values.values()),
new GerritCallback<VoidResult>() {
public void onSuccess(final VoidResult result) {
- if(submit) {
+ if(action == Action.SUBMIT) {
submit();
- } else {
+ } else if (action == Action.STAGING) {
+ stage();
+ }else {
saveStateOnUnload = false;
goChangeSet();
}
@@ -299,6 +311,23 @@ public class PublishTopicCommentScreen extends AccountScreen implements
});
}
+ private void stage() {
+ Util.T_MANAGE_SVC.stage(changeSetId,
+ new GerritCallback<TopicDetail>() {
+ @Override
+ public void onSuccess(TopicDetail result) {
+ saveStateOnUnload = false;
+ goChangeSet();
+ }
+
+ @Override
+ public void onFailure(Throwable caught) {
+ goChangeSet();
+ super.onFailure(caught);
+ }
+ });
+ }
+
private void goChangeSet() {
final Topic.Id ck = changeSetId.getParentKey();
Gerrit.display(PageLinks.toTopic(ck), new TopicScreen(ck));
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/TopicConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/TopicConstants.java
index 1f7b1cae34..4dceee4515 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/TopicConstants.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/TopicConstants.java
@@ -43,6 +43,7 @@ public interface TopicConstants extends Constants {
String buttonReview();
String buttonPublishCommentsSend();
+ String buttonPublishStaging();
String buttonPublishSubmitSend();
String buttonPublishCommentsCancel();
String headingCoverMessage();
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/TopicConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/TopicConstants.properties
index b285a05b59..91a374d4ad 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/TopicConstants.properties
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/TopicConstants.properties
@@ -24,6 +24,7 @@ buttonRestoreTopicSend = Restore Topic
buttonReview = Review
buttonPublishCommentsSend = Publish Comments
+buttonPublishStaging = Publish and Merge to Staging
buttonPublishSubmitSend = Publish and Submit
buttonPublishCommentsCancel = Cancel
headingCoverMessage = Cover Message:
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/TopicMessages.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/TopicMessages.java
index c5dda35210..35006f8642 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/TopicMessages.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/TopicMessages.java
@@ -24,4 +24,5 @@ public interface TopicMessages extends Messages {
String publishCommentsOnSet(String commitSetId, String topicName);
String revertTopicDefaultMessage(String topic, int id, int changesetid);
+ String stageChangeSet(int id);
}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/TopicMessages.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/TopicMessages.properties
index 9622ba96c8..a09c5b068e 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/TopicMessages.properties
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/TopicMessages.properties
@@ -7,3 +7,5 @@ submitChangeSet = Submit Change Set {0}
revertTopicDefaultMessage = Reverted from Topic \"{0}\" with Topic Id: {1}\n\nThis reverts ChangeSet {2}
publishCommentsOnSet = Topic {0} - {1}: Publish Comments
+
+stageChangeSet = Merge Change Set {0} to Staging \ No newline at end of file
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeDetailFactory.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeDetailFactory.java
index 527974d9e8..368c1fc03b 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeDetailFactory.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeDetailFactory.java
@@ -111,9 +111,11 @@ public class ChangeDetailFactory extends Handler<ChangeDetail> {
detail.setCanRevert(change.getStatus() == Change.Status.MERGED && control.canAddPatchSet() && (change.getTopicId() == null));
- final CanSubmitResult canStageResult = control.canMergeToStaging(patch.getId());
+ final CanSubmitResult canStageResult =
+ control.canStage(patch.getId());
detail.setCanStage(canStageResult == CanSubmitResult.OK);
- detail.setCanUnstage(change.getStatus() == Change.Status.STAGED && control.canAbandon());
+ detail.setCanUnstage(change.getStatus() == Change.Status.STAGED
+ && control.canAbandon());
loadPatchSets();
loadMessages();
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/PatchSetPublishDetailFactory.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/PatchSetPublishDetailFactory.java
index 70ffc3a402..821bb7e28d 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/PatchSetPublishDetailFactory.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/PatchSetPublishDetailFactory.java
@@ -111,11 +111,11 @@ final class PatchSetPublishDetailFactory extends Handler<PatchSetPublishDetail>
&& (change.getTopicId() == null)) {
detail.setCanSubmit(true);
}
-
- final CanSubmitResult canMergeToStaging = control.canMergeToStaging(patchSetId);
+
+ final CanSubmitResult canMergeToStaging = control.canStage(patchSetId);
if (canMergeToStaging == CanSubmitResult.OK
&& (change.getTopicId() == null)) {
- detail.setStagingBranchAllowed(true);
+ detail.setCanStage(true);
}
return detail;
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/StagingAction.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/StagingAction.java
index 9a368f9f91..ecdb01ba6e 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/StagingAction.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/StagingAction.java
@@ -110,7 +110,7 @@ class StagingAction extends Handler<ChangeDetail> {
// Check if the change can be merged to staging branch.
CanSubmitResult err =
- changeControl.canMergeToStaging(patchSetId, db, approvalTypes,
+ changeControl.canStage(patchSetId, db, approvalTypes,
functionState);
Repository git = null;
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/UnstageChange.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/UnstageChange.java
index d2db9483f8..a699f269ce 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/UnstageChange.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/UnstageChange.java
@@ -111,7 +111,7 @@ class UnstageChange extends Handler<ChangeDetail> {
// Check if the change can be merged to staging branch.
CanSubmitResult err =
- changeControl.canMergeToStaging(patchSetId, db, approvalTypes,
+ changeControl.canStage(patchSetId, db, approvalTypes,
functionState);
Repository git = null;
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/patch/PatchDetailServiceImpl.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/patch/PatchDetailServiceImpl.java
index c81c2e9ba8..d8e96dcaf5 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/patch/PatchDetailServiceImpl.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/patch/PatchDetailServiceImpl.java
@@ -233,7 +233,8 @@ class PatchDetailServiceImpl extends BaseServiceImplementation implements
for (PatchSetApproval ca : db.patchSetApprovals().byPatchSet(ps_id)) {
final ApprovalCategory.Id category = ca.getCategoryId();
- if (ApprovalCategory.SUBMIT.equals(category)) {
+ if (ApprovalCategory.SUBMIT.equals(category)
+ || ApprovalCategory.STAGING.equals(category)) {
continue;
}
if (change.getStatus().isOpen()) {
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/topic/ChangeSetPublishDetailFactory.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/topic/ChangeSetPublishDetailFactory.java
index daa8caf205..0b2442f761 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/topic/ChangeSetPublishDetailFactory.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/topic/ChangeSetPublishDetailFactory.java
@@ -14,12 +14,11 @@
package com.google.gerrit.httpd.rpc.topic;
-import com.google.gerrit.common.data.ApprovalType;
-import com.google.gerrit.common.data.ApprovalTypes;
import com.google.gerrit.common.data.ChangeSetPublishDetail;
import com.google.gerrit.common.data.PermissionRange;
import com.google.gerrit.common.errors.NoSuchEntityException;
import com.google.gerrit.httpd.rpc.Handler;
+import com.google.gerrit.reviewdb.AbstractEntity;
import com.google.gerrit.reviewdb.ChangeSet;
import com.google.gerrit.reviewdb.ChangeSetApproval;
import com.google.gerrit.reviewdb.ChangeSetInfo;
@@ -28,20 +27,16 @@ import com.google.gerrit.reviewdb.Topic;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.AccountInfoCacheFactory;
import com.google.gerrit.server.project.CanSubmitResult;
-import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.project.NoSuchTopicException;
import com.google.gerrit.server.project.TopicControl;
-import com.google.gerrit.server.workflow.TopicFunctionState;
import com.google.gwtorm.client.OrmException;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
final class ChangeSetPublishDetailFactory extends Handler<ChangeSetPublishDetail> {
interface Factory {
@@ -50,10 +45,7 @@ final class ChangeSetPublishDetailFactory extends Handler<ChangeSetPublishDetail
private final ChangeSetInfoFactory infoFactory;
private final ReviewDb db;
- private final ChangeControl.Factory changeControlFactory;
private final TopicControl.Factory topicControlFactory;
- private final TopicFunctionState.Factory topicFunctionState;
- private final ApprovalTypes approvalTypes;
private final AccountInfoCacheFactory aic;
private final IdentifiedUser user;
@@ -66,17 +58,12 @@ final class ChangeSetPublishDetailFactory extends Handler<ChangeSetPublishDetail
ChangeSetPublishDetailFactory(final ChangeSetInfoFactory infoFactory,
final ReviewDb db,
final AccountInfoCacheFactory.Factory accountInfoCacheFactory,
- final ChangeControl.Factory changeControlFactory,
final TopicControl.Factory topicControlFactory,
- final TopicFunctionState.Factory topicFunctionState,
- final ApprovalTypes approvalTypes,
- final IdentifiedUser user, @Assisted final ChangeSet.Id changeSetId) {
+ final IdentifiedUser user,
+ @Assisted final ChangeSet.Id changeSetId) {
this.infoFactory = infoFactory;
this.db = db;
- this.changeControlFactory = changeControlFactory;
this.topicControlFactory = topicControlFactory;
- this.topicFunctionState = topicFunctionState;
- this.approvalTypes = approvalTypes;
this.aic = accountInfoCacheFactory.create();
this.user = user;
@@ -92,12 +79,6 @@ final class ChangeSetPublishDetailFactory extends Handler<ChangeSetPublishDetail
topic = control.getTopic();
changeSetInfo = infoFactory.get(changeSetId);
- aic.want(topic.getOwner());
-
- ChangeSetPublishDetail detail = new ChangeSetPublishDetail();
- detail.setChangeSetInfo(changeSetInfo);
- detail.setTopic(topic);
-
List<PermissionRange> allowed = Collections.emptyList();
List<ChangeSetApproval> given = Collections.emptyList();
@@ -111,6 +92,12 @@ final class ChangeSetPublishDetailFactory extends Handler<ChangeSetPublishDetail
.toList();
}
+ aic.want(topic.getOwner());
+
+ ChangeSetPublishDetail detail = new ChangeSetPublishDetail();
+ detail.setChangeSetInfo(changeSetInfo);
+ detail.setTopic(topic);
+
detail.setLabels(allowed);
detail.setGiven(given);
detail.setAccounts(aic.create());
@@ -118,7 +105,17 @@ final class ChangeSetPublishDetailFactory extends Handler<ChangeSetPublishDetail
final CanSubmitResult canSubmitResult = control.canSubmit(changeSetId);
if (canSubmitResult == CanSubmitResult.OK) {
detail.setCanSubmit(true);
- }
+ }
+
+ final CanSubmitResult canStage = control.canStage(changeSetId);
+ if (canStage == CanSubmitResult.OK) {
+ detail.setCanStage(true);
+ }
+
+ if (topic.getStatus() == AbstractEntity.Status.STAGED
+ && control.getRefControl().canStage()) {
+ detail.setCanUnstage(true);
+ }
return detail;
}
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/topic/StagingAction.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/topic/StagingAction.java
new file mode 100644
index 0000000000..d74e7a08c0
--- /dev/null
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/topic/StagingAction.java
@@ -0,0 +1,131 @@
+// Copyright (C) 2011 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.httpd.rpc.topic;
+
+import com.google.gerrit.common.ChangeHookRunner;
+import com.google.gerrit.common.data.ApprovalTypes;
+import com.google.gerrit.common.data.TopicDetail;
+import com.google.gerrit.common.errors.NoSuchEntityException;
+import com.google.gerrit.httpd.rpc.Handler;
+import com.google.gerrit.reviewdb.ChangeSet;
+import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.Topic;
+import com.google.gerrit.server.IdentifiedUser;
+import com.google.gerrit.server.TopicUtil;
+import com.google.gerrit.server.git.GitRepositoryManager;
+import com.google.gerrit.server.git.MergeOp;
+import com.google.gerrit.server.git.MergeQueue;
+import com.google.gerrit.server.project.CanSubmitResult;
+import com.google.gerrit.server.project.ChangeControl;
+import com.google.gerrit.server.project.NoSuchChangeException;
+import com.google.gerrit.server.project.NoSuchRefException;
+import com.google.gerrit.server.project.NoSuchTopicException;
+import com.google.gerrit.server.project.TopicControl;
+import com.google.gerrit.server.workflow.TopicFunctionState;
+import com.google.gwtorm.client.OrmException;
+import com.google.inject.Inject;
+import com.google.inject.assistedinject.Assisted;
+
+import org.eclipse.jgit.lib.Repository;
+
+import java.io.IOException;
+
+
+class StagingAction extends Handler<TopicDetail> {
+ interface Factory {
+ StagingAction create(ChangeSet.Id changeSetId);
+ }
+
+ private final ReviewDb db;
+ private final MergeQueue merger;
+ private final ApprovalTypes approvalTypes;
+ private final IdentifiedUser user;
+ private final TopicDetailFactory.Factory topicDetailFactory;
+ private final ChangeControl.Factory changeControlFactory;
+ private final TopicControl.Factory topicControlFactory;
+ private final TopicFunctionState.Factory topicFunctionState;
+ private final MergeOp.Factory opFactory;
+ private final GitRepositoryManager gitManager;
+ private final ChangeHookRunner hooks;
+
+ private final ChangeSet.Id changeSetId;
+
+ @Inject
+ StagingAction(final ReviewDb db, final MergeQueue mq,
+ final IdentifiedUser user,
+ final ApprovalTypes approvalTypes,
+ final TopicDetailFactory.Factory topicDetailFactory,
+ final ChangeControl.Factory changeControlFactory,
+ final TopicControl.Factory topicControlFactory,
+ final TopicFunctionState.Factory topicFunctionState,
+ final MergeOp.Factory opFactory,
+ final GitRepositoryManager gitManager,
+ final ChangeHookRunner hooks,
+ @Assisted final ChangeSet.Id changeSetId) {
+ this.db = db;
+ this.merger = mq;
+ this.approvalTypes = approvalTypes;
+ this.user = user;
+ this.changeControlFactory = changeControlFactory;
+ this.topicControlFactory = topicControlFactory;
+ this.topicDetailFactory = topicDetailFactory;
+ this.topicFunctionState = topicFunctionState;
+ this.opFactory = opFactory;
+ this.gitManager = gitManager;
+ this.hooks = hooks;
+
+ this.changeSetId = changeSetId;
+ }
+
+ @Override
+ public TopicDetail call() throws OrmException, NoSuchEntityException,
+ IllegalStateException, ChangeSetInfoNotAvailableException,
+ NoSuchTopicException, NoSuchChangeException {
+
+ final Topic.Id topicId = changeSetId.getParentKey();
+ final TopicControl topicControl =
+ topicControlFactory.validateFor(topicId);
+
+ CanSubmitResult result = topicControl.canStage(db, changeSetId,
+ changeControlFactory, approvalTypes, topicFunctionState);
+
+ Repository git = null;
+ if (result == CanSubmitResult.OK) {
+ try {
+ // Open a handle to Git repository.
+ git =
+ gitManager.openRepository(topicControl.getProject().getNameKey());
+
+ // Move change to staging.
+ TopicUtil.stage(changeSetId, user, db, opFactory, merger, git, hooks);
+ } catch (IOException e) {
+ throw new IllegalStateException(e.getMessage());
+ } catch (NoSuchRefException e) {
+ throw new IllegalStateException(e.getMessage());
+ } finally {
+ // Make sure that access to Git repository is closed.
+ if (git != null) {
+ git.close();
+ }
+ }
+ return topicDetailFactory.create(topicId).call();
+ } else {
+ // Report error message to user. User cannot move this change to staging.
+ // The problem is caused because of illegal stage of missing access
+ // rights.
+ throw new IllegalStateException(result.getMessage());
+ }
+ }
+}
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/topic/SubmitAction.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/topic/SubmitAction.java
index c9a9fad309..0e2d0649cc 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/topic/SubmitAction.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/topic/SubmitAction.java
@@ -26,7 +26,6 @@ import com.google.gerrit.server.TopicUtil;
import com.google.gerrit.server.git.MergeOp;
import com.google.gerrit.server.git.MergeQueue;
import com.google.gerrit.server.project.CanSubmitResult;
-import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.project.NoSuchTopicException;
import com.google.gerrit.server.project.TopicControl;
@@ -35,9 +34,6 @@ import com.google.gwtorm.client.OrmException;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
-import java.util.List;
-
-
class SubmitAction extends Handler<TopicDetail> {
interface Factory {
SubmitAction create(ChangeSet.Id changeSetId);
@@ -48,7 +44,6 @@ class SubmitAction extends Handler<TopicDetail> {
private final ApprovalTypes approvalTypes;
private final IdentifiedUser user;
private final TopicDetailFactory.Factory topicDetailFactory;
- private final ChangeControl.Factory changeControlFactory;
private final TopicControl.Factory topicControlFactory;
private final TopicFunctionState.Factory topicFunctionState;
private final MergeOp.Factory opFactory;
@@ -60,7 +55,6 @@ class SubmitAction extends Handler<TopicDetail> {
final IdentifiedUser user,
final ApprovalTypes approvalTypes,
final TopicDetailFactory.Factory topicDetailFactory,
- final ChangeControl.Factory changeControlFactory,
final TopicControl.Factory topicControlFactory,
final TopicFunctionState.Factory topicFunctionState,
final MergeOp.Factory opFactory,
@@ -69,7 +63,6 @@ class SubmitAction extends Handler<TopicDetail> {
this.merger = mq;
this.approvalTypes = approvalTypes;
this.user = user;
- this.changeControlFactory = changeControlFactory;
this.topicControlFactory = topicControlFactory;
this.topicDetailFactory = topicDetailFactory;
this.topicFunctionState = topicFunctionState;
@@ -87,7 +80,7 @@ class SubmitAction extends Handler<TopicDetail> {
final TopicControl topicControl =
topicControlFactory.validateFor(topicId);
- CanSubmitResult result = topicControl.canSubmit(db, changeSetId, changeControlFactory,
+ CanSubmitResult result = topicControl.canSubmit(db, changeSetId,
approvalTypes, topicFunctionState);
if (result == CanSubmitResult.OK) {
TopicUtil.submit(changeSetId, user, db, opFactory, merger);
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/topic/TopicDetailFactory.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/topic/TopicDetailFactory.java
index 625965396c..a7ed068b9e 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/topic/TopicDetailFactory.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/topic/TopicDetailFactory.java
@@ -108,6 +108,7 @@ public class TopicDetailFactory extends Handler<TopicDetail> {
throw new NoSuchEntityException();
}
final CanSubmitResult canSubmitResult = control.canSubmit(changeSet.getId());
+ final CanSubmitResult canStageResult = control.canStage(changeSet.getId());
aic.want(topic.getOwner());
@@ -122,6 +123,7 @@ public class TopicDetailFactory extends Handler<TopicDetail> {
detail.setCanRevert(topic.getStatus() == AbstractEntity.Status.MERGED && control.canAddChangeSet());
detail.setCanSubmit(canSubmitResult == CanSubmitResult.OK);
+ detail.setCanStage(canStageResult == CanSubmitResult.OK);
loadChangeSets();
loadMessages();
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/topic/TopicManageServiceImpl.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/topic/TopicManageServiceImpl.java
index 817a9e2f7c..080f394d31 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/topic/TopicManageServiceImpl.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/topic/TopicManageServiceImpl.java
@@ -25,16 +25,19 @@ class TopicManageServiceImpl implements TopicManageService {
private final AbandonTopic.Factory abandonTopicFactory;
private final RestoreTopic.Factory restoreTopicFactory;
private final RevertTopic.Factory revertTopicFactory;
+ private final StagingAction.Factory stagingActionFactory;
@Inject
TopicManageServiceImpl(final SubmitAction.Factory changeSetAction,
final AbandonTopic.Factory abandonTopicFactory,
final RestoreTopic.Factory restoreTopicFactory,
- final RevertTopic.Factory revertTopicFactory) {
+ final RevertTopic.Factory revertTopicFactory,
+ final StagingAction.Factory stagingActionFactory) {
this.submitAction = changeSetAction;
this.abandonTopicFactory = abandonTopicFactory;
this.restoreTopicFactory = restoreTopicFactory;
this.revertTopicFactory = revertTopicFactory;
+ this.stagingActionFactory = stagingActionFactory;
}
public void submit(final ChangeSet.Id csid,
@@ -56,4 +59,9 @@ class TopicManageServiceImpl implements TopicManageService {
final AsyncCallback<TopicDetail> cb) {
restoreTopicFactory.create(csid, message).to(cb);
}
+
+ public void stage(ChangeSet.Id changeSetId,
+ AsyncCallback<TopicDetail> callback) {
+ stagingActionFactory.create(changeSetId).to(callback);
+ }
}
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/topic/TopicModule.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/topic/TopicModule.java
index e9c91623a3..528c4b3b88 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/topic/TopicModule.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/topic/TopicModule.java
@@ -39,6 +39,7 @@ public class TopicModule extends RpcServletModule {
factory(TopicDetailFactory.Factory.class);
factory(SubmitAction.Factory.class);
factory(IncludedInDetailHandler.Factory.class);
+ factory(StagingAction.Factory.class);
}
});
rpc(TopicDetailServiceImpl.class);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/ChangeUtil.java b/gerrit-server/src/main/java/com/google/gerrit/server/ChangeUtil.java
index 24e93b66cc..65c1e88146 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/ChangeUtil.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/ChangeUtil.java
@@ -59,11 +59,9 @@ import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.CommitBuilder;
-import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.RefUpdate;
-import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.FooterLine;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/TopicUtil.java b/gerrit-server/src/main/java/com/google/gerrit/server/TopicUtil.java
index fba6ce0ac4..6aef58fb03 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/TopicUtil.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/TopicUtil.java
@@ -15,6 +15,7 @@
package com.google.gerrit.server;
import static com.google.gerrit.reviewdb.ApprovalCategory.SUBMIT;
+import static com.google.gerrit.reviewdb.ApprovalCategory.STAGING;
import com.google.gerrit.common.ChangeHookRunner;
import com.google.gerrit.reviewdb.AbstractEntity;
@@ -39,6 +40,7 @@ import com.google.gerrit.server.patch.PatchSetInfoFactory;
import com.google.gerrit.server.patch.PatchSetInfoNotAvailableException;
import com.google.gerrit.server.project.InvalidChangeOperationException;
import com.google.gerrit.server.project.NoSuchChangeException;
+import com.google.gerrit.server.project.NoSuchRefException;
import com.google.gerrit.server.project.NoSuchTopicException;
import com.google.gerrit.server.project.TopicControl;
import com.google.gerrit.server.mail.AbandonedSender;
@@ -52,6 +54,7 @@ import com.google.gwtorm.client.OrmException;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.lib.PersonIdent;
+import org.eclipse.jgit.lib.Repository;
import java.io.IOException;
import java.util.ArrayList;
@@ -109,6 +112,40 @@ public class TopicUtil {
}
}
+ public static void stage(final ChangeSet.Id changeSetId,
+ final IdentifiedUser user, final ReviewDb db,
+ final MergeOp.Factory opFactory, final MergeQueue merger,
+ final Repository git, final ChangeHookRunner hooks)
+ throws OrmException, IOException, NoSuchRefException {
+ final Topic.Id topicId = changeSetId.getParentKey();
+ final ChangeSetApproval approval = createStagingApproval(changeSetId, user, db);
+
+ db.changeSetApprovals().upsert(Collections.singleton(approval));
+
+ final Topic updatedTopic = db.topics().atomicUpdate(topicId,
+ new AtomicUpdate<Topic>() {
+ @Override
+ public Topic update(Topic topic) {
+ if (topic.getStatus() == Topic.Status.NEW) {
+ topic.setStatus(Topic.Status.STAGED);
+ TopicUtil.updated(topic);
+ }
+ return topic;
+ }
+ });
+
+ if (updatedTopic.getStatus() == Topic.Status.STAGED) {
+ // Submit the changes belonging to the Topic
+ //
+
+ List<Change> toStage = db.changes().byTopicOpenAll(topicId).toList();
+ for(Change c : toStage) {
+ ChangeUtil.moveToStaging(opFactory, c.currentPatchSetId(), user, db,
+ merger, git, hooks);
+ }
+ }
+ }
+
public static ChangeSetApproval createSubmitApproval(
final ChangeSet.Id changeSetId, final IdentifiedUser user, final ReviewDb db
) throws OrmException {
@@ -129,6 +166,26 @@ public class TopicUtil {
return new ChangeSetApproval(akey, (short) 1);
}
+public static ChangeSetApproval createStagingApproval(
+ final ChangeSet.Id changeSetId, final IdentifiedUser user, final ReviewDb db
+ ) throws OrmException {
+ final List<ChangeSetApproval> allApprovals =
+ new ArrayList<ChangeSetApproval>(db.changeSetApprovals().byChangeSet(
+ changeSetId).toList());
+
+ final ChangeSetApproval.Key akey =
+ new ChangeSetApproval.Key(changeSetId, user.getAccountId(), STAGING);
+
+ for (final ChangeSetApproval approval : allApprovals) {
+ if (akey.equals(approval.getKey())) {
+ approval.setValue((short) 1);
+ approval.setGranted();
+ return approval;
+ }
+ }
+ return new ChangeSetApproval(akey, (short) 1);
+ }
+
public static void abandon(final ChangeSet.Id changeSetId,
final IdentifiedUser user, final String message, final ReviewDb db,
final AbandonedSender.Factory abandonedSenderFactory,
@@ -487,4 +544,53 @@ public class TopicUtil {
}
return null;
}
+
+ public static Topic setIntegrating(final Topic.Id topicId, ReviewDb db)
+ throws OrmException {
+ final Topic updatedTopic = db.topics().atomicUpdate(topicId,
+ new AtomicUpdate<Topic>() {
+ @Override
+ public Topic update(Topic topic) {
+ if (topic.getStatus() == Topic.Status.STAGED) {
+ topic.setStatus(Topic.Status.INTEGRATING);
+ TopicUtil.updated(topic);
+ }
+ return topic;
+ }
+ });
+
+ return updatedTopic;
+ }
+
+ public static Topic setIntegratingToMerged(final Topic.Id topicId, ReviewDb db)
+ throws OrmException {
+ final Topic updatedTopic =
+ db.topics().atomicUpdate(topicId, new AtomicUpdate<Topic>() {
+ @Override
+ public Topic update(Topic topic) {
+ if (topic.getStatus() == Topic.Status.INTEGRATING) {
+ topic.setStatus(Topic.Status.MERGED);
+ TopicUtil.updated(topic);
+ }
+ return topic;
+ }
+ });
+ return updatedTopic;
+ }
+
+ public static Topic setIntegratingToNew(final Topic.Id topicId, ReviewDb db)
+ throws OrmException {
+ final Topic updatedTopic =
+ db.topics().atomicUpdate(topicId, new AtomicUpdate<Topic>() {
+ @Override
+ public Topic update(Topic topic) {
+ if (topic.getStatus() == Topic.Status.INTEGRATING) {
+ topic.setStatus(Topic.Status.NEW);
+ TopicUtil.updated(topic);
+ }
+ return topic;
+ }
+ });
+ return updatedTopic;
+ }
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOp.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOp.java
index c35ef30fe3..78b50c2d00 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOp.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOp.java
@@ -20,6 +20,7 @@ import static java.util.concurrent.TimeUnit.MINUTES;
import com.google.gerrit.common.ChangeHookRunner;
import com.google.gerrit.common.data.ApprovalType;
import com.google.gerrit.common.data.ApprovalTypes;
+import com.google.gerrit.reviewdb.AbstractEntity;
import com.google.gerrit.reviewdb.Account;
import com.google.gerrit.reviewdb.ApprovalCategory;
import com.google.gerrit.reviewdb.Branch;
@@ -157,7 +158,7 @@ public class MergeOp {
* The status that the change should be set to after a successful merge.
* @return Final status of the change.
*/
- public Change.Status getStatus();
+ public AbstractEntity.Status getStatus();
/**
* Indicates if staging rebuild is required after a change is merged.
@@ -1351,7 +1352,7 @@ public class MergeOp {
final Topic.Id topicId = c.getTopicId();
final Change.Id changeId = c.getId();
final PatchSet.Id merged = c.currentPatchSetId();
- final Change.Status newStatus = mergeDelegate.getStatus();
+ final AbstractEntity.Status newStatus = mergeDelegate.getStatus();
try {
schema.changes().atomicUpdate(changeId, new AtomicUpdate<Change>() {
@@ -1396,7 +1397,7 @@ public class MergeOp {
schema.topics().atomicUpdate(topicId, new AtomicUpdate<Topic>() {
@Override
public Topic update(Topic t) {
- t.setStatus(Topic.Status.MERGED);
+ t.setStatus(newStatus);
TopicUtil.updated(t);
return t;
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/StagingMergeDelegate.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/StagingMergeDelegate.java
index 42172fbb96..eb777850af 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/StagingMergeDelegate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/StagingMergeDelegate.java
@@ -14,6 +14,7 @@
package com.google.gerrit.server.git;
+import com.google.gerrit.reviewdb.AbstractEntity;
import com.google.gerrit.reviewdb.ApprovalCategory;
import com.google.gerrit.reviewdb.Branch;
import com.google.gerrit.reviewdb.Change;
@@ -128,7 +129,7 @@ public class StagingMergeDelegate implements MergeDelegate {
}
@Override
- public Change.Status getStatus() {
+ public AbstractEntity.Status getStatus() {
return Change.Status.STAGED;
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/SubmitMergeDelegate.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/SubmitMergeDelegate.java
index 364992b9fe..b39b5f268c 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/SubmitMergeDelegate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/SubmitMergeDelegate.java
@@ -1,5 +1,6 @@
package com.google.gerrit.server.git;
+import com.google.gerrit.reviewdb.AbstractEntity;
import com.google.gerrit.reviewdb.ApprovalCategory;
import com.google.gerrit.reviewdb.Change;
import com.google.gerrit.reviewdb.ReviewDb;
@@ -69,7 +70,7 @@ public class SubmitMergeDelegate implements MergeDelegate {
}
@Override
- public Change.Status getStatus() {
+ public AbstractEntity.Status getStatus() {
return Change.Status.MERGED;
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/ChangeControl.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ChangeControl.java
index 1feee1b2cf..563fae7ec5 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/ChangeControl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ChangeControl.java
@@ -22,7 +22,6 @@ import com.google.gerrit.reviewdb.PatchSet;
import com.google.gerrit.reviewdb.PatchSetApproval;
import com.google.gerrit.reviewdb.Project;
import com.google.gerrit.reviewdb.ReviewDb;
-import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.workflow.CategoryFunction;
@@ -232,7 +231,6 @@ public class ChangeControl {
public CanSubmitResult canSubmit(final PatchSet.Id patchSetId,
final boolean fromTopic) {
- // FIXME Add topic handling
if (change.getStatus().isClosed()) {
return new CanSubmitResult("Change " + change.getId() + " is closed");
}
@@ -278,50 +276,35 @@ public class ChangeControl {
return CanSubmitResult.OK;
}
- /**
- * Checks if patch set can be merged to a staging branch.
- * @param patchSetId Patch set ID.
- * @param db Review database.
- * @param approvalTypes Approval types for this patch set.
- * @param functionStateFactory Factory for creating check functions for
- * different approval categories.
- * @return Result indicating if the patch set can be merged or not.
- * @throws OrmException Thrown if review database cannot accessed.
- */
- public CanSubmitResult canMergeToStaging(final PatchSet.Id patchSetId,
+ public CanSubmitResult canStage(final PatchSet.Id patchSetId,
final ReviewDb db, final ApprovalTypes approvalTypes,
FunctionState.Factory functionStateFactory)
throws OrmException {
- // Check that the state of the patch set and its parent change are valid.
- CanSubmitResult result = canMergeToStaging(patchSetId);
+ CanSubmitResult result = canStage(patchSetId);
if (result != CanSubmitResult.OK) {
return result;
}
- // List all approvals for this patch set.
- final List<PatchSetApproval> allApprovals =
- new ArrayList<PatchSetApproval>(db.patchSetApprovals().byPatchSet(
- patchSetId).toList());
+ final List<PatchSetApproval> all =
+ db.patchSetApprovals().byPatchSet(patchSetId).toList();
- // Create function for staging approval category and run it.
final FunctionState fs =
- functionStateFactory.create(change, patchSetId, allApprovals);
+ functionStateFactory.create(change, patchSetId, all);
+
for (ApprovalType c : approvalTypes.getApprovalTypes()) {
CategoryFunction.forCategory(c.getCategory()).run(c, fs);
}
- // There is nothing preventing the merge. Return OK result.
+ for (ApprovalType type : approvalTypes.getApprovalTypes()) {
+ if (!fs.isValid(type)) {
+ return new CanSubmitResult("Requires " + type.getCategory().getName());
+ }
+ }
+
return CanSubmitResult.OK;
}
- /**
- * Checks if the patch set and its parent change are in correct state for
- * merge to staging.
- *
- * @param patchSetId Patch set ID.
- * @return CanSubmitResult.OK if patch set can be merged to staging.
- */
- public CanSubmitResult canMergeToStaging(final PatchSet.Id patchSetId) {
+ public CanSubmitResult canStage(final PatchSet.Id patchSetId) {
if (change.getStatus() != Change.Status.NEW) {
return new CanSubmitResult("Change " + change.currPatchSetId().getParentKey() + " is not NEW");
}
@@ -337,19 +320,6 @@ public class ChangeControl {
return CanSubmitResult.OK;
}
- /**
- * Checks if change has valid approval in categories that are using
- * MaxWithBlock function. This function is used by categories like code
- * review or verified.
- *
- * @param patchSetId Patch set ID.
- * @param db Review database.
- * @param approvalTypes Configured approval types.
- * @param functionStateFactory Function state factory.
- * @return True if there is max score available in all MaxWithBlock
- * categories.
- * @throws OrmException Thrown, if datbase access fails.
- */
public boolean hasValidCategoryFunctions(final PatchSet.Id patchSetId,
final ReviewDb db, final ApprovalTypes approvalTypes,
FunctionState.Factory functionStateFactory) throws OrmException {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java
index 0f1aa27f8f..ecdf5937d9 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java
@@ -14,8 +14,6 @@
package com.google.gerrit.server.project;
-import static com.google.gerrit.reviewdb.ApprovalCategory.STAGING;
-
import com.google.gerrit.common.CollectionsUtil;
import com.google.gerrit.common.data.AccessSection;
import com.google.gerrit.common.data.ParamertizedString;
@@ -160,6 +158,10 @@ public class RefControl {
return canPerform(Permission.SUBMIT);
}
+ public boolean canStage() {
+ return canPerform(Permission.STAGE);
+ }
+
/** @return true if the user can update the reference as a fast-forward. */
public boolean canUpdate() {
if (GitRepositoryManager.REF_CONFIG.equals(refName)
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/TopicControl.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/TopicControl.java
index 83cb4d2676..b93632d659 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/TopicControl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/TopicControl.java
@@ -17,26 +17,19 @@ package com.google.gerrit.server.project;
import com.google.gerrit.common.data.ApprovalType;
import com.google.gerrit.common.data.ApprovalTypes;
import com.google.gerrit.common.data.PermissionRange;
-import com.google.gerrit.reviewdb.Change;
import com.google.gerrit.reviewdb.ChangeSet;
import com.google.gerrit.reviewdb.ChangeSetApproval;
-import com.google.gerrit.reviewdb.ChangeSetElement;
-import com.google.gerrit.reviewdb.PatchSetApproval;
import com.google.gerrit.reviewdb.Project;
import com.google.gerrit.reviewdb.ReviewDb;
import com.google.gerrit.reviewdb.Topic;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
-import com.google.gerrit.server.workflow.CategoryFunction;
-import com.google.gerrit.server.workflow.FunctionState;
import com.google.gerrit.server.workflow.TopicCategoryFunction;
import com.google.gerrit.server.workflow.TopicFunctionState;
import com.google.gwtorm.client.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
-import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
@@ -220,8 +213,8 @@ public class TopicControl {
}
public CanSubmitResult canSubmit(ReviewDb db, ChangeSet.Id changeSetId,
- final ChangeControl.Factory changeControlFactory,
- final ApprovalTypes approvalTypes, final TopicFunctionState.Factory functionStateFactory)
+ final ApprovalTypes approvalTypes,
+ final TopicFunctionState.Factory functionStateFactory)
throws NoSuchChangeException, OrmException {
CanSubmitResult result = canSubmit(changeSetId);
if (result != CanSubmitResult.OK) {
@@ -262,4 +255,49 @@ public class TopicControl {
}
return CanSubmitResult.OK;
}
+
+ public CanSubmitResult canStage(ChangeSet.Id changeSetId) {
+ if (topic.getStatus().isClosed()) {
+ return new CanSubmitResult("topic " + topic.getId() + " is closed");
+ }
+ if (!changeSetId.equals(topic.currentChangeSetId())) {
+ return new CanSubmitResult("Change set " + changeSetId + " is not current");
+ }
+ if (!getRefControl().canBranchToStaging()) {
+ return new CanSubmitResult("User does not have permission to merge to staging");
+ }
+ if (!(getCurrentUser() instanceof IdentifiedUser)) {
+ return new CanSubmitResult("User is not signed-in");
+ }
+ return CanSubmitResult.OK;
+ }
+
+ public CanSubmitResult canStage(ReviewDb db, ChangeSet.Id changeSetId,
+ final ChangeControl.Factory changeControlFactory,
+ final ApprovalTypes approvalTypes,
+ final TopicFunctionState.Factory functionStateFactory)
+ throws NoSuchChangeException, OrmException {
+ CanSubmitResult result = canStage(changeSetId);
+ if (result != CanSubmitResult.OK) {
+ return result;
+ }
+
+ final List<ChangeSetApproval> all =
+ db.changeSetApprovals().byChangeSet(changeSetId).toList();
+
+ final TopicFunctionState fs =
+ functionStateFactory.create(topic, changeSetId, all);
+
+ for (ApprovalType c : approvalTypes.getApprovalTypes()) {
+ TopicCategoryFunction.forCategory(c.getCategory()).run(c, fs);
+ }
+
+ for (ApprovalType type : approvalTypes.getApprovalTypes()) {
+ if (!fs.isValid(type)) {
+ return new CanSubmitResult("Requires " + type.getCategory().getName());
+ }
+ }
+
+ return CanSubmitResult.OK;
+ }
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/workflow/CategoryFunction.java b/gerrit-server/src/main/java/com/google/gerrit/server/workflow/CategoryFunction.java
index 94901c3428..ffed95a1de 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/workflow/CategoryFunction.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/workflow/CategoryFunction.java
@@ -32,7 +32,6 @@ public abstract class CategoryFunction {
all.put(MaxNoBlock.NAME, new MaxNoBlock());
all.put(NoOpFunction.NAME, new NoOpFunction());
all.put(NoBlock.NAME, new NoBlock());
- all.put(StagingFunction.NAME, new StagingFunction());
}
/**
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ReviewCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ReviewCommand.java
index c28efd00b1..44855c96d7 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ReviewCommand.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ReviewCommand.java
@@ -329,7 +329,7 @@ public class ReviewCommand extends BaseCommand {
throw error(result.getMessage());
}
} else if (staging) {
- CanSubmitResult result = changeControl.canMergeToStaging(patchSetId,
+ CanSubmitResult result = changeControl.canStage(patchSetId,
db, approvalTypes, functionStateFactory);
if (result == CanSubmitResult.OK) {
toStaging.add(patchSetId);
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/StagingApprove.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/StagingApprove.java
index 454b4bf948..5e2badf428 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/StagingApprove.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/StagingApprove.java
@@ -14,17 +14,21 @@
package com.google.gerrit.sshd.commands;
import static com.google.gerrit.sshd.commands.StagingCommand.R_BUILDS;
+import static com.google.gerrit.sshd.commands.StagingCommand.R_HEADS;
import com.google.gerrit.common.ChangeHookRunner;
import com.google.gerrit.common.data.ApprovalTypes;
import com.google.gerrit.reviewdb.ApprovalCategoryValue;
import com.google.gerrit.reviewdb.Branch;
import com.google.gerrit.reviewdb.Change;
+import com.google.gerrit.reviewdb.ChangeSet;
import com.google.gerrit.reviewdb.PatchSet;
import com.google.gerrit.reviewdb.Project;
import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.Topic;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.IdentifiedUser;
+import com.google.gerrit.server.TopicUtil;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.MergeOp;
import com.google.gerrit.server.git.MergeQueue;
@@ -34,7 +38,10 @@ import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.project.InvalidChangeOperationException;
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.project.NoSuchRefException;
+import com.google.gerrit.server.project.NoSuchTopicException;
import com.google.gerrit.server.workflow.FunctionState;
+import com.google.gerrit.server.project.TopicControl;
+import com.google.gerrit.server.workflow.TopicFunctionState;
import com.google.gerrit.sshd.BaseCommand;
import com.google.gerrit.sshd.commands.StagingCommand.BranchNotFoundException;
import com.google.gwtorm.client.AtomicUpdate;
@@ -101,6 +108,9 @@ public class StagingApprove extends BaseCommand {
private ChangeControl.Factory changeControlFactory;
@Inject
+ private TopicControl.Factory topicControlFactory;
+
+ @Inject
private ApprovalTypes approvalTypes;
@Inject
@@ -118,6 +128,9 @@ public class StagingApprove extends BaseCommand {
@Inject
private MergeOp.Factory opFactory;
+ @Inject
+ private TopicFunctionState.Factory topicFunctionStateFactory;
+
@Option(name = "--project", aliases = {"-p"},
required = true, usage = "project name")
private String project;
@@ -134,6 +147,10 @@ public class StagingApprove extends BaseCommand {
usage = "message added to all changes")
private String message;
+ @Option(name = "--branch", aliases = {"-b"}, metaVar = "BRANCH",
+ required = true, usage = "destination branch")
+ private String branch;
+
private Repository git;
private List<PatchSet> toApprove;
@@ -170,11 +187,13 @@ public class StagingApprove extends BaseCommand {
Branch.NameKey buildBranchNameKey =
StagingCommand.getNameKey(project, R_BUILDS, buildBranch);
+ destination = StagingCommand.getNameKey(project, R_HEADS, branch);
+
try {
openRepository(project);
// Initialize and populate open changes list.
- toApprove = StagingCommand.openChanges(git, db, buildBranchNameKey.get());
+ toApprove = StagingCommand.openChanges(git, db, buildBranchNameKey);
// Notify user that build did not have any open changes. The build has
// already been approved.
@@ -235,6 +254,10 @@ public class StagingApprove extends BaseCommand {
throw new UnloggedFailure(1, "fatal: " + e.getMessage(), e);
} catch (InvalidChangeOperationException e) {
throw new UnloggedFailure(1, "fatal: Failed to publish comments", e);
+ } catch (IllegalStateException e) {
+ throw new UnloggedFailure(1, "fatal: Changes are missing required approvals: " + e.getMessage(), e);
+ } catch (NoSuchTopicException e) {
+ throw new UnloggedFailure(1, "fatal: Invalid topic: " + e.getMessage(), e);
} finally {
stdout.flush();
if (git != null) {
@@ -245,16 +268,7 @@ public class StagingApprove extends BaseCommand {
private void validateChanges() throws OrmException, UnloggedFailure {
for (PatchSet patchSet : toApprove) {
- Change change = db.changes().get(patchSet.getId().getParentKey());
-
- // All changes must originate from the same destination branch.
- if (destination == null) {
- destination = change.getDest();
- } else if (!destination.get().equals(change.getDest().get())) {
- throw new UnloggedFailure(1,
- "All changes in build must belong to same destination branch."
- + " (" + destination + " != " + change.getDest() + ")");
- }
+ final Change change = db.changes().get(patchSet.getId().getParentKey());
// All changes must be in state INTEGRATING.
if (change.getStatus() != Change.Status.INTEGRATING) {
@@ -270,17 +284,37 @@ public class StagingApprove extends BaseCommand {
}
private void validateSubmitRights() throws UnloggedFailure,
- NoSuchChangeException, OrmException {
+ NoSuchChangeException, OrmException, NoSuchTopicException {
for (PatchSet patchSet : toApprove) {
final Change.Id changeId = patchSet.getId().getParentKey();
- final ChangeControl changeControl =
- changeControlFactory.validateFor(changeId);
-
- CanSubmitResult result =
- changeControl.canSubmit(patchSet.getId(), db, approvalTypes, functionStateFactory);
-
- if (result != CanSubmitResult.OK) {
- throw new UnloggedFailure(1, result.getMessage());
+ final Change change = db.changes().get(changeId);
+
+ final Topic.Id topicId = change.getTopicId();
+ // Check only topic status for changes in topic.
+ if (topicId != null) {
+ // Change is part of a topic. Validate the topic with
+ // TopicChangeControl.
+ final TopicControl topicControl =
+ topicControlFactory.validateFor(topicId);
+ List<ChangeSet> changeSets = db.changeSets().byTopic(topicId).toList();
+ for (ChangeSet changeSet : changeSets) {
+ CanSubmitResult result =
+ topicControl.canSubmit(db, changeSet.getId(), approvalTypes,
+ topicFunctionStateFactory);
+ if (result != CanSubmitResult.OK) {
+ throw new UnloggedFailure(1, result.getMessage());
+ }
+ }
+ } else {
+ // Change is not part of a topic. Validate it with ChangeControl.
+ final ChangeControl changeControl =
+ changeControlFactory.validateFor(changeId);
+ CanSubmitResult result =
+ changeControl.canSubmit(patchSet.getId(), db, approvalTypes,
+ functionStateFactory);
+ if (result != CanSubmitResult.OK) {
+ throw new UnloggedFailure(1, result.getMessage());
+ }
}
}
}
@@ -344,12 +378,28 @@ public class StagingApprove extends BaseCommand {
private void pass(final PatchSet.Id patchSetId) throws OrmException {
// Update change status from INTEGRATING to MERGED.
ChangeUtil.setIntegratingToMerged(patchSetId, currentUser, db);
+ Change change = db.changes().get(patchSetId.getParentKey());
+ Topic.Id topicId = change.getTopicId();
+ if (topicId != null) {
+ Topic topic = db.topics().get(topicId);
+ if (topic.getStatus() != Topic.Status.MERGED) {
+ TopicUtil.setIntegratingToMerged(topicId, db);
+ }
+ }
}
private void reject(final PatchSet.Id patchSetId) throws OrmException,
IOException {
// Remove staging approval and update status from INTEGRATING to NEW.
ChangeUtil.rejectStagedChange(patchSetId, currentUser, db);
+ Change change = db.changes().get(patchSetId.getParentKey());
+ Topic.Id topicId = change.getTopicId();
+ if (topicId != null) {
+ Topic topic = db.topics().get(topicId);
+ if (topic.getStatus() != Topic.Status.NEW) {
+ TopicUtil.setIntegratingToNew(topicId, db);
+ }
+ }
}
private void prepareMessage() throws IOException {
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/StagingCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/StagingCommand.java
index 4ff0da3800..e30e1123ac 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/StagingCommand.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/StagingCommand.java
@@ -110,7 +110,7 @@ public class StagingCommand {
* @throws OrmException Thrown if ReviewDb is not accessible.
*/
public static List<PatchSet> openChanges(Repository git, ReviewDb db,
- final String branch) throws IOException, OrmException,
+ final Branch.NameKey branch) throws IOException, OrmException,
BranchNotFoundException {
List<PatchSet> open = new ArrayList<PatchSet>();
PatchSetAccess patchSetAccess = db.patchSets();
@@ -118,7 +118,7 @@ public class StagingCommand {
RevWalk revWalk = new RevWalk(git);
try {
- Ref ref = git.getRef(branch);
+ Ref ref = git.getRef(branch.get());
if (ref == null) {
throw new BranchNotFoundException("No such branch: " + branch);
}
@@ -151,7 +151,7 @@ public class StagingCommand {
List<Change> changes =
db.changes().byKey(Change.Key.parse(changeId)).toList();
for (Change change : changes) {
- if (change.getStatus().isOpen()) {
+ if (change.getStatus().isOpen() && change.getDest().equals(branch)) {
open.add(patchSetAccess.get(change.currentPatchSetId()));
}
}
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/StagingListChanges.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/StagingListChanges.java
index c37a096f43..2b70afd510 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/StagingListChanges.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/StagingListChanges.java
@@ -13,6 +13,7 @@
// limitations under the License.
package com.google.gerrit.sshd.commands;
+import com.google.gerrit.reviewdb.Branch;
import com.google.gerrit.reviewdb.Change;
import com.google.gerrit.reviewdb.PatchSet;
import com.google.gerrit.reviewdb.Project;
@@ -66,7 +67,9 @@ public class StagingListChanges extends BaseCommand {
try {
openRepository(project);
- List<PatchSet> open = StagingCommand.openChanges(git, db, branch);
+ final Project.NameKey projectKey = new Project.NameKey(project);
+ final Branch.NameKey branchKey = new Branch.NameKey(projectKey, branch);
+ List<PatchSet> open = StagingCommand.openChanges(git, db, branchKey);
for (PatchSet patchSet : open) {
Change.Id changeId = patchSet.getId().getParentKey();
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/StagingNewBuild.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/StagingNewBuild.java
index afeb5528ee..83cf163f6b 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/StagingNewBuild.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/StagingNewBuild.java
@@ -16,10 +16,13 @@ package com.google.gerrit.sshd.commands;
import static com.google.gerrit.sshd.commands.StagingCommand.R_BUILDS;
import static com.google.gerrit.sshd.commands.StagingCommand.R_STAGING;
import com.google.gerrit.reviewdb.Branch;
+import com.google.gerrit.reviewdb.Change;
import com.google.gerrit.reviewdb.PatchSet;
import com.google.gerrit.reviewdb.Project;
import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.Topic;
import com.google.gerrit.server.ChangeUtil;
+import com.google.gerrit.server.TopicUtil;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.StagingUtil;
import com.google.gerrit.server.project.NoSuchRefException;
@@ -30,7 +33,6 @@ import com.google.inject.Inject;
import org.apache.sshd.server.Environment;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
-import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefUpdate.Result;
import org.eclipse.jgit.lib.Repository;
import org.kohsuke.args4j.Option;
@@ -87,8 +89,11 @@ public class StagingNewBuild extends BaseCommand {
Branch.NameKey stagingBranchKey =
StagingCommand.getNameKey(project, R_STAGING, stagingBranch);
+ Branch.NameKey branchNameKey =
+ StagingCommand.getShortNameKey(project, R_STAGING, stagingBranch);
+
// Make sure that are changes in the staging branch.
- if (StagingCommand.openChanges(git, db, stagingBranchKey.get()).isEmpty()) {
+ if (StagingCommand.openChanges(git, db, stagingBranchKey).isEmpty()) {
stdout.println("No changes in staging branch. Not creating a build reference");
return;
}
@@ -100,12 +105,11 @@ public class StagingNewBuild extends BaseCommand {
if (result != Result.NEW && result != Result.FAST_FORWARD) {
throw new UnloggedFailure(1, "fatal: failed to create new build ref: " + result);
} else {
- updateChangeStatus(buildBranchKey);
+ updateChangeStatus(buildBranchKey, branchNameKey);
}
// Re-create staging branch.
- Branch.NameKey branchNameKey =
- StagingCommand.getShortNameKey(project, R_STAGING, stagingBranch);
+
result = StagingUtil.createStagingBranch(git, branchNameKey);
if (result != Result.NEW && result != Result.FAST_FORWARD
&& result != Result.FORCED && result != Result.NO_CHANGE) {
@@ -116,7 +120,7 @@ public class StagingNewBuild extends BaseCommand {
} catch (OrmException e) {
throw new UnloggedFailure(1, "fatal: Failed to access database", e);
} catch (BranchNotFoundException e) {
- throw new UnloggedFailure(1, "fatal: Failed to access build ref", e);
+ throw new UnloggedFailure(1, "fatal: Failed to access build or staging ref", e);
} catch (NoSuchRefException e) {
throw new UnloggedFailure(1, "fatal: Invalid branch name", e);
} finally {
@@ -132,12 +136,21 @@ public class StagingNewBuild extends BaseCommand {
git = gitManager.openRepository(projectKey);
}
- private void updateChangeStatus(final Branch.NameKey buildBranchKey)
+ private void updateChangeStatus(final Branch.NameKey buildBranchKey,
+ final Branch.NameKey destBranchKey)
throws IOException, OrmException, BranchNotFoundException {
List<PatchSet> patchSets =
- StagingCommand.openChanges(git, db, buildBranchKey.get());
+ StagingCommand.openChanges(git, db, buildBranchKey);
for (PatchSet patchSet : patchSets) {
ChangeUtil.setIntegrating(patchSet.getId(), db);
+ Change change = db.changes().get(patchSet.getId().getParentKey());
+ Topic.Id topicId = change.getTopicId();
+ if (topicId != null) {
+ Topic topic = db.topics().get(topicId);
+ if (topic.getStatus() != Topic.Status.INTEGRATING) {
+ TopicUtil.setIntegrating(topicId, db);
+ }
+ }
}
}
}
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/StagingRebuild.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/StagingRebuild.java
index af252cdb77..f750ae0783 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/StagingRebuild.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/StagingRebuild.java
@@ -4,7 +4,6 @@ import static com.google.gerrit.sshd.commands.StagingCommand.R_HEADS;
import com.google.gerrit.common.ChangeHookRunner;
import com.google.gerrit.reviewdb.Branch;
-import com.google.gerrit.reviewdb.Project;
import com.google.gerrit.reviewdb.ReviewDb;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.IdentifiedUser;