Merge "Permit booleans in project.config to be inherited"

This commit is contained in:
Shawn O. Pearce
2012-10-25 12:31:35 -07:00
committed by Gerrit Code Review
13 changed files with 302 additions and 171 deletions

View File

@@ -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

View File

@@ -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())));

View File

@@ -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;
}

View File

@@ -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) {

View File

@@ -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 {

View File

@@ -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));

View File

@@ -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() {

View File

@@ -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;

View File

@@ -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;
}
}

View File

@@ -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);

View File

@@ -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>>();

View File

@@ -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)")

View File

@@ -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");
}
}