Merge changes Ice62183c,I41c3c444
* changes: MergeOp: Report change id in case of submit rule problems Submit: Include ancestors into problem description
This commit is contained in:
@@ -871,6 +871,17 @@ abbreviated commit SHA-1 (`c9c0edb`).
|
||||
+
|
||||
Default is "Submit patch set ${patchSet} into ${branch}".
|
||||
|
||||
[[change.submitTooltipAncestors]]change.submitTooltipAncestors::
|
||||
+
|
||||
Tooltip for the submit button if there are ancestors which would
|
||||
also be submitted by submitting the change. Additionally to the variables
|
||||
as in link:#change.submitTooltip[change.submitTooltip], there is the
|
||||
variable `${submitSize}` indicating the number of changes which are
|
||||
submitted.
|
||||
+
|
||||
Default is "Submit all ${topicSize} changes of the same topic (${submitSize}
|
||||
changes including ancestors and other changes related by topic)".
|
||||
|
||||
[[change.submitWholeTopic]]change.submitWholeTopic::
|
||||
+
|
||||
Determines if the submit button submits the whole topic instead of
|
||||
|
@@ -52,15 +52,14 @@ public class ActionsIT extends AbstractDaemonTest {
|
||||
commonActionsAssertions(actions);
|
||||
// We want to treat a single change in a topic not as a whole topic,
|
||||
// so regardless of how submitWholeTopic is configured:
|
||||
noSubmitWholeTopicAssertions(actions);
|
||||
noSubmitWholeTopicAssertions(actions, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void revisionActionsTwoChangeChangesInTopic() throws Exception {
|
||||
public void revisionActionsTwoChangesInTopic() throws Exception {
|
||||
String changeId = createChangeWithTopic().getChangeId();
|
||||
approve(changeId);
|
||||
// create another change with the same topic
|
||||
createChangeWithTopic().getChangeId();
|
||||
String changeId2 = createChangeWithTopic().getChangeId();
|
||||
Map<String, ActionInfo> actions = getActions(changeId);
|
||||
commonActionsAssertions(actions);
|
||||
if (isSubmitWholeTopicEnabled()) {
|
||||
@@ -68,14 +67,19 @@ public class ActionsIT extends AbstractDaemonTest {
|
||||
assertThat(info.enabled).isNull();
|
||||
assertThat(info.label).isEqualTo("Submit whole topic");
|
||||
assertThat(info.method).isEqualTo("POST");
|
||||
assertThat(info.title).isEqualTo("Other changes in this topic are not ready");
|
||||
assertThat(info.title).isEqualTo("This change depends on other " +
|
||||
"changes which are not ready");
|
||||
} else {
|
||||
noSubmitWholeTopicAssertions(actions);
|
||||
noSubmitWholeTopicAssertions(actions, 1);
|
||||
|
||||
assertThat(getActions(changeId2).get("submit")).isNull();
|
||||
approve(changeId2);
|
||||
noSubmitWholeTopicAssertions(getActions(changeId2), 2);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void revisionActionsTwoChangeChangesInTopic_conflicting() throws Exception {
|
||||
public void revisionActionsTwoChangesInTopic_conflicting() throws Exception {
|
||||
String changeId = createChangeWithTopic().getChangeId();
|
||||
approve(changeId);
|
||||
|
||||
@@ -99,38 +103,66 @@ public class ActionsIT extends AbstractDaemonTest {
|
||||
assertThat(info.label).isEqualTo("Submit whole topic");
|
||||
assertThat(info.method).isEqualTo("POST");
|
||||
assertThat(info.title).isEqualTo(
|
||||
"Clicking the button would fail for other changes in the topic");
|
||||
"Clicking the button would fail for other changes");
|
||||
} else {
|
||||
noSubmitWholeTopicAssertions(actions);
|
||||
noSubmitWholeTopicAssertions(actions, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void revisionActionsTwoChangeChangesInTopicReady() throws Exception {
|
||||
String changeId = createChangeWithTopic().getChangeId();
|
||||
public void revisionActionsTwoChangesInTopicWithAncestorReady()
|
||||
throws Exception {
|
||||
String changeId = createChange().getChangeId();
|
||||
approve(changeId);
|
||||
approve(changeId);
|
||||
String changeId1 = createChangeWithTopic().getChangeId();
|
||||
approve(changeId1);
|
||||
// create another change with the same topic
|
||||
String changeId2 = createChangeWithTopic().getChangeId();
|
||||
approve(changeId2);
|
||||
Map<String, ActionInfo> actions = getActions(changeId);
|
||||
Map<String, ActionInfo> actions = getActions(changeId1);
|
||||
commonActionsAssertions(actions);
|
||||
if (isSubmitWholeTopicEnabled()) {
|
||||
ActionInfo info = actions.get("submit");
|
||||
assertThat(info.enabled).isTrue();
|
||||
assertThat(info.label).isEqualTo("Submit whole topic");
|
||||
assertThat(info.method).isEqualTo("POST");
|
||||
assertThat(info.title).isEqualTo("Submit all 2 changes of the same topic");
|
||||
assertThat(info.title).isEqualTo("Submit all 2 changes of the same " +
|
||||
"topic (3 changes including ancestors " +
|
||||
"and other changes related by topic)");
|
||||
} else {
|
||||
noSubmitWholeTopicAssertions(actions);
|
||||
noSubmitWholeTopicAssertions(actions, 2);
|
||||
}
|
||||
}
|
||||
|
||||
private void noSubmitWholeTopicAssertions(Map<String, ActionInfo> actions) {
|
||||
@Test
|
||||
public void revisionActionsReadyWithAncestors() throws Exception {
|
||||
String changeId = createChange().getChangeId();
|
||||
approve(changeId);
|
||||
approve(changeId);
|
||||
String changeId1 = createChange().getChangeId();
|
||||
approve(changeId1);
|
||||
String changeId2 = createChangeWithTopic().getChangeId();
|
||||
approve(changeId2);
|
||||
Map<String, ActionInfo> actions = getActions(changeId2);
|
||||
commonActionsAssertions(actions);
|
||||
// The topic contains only one change, so standard text applies
|
||||
noSubmitWholeTopicAssertions(actions, 3);
|
||||
}
|
||||
|
||||
private void noSubmitWholeTopicAssertions(Map<String, ActionInfo> actions,
|
||||
int nrChanges) {
|
||||
ActionInfo info = actions.get("submit");
|
||||
assertThat(info.enabled).isTrue();
|
||||
assertThat(info.label).isEqualTo("Submit");
|
||||
assertThat(info.method).isEqualTo("POST");
|
||||
if (nrChanges == 1) {
|
||||
assertThat(info.title).isEqualTo("Submit patch set 1 into master");
|
||||
} else {
|
||||
assertThat(info.title).isEqualTo(String.format(
|
||||
"Submit patch set 1 and ancestors (%d changes " +
|
||||
"altogether) into master", nrChanges));
|
||||
}
|
||||
}
|
||||
|
||||
private void commonActionsAssertions(Map<String, ActionInfo> actions) {
|
||||
|
@@ -46,6 +46,7 @@ import com.google.gerrit.server.config.GerritServerConfig;
|
||||
import com.google.gerrit.server.git.ChangeSet;
|
||||
import com.google.gerrit.server.git.GitRepositoryManager;
|
||||
import com.google.gerrit.server.git.MergeOp;
|
||||
import com.google.gerrit.server.git.MergeSuperSet;
|
||||
import com.google.gerrit.server.project.ChangeControl;
|
||||
import com.google.gerrit.server.project.NoSuchChangeException;
|
||||
import com.google.gerrit.server.project.SubmitRuleEvaluator;
|
||||
@@ -64,8 +65,6 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -77,16 +76,21 @@ public class Submit implements RestModifyView<RevisionResource, SubmitInput>,
|
||||
|
||||
private static final String DEFAULT_TOOLTIP =
|
||||
"Submit patch set ${patchSet} into ${branch}";
|
||||
private static final String DEFAULT_TOOLTIP_ANCESTORS =
|
||||
"Submit patch set ${patchSet} and ancestors (${submitSize} changes " +
|
||||
"altogether) into ${branch}";
|
||||
private static final String DEFAULT_TOPIC_TOOLTIP =
|
||||
"Submit all ${topicSize} changes of the same topic";
|
||||
private static final String BLOCKED_TOPIC_TOOLTIP =
|
||||
"Other changes in this topic are not ready";
|
||||
private static final String BLOCKED_HIDDEN_TOPIC_TOOLTIP =
|
||||
"Other hidden changes in this topic are not ready";
|
||||
private static final String CLICK_FAILURE_OTHER_TOOLTIP =
|
||||
"Clicking the button would fail for other changes in the topic";
|
||||
"Submit all ${topicSize} changes of the same topic " +
|
||||
"(${submitSize} changes including ancestors and other " +
|
||||
"changes related by topic)";
|
||||
private static final String BLOCKED_SUBMIT_TOOLTIP =
|
||||
"This change depends on other changes which are not ready";
|
||||
private static final String BLOCKED_HIDDEN_SUBMIT_TOOLTIP =
|
||||
"This change depends on other hidden changes which are not ready";
|
||||
private static final String CLICK_FAILURE_TOOLTIP =
|
||||
"Clicking the button would fail.";
|
||||
"Clicking the button would fail";
|
||||
private static final String CLICK_FAILURE_OTHER_TOOLTIP =
|
||||
"Clicking the button would fail for other changes";
|
||||
|
||||
public static class Output {
|
||||
transient Change change;
|
||||
@@ -100,11 +104,14 @@ public class Submit implements RestModifyView<RevisionResource, SubmitInput>,
|
||||
private final GitRepositoryManager repoManager;
|
||||
private final ChangeData.Factory changeDataFactory;
|
||||
private final ChangeMessagesUtil cmUtil;
|
||||
private final ChangeControl.GenericFactory changeControlFactory;
|
||||
private final Provider<MergeOp> mergeOpProvider;
|
||||
private final MergeSuperSet mergeSuperSet;
|
||||
private final AccountsCollection accounts;
|
||||
private final ChangesCollection changes;
|
||||
private final String label;
|
||||
private final ParameterizedString titlePattern;
|
||||
private final ParameterizedString titlePatternWithAncestors;
|
||||
private final String submitTopicLabel;
|
||||
private final ParameterizedString submitTopicTooltip;
|
||||
private final boolean submitWholeTopic;
|
||||
@@ -115,7 +122,9 @@ public class Submit implements RestModifyView<RevisionResource, SubmitInput>,
|
||||
GitRepositoryManager repoManager,
|
||||
ChangeData.Factory changeDataFactory,
|
||||
ChangeMessagesUtil cmUtil,
|
||||
ChangeControl.GenericFactory changeControlFactory,
|
||||
Provider<MergeOp> mergeOpProvider,
|
||||
MergeSuperSet mergeSuperSet,
|
||||
AccountsCollection accounts,
|
||||
ChangesCollection changes,
|
||||
@GerritServerConfig Config cfg,
|
||||
@@ -124,7 +133,9 @@ public class Submit implements RestModifyView<RevisionResource, SubmitInput>,
|
||||
this.repoManager = repoManager;
|
||||
this.changeDataFactory = changeDataFactory;
|
||||
this.cmUtil = cmUtil;
|
||||
this.changeControlFactory = changeControlFactory;
|
||||
this.mergeOpProvider = mergeOpProvider;
|
||||
this.mergeSuperSet = mergeSuperSet;
|
||||
this.accounts = accounts;
|
||||
this.changes = changes;
|
||||
this.label = MoreObjects.firstNonNull(
|
||||
@@ -133,6 +144,10 @@ public class Submit implements RestModifyView<RevisionResource, SubmitInput>,
|
||||
this.titlePattern = new ParameterizedString(MoreObjects.firstNonNull(
|
||||
cfg.getString("change", null, "submitTooltip"),
|
||||
DEFAULT_TOOLTIP));
|
||||
this.titlePatternWithAncestors = new ParameterizedString(
|
||||
MoreObjects.firstNonNull(
|
||||
cfg.getString("change", null, "submitTooltipAncestors"),
|
||||
DEFAULT_TOOLTIP_ANCESTORS));
|
||||
submitWholeTopic = wholeTopicEnabled(cfg);
|
||||
this.submitTopicLabel = MoreObjects.firstNonNull(
|
||||
Strings.emptyToNull(cfg.getString("change", null, "submitTopicLabel")),
|
||||
@@ -170,16 +185,7 @@ public class Submit implements RestModifyView<RevisionResource, SubmitInput>,
|
||||
rsrc.getPatchSet().getRevision().get()));
|
||||
}
|
||||
|
||||
List<Change> changes;
|
||||
if (submitWholeTopic && !Strings.isNullOrEmpty(change.getTopic())) {
|
||||
changes = new ArrayList<>();
|
||||
for (ChangeData cd : getChangesByTopic(change.getTopic())) {
|
||||
changes.add(cd.change());
|
||||
}
|
||||
} else {
|
||||
changes = Arrays.asList(change);
|
||||
}
|
||||
ChangeSet submittedChanges = ChangeSet.create(changes);
|
||||
ChangeSet submittedChanges = ChangeSet.create(change);
|
||||
|
||||
try {
|
||||
ReviewDb db = dbProvider.get();
|
||||
@@ -207,22 +213,24 @@ public class Submit implements RestModifyView<RevisionResource, SubmitInput>,
|
||||
}
|
||||
|
||||
/**
|
||||
* @param changeList list of changes to be submitted at once
|
||||
* @param cs set of changes to be submitted at once
|
||||
* @param identifiedUser the user who is checking to submit
|
||||
* @return a reason why any of the changes is not submittable or null
|
||||
*/
|
||||
private String problemsForSubmittingChanges(
|
||||
List<ChangeData> changeList,
|
||||
IdentifiedUser identifiedUser) {
|
||||
private String problemsForSubmittingChangeset(
|
||||
ChangeSet cs, IdentifiedUser identifiedUser) {
|
||||
try {
|
||||
for (ChangeData c : changeList) {
|
||||
ChangeControl changeControl = c.changeControl().forUser(
|
||||
identifiedUser);
|
||||
for (PatchSet.Id psId : cs.patchIds()) {
|
||||
ReviewDb db = dbProvider.get();
|
||||
ChangeControl changeControl = changeControlFactory
|
||||
.controlFor(psId.getParentKey(), identifiedUser);
|
||||
ChangeData c = changeDataFactory.create(db, changeControl);
|
||||
|
||||
if (!changeControl.isVisible(dbProvider.get())) {
|
||||
return BLOCKED_HIDDEN_TOPIC_TOOLTIP;
|
||||
return BLOCKED_HIDDEN_SUBMIT_TOOLTIP;
|
||||
}
|
||||
if (!changeControl.canSubmit()) {
|
||||
return BLOCKED_TOPIC_TOOLTIP;
|
||||
return BLOCKED_SUBMIT_TOOLTIP;
|
||||
}
|
||||
// Recheck mergeability rather than using value stored in the index,
|
||||
// which may be stale.
|
||||
@@ -240,8 +248,8 @@ public class Submit implements RestModifyView<RevisionResource, SubmitInput>,
|
||||
checkSubmitRule(c, c.currentPatchSet(), false);
|
||||
}
|
||||
} catch (ResourceConflictException e) {
|
||||
return BLOCKED_TOPIC_TOOLTIP;
|
||||
} catch (OrmException e) {
|
||||
return BLOCKED_SUBMIT_TOOLTIP;
|
||||
} catch (NoSuchChangeException | OrmException e) {
|
||||
log.error("Error checking if change is submittable", e);
|
||||
throw new OrmRuntimeException("Could not determine problems for the change", e);
|
||||
}
|
||||
@@ -282,40 +290,55 @@ public class Submit implements RestModifyView<RevisionResource, SubmitInput>,
|
||||
throw new OrmRuntimeException("Could not determine mergeability", e);
|
||||
}
|
||||
|
||||
List<ChangeData> changesByTopic = null;
|
||||
if (submitWholeTopic && !Strings.isNullOrEmpty(topic)) {
|
||||
changesByTopic = getChangesByTopic(topic);
|
||||
ChangeSet cs;
|
||||
try {
|
||||
cs = mergeSuperSet.completeChangeSet(db,
|
||||
ChangeSet.create(cd.change()));
|
||||
} catch (OrmException | IOException e) {
|
||||
throw new OrmRuntimeException("Could not determine complete set of " +
|
||||
"changes to be submitted", e);
|
||||
}
|
||||
if (submitWholeTopic
|
||||
|
||||
int topicSize = 0;
|
||||
if (!Strings.isNullOrEmpty(topic)) {
|
||||
topicSize = getChangesByTopic(topic).size();
|
||||
}
|
||||
boolean treatWithTopic = submitWholeTopic
|
||||
&& !Strings.isNullOrEmpty(topic)
|
||||
&& changesByTopic.size() > 1) {
|
||||
Map<String, String> params = ImmutableMap.of(
|
||||
"topicSize", String.valueOf(changesByTopic.size()));
|
||||
String topicProblems = problemsForSubmittingChanges(changesByTopic,
|
||||
&& topicSize > 1;
|
||||
|
||||
String submitProblems = problemsForSubmittingChangeset(cs,
|
||||
resource.getUser());
|
||||
if (topicProblems != null) {
|
||||
if (submitProblems != null) {
|
||||
return new UiAction.Description()
|
||||
.setLabel(submitTopicLabel)
|
||||
.setTitle(topicProblems)
|
||||
.setLabel(treatWithTopic ? submitTopicLabel : label)
|
||||
.setTitle(submitProblems)
|
||||
.setVisible(true)
|
||||
.setEnabled(false);
|
||||
} else {
|
||||
}
|
||||
|
||||
if (treatWithTopic) {
|
||||
Map<String, String> params = ImmutableMap.of(
|
||||
"topicSize", String.valueOf(topicSize),
|
||||
"submitSize", String.valueOf(cs.size()));
|
||||
return new UiAction.Description()
|
||||
.setLabel(submitTopicLabel)
|
||||
.setTitle(Strings.emptyToNull(
|
||||
submitTopicTooltip.replace(params)))
|
||||
.setVisible(true)
|
||||
.setEnabled(Boolean.TRUE.equals(enabled));
|
||||
}
|
||||
} else {
|
||||
RevId revId = resource.getPatchSet().getRevision();
|
||||
Map<String, String> params = ImmutableMap.of(
|
||||
"patchSet", String.valueOf(resource.getPatchSet().getPatchSetId()),
|
||||
"branch", resource.getChange().getDest().getShortName(),
|
||||
"commit", ObjectId.fromString(revId.get()).abbreviate(7).name());
|
||||
"commit", ObjectId.fromString(revId.get()).abbreviate(7).name(),
|
||||
"submitSize", String.valueOf(cs.size()));
|
||||
ParameterizedString tp = cs.size() > 1 ? titlePatternWithAncestors :
|
||||
titlePattern;
|
||||
return new UiAction.Description()
|
||||
.setLabel(label)
|
||||
.setTitle(Strings.emptyToNull(titlePattern.replace(params)))
|
||||
.setTitle(Strings.emptyToNull(tp.replace(params)))
|
||||
.setVisible(true)
|
||||
.setEnabled(Boolean.TRUE.equals(enabled));
|
||||
}
|
||||
|
@@ -20,6 +20,7 @@ import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSetMultimap;
|
||||
import com.google.gerrit.reviewdb.client.Branch;
|
||||
import com.google.gerrit.reviewdb.client.Change;
|
||||
import com.google.gerrit.reviewdb.client.PatchSet;
|
||||
import com.google.gerrit.reviewdb.client.Project;
|
||||
|
||||
/** A set of changes grouped together to be submitted atomically.*/
|
||||
@@ -29,6 +30,7 @@ public abstract class ChangeSet {
|
||||
ImmutableSet.Builder<Project.NameKey> pb = ImmutableSet.builder();
|
||||
ImmutableSet.Builder<Branch.NameKey> bb = ImmutableSet.builder();
|
||||
ImmutableSet.Builder<Change.Id> ib = ImmutableSet.builder();
|
||||
ImmutableSet.Builder<PatchSet.Id> psb = ImmutableSet.builder();
|
||||
ImmutableSetMultimap.Builder<Project.NameKey, Branch.NameKey> pbb =
|
||||
ImmutableSetMultimap.builder();
|
||||
ImmutableSetMultimap.Builder<Project.NameKey, Change.Id> pcb =
|
||||
@@ -42,13 +44,14 @@ public abstract class ChangeSet {
|
||||
pb.add(project);
|
||||
bb.add(branch);
|
||||
ib.add(c.getId());
|
||||
psb.add(c.currentPatchSetId());
|
||||
pbb.put(project, branch);
|
||||
pcb.put(project, c.getId());
|
||||
cbb.put(branch, c.getId());
|
||||
}
|
||||
|
||||
return new AutoValue_ChangeSet(pb.build(), bb.build(),
|
||||
ib.build(), pbb.build(), pcb.build(), cbb.build());
|
||||
return new AutoValue_ChangeSet(pb.build(), bb.build(), ib.build(),
|
||||
psb.build(), pbb.build(), pcb.build(), cbb.build());
|
||||
}
|
||||
|
||||
public static ChangeSet create(Change change) {
|
||||
@@ -58,6 +61,7 @@ public abstract class ChangeSet {
|
||||
public abstract ImmutableSet<Project.NameKey> projects();
|
||||
public abstract ImmutableSet<Branch.NameKey> branches();
|
||||
public abstract ImmutableSet<Change.Id> ids();
|
||||
public abstract ImmutableSet<PatchSet.Id> patchIds();
|
||||
public abstract ImmutableSetMultimap<Project.NameKey, Branch.NameKey>
|
||||
branchesByProject();
|
||||
public abstract ImmutableSetMultimap<Project.NameKey, Change.Id>
|
||||
@@ -69,4 +73,8 @@ public abstract class ChangeSet {
|
||||
public int hashCode() {
|
||||
return ids().hashCode();
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return ids().size();
|
||||
}
|
||||
}
|
||||
|
@@ -237,7 +237,9 @@ public class MergeOp {
|
||||
return ImmutableList.of(ok.get());
|
||||
} else if (results.isEmpty()) {
|
||||
throw new IllegalStateException(String.format(
|
||||
"SubmitRuleEvaluator.evaluate returned empty list for %s in %s",
|
||||
"SubmitRuleEvaluator.evaluate for change %s " +
|
||||
"returned empty list for %s in %s",
|
||||
cd.getId(),
|
||||
patchSet.getId(),
|
||||
cd.change().getProject().get()));
|
||||
}
|
||||
@@ -245,15 +247,17 @@ public class MergeOp {
|
||||
for (SubmitRecord record : results) {
|
||||
switch (record.status) {
|
||||
case CLOSED:
|
||||
throw new ResourceConflictException("change is closed");
|
||||
throw new ResourceConflictException(String.format(
|
||||
"change %s is closed", cd.getId()));
|
||||
|
||||
case RULE_ERROR:
|
||||
throw new ResourceConflictException(String.format(
|
||||
"rule error: %s",
|
||||
record.errorMessage));
|
||||
"rule error for change %s: %s",
|
||||
cd.getId(), record.errorMessage));
|
||||
|
||||
case NOT_READY:
|
||||
StringBuilder msg = new StringBuilder();
|
||||
msg.append(cd.getId() + ":");
|
||||
for (SubmitRecord.Label lbl : record.labels) {
|
||||
switch (lbl.status) {
|
||||
case OK:
|
||||
@@ -261,32 +265,27 @@ public class MergeOp {
|
||||
continue;
|
||||
|
||||
case REJECT:
|
||||
if (msg.length() > 0) {
|
||||
msg.append("; ");
|
||||
}
|
||||
msg.append("blocked by ").append(lbl.label);
|
||||
msg.append(" blocked by ").append(lbl.label);
|
||||
msg.append(";");
|
||||
continue;
|
||||
|
||||
case NEED:
|
||||
if (msg.length() > 0) {
|
||||
msg.append("; ");
|
||||
}
|
||||
msg.append("needs ").append(lbl.label);
|
||||
msg.append(" needs ").append(lbl.label);
|
||||
msg.append(";");
|
||||
continue;
|
||||
|
||||
case IMPOSSIBLE:
|
||||
if (msg.length() > 0) {
|
||||
msg.append("; ");
|
||||
}
|
||||
msg.append("needs ").append(lbl.label)
|
||||
msg.append(" needs ").append(lbl.label)
|
||||
.append(" (check project access)");
|
||||
msg.append(";");
|
||||
continue;
|
||||
|
||||
default:
|
||||
throw new IllegalStateException(String.format(
|
||||
"Unsupported SubmitRecord.Label %s for %s in %s",
|
||||
"Unsupported SubmitRecord.Label %s for %s in %s in %s",
|
||||
lbl.toString(),
|
||||
patchSet.getId(),
|
||||
cd.getId(),
|
||||
cd.change().getProject().get()));
|
||||
}
|
||||
}
|
||||
@@ -303,21 +302,37 @@ public class MergeOp {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
private void checkPermissions(ChangeSet cs)
|
||||
private void checkSubmitRulesAndState(ChangeSet cs)
|
||||
throws ResourceConflictException, OrmException {
|
||||
|
||||
StringBuilder msgbuf = new StringBuilder();
|
||||
List<Change.Id> problemChanges = new ArrayList<>();
|
||||
for (Change.Id id : cs.ids()) {
|
||||
try {
|
||||
ChangeData cd = changeDataFactory.create(db, id);
|
||||
if (cd.change().getStatus() != Change.Status.NEW){
|
||||
throw new OrmException("Change " + cd.change().getChangeId()
|
||||
+ " is in state " + cd.change().getStatus());
|
||||
throw new ResourceConflictException("Change " +
|
||||
cd.change().getChangeId() + " is in state " +
|
||||
cd.change().getStatus());
|
||||
} else {
|
||||
records.put(cd.change().getId(), checkSubmitRule(cd));
|
||||
}
|
||||
} catch (ResourceConflictException e) {
|
||||
msgbuf.append(e.getMessage() + "\n");
|
||||
problemChanges.add(id);
|
||||
}
|
||||
}
|
||||
String reason = msgbuf.toString();
|
||||
if (!reason.isEmpty()) {
|
||||
throw new ResourceConflictException("The change could not be " +
|
||||
"submitted because it depends on change(s) " +
|
||||
problemChanges.toString() + ", which could not be submitted " +
|
||||
"because:\n" + reason);
|
||||
}
|
||||
}
|
||||
|
||||
public void merge(ReviewDb db, ChangeSet changes, IdentifiedUser caller,
|
||||
boolean checkPermissions) throws NoSuchChangeException,
|
||||
boolean checkSubmitRules) throws NoSuchChangeException,
|
||||
OrmException, ResourceConflictException {
|
||||
logPrefix = String.format("[%s]: ", String.valueOf(changes.hashCode()));
|
||||
this.db = db;
|
||||
@@ -325,9 +340,9 @@ public class MergeOp {
|
||||
try {
|
||||
ChangeSet cs = mergeSuperSet.completeChangeSet(db, changes);
|
||||
logDebug("Calculated to merge {}", cs);
|
||||
if (checkPermissions) {
|
||||
logDebug("Checking permissions");
|
||||
checkPermissions(cs);
|
||||
if (checkSubmitRules) {
|
||||
logDebug("Checking submit rules and state");
|
||||
checkSubmitRulesAndState(cs);
|
||||
}
|
||||
try {
|
||||
integrateIntoHistory(cs, caller);
|
||||
|
Reference in New Issue
Block a user