Merge changes Ib5711baa,I730e37bc

* changes:
  Support inheriting project submit type
  Clarify behavior of "default" submit types
This commit is contained in:
David Pursehouse
2018-01-09 14:46:48 +00:00
committed by Gerrit Code Review
27 changed files with 323 additions and 31 deletions

View File

@@ -3748,12 +3748,15 @@ Path must be absolute.
[[repository.name.defaultSubmitType]]repository.<name>.defaultSubmitType::
+
The default submit type for newly created projects. Supported values
are `MERGE_IF_NECESSARY`, `FAST_FORWARD_ONLY`, `REBASE_IF_NECESSARY`,
are `INHERIT`, `MERGE_IF_NECESSARY`, `FAST_FORWARD_ONLY`, `REBASE_IF_NECESSARY`,
`REBASE_ALWAYS`, `MERGE_ALWAYS` and `CHERRY_PICK`.
+
For more details see link:project-configuration.html#submit_type[Submit Types].
+
By default, `MERGE_IF_NECESSARY`.
This submit type is only applied at project creation time if a submit type is
omitted from the link:rest-api-projects.html#project-input[ProjectInput]. If the
submit type is unset in the project config at runtime, it defaults to
link:project-configuration.html#merge_if_necessary[`MERGE_IF_NECESSARY`].
[[repository.name.ownerGroup]]repository.<name>.ownerGroup::
+

View File

@@ -57,6 +57,12 @@ modified by any project owner through the project console, `Projects` >
its dependencies are also submitted, with exceptions documented below.
The following submit types are supported:
[[submit_type_inherit]]
* Inherit
+
Inherit the submit type from the parent project. In `All-Projects`, this
is equivalent to link:#merge_if_necessary[Merge If Necessary].
[[fast_forward_only]]
* Fast Forward Only
+
@@ -70,7 +76,8 @@ tip of the destination branch at submit time.
[[merge_if_necessary]]
* Merge If Necessary
+
This is the default for a new project.
This is the default for new projects, unless overridden by a global
link:config-gerrit.html#repository.name.defaultSubmitType[`defaultSubmitType` option].
+
If the change being submitted is a strict superset of the destination
branch, then the branch is fast-forwarded to the change. If not,

View File

@@ -494,7 +494,7 @@ link:#project-input[ProjectInput].
{
"description": "This is a demo project.",
"submit_type": "CHERRY_PICK",
"submit_type": "INHERIT",
"owners": [
"MyProject-Owners"
]
@@ -821,7 +821,12 @@ read access to `refs/meta/config`.
"configured_value": "15m",
"inherited_value": "20m"
},
"submit_type": "MERGE_IF_NECESSARY",
"submit_type": "INHERIT",
"default_submit_type": {
"value": "MERGE_IF_NECESSARY",
"configured_value": "INHERIT",
"inherited_value": "MERGE_IF_NECESSARY"
},
"state": "ACTIVE",
"commentlinks": {},
"plugin_config": {
@@ -933,6 +938,11 @@ ConfigInfo] entity.
"inherited_value": "20m"
},
"submit_type": "REBASE_IF_NECESSARY",
"default_submit_type": {
"value": "REBASE_IF_NECESSARY",
"configured_value": "INHERIT",
"inherited_value": "REBASE_IF_NECESSARY"
},
"state": "ACTIVE",
"commentlinks": {}
}
@@ -2846,10 +2856,12 @@ all new changes are set as private by default.
The link:config-gerrit.html#receive.maxObjectSizeLimit[max object size
limit] of this project as a link:#max-object-size-limit-info[
MaxObjectSizeLimitInfo] entity.
|`default_submit_type` ||
link:#submit-type-info[SubmitTypeInfo] that describes the default submit type of
the project, when not overridden at the change level.
|`submit_type` ||
The default submit type of the project, can be `MERGE_IF_NECESSARY`,
`FAST_FORWARD_ONLY`, `REBASE_IF_NECESSARY`, `REBASE_ALWAYS`, `MERGE_ALWAYS` or
`CHERRY_PICK`.
Deprecated; equivalent to link:#submit-type-info[`value`] in
`default_submit_type`.
|`match_author_to_committer_date` |optional|
link:#inherited-boolean-info[InheritedBooleanInfo] that indicates whether
a change's author date will be changed to match its submitter date upon submit.
@@ -3327,6 +3339,27 @@ statistics of a Git repository.
|`size_of_packed_objects` |Size of packed objects in bytes.
|======================================
[[submit-type-info]]
=== SubmitTypeInfo
Information about the link:project-configuration.html#submit_type[default submit
type of a project], taking into account project inheritance.
Valid values for each field are `MERGE_IF_NECESSARY`, `FAST_FORWARD_ONLY`,
`REBASE_IF_NECESSARY`, `REBASE_ALWAYS`, `MERGE_ALWAYS` or `CHERRY_PICK`, plus
`INHERIT` where applicable.
[options="header",cols="1,6"]
|===============================
|Field Name |Description
|`value` |
The effective submit type value. Never `INHERIT`.
|`configured_value` |
The configured value, can be one of the submit types, or `INHERIT` to inherit
from the parent project.
|`inherited_value` |
The effective value that would be inherited from the parent. Never `INHERIT`.
|===============================
[[tag-info]]
=== TagInfo
The `TagInfo` entity contains information about a tag.

