Option to create a new change for every commit not in target

One not-so-well-known feature of gerrit is that, you can set a
%base for the RevWalk in ReceiveCommits when pushing changes to
Gerrit. This makes it possible to push a commit for review and
override Gerrits default algorithm for creating new changes on
push to refs/for/*. For instance, one could submit a commit in
a private branch and, afterward, push the same commit to a
release branch.

Specifying the tip of the destination branch as the %base would
have an effect of creating a new change for every commit reachable
from the pushed commit and not reachable from the target branch.
This behavior seems to be wanted by some Gerrit users and is
implemented as a project config option by this change (although
it contradicts the Gerrit's philosophy of reviewing one commit once).
If a %base is explicitly set on during uploading changes,
new-change-for-all-not-in-target is ignored.

To avoid incidental pushes with merges,
new-change-for-all-not-in-target rejects uploads if changes
contain merge commits. In such cases to push a merge commit, you
need to explicitly set the %base parameter as described in
Uploading Changes / Selecting Merge Base documentation.

Bug: issue 1195
Change-Id: Ifa90184352c912885e52d2060356fcc039d0ef03
This commit is contained in:
Deniz Türkoglu
2014-09-08 17:02:48 +02:00
parent 64eb1e2f21
commit 52777270d9
19 changed files with 191 additions and 27 deletions

View File

@@ -15,6 +15,7 @@ gerrit create-project - Create a new hosted project
[--use-contributor-agreements | --ca]
[--use-signed-off-by | --so]
[--use-content-merge]
[--create-new-change-for-all-not-in-target]
[--require-change-id | --id]
[[--branch <REF> | -b <REF>] ...]
[--empty-commit]
@@ -134,6 +135,15 @@ Submit Types].
from either the author or the uploader in the commit message.
Disabled by default.
--create-new-change-for-all-not-in-target::
--ncfa:
If enabled, a new change is created for every commit not in
target branch. If the pushed commit is merge commit, this flag is
ignored for that push. This option also does not accept merge
commits in commit chain to avoid accidental creation of a large
number of open changes.
Disabled by default.
--require-change-id::
--id::
Require a valid link:user-changeid.html[Change-Id] footer

View File

@@ -150,6 +150,25 @@ The project is hidden and only visible to project owners. Other users
are not able to see the project even if they have read permissions
granted on the project.
=== Use target branch when determining new changes to open
The `create-new-change-for-all-not-in-target` option provides a
convenience for selecting link:user-upload.html#base[the merge base]
by setting it automatically to the target branch's tip so you can
create new changes for all commits not in the target branch.
This option is disabled if the tip of the push is a merge commit.
This option also only works if there are no merge commits in the
commit chain, in such cases it fails warning the user that such
pushes can only be performed by manually specifying
link:user-upload.html#base[bases]
This option is useful if you want to push a change to your personal
branch first and for review to another branch for example. Or in cases
where a commit is already merged into a branch and you want to create
a new open change for that commit on another branch.
=== Require Change-Id
The `Require Change-Id in commit message` option defines whether a

View File

@@ -671,6 +671,11 @@ read access to `refs/meta/config`.
"configured_value": "INHERIT",
"inherited_value": false
},
"create_new_change_for_all_not_in_target": {
"value": false,
"configured_value": "INHERIT",
"inherited_value": false
},
"require_change_id": {
"value": false,
"configured_value": "FALSE",
@@ -725,6 +730,7 @@ link:#config-input[ConfigInput] entity.
"use_contributor_agreements": "FALSE",
"use_content_merge": "INHERIT",
"use_signed_off_by": "INHERIT",
"create_new_change_for_all_not_in_target": "INHERIT",
"require_change_id": "TRUE",
"max_object_size_limit": "10m",
"submit_type": "REBASE_IF_NECESSARY",
@@ -758,6 +764,11 @@ ConfigInfo] entity.
"configured_value": "INHERIT",
"inherited_value": false
},
"create_new_change_for_all_not_in_target": {
"value": true,
"configured_value": "INHERIT",
"inherited_value": false
},
"require_change_id": {
"value": true,
"configured_value": "TRUE",
@@ -1622,7 +1633,7 @@ The `ConfigInfo` entity contains information about the effective project
configuration.
[options="header",width="50%",cols="1,^2,4"]
|=========================================
|=======================================================
|Field Name ||Description
|`description` |optional|
The description of the project.
@@ -1640,6 +1651,9 @@ FAST_FORWARD_ONLY.
link:#inherited-boolean-info[InheritedBooleanInfo] that tells whether
each change must contain a Signed-off-by line from either the author or
the uploader in the commit message.
|`create_new_change_for_all_not_in_target` |optional|
link:#inherited-boolean-info[InheritedBooleanInfo] that tells whether
a new change is created for every commit not in target branch.
|`require_change_id` |optional|
link:#inherited-boolean-info[InheritedBooleanInfo] that tells whether a
valid link:user-changeid.html[Change-Id] footer in any commit uploaded
@@ -1680,7 +1694,7 @@ link:rest-api-changes.html#action-info[ActionInfo] entities.
The `ConfigInput` entity describes a new project configuration.
[options="header",width="50%",cols="1,^2,4"]
|=========================================
|======================================================
|Field Name ||Description
|`description` |optional|
The new description of the project. +
@@ -1702,6 +1716,11 @@ Whether each change must contain a Signed-off-by line from either the
author or the uploader in the commit message. +
Can be `TRUE`, `FALSE` or `INHERIT`. +
If not set, this setting is not updated.
|`create_new_change_for_all_not_in_target` |optional|
Whether a new change will be created for every commit not in target
branch. +
Can be `TRUE`, `FALSE` or `INHERIT`. +
If not set, this setting is not updated.
|`require_change_id` |optional|
Whether a valid link:user-changeid.html[Change-Id] footer in any commit
uploaded for review is required. This does not apply to commits pushed
@@ -1976,6 +1995,9 @@ Whether contributor agreements should be used for the project (`TRUE`,
|`use_signed_off_by` |`INHERIT` if not set|
Whether the usage of 'Signed-Off-By' footers is required for the
project (`TRUE`, `FALSE`, `INHERIT`).
|`create_new_change_for_all_not_in_target` |`INHERIT` if not set|
Whether a new change is created for every commit not in target branch
for the project (`TRUE`, `FALSE`, `INHERIT`).
|`use_content_merge` |`INHERIT` if not set|
Whether content merge should be enabled for the project (`TRUE`,
`FALSE`, `INHERIT`). +

View File

@@ -33,6 +33,7 @@ public class ProjectInput {
public InheritableBoolean useSignedOffBy;
public InheritableBoolean useContentMerge;
public InheritableBoolean requireChangeId;
public InheritableBoolean createNewChangeForAllNotInTarget;
public String maxObjectSizeLimit;
public Map<String, Map<String, ConfigValue>> pluginConfigValues;

View File

@@ -41,6 +41,7 @@ public interface AdminConstants extends Constants {
String useContentMerge();
String useContributorAgreements();
String useSignedOffBy();
String createNewChangeForAllNotInTarget();
String requireChangeID();
String headingMaxObjectSizeLimit();
String headingGroupOptions();

View File

@@ -23,6 +23,7 @@ projectRepoBrowser = Repository Browser
useContentMerge = Automatically resolve conflicts
useContributorAgreements = Require a valid contributor agreement to upload
useSignedOffBy = Require <code>Signed-off-by</code> in commit message
createNewChangeForAllNotInTarget = Create a new change for every commit not in the target branch
requireChangeID = Require <code>Change-Id</code> in commit message
headingMaxObjectSizeLimit = Maximum Git object size limit
headingGroupOptions = Group Options

View File

@@ -79,6 +79,7 @@ public class ProjectInfoScreen extends ProjectScreen {
private ListBox submitType;
private ListBox state;
private ListBox contentMerge;
private ListBox newChangeForAllNotInTarget;
private NpTextBox maxObjectSizeLimit;
private Label effectiveMaxObjectSizeLimit;
private Map<String, Map<String, HasEnabled>> pluginConfigWidgets;
@@ -157,6 +158,7 @@ public class ProjectInfoScreen extends ProjectScreen {
state.setEnabled(isOwner);
submitType.setEnabled(isOwner);
setEnabledForUseContentMerge();
newChangeForAllNotInTarget.setEnabled(isOwner);
descTxt.setEnabled(isOwner);
contributorAgreements.setEnabled(isOwner);
signedOffBy.setEnabled(isOwner);
@@ -213,6 +215,10 @@ public class ProjectInfoScreen extends ProjectScreen {
saveEnabler.listenTo(contentMerge);
grid.add(Util.C.useContentMerge(), contentMerge);
newChangeForAllNotInTarget = newInheritedBooleanBox();
saveEnabler.listenTo(newChangeForAllNotInTarget);
grid.add(Util.C.createNewChangeForAllNotInTarget(), newChangeForAllNotInTarget);
requireChangeID = newInheritedBooleanBox();
saveEnabler.listenTo(requireChangeID);
grid.addHtml(Util.C.requireChangeID(), requireChangeID);
@@ -338,6 +344,7 @@ public class ProjectInfoScreen extends ProjectScreen {
setBool(contributorAgreements, result.use_contributor_agreements());
setBool(signedOffBy, result.use_signed_off_by());
setBool(contentMerge, result.use_content_merge());
setBool(newChangeForAllNotInTarget, result.create_new_change_for_all_not_in_target());
setBool(requireChangeID, result.require_change_id());
setSubmitType(result.submit_type());
setState(result.state());
@@ -569,7 +576,7 @@ public class ProjectInfoScreen extends ProjectScreen {
saveProject.setEnabled(false);
ProjectApi.setConfig(getProjectKey(), descTxt.getText().trim(),
getBool(contributorAgreements), getBool(contentMerge),
getBool(signedOffBy), getBool(requireChangeID),
getBool(signedOffBy), getBool(newChangeForAllNotInTarget), getBool(requireChangeID),
maxObjectSizeLimit.getText().trim(),
SubmitType.valueOf(submitType.getValue(submitType.getSelectedIndex())),
ProjectState.valueOf(state.getValue(state.getSelectedIndex())),

View File

@@ -44,6 +44,9 @@ public class ConfigInfo extends JavaScriptObject {
public final native InheritedBooleanInfo use_contributor_agreements()
/*-{ return this.use_contributor_agreements; }-*/;
public final native InheritedBooleanInfo create_new_change_for_all_not_in_target()
/*-{ return this.create_new_change_for_all_not_in_target; }-*/;
public final native InheritedBooleanInfo use_signed_off_by()
/*-{ return this.use_signed_off_by; }-*/;

View File

@@ -85,6 +85,7 @@ public class ProjectApi {
public static void setConfig(Project.NameKey name, String description,
InheritableBoolean useContributorAgreements,
InheritableBoolean useContentMerge, InheritableBoolean useSignedOffBy,
InheritableBoolean createNewChangeForAllNotInTarget,
InheritableBoolean requireChangeId, String maxObjectSizeLimit,
SubmitType submitType, ProjectState state,
Map<String, Map<String, ConfigParameterValue>> pluginConfigValues,
@@ -95,6 +96,7 @@ public class ProjectApi {
in.setUseContentMerge(useContentMerge);
in.setUseSignedOffBy(useSignedOffBy);
in.setRequireChangeId(requireChangeId);
in.setCreateNewChangeForAllNotInTarget(createNewChangeForAllNotInTarget);
in.setMaxObjectSizeLimit(maxObjectSizeLimit);
in.setSubmitType(submitType);
in.setState(state);
@@ -209,6 +211,12 @@ public class ProjectApi {
private final native void setRequireChangeIdRaw(String v)
/*-{ if(v)this.require_change_id=v; }-*/;
final void setCreateNewChangeForAllNotInTarget(InheritableBoolean v) {
setCreateNewChangeForAllNotInTargetRaw(v.name());
}
private final native void setCreateNewChangeForAllNotInTargetRaw(String v)
/*-{ if(v)this.create_new_change_for_all_not_in_target=v; }-*/;
final native void setMaxObjectSizeLimit(String l)
/*-{ if(l)this.max_object_size_limit=l; }-*/;

View File

@@ -94,6 +94,8 @@ public final class Project {
protected String themeName;
protected InheritableBoolean createNewChangeForAllNotInTarget;
protected Project() {
}
@@ -105,6 +107,7 @@ public final class Project {
useSignedOffBy = InheritableBoolean.INHERIT;
requireChangeID = InheritableBoolean.INHERIT;
useContentMerge = InheritableBoolean.INHERIT;
createNewChangeForAllNotInTarget = InheritableBoolean.INHERIT;
}
public Project.NameKey getNameKey() {
@@ -159,6 +162,15 @@ public final class Project {
requireChangeID = cid;
}
public InheritableBoolean getCreateNewChangeForAllNotInTarget() {
return createNewChangeForAllNotInTarget;
}
public void setCreateNewChangeForAllNotInTarget(
InheritableBoolean useAllNotInTarget) {
this.createNewChangeForAllNotInTarget = useAllNotInTarget;
}
public void setMaxObjectSizeLimit(final String limit) {
maxObjectSizeLimit = limit;
}
@@ -212,6 +224,7 @@ public final class Project {
submitType = update.submitType;
state = update.state;
maxObjectSizeLimit = update.maxObjectSizeLimit;
createNewChangeForAllNotInTarget = update.createNewChangeForAllNotInTarget;
}
/**

View File

@@ -115,6 +115,8 @@ public class ProjectConfig extends VersionedMetaData {
private static final String RECEIVE = "receive";
private static final String KEY_REQUIRE_SIGNED_OFF_BY = "requireSignedOffBy";
private static final String KEY_REQUIRE_CHANGE_ID = "requireChangeId";
private static final String KEY_USE_ALL_NOT_IN_TARGET =
"createNewChangeForAllNotInTarget";
private static final String KEY_MAX_OBJECT_SIZE_LIMIT = "maxObjectSizeLimit";
private static final String KEY_REQUIRE_CONTRIBUTOR_AGREEMENT =
"requireContributorAgreement";
@@ -419,6 +421,7 @@ public class ProjectConfig extends VersionedMetaData {
p.setUseContributorAgreements(getEnum(rc, RECEIVE, null, KEY_REQUIRE_CONTRIBUTOR_AGREEMENT, InheritableBoolean.INHERIT));
p.setUseSignedOffBy(getEnum(rc, RECEIVE, null, KEY_REQUIRE_SIGNED_OFF_BY, InheritableBoolean.INHERIT));
p.setRequireChangeID(getEnum(rc, RECEIVE, null, KEY_REQUIRE_CHANGE_ID, InheritableBoolean.INHERIT));
p.setCreateNewChangeForAllNotInTarget(getEnum(rc, RECEIVE, null, KEY_USE_ALL_NOT_IN_TARGET, InheritableBoolean.INHERIT));
p.setMaxObjectSizeLimit(rc.getString(RECEIVE, null, KEY_MAX_OBJECT_SIZE_LIMIT));
p.setSubmitType(getEnum(rc, SUBMIT, null, KEY_ACTION, defaultSubmitAction));
@@ -818,6 +821,7 @@ public class ProjectConfig extends VersionedMetaData {
set(rc, RECEIVE, null, KEY_REQUIRE_CONTRIBUTOR_AGREEMENT, p.getUseContributorAgreements(), InheritableBoolean.INHERIT);
set(rc, RECEIVE, null, KEY_REQUIRE_SIGNED_OFF_BY, p.getUseSignedOffBy(), InheritableBoolean.INHERIT);
set(rc, RECEIVE, null, KEY_REQUIRE_CHANGE_ID, p.getRequireChangeID(), InheritableBoolean.INHERIT);
set(rc, RECEIVE, null, KEY_USE_ALL_NOT_IN_TARGET, p.getCreateNewChangeForAllNotInTarget(), InheritableBoolean.INHERIT);
set(rc, RECEIVE, null, KEY_MAX_OBJECT_SIZE_LIMIT, validMaxObjectSizeLimit(p.getMaxObjectSizeLimit()));
set(rc, SUBMIT, null, KEY_ACTION, p.getSubmitType(), defaultSubmitAction);

View File

@@ -311,6 +311,7 @@ public class ReceiveCommits {
private final ReceivePack rp;
private final NoteMap rejectCommits;
private MagicBranchInput magicBranch;
private boolean newChangeForAllNotInTarget;
private List<CreateRequest> newChanges = Collections.emptyList();
private final Map<Change.Id, ReplaceRequest> replaceByChange =
@@ -428,6 +429,7 @@ public class ReceiveCommits {
ProjectState ps = projectControl.getProjectState();
this.newChangeForAllNotInTarget = ps.isCreateNewChangeForAllNotInTarget();
rp.setAllowCreates(true);
rp.setAllowDeletes(true);
rp.setAllowNonFastForwards(true);
@@ -1293,6 +1295,21 @@ public class ReceiveCommits {
}
RevWalk walk = rp.getRevWalk();
RevCommit tip;
try {
tip = walk.parseCommit(magicBranch.cmd.getNewId());
} catch (IOException ex) {
magicBranch.cmd.setResult(REJECTED_MISSING_OBJECT);
log.error("Invalid pack upload; one or more objects weren't sent", ex);
return;
}
// If tip is a merge commit or %base was specified,
// ignore newChangeForAllNotInTarget
if (tip.getParentCount() > 1 || magicBranch.base != null) {
newChangeForAllNotInTarget = false;
}
if (magicBranch.base != null) {
magicBranch.baseCommit = Lists.newArrayListWithCapacity(
magicBranch.base.size());
@@ -1313,6 +1330,18 @@ public class ReceiveCommits {
return;
}
}
} else if (newChangeForAllNotInTarget) {
String destBranch = magicBranch.dest.get();
try {
ObjectId baseHead = repo.getRef(destBranch).getObjectId();
magicBranch.baseCommit =
Collections.singletonList(walk.parseCommit(baseHead));
} catch (IOException ex) {
log.warn(String.format("Project %s cannot read %s", project.getName(),
destBranch), ex);
reject(cmd, "internal server error");
return;
}
}
// Validate that the new commits are connected with the target
@@ -1321,7 +1350,6 @@ public class ReceiveCommits {
// commits and the target branch head.
//
try {
final RevCommit tip = walk.parseCommit(magicBranch.cmd.getNewId());
Ref targetRef = rp.getAdvertisedRefs().get(magicBranch.ctl.getRefName());
if (targetRef == null || targetRef.getObjectId() == null) {
// The destination branch does not yet exist. Assume the
@@ -1462,6 +1490,13 @@ public class ReceiveCommits {
return Collections.emptyList();
}
// Don't allow merges to be uploaded in commit chain via all-not-in-target
if (newChangeForAllNotInTarget && c.getParentCount() > 1) {
reject(magicBranch.cmd,
"Pushing merges in commit chains with 'all not in target' is not allowed,\n"
+ "to override please set the base manually");
}
Change.Key changeKey = new Change.Key("I" + c.name());
final List<String> idList = c.getFooterLines(CHANGE_ID);
if (idList.isEmpty()) {

View File

@@ -43,6 +43,7 @@ public class ConfigInfo {
public InheritedBooleanInfo useContributorAgreements;
public InheritedBooleanInfo useContentMerge;
public InheritedBooleanInfo useSignedOffBy;
public InheritedBooleanInfo createNewChangeForAllNotInTarget;
public InheritedBooleanInfo requireChangeId;
public MaxObjectSizeLimitInfo maxObjectSizeLimit;
public SubmitType submitType;
@@ -68,17 +69,23 @@ public class ConfigInfo {
InheritedBooleanInfo useSignedOffBy = new InheritedBooleanInfo();
InheritedBooleanInfo useContentMerge = new InheritedBooleanInfo();
InheritedBooleanInfo requireChangeId = new InheritedBooleanInfo();
InheritedBooleanInfo createNewChangeForAllNotInTarget =
new InheritedBooleanInfo();
useContributorAgreements.value = projectState.isUseContributorAgreements();
useSignedOffBy.value = projectState.isUseSignedOffBy();
useContentMerge.value = projectState.isUseContentMerge();
requireChangeId.value = projectState.isRequireChangeID();
createNewChangeForAllNotInTarget.value =
projectState.isCreateNewChangeForAllNotInTarget();
useContributorAgreements.configuredValue =
p.getUseContributorAgreements();
useSignedOffBy.configuredValue = p.getUseSignedOffBy();
useContentMerge.configuredValue = p.getUseContentMerge();
requireChangeId.configuredValue = p.getRequireChangeID();
createNewChangeForAllNotInTarget.configuredValue =
p.getCreateNewChangeForAllNotInTarget();
ProjectState parentState = Iterables.getFirst(projectState
.parents(), null);
@@ -88,12 +95,15 @@ public class ConfigInfo {
useSignedOffBy.inheritedValue = parentState.isUseSignedOffBy();
useContentMerge.inheritedValue = parentState.isUseContentMerge();
requireChangeId.inheritedValue = parentState.isRequireChangeID();
createNewChangeForAllNotInTarget.inheritedValue =
parentState.isCreateNewChangeForAllNotInTarget();
}
this.useContributorAgreements = useContributorAgreements;
this.useSignedOffBy = useSignedOffBy;
this.useContentMerge = useContentMerge;
this.requireChangeId = requireChangeId;
this.createNewChangeForAllNotInTarget = createNewChangeForAllNotInTarget;
MaxObjectSizeLimitInfo maxObjectSizeLimit = new MaxObjectSizeLimitInfo();
maxObjectSizeLimit.value =

View File

@@ -124,6 +124,9 @@ public class CreateProject implements RestModifyView<TopLevelResource, ProjectIn
? InheritableBoolean.FALSE : MoreObjects.firstNonNull(
input.useContentMerge,
InheritableBoolean.INHERIT);
args.newChangeForAllNotInTarget =
MoreObjects.firstNonNull(input.createNewChangeForAllNotInTarget,
InheritableBoolean.INHERIT);
args.changeIdRequired =
MoreObjects.firstNonNull(input.requireChangeId, InheritableBoolean.INHERIT);
try {

View File

@@ -33,6 +33,7 @@ public class CreateProjectArgs {
public boolean permissionsOnly;
public List<String> branch;
public InheritableBoolean contentMerge;
public InheritableBoolean newChangeForAllNotInTarget;
public InheritableBoolean changeIdRequired;
public boolean createEmptyCommit;
public String maxObjectSizeLimit;
@@ -42,6 +43,7 @@ public class CreateProjectArgs {
signedOffBy = InheritableBoolean.INHERIT;
contentMerge = InheritableBoolean.INHERIT;
changeIdRequired = InheritableBoolean.INHERIT;
newChangeForAllNotInTarget = InheritableBoolean.INHERIT;
submitType = SubmitType.MERGE_IF_NECESSARY;
}

View File

@@ -193,6 +193,7 @@ public class PerformCreateProject {
.setUseContributorAgreements(createProjectArgs.contributorAgreements);
newProject.setUseSignedOffBy(createProjectArgs.signedOffBy);
newProject.setUseContentMerge(createProjectArgs.contentMerge);
newProject.setCreateNewChangeForAllNotInTarget(createProjectArgs.newChangeForAllNotInTarget);
newProject.setRequireChangeID(createProjectArgs.changeIdRequired);
newProject.setMaxObjectSizeLimit(createProjectArgs.maxObjectSizeLimit);
if (createProjectArgs.newParent != null) {

View File

@@ -404,6 +404,15 @@ public class ProjectState {
});
}
public boolean isCreateNewChangeForAllNotInTarget() {
return getInheritableBoolean(new Function<Project, InheritableBoolean>() {
@Override
public InheritableBoolean apply(Project input) {
return input.getCreateNewChangeForAllNotInTarget();
}
});
}
public LabelTypes getLabelTypes() {
Map<String, LabelType> types = Maps.newLinkedHashMap();
for (ProjectState s : treeInOrder()) {

View File

@@ -66,6 +66,7 @@ public class PutConfig implements RestModifyView<ProjectResource, Input> {
public InheritableBoolean useContributorAgreements;
public InheritableBoolean useContentMerge;
public InheritableBoolean useSignedOffBy;
public InheritableBoolean createNewChangeForAllNotInTarget;
public InheritableBoolean requireChangeId;
public String maxObjectSizeLimit;
public SubmitType submitType;
@@ -146,6 +147,11 @@ public class PutConfig implements RestModifyView<ProjectResource, Input> {
if (input.useSignedOffBy != null) {
p.setUseSignedOffBy(input.useSignedOffBy);
}
if (input.createNewChangeForAllNotInTarget != null) {
p.setCreateNewChangeForAllNotInTarget(input.createNewChangeForAllNotInTarget);
}
if (input.requireChangeId != null) {
p.setRequireChangeID(input.requireChangeId);
}

View File

@@ -87,6 +87,9 @@ final class CreateProjectCommand extends SshCommand {
@Option(name = "--change-id", usage = "if change-id is required")
private InheritableBoolean requireChangeID = InheritableBoolean.INHERIT;
@Option(name = "--new-change-for-all-not-in-target", usage = "if a new change will be created for every commit not in target branch")
private InheritableBoolean createNewChangeForAllNotInTarget = InheritableBoolean.INHERIT;
@Option(name = "--use-contributor-agreements", aliases = {"--ca"}, usage = "if contributor agreement is required")
void setUseContributorArgreements(boolean on) {
contributorAgreements = InheritableBoolean.TRUE;
@@ -107,6 +110,11 @@ final class CreateProjectCommand extends SshCommand {
requireChangeID = InheritableBoolean.TRUE;
}
@Option(name = "--create-new-change-for-all-not-in-target", aliases = {"--ncfa"}, usage = "if a new change will be created for every commit not in target branch")
void setNewChangeForAllNotInTarget(boolean on) {
createNewChangeForAllNotInTarget = InheritableBoolean.TRUE;
}
@Option(name = "--branch", aliases = {"-b"}, metaVar = "BRANCH", usage = "initial branch name\n"
+ "(default: master)")
private List<String> branch;
@@ -166,6 +174,7 @@ final class CreateProjectCommand extends SshCommand {
input.useSignedOffBy = signedOffBy;
input.useContentMerge = contentMerge;
input.requireChangeId = requireChangeID;
input.createNewChangeForAllNotInTarget = createNewChangeForAllNotInTarget;
input.branches = branch;
input.createEmptyCommit = createEmptyCommit;
input.maxObjectSizeLimit = maxObjectSizeLimit;