Make reviewer.enableByEmail inheritable

This change makes the config inheritable, adds it to PutConfig
and adapts the test code and docs where needed.

The GWT UI is adapted such that the config can be set using the UI
control.

Change-Id: I7b4a52eebbb69c44c1095a6a4ea3e402d1eb4206
This commit is contained in:
Patrick Hiesel
2017-03-29 14:19:23 +02:00
parent 8d2b2bb95c
commit 502b26ca18
11 changed files with 52 additions and 54 deletions

View File

@@ -302,7 +302,9 @@ reviewers and CCs by email.
A boolean indicating if reviewers and CCs that do not currently have a Gerrit A boolean indicating if reviewers and CCs that do not currently have a Gerrit
account can be added to a change by providing their email address. account can be added to a change by providing their email address.
Defaults to `false`. Default is `INHERIT`, which means that this property is inherited from
the parent project. If the property is not set in any parent project, the
default value is `FALSE`.
[[file-groups]] [[file-groups]]
== The file +groups+ == The file +groups+

View File

@@ -25,13 +25,14 @@ import com.google.gerrit.acceptance.NoHttpd;
import com.google.gerrit.acceptance.PushOneCommit; import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.extensions.api.changes.AddReviewerInput; import com.google.gerrit.extensions.api.changes.AddReviewerInput;
import com.google.gerrit.extensions.api.changes.ReviewInput; import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.api.projects.ConfigInput;
import com.google.gerrit.extensions.client.InheritableBoolean;
import com.google.gerrit.extensions.client.ListChangesOption; import com.google.gerrit.extensions.client.ListChangesOption;
import com.google.gerrit.extensions.client.ReviewerState; import com.google.gerrit.extensions.client.ReviewerState;
import com.google.gerrit.extensions.common.AccountInfo; import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.extensions.common.ChangeInfo; import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.restapi.BadRequestException; import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.UnprocessableEntityException; import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
import com.google.gerrit.server.git.ProjectConfig;
import com.google.gerrit.server.mail.Address; import com.google.gerrit.server.mail.Address;
import com.google.gerrit.testutil.FakeEmailSender.Message; import com.google.gerrit.testutil.FakeEmailSender.Message;
import java.util.EnumSet; import java.util.EnumSet;
@@ -44,9 +45,9 @@ public class ChangeReviewersByEmailIT extends AbstractDaemonTest {
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
ProjectConfig cfg = projectCache.checkedGet(project).getConfig(); ConfigInput conf = new ConfigInput();
cfg.setEnableReviewerByEmail(true); conf.enableReviewerByEmail = InheritableBoolean.TRUE;
saveProjectConfig(project, cfg); gApi.projects().name(project.get()).config(conf);
} }
@Test @Test
@@ -228,9 +229,9 @@ public class ChangeReviewersByEmailIT extends AbstractDaemonTest {
public void rejectWhenFeatureIsDisabled() throws Exception { public void rejectWhenFeatureIsDisabled() throws Exception {
assume().that(notesMigration.readChanges()).isTrue(); assume().that(notesMigration.readChanges()).isTrue();
ProjectConfig cfg = projectCache.checkedGet(project).getConfig(); ConfigInput conf = new ConfigInput();
cfg.setEnableReviewerByEmail(false); conf.enableReviewerByEmail = InheritableBoolean.FALSE;
saveProjectConfig(project, cfg); gApi.projects().name(project.get()).config(conf);
PushOneCommit.Result r = createChange(); PushOneCommit.Result r = createChange();

View File

@@ -29,6 +29,7 @@ public class ConfigInput {
public InheritableBoolean enableSignedPush; public InheritableBoolean enableSignedPush;
public InheritableBoolean requireSignedPush; public InheritableBoolean requireSignedPush;
public InheritableBoolean rejectImplicitMerges; public InheritableBoolean rejectImplicitMerges;
public InheritableBoolean enableReviewerByEmail;
public String maxObjectSizeLimit; public String maxObjectSizeLimit;
public SubmitType submitType; public SubmitType submitType;
public ProjectState state; public ProjectState state;

View File

@@ -672,6 +672,7 @@ public class ProjectInfoScreen extends ProjectScreen {
esp, esp,
rsp, rsp,
getBool(rejectImplicitMerges), getBool(rejectImplicitMerges),
getBool(enableReviewerByEmail),
maxObjectSizeLimit.getText().trim(), maxObjectSizeLimit.getText().trim(),
SubmitType.valueOf(submitType.getValue(submitType.getSelectedIndex())), SubmitType.valueOf(submitType.getValue(submitType.getSelectedIndex())),
ProjectState.valueOf(state.getValue(state.getSelectedIndex())), ProjectState.valueOf(state.getValue(state.getSelectedIndex())),

View File

@@ -147,6 +147,7 @@ public class ProjectApi {
InheritableBoolean enableSignedPush, InheritableBoolean enableSignedPush,
InheritableBoolean requireSignedPush, InheritableBoolean requireSignedPush,
InheritableBoolean rejectImplicitMerges, InheritableBoolean rejectImplicitMerges,
InheritableBoolean enableReviewerByEmail,
String maxObjectSizeLimit, String maxObjectSizeLimit,
SubmitType submitType, SubmitType submitType,
ProjectState state, ProjectState state,
@@ -170,6 +171,7 @@ public class ProjectApi {
in.setSubmitType(submitType); in.setSubmitType(submitType);
in.setState(state); in.setState(state);
in.setPluginConfigValues(pluginConfigValues); in.setPluginConfigValues(pluginConfigValues);
in.setEnableReviewerByEmail(enableReviewerByEmail);
project(name).view("config").put(in, cb); project(name).view("config").put(in, cb);
} }
@@ -294,6 +296,13 @@ public class ProjectApi {
setRequireSignedPushRaw(v.name()); setRequireSignedPushRaw(v.name());
} }
final void setEnableReviewerByEmail(InheritableBoolean v) {
setEnableReviewerByEmailRaw(v.name());
}
private native void setEnableReviewerByEmailRaw(String v)
/*-{ if(v)this.enable_reviewer_by_email=v; }-*/ ;
private native void setRequireSignedPushRaw(String v) private native void setRequireSignedPushRaw(String v)
/*-{ if(v)this.require_signed_push=v; }-*/ ; /*-{ if(v)this.require_signed_push=v; }-*/ ;

View File

@@ -161,6 +161,10 @@ public final class Project {
return enableReviewerByEmail; return enableReviewerByEmail;
} }
public void setEnableReviewerByEmail(final InheritableBoolean enable) {
enableReviewerByEmail = enable;
}
public void setUseContributorAgreements(final InheritableBoolean u) { public void setUseContributorAgreements(final InheritableBoolean u) {
useContributorAgreements = u; useContributorAgreements = u;
} }

View File

@@ -55,7 +55,6 @@ import com.google.gerrit.server.account.AccountsCollection;
import com.google.gerrit.server.account.GroupMembers; import com.google.gerrit.server.account.GroupMembers;
import com.google.gerrit.server.config.GerritServerConfig; import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.extensions.events.ReviewerAdded; import com.google.gerrit.server.extensions.events.ReviewerAdded;
import com.google.gerrit.server.git.ProjectConfig;
import com.google.gerrit.server.group.GroupsCollection; import com.google.gerrit.server.group.GroupsCollection;
import com.google.gerrit.server.group.SystemGroupBackend; import com.google.gerrit.server.group.SystemGroupBackend;
import com.google.gerrit.server.mail.Address; import com.google.gerrit.server.mail.Address;
@@ -189,19 +188,20 @@ public class PostReviewers implements RestModifyView<ChangeResource, AddReviewer
try { try {
accountId = accounts.parse(input.reviewer).getAccountId(); accountId = accounts.parse(input.reviewer).getAccountId();
} catch (UnprocessableEntityException e) { } catch (UnprocessableEntityException e) {
ProjectConfig projectConfig = projectCache.checkedGet(rsrc.getProject()).getConfig(); boolean enableReviewerByEmail =
projectCache.checkedGet(rsrc.getProject()).isEnableReviewerByEmail();
if (allowGroup) { if (allowGroup) {
try { try {
return putGroup(rsrc, input); return putGroup(rsrc, input);
} catch (UnprocessableEntityException e2) { } catch (UnprocessableEntityException e2) {
if (!projectConfig.getEnableReviewerByEmail()) { if (!enableReviewerByEmail) {
throw new UnprocessableEntityException( throw new UnprocessableEntityException(
MessageFormat.format( MessageFormat.format(
ChangeMessages.get().reviewerNotFoundUserOrGroup, input.reviewer)); ChangeMessages.get().reviewerNotFoundUserOrGroup, input.reviewer));
} }
} }
} }
if (!projectConfig.getEnableReviewerByEmail()) { if (!enableReviewerByEmail) {
throw new UnprocessableEntityException( throw new UnprocessableEntityException(
MessageFormat.format(ChangeMessages.get().reviewerNotFoundUser, input.reviewer)); MessageFormat.format(ChangeMessages.get().reviewerNotFoundUser, input.reviewer));
} }

View File

@@ -188,7 +188,6 @@ public class ProjectConfig extends VersionedMetaData implements ValidationError.
private boolean checkReceivedObjects; private boolean checkReceivedObjects;
private Set<String> sectionsWithUnknownPermissions; private Set<String> sectionsWithUnknownPermissions;
private boolean hasLegacyPermissions; private boolean hasLegacyPermissions;
private boolean enableReviewerByEmail;
private Map<String, List<String>> extensionPanelSections; private Map<String, List<String>> extensionPanelSections;
public static ProjectConfig read(MetaDataUpdate update) public static ProjectConfig read(MetaDataUpdate update)
@@ -447,16 +446,6 @@ public class ProjectConfig extends VersionedMetaData implements ValidationError.
return checkReceivedObjects; return checkReceivedObjects;
} }
/** @return the enableReviewerByEmail for this project, default is false. */
public boolean getEnableReviewerByEmail() {
return enableReviewerByEmail;
}
/** Set enableReviewerByEmail for this project, default is false. */
public void setEnableReviewerByEmail(boolean val) {
enableReviewerByEmail = val;
}
/** /**
* Check all GroupReferences use current group name, repairing stale ones. * Check all GroupReferences use current group name, repairing stale ones.
* *
@@ -529,6 +518,8 @@ public class ProjectConfig extends VersionedMetaData implements ValidationError.
p.setMaxObjectSizeLimit(rc.getString(RECEIVE, null, KEY_MAX_OBJECT_SIZE_LIMIT)); p.setMaxObjectSizeLimit(rc.getString(RECEIVE, null, KEY_MAX_OBJECT_SIZE_LIMIT));
p.setRejectImplicitMerges( p.setRejectImplicitMerges(
getEnum(rc, RECEIVE, null, KEY_REJECT_IMPLICIT_MERGES, InheritableBoolean.INHERIT)); getEnum(rc, RECEIVE, null, KEY_REJECT_IMPLICIT_MERGES, InheritableBoolean.INHERIT));
p.setEnableReviewerByEmail(
getEnum(rc, REVIEWER, null, KEY_ENABLE_REVIEWER_BY_EMAIL, InheritableBoolean.INHERIT));
p.setSubmitType(getEnum(rc, SUBMIT, null, KEY_ACTION, DEFAULT_SUBMIT_ACTION)); p.setSubmitType(getEnum(rc, SUBMIT, null, KEY_ACTION, DEFAULT_SUBMIT_ACTION));
p.setUseContentMerge(getEnum(rc, SUBMIT, null, KEY_MERGE_CONTENT, InheritableBoolean.INHERIT)); p.setUseContentMerge(getEnum(rc, SUBMIT, null, KEY_MERGE_CONTENT, InheritableBoolean.INHERIT));
@@ -548,7 +539,6 @@ public class ProjectConfig extends VersionedMetaData implements ValidationError.
mimeTypes = new ConfiguredMimeTypes(projectName.get(), rc); mimeTypes = new ConfiguredMimeTypes(projectName.get(), rc);
loadPluginSections(rc); loadPluginSections(rc);
loadReceiveSection(rc); loadReceiveSection(rc);
loadReviewerSection(rc);
loadExtensionPanelSections(rc); loadExtensionPanelSections(rc);
} }
@@ -976,10 +966,6 @@ public class ProjectConfig extends VersionedMetaData implements ValidationError.
maxObjectSizeLimit = rc.getLong(RECEIVE, null, KEY_MAX_OBJECT_SIZE_LIMIT, 0); maxObjectSizeLimit = rc.getLong(RECEIVE, null, KEY_MAX_OBJECT_SIZE_LIMIT, 0);
} }
private void loadReviewerSection(Config rc) {
enableReviewerByEmail = rc.getBoolean(REVIEWER, null, KEY_ENABLE_REVIEWER_BY_EMAIL, false);
}
private void loadPluginSections(Config rc) { private void loadPluginSections(Config rc) {
pluginConfigs = new HashMap<>(); pluginConfigs = new HashMap<>();
for (String plugin : rc.getSubsections(PLUGIN)) { for (String plugin : rc.getSubsections(PLUGIN)) {
@@ -1099,6 +1085,13 @@ public class ProjectConfig extends VersionedMetaData implements ValidationError.
KEY_REJECT_IMPLICIT_MERGES, KEY_REJECT_IMPLICIT_MERGES,
p.getRejectImplicitMerges(), p.getRejectImplicitMerges(),
InheritableBoolean.INHERIT); InheritableBoolean.INHERIT);
set(
rc,
REVIEWER,
null,
KEY_ENABLE_REVIEWER_BY_EMAIL,
p.getEnableReviewerByEmail(),
InheritableBoolean.INHERIT);
set(rc, SUBMIT, null, KEY_ACTION, p.getSubmitType(), DEFAULT_SUBMIT_ACTION); set(rc, SUBMIT, null, KEY_ACTION, p.getSubmitType(), DEFAULT_SUBMIT_ACTION);
set(rc, SUBMIT, null, KEY_MERGE_CONTENT, p.getUseContentMerge(), InheritableBoolean.INHERIT); set(rc, SUBMIT, null, KEY_MERGE_CONTENT, p.getUseContentMerge(), InheritableBoolean.INHERIT);
@@ -1114,7 +1107,6 @@ public class ProjectConfig extends VersionedMetaData implements ValidationError.
saveAccessSections(rc, keepGroups); saveAccessSections(rc, keepGroups);
saveNotifySections(rc, keepGroups); saveNotifySections(rc, keepGroups);
savePluginSections(rc, keepGroups); savePluginSections(rc, keepGroups);
saveReviewerSection(rc);
groupList.retainUUIDs(keepGroups); groupList.retainUUIDs(keepGroups);
saveLabelSections(rc); saveLabelSections(rc);
saveSubscribeSections(rc); saveSubscribeSections(rc);
@@ -1430,11 +1422,6 @@ public class ProjectConfig extends VersionedMetaData implements ValidationError.
} }
} }
private void saveReviewerSection(Config rc) {
setBooleanConfigKey(
rc, REVIEWER, null, KEY_ENABLE_REVIEWER_BY_EMAIL, enableReviewerByEmail, false);
}
private void saveGroupList() throws IOException { private void saveGroupList() throws IOException {
saveUTF8(GroupList.FILE_NAME, groupList.asText()); saveUTF8(GroupList.FILE_NAME, groupList.asText());
} }

View File

@@ -154,6 +154,10 @@ public class PutConfig implements RestModifyView<ProjectResource, ConfigInput> {
p.setState(input.state); p.setState(input.state);
} }
if (input.enableReviewerByEmail != null) {
p.setEnableReviewerByEmail(input.enableReviewerByEmail);
}
if (input.pluginConfigValues != null) { if (input.pluginConfigValues != null) {
setPluginConfigValues(ctrl.getProjectState(), projectConfig, input.pluginConfigValues); setPluginConfigValues(ctrl.getProjectState(), projectConfig, input.pluginConfigValues);
} }

View File

@@ -105,9 +105,7 @@ public class ProjectConfigTest extends LocalDiskRepositoryTestCase {
+ " accepted = group Developers\n" // + " accepted = group Developers\n" //
+ " accepted = group Staff\n" // + " accepted = group Staff\n" //
+ " autoVerify = group Developers\n" // + " autoVerify = group Developers\n" //
+ " agreementUrl = http://www.example.com/agree\n" // + " agreementUrl = http://www.example.com/agree\n")) //
+ "[reviewer]\n" //
+ " enableByEmail = true\n")) //
)); ));
ProjectConfig cfg = read(rev); ProjectConfig cfg = read(rev);
@@ -134,8 +132,6 @@ public class ProjectConfigTest extends LocalDiskRepositoryTestCase {
assertThat(submit.getExclusiveGroup()).isTrue(); assertThat(submit.getExclusiveGroup()).isTrue();
assertThat(read.getExclusiveGroup()).isTrue(); assertThat(read.getExclusiveGroup()).isTrue();
assertThat(push.getExclusiveGroup()).isFalse(); assertThat(push.getExclusiveGroup()).isFalse();
assertThat(cfg.getEnableReviewerByEmail()).isTrue();
} }
@Test @Test

View File

@@ -44,6 +44,8 @@ import com.google.gerrit.extensions.api.changes.ReviewInput.DraftHandling;
import com.google.gerrit.extensions.api.changes.ReviewInput.RobotCommentInput; import com.google.gerrit.extensions.api.changes.ReviewInput.RobotCommentInput;
import com.google.gerrit.extensions.api.changes.StarsInput; import com.google.gerrit.extensions.api.changes.StarsInput;
import com.google.gerrit.extensions.api.groups.GroupInput; import com.google.gerrit.extensions.api.groups.GroupInput;
import com.google.gerrit.extensions.api.projects.ConfigInput;
import com.google.gerrit.extensions.client.InheritableBoolean;
import com.google.gerrit.extensions.client.ReviewerState; import com.google.gerrit.extensions.client.ReviewerState;
import com.google.gerrit.extensions.common.ChangeInfo; import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.common.ChangeMessageInfo; import com.google.gerrit.extensions.common.ChangeMessageInfo;
@@ -72,7 +74,6 @@ import com.google.gerrit.server.change.ChangeTriplet;
import com.google.gerrit.server.change.PatchSetInserter; import com.google.gerrit.server.change.PatchSetInserter;
import com.google.gerrit.server.config.AllUsersName; import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.git.MetaDataUpdate; import com.google.gerrit.server.git.MetaDataUpdate;
import com.google.gerrit.server.git.ProjectConfig;
import com.google.gerrit.server.git.validators.CommitValidators; import com.google.gerrit.server.git.validators.CommitValidators;
import com.google.gerrit.server.index.IndexConfig; import com.google.gerrit.server.index.IndexConfig;
import com.google.gerrit.server.index.QueryOptions; import com.google.gerrit.server.index.QueryOptions;
@@ -1566,9 +1567,9 @@ public abstract class AbstractQueryChangesTest extends GerritServerTests {
Project.NameKey project = new Project.NameKey("repo"); Project.NameKey project = new Project.NameKey("repo");
TestRepository<Repo> repo = createProject(project.get()); TestRepository<Repo> repo = createProject(project.get());
ProjectConfig cfg = projectCache.checkedGet(project).getConfig(); ConfigInput conf = new ConfigInput();
cfg.setEnableReviewerByEmail(true); conf.enableReviewerByEmail = InheritableBoolean.TRUE;
saveProjectConfig(project, cfg); gApi.projects().name(project.get()).config(conf);
String userByEmail = "un.registered@reviewer.com"; String userByEmail = "un.registered@reviewer.com";
String userByEmailWithName = "John Doe <" + userByEmail + ">"; String userByEmailWithName = "John Doe <" + userByEmail + ">";
@@ -1601,9 +1602,9 @@ public abstract class AbstractQueryChangesTest extends GerritServerTests {
Project.NameKey project = new Project.NameKey("repo"); Project.NameKey project = new Project.NameKey("repo");
TestRepository<Repo> repo = createProject(project.get()); TestRepository<Repo> repo = createProject(project.get());
ProjectConfig cfg = projectCache.checkedGet(project).getConfig(); ConfigInput conf = new ConfigInput();
cfg.setEnableReviewerByEmail(true); conf.enableReviewerByEmail = InheritableBoolean.TRUE;
saveProjectConfig(project, cfg); gApi.projects().name(project.get()).config(conf);
String userByEmail = "John Doe <un.registered@reviewer.com>"; String userByEmail = "John Doe <un.registered@reviewer.com>";
@@ -2127,12 +2128,4 @@ public abstract class AbstractQueryChangesTest extends GerritServerTests {
Patch.COMMIT_MSG, ImmutableList.<ReviewInput.CommentInput>of(comment)); Patch.COMMIT_MSG, ImmutableList.<ReviewInput.CommentInput>of(comment));
gApi.changes().id(changeId).current().review(input); gApi.changes().id(changeId).current().review(input);
} }
private void saveProjectConfig(Project.NameKey p, ProjectConfig cfg) throws Exception {
try (MetaDataUpdate md = metaDataUpdateFactory.create(p)) {
md.setAuthor(userFactory.create(userId));
cfg.commit(md);
}
projectCache.evict(cfg.getProject());
}
} }