View File

@@ -133,6 +133,8 @@ public interface AdminConstants extends Constants {
String headingProjectSubmitType();
String projectSubmitType_INHERIT();
String projectSubmitType_FAST_FORWARD_ONLY();
String projectSubmitType_MERGE_ALWAYS();

View File

@@ -57,6 +57,7 @@ headingAgreements = Contributor Agreements
headingAuditLog = Audit Log
headingProjectSubmitType = Submit Type
projectSubmitType_INHERIT = Inherit
projectSubmitType_FAST_FORWARD_ONLY = Fast Forward Only
projectSubmitType_MERGE_IF_NECESSARY = Merge if Necessary
projectSubmitType_REBASE_ALWAYS = Rebase Always

View File

@@ -30,6 +30,7 @@ import com.google.gerrit.client.projects.ConfigInfo;
import com.google.gerrit.client.projects.ConfigInfo.ConfigParameterInfo;
import com.google.gerrit.client.projects.ConfigInfo.ConfigParameterValue;
import com.google.gerrit.client.projects.ConfigInfo.InheritedBooleanInfo;
import com.google.gerrit.client.projects.ConfigInfo.SubmitTypeInfo;
import com.google.gerrit.client.projects.ProjectApi;
import com.google.gerrit.client.rpc.CallbackGroup;
import com.google.gerrit.client.rpc.GerritCallback;
@@ -335,13 +336,15 @@ public class ProjectInfoScreen extends ProjectScreen {
grid.addHtml(AdminConstants.I.useSignedOffBy(), signedOffBy);
}
private void setSubmitType(SubmitType newSubmitType) {
private void setSubmitType(SubmitTypeInfo newSubmitType) {
int index = -1;
if (submitType != null) {
if (newSubmitType != null) {
for (int i = 0; i < submitType.getItemCount(); i++) {
if (newSubmitType.name().equals(submitType.getValue(i))) {
if (submitType.getValue(i).equals(SubmitType.INHERIT.name())) {
submitType.setItemText(i, getInheritString(newSubmitType));
}
if (newSubmitType.configuredValue().name().equals(submitType.getValue(i))) {
index = i;
break;
}
}
submitType.setSelectedIndex(index);
@@ -349,6 +352,13 @@ public class ProjectInfoScreen extends ProjectScreen {
}
}
private static String getInheritString(SubmitTypeInfo submitType) {
return Util.toLongString(SubmitType.INHERIT)
+ " ("
+ Util.toLongString(submitType.inheritedValue())
+ ")";
}
private void setState(ProjectState newState) {
if (state != null) {
for (int i = 0; i < state.getItemCount(); i++) {
@@ -419,7 +429,7 @@ public class ProjectInfoScreen extends ProjectScreen {
setBool(privateByDefault, result.privateByDefault());
setBool(enableReviewerByEmail, result.enableReviewerByEmail());
setBool(matchAuthorToCommitterDate, result.matchAuthorToCommitterDate());
setSubmitType(result.submitType());
setSubmitType(result.defaultSubmitType());
setState(result.state());
maxObjectSizeLimit.setText(result.maxObjectSizeLimit().configuredValue());
if (result.maxObjectSizeLimit().inheritedValue() != null) {

View File

@@ -35,6 +35,8 @@ public class Util {
return "";
}
switch (type) {
case INHERIT:
return AdminConstants.I.projectSubmitType_INHERIT();
case FAST_FORWARD_ONLY:
return AdminConstants.I.projectSubmitType_FAST_FORWARD_ONLY();
case MERGE_IF_NECESSARY:

View File

@@ -70,6 +70,8 @@ public class ConfigInfo extends JavaScriptObject {
return SubmitType.valueOf(submitTypeRaw());
}
public final native SubmitTypeInfo defaultSubmitType() /*-{ return this.default_submit_type; }-*/;
public final native NativeMap<NativeMap<ConfigParameterInfo>> pluginConfig()
/*-{ return this.plugin_config || {}; }-*/ ;
@@ -232,4 +234,26 @@ public class ConfigInfo extends JavaScriptObject {
protected ConfigParameterValue() {}
}
public static class SubmitTypeInfo extends JavaScriptObject {
public final SubmitType value() {
return SubmitType.valueOf(valueRaw());
}
public final SubmitType configuredValue() {
return SubmitType.valueOf(configuredValueRaw());
}
public final SubmitType inheritedValue() {
return SubmitType.valueOf(inheritedValueRaw());
}
private final native String valueRaw() /*-{ return this.value; }-*/;
private final native String configuredValueRaw() /*-{ return this.configured_value; }-*/;
private final native String inheritedValueRaw() /*-{ return this.inherited_value; }-*/;
protected SubmitTypeInfo() {}
}
}

View File

@@ -176,7 +176,9 @@ public class ProjectApi {
in.setRejectImplicitMerges(rejectImplicitMerges);
in.setPrivateByDefault(privateByDefault);
in.setMaxObjectSizeLimit(maxObjectSizeLimit);
if (submitType != null) {
in.setSubmitType(submitType);
}
in.setState(state);
in.setPluginConfigValues(pluginConfigValues);
in.setEnableReviewerByEmail(enableReviewerByEmail);

View File

@@ -48,6 +48,9 @@ public class SubmitTypeRecord {
public final String errorMessage;
private SubmitTypeRecord(Status status, SubmitType type, String errorMessage) {
if (type == SubmitType.INHERIT) {
throw new IllegalArgumentException("Cannot output submit type " + type);
}
this.status = status;
this.type = type;
this.errorMessage = errorMessage;

View File

@@ -38,7 +38,9 @@ public class ConfigInfo {
public InheritedBooleanInfo rejectEmptyCommit;
public MaxObjectSizeLimitInfo maxObjectSizeLimit;
@Deprecated // Equivalent to defaultSubmitType.value
public SubmitType submitType;
public SubmitTypeInfo defaultSubmitType;
public ProjectState state;
public Map<String, Map<String, ConfigParameterInfo>> pluginConfig;
public Map<String, ActionInfo> actions;
@@ -73,4 +75,10 @@ public class ConfigInfo {
public List<String> permittedValues;
public List<String> values;
}
public static class SubmitTypeInfo {
public SubmitType value;
public SubmitType configuredValue;
public SubmitType inheritedValue;
}
}

View File

@@ -15,10 +15,11 @@
package com.google.gerrit.extensions.client;
public enum SubmitType {
INHERIT,
FAST_FORWARD_ONLY,
MERGE_IF_NECESSARY,
REBASE_IF_NECESSARY,
REBASE_ALWAYS,
MERGE_ALWAYS,
CHERRY_PICK
CHERRY_PICK;
}

View File

@@ -25,6 +25,12 @@ import java.util.Map;
/** Projects match a source code repository managed by Gerrit */
public final class Project {
/** Default submit type for new projects. */
public static final SubmitType DEFAULT_SUBMIT_TYPE = SubmitType.MERGE_IF_NECESSARY;
/** Default submit type for root project (All-Projects). */
public static final SubmitType DEFAULT_ALL_PROJECTS_SUBMIT_TYPE = SubmitType.MERGE_IF_NECESSARY;
/** Project name key */
public static class NameKey extends StringKey<com.google.gwtorm.client.Key<?>> {
private static final long serialVersionUID = 1L;
@@ -137,7 +143,14 @@ public final class Project {
maxObjectSizeLimit = limit;
}
public SubmitType getSubmitType() {
/**
* Submit type as configured in {@code project.config}.
*
* <p>Does not take inheritance into account, i.e. may return {@link SubmitType#INHERIT}.
*
* @return submit type.
*/
public SubmitType getConfiguredSubmitType() {
return submitType;
}

View File

@@ -14,6 +14,7 @@
package com.google.gerrit.server.change;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.gerrit.server.ioutil.BasicSerialization.readString;
@@ -59,6 +60,7 @@ public class MergeabilityCacheImpl implements MergeabilityCache {
public static final ImmutableBiMap<SubmitType, Character> SUBMIT_TYPES =
new ImmutableBiMap.Builder<SubmitType, Character>()
.put(SubmitType.INHERIT, 'I')
.put(SubmitType.FAST_FORWARD_ONLY, 'F')
.put(SubmitType.MERGE_IF_NECESSARY, 'M')
.put(SubmitType.REBASE_ALWAYS, 'P')
@@ -98,6 +100,11 @@ public class MergeabilityCacheImpl implements MergeabilityCache {
private String mergeStrategy;
public EntryKey(ObjectId commit, ObjectId into, SubmitType submitType, String mergeStrategy) {
checkArgument(
submitType != SubmitType.INHERIT,
"Cannot cache %s.%s",
SubmitType.class.getSimpleName(),
submitType);
this.commit = checkNotNull(commit, "commit");
this.into = checkNotNull(into, "into");
this.submitType = checkNotNull(submitType, "submitType");

View File

@@ -16,6 +16,7 @@ package com.google.gerrit.server.git;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.gerrit.common.data.Permission.isPermission;
import static com.google.gerrit.reviewdb.client.Project.DEFAULT_SUBMIT_TYPE;
import com.google.common.base.CharMatcher;
import com.google.common.base.Joiner;
@@ -42,7 +43,6 @@ import com.google.gerrit.common.data.SubscribeSection;
import com.google.gerrit.common.errors.InvalidNameException;
import com.google.gerrit.extensions.client.InheritableBoolean;
import com.google.gerrit.extensions.client.ProjectState;
import com.google.gerrit.extensions.client.SubmitType;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.BooleanProjectConfig;
import com.google.gerrit.reviewdb.client.Branch;
@@ -151,7 +151,6 @@ public class ProjectConfig extends VersionedMetaData implements ValidationError.
private static final String PLUGIN = "plugin";
private static final SubmitType DEFAULT_SUBMIT_ACTION = SubmitType.MERGE_IF_NECESSARY;
private static final ProjectState DEFAULT_STATE_VALUE = ProjectState.ACTIVE;
private static final String EXTENSION_PANELS = "extension-panels";
@@ -519,7 +518,7 @@ public class ProjectConfig extends VersionedMetaData implements ValidationError.
p.setMaxObjectSizeLimit(rc.getString(RECEIVE, null, KEY_MAX_OBJECT_SIZE_LIMIT));
p.setSubmitType(getEnum(rc, SUBMIT, null, KEY_ACTION, DEFAULT_SUBMIT_ACTION));
p.setSubmitType(getEnum(rc, SUBMIT, null, KEY_ACTION, DEFAULT_SUBMIT_TYPE));
p.setState(getEnum(rc, PROJECT, null, KEY_STATE, DEFAULT_STATE_VALUE));
p.setDefaultDashboard(rc.getString(DASHBOARD, null, KEY_DEFAULT));
@@ -1043,7 +1042,7 @@ public class ProjectConfig extends VersionedMetaData implements ValidationError.
KEY_MAX_OBJECT_SIZE_LIMIT,
validMaxObjectSizeLimit(p.getMaxObjectSizeLimit()));
set(rc, SUBMIT, null, KEY_ACTION, p.getSubmitType(), DEFAULT_SUBMIT_ACTION);
set(rc, SUBMIT, null, KEY_ACTION, p.getConfiguredSubmitType(), DEFAULT_SUBMIT_TYPE);
set(rc, PROJECT, null, KEY_STATE, p.getState(), DEFAULT_STATE_VALUE);

View File

@@ -133,6 +133,7 @@ public class SubmitDryRun {
return RebaseIfNecessary.dryRun(args, repo, tipCommit, toMergeCommit);
case REBASE_ALWAYS:
return RebaseAlways.dryRun(args, repo, tipCommit, toMergeCommit);
case INHERIT:
default:
String errorMsg = "No submit strategy for: " + submitType;
log.error(errorMsg);

View File

@@ -96,6 +96,7 @@ public class SubmitStrategyFactory {
return new RebaseIfNecessary(args);
case REBASE_ALWAYS:
return new RebaseAlways(args);
case INHERIT:
default:
String errorMsg = "No submit strategy for: " + submitType;
log.error(errorMsg);

View File

@@ -465,6 +465,7 @@ abstract class SubmitStrategyOp implements BatchUpdateOp {
case REBASE_IF_NECESSARY:
case REBASE_ALWAYS:
return message(ctx, commit, CommitMergeStatus.CLEAN_REBASE);
case INHERIT:
default:
throw new IllegalStateException(
"unexpected submit type "

View File

@@ -31,6 +31,7 @@ import com.google.gerrit.common.data.RefConfigSection;
import com.google.gerrit.common.data.SubscribeSection;
import com.google.gerrit.extensions.api.projects.CommentLinkInfo;
import com.google.gerrit.extensions.api.projects.ThemeInfo;
import com.google.gerrit.extensions.client.SubmitType;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.BooleanProjectConfig;
import com.google.gerrit.reviewdb.client.Branch;
@@ -490,6 +491,16 @@ public class ProjectState {
return getGroups(getLocalAccessSections());
}
public SubmitType getSubmitType() {
for (ProjectState s : tree()) {
SubmitType t = s.getProject().getConfiguredSubmitType();
if (t != SubmitType.INHERIT) {
return t;
}
}
return Project.DEFAULT_ALL_PROJECTS_SUBMIT_TYPE;
}
private static Set<GroupReference> getGroups(List<SectionMatcher> sectionMatcherList) {
final Set<GroupReference> all = new HashSet<>();
for (SectionMatcher matcher : sectionMatcherList) {

View File

@@ -14,6 +14,7 @@
package com.google.gerrit.server.restapi.project;
import com.google.common.base.MoreObjects;
import com.google.common.base.Strings;
import com.google.common.collect.Iterables;
import com.google.gerrit.extensions.api.projects.CommentLinkInfo;
@@ -42,6 +43,7 @@ import java.util.Map;
import java.util.TreeMap;
public class ConfigInfoImpl extends ConfigInfo {
@SuppressWarnings("deprecation")
public ConfigInfoImpl(
boolean serverEnableSignedPush,
ProjectState projectState,
@@ -79,7 +81,18 @@ public class ConfigInfoImpl extends ConfigInfo {
maxObjectSizeLimit.inheritedValue = config.getFormattedMaxObjectSizeLimit();
this.maxObjectSizeLimit = maxObjectSizeLimit;
this.submitType = p.getSubmitType();
this.defaultSubmitType = new SubmitTypeInfo();
this.defaultSubmitType.value = projectState.getSubmitType();
this.defaultSubmitType.configuredValue =
MoreObjects.firstNonNull(
projectState.getConfig().getProject().getConfiguredSubmitType(),
Project.DEFAULT_SUBMIT_TYPE);
ProjectState parent =
projectState.isAllProjects() ? projectState : projectState.parents().get(0);
this.defaultSubmitType.inheritedValue = parent.getSubmitType();
this.submitType = this.defaultSubmitType.value;
this.state =
p.getState() != com.google.gerrit.extensions.client.ProjectState.ACTIVE
? p.getState()

View File

@@ -47,7 +47,7 @@ public class PRED_project_default_submit_type_1 extends Predicate.P1 {
Term a1 = arg1.dereference();
ProjectState projectState = StoredValues.PROJECT_STATE.get(engine);
SubmitType submitType = projectState.getProject().getSubmitType();
SubmitType submitType = projectState.getSubmitType();
if (!a1.unify(term[submitType.ordinal()], engine.trail)) {
return engine.fail();
}

View File

@@ -219,13 +219,13 @@ public class ProjectIT extends AbstractDaemonTest {
RevCommit initialHead = getRemoteHead(project, RefNames.REFS_CONFIG);
ConfigInfo info = gApi.projects().name(project.get()).config();
assertThat(info.submitType).isEqualTo(SubmitType.MERGE_IF_NECESSARY);
assertThat(info.defaultSubmitType.value).isEqualTo(SubmitType.MERGE_IF_NECESSARY);
ConfigInput input = new ConfigInput();
input.submitType = SubmitType.CHERRY_PICK;
info = gApi.projects().name(project.get()).config(input);
assertThat(info.submitType).isEqualTo(SubmitType.CHERRY_PICK);
assertThat(info.defaultSubmitType.value).isEqualTo(SubmitType.CHERRY_PICK);
info = gApi.projects().name(project.get()).config();
assertThat(info.submitType).isEqualTo(SubmitType.CHERRY_PICK);
assertThat(info.defaultSubmitType.value).isEqualTo(SubmitType.CHERRY_PICK);
RevCommit updatedHead = getRemoteHead(project, RefNames.REFS_CONFIG);
eventRecorder.assertRefUpdatedEvents(
@@ -233,6 +233,7 @@ public class ProjectIT extends AbstractDaemonTest {
}
@Test
@SuppressWarnings("deprecation")
public void setConfig() throws Exception {
ConfigInput input = createTestConfigInput();
ConfigInfo info = gApi.projects().name(project.get()).config(input);
@@ -250,9 +251,13 @@ public class ProjectIT extends AbstractDaemonTest {
.isEqualTo(input.createNewChangeForAllNotInTarget);
assertThat(info.maxObjectSizeLimit.configuredValue).isEqualTo(input.maxObjectSizeLimit);
assertThat(info.submitType).isEqualTo(input.submitType);
assertThat(info.defaultSubmitType.value).isEqualTo(input.submitType);
assertThat(info.defaultSubmitType.inheritedValue).isEqualTo(SubmitType.MERGE_IF_NECESSARY);
assertThat(info.defaultSubmitType.configuredValue).isEqualTo(input.submitType);
assertThat(info.state).isEqualTo(input.state);
}
@SuppressWarnings("deprecation")
@Test
public void setPartialConfig() throws Exception {
ConfigInput input = createTestConfigInput();
@@ -276,6 +281,9 @@ public class ProjectIT extends AbstractDaemonTest {
.isEqualTo(input.createNewChangeForAllNotInTarget);
assertThat(info.maxObjectSizeLimit.configuredValue).isEqualTo(input.maxObjectSizeLimit);
assertThat(info.submitType).isEqualTo(input.submitType);
assertThat(info.defaultSubmitType.value).isEqualTo(input.submitType);
assertThat(info.defaultSubmitType.inheritedValue).isEqualTo(SubmitType.MERGE_IF_NECESSARY);
assertThat(info.defaultSubmitType.configuredValue).isEqualTo(input.submitType);
assertThat(info.state).isEqualTo(input.state);
}

View File

@@ -238,6 +238,7 @@ public abstract class AbstractSubmit extends AbstractDaemonTest {
break;
case MERGE_ALWAYS:
case MERGE_IF_NECESSARY:
case INHERIT:
assertThat(e.getMessage())
.isEqualTo(
"Failed to submit 3 changes due to the following problems:\n"

View File

@@ -24,9 +24,12 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.common.net.HttpHeaders;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.GerritConfig;
import com.google.gerrit.acceptance.RestResponse;
import com.google.gerrit.acceptance.UseLocalDisk;
import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.extensions.api.projects.ConfigInfo;
import com.google.gerrit.extensions.api.projects.ConfigInput;
import com.google.gerrit.extensions.api.projects.ProjectInput;
import com.google.gerrit.extensions.client.InheritableBoolean;
import com.google.gerrit.extensions.client.SubmitType;
@@ -181,7 +184,7 @@ public class CreateProjectIT extends AbstractDaemonTest {
Project project = projectCache.get(new Project.NameKey(newProjectName)).getProject();
assertProjectInfo(project, p);
assertThat(project.getDescription()).isEqualTo(in.description);
assertThat(project.getSubmitType()).isEqualTo(in.submitType);
assertThat(project.getConfiguredSubmitType()).isEqualTo(in.submitType);
assertThat(project.getBooleanConfig(BooleanProjectConfig.USE_CONTRIBUTOR_AGREEMENTS))
.isEqualTo(in.useContributorAgreements);
assertThat(project.getBooleanConfig(BooleanProjectConfig.USE_SIGNED_OFF_BY))
@@ -331,6 +334,84 @@ public class CreateProjectIT extends AbstractDaemonTest {
}
}
@SuppressWarnings("deprecation")
@Test
public void createProjectWithDefaultInheritedSubmitType() throws Exception {
String parent = name("parent");
ProjectInput pin = new ProjectInput();
pin.name = parent;
ConfigInfo cfg = gApi.projects().create(pin).config();
assertThat(cfg.submitType).isEqualTo(SubmitType.MERGE_IF_NECESSARY);
assertThat(cfg.defaultSubmitType.value).isEqualTo(SubmitType.MERGE_IF_NECESSARY);
assertThat(cfg.defaultSubmitType.configuredValue).isEqualTo(SubmitType.MERGE_IF_NECESSARY);
assertThat(cfg.defaultSubmitType.inheritedValue).isEqualTo(SubmitType.MERGE_IF_NECESSARY);
ConfigInput cin = new ConfigInput();
cin.submitType = SubmitType.CHERRY_PICK;
gApi.projects().name(parent).config(cin);
cfg = gApi.projects().name(parent).config();
assertThat(cfg.submitType).isEqualTo(SubmitType.CHERRY_PICK);
assertThat(cfg.defaultSubmitType.value).isEqualTo(SubmitType.CHERRY_PICK);
assertThat(cfg.defaultSubmitType.configuredValue).isEqualTo(SubmitType.CHERRY_PICK);
assertThat(cfg.defaultSubmitType.inheritedValue).isEqualTo(SubmitType.MERGE_IF_NECESSARY);
String child = name("child");
pin = new ProjectInput();
pin.submitType = SubmitType.INHERIT;
pin.parent = parent;
pin.name = child;
cfg = gApi.projects().create(pin).config();
assertThat(cfg.submitType).isEqualTo(SubmitType.CHERRY_PICK);
assertThat(cfg.defaultSubmitType.value).isEqualTo(SubmitType.CHERRY_PICK);
assertThat(cfg.defaultSubmitType.configuredValue).isEqualTo(SubmitType.INHERIT);
assertThat(cfg.defaultSubmitType.inheritedValue).isEqualTo(SubmitType.CHERRY_PICK);
cin = new ConfigInput();
cin.submitType = SubmitType.REBASE_IF_NECESSARY;
gApi.projects().name(parent).config(cin);
cfg = gApi.projects().name(parent).config();
assertThat(cfg.submitType).isEqualTo(SubmitType.REBASE_IF_NECESSARY);
assertThat(cfg.defaultSubmitType.value).isEqualTo(SubmitType.REBASE_IF_NECESSARY);
assertThat(cfg.defaultSubmitType.configuredValue).isEqualTo(SubmitType.REBASE_IF_NECESSARY);
assertThat(cfg.defaultSubmitType.inheritedValue).isEqualTo(SubmitType.MERGE_IF_NECESSARY);
cfg = gApi.projects().name(child).config();
assertThat(cfg.submitType).isEqualTo(SubmitType.REBASE_IF_NECESSARY);
assertThat(cfg.defaultSubmitType.value).isEqualTo(SubmitType.REBASE_IF_NECESSARY);
assertThat(cfg.defaultSubmitType.configuredValue).isEqualTo(SubmitType.INHERIT);
assertThat(cfg.defaultSubmitType.inheritedValue).isEqualTo(SubmitType.REBASE_IF_NECESSARY);
}
@SuppressWarnings("deprecation")
@Test
@GerritConfig(
name = "repository.testinheritedsubmittype/*.defaultSubmitType",
value = "CHERRY_PICK"
)
public void repositoryConfigTakesPrecedenceOverInheritedSubmitType() throws Exception {
// Can't use name() since we need to specify this project name in gerrit.config prior to
// startup. Pick something reasonably unique instead.
String parent = "testinheritedsubmittype";
ProjectInput pin = new ProjectInput();
pin.name = parent;
pin.submitType = SubmitType.MERGE_ALWAYS;
ConfigInfo cfg = gApi.projects().create(pin).config();
assertThat(cfg.submitType).isEqualTo(SubmitType.MERGE_ALWAYS);
assertThat(cfg.defaultSubmitType.value).isEqualTo(SubmitType.MERGE_ALWAYS);
assertThat(cfg.defaultSubmitType.configuredValue).isEqualTo(SubmitType.MERGE_ALWAYS);
assertThat(cfg.defaultSubmitType.inheritedValue).isEqualTo(SubmitType.MERGE_IF_NECESSARY);
String child = parent + "/child";
pin = new ProjectInput();
pin.parent = parent;
pin.name = child;
cfg = gApi.projects().create(pin).config();
assertThat(cfg.submitType).isEqualTo(SubmitType.CHERRY_PICK);
assertThat(cfg.defaultSubmitType.value).isEqualTo(SubmitType.CHERRY_PICK);
assertThat(cfg.defaultSubmitType.configuredValue).isEqualTo(SubmitType.CHERRY_PICK);
assertThat(cfg.defaultSubmitType.inheritedValue).isEqualTo(SubmitType.MERGE_ALWAYS);
}
private void assertHead(String projectName, String expectedRef) throws Exception {
try (Repository repo = repoManager.openRepository(new Project.NameKey(projectName))) {
assertThat(repo.exactRef(Constants.HEAD).getTarget().getName()).isEqualTo(expectedRef);

View File

@@ -103,7 +103,8 @@ limitations under the License.
id="submitTypeSelect"
bind-value="{{_repoConfig.submit_type}}">
<select disabled$="[[_readOnly]]">
<template is="dom-repeat" items="[[_submitTypes]]">
<template is="dom-repeat"
items="[[_formatSubmitTypeSelect(_repoConfig)]]">
<option value="[[item.value]]">[[item.label]]</option>
</template>
</select>

View File

@@ -21,6 +21,7 @@
};
const SUBMIT_TYPES = {
// Exclude INHERIT, which is handled specially.
mergeIfNecessary: {
value: 'MERGE_IF_NECESSARY',
label: 'Merge if necessary',
@@ -129,6 +130,15 @@
promises.push(this.$.restAPI.getProjectConfig(this.repo).then(
config => {
if (config.default_submit_type) {
// The gr-select is bound to submit_type, which needs to be the
// *configured* submit type. When default_submit_type is
// present, the server reports the *effective* submit type in
// submit_type, so we need to overwrite it before storing the
// config in this.
config.submit_type =
config.default_submit_type.configured_value;
}
if (!config.state) {
config.state = STATES.active.value;
}
@@ -183,6 +193,36 @@
];
},
_formatSubmitTypeSelect(projectConfig) {
if (!projectConfig) { return; }
const allValues = Object.values(SUBMIT_TYPES);
const type = projectConfig.default_submit_type;
if (!type) {
// Server is too old to report default_submit_type, so assume INHERIT
// is not a valid value.
return allValues;
}
let inheritLabel = 'Inherit';
if (type.inherited_value) {
let inherited = type.inherited_value;
for (const val of allValues) {
if (val.value === type.inherited_value) {
inherited = val.label;
break;
}
}
inheritLabel = `Inherit (${inherited})`;
}
return [
{
label: inheritLabel,
value: 'INHERIT',
},
...allValues,
];
},
_isLoading() {
return this._loading || this._loading === undefined;
},
@@ -195,6 +235,12 @@
const configInputObj = {};
for (const key in p) {
if (p.hasOwnProperty(key)) {
if (key === 'default_submit_type') {
// default_submit_type is not in the input type, and the
// configured value was already copied to submit_type by
// _loadProject. Omit this property when saving.
continue;
}
if (typeof p[key] === 'object') {
configInputObj[key] = p[key].configured_value;
} else {

View File

@@ -99,6 +99,11 @@ limitations under the License.
},
max_object_size_limit: {},
submit_type: 'MERGE_IF_NECESSARY',
default_submit_type: {
value: 'MERGE_IF_NECESSARY',
configured_value: 'INHERIT',
inherited_value: 'MERGE_IF_NECESSARY',
},
});
},
getConfig() {
@@ -252,7 +257,16 @@ limitations under the License.
});
});
test('fields update and save correctly', done => {
test('inherited submit type value is calculated correctly', () => {
return element._loadRepo().then(() => {
const sel = element.$.submitTypeSelect;
assert.equal(sel.bindValue, 'INHERIT');
assert.equal(
sel.nativeSelect.options[0].text, 'Inherit (Merge if necessary)');
});
});
test('fields update and save correctly', () => {
// test notedb
element._noteDbEnabled = false;
@@ -289,7 +303,7 @@ limitations under the License.
const button = Polymer.dom(element.root).querySelector('gr-button');
element._loadRepo().then(() => {
return element._loadRepo().then(() => {
assert.isTrue(button.hasAttribute('disabled'));
assert.isFalse(element.$.Title.classList.contains('edited'));
element.$.descriptionInput.bindValue = configInputObj.description;
@@ -327,12 +341,11 @@ limitations under the License.
element._formatRepoConfigForSave(element._repoConfig);
assert.deepEqual(formattedObj, configInputObj);
element._handleSaveRepoConfig().then(() => {
return element._handleSaveRepoConfig().then(() => {
assert.isTrue(button.hasAttribute('disabled'));
assert.isFalse(element.$.Title.classList.contains('edited'));
assert.isTrue(saveStub.lastCall.calledWithExactly(REPO,
configInputObj));
done();
});
});
});