Merge branch 'stable-2.15'
* stable-2.15: Fix star icon not highlighted in change list on UI Fix the "red" change size on elasticsearch site UI Restore not strict label votes per default SshCommandsIT: Include `logging ls` and `logging set` commands Add tests to make sure ssh commands can be executed Align ElasticIndexModule with LuceneIndexModule Revert "Remove unneeded nested MultiVersionModule class" Remove unneeded nested MultiVersionModule class Only bind index {start/activate} if needed Allow percent encoding in patch set titles. InitIndex: Allow to configure index.maxLimit for Elasticsearch Don't curse over files with up/down keys Add reset button to my menu in settings Add a check for name in Firefox/Safari Make sure plugins are not double counted Link account chips to owner search rather than user dashboard Add a link to group page in groups section of settings Change-Id: Ifad7c2402614afe247e812bdd12de72dc3c299fe
This commit is contained in:
@@ -1245,6 +1245,14 @@ Zero or negative values allow robot comments of unlimited size.
|
|||||||
+
|
+
|
||||||
The default limit is 1024kB.
|
The default limit is 1024kB.
|
||||||
|
|
||||||
|
[[change.strictLabels]]change.strictLabels::
|
||||||
|
+
|
||||||
|
Reject invalid label votes: invalid labels or invalid values. This
|
||||||
|
configuration option is provided for backwards compaitbility and may
|
||||||
|
be removed in future gerrit versions.
|
||||||
|
+
|
||||||
|
Default is false.
|
||||||
|
|
||||||
[[change.disablePrivateChanges]]change.disablePrivateChanges::
|
[[change.disablePrivateChanges]]change.disablePrivateChanges::
|
||||||
+
|
+
|
||||||
If set to true, users are not allowed to create private changes.
|
If set to true, users are not allowed to create private changes.
|
||||||
@@ -2741,9 +2749,10 @@ result lists). Set to 0 for no limit.
|
|||||||
+
|
+
|
||||||
When `index.type` is set to `ELASTICSEARCH`, this value should not exceed
|
When `index.type` is set to `ELASTICSEARCH`, this value should not exceed
|
||||||
the `index.max_result_window` value configured on the Elasticsearch
|
the `index.max_result_window` value configured on the Elasticsearch
|
||||||
server.
|
server. If a value is not configured during site initialization, defaults to
|
||||||
|
10000, which is the default value of `index.max_result_window` in Elasticsearch.
|
||||||
+
|
+
|
||||||
Defaults to no limit.
|
When `index.type` is set to `LUCENE`, defaults to no limit.
|
||||||
|
|
||||||
[[index.maxPages]]index.maxPages::
|
[[index.maxPages]]index.maxPages::
|
||||||
+
|
+
|
||||||
|
@@ -69,6 +69,7 @@ import io.searchbox.core.search.sort.Sort.Sorting;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.apache.commons.codec.binary.Base64;
|
import org.apache.commons.codec.binary.Base64;
|
||||||
import org.eclipse.jgit.lib.Config;
|
import org.eclipse.jgit.lib.Config;
|
||||||
@@ -221,9 +222,24 @@ class ElasticChangeIndex extends AbstractElasticIndex<Change.Id, ChangeData>
|
|||||||
// Changed lines.
|
// Changed lines.
|
||||||
int added = addedElement.getAsInt();
|
int added = addedElement.getAsInt();
|
||||||
int deleted = deletedElement.getAsInt();
|
int deleted = deletedElement.getAsInt();
|
||||||
if (added != 0 && deleted != 0) {
|
cd.setChangedLines(added, deleted);
|
||||||
cd.setChangedLines(added, deleted);
|
}
|
||||||
|
|
||||||
|
// Star.
|
||||||
|
JsonElement starredElement = source.get(ChangeField.STAR.getName());
|
||||||
|
if (starredElement != null) {
|
||||||
|
ListMultimap<Account.Id, String> stars = MultimapBuilder.hashKeys().arrayListValues().build();
|
||||||
|
JsonArray starBy = starredElement.getAsJsonArray();
|
||||||
|
if (starBy.size() > 0) {
|
||||||
|
for (int i = 0; i < starBy.size(); i++) {
|
||||||
|
String[] indexableFields = starBy.get(i).getAsString().split(":");
|
||||||
|
Optional<Account.Id> id = Account.Id.tryParse(indexableFields[0]);
|
||||||
|
if (id.isPresent()) {
|
||||||
|
stars.put(id.get(), indexableFields[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
cd.setStars(stars);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mergeable.
|
// Mergeable.
|
||||||
|
@@ -96,7 +96,6 @@ public class ElasticIndexModule extends AbstractModule {
|
|||||||
} else {
|
} else {
|
||||||
install(new SingleVersionModule(singleVersions));
|
install(new SingleVersionModule(singleVersions));
|
||||||
}
|
}
|
||||||
bind(VersionManager.class).to(ElasticVersionManager.class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
@@ -113,6 +112,7 @@ public class ElasticIndexModule extends AbstractModule {
|
|||||||
private class MultiVersionModule extends LifecycleModule {
|
private class MultiVersionModule extends LifecycleModule {
|
||||||
@Override
|
@Override
|
||||||
public void configure() {
|
public void configure() {
|
||||||
|
bind(VersionManager.class).to(ElasticVersionManager.class);
|
||||||
listener().to(ElasticVersionManager.class);
|
listener().to(ElasticVersionManager.class);
|
||||||
if (onlineUpgrade) {
|
if (onlineUpgrade) {
|
||||||
listener().to(OnlineUpgrader.class);
|
listener().to(OnlineUpgrader.class);
|
||||||
|
@@ -413,7 +413,7 @@ public class WebAppInitializer extends GuiceServletContextListener implements Fi
|
|||||||
false,
|
false,
|
||||||
sysInjector.getInstance(DownloadConfig.class),
|
sysInjector.getInstance(DownloadConfig.class),
|
||||||
sysInjector.getInstance(LfsPluginAuthCommand.Module.class)));
|
sysInjector.getInstance(LfsPluginAuthCommand.Module.class)));
|
||||||
modules.add(new IndexCommandsModule());
|
modules.add(new IndexCommandsModule(sysInjector));
|
||||||
return sysInjector.createChildInjector(modules);
|
return sysInjector.createChildInjector(modules);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -106,7 +106,6 @@ public class LuceneIndexModule extends AbstractModule {
|
|||||||
} else {
|
} else {
|
||||||
install(new SingleVersionModule(singleVersions));
|
install(new SingleVersionModule(singleVersions));
|
||||||
}
|
}
|
||||||
bind(VersionManager.class).to(LuceneVersionManager.class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
@@ -125,6 +124,7 @@ public class LuceneIndexModule extends AbstractModule {
|
|||||||
private class MultiVersionModule extends LifecycleModule {
|
private class MultiVersionModule extends LifecycleModule {
|
||||||
@Override
|
@Override
|
||||||
public void configure() {
|
public void configure() {
|
||||||
|
bind(VersionManager.class).to(LuceneVersionManager.class);
|
||||||
listener().to(LuceneVersionManager.class);
|
listener().to(LuceneVersionManager.class);
|
||||||
if (onlineUpgrade) {
|
if (onlineUpgrade) {
|
||||||
listener().to(OnlineUpgrader.class);
|
listener().to(OnlineUpgrader.class);
|
||||||
|
@@ -545,7 +545,7 @@ public class Daemon extends SiteProgram {
|
|||||||
sysInjector.getInstance(DownloadConfig.class),
|
sysInjector.getInstance(DownloadConfig.class),
|
||||||
sysInjector.getInstance(LfsPluginAuthCommand.Module.class)));
|
sysInjector.getInstance(LfsPluginAuthCommand.Module.class)));
|
||||||
if (!slave) {
|
if (!slave) {
|
||||||
modules.add(new IndexCommandsModule());
|
modules.add(new IndexCommandsModule(sysInjector));
|
||||||
}
|
}
|
||||||
return sysInjector.createChildInjector(modules);
|
return sysInjector.createChildInjector(modules);
|
||||||
}
|
}
|
||||||
|
@@ -70,6 +70,7 @@ class InitIndex implements InitStep {
|
|||||||
"Transport protocol", "protocol", "http", Sets.newHashSet("http", "https"));
|
"Transport protocol", "protocol", "http", Sets.newHashSet("http", "https"));
|
||||||
defaultServer.string("Hostname", "hostname", "localhost");
|
defaultServer.string("Hostname", "hostname", "localhost");
|
||||||
defaultServer.string("Port", "port", "9200");
|
defaultServer.string("Port", "port", "9200");
|
||||||
|
index.string("Result window size", "maxLimit", "10000");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((site.isNew || isEmptySite()) && type == IndexType.LUCENE) {
|
if ((site.isNew || isEmptySite()) && type == IndexType.LUCENE) {
|
||||||
|
@@ -172,6 +172,7 @@ public class PostReview
|
|||||||
private final Config gerritConfig;
|
private final Config gerritConfig;
|
||||||
private final WorkInProgressOp.Factory workInProgressOpFactory;
|
private final WorkInProgressOp.Factory workInProgressOpFactory;
|
||||||
private final ProjectCache projectCache;
|
private final ProjectCache projectCache;
|
||||||
|
private final boolean strictLabels;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
PostReview(
|
PostReview(
|
||||||
@@ -211,6 +212,7 @@ public class PostReview
|
|||||||
this.gerritConfig = gerritConfig;
|
this.gerritConfig = gerritConfig;
|
||||||
this.workInProgressOpFactory = workInProgressOpFactory;
|
this.workInProgressOpFactory = workInProgressOpFactory;
|
||||||
this.projectCache = projectCache;
|
this.projectCache = projectCache;
|
||||||
|
this.strictLabels = gerritConfig.getBoolean("change", "strictLabels", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -450,8 +452,12 @@ public class PostReview
|
|||||||
Map.Entry<String, Short> ent = itr.next();
|
Map.Entry<String, Short> ent = itr.next();
|
||||||
LabelType type = labelTypes.byLabel(ent.getKey());
|
LabelType type = labelTypes.byLabel(ent.getKey());
|
||||||
if (type == null) {
|
if (type == null) {
|
||||||
throw new BadRequestException(
|
if (strictLabels) {
|
||||||
String.format("label \"%s\" is not a configured label", ent.getKey()));
|
throw new BadRequestException(
|
||||||
|
String.format("label \"%s\" is not a configured label", ent.getKey()));
|
||||||
|
}
|
||||||
|
itr.remove();
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!caller.isInternalUser()) {
|
if (!caller.isInternalUser()) {
|
||||||
@@ -490,8 +496,12 @@ public class PostReview
|
|||||||
Map.Entry<String, Short> ent = itr.next();
|
Map.Entry<String, Short> ent = itr.next();
|
||||||
LabelType lt = labelTypes.byLabel(ent.getKey());
|
LabelType lt = labelTypes.byLabel(ent.getKey());
|
||||||
if (lt == null) {
|
if (lt == null) {
|
||||||
throw new BadRequestException(
|
if (strictLabels) {
|
||||||
String.format("label \"%s\" is not a configured label", ent.getKey()));
|
throw new BadRequestException(
|
||||||
|
String.format("label \"%s\" is not a configured label", ent.getKey()));
|
||||||
|
}
|
||||||
|
itr.remove();
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ent.getValue() == null || ent.getValue() == 0) {
|
if (ent.getValue() == null || ent.getValue() == 0) {
|
||||||
@@ -501,8 +511,12 @@ public class PostReview
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (lt.getValue(ent.getValue()) == null) {
|
if (lt.getValue(ent.getValue()) == null) {
|
||||||
throw new BadRequestException(
|
if (strictLabels) {
|
||||||
String.format("label \"%s\": %d is not a valid value", ent.getKey(), ent.getValue()));
|
throw new BadRequestException(
|
||||||
|
String.format("label \"%s\": %d is not a valid value", ent.getKey(), ent.getValue()));
|
||||||
|
}
|
||||||
|
itr.remove();
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
short val = ent.getValue();
|
short val = ent.getValue();
|
||||||
|
@@ -14,20 +14,31 @@
|
|||||||
|
|
||||||
package com.google.gerrit.sshd.commands;
|
package com.google.gerrit.sshd.commands;
|
||||||
|
|
||||||
|
import com.google.gerrit.server.index.VersionManager;
|
||||||
import com.google.gerrit.sshd.CommandModule;
|
import com.google.gerrit.sshd.CommandModule;
|
||||||
import com.google.gerrit.sshd.CommandName;
|
import com.google.gerrit.sshd.CommandName;
|
||||||
import com.google.gerrit.sshd.Commands;
|
import com.google.gerrit.sshd.Commands;
|
||||||
import com.google.gerrit.sshd.DispatchCommandProvider;
|
import com.google.gerrit.sshd.DispatchCommandProvider;
|
||||||
|
import com.google.inject.Injector;
|
||||||
|
import com.google.inject.Key;
|
||||||
|
|
||||||
public class IndexCommandsModule extends CommandModule {
|
public class IndexCommandsModule extends CommandModule {
|
||||||
|
|
||||||
|
private final Injector injector;
|
||||||
|
|
||||||
|
public IndexCommandsModule(Injector injector) {
|
||||||
|
this.injector = injector;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
CommandName gerrit = Commands.named("gerrit");
|
CommandName gerrit = Commands.named("gerrit");
|
||||||
CommandName index = Commands.named(gerrit, "index");
|
CommandName index = Commands.named(gerrit, "index");
|
||||||
command(index).toProvider(new DispatchCommandProvider(index));
|
command(index).toProvider(new DispatchCommandProvider(index));
|
||||||
command(index, IndexActivateCommand.class);
|
if (injector.getExistingBinding(Key.get(VersionManager.class)) != null) {
|
||||||
command(index, IndexStartCommand.class);
|
command(index, IndexActivateCommand.class);
|
||||||
|
command(index, IndexStartCommand.class);
|
||||||
|
}
|
||||||
command(index, IndexChangesCommand.class);
|
command(index, IndexChangesCommand.class);
|
||||||
command(index, IndexProjectCommand.class);
|
command(index, IndexProjectCommand.class);
|
||||||
}
|
}
|
||||||
|
@@ -3105,6 +3105,58 @@ public class ChangeIT extends AbstractDaemonTest {
|
|||||||
assertThat(approval.permittedVotingRange).isNull();
|
assertThat(approval.permittedVotingRange).isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void nonStrictLabelWithInvalidLabelPerDefault() throws Exception {
|
||||||
|
String changeId = createChange().getChangeId();
|
||||||
|
|
||||||
|
// Add a review with invalid labels.
|
||||||
|
ReviewInput input = ReviewInput.approve().label("Code-Style", 1);
|
||||||
|
gApi.changes().id(changeId).current().review(input);
|
||||||
|
|
||||||
|
Map<String, Short> votes = gApi.changes().id(changeId).current().reviewer(admin.email).votes();
|
||||||
|
assertThat(votes.keySet()).containsExactly("Code-Review");
|
||||||
|
assertThat(votes.values()).containsExactly((short) 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void nonStrictLabelWithInvalidValuePerDefault() throws Exception {
|
||||||
|
String changeId = createChange().getChangeId();
|
||||||
|
|
||||||
|
// Add a review with invalid label values.
|
||||||
|
ReviewInput input = new ReviewInput().label("Code-Review", 3);
|
||||||
|
gApi.changes().id(changeId).current().review(input);
|
||||||
|
|
||||||
|
Map<String, Short> votes = gApi.changes().id(changeId).current().reviewer(admin.email).votes();
|
||||||
|
if (!notesMigration.readChanges()) {
|
||||||
|
assertThat(votes.keySet()).containsExactly("Code-Review");
|
||||||
|
assertThat(votes.values()).containsExactly((short) 0);
|
||||||
|
} else {
|
||||||
|
assertThat(votes).isEmpty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@GerritConfig(name = "change.strictLabels", value = "true")
|
||||||
|
public void strictLabelWithInvalidLabel() throws Exception {
|
||||||
|
String changeId = createChange().getChangeId();
|
||||||
|
ReviewInput in = new ReviewInput().label("Code-Style", 1);
|
||||||
|
|
||||||
|
exception.expect(BadRequestException.class);
|
||||||
|
exception.expectMessage("label \"Code-Style\" is not a configured label");
|
||||||
|
gApi.changes().id(changeId).current().review(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@GerritConfig(name = "change.strictLabels", value = "true")
|
||||||
|
public void strictLabelWithInvalidValue() throws Exception {
|
||||||
|
String changeId = createChange().getChangeId();
|
||||||
|
ReviewInput in = new ReviewInput().label("Code-Review", 3);
|
||||||
|
|
||||||
|
exception.expect(BadRequestException.class);
|
||||||
|
exception.expectMessage("label \"Code-Review\": 3 is not a valid value");
|
||||||
|
gApi.changes().id(changeId).current().review(in);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void unresolvedCommentsBlocked() throws Exception {
|
public void unresolvedCommentsBlocked() throws Exception {
|
||||||
modifySubmitRules(
|
modifySubmitRules(
|
||||||
|
@@ -139,18 +139,29 @@ public class ImpersonationIT extends AbstractDaemonTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@GerritConfig(name = "change.strictLabels", value = "true")
|
||||||
public void voteOnBehalfOfInvalidLabel() throws Exception {
|
public void voteOnBehalfOfInvalidLabel() throws Exception {
|
||||||
allowCodeReviewOnBehalfOf();
|
allowCodeReviewOnBehalfOf();
|
||||||
PushOneCommit.Result r = createChange();
|
|
||||||
RevisionApi revision = gApi.changes().id(r.getChangeId()).current();
|
|
||||||
|
|
||||||
ReviewInput in = new ReviewInput();
|
String changeId = createChange().getChangeId();
|
||||||
|
ReviewInput in = new ReviewInput().label("Not-A-Label", 5);
|
||||||
in.onBehalfOf = user.id.toString();
|
in.onBehalfOf = user.id.toString();
|
||||||
in.label("Not-A-Label", 5);
|
|
||||||
|
|
||||||
exception.expect(BadRequestException.class);
|
exception.expect(BadRequestException.class);
|
||||||
exception.expectMessage("label \"Not-A-Label\" is not a configured label");
|
exception.expectMessage("label \"Not-A-Label\" is not a configured label");
|
||||||
revision.review(in);
|
gApi.changes().id(changeId).current().review(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void voteOnBehalfOfInvalidLabelIgnoredWithoutStrictLabels() throws Exception {
|
||||||
|
allowCodeReviewOnBehalfOf();
|
||||||
|
|
||||||
|
String changeId = createChange().getChangeId();
|
||||||
|
ReviewInput in = new ReviewInput().label("Code-Review", 1).label("Not-A-Label", 5);
|
||||||
|
in.onBehalfOf = user.id.toString();
|
||||||
|
gApi.changes().id(changeId).current().review(in);
|
||||||
|
|
||||||
|
assertThat(gApi.changes().id(changeId).get().labels).doesNotContainKey("Not-A-Label");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@@ -95,7 +95,9 @@ public class SshCommandsIT extends AbstractDaemonTest {
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
"index",
|
"index",
|
||||||
ImmutableList.of("activate", "changes", "project", "start"),
|
ImmutableList.of("changes", "project"), // "activate" and "start" are not included
|
||||||
|
"logging",
|
||||||
|
ImmutableList.of("ls", "set"),
|
||||||
"plugin",
|
"plugin",
|
||||||
ImmutableList.of("add", "enable", "install", "ls", "reload", "remove", "rm"),
|
ImmutableList.of("add", "enable", "install", "ls", "reload", "remove", "rm"),
|
||||||
"test-submit",
|
"test-submit",
|
||||||
|
Reference in New Issue
Block a user