diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt index 3fde9e46b4..5d29fc71b0 100644 --- a/Documentation/config-gerrit.txt +++ b/Documentation/config-gerrit.txt @@ -3748,12 +3748,15 @@ Path must be absolute. [[repository.name.defaultSubmitType]]repository..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..ownerGroup:: + diff --git a/Documentation/project-configuration.txt b/Documentation/project-configuration.txt index 079ff49180..6260f5b6c8 100644 --- a/Documentation/project-configuration.txt +++ b/Documentation/project-configuration.txt @@ -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, diff --git a/Documentation/rest-api-projects.txt b/Documentation/rest-api-projects.txt index 9e8e9c5904..dd5e9f3f46 100644 --- a/Documentation/rest-api-projects.txt +++ b/Documentation/rest-api-projects.txt @@ -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. diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.java index b556519325..c0947a8a79 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.java @@ -133,6 +133,8 @@ public interface AdminConstants extends Constants { String headingProjectSubmitType(); + String projectSubmitType_INHERIT(); + String projectSubmitType_FAST_FORWARD_ONLY(); String projectSubmitType_MERGE_ALWAYS(); diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.properties index 62f37787d1..8d6878fecb 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.properties +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.properties @@ -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 diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoScreen.java index 4e94250272..64e147dde2 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoScreen.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoScreen.java @@ -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) { diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/Util.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/Util.java index 2e4926dcd0..bbc8a1de41 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/Util.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/Util.java @@ -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: diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ConfigInfo.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ConfigInfo.java index b8effdf8e7..f670ac73de 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ConfigInfo.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ConfigInfo.java @@ -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> 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() {} + } } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ProjectApi.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ProjectApi.java index 3766dd99d1..66afdb2301 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ProjectApi.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ProjectApi.java @@ -176,7 +176,9 @@ public class ProjectApi { in.setRejectImplicitMerges(rejectImplicitMerges); in.setPrivateByDefault(privateByDefault); in.setMaxObjectSizeLimit(maxObjectSizeLimit); - in.setSubmitType(submitType); + if (submitType != null) { + in.setSubmitType(submitType); + } in.setState(state); in.setPluginConfigValues(pluginConfigValues); in.setEnableReviewerByEmail(enableReviewerByEmail); diff --git a/java/com/google/gerrit/common/data/SubmitTypeRecord.java b/java/com/google/gerrit/common/data/SubmitTypeRecord.java index a01d83d8c9..d16da96126 100644 --- a/java/com/google/gerrit/common/data/SubmitTypeRecord.java +++ b/java/com/google/gerrit/common/data/SubmitTypeRecord.java @@ -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; diff --git a/java/com/google/gerrit/extensions/api/projects/ConfigInfo.java b/java/com/google/gerrit/extensions/api/projects/ConfigInfo.java index 1a97e6711d..80115aa2ef 100644 --- a/java/com/google/gerrit/extensions/api/projects/ConfigInfo.java +++ b/java/com/google/gerrit/extensions/api/projects/ConfigInfo.java @@ -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> pluginConfig; public Map actions; @@ -73,4 +75,10 @@ public class ConfigInfo { public List permittedValues; public List values; } + + public static class SubmitTypeInfo { + public SubmitType value; + public SubmitType configuredValue; + public SubmitType inheritedValue; + } } diff --git a/java/com/google/gerrit/extensions/client/SubmitType.java b/java/com/google/gerrit/extensions/client/SubmitType.java index b52e89aa8d..0e2f362092 100644 --- a/java/com/google/gerrit/extensions/client/SubmitType.java +++ b/java/com/google/gerrit/extensions/client/SubmitType.java @@ -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; } diff --git a/java/com/google/gerrit/reviewdb/client/Project.java b/java/com/google/gerrit/reviewdb/client/Project.java index c66b646232..921667e28b 100644 --- a/java/com/google/gerrit/reviewdb/client/Project.java +++ b/java/com/google/gerrit/reviewdb/client/Project.java @@ -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> { 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}. + * + *

Does not take inheritance into account, i.e. may return {@link SubmitType#INHERIT}. + * + * @return submit type. + */ + public SubmitType getConfiguredSubmitType() { return submitType; } diff --git a/java/com/google/gerrit/server/change/MergeabilityCacheImpl.java b/java/com/google/gerrit/server/change/MergeabilityCacheImpl.java index 119051ed4a..7ba18e858b 100644 --- a/java/com/google/gerrit/server/change/MergeabilityCacheImpl.java +++ b/java/com/google/gerrit/server/change/MergeabilityCacheImpl.java @@ -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 SUBMIT_TYPES = new ImmutableBiMap.Builder() + .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"); diff --git a/java/com/google/gerrit/server/git/ProjectConfig.java b/java/com/google/gerrit/server/git/ProjectConfig.java index e5b4a17eb2..fec1ae3d5f 100644 --- a/java/com/google/gerrit/server/git/ProjectConfig.java +++ b/java/com/google/gerrit/server/git/ProjectConfig.java @@ -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); diff --git a/java/com/google/gerrit/server/git/strategy/SubmitDryRun.java b/java/com/google/gerrit/server/git/strategy/SubmitDryRun.java index 3a954fb959..585361cf3c 100644 --- a/java/com/google/gerrit/server/git/strategy/SubmitDryRun.java +++ b/java/com/google/gerrit/server/git/strategy/SubmitDryRun.java @@ -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); diff --git a/java/com/google/gerrit/server/git/strategy/SubmitStrategyFactory.java b/java/com/google/gerrit/server/git/strategy/SubmitStrategyFactory.java index 7678623d3e..8600322f15 100644 --- a/java/com/google/gerrit/server/git/strategy/SubmitStrategyFactory.java +++ b/java/com/google/gerrit/server/git/strategy/SubmitStrategyFactory.java @@ -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); diff --git a/java/com/google/gerrit/server/git/strategy/SubmitStrategyOp.java b/java/com/google/gerrit/server/git/strategy/SubmitStrategyOp.java index 9a362d4325..bd095efea9 100644 --- a/java/com/google/gerrit/server/git/strategy/SubmitStrategyOp.java +++ b/java/com/google/gerrit/server/git/strategy/SubmitStrategyOp.java @@ -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 " diff --git a/java/com/google/gerrit/server/project/ProjectState.java b/java/com/google/gerrit/server/project/ProjectState.java index a189d9235f..00d7636b72 100644 --- a/java/com/google/gerrit/server/project/ProjectState.java +++ b/java/com/google/gerrit/server/project/ProjectState.java @@ -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 getGroups(List sectionMatcherList) { final Set all = new HashSet<>(); for (SectionMatcher matcher : sectionMatcherList) { diff --git a/java/com/google/gerrit/server/restapi/project/ConfigInfoImpl.java b/java/com/google/gerrit/server/restapi/project/ConfigInfoImpl.java index 70dc317fd5..0d52090b63 100644 --- a/java/com/google/gerrit/server/restapi/project/ConfigInfoImpl.java +++ b/java/com/google/gerrit/server/restapi/project/ConfigInfoImpl.java @@ -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() diff --git a/java/gerrit/PRED_project_default_submit_type_1.java b/java/gerrit/PRED_project_default_submit_type_1.java index 91db57ed23..d70a9e4096 100644 --- a/java/gerrit/PRED_project_default_submit_type_1.java +++ b/java/gerrit/PRED_project_default_submit_type_1.java @@ -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(); } diff --git a/javatests/com/google/gerrit/acceptance/api/project/ProjectIT.java b/javatests/com/google/gerrit/acceptance/api/project/ProjectIT.java index aba5c7d236..453a89f34c 100644 --- a/javatests/com/google/gerrit/acceptance/api/project/ProjectIT.java +++ b/javatests/com/google/gerrit/acceptance/api/project/ProjectIT.java @@ -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); } diff --git a/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java b/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java index 299f466ce3..78a00b2abc 100644 --- a/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java +++ b/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java @@ -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" diff --git a/javatests/com/google/gerrit/acceptance/rest/project/CreateProjectIT.java b/javatests/com/google/gerrit/acceptance/rest/project/CreateProjectIT.java index 9d811b2ad9..8cbe1e7e55 100644 --- a/javatests/com/google/gerrit/acceptance/rest/project/CreateProjectIT.java +++ b/javatests/com/google/gerrit/acceptance/rest/project/CreateProjectIT.java @@ -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); diff --git a/polygerrit-ui/app/elements/admin/gr-repo/gr-repo.html b/polygerrit-ui/app/elements/admin/gr-repo/gr-repo.html index ea0c0a49b5..dc91eafd2b 100644 --- a/polygerrit-ui/app/elements/admin/gr-repo/gr-repo.html +++ b/polygerrit-ui/app/elements/admin/gr-repo/gr-repo.html @@ -103,7 +103,8 @@ limitations under the License. id="submitTypeSelect" bind-value="{{_repoConfig.submit_type}}">