Merge "Permit booleans in project.config to be inherited"
This commit is contained in:
@@ -11,11 +11,11 @@ SYNOPSIS
|
||||
'ssh' -p <port> <host> 'gerrit set-project'
|
||||
[--description <DESC> | -d <DESC>]
|
||||
[--submit-type <TYPE> | -t <TYPE>]
|
||||
[--use|no-contributor-agreements | --ca|nca]
|
||||
[--use|no-signed-off-by | --so|nso]
|
||||
[--use|no-content-merge]
|
||||
[--require|no-change-id | --id|nid]
|
||||
[--project-state | --ps]
|
||||
[--contributor-agreements <true|false|inherit>]
|
||||
[--signed-off-by <true|false|inherit>]
|
||||
[--content-merge <true|false|inherit>]
|
||||
[--change-id <true|false|inherit>]
|
||||
[--project-state <STATE> | --ps <STATE>]
|
||||
<NAME>
|
||||
|
||||
DESCRIPTION
|
||||
@@ -63,26 +63,23 @@ Description values containing spaces should be quoted in single quotes
|
||||
For more details see
|
||||
link:project-setup.html#submit_type[Change Submit Actions].
|
||||
|
||||
--use|no-content-merge::
|
||||
--content-merge::
|
||||
If enabled, Gerrit will try to perform a 3-way merge of text
|
||||
file content when a file has been modified by both the
|
||||
destination branch and the change being submitted. This
|
||||
option only takes effect if submit type is not
|
||||
FAST_FORWARD_ONLY.
|
||||
|
||||
--use|no-contributor-agreements::
|
||||
--ca|nca::
|
||||
--contributor-agreements::
|
||||
If enabled, authors must complete a contributor agreement
|
||||
on the site before pushing any commits or changes to this
|
||||
project.
|
||||
|
||||
--use|no-signed-off-by::
|
||||
--so|nso:
|
||||
--signed-off-by::
|
||||
If enabled, each change must contain a Signed-off-by line
|
||||
from either the author or the uploader in the commit message.
|
||||
|
||||
--require|no-change-id::
|
||||
--id|nid::
|
||||
--change-id::
|
||||
Require a valid link:user-changeid.html[Change-Id] footer
|
||||
in any commit uploaded for review. This does not apply to
|
||||
commits pushed directly to a branch or tag.
|
||||
@@ -103,7 +100,7 @@ and use 'merge if necessary' as merge strategy:
|
||||
|
||||
====
|
||||
$ ssh -p 29418 review.example.com gerrit set-project example --submit-type MERGE_IF_NECESSARY\
|
||||
--require-change-id --no-content-merge --project-state HIDDEN
|
||||
--change-id true --content-merge false --project-state HIDDEN
|
||||
====
|
||||
|
||||
GERRIT
|
||||
|
||||
@@ -21,13 +21,16 @@ import com.google.gerrit.client.ui.OnEditEnabler;
|
||||
import com.google.gerrit.client.ui.SmallHeading;
|
||||
import com.google.gerrit.common.data.ProjectDetail;
|
||||
import com.google.gerrit.reviewdb.client.Project;
|
||||
import com.google.gerrit.reviewdb.client.Project.InheritedBoolean;
|
||||
import com.google.gerrit.reviewdb.client.Project.SubmitType;
|
||||
import com.google.gwt.event.dom.client.ChangeEvent;
|
||||
import com.google.gwt.event.dom.client.ChangeHandler;
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.event.dom.client.ClickHandler;
|
||||
import com.google.gwt.user.client.ui.Button;
|
||||
import com.google.gwt.user.client.ui.CheckBox;
|
||||
import com.google.gwt.user.client.ui.FlowPanel;
|
||||
import com.google.gwt.user.client.ui.InlineHTML;
|
||||
import com.google.gwt.user.client.ui.InlineLabel;
|
||||
import com.google.gwt.user.client.ui.ListBox;
|
||||
import com.google.gwt.user.client.ui.Panel;
|
||||
import com.google.gwt.user.client.ui.VerticalPanel;
|
||||
@@ -37,14 +40,14 @@ public class ProjectInfoScreen extends ProjectScreen {
|
||||
private Project project;
|
||||
|
||||
private Panel projectOptionsPanel;
|
||||
private CheckBox requireChangeID;
|
||||
private ListBox requireChangeID;
|
||||
private ListBox submitType;
|
||||
private ListBox state;
|
||||
private CheckBox useContentMerge;
|
||||
private ListBox contentMerge;
|
||||
|
||||
private Panel agreementsPanel;
|
||||
private CheckBox useContributorAgreements;
|
||||
private CheckBox useSignedOffBy;
|
||||
private ListBox contributorAgreements;
|
||||
private ListBox signedOffBy;
|
||||
|
||||
private NpTextArea descTxt;
|
||||
private Button saveProject;
|
||||
@@ -96,10 +99,10 @@ public class ProjectInfoScreen extends ProjectScreen {
|
||||
final boolean canModifyState) {
|
||||
submitType.setEnabled(canModifyMergeType);
|
||||
state.setEnabled(canModifyState);
|
||||
useContentMerge.setEnabled(canModifyMergeType);
|
||||
contentMerge.setEnabled(canModifyMergeType);
|
||||
descTxt.setEnabled(canModifyDescription);
|
||||
useContributorAgreements.setEnabled(canModifyAgreements);
|
||||
useSignedOffBy.setEnabled(canModifyAgreements);
|
||||
contributorAgreements.setEnabled(canModifyAgreements);
|
||||
signedOffBy.setEnabled(canModifyAgreements);
|
||||
requireChangeID.setEnabled(canModifyMergeType);
|
||||
}
|
||||
|
||||
@@ -142,19 +145,33 @@ public class ProjectInfoScreen extends ProjectScreen {
|
||||
saveEnabler.listenTo(state);
|
||||
projectOptionsPanel.add(state);
|
||||
|
||||
useContentMerge = new CheckBox(Util.C.useContentMerge(), true);
|
||||
saveEnabler.listenTo(useContentMerge);
|
||||
projectOptionsPanel.add(useContentMerge);
|
||||
contentMerge = newInheritedBooleanBox();
|
||||
FlowPanel fp = new FlowPanel();
|
||||
fp.add(contentMerge);
|
||||
fp.add(new InlineLabel(Util.C.useContentMerge()));
|
||||
saveEnabler.listenTo(contentMerge);
|
||||
projectOptionsPanel.add(fp);
|
||||
|
||||
requireChangeID = new CheckBox(Util.C.requireChangeID(), true);
|
||||
requireChangeID = newInheritedBooleanBox();
|
||||
fp = new FlowPanel();
|
||||
fp.add(requireChangeID);
|
||||
fp.add(new InlineHTML(Util.C.requireChangeID()));
|
||||
saveEnabler.listenTo(requireChangeID);
|
||||
projectOptionsPanel.add(requireChangeID);
|
||||
projectOptionsPanel.add(fp);
|
||||
|
||||
add(projectOptionsPanel);
|
||||
}
|
||||
|
||||
private static ListBox newInheritedBooleanBox() {
|
||||
ListBox box = new ListBox();
|
||||
for (InheritedBoolean b : InheritedBoolean.values()) {
|
||||
box.addItem(b.name(), b.name());
|
||||
}
|
||||
return box;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables the {@link #useContentMerge} checkbox if the selected submit type
|
||||
* Enables the {@link #contentMerge} checkbox if the selected submit type
|
||||
* allows the usage of content merge.
|
||||
* If the submit type (currently only 'Fast Forward Only') does not allow
|
||||
* content merge the useContentMerge checkbox gets disabled.
|
||||
@@ -162,10 +179,10 @@ public class ProjectInfoScreen extends ProjectScreen {
|
||||
private void setEnabledForUseContentMerge() {
|
||||
if (SubmitType.FAST_FORWARD_ONLY.equals(Project.SubmitType
|
||||
.valueOf(submitType.getValue(submitType.getSelectedIndex())))) {
|
||||
useContentMerge.setEnabled(false);
|
||||
useContentMerge.setValue(false);
|
||||
contentMerge.setEnabled(false);
|
||||
setBool(contentMerge, InheritedBoolean.FALSE);
|
||||
} else {
|
||||
useContentMerge.setEnabled(submitType.isEnabled());
|
||||
contentMerge.setEnabled(submitType.isEnabled());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,13 +190,21 @@ public class ProjectInfoScreen extends ProjectScreen {
|
||||
agreementsPanel = new VerticalPanel();
|
||||
agreementsPanel.add(new SmallHeading(Util.C.headingAgreements()));
|
||||
|
||||
useContributorAgreements = new CheckBox(Util.C.useContributorAgreements());
|
||||
saveEnabler.listenTo(useContributorAgreements);
|
||||
agreementsPanel.add(useContributorAgreements);
|
||||
contributorAgreements = newInheritedBooleanBox();
|
||||
if (Gerrit.getConfig().isUseContributorAgreements()) {
|
||||
FlowPanel fp = new FlowPanel();
|
||||
fp.add(contributorAgreements);
|
||||
fp.add(new InlineLabel(Util.C.useContributorAgreements()));
|
||||
saveEnabler.listenTo(contributorAgreements);
|
||||
agreementsPanel.add(fp);
|
||||
}
|
||||
|
||||
useSignedOffBy = new CheckBox(Util.C.useSignedOffBy(), true);
|
||||
saveEnabler.listenTo(useSignedOffBy);
|
||||
agreementsPanel.add(useSignedOffBy);
|
||||
signedOffBy = newInheritedBooleanBox();
|
||||
FlowPanel fp = new FlowPanel();
|
||||
fp.add(signedOffBy);
|
||||
fp.add(new InlineHTML(Util.C.useSignedOffBy()));
|
||||
saveEnabler.listenTo(signedOffBy);
|
||||
agreementsPanel.add(fp);
|
||||
|
||||
add(agreementsPanel);
|
||||
}
|
||||
@@ -209,21 +234,31 @@ public class ProjectInfoScreen extends ProjectScreen {
|
||||
}
|
||||
}
|
||||
|
||||
private static void setBool(ListBox box, InheritedBoolean val) {
|
||||
for (int i = 0; i < box.getItemCount(); i++) {
|
||||
if (val.name().equals(box.getValue(i))) {
|
||||
box.setSelectedIndex(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static InheritedBoolean getBool(ListBox box) {
|
||||
int i = box.getSelectedIndex();
|
||||
if (i >= 0) {
|
||||
return InheritedBoolean.valueOf(box.getValue(i));
|
||||
}
|
||||
return InheritedBoolean.INHERIT;
|
||||
}
|
||||
|
||||
void display(final ProjectDetail result) {
|
||||
project = result.project;
|
||||
|
||||
final boolean isall =
|
||||
Gerrit.getConfig().getWildProject().equals(project.getNameKey());
|
||||
projectOptionsPanel.setVisible(!isall);
|
||||
agreementsPanel.setVisible(!isall);
|
||||
useContributorAgreements.setVisible(Gerrit.getConfig()
|
||||
.isUseContributorAgreements());
|
||||
|
||||
descTxt.setText(project.getDescription());
|
||||
useContributorAgreements.setValue(project.isUseContributorAgreements());
|
||||
useSignedOffBy.setValue(project.isUseSignedOffBy());
|
||||
useContentMerge.setValue(project.isUseContentMerge());
|
||||
requireChangeID.setValue(project.isRequireChangeID());
|
||||
setBool(contributorAgreements, project.getUseContributorAgreements());
|
||||
setBool(signedOffBy, project.getUseSignedOffBy());
|
||||
setBool(contentMerge, project.getUseContentMerge());
|
||||
setBool(requireChangeID, project.getRequireChangeID());
|
||||
setSubmitType(project.getSubmitType());
|
||||
setState(project.getState());
|
||||
|
||||
@@ -232,10 +267,10 @@ public class ProjectInfoScreen extends ProjectScreen {
|
||||
|
||||
private void doSave() {
|
||||
project.setDescription(descTxt.getText().trim());
|
||||
project.setUseContributorAgreements(useContributorAgreements.getValue());
|
||||
project.setUseSignedOffBy(useSignedOffBy.getValue());
|
||||
project.setUseContentMerge(useContentMerge.getValue());
|
||||
project.setRequireChangeID(requireChangeID.getValue());
|
||||
project.setUseContributorAgreements(getBool(contributorAgreements));
|
||||
project.setUseSignedOffBy(getBool(signedOffBy));
|
||||
project.setUseContentMerge(getBool(contentMerge));
|
||||
project.setRequireChangeID(getBool(requireChangeID));
|
||||
if (submitType.getSelectedIndex() >= 0) {
|
||||
project.setSubmitType(Project.SubmitType.valueOf(submitType
|
||||
.getValue(submitType.getSelectedIndex())));
|
||||
|
||||
@@ -85,13 +85,19 @@ public final class Project {
|
||||
HIDDEN;
|
||||
}
|
||||
|
||||
public static enum InheritedBoolean {
|
||||
TRUE,
|
||||
FALSE,
|
||||
INHERIT;
|
||||
}
|
||||
|
||||
protected NameKey name;
|
||||
|
||||
protected String description;
|
||||
|
||||
protected boolean useContributorAgreements;
|
||||
protected InheritedBoolean useContributorAgreements;
|
||||
|
||||
protected boolean useSignedOffBy;
|
||||
protected InheritedBoolean useSignedOffBy;
|
||||
|
||||
protected SubmitType submitType;
|
||||
|
||||
@@ -99,9 +105,9 @@ public final class Project {
|
||||
|
||||
protected NameKey parent;
|
||||
|
||||
protected boolean requireChangeID;
|
||||
protected InheritedBoolean requireChangeID;
|
||||
|
||||
protected boolean useContentMerge;
|
||||
protected InheritedBoolean useContentMerge;
|
||||
|
||||
protected Project() {
|
||||
}
|
||||
@@ -110,6 +116,10 @@ public final class Project {
|
||||
name = nameKey;
|
||||
submitType = SubmitType.MERGE_IF_NECESSARY;
|
||||
state = State.ACTIVE;
|
||||
useContributorAgreements = InheritedBoolean.INHERIT;
|
||||
useSignedOffBy = InheritedBoolean.INHERIT;
|
||||
requireChangeID = InheritedBoolean.INHERIT;
|
||||
useContentMerge = InheritedBoolean.INHERIT;
|
||||
}
|
||||
|
||||
public Project.NameKey getNameKey() {
|
||||
@@ -128,35 +138,35 @@ public final class Project {
|
||||
description = d;
|
||||
}
|
||||
|
||||
public boolean isUseContributorAgreements() {
|
||||
public InheritedBoolean getUseContributorAgreements() {
|
||||
return useContributorAgreements;
|
||||
}
|
||||
|
||||
public void setUseContributorAgreements(final boolean u) {
|
||||
useContributorAgreements = u;
|
||||
}
|
||||
|
||||
public boolean isUseSignedOffBy() {
|
||||
public InheritedBoolean getUseSignedOffBy() {
|
||||
return useSignedOffBy;
|
||||
}
|
||||
|
||||
public boolean isUseContentMerge() {
|
||||
public InheritedBoolean getUseContentMerge() {
|
||||
return useContentMerge;
|
||||
}
|
||||
|
||||
public boolean isRequireChangeID() {
|
||||
public InheritedBoolean getRequireChangeID() {
|
||||
return requireChangeID;
|
||||
}
|
||||
|
||||
public void setUseSignedOffBy(final boolean sbo) {
|
||||
public void setUseContributorAgreements(final InheritedBoolean u) {
|
||||
useContributorAgreements = u;
|
||||
}
|
||||
|
||||
public void setUseSignedOffBy(final InheritedBoolean sbo) {
|
||||
useSignedOffBy = sbo;
|
||||
}
|
||||
|
||||
public void setUseContentMerge(final boolean cm) {
|
||||
public void setUseContentMerge(final InheritedBoolean cm) {
|
||||
useContentMerge = cm;
|
||||
}
|
||||
|
||||
public void setRequireChangeID(final boolean cid) {
|
||||
public void setRequireChangeID(final InheritedBoolean cid) {
|
||||
requireChangeID = cid;
|
||||
}
|
||||
|
||||
|
||||
@@ -132,7 +132,7 @@ public class MergeOp {
|
||||
|
||||
private final PersonIdent myIdent;
|
||||
private final Branch.NameKey destBranch;
|
||||
private Project destProject;
|
||||
private ProjectState destProject;
|
||||
private final ListMultimap<SubmitType, CodeReviewCommit> toMerge;
|
||||
private final List<CodeReviewCommit> potentiallyStillSubmittable;
|
||||
private final Map<Change.Id, CodeReviewCommit> commits;
|
||||
@@ -253,11 +253,10 @@ public class MergeOp {
|
||||
}
|
||||
|
||||
private void setDestProject() throws MergeException {
|
||||
final ProjectState pe = projectCache.get(destBranch.getParentKey());
|
||||
if (pe == null) {
|
||||
destProject = projectCache.get(destBranch.getParentKey());
|
||||
if (destProject == null) {
|
||||
throw new MergeException("No such project: " + destBranch.getParentKey());
|
||||
}
|
||||
destProject = pe.getProject();
|
||||
}
|
||||
|
||||
private void openSchema() throws OrmException {
|
||||
@@ -602,12 +601,13 @@ public class MergeOp {
|
||||
if (mergeTip != null && (branchTip == null || branchTip != mergeTip)) {
|
||||
if (GitRepositoryManager.REF_CONFIG.equals(branchUpdate.getName())) {
|
||||
try {
|
||||
ProjectConfig cfg = new ProjectConfig(destProject.getNameKey());
|
||||
ProjectConfig cfg =
|
||||
new ProjectConfig(destProject.getProject().getNameKey());
|
||||
cfg.load(repo, mergeTip);
|
||||
} catch (Exception e) {
|
||||
throw new MergeException("Submit would store invalid"
|
||||
+ " project configuration " + mergeTip.name() + " for "
|
||||
+ destProject.getName(), e);
|
||||
+ destProject.getProject().getName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -627,10 +627,11 @@ public class MergeOp {
|
||||
}
|
||||
|
||||
if (GitRepositoryManager.REF_CONFIG.equals(branchUpdate.getName())) {
|
||||
projectCache.evict(destProject);
|
||||
ProjectState ps = projectCache.get(destProject.getNameKey());
|
||||
repoManager.setProjectDescription(destProject.getNameKey(), //
|
||||
ps.getProject().getDescription());
|
||||
projectCache.evict(destProject.getProject());
|
||||
destProject = projectCache.get(destProject.getProject().getNameKey());
|
||||
repoManager.setProjectDescription(
|
||||
destProject.getProject().getNameKey(),
|
||||
destProject.getProject().getDescription());
|
||||
}
|
||||
|
||||
replication.fire(destBranch.getParentKey(), branchUpdate.getName());
|
||||
@@ -732,8 +733,8 @@ public class MergeOp {
|
||||
private void updateSubscriptions(final List<Change> submitted) {
|
||||
if (mergeTip != null && (branchTip == null || branchTip != mergeTip)) {
|
||||
SubmoduleOp subOp =
|
||||
subOpFactory.create(destBranch, mergeTip, rw, repo, destProject,
|
||||
submitted, commits);
|
||||
subOpFactory.create(destBranch, mergeTip, rw, repo,
|
||||
destProject.getProject(), submitted, commits);
|
||||
try {
|
||||
subOp.update();
|
||||
} catch (SubmoduleException e) {
|
||||
|
||||
@@ -282,12 +282,12 @@ public class ProjectConfig extends VersionedMetaData {
|
||||
}
|
||||
p.setParentName(rc.getString(ACCESS, null, KEY_INHERIT_FROM));
|
||||
|
||||
p.setUseContributorAgreements(getBoolean(rc, RECEIVE, KEY_REQUIRE_CONTRIBUTOR_AGREEMENT, false));
|
||||
p.setUseSignedOffBy(getBoolean(rc, RECEIVE, KEY_REQUIRE_SIGNED_OFF_BY, false));
|
||||
p.setRequireChangeID(getBoolean(rc, RECEIVE, KEY_REQUIRE_CHANGE_ID, false));
|
||||
p.setUseContributorAgreements(getEnum(rc, RECEIVE, null, KEY_REQUIRE_CONTRIBUTOR_AGREEMENT, Project.InheritedBoolean.INHERIT));
|
||||
p.setUseSignedOffBy(getEnum(rc, RECEIVE, null, KEY_REQUIRE_SIGNED_OFF_BY, Project.InheritedBoolean.INHERIT));
|
||||
p.setRequireChangeID(getEnum(rc, RECEIVE, null, KEY_REQUIRE_CHANGE_ID, Project.InheritedBoolean.INHERIT));
|
||||
|
||||
p.setSubmitType(getEnum(rc, SUBMIT, null, KEY_ACTION, defaultSubmitAction));
|
||||
p.setUseContentMerge(getBoolean(rc, SUBMIT, KEY_MERGE_CONTENT, false));
|
||||
p.setUseContentMerge(getEnum(rc, SUBMIT, null, KEY_MERGE_CONTENT, Project.InheritedBoolean.INHERIT));
|
||||
p.setState(getEnum(rc, PROJECT, null, KEY_STATE, defaultStateValue));
|
||||
|
||||
loadAccountsSection(rc, groupsByName);
|
||||
@@ -525,12 +525,12 @@ public class ProjectConfig extends VersionedMetaData {
|
||||
}
|
||||
set(rc, ACCESS, null, KEY_INHERIT_FROM, p.getParentName());
|
||||
|
||||
set(rc, RECEIVE, null, KEY_REQUIRE_CONTRIBUTOR_AGREEMENT, p.isUseContributorAgreements());
|
||||
set(rc, RECEIVE, null, KEY_REQUIRE_SIGNED_OFF_BY, p.isUseSignedOffBy());
|
||||
set(rc, RECEIVE, null, KEY_REQUIRE_CHANGE_ID, p.isRequireChangeID());
|
||||
set(rc, RECEIVE, null, KEY_REQUIRE_CONTRIBUTOR_AGREEMENT, p.getUseContributorAgreements(), Project.InheritedBoolean.INHERIT);
|
||||
set(rc, RECEIVE, null, KEY_REQUIRE_SIGNED_OFF_BY, p.getUseSignedOffBy(), Project.InheritedBoolean.INHERIT);
|
||||
set(rc, RECEIVE, null, KEY_REQUIRE_CHANGE_ID, p.getRequireChangeID(), Project.InheritedBoolean.INHERIT);
|
||||
|
||||
set(rc, SUBMIT, null, KEY_ACTION, p.getSubmitType(), defaultSubmitAction);
|
||||
set(rc, SUBMIT, null, KEY_MERGE_CONTENT, p.isUseContentMerge());
|
||||
set(rc, SUBMIT, null, KEY_MERGE_CONTENT, p.getUseContentMerge(), Project.InheritedBoolean.INHERIT);
|
||||
|
||||
set(rc, PROJECT, null, KEY_STATE, p.getState(), null);
|
||||
|
||||
@@ -734,16 +734,6 @@ public class ProjectConfig extends VersionedMetaData {
|
||||
saveUTF8(GROUP_LIST, buf.toString());
|
||||
}
|
||||
|
||||
private boolean getBoolean(Config rc, String section, String name,
|
||||
boolean defaultValue) {
|
||||
try {
|
||||
return rc.getBoolean(section, name, defaultValue);
|
||||
} catch (IllegalArgumentException err) {
|
||||
error(new ValidationError(PROJECT_CONFIG, err.getMessage()));
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
private <E extends Enum<?>> E getEnum(Config rc, String section,
|
||||
String subsection, String name, E defaultValue) {
|
||||
try {
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
|
||||
package com.google.gerrit.server.git;
|
||||
|
||||
import static org.eclipse.jgit.lib.Constants.R_HEADS;
|
||||
import static com.google.gerrit.server.git.MultiProgressMonitor.UNKNOWN;
|
||||
import static org.eclipse.jgit.lib.Constants.R_HEADS;
|
||||
import static org.eclipse.jgit.transport.ReceiveCommand.Result.NOT_ATTEMPTED;
|
||||
import static org.eclipse.jgit.transport.ReceiveCommand.Result.OK;
|
||||
import static org.eclipse.jgit.transport.ReceiveCommand.Result.REJECTED_MISSING_OBJECT;
|
||||
@@ -79,6 +79,7 @@ import com.google.inject.Inject;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
|
||||
import com.jcraft.jsch.HostKey;
|
||||
|
||||
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
|
||||
import org.eclipse.jgit.errors.MissingObjectException;
|
||||
import org.eclipse.jgit.lib.AbbreviatedObjectId;
|
||||
@@ -1868,7 +1869,7 @@ public class ReceiveCommits {
|
||||
&& ctl.canForgeCommitter()
|
||||
&& ctl.canForgeGerritServerIdentity()
|
||||
&& ctl.canUploadMerges()
|
||||
&& !project.isUseSignedOffBy()
|
||||
&& !projectControl.getProjectState().isUseSignedOffBy()
|
||||
&& Iterables.isEmpty(rejectCommits)
|
||||
&& !GitRepositoryManager.REF_CONFIG.equals(ctl.getRefName())
|
||||
&& !(MagicBranch.isMagicBranch(cmd.getRefName())
|
||||
@@ -1954,7 +1955,7 @@ public class ReceiveCommits {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (project.isUseSignedOffBy()) {
|
||||
if (projectControl.getProjectState().isUseSignedOffBy()) {
|
||||
// If the project wants Signed-off-by / Acked-by lines, verify we
|
||||
// have them for the blamable parties involved on this change.
|
||||
//
|
||||
@@ -1978,7 +1979,7 @@ public class ReceiveCommits {
|
||||
final List<String> idList = c.getFooterLines(CHANGE_ID);
|
||||
if (MagicBranch.isMagicBranch(cmd.getRefName()) || NEW_PATCHSET.matcher(cmd.getRefName()).matches()) {
|
||||
if (idList.isEmpty()) {
|
||||
if (project.isRequireChangeID()) {
|
||||
if (projectControl.getProjectState().isRequireChangeID()) {
|
||||
String errMsg = "missing Change-Id in commit message";
|
||||
reject(cmd, errMsg);
|
||||
addMessage(getFixedCommitMsgWithChangeId(errMsg, c));
|
||||
|
||||
@@ -16,6 +16,7 @@ package com.google.gerrit.server.project;
|
||||
|
||||
import com.google.gerrit.reviewdb.client.AccountGroup;
|
||||
import com.google.gerrit.reviewdb.client.Project;
|
||||
import com.google.gerrit.reviewdb.client.Project.InheritedBoolean;
|
||||
import com.google.gerrit.reviewdb.client.Project.SubmitType;
|
||||
|
||||
import java.util.List;
|
||||
@@ -27,12 +28,12 @@ public class CreateProjectArgs {
|
||||
public ProjectControl newParent;
|
||||
public String projectDescription;
|
||||
public SubmitType submitType;
|
||||
public boolean contributorAgreements;
|
||||
public boolean signedOffBy;
|
||||
public InheritedBoolean contributorAgreements;
|
||||
public InheritedBoolean signedOffBy;
|
||||
public boolean permissionsOnly;
|
||||
public List<String> branch;
|
||||
public boolean contentMerge;
|
||||
public boolean changeIdRequired;
|
||||
public InheritedBoolean contentMerge;
|
||||
public InheritedBoolean changeIdRequired;
|
||||
public boolean createEmptyCommit;
|
||||
|
||||
public CreateProjectArgs() {
|
||||
|
||||
@@ -232,8 +232,7 @@ public class ProjectControl {
|
||||
String pName = state.getProject().getName();
|
||||
return new Capable("Upload denied for project '" + pName + "'");
|
||||
}
|
||||
Project project = state.getProject();
|
||||
if (project.isUseContributorAgreements()) {
|
||||
if (state.isUseContributorAgreements()) {
|
||||
return verifyActiveContributorAgreement();
|
||||
}
|
||||
return Capable.OK;
|
||||
|
||||
@@ -14,13 +14,16 @@
|
||||
|
||||
package com.google.gerrit.server.project;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.gerrit.common.data.AccessSection;
|
||||
import com.google.gerrit.common.data.GroupReference;
|
||||
import com.google.gerrit.common.data.Permission;
|
||||
import com.google.gerrit.common.data.PermissionRule;
|
||||
import com.google.gerrit.reviewdb.client.AccountGroup;
|
||||
import com.google.gerrit.reviewdb.client.Project;
|
||||
import com.google.gerrit.reviewdb.client.Project.InheritedBoolean;
|
||||
import com.google.gerrit.rules.PrologEnvironment;
|
||||
import com.google.gerrit.rules.RulesCache;
|
||||
import com.google.gerrit.server.CurrentUser;
|
||||
@@ -295,4 +298,63 @@ public class ProjectState {
|
||||
public boolean isAllProjects() {
|
||||
return isAllProjects;
|
||||
}
|
||||
|
||||
public boolean isUseContributorAgreements() {
|
||||
return getInheritedBoolean(new Function<Project, InheritedBoolean>() {
|
||||
@Override
|
||||
public InheritedBoolean apply(Project input) {
|
||||
return input.getUseContributorAgreements();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public boolean isUseContentMerge() {
|
||||
return getInheritedBoolean(new Function<Project, InheritedBoolean>() {
|
||||
@Override
|
||||
public InheritedBoolean apply(Project input) {
|
||||
return input.getUseContentMerge();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public boolean isUseSignedOffBy() {
|
||||
return getInheritedBoolean(new Function<Project, InheritedBoolean>() {
|
||||
@Override
|
||||
public InheritedBoolean apply(Project input) {
|
||||
return input.getUseSignedOffBy();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public boolean isRequireChangeID() {
|
||||
return getInheritedBoolean(new Function<Project, InheritedBoolean>() {
|
||||
@Override
|
||||
public InheritedBoolean apply(Project input) {
|
||||
return input.getRequireChangeID();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private boolean getInheritedBoolean(Function<Project, InheritedBoolean> func) {
|
||||
Set<Project.NameKey> seen = Sets.newHashSet();
|
||||
seen.add(getProject().getNameKey());
|
||||
ProjectState s = this;
|
||||
do {
|
||||
switch (func.apply(s.getProject())) {
|
||||
case TRUE:
|
||||
return true;
|
||||
case FALSE:
|
||||
return false;
|
||||
case INHERIT:
|
||||
default:
|
||||
Project.NameKey parent = s.getProject().getParent(allProjectsName);
|
||||
if (parent != null && seen.add(parent)) {
|
||||
s = projectCache.get(parent);
|
||||
} else {
|
||||
s = null;
|
||||
}
|
||||
}
|
||||
} while (s != null);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ import com.google.gerrit.reviewdb.client.ApprovalCategory;
|
||||
import com.google.gerrit.reviewdb.client.ApprovalCategoryValue;
|
||||
import com.google.gerrit.reviewdb.client.CurrentSchemaVersion;
|
||||
import com.google.gerrit.reviewdb.client.Project;
|
||||
import com.google.gerrit.reviewdb.client.Project.InheritedBoolean;
|
||||
import com.google.gerrit.reviewdb.client.SystemConfig;
|
||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
||||
import com.google.gerrit.server.GerritPersonIdent;
|
||||
@@ -209,7 +210,10 @@ public class SchemaCreator {
|
||||
ProjectConfig config = ProjectConfig.read(md);
|
||||
Project p = config.getProject();
|
||||
p.setDescription("Rights inherited by all other projects");
|
||||
p.setUseContributorAgreements(false);
|
||||
p.setRequireChangeID(InheritedBoolean.TRUE);
|
||||
p.setUseContentMerge(InheritedBoolean.FALSE);
|
||||
p.setUseContributorAgreements(InheritedBoolean.FALSE);
|
||||
p.setUseSignedOffBy(InheritedBoolean.FALSE);
|
||||
|
||||
AccessSection cap = config.getAccessSection(AccessSection.GLOBAL_CAPABILITIES, true);
|
||||
AccessSection all = config.getAccessSection(AccessSection.ALL, true);
|
||||
|
||||
@@ -33,6 +33,7 @@ import com.google.gerrit.common.data.PermissionRule;
|
||||
import com.google.gerrit.reviewdb.client.AccountGroup;
|
||||
import com.google.gerrit.reviewdb.client.ApprovalCategory;
|
||||
import com.google.gerrit.reviewdb.client.Project;
|
||||
import com.google.gerrit.reviewdb.client.Project.InheritedBoolean;
|
||||
import com.google.gerrit.reviewdb.client.SystemConfig;
|
||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
||||
import com.google.gerrit.server.GerritPersonIdent;
|
||||
@@ -200,8 +201,7 @@ class Schema_53 extends SchemaVersion {
|
||||
private void loadProject(ResultSet rs, Project project) throws SQLException,
|
||||
OrmException {
|
||||
project.setDescription(rs.getString("description"));
|
||||
project.setUseContributorAgreements("Y".equals(rs
|
||||
.getString("use_contributor_agreements")));
|
||||
project.setUseContributorAgreements(asInheritedBoolean(rs, "use_contributor_agreements"));
|
||||
|
||||
switch (rs.getString("submit_type").charAt(0)) {
|
||||
case 'F':
|
||||
@@ -221,12 +221,19 @@ class Schema_53 extends SchemaVersion {
|
||||
+ rs.getString("submit_type") + " on project " + project.getName());
|
||||
}
|
||||
|
||||
project.setUseSignedOffBy("Y".equals(rs.getString("use_signed_off_by")));
|
||||
project.setRequireChangeID("Y".equals(rs.getString("require_change_id")));
|
||||
project.setUseContentMerge("Y".equals(rs.getString("use_content_merge")));
|
||||
project.setUseSignedOffBy(asInheritedBoolean(rs, "use_signed_off_by"));
|
||||
project.setRequireChangeID(asInheritedBoolean(rs, "require_change_id"));
|
||||
project.setUseContentMerge(asInheritedBoolean(rs, "use_content_merge"));
|
||||
project.setParentName(rs.getString("parent_name"));
|
||||
}
|
||||
|
||||
private static InheritedBoolean asInheritedBoolean(ResultSet rs, String col)
|
||||
throws SQLException {
|
||||
return "Y".equals(rs.getString(col))
|
||||
? Project.InheritedBoolean.TRUE
|
||||
: Project.InheritedBoolean.INHERIT;
|
||||
}
|
||||
|
||||
private void readOldRefRights(ReviewDb db) throws SQLException {
|
||||
rightsByProject = new HashMap<Project.NameKey, List<OldRefRight>>();
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ import com.google.gerrit.common.errors.ProjectCreationFailedException;
|
||||
import com.google.gerrit.extensions.annotations.RequiresCapability;
|
||||
import com.google.gerrit.reviewdb.client.AccountGroup;
|
||||
import com.google.gerrit.reviewdb.client.Project;
|
||||
import com.google.gerrit.reviewdb.client.Project.InheritedBoolean;
|
||||
import com.google.gerrit.reviewdb.client.Project.SubmitType;
|
||||
import com.google.gerrit.server.project.CreateProject;
|
||||
import com.google.gerrit.server.project.CreateProjectArgs;
|
||||
@@ -64,17 +65,37 @@ final class CreateProjectCommand extends SshCommand {
|
||||
+ "(default: MERGE_IF_NECESSARY)")
|
||||
private SubmitType submitType = SubmitType.MERGE_IF_NECESSARY;
|
||||
|
||||
@Option(name = "--contributor-agreements", usage = "if contributor agreement is required")
|
||||
private InheritedBoolean contributorAgreements;
|
||||
|
||||
@Option(name = "--signed-off-by", usage = "if signed-off-by is required")
|
||||
private InheritedBoolean signedOffBy = InheritedBoolean.INHERIT;
|
||||
|
||||
@Option(name = "--content-merge", usage = "allow automatic conflict resolving within files")
|
||||
private InheritedBoolean contentMerge = InheritedBoolean.INHERIT;
|
||||
|
||||
@Option(name = "--change-id", usage = "if change-id is required")
|
||||
private InheritedBoolean requireChangeID = InheritedBoolean.INHERIT;
|
||||
|
||||
@Option(name = "--use-contributor-agreements", aliases = {"--ca"}, usage = "if contributor agreement is required")
|
||||
private boolean contributorAgreements;
|
||||
void setUseContributorArgreements(boolean on) {
|
||||
contributorAgreements = InheritedBoolean.TRUE;
|
||||
}
|
||||
|
||||
@Option(name = "--use-signed-off-by", aliases = {"--so"}, usage = "if signed-off-by is required")
|
||||
private boolean signedOffBy;
|
||||
void setUseSignedOffBy(boolean on) {
|
||||
signedOffBy = InheritedBoolean.TRUE;
|
||||
}
|
||||
|
||||
@Option(name = "--use-content-merge", usage = "allow automatic conflict resolving within files")
|
||||
private boolean contentMerge;
|
||||
void setUseContentMerge(boolean on) {
|
||||
contentMerge = InheritedBoolean.TRUE;
|
||||
}
|
||||
|
||||
@Option(name = "--require-change-id", aliases = {"--id"}, usage = "if change-id is required")
|
||||
private boolean requireChangeID;
|
||||
void setRequireChangeId(boolean on) {
|
||||
requireChangeID = InheritedBoolean.TRUE;
|
||||
}
|
||||
|
||||
@Option(name = "--branch", aliases = {"-b"}, metaVar = "BRANCH", usage = "initial branch name\n"
|
||||
+ "(default: master)")
|
||||
|
||||
@@ -17,6 +17,7 @@ package com.google.gerrit.sshd.commands;
|
||||
import com.google.gerrit.common.data.GlobalCapability;
|
||||
import com.google.gerrit.extensions.annotations.RequiresCapability;
|
||||
import com.google.gerrit.reviewdb.client.Project;
|
||||
import com.google.gerrit.reviewdb.client.Project.InheritedBoolean;
|
||||
import com.google.gerrit.reviewdb.client.Project.State;
|
||||
import com.google.gerrit.reviewdb.client.Project.SubmitType;
|
||||
import com.google.gerrit.server.git.MetaDataUpdate;
|
||||
@@ -50,29 +51,57 @@ final class SetProjectCommand extends SshCommand {
|
||||
+ "(default: MERGE_IF_NECESSARY)")
|
||||
private SubmitType submitType;
|
||||
|
||||
@Option(name = "--contributor-agreements", usage = "if contributor agreement is required")
|
||||
private InheritedBoolean contributorAgreements;
|
||||
|
||||
@Option(name = "--signed-off-by", usage = "if signed-off-by is required")
|
||||
private InheritedBoolean signedOffBy;
|
||||
|
||||
@Option(name = "--content-merge", usage = "allow automatic conflict resolving within files")
|
||||
private InheritedBoolean contentMerge;
|
||||
|
||||
@Option(name = "--change-id", usage = "if change-id is required")
|
||||
private InheritedBoolean requireChangeID;
|
||||
|
||||
@Option(name = "--use-contributor-agreements", aliases = {"--ca"}, usage = "if contributor agreement is required")
|
||||
private Boolean contributorAgreements;
|
||||
void setUseContributorArgreements(boolean on) {
|
||||
contributorAgreements = InheritedBoolean.TRUE;
|
||||
}
|
||||
|
||||
@Option(name = "--no-contributor-agreements", aliases = {"--nca"}, usage = "if contributor agreement is not required")
|
||||
private Boolean noContributorAgreements;
|
||||
void setNoContributorArgreements(boolean on) {
|
||||
contributorAgreements = InheritedBoolean.FALSE;
|
||||
}
|
||||
|
||||
@Option(name = "--use-signed-off-by", aliases = {"--so"}, usage = "if signed-off-by is required")
|
||||
private Boolean signedOffBy;
|
||||
void setUseSignedOffBy(boolean on) {
|
||||
signedOffBy = InheritedBoolean.TRUE;
|
||||
}
|
||||
|
||||
@Option(name = "--no-signed-off-by", aliases = {"--nso"}, usage = "if signed-off-by is not required")
|
||||
private Boolean noSignedOffBy;
|
||||
void setNoSignedOffBy(boolean on) {
|
||||
signedOffBy = InheritedBoolean.FALSE;
|
||||
}
|
||||
|
||||
@Option(name = "--use-content-merge", usage = "allow automatic conflict resolving within files")
|
||||
private Boolean contentMerge;
|
||||
void setUseContentMerge(boolean on) {
|
||||
contentMerge = InheritedBoolean.TRUE;
|
||||
}
|
||||
|
||||
@Option(name = "--no-content-merge", usage = "don't allow automatic conflict resolving within files")
|
||||
private Boolean noContentMerge;
|
||||
void setNoContentMerge(boolean on) {
|
||||
contentMerge = InheritedBoolean.FALSE;
|
||||
}
|
||||
|
||||
@Option(name = "--require-change-id", aliases = {"--id"}, usage = "if change-id is required")
|
||||
private Boolean requireChangeID;
|
||||
void setRequireChangeId(boolean on) {
|
||||
requireChangeID = InheritedBoolean.TRUE;
|
||||
}
|
||||
|
||||
@Option(name = "--no-change-id", aliases = {"--nid"}, usage = "if change-id is not required")
|
||||
private Boolean noRequireChangeID;
|
||||
void setNoChangeId(boolean on) {
|
||||
requireChangeID = InheritedBoolean.FALSE;
|
||||
}
|
||||
|
||||
@Option(name = "--project-state", aliases = {"--ps"}, usage = "project's visibility state")
|
||||
private State state;
|
||||
@@ -85,7 +114,6 @@ final class SetProjectCommand extends SshCommand {
|
||||
|
||||
@Override
|
||||
protected void run() throws Failure {
|
||||
validate();
|
||||
Project ctlProject = projectControl.getProject();
|
||||
Project.NameKey nameKey = ctlProject.getNameKey();
|
||||
String name = ctlProject.getName();
|
||||
@@ -97,38 +125,27 @@ final class SetProjectCommand extends SshCommand {
|
||||
ProjectConfig config = ProjectConfig.read(md);
|
||||
Project project = config.getProject();
|
||||
|
||||
project.setRequireChangeID(requireChangeID != null ? requireChangeID
|
||||
: project.isRequireChangeID());
|
||||
|
||||
project.setRequireChangeID(noRequireChangeID != null
|
||||
? !noRequireChangeID : project.isRequireChangeID());
|
||||
|
||||
project.setSubmitType(submitType != null ? submitType : project
|
||||
.getSubmitType());
|
||||
|
||||
project.setUseContentMerge(contentMerge != null ? contentMerge
|
||||
: project.isUseContentMerge());
|
||||
|
||||
project.setUseContentMerge(noContentMerge != null ? !noContentMerge
|
||||
: project.isUseContentMerge());
|
||||
|
||||
project.setUseContributorAgreements(contributorAgreements != null
|
||||
? contributorAgreements : project.isUseContributorAgreements());
|
||||
|
||||
project.setUseContributorAgreements(noContributorAgreements != null
|
||||
? !noContributorAgreements : project.isUseContributorAgreements());
|
||||
|
||||
project.setUseSignedOffBy(signedOffBy != null ? signedOffBy : project
|
||||
.isUseSignedOffBy());
|
||||
|
||||
project.setUseContentMerge(noSignedOffBy != null ? !noSignedOffBy
|
||||
: project.isUseContentMerge());
|
||||
|
||||
project.setDescription(projectDescription != null ? projectDescription
|
||||
: project.getDescription());
|
||||
|
||||
project.setState(state != null ? state : project.getState());
|
||||
|
||||
if (requireChangeID != null) {
|
||||
project.setRequireChangeID(requireChangeID);
|
||||
}
|
||||
if (submitType != null) {
|
||||
project.setSubmitType(submitType);
|
||||
}
|
||||
if (contentMerge != null) {
|
||||
project.setUseContentMerge(contentMerge);
|
||||
}
|
||||
if (contributorAgreements != null) {
|
||||
project.setUseContributorAgreements(contributorAgreements);
|
||||
}
|
||||
if (signedOffBy != null) {
|
||||
project.setUseSignedOffBy(signedOffBy);
|
||||
}
|
||||
if (projectDescription != null) {
|
||||
project.setDescription(projectDescription);
|
||||
}
|
||||
if (state != null) {
|
||||
project.setState(state);
|
||||
}
|
||||
md.setMessage("Project settings updated");
|
||||
config.commit(md);
|
||||
} finally {
|
||||
@@ -154,18 +171,4 @@ final class SetProjectCommand extends SshCommand {
|
||||
throw new UnloggedFailure(1, err.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private void validate() throws UnloggedFailure {
|
||||
checkExclusivity(contentMerge, "--use-content-merge",
|
||||
noContentMerge, "--no-content-merge");
|
||||
|
||||
checkExclusivity(contributorAgreements, "--use-contributor-agreements",
|
||||
noContributorAgreements, "--no-contributor-agreements");
|
||||
|
||||
checkExclusivity(signedOffBy, "--use-signed-off-by",
|
||||
noSignedOffBy, "--no-signed-off-by");
|
||||
|
||||
checkExclusivity(requireChangeID, "--require-change-id",
|
||||
noRequireChangeID, "--no-change-id");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user