Merge branch 'stable-2.15'
* stable-2.15:
ProjectTagsScreen: Base visibility on the create refs/tags/* permission
Upgrade JGit to 4.9.4.201809090327-r
Upgrade JGit to 4.7.3.201809090215-r
Set version to 2.14.13-SNAPSHOT
ProjectTagsScreen: Base visibility on the create refs/tags/* permission
Set version to 2.15.4-SNAPSHOT
Set version to 2.14.12
[project.config] Allow to add commentLink entries
ElasticVersionTest: Align tested versions w/ ElasticContainer last ones
Assume correct relative or absolute URL from Weblink provider
AbstractSubmit: Remove redundant assertion about null IOException
ListMailFilter: Fix operator precedence warning raised by ErrorProne
ListProjects: Fix operator precedence warning raised by ErrorProne
ChangeBundle: Fix operator precedence warning raised by ErrorProne
Bazel: fix error_prone_warnings_toolchain rule
Elastic{Index|ReindexIT} Remove tests for 6.2 and 6.3
ElasticVersionTest#version6: Add missing test for V6_4
Allow more email RFC accepted chars in username
Make inheritance of receive.maxObjectSizeLimit optional
Allow to inherit receive.maxObjectSizeLimit from parent project
RestApiServlet: Skip capability check for administrators
CreateAccount: Simplify error message when username is invalid
Bazel: Provide toolchain with activated error prone warnings
Use ExternalId.isValidUsername instead of ExternalId.USER_NAME_PATTERN_REGEX
Move regular expressions for user name from Account to ExternalId
AccountIT: Add basic tests for creating user with {in}valid username
Revert refactoring of Account.USER_NAME_PATTERN
Fix code that caused changes to break in MS Edge
Add support for Elasticsearch 6.4.0
Upgrade elasticsearch-rest-client to 6.4.0
ElasticVersion: Say 'Unsupported' rather than 'Invalid'
ElasticQueryAdapter: Move isV6 method to ElasticVersion and simplify
Account.java: introduce compiled pattern and use where applicable
Optimize USER_NAME_PATTERN string and its usage
ElasticContainer: Test against Elasticsearch version 5.6.11
rest-api-accounts: Fix documentation of "Get Active" response
GetCapabilities#CheckOne: Return json content type
ConfigSuite: Instantiate class via getDeclaredConstructor()
Change-Id: I08136f1d27da08ce8a523f2dc062316723e17c45
diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt
index 7f32488..0108a04 100644
--- a/Documentation/config-gerrit.txt
+++ b/Documentation/config-gerrit.txt
@@ -3748,6 +3748,14 @@
+
Common unit suffixes of 'k', 'm', or 'g' are supported.
+[[receive.inheritProjectMaxObjectSizeLimit]]receive.inheritProjectMaxObjectSizeLimit::
++
+Controls whether the project-level link:config-project-config.html[`receive.maxObjectSizeLimit`]
+value is inherited from the parent project. When `true`, the value is
+inherited, otherwise it is not inherited.
++
+Default is false, the value is not inherited.
+
[[receive.maxTrustDepth]]receive.maxTrustDepth::
+
If signed push validation is link:#receive.enableSignedPush[enabled],
diff --git a/Documentation/config-project-config.txt b/Documentation/config-project-config.txt
index b652bda9..cc5386f 100644
--- a/Documentation/config-project-config.txt
+++ b/Documentation/config-project-config.txt
@@ -148,8 +148,10 @@
than the global limit (if configured). In other words, it is only honored when
it further reduces the global limit.
+
-The setting is not inherited from the parent project; it must be explicitly
-set per project.
+When link:config-gerrit.html#receive.inheritProjectMaxObjectSizeLimit[
+`receive.inheritProjectmaxObjectSizeLimit`] is enabled in the global config,
+the value is inherited from the parent project. Otherwise, it is not inherited
+and must be explicitly set per project.
+
Default is zero.
+
diff --git a/Documentation/rest-api-access.txt b/Documentation/rest-api-access.txt
index 65a15ca..c2a7d21 100644
--- a/Documentation/rest-api-access.txt
+++ b/Documentation/rest-api-access.txt
@@ -263,6 +263,7 @@
],
"can_upload": true,
"can_add": true,
+ "can_add_tags": true,
"config_visible": true,
"groups": {
"53a4f647a89ea57992571187d8025f830625192a": {
@@ -313,6 +314,7 @@
],
"can_upload": true,
"can_add": true,
+ "can_add_tags": true,
"config_visible": true
}
}
@@ -399,6 +401,8 @@
Whether the calling user can upload to any ref.
|`can_add` |not set if `false`|
Whether the calling user can add any ref.
+|`can_add_tags` |not set if `false`|
+Whether the calling user can add any tag ref.
|`config_visible` |not set if `false`|
Whether the calling user can see the `refs/meta/config` branch of the
project.
diff --git a/Documentation/rest-api-accounts.txt b/Documentation/rest-api-accounts.txt
index edb642e..e28a9c4 100644
--- a/Documentation/rest-api-accounts.txt
+++ b/Documentation/rest-api-accounts.txt
@@ -418,7 +418,10 @@
.Response
----
HTTP/1.1 200 OK
+ Content-Disposition: attachment
+ Content-Type: application/json; charset=UTF-8
+ )]}'
ok
----
@@ -1095,7 +1098,10 @@
.Response
----
HTTP/1.1 200 OK
+ Content-Disposition: attachment
+ Content-Type: application/json; charset=UTF-8
+ )]}'
ok
----
diff --git a/Documentation/rest-api-projects.txt b/Documentation/rest-api-projects.txt
index 310ec7b..b517d3c 100644
--- a/Documentation/rest-api-projects.txt
+++ b/Documentation/rest-api-projects.txt
@@ -1141,6 +1141,7 @@
],
"can_upload": true,
"can_add": true,
+ "can_add_tags": true,
"config_visible": true,
"groups": {
"c2ce4749a32ceb82cd6adcce65b8216e12afb41c": {
@@ -1242,6 +1243,7 @@
],
"can_upload": true,
"can_add": true,
+ "can_add_tags": true,
"config_visible": true,
"groups": {
"global:Anonymous-Users": {
@@ -3442,10 +3444,10 @@
formatted string. +
Not set if there is no limit for the object size configured on project
level.
-|`inherited_value` |optional|
-The max object size limit that is inherited from the global config as a
-formatted string. +
-Not set if there is no global limit for the object size.
+|`summary` |optional|
+A string describing whether the value was inherited or overridden from
+the parent project or global config. +
+Not set if not inherited or overridden.
|===============================
[[project-access-input]]
diff --git a/WORKSPACE b/WORKSPACE
index 0a6caa2..dca68d3 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -1038,8 +1038,8 @@
maven_jar(
name = "elasticsearch-rest-client",
- artifact = "org.elasticsearch.client:elasticsearch-rest-client:6.3.2",
- sha1 = "2077ea5f00fdd2d6af85223b730ba8047303297f",
+ artifact = "org.elasticsearch.client:elasticsearch-rest-client:6.4.0",
+ sha1 = "0eaa13decb9796eb671c5841d0770ae68b348da5",
)
JACKSON_VERSION = "2.8.9"
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/access/ProjectAccessInfo.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/access/ProjectAccessInfo.java
index b115c7d..88635df 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/access/ProjectAccessInfo.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/access/ProjectAccessInfo.java
@@ -19,6 +19,8 @@
public class ProjectAccessInfo extends JavaScriptObject {
public final native boolean canAddRefs() /*-{ return this.can_add ? true : false; }-*/;
+ public final native boolean canAddTagRefs() /*-{ return this.can_add_tags ? true : false; }-*/;
+
public final native boolean isOwner() /*-{ return this.is_owner ? true : false; }-*/;
public final native boolean configVisible() /*-{ return this.config_visible ? true : false; }-*/;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/UsernameField.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/UsernameField.java
index 80c6d1a..4fdd067 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/UsernameField.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/UsernameField.java
@@ -41,7 +41,7 @@
// corresponding regular expressions in the
// com.google.gerrit.server.account.externalids.ExternalId class.
private static final String USER_NAME_PATTERN_FIRST_REGEX = "[a-zA-Z0-9]";
- private static final String USER_NAME_PATTERN_REST_REGEX = "[a-zA-Z0-9._@-]";
+ private static final String USER_NAME_PATTERN_REST_REGEX = "[a-zA-Z0-9.!#$%&’*+=?^_`\\{|\\}~@-]";
private CopyableLabel userNameLbl;
private NpTextBox userNameTxt;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminMessages.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminMessages.java
index fe27e9c..7b18a39 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminMessages.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminMessages.java
@@ -36,8 +36,6 @@
String effectiveMaxObjectSizeLimit(String effectiveMaxObjectSizeLimit);
- String globalMaxObjectSizeLimit(String globalMaxObjectSizeLimit);
-
String noMaxObjectSizeLimit();
String pluginProjectOptionsTitle(String pluginName);
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminMessages.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminMessages.properties
index f746365..c9aa987 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminMessages.properties
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminMessages.properties
@@ -6,7 +6,6 @@
deletedReference = Reference {0} was deleted
deletedSection = Section {0} was deleted
effectiveMaxObjectSizeLimit = effective: {0} bytes
-globalMaxObjectSizeLimit = The global max object size limit is set to {0}. The limit cannot be increased on project level.
noMaxObjectSizeLimit = No max object size limit is set.
pluginProjectOptionsTitle = {0} Plugin Options
pluginProjectOptionsTitle = {0} Plugin
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoScreen.java
index 05a29ac..d10a031 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoScreen.java
@@ -442,9 +442,8 @@
if (result.maxObjectSizeLimit().value() != null) {
effectiveMaxObjectSizeLimit.setText(
AdminMessages.I.effectiveMaxObjectSizeLimit(result.maxObjectSizeLimit().value()));
- if (result.maxObjectSizeLimit().inheritedValue() != null) {
- effectiveMaxObjectSizeLimit.setTitle(
- AdminMessages.I.globalMaxObjectSizeLimit(result.maxObjectSizeLimit().inheritedValue()));
+ if (result.maxObjectSizeLimit().summary() != null) {
+ effectiveMaxObjectSizeLimit.setTitle(result.maxObjectSizeLimit().summary());
}
} else {
effectiveMaxObjectSizeLimit.setText(AdminMessages.I.noMaxObjectSizeLimit());
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectTagsScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectTagsScreen.java
index 18e4176..22c331d 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectTagsScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectTagsScreen.java
@@ -94,7 +94,7 @@
new GerritCallback<ProjectAccessInfo>() {
@Override
public void onSuccess(ProjectAccessInfo result) {
- addPanel.setVisible(result.canAddRefs());
+ addPanel.setVisible(result.canAddTagRefs());
}
});
query = new Query(match).start(start).run();
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ConfigInfo.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ConfigInfo.java
index 4185ef3..684f8e6 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ConfigInfo.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ConfigInfo.java
@@ -175,10 +175,10 @@
public static class MaxObjectSizeLimitInfo extends JavaScriptObject {
public final native String value() /*-{ return this.value; }-*/;
- public final native String inheritedValue() /*-{ return this.inherited_value; }-*/;
-
public final native String configuredValue() /*-{ return this.configured_value }-*/;
+ public final native String summary() /*-{ return this.summary; }-*/;
+
protected MaxObjectSizeLimitInfo() {}
}
diff --git a/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java b/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java
index 630594f..2c1c93a 100644
--- a/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java
+++ b/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java
@@ -71,6 +71,7 @@
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.nio.entity.NStringEntity;
+import org.elasticsearch.client.Request;
import org.elasticsearch.client.Response;
abstract class AbstractElasticIndex<K, V> implements Index<K, V> {
@@ -171,10 +172,10 @@
public void deleteAll() throws IOException {
// Delete the index, if it exists.
String endpoint = indexName + client.adapter().indicesExistParam();
- Response response = client.get().performRequest("HEAD", endpoint);
+ Response response = client.get().performRequest(new Request("HEAD", endpoint));
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == HttpStatus.SC_OK) {
- response = client.get().performRequest("DELETE", indexName);
+ response = client.get().performRequest(new Request("DELETE", indexName));
statusCode = response.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
throw new IOException(
@@ -307,9 +308,13 @@
private Response performRequest(
String method, Object payload, String uri, Map<String, String> params) throws IOException {
+ Request request = new Request(method, uri);
String payloadStr = payload instanceof String ? (String) payload : payload.toString();
- HttpEntity entity = new NStringEntity(payloadStr, ContentType.APPLICATION_JSON);
- return client.get().performRequest(method, uri, params, entity);
+ request.setEntity(new NStringEntity(payloadStr, ContentType.APPLICATION_JSON));
+ for (Map.Entry<String, String> entry : params.entrySet()) {
+ request.addParameter(entry.getKey(), entry.getValue());
+ }
+ return client.get().performRequest(request);
}
protected class ElasticQuerySource implements DataSource<V> {
diff --git a/java/com/google/gerrit/elasticsearch/ElasticIndexVersionDiscovery.java b/java/com/google/gerrit/elasticsearch/ElasticIndexVersionDiscovery.java
index e36ab2d..a777f47 100644
--- a/java/com/google/gerrit/elasticsearch/ElasticIndexVersionDiscovery.java
+++ b/java/com/google/gerrit/elasticsearch/ElasticIndexVersionDiscovery.java
@@ -24,7 +24,7 @@
import java.util.List;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;
-import org.apache.http.client.methods.HttpGet;
+import org.elasticsearch.client.Request;
import org.elasticsearch.client.Response;
@Singleton
@@ -40,10 +40,8 @@
List<String> discover(String prefix, String indexName) throws IOException {
String name = prefix + indexName + "_";
- Response response =
- client
- .get()
- .performRequest(HttpGet.METHOD_NAME, client.adapter().getVersionDiscoveryUrl(name));
+ Request request = new Request("GET", client.adapter().getVersionDiscoveryUrl(name));
+ Response response = client.get().performRequest(request);
StatusLine statusLine = response.getStatusLine();
if (statusLine.getStatusCode() != HttpStatus.SC_OK) {
diff --git a/java/com/google/gerrit/elasticsearch/ElasticQueryAdapter.java b/java/com/google/gerrit/elasticsearch/ElasticQueryAdapter.java
index 2beb528..8cb69e0 100644
--- a/java/com/google/gerrit/elasticsearch/ElasticQueryAdapter.java
+++ b/java/com/google/gerrit/elasticsearch/ElasticQueryAdapter.java
@@ -32,13 +32,14 @@
ElasticQueryAdapter(ElasticVersion version) {
this.ignoreUnmapped = version == ElasticVersion.V2_4;
- this.usePostV5Type = isV6(version);
- this.versionDiscoveryUrl = isV6(version) ? "%s*" : "%s*/_aliases";
+ this.usePostV5Type = version.isV6();
+ this.versionDiscoveryUrl = version.isV6() ? "%s*" : "%s*/_aliases";
switch (version) {
case V5_6:
case V6_2:
case V6_3:
+ case V6_4:
this.searchFilteringName = "_source";
this.indicesExistParam = "?allow_no_indices=false";
this.exactFieldType = "keyword";
@@ -58,10 +59,6 @@
}
}
- private boolean isV6(ElasticVersion version) {
- return version == ElasticVersion.V6_2 || version == ElasticVersion.V6_3;
- }
-
void setIgnoreUnmapped(JsonObject properties) {
if (ignoreUnmapped) {
properties.addProperty("ignore_unmapped", true);
diff --git a/java/com/google/gerrit/elasticsearch/ElasticRestClientProvider.java b/java/com/google/gerrit/elasticsearch/ElasticRestClientProvider.java
index 6ceb897..337f2ca 100644
--- a/java/com/google/gerrit/elasticsearch/ElasticRestClientProvider.java
+++ b/java/com/google/gerrit/elasticsearch/ElasticRestClientProvider.java
@@ -29,6 +29,7 @@
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
+import org.elasticsearch.client.Request;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
@@ -105,7 +106,7 @@
private ElasticVersion getVersion() throws ElasticException {
try {
- Response response = client.performRequest("GET", "");
+ Response response = client.performRequest(new Request("GET", ""));
StatusLine statusLine = response.getStatusLine();
if (statusLine.getStatusCode() != HttpStatus.SC_OK) {
throw new FailedToGetVersion(statusLine);
diff --git a/java/com/google/gerrit/elasticsearch/ElasticVersion.java b/java/com/google/gerrit/elasticsearch/ElasticVersion.java
index 610a212..dfa5d21 100644
--- a/java/com/google/gerrit/elasticsearch/ElasticVersion.java
+++ b/java/com/google/gerrit/elasticsearch/ElasticVersion.java
@@ -21,7 +21,8 @@
V2_4("2.4.*"),
V5_6("5.6.*"),
V6_2("6.2.*"),
- V6_3("6.3.*");
+ V6_3("6.3.*"),
+ V6_4("6.4.*");
private final String version;
private final Pattern pattern;
@@ -31,29 +32,33 @@
this.pattern = Pattern.compile(version);
}
- public static class InvalidVersion extends ElasticException {
+ public static class UnsupportedVersion extends ElasticException {
private static final long serialVersionUID = 1L;
- InvalidVersion(String version) {
+ UnsupportedVersion(String version) {
super(
String.format(
- "Invalid version: [%s]. Supported versions: %s", version, supportedVersions()));
+ "Unsupported version: [%s]. Supported versions: %s", version, supportedVersions()));
}
}
- public static ElasticVersion forVersion(String version) throws InvalidVersion {
+ public static ElasticVersion forVersion(String version) throws UnsupportedVersion {
for (ElasticVersion value : ElasticVersion.values()) {
if (value.pattern.matcher(version).matches()) {
return value;
}
}
- throw new InvalidVersion(version);
+ throw new UnsupportedVersion(version);
}
public static String supportedVersions() {
return Joiner.on(", ").join(ElasticVersion.values());
}
+ public boolean isV6() {
+ return version.startsWith("6.");
+ }
+
@Override
public String toString() {
return version;
diff --git a/java/com/google/gerrit/extensions/api/access/ProjectAccessInfo.java b/java/com/google/gerrit/extensions/api/access/ProjectAccessInfo.java
index 5d8e950..8273d84 100644
--- a/java/com/google/gerrit/extensions/api/access/ProjectAccessInfo.java
+++ b/java/com/google/gerrit/extensions/api/access/ProjectAccessInfo.java
@@ -29,6 +29,7 @@
public Set<String> ownerOf;
public Boolean canUpload;
public Boolean canAdd;
+ public Boolean canAddTags;
public Boolean configVisible;
public Map<String, GroupInfo> groups;
public List<WebLinkInfo> configWebLinks;
diff --git a/java/com/google/gerrit/extensions/api/projects/ConfigInfo.java b/java/com/google/gerrit/extensions/api/projects/ConfigInfo.java
index b5aff67..08ba486 100644
--- a/java/com/google/gerrit/extensions/api/projects/ConfigInfo.java
+++ b/java/com/google/gerrit/extensions/api/projects/ConfigInfo.java
@@ -59,14 +59,17 @@
}
public static class MaxObjectSizeLimitInfo {
- /* The effective value. Null if not set. */
+ /** The effective value in bytes. Null if not set. */
@Nullable public String value;
- /* The value configured on the project. Null if not set. */
+ /** The value configured explicitly on the project as a formatted string. Null if not set. */
@Nullable public String configuredValue;
- /* The value configured globally. Null if not set. */
- @Nullable public String inheritedValue;
+ /**
+ * Whether the value was inherited or overridden from the project's parent hierarchy or global
+ * config. Null if not inherited or overridden.
+ */
+ @Nullable public String summary;
}
public static class ConfigParameterInfo {
diff --git a/java/com/google/gerrit/httpd/restapi/RestApiServlet.java b/java/com/google/gerrit/httpd/restapi/RestApiServlet.java
index 10f2638..e0559f1 100644
--- a/java/com/google/gerrit/httpd/restapi/RestApiServlet.java
+++ b/java/com/google/gerrit/httpd/restapi/RestApiServlet.java
@@ -1392,10 +1392,15 @@
private void checkRequiresCapability(ViewData d)
throws AuthException, PermissionBackendException {
- globals
- .permissionBackend
- .currentUser()
- .checkAny(GlobalPermission.fromAnnotation(d.pluginName, d.view.getClass()));
+ try {
+ globals.permissionBackend.currentUser().check(GlobalPermission.ADMINISTRATE_SERVER);
+ } catch (AuthException e) {
+ // Skiping
+ globals
+ .permissionBackend
+ .currentUser()
+ .checkAny(GlobalPermission.fromAnnotation(d.pluginName, d.view.getClass()));
+ }
}
private static long handleException(
diff --git a/java/com/google/gerrit/server/account/externalids/ExternalId.java b/java/com/google/gerrit/server/account/externalids/ExternalId.java
index db8ea41..96ea0cc 100644
--- a/java/com/google/gerrit/server/account/externalids/ExternalId.java
+++ b/java/com/google/gerrit/server/account/externalids/ExternalId.java
@@ -47,14 +47,12 @@
// corresponding regular expressions in the
// com.google.gerrit.client.account.UsernameField class.
private static final String USER_NAME_PATTERN_FIRST_REGEX = "[a-zA-Z0-9]";
- private static final String USER_NAME_PATTERN_REST_REGEX = "[a-zA-Z0-9._@-]";
+ private static final String USER_NAME_PATTERN_REST_REGEX = "[a-zA-Z0-9.!#$%&’*+=?^_`\\{|\\}~@-]";
private static final String USER_NAME_PATTERN_LAST_REGEX = "[a-zA-Z0-9]";
/** Regular expression that a username must match. */
private static final String USER_NAME_PATTERN_REGEX =
- "^"
- + //
- "("
+ "^("
+ //
USER_NAME_PATTERN_FIRST_REGEX
+ //
@@ -67,9 +65,7 @@
+ //
USER_NAME_PATTERN_FIRST_REGEX
+ //
- ")"
- + //
- "$";
+ ")$";
private static final Pattern USER_NAME_PATTERN = Pattern.compile(USER_NAME_PATTERN_REGEX);
diff --git a/java/com/google/gerrit/server/git/TransferConfig.java b/java/com/google/gerrit/server/git/TransferConfig.java
index f85f24b..8c93833 100644
--- a/java/com/google/gerrit/server/git/TransferConfig.java
+++ b/java/com/google/gerrit/server/git/TransferConfig.java
@@ -28,6 +28,7 @@
private final PackConfig packConfig;
private final long maxObjectSizeLimit;
private final String maxObjectSizeLimitFormatted;
+ private final boolean inheritProjectMaxObjectSizeLimit;
@Inject
TransferConfig(@GerritServerConfig Config cfg) {
@@ -42,6 +43,8 @@
TimeUnit.SECONDS);
maxObjectSizeLimit = cfg.getLong("receive", "maxObjectSizeLimit", 0);
maxObjectSizeLimitFormatted = cfg.getString("receive", null, "maxObjectSizeLimit");
+ inheritProjectMaxObjectSizeLimit =
+ cfg.getBoolean("receive", "inheritProjectMaxObjectSizeLimit", false);
packConfig = new PackConfig();
packConfig.setDeltaCompress(false);
@@ -65,4 +68,8 @@
public String getFormattedMaxObjectSizeLimit() {
return maxObjectSizeLimitFormatted;
}
+
+ public boolean getInheritProjectMaxObjectSizeLimit() {
+ return inheritProjectMaxObjectSizeLimit;
+ }
}
diff --git a/java/com/google/gerrit/server/git/receive/AsyncReceiveCommits.java b/java/com/google/gerrit/server/git/receive/AsyncReceiveCommits.java
index 7fe0c04..d83ab13 100644
--- a/java/com/google/gerrit/server/git/receive/AsyncReceiveCommits.java
+++ b/java/com/google/gerrit/server/git/receive/AsyncReceiveCommits.java
@@ -224,7 +224,7 @@
receivePack.setAllowNonFastForwards(true);
receivePack.setRefLogIdent(user.newRefLogIdent());
receivePack.setTimeout(transferConfig.getTimeout());
- receivePack.setMaxObjectSizeLimit(projectState.getEffectiveMaxObjectSizeLimit());
+ receivePack.setMaxObjectSizeLimit(projectState.getEffectiveMaxObjectSizeLimit().value);
receivePack.setCheckReceivedObjects(projectState.getConfig().getCheckReceivedObjects());
receivePack.setRefFilter(new ReceiveRefFilter());
receivePack.setAllowPushOptions(true);
diff --git a/java/com/google/gerrit/server/mail/ListMailFilter.java b/java/com/google/gerrit/server/mail/ListMailFilter.java
index eee8c60..1549f8d 100644
--- a/java/com/google/gerrit/server/mail/ListMailFilter.java
+++ b/java/com/google/gerrit/server/mail/ListMailFilter.java
@@ -53,7 +53,8 @@
}
boolean match = mailPattern.matcher(message.from().getEmail()).find();
- if (mode == ListFilterMode.WHITELIST && !match || mode == ListFilterMode.BLACKLIST && match) {
+ if ((mode == ListFilterMode.WHITELIST && !match)
+ || (mode == ListFilterMode.BLACKLIST && match)) {
logger.atInfo().log("Mail message from %s rejected by list filter", message.from());
return false;
}
diff --git a/java/com/google/gerrit/server/notedb/ChangeBundle.java b/java/com/google/gerrit/server/notedb/ChangeBundle.java
index c48a2f8..0ebee1a 100644
--- a/java/com/google/gerrit/server/notedb/ChangeBundle.java
+++ b/java/com/google/gerrit/server/notedb/ChangeBundle.java
@@ -395,7 +395,7 @@
excludeOrigSubj = true;
String aTopic = trimOrNull(a.getTopic());
excludeTopic =
- Objects.equals(aTopic, b.getTopic()) || "".equals(aTopic) && b.getTopic() == null;
+ Objects.equals(aTopic, b.getTopic()) || ("".equals(aTopic) && b.getTopic() == null);
aUpdated = bundleA.getLatestTimestamp();
} else if (bundleA.source == NOTE_DB && bundleB.source == REVIEW_DB) {
boolean createdOnMatchesFirstPs =
@@ -413,7 +413,7 @@
excludeOrigSubj = true;
String bTopic = trimOrNull(b.getTopic());
excludeTopic =
- Objects.equals(bTopic, a.getTopic()) || a.getTopic() == null && "".equals(bTopic);
+ Objects.equals(bTopic, a.getTopic()) || (a.getTopic() == null && "".equals(bTopic));
bUpdated = bundleB.getLatestTimestamp();
}
@@ -718,7 +718,8 @@
excludePostSubmit = a.getValue() == 0 && b.isPostSubmit();
} else if (bundleA.source == NOTE_DB && bundleB.source == REVIEW_DB) {
excludeGranted =
- tb.before(psb.getCreatedOn()) && ta.equals(psa.getCreatedOn()) || tb.compareTo(ta) < 0;
+ (tb.before(psb.getCreatedOn()) && ta.equals(psa.getCreatedOn()))
+ || (tb.compareTo(ta) < 0);
excludePostSubmit = b.getValue() == 0 && a.isPostSubmit();
}
diff --git a/java/com/google/gerrit/server/permissions/ProjectControl.java b/java/com/google/gerrit/server/permissions/ProjectControl.java
index 67662c7..4a4ea37 100644
--- a/java/com/google/gerrit/server/permissions/ProjectControl.java
+++ b/java/com/google/gerrit/server/permissions/ProjectControl.java
@@ -15,6 +15,7 @@
package com.google.gerrit.server.permissions;
import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.gerrit.reviewdb.client.RefNames.REFS_TAGS;
import com.google.gerrit.common.data.AccessSection;
import com.google.gerrit.common.data.Permission;
@@ -212,6 +213,10 @@
return (canPerformOnAnyRef(Permission.CREATE) || isAdmin());
}
+ private boolean canAddTagRefs() {
+ return (canPerformOnTagRef(Permission.CREATE) || isAdmin());
+ }
+
private boolean canCreateChanges() {
for (SectionMatcher matcher : access()) {
AccessSection section = matcher.getSection();
@@ -233,6 +238,26 @@
return declaredOwner;
}
+ private boolean canPerformOnTagRef(String permissionName) {
+ for (SectionMatcher matcher : access()) {
+ AccessSection section = matcher.getSection();
+
+ if (section.getName().startsWith(REFS_TAGS)) {
+ Permission permission = section.getPermission(permissionName);
+ if (permission == null) {
+ continue;
+ }
+
+ Boolean can = canPerform(permissionName, section, permission);
+ if (can != null) {
+ return can;
+ }
+ }
+ }
+
+ return false;
+ }
+
private boolean canPerformOnAnyRef(String permissionName) {
for (SectionMatcher matcher : access()) {
AccessSection section = matcher.getSection();
@@ -241,25 +266,33 @@
continue;
}
- for (PermissionRule rule : permission.getRules()) {
- if (rule.isBlock() || rule.isDeny() || !match(rule)) {
- continue;
- }
-
- // Being in a group that was granted this permission is only an
- // approximation. There might be overrides and doNotInherit
- // that would render this to be false.
- //
- if (controlForRef(section.getName()).canPerform(permissionName)) {
- return true;
- }
- break;
+ Boolean can = canPerform(permissionName, section, permission);
+ if (can != null) {
+ return can;
}
}
return false;
}
+ private Boolean canPerform(String permissionName, AccessSection section, Permission permission) {
+ for (PermissionRule rule : permission.getRules()) {
+ if (rule.isBlock() || rule.isDeny() || !match(rule)) {
+ continue;
+ }
+
+ // Being in a group that was granted this permission is only an
+ // approximation. There might be overrides and doNotInherit
+ // that would render this to be false.
+ //
+ if (controlForRef(section.getName()).canPerform(permissionName)) {
+ return true;
+ }
+ break;
+ }
+ return null;
+ }
+
private boolean canPerformOnAllRefs(String permission, Set<String> ignore) {
boolean canPerform = false;
Set<String> patterns = allRefPatterns(permission);
@@ -403,6 +436,8 @@
case CREATE_REF:
return canAddRefs();
+ case CREATE_TAG_REF:
+ return canAddTagRefs();
case CREATE_CHANGE:
return canCreateChanges();
diff --git a/java/com/google/gerrit/server/permissions/ProjectPermission.java b/java/com/google/gerrit/server/permissions/ProjectPermission.java
index 3fee6cf..7c58ccb 100644
--- a/java/com/google/gerrit/server/permissions/ProjectPermission.java
+++ b/java/com/google/gerrit/server/permissions/ProjectPermission.java
@@ -51,6 +51,21 @@
CREATE_REF,
/**
+ * Can create at least one tag reference in the project.
+ *
+ * <p>This project level permission only validates the user may create some tag reference within
+ * the project. The exact reference name must be checked at creation:
+ *
+ * <pre>permissionBackend
+ * .user(user)
+ * .project(proj)
+ * .ref(ref)
+ * .check(RefPermission.CREATE);
+ * </pre>
+ */
+ CREATE_TAG_REF,
+
+ /**
* Can create at least one change in the project.
*
* <p>This project level permission only validates the user may create a change for some branch
diff --git a/java/com/google/gerrit/server/project/ProjectState.java b/java/com/google/gerrit/server/project/ProjectState.java
index 3e379a6..a9b19d9 100644
--- a/java/com/google/gerrit/server/project/ProjectState.java
+++ b/java/com/google/gerrit/server/project/ProjectState.java
@@ -17,6 +17,7 @@
import static com.google.gerrit.common.data.PermissionRule.Action.ALLOW;
import static java.nio.charset.StandardCharsets.UTF_8;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
@@ -89,6 +90,7 @@
private final Map<String, ProjectLevelConfig> configs;
private final Set<AccountGroup.UUID> localOwners;
private final long globalMaxObjectSizeLimit;
+ private final boolean inheritProjectMaxObjectSizeLimit;
/** Last system time the configuration's revision was examined. */
private volatile long lastCheckGeneration;
@@ -132,6 +134,7 @@
? limitsFactory.create(config.getAccessSection(AccessSection.GLOBAL_CAPABILITIES))
: null;
this.globalMaxObjectSizeLimit = transferConfig.getMaxObjectSizeLimit();
+ this.inheritProjectMaxObjectSizeLimit = transferConfig.getInheritProjectMaxObjectSizeLimit();
if (isAllProjects && !Permission.canBeOnAllProjects(AccessSection.ALL, Permission.OWNER)) {
localOwners = Collections.emptySet();
@@ -264,13 +267,58 @@
}
}
- public long getEffectiveMaxObjectSizeLimit() {
- long local = config.getMaxObjectSizeLimit();
- if (globalMaxObjectSizeLimit > 0 && local > 0) {
- return Math.min(globalMaxObjectSizeLimit, local);
+ public static class EffectiveMaxObjectSizeLimit {
+ public long value;
+ public String summary;
+ }
+
+ private static final String MAY_NOT_SET = "This project may not set a higher limit.";
+
+ @VisibleForTesting
+ public static final String INHERITED_FROM_PARENT = "Inherited from parent project '%s'.";
+
+ @VisibleForTesting
+ public static final String OVERRIDDEN_BY_PARENT =
+ "Overridden by parent project '%s'. " + MAY_NOT_SET;
+
+ @VisibleForTesting
+ public static final String INHERITED_FROM_GLOBAL = "Inherited from the global config.";
+
+ @VisibleForTesting
+ public static final String OVERRIDDEN_BY_GLOBAL =
+ "Overridden by the global config. " + MAY_NOT_SET;
+
+ public EffectiveMaxObjectSizeLimit getEffectiveMaxObjectSizeLimit() {
+ EffectiveMaxObjectSizeLimit result = new EffectiveMaxObjectSizeLimit();
+
+ result.value = config.getMaxObjectSizeLimit();
+
+ if (inheritProjectMaxObjectSizeLimit) {
+ for (ProjectState parent : parents()) {
+ long parentValue = parent.config.getMaxObjectSizeLimit();
+ if (parentValue > 0 && result.value > 0) {
+ if (parentValue < result.value) {
+ result.value = parentValue;
+ result.summary = String.format(OVERRIDDEN_BY_PARENT, parent.config.getName());
+ }
+ } else if (parentValue > 0) {
+ result.value = parentValue;
+ result.summary = String.format(INHERITED_FROM_PARENT, parent.config.getName());
+ }
+ }
}
- // zero means "no limit", in this case the max is more limiting
- return Math.max(globalMaxObjectSizeLimit, local);
+
+ if (globalMaxObjectSizeLimit > 0 && result.value > 0) {
+ if (globalMaxObjectSizeLimit < result.value) {
+ result.value = globalMaxObjectSizeLimit;
+ result.summary = OVERRIDDEN_BY_GLOBAL;
+ }
+ } else if (globalMaxObjectSizeLimit > result.value) {
+ // zero means "no limit", in this case the max is more limiting
+ result.value = globalMaxObjectSizeLimit;
+ result.summary = INHERITED_FROM_GLOBAL;
+ }
+ return result;
}
/** Get the sections that pertain only to this project. */
diff --git a/java/com/google/gerrit/server/restapi/account/CreateAccount.java b/java/com/google/gerrit/server/restapi/account/CreateAccount.java
index 78ec540..0e8eb70 100644
--- a/java/com/google/gerrit/server/restapi/account/CreateAccount.java
+++ b/java/com/google/gerrit/server/restapi/account/CreateAccount.java
@@ -115,8 +115,7 @@
throw new BadRequestException("username must match URL");
}
if (!ExternalId.isValidUsername(username)) {
- throw new BadRequestException(
- "Username '" + username + "' must contain only letters, numbers, _, - or .");
+ throw new BadRequestException("Invalid username '" + username + "'");
}
Set<AccountGroup.UUID> groups = parseGroups(input.groups);
diff --git a/java/com/google/gerrit/server/restapi/account/GetCapabilities.java b/java/com/google/gerrit/server/restapi/account/GetCapabilities.java
index 7889f6e..5c466bf 100644
--- a/java/com/google/gerrit/server/restapi/account/GetCapabilities.java
+++ b/java/com/google/gerrit/server/restapi/account/GetCapabilities.java
@@ -26,8 +26,8 @@
import com.google.gerrit.extensions.api.access.PluginPermission;
import com.google.gerrit.extensions.config.CapabilityDefinition;
import com.google.gerrit.extensions.registration.DynamicMap;
-import com.google.gerrit.extensions.restapi.BinaryResult;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
+import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.server.CurrentUser;
@@ -172,9 +172,9 @@
}
@Override
- public BinaryResult apply(Capability resource) throws ResourceNotFoundException {
+ public Response<String> apply(Capability resource) throws ResourceNotFoundException {
permissionBackend.checkUsesDefaultCapabilities();
- return BinaryResult.create("ok\n");
+ return Response.ok("ok");
}
}
}
diff --git a/java/com/google/gerrit/server/restapi/project/ConfigInfoImpl.java b/java/com/google/gerrit/server/restapi/project/ConfigInfoImpl.java
index 076bf78..60b5dee 100644
--- a/java/com/google/gerrit/server/restapi/project/ConfigInfoImpl.java
+++ b/java/com/google/gerrit/server/restapi/project/ConfigInfoImpl.java
@@ -33,10 +33,10 @@
import com.google.gerrit.server.config.PluginConfigFactory;
import com.google.gerrit.server.config.ProjectConfigEntry;
import com.google.gerrit.server.extensions.webui.UiActions;
-import com.google.gerrit.server.git.TransferConfig;
import com.google.gerrit.server.project.BooleanProjectConfigTransformations;
import com.google.gerrit.server.project.ProjectResource;
import com.google.gerrit.server.project.ProjectState;
+import com.google.gerrit.server.project.ProjectState.EffectiveMaxObjectSizeLimit;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.Map;
@@ -48,7 +48,6 @@
boolean serverEnableSignedPush,
ProjectState projectState,
CurrentUser user,
- TransferConfig transferConfig,
DynamicMap<ProjectConfigEntry> pluginConfigEntries,
PluginConfigFactory cfgFactory,
AllProjectsName allProjects,
@@ -72,7 +71,7 @@
this.requireSignedPush = null;
}
- this.maxObjectSizeLimit = getMaxObjectSizeLimit(projectState, transferConfig, p);
+ this.maxObjectSizeLimit = getMaxObjectSizeLimit(projectState, p);
this.defaultSubmitType = new SubmitTypeInfo();
this.defaultSubmitType.value = projectState.getSubmitType();
@@ -107,13 +106,13 @@
this.extensionPanelNames = projectState.getConfig().getExtensionPanelSections();
}
- private MaxObjectSizeLimitInfo getMaxObjectSizeLimit(
- ProjectState projectState, TransferConfig transferConfig, Project p) {
+ private MaxObjectSizeLimitInfo getMaxObjectSizeLimit(ProjectState projectState, Project p) {
MaxObjectSizeLimitInfo info = new MaxObjectSizeLimitInfo();
- long value = projectState.getEffectiveMaxObjectSizeLimit();
+ EffectiveMaxObjectSizeLimit limit = projectState.getEffectiveMaxObjectSizeLimit();
+ long value = limit.value;
info.value = value == 0 ? null : String.valueOf(value);
info.configuredValue = p.getMaxObjectSizeLimit();
- info.inheritedValue = transferConfig.getFormattedMaxObjectSizeLimit();
+ info.summary = limit.summary;
return info;
}
diff --git a/java/com/google/gerrit/server/restapi/project/GetAccess.java b/java/com/google/gerrit/server/restapi/project/GetAccess.java
index d545f92..a6b9404 100644
--- a/java/com/google/gerrit/server/restapi/project/GetAccess.java
+++ b/java/com/google/gerrit/server/restapi/project/GetAccess.java
@@ -16,6 +16,7 @@
import static com.google.gerrit.server.permissions.GlobalPermission.ADMINISTRATE_SERVER;
import static com.google.gerrit.server.permissions.ProjectPermission.CREATE_REF;
+import static com.google.gerrit.server.permissions.ProjectPermission.CREATE_TAG_REF;
import static com.google.gerrit.server.permissions.RefPermission.CREATE_CHANGE;
import static com.google.gerrit.server.permissions.RefPermission.READ;
import static com.google.gerrit.server.permissions.RefPermission.WRITE_CONFIG;
@@ -270,6 +271,7 @@
|| (canReadConfig
&& perm.ref(RefNames.REFS_CONFIG).testOrFalse(CREATE_CHANGE))));
info.canAdd = toBoolean(perm.testOrFalse(CREATE_REF));
+ info.canAddTags = toBoolean(perm.testOrFalse(CREATE_TAG_REF));
info.configVisible = canReadConfig || canWriteConfig;
info.groups =
diff --git a/java/com/google/gerrit/server/restapi/project/GetConfig.java b/java/com/google/gerrit/server/restapi/project/GetConfig.java
index 7fedc8f..b3ad962 100644
--- a/java/com/google/gerrit/server/restapi/project/GetConfig.java
+++ b/java/com/google/gerrit/server/restapi/project/GetConfig.java
@@ -23,7 +23,6 @@
import com.google.gerrit.server.config.PluginConfigFactory;
import com.google.gerrit.server.config.ProjectConfigEntry;
import com.google.gerrit.server.extensions.webui.UiActions;
-import com.google.gerrit.server.git.TransferConfig;
import com.google.gerrit.server.project.ProjectResource;
import com.google.inject.Inject;
import com.google.inject.Singleton;
@@ -31,7 +30,6 @@
@Singleton
public class GetConfig implements RestReadView<ProjectResource> {
private final boolean serverEnableSignedPush;
- private final TransferConfig transferConfig;
private final DynamicMap<ProjectConfigEntry> pluginConfigEntries;
private final PluginConfigFactory cfgFactory;
private final AllProjectsName allProjects;
@@ -41,14 +39,12 @@
@Inject
public GetConfig(
@EnableSignedPush boolean serverEnableSignedPush,
- TransferConfig transferConfig,
DynamicMap<ProjectConfigEntry> pluginConfigEntries,
PluginConfigFactory cfgFactory,
AllProjectsName allProjects,
UiActions uiActions,
DynamicMap<RestView<ProjectResource>> views) {
this.serverEnableSignedPush = serverEnableSignedPush;
- this.transferConfig = transferConfig;
this.pluginConfigEntries = pluginConfigEntries;
this.allProjects = allProjects;
this.cfgFactory = cfgFactory;
@@ -62,7 +58,6 @@
serverEnableSignedPush,
resource.getProjectState(),
resource.getUser(),
- transferConfig,
pluginConfigEntries,
cfgFactory,
allProjects,
diff --git a/java/com/google/gerrit/server/restapi/project/PutConfig.java b/java/com/google/gerrit/server/restapi/project/PutConfig.java
index f4eb781..76ea0c9 100644
--- a/java/com/google/gerrit/server/restapi/project/PutConfig.java
+++ b/java/com/google/gerrit/server/restapi/project/PutConfig.java
@@ -38,7 +38,6 @@
import com.google.gerrit.server.config.PluginConfigFactory;
import com.google.gerrit.server.config.ProjectConfigEntry;
import com.google.gerrit.server.extensions.webui.UiActions;
-import com.google.gerrit.server.git.TransferConfig;
import com.google.gerrit.server.git.meta.MetaDataUpdate;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendException;
@@ -71,7 +70,6 @@
private final Provider<MetaDataUpdate.User> metaDataUpdateFactory;
private final ProjectCache projectCache;
private final ProjectState.Factory projectStateFactory;
- private final TransferConfig transferConfig;
private final DynamicMap<ProjectConfigEntry> pluginConfigEntries;
private final PluginConfigFactory cfgFactory;
private final AllProjectsName allProjects;
@@ -86,7 +84,6 @@
Provider<MetaDataUpdate.User> metaDataUpdateFactory,
ProjectCache projectCache,
ProjectState.Factory projectStateFactory,
- TransferConfig transferConfig,
DynamicMap<ProjectConfigEntry> pluginConfigEntries,
PluginConfigFactory cfgFactory,
AllProjectsName allProjects,
@@ -98,7 +95,6 @@
this.metaDataUpdateFactory = metaDataUpdateFactory;
this.projectCache = projectCache;
this.projectStateFactory = projectStateFactory;
- this.transferConfig = transferConfig;
this.pluginConfigEntries = pluginConfigEntries;
this.cfgFactory = cfgFactory;
this.allProjects = allProjects;
@@ -173,7 +169,6 @@
serverEnableSignedPush,
state,
user.get(),
- transferConfig,
pluginConfigEntries,
cfgFactory,
allProjects,
diff --git a/java/com/google/gerrit/testing/ConfigSuite.java b/java/com/google/gerrit/testing/ConfigSuite.java
index ff87fd8..9e45b7c 100644
--- a/java/com/google/gerrit/testing/ConfigSuite.java
+++ b/java/com/google/gerrit/testing/ConfigSuite.java
@@ -159,7 +159,7 @@
@Override
public Object createTest() throws Exception {
- Object test = getTestClass().getJavaClass().newInstance();
+ Object test = getTestClass().getJavaClass().getDeclaredConstructor().newInstance();
parameterField.set(test, new org.eclipse.jgit.lib.Config(cfg));
if (nameField != null) {
nameField.set(test, name);
diff --git a/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java b/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java
index 7126354..de66b87 100644
--- a/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java
@@ -2164,6 +2164,38 @@
}
@Test
+ public void createUserWithValidUsername() throws Exception {
+ ImmutableList<String> names =
+ ImmutableList.of(
+ "user@domain",
+ "user-name",
+ "user_name",
+ "1234",
+ "user1234",
+ "1234@domain",
+ "user!+alias{*}#$%&’^=~|@domain");
+ for (String name : names) {
+ gApi.accounts().create(name);
+ }
+ }
+
+ @Test
+ public void createUserWithInvalidUsername() throws Exception {
+ ImmutableList<String> invalidNames =
+ ImmutableList.of(
+ "@", "@foo", "-", "-foo", "_", "_foo", "!", "+", "{", "}", "*", "%", "#", "$", "&", "’",
+ "^", "=", "~");
+ for (String name : invalidNames) {
+ try {
+ gApi.accounts().create(name);
+ fail(String.format("Expected BadRequestException for username [%s]", name));
+ } catch (BadRequestException e) {
+ assertThat(e).hasMessageThat().isEqualTo(String.format("Invalid username '%s'", name));
+ }
+ }
+ }
+
+ @Test
public void allGroupsForAUserAccountCanBeRetrieved() throws Exception {
String username = name("user1");
accountOperations.newAccount().username(username).create();
diff --git a/javatests/com/google/gerrit/acceptance/api/project/ProjectIT.java b/javatests/com/google/gerrit/acceptance/api/project/ProjectIT.java
index f7d3867..18888ea 100644
--- a/javatests/com/google/gerrit/acceptance/api/project/ProjectIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/project/ProjectIT.java
@@ -16,6 +16,10 @@
import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.server.git.QueueProvider.QueueType.BATCH;
+import static com.google.gerrit.server.project.ProjectState.INHERITED_FROM_GLOBAL;
+import static com.google.gerrit.server.project.ProjectState.INHERITED_FROM_PARENT;
+import static com.google.gerrit.server.project.ProjectState.OVERRIDDEN_BY_GLOBAL;
+import static com.google.gerrit.server.project.ProjectState.OVERRIDDEN_BY_PARENT;
import static java.util.stream.Collectors.toSet;
import com.google.common.collect.ImmutableList;
@@ -416,7 +420,7 @@
ConfigInfo info = getConfig();
assertThat(info.maxObjectSizeLimit.value).isNull();
assertThat(info.maxObjectSizeLimit.configuredValue).isNull();
- assertThat(info.maxObjectSizeLimit.inheritedValue).isNull();
+ assertThat(info.maxObjectSizeLimit.summary).isNull();
}
@Test
@@ -425,13 +429,30 @@
ConfigInfo info = setMaxObjectSize("100k");
assertThat(info.maxObjectSizeLimit.value).isEqualTo("102400");
assertThat(info.maxObjectSizeLimit.configuredValue).isEqualTo("100k");
- assertThat(info.maxObjectSizeLimit.inheritedValue).isNull();
+ assertThat(info.maxObjectSizeLimit.summary).isNull();
// Clear the value
info = setMaxObjectSize("0");
assertThat(info.maxObjectSizeLimit.value).isNull();
assertThat(info.maxObjectSizeLimit.configuredValue).isNull();
- assertThat(info.maxObjectSizeLimit.inheritedValue).isNull();
+ assertThat(info.maxObjectSizeLimit.summary).isNull();
+ }
+
+ @Test
+ @GerritConfig(name = "receive.inheritProjectMaxObjectSizeLimit", value = "true")
+ public void maxObjectSizeIsInheritedFromParentProject() throws Exception {
+ Project.NameKey child = createProject(name("child"), project);
+
+ ConfigInfo info = setMaxObjectSize("100k");
+ assertThat(info.maxObjectSizeLimit.value).isEqualTo("102400");
+ assertThat(info.maxObjectSizeLimit.configuredValue).isEqualTo("100k");
+ assertThat(info.maxObjectSizeLimit.summary).isNull();
+
+ info = getConfig(child);
+ assertThat(info.maxObjectSizeLimit.value).isEqualTo("102400");
+ assertThat(info.maxObjectSizeLimit.configuredValue).isNull();
+ assertThat(info.maxObjectSizeLimit.summary)
+ .isEqualTo(String.format(INHERITED_FROM_PARENT, project));
}
@Test
@@ -441,21 +462,75 @@
ConfigInfo info = setMaxObjectSize("100k");
assertThat(info.maxObjectSizeLimit.value).isEqualTo("102400");
assertThat(info.maxObjectSizeLimit.configuredValue).isEqualTo("100k");
- assertThat(info.maxObjectSizeLimit.inheritedValue).isNull();
+ assertThat(info.maxObjectSizeLimit.summary).isNull();
info = getConfig(child);
assertThat(info.maxObjectSizeLimit.value).isNull();
assertThat(info.maxObjectSizeLimit.configuredValue).isNull();
- assertThat(info.maxObjectSizeLimit.inheritedValue).isNull();
+ assertThat(info.maxObjectSizeLimit.summary).isNull();
+ }
+
+ @Test
+ public void maxObjectSizeOverridesParentProjectWhenNotSetOnParent() throws Exception {
+ Project.NameKey child = createProject(name("child"), project);
+
+ ConfigInfo info = setMaxObjectSize("0");
+ assertThat(info.maxObjectSizeLimit.value).isNull();
+ assertThat(info.maxObjectSizeLimit.configuredValue).isNull();
+ assertThat(info.maxObjectSizeLimit.summary).isNull();
+
+ info = setMaxObjectSize(child, "100k");
+ assertThat(info.maxObjectSizeLimit.value).isEqualTo("102400");
+ assertThat(info.maxObjectSizeLimit.configuredValue).isEqualTo("100k");
+ assertThat(info.maxObjectSizeLimit.summary).isNull();
+ }
+
+ @Test
+ public void maxObjectSizeOverridesParentProjectWhenLower() throws Exception {
+ Project.NameKey child = createProject(name("child"), project);
+
+ ConfigInfo info = setMaxObjectSize("200k");
+ assertThat(info.maxObjectSizeLimit.value).isEqualTo("204800");
+ assertThat(info.maxObjectSizeLimit.configuredValue).isEqualTo("200k");
+ assertThat(info.maxObjectSizeLimit.summary).isNull();
+
+ info = setMaxObjectSize(child, "100k");
+ assertThat(info.maxObjectSizeLimit.value).isEqualTo("102400");
+ assertThat(info.maxObjectSizeLimit.configuredValue).isEqualTo("100k");
+ assertThat(info.maxObjectSizeLimit.summary).isNull();
+ }
+
+ @Test
+ @GerritConfig(name = "receive.inheritProjectMaxObjectSizeLimit", value = "true")
+ public void maxObjectSizeDoesNotOverrideParentProjectWhenHigher() throws Exception {
+ Project.NameKey child = createProject(name("child"), project);
+
+ ConfigInfo info = setMaxObjectSize("100k");
+ assertThat(info.maxObjectSizeLimit.value).isEqualTo("102400");
+ assertThat(info.maxObjectSizeLimit.configuredValue).isEqualTo("100k");
+ assertThat(info.maxObjectSizeLimit.summary).isNull();
+
+ info = setMaxObjectSize(child, "200k");
+ assertThat(info.maxObjectSizeLimit.value).isEqualTo("102400");
+ assertThat(info.maxObjectSizeLimit.configuredValue).isEqualTo("200k");
+ assertThat(info.maxObjectSizeLimit.summary)
+ .isEqualTo(String.format(OVERRIDDEN_BY_PARENT, project));
}
@Test
@GerritConfig(name = "receive.maxObjectSizeLimit", value = "200k")
public void maxObjectSizeIsInheritedFromGlobalConfig() throws Exception {
+ Project.NameKey child = createProject(name("child"), project);
+
ConfigInfo info = getConfig();
assertThat(info.maxObjectSizeLimit.value).isEqualTo("204800");
assertThat(info.maxObjectSizeLimit.configuredValue).isNull();
- assertThat(info.maxObjectSizeLimit.inheritedValue).isEqualTo("200k");
+ assertThat(info.maxObjectSizeLimit.summary).isEqualTo(INHERITED_FROM_GLOBAL);
+
+ info = getConfig(child);
+ assertThat(info.maxObjectSizeLimit.value).isEqualTo("204800");
+ assertThat(info.maxObjectSizeLimit.configuredValue).isNull();
+ assertThat(info.maxObjectSizeLimit.summary).isEqualTo(INHERITED_FROM_GLOBAL);
}
@Test
@@ -464,16 +539,40 @@
ConfigInfo info = setMaxObjectSize("100k");
assertThat(info.maxObjectSizeLimit.value).isEqualTo("102400");
assertThat(info.maxObjectSizeLimit.configuredValue).isEqualTo("100k");
- assertThat(info.maxObjectSizeLimit.inheritedValue).isEqualTo("200k");
+ assertThat(info.maxObjectSizeLimit.summary).isNull();
+ }
+
+ @Test
+ @GerritConfig(name = "receive.maxObjectSizeLimit", value = "300k")
+ public void inheritedMaxObjectSizeOverridesGlobalConfigWhenLower() throws Exception {
+ Project.NameKey child = createProject(name("child"), project);
+
+ ConfigInfo info = setMaxObjectSize("200k");
+ assertThat(info.maxObjectSizeLimit.value).isEqualTo("204800");
+ assertThat(info.maxObjectSizeLimit.configuredValue).isEqualTo("200k");
+ assertThat(info.maxObjectSizeLimit.summary).isNull();
+
+ info = setMaxObjectSize(child, "100k");
+ assertThat(info.maxObjectSizeLimit.value).isEqualTo("102400");
+ assertThat(info.maxObjectSizeLimit.configuredValue).isEqualTo("100k");
+ assertThat(info.maxObjectSizeLimit.summary).isNull();
}
@Test
@GerritConfig(name = "receive.maxObjectSizeLimit", value = "200k")
+ @GerritConfig(name = "receive.inheritProjectMaxObjectSizeLimit", value = "true")
public void maxObjectSizeDoesNotOverrideGlobalConfigWhenHigher() throws Exception {
+ Project.NameKey child = createProject(name("child"), project);
+
ConfigInfo info = setMaxObjectSize("300k");
assertThat(info.maxObjectSizeLimit.value).isEqualTo("204800");
assertThat(info.maxObjectSizeLimit.configuredValue).isEqualTo("300k");
- assertThat(info.maxObjectSizeLimit.inheritedValue).isEqualTo("200k");
+ assertThat(info.maxObjectSizeLimit.summary).isEqualTo(OVERRIDDEN_BY_GLOBAL);
+
+ info = getConfig(child);
+ assertThat(info.maxObjectSizeLimit.value).isEqualTo("204800");
+ assertThat(info.maxObjectSizeLimit.configuredValue).isNull();
+ assertThat(info.maxObjectSizeLimit.summary).isEqualTo(OVERRIDDEN_BY_GLOBAL);
}
@Test
@@ -487,10 +586,6 @@
return gApi.projects().name(name.get()).config(input);
}
- private ConfigInfo setConfig(ConfigInput input) throws Exception {
- return setConfig(project, input);
- }
-
private ConfigInfo getConfig(Project.NameKey name) throws Exception {
return gApi.projects().name(name.get()).config();
}
@@ -517,9 +612,13 @@
}
private ConfigInfo setMaxObjectSize(String value) throws Exception {
+ return setMaxObjectSize(project, value);
+ }
+
+ private ConfigInfo setMaxObjectSize(Project.NameKey name, String value) throws Exception {
ConfigInput input = new ConfigInput();
input.maxObjectSizeLimit = value;
- return setConfig(input);
+ return setConfig(name, input);
}
private static class ProjectIndexedCounter implements ProjectIndexedListener {
diff --git a/javatests/com/google/gerrit/acceptance/pgm/ElasticReindexIT.java b/javatests/com/google/gerrit/acceptance/pgm/ElasticReindexIT.java
index c90b3d3..0d5d2cd 100644
--- a/javatests/com/google/gerrit/acceptance/pgm/ElasticReindexIT.java
+++ b/javatests/com/google/gerrit/acceptance/pgm/ElasticReindexIT.java
@@ -47,13 +47,8 @@
}
@ConfigSuite.Config
- public static Config elasticsearchV6_2() {
- return getConfig(ElasticVersion.V6_2);
- }
-
- @ConfigSuite.Config
- public static Config elasticsearchV6_3() {
- return getConfig(ElasticVersion.V6_3);
+ public static Config elasticsearchV6() {
+ return getConfig(ElasticVersion.V6_4);
}
@Override
diff --git a/javatests/com/google/gerrit/acceptance/ssh/ElasticIndexIT.java b/javatests/com/google/gerrit/acceptance/ssh/ElasticIndexIT.java
index 95da5a6..9d69955 100644
--- a/javatests/com/google/gerrit/acceptance/ssh/ElasticIndexIT.java
+++ b/javatests/com/google/gerrit/acceptance/ssh/ElasticIndexIT.java
@@ -46,13 +46,8 @@
}
@ConfigSuite.Config
- public static Config elasticsearchV6_2() {
- return getConfig(ElasticVersion.V6_2);
- }
-
- @ConfigSuite.Config
- public static Config elasticsearchV6_3() {
- return getConfig(ElasticVersion.V6_3);
+ public static Config elasticsearchV6() {
+ return getConfig(ElasticVersion.V6_4);
}
@Override
diff --git a/javatests/com/google/gerrit/elasticsearch/ElasticContainer.java b/javatests/com/google/gerrit/elasticsearch/ElasticContainer.java
index f5614b4..8b3c08f 100644
--- a/javatests/com/google/gerrit/elasticsearch/ElasticContainer.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticContainer.java
@@ -45,11 +45,13 @@
case V2_4:
return "elasticsearch:2.4.6-alpine";
case V5_6:
- return "docker.elastic.co/elasticsearch/elasticsearch:5.6.10";
+ return "docker.elastic.co/elasticsearch/elasticsearch:5.6.11";
case V6_2:
return "docker.elastic.co/elasticsearch/elasticsearch-oss:6.2.4";
case V6_3:
return "docker.elastic.co/elasticsearch/elasticsearch-oss:6.3.2";
+ case V6_4:
+ return "docker.elastic.co/elasticsearch/elasticsearch-oss:6.4.0";
}
throw new IllegalStateException("No tests for version: " + version.name());
}
diff --git a/javatests/com/google/gerrit/elasticsearch/ElasticV6QueryAccountsTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticV6QueryAccountsTest.java
index 1d17b5b..b8154ce 100644
--- a/javatests/com/google/gerrit/elasticsearch/ElasticV6QueryAccountsTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticV6QueryAccountsTest.java
@@ -41,7 +41,7 @@
return;
}
- container = ElasticContainer.createAndStart(ElasticVersion.V6_3);
+ container = ElasticContainer.createAndStart(ElasticVersion.V6_4);
nodeInfo = new ElasticNodeInfo(container.getHttpHost().getPort());
}
diff --git a/javatests/com/google/gerrit/elasticsearch/ElasticV6QueryChangesTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticV6QueryChangesTest.java
index 7c5d2e2..3445b36 100644
--- a/javatests/com/google/gerrit/elasticsearch/ElasticV6QueryChangesTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticV6QueryChangesTest.java
@@ -41,7 +41,7 @@
return;
}
- container = ElasticContainer.createAndStart(ElasticVersion.V6_3);
+ container = ElasticContainer.createAndStart(ElasticVersion.V6_4);
nodeInfo = new ElasticNodeInfo(container.getHttpHost().getPort());
}
diff --git a/javatests/com/google/gerrit/elasticsearch/ElasticV6QueryGroupsTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticV6QueryGroupsTest.java
index 15b58e0..851b27d 100644
--- a/javatests/com/google/gerrit/elasticsearch/ElasticV6QueryGroupsTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticV6QueryGroupsTest.java
@@ -41,7 +41,7 @@
return;
}
- container = ElasticContainer.createAndStart(ElasticVersion.V6_3);
+ container = ElasticContainer.createAndStart(ElasticVersion.V6_4);
nodeInfo = new ElasticNodeInfo(container.getHttpHost().getPort());
}
diff --git a/javatests/com/google/gerrit/elasticsearch/ElasticVersionTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticVersionTest.java
index 860dca6..b598a0a 100644
--- a/javatests/com/google/gerrit/elasticsearch/ElasticVersionTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticVersionTest.java
@@ -29,21 +29,31 @@
assertThat(ElasticVersion.forVersion("2.4.6")).isEqualTo(ElasticVersion.V2_4);
assertThat(ElasticVersion.forVersion("5.6.0")).isEqualTo(ElasticVersion.V5_6);
- assertThat(ElasticVersion.forVersion("5.6.9")).isEqualTo(ElasticVersion.V5_6);
- assertThat(ElasticVersion.forVersion("5.6.10")).isEqualTo(ElasticVersion.V5_6);
+ assertThat(ElasticVersion.forVersion("5.6.11")).isEqualTo(ElasticVersion.V5_6);
assertThat(ElasticVersion.forVersion("6.2.0")).isEqualTo(ElasticVersion.V6_2);
assertThat(ElasticVersion.forVersion("6.2.4")).isEqualTo(ElasticVersion.V6_2);
assertThat(ElasticVersion.forVersion("6.3.0")).isEqualTo(ElasticVersion.V6_3);
- assertThat(ElasticVersion.forVersion("6.3.1")).isEqualTo(ElasticVersion.V6_3);
+ assertThat(ElasticVersion.forVersion("6.3.2")).isEqualTo(ElasticVersion.V6_3);
+
+ assertThat(ElasticVersion.forVersion("6.4.0")).isEqualTo(ElasticVersion.V6_4);
+ assertThat(ElasticVersion.forVersion("6.4.1")).isEqualTo(ElasticVersion.V6_4);
}
@Test
public void unsupportedVersion() throws Exception {
- exception.expect(ElasticVersion.InvalidVersion.class);
+ exception.expect(ElasticVersion.UnsupportedVersion.class);
exception.expectMessage(
- "Invalid version: [4.0.0]. Supported versions: " + ElasticVersion.supportedVersions());
+ "Unsupported version: [4.0.0]. Supported versions: " + ElasticVersion.supportedVersions());
ElasticVersion.forVersion("4.0.0");
}
+
+ @Test
+ public void version6() throws Exception {
+ assertThat(ElasticVersion.V6_2.isV6()).isTrue();
+ assertThat(ElasticVersion.V6_3.isV6()).isTrue();
+ assertThat(ElasticVersion.V6_4.isV6()).isTrue();
+ assertThat(ElasticVersion.V5_6.isV6()).isFalse();
+ }
}
diff --git a/plugins/singleusergroup b/plugins/singleusergroup
index e4024e9..cc636d7 160000
--- a/plugins/singleusergroup
+++ b/plugins/singleusergroup
@@ -1 +1 @@
-Subproject commit e4024e9d8d8139fc4c658c3af1a5e11e19b2d476
+Subproject commit cc636d7e36afb62455a9f045b125d246fd84afd0