Merge "Merge branch 'stable-3.3' into master"
diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt
index ac5e3b7..645954d 100644
--- a/Documentation/config-gerrit.txt
+++ b/Documentation/config-gerrit.txt
@@ -2336,8 +2336,8 @@
[[gerrit.experimentalRollingUpgrade]]gerrit.experimentalRollingUpgrade::
+
Enable Gerrit rolling upgrade to the next version.
-For example if Gerrit v3.1 is version N (All-Projects:refs/meta/version=181)
-then its next version N+1 is v3.2 (All-Projects:refs/meta/version=183).
+For example if Gerrit v3.2 is version N (All-Projects:refs/meta/version=183)
+then its next version N+1 is v3.3 (All-Projects:refs/meta/version=184).
Allow Gerrit to start even if the underlying schema version has been bumped to
the next Gerrit version.
+
@@ -2354,7 +2354,7 @@
1. Set gerrit.experimentalRollingUpgrade to true on all Gerrit masters
2. Set the first master unhealthy
3. Shutdown the first master and [upgrade](install.html#init) to the next version
-4. Startup the first master, wait for the online reindex to complete
+4. Startup the first master, wait for the online reindex to complete (where applicable)
5. Verify the the first master upgrade is successful and online reindex is complete
6. Set the first master healthy
7. Repeat steps 2. to 6. for all the other Gerrit nodes
@@ -5625,10 +5625,12 @@
[[receive.autogc]]receive.autogc::
+
-By default, `git-receive-pack` will run auto gc after receiving data from git-push and updating refs.
+By default, up to Gerrit 3.2 `git-receive-pack` will run auto gc after receiving data from git-push and updating refs.
You can stop it by setting this variable to `false`. This is recommended in gerrit to avoid the
additional load this creates. Instead schedule gc using link:cmd-gc.html#gc.startTime[gc.startTime]
and link:cmd-gc.html#gc.interval[gc.interval] or e.g. in a cron job that runs gc in a separate process.
+Since Gerrit 3.3 the init command will auto-configure `git-receive-pack = false` in `etc/jgit.config` if
+it wasn't set manually and show a warning if it was set to `true` manually.
GERRIT
------
diff --git a/WORKSPACE b/WORKSPACE
index 01decd5..cb1d22c 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -899,48 +899,48 @@
sha1 = "7e060dd5b19431e6d198e91ff670644372f60fbd",
)
-JETTY_VERS = "9.4.32.v20200930"
+JETTY_VERS = "9.4.33.v20201020"
maven_jar(
name = "jetty-servlet",
artifact = "org.eclipse.jetty:jetty-servlet:" + JETTY_VERS,
- sha1 = "4253dd46c099e0bca4dd763fc1e10774e10de00a",
+ sha1 = "101609e8e5365c4406e4448099459eb605ac551f",
)
maven_jar(
name = "jetty-security",
artifact = "org.eclipse.jetty:jetty-security:" + JETTY_VERS,
- sha1 = "16a6110fa40e49050146de5f597ab3a3a3fa83b5",
+ sha1 = "c150bf2aca6cb1636e7195f844a2bb156546e50e",
)
maven_jar(
name = "jetty-server",
artifact = "org.eclipse.jetty:jetty-server:" + JETTY_VERS,
- sha1 = "d2d89099be5237cf68254bc943a7d800d3ee1945",
+ sha1 = "f586ff2ee048ad2575866c1833d854288f402307",
)
maven_jar(
name = "jetty-jmx",
artifact = "org.eclipse.jetty:jetty-jmx:" + JETTY_VERS,
- sha1 = "5e8e87a6f89b8eabf5b5b1765e3d758209001570",
+ sha1 = "56b723070eeafc51b943cd9bf1a064a037e806a7",
)
maven_jar(
name = "jetty-http",
artifact = "org.eclipse.jetty:jetty-http:" + JETTY_VERS,
- sha1 = "5fdcefd82178d11f895690f4fe6e843be69394b3",
+ sha1 = "ad28940f89ffde6ec1bd1656fe3f8493b01ba3c2",
)
maven_jar(
name = "jetty-io",
artifact = "org.eclipse.jetty:jetty-io:" + JETTY_VERS,
- sha1 = "0d0f32c3b511d6b3a542787f95ed229731588810",
+ sha1 = "9e4b0048285b71f4769908780f957a470eca11da",
)
maven_jar(
name = "jetty-util",
artifact = "org.eclipse.jetty:jetty-util:" + JETTY_VERS,
- sha1 = "efefd29006dcc9c9960a679263504287ce4e6896",
+ sha1 = "c88807f210ab216aa831b48569ef50bd797384bc",
)
maven_jar(
diff --git a/java/com/google/gerrit/httpd/restapi/RestApiServlet.java b/java/com/google/gerrit/httpd/restapi/RestApiServlet.java
index 0e525ce..51e032a 100644
--- a/java/com/google/gerrit/httpd/restapi/RestApiServlet.java
+++ b/java/com/google/gerrit/httpd/restapi/RestApiServlet.java
@@ -1348,7 +1348,7 @@
TemporaryBuffer.Heap buf = heap(HEAP_EST_SIZE, Integer.MAX_VALUE);
buf.write(JSON_MAGIC);
Writer w = new BufferedWriter(new OutputStreamWriter(buf, UTF_8));
- Gson gson = newGson(config, req);
+ Gson gson = newGson(config);
if (result instanceof JsonElement) {
gson.toJson((JsonElement) result, w);
} else {
@@ -1375,25 +1375,18 @@
req, res, asBinaryResult(buf).setContentType(JSON_TYPE).setCharacterEncoding(UTF_8));
}
- private static Gson newGson(
- ListMultimap<String, String> config, @Nullable HttpServletRequest req) {
+ private static Gson newGson(ListMultimap<String, String> config) {
GsonBuilder gb = OutputFormat.JSON_COMPACT.newGsonBuilder();
- enablePrettyPrint(gb, config, req);
+ enablePrettyPrint(gb, config);
enablePartialGetFields(gb, config);
return gb.create();
}
- private static void enablePrettyPrint(
- GsonBuilder gb, ListMultimap<String, String> config, @Nullable HttpServletRequest req) {
- String pp = Iterables.getFirst(config.get("pp"), null);
- if (pp == null) {
- pp = Iterables.getFirst(config.get("prettyPrint"), null);
- if (pp == null && req != null) {
- pp = acceptsJson(req) ? "0" : "1";
- }
- }
+ private static void enablePrettyPrint(GsonBuilder gb, ListMultimap<String, String> config) {
+ String pp =
+ Iterables.getFirst(config.get("pp"), Iterables.getFirst(config.get("prettyPrint"), "0"));
if ("1".equals(pp) || "true".equals(pp)) {
gb.setPrettyPrinting();
}
@@ -1903,10 +1896,6 @@
return CharMatcher.anyOf("<&").matchesAnyOf(text);
}
- private static boolean acceptsJson(HttpServletRequest req) {
- return req != null && isType(JSON_TYPE, req.getHeader(HttpHeaders.ACCEPT));
- }
-
private static boolean acceptsGzip(HttpServletRequest req) {
if (req != null) {
String accepts = req.getHeader(HttpHeaders.ACCEPT_ENCODING);
diff --git a/java/com/google/gerrit/pgm/init/InitJGitConfig.java b/java/com/google/gerrit/pgm/init/InitJGitConfig.java
new file mode 100644
index 0000000..6e37f7f
--- /dev/null
+++ b/java/com/google/gerrit/pgm/init/InitJGitConfig.java
@@ -0,0 +1,102 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.pgm.init;
+
+import static com.google.gerrit.pgm.init.api.InitUtil.die;
+
+import com.google.gerrit.pgm.init.api.ConsoleUI;
+import com.google.gerrit.pgm.init.api.InitStep;
+import com.google.gerrit.server.config.SitePaths;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+import java.io.IOException;
+import org.eclipse.jgit.errors.ConfigInvalidException;
+import org.eclipse.jgit.lib.ConfigConstants;
+import org.eclipse.jgit.storage.file.FileBasedConfig;
+import org.eclipse.jgit.transport.TransferConfig;
+import org.eclipse.jgit.util.FS;
+
+/** Initialize the JGit configuration. */
+@Singleton
+class InitJGitConfig implements InitStep {
+ private final ConsoleUI ui;
+ private final SitePaths sitePaths;
+
+ @Inject
+ InitJGitConfig(ConsoleUI ui, SitePaths sitePaths) {
+ this.ui = ui;
+ this.sitePaths = sitePaths;
+ }
+
+ @Override
+ public void run() {
+ ui.header("JGit Configuration");
+ FileBasedConfig jgitConfig = new FileBasedConfig(sitePaths.jgit_config.toFile(), FS.DETECTED);
+ try {
+ jgitConfig.load();
+ if (!jgitConfig
+ .getNames(ConfigConstants.CONFIG_RECEIVE_SECTION)
+ .contains(ConfigConstants.CONFIG_KEY_AUTOGC)) {
+ jgitConfig.setBoolean(
+ ConfigConstants.CONFIG_RECEIVE_SECTION, null, ConfigConstants.CONFIG_KEY_AUTOGC, false);
+ jgitConfig.save();
+ ui.error(
+ "Auto-configured \"receive.autogc = false\" to disable auto-gc after git-receive-pack.");
+ } else if (jgitConfig.getBoolean(
+ ConfigConstants.CONFIG_RECEIVE_SECTION, ConfigConstants.CONFIG_KEY_AUTOGC, true)) {
+ ui.error(
+ "WARNING: JGit option \"receive.autogc = true\". This is not recommended in Gerrit.\n"
+ + "git-receive-pack will run auto gc after receiving data from "
+ + "git-push and updating refs.\n"
+ + "Disable this behavior to avoid the additional load it creates: "
+ + "gc should be configured in gc config section or run as a separate process.");
+ }
+
+ if (!jgitConfig
+ .getNames(ConfigConstants.CONFIG_PROTOCOL_SECTION)
+ .contains(ConfigConstants.CONFIG_KEY_VERSION)) {
+ jgitConfig.setString(
+ ConfigConstants.CONFIG_PROTOCOL_SECTION,
+ null,
+ ConfigConstants.CONFIG_KEY_VERSION,
+ TransferConfig.ProtocolVersion.V2.version());
+ jgitConfig.save();
+ ui.error(
+ String.format(
+ "Auto-configured \"%s.%s = %s\" to activate git wire protocol version 2.",
+ ConfigConstants.CONFIG_PROTOCOL_SECTION,
+ ConfigConstants.CONFIG_KEY_VERSION,
+ TransferConfig.ProtocolVersion.V2.version()));
+ } else {
+ String version =
+ jgitConfig.getString(
+ ConfigConstants.CONFIG_PROTOCOL_SECTION, null, ConfigConstants.CONFIG_KEY_VERSION);
+ if (!TransferConfig.ProtocolVersion.V2.version().equals(version)) {
+ ui.error(
+ String.format(
+ "HINT: JGit option \"%s.%s = %s\". It's recommended to activate git\n"
+ + "wire protocol version 2 to improve git fetch performance.",
+ ConfigConstants.CONFIG_PROTOCOL_SECTION,
+ ConfigConstants.CONFIG_KEY_VERSION,
+ version));
+ }
+ }
+ } catch (IOException e) {
+ throw die(String.format("Handling JGit configuration %s failed", sitePaths.jgit_config), e);
+ } catch (ConfigInvalidException e) {
+ throw die(String.format("Invalid JGit configuration %s", sitePaths.jgit_config), e);
+ }
+ }
+}
diff --git a/java/com/google/gerrit/pgm/init/InitModule.java b/java/com/google/gerrit/pgm/init/InitModule.java
index b658675..32c6697 100644
--- a/java/com/google/gerrit/pgm/init/InitModule.java
+++ b/java/com/google/gerrit/pgm/init/InitModule.java
@@ -40,6 +40,7 @@
// Steps are executed in the order listed here.
//
step().to(InitGitManager.class);
+ step().to(InitJGitConfig.class);
step().to(InitLogging.class);
step().to(InitIndex.class);
step().to(InitAuth.class);
diff --git a/java/com/google/gerrit/server/cache/serialize/entities/StoredCommentLinkInfoSerializer.java b/java/com/google/gerrit/server/cache/serialize/entities/StoredCommentLinkInfoSerializer.java
index d7bd373..a7a84f7 100644
--- a/java/com/google/gerrit/server/cache/serialize/entities/StoredCommentLinkInfoSerializer.java
+++ b/java/com/google/gerrit/server/cache/serialize/entities/StoredCommentLinkInfoSerializer.java
@@ -19,6 +19,7 @@
import com.google.gerrit.entities.StoredCommentLinkInfo;
import com.google.gerrit.server.cache.proto.Cache;
+import java.util.Optional;
/** Helper to (de)serialize values for caches. */
public class StoredCommentLinkInfoSerializer {
@@ -38,7 +39,7 @@
.setMatch(nullToEmpty(autoValue.getMatch()))
.setLink(nullToEmpty(autoValue.getLink()))
.setHtml(nullToEmpty(autoValue.getHtml()))
- .setEnabled(autoValue.getEnabled())
+ .setEnabled(Optional.ofNullable(autoValue.getEnabled()).orElse(true))
.setOverrideOnly(autoValue.getOverrideOnly())
.build();
}
diff --git a/java/com/google/gerrit/server/git/receive/ReceiveCommits.java b/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
index fb8a9d3..6992cd0 100644
--- a/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
+++ b/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
@@ -25,7 +25,7 @@
import static com.google.gerrit.server.change.HashtagsUtil.cleanupHashtag;
import static com.google.gerrit.server.git.MultiProgressMonitor.UNKNOWN;
import static com.google.gerrit.server.git.receive.ReceiveConstants.COMMAND_REJECTION_MESSAGE_FOOTER;
-import static com.google.gerrit.server.git.receive.ReceiveConstants.ONLY_CHANGE_OWNER_OR_PROJECT_OWNER_CAN_MODIFY_WIP;
+import static com.google.gerrit.server.git.receive.ReceiveConstants.ONLY_USERS_WITH_TOGGLE_WIP_STATE_PERM_CAN_MODIFY_WIP;
import static com.google.gerrit.server.git.receive.ReceiveConstants.PUSH_OPTION_SKIP_VALIDATION;
import static com.google.gerrit.server.git.receive.ReceiveConstants.SAME_CHANGE_ID_IN_MULTIPLE_CHANGES;
import static com.google.gerrit.server.git.validators.CommitValidators.NEW_PATCHSET_PATTERN;
@@ -2883,9 +2883,9 @@
if (!hasWriteConfigPermission) {
try {
- permissionBackend.user(user).check(GlobalPermission.ADMINISTRATE_SERVER);
+ permissions.change(notes).check(ChangePermission.TOGGLE_WORK_IN_PROGRESS_STATE);
} catch (AuthException e1) {
- reject(inputCommand, ONLY_CHANGE_OWNER_OR_PROJECT_OWNER_CAN_MODIFY_WIP);
+ reject(inputCommand, ONLY_USERS_WITH_TOGGLE_WIP_STATE_PERM_CAN_MODIFY_WIP);
}
}
}
diff --git a/java/com/google/gerrit/server/git/receive/ReceiveConstants.java b/java/com/google/gerrit/server/git/receive/ReceiveConstants.java
index 03a1b33..df1888b 100644
--- a/java/com/google/gerrit/server/git/receive/ReceiveConstants.java
+++ b/java/com/google/gerrit/server/git/receive/ReceiveConstants.java
@@ -20,8 +20,8 @@
public static final String PUSH_OPTION_SKIP_VALIDATION = "skip-validation";
@VisibleForTesting
- public static final String ONLY_CHANGE_OWNER_OR_PROJECT_OWNER_CAN_MODIFY_WIP =
- "only change owner or project owner can modify Work-in-Progress";
+ public static final String ONLY_USERS_WITH_TOGGLE_WIP_STATE_PERM_CAN_MODIFY_WIP =
+ "only users with Toogle-Wip-State permission can modify Work-in-Progress";
static final String COMMAND_REJECTION_MESSAGE_FOOTER =
"Contact an administrator to fix the permissions";
diff --git a/javatests/com/google/gerrit/acceptance/git/AbstractPushForReview.java b/javatests/com/google/gerrit/acceptance/git/AbstractPushForReview.java
index c9b0a9f..a50bbcf 100644
--- a/javatests/com/google/gerrit/acceptance/git/AbstractPushForReview.java
+++ b/javatests/com/google/gerrit/acceptance/git/AbstractPushForReview.java
@@ -899,7 +899,19 @@
GitUtil.fetch(user2Repo, r.getPatchSet().refName() + ":ps");
user2Repo.reset("ps");
r = amendChange(r.getChangeId(), "refs/for/master%ready", user2, user2Repo);
- r.assertErrorStatus(ReceiveConstants.ONLY_CHANGE_OWNER_OR_PROJECT_OWNER_CAN_MODIFY_WIP);
+ r.assertErrorStatus(ReceiveConstants.ONLY_USERS_WITH_TOGGLE_WIP_STATE_PERM_CAN_MODIFY_WIP);
+
+ // Non owner, non admin and non project owner with toggleWipState should succeed.
+ projectOperations
+ .project(project)
+ .forUpdate()
+ .add(
+ allow(Permission.TOGGLE_WORK_IN_PROGRESS_STATE)
+ .ref(RefNames.REFS_HEADS + "*")
+ .group(REGISTERED_USERS))
+ .update();
+ r = amendChange(r.getChangeId(), "refs/for/master%ready", user2, user2Repo);
+ r.assertOkStatus();
// Project owner trying to move from WIP to ready should succeed.
projectOperations
diff --git a/javatests/com/google/gerrit/acceptance/rest/RestApiServletIT.java b/javatests/com/google/gerrit/acceptance/rest/RestApiServletIT.java
new file mode 100644
index 0000000..bc45460
--- /dev/null
+++ b/javatests/com/google/gerrit/acceptance/rest/RestApiServletIT.java
@@ -0,0 +1,76 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.acceptance.rest;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.apache.http.HttpStatus.SC_OK;
+
+import com.google.gerrit.acceptance.AbstractDaemonTest;
+import com.google.gerrit.acceptance.RestResponse;
+import com.google.gerrit.httpd.restapi.RestApiServlet;
+import java.io.IOException;
+import java.util.regex.Pattern;
+import org.apache.http.message.BasicHeader;
+import org.junit.Test;
+
+public class RestApiServletIT extends AbstractDaemonTest {
+ private static String ANY_REST_API = "/accounts/self/capabilities";
+ private static BasicHeader ACCEPT_STAR_HEADER = new BasicHeader("Accept", "*/*");
+ private static Pattern ANY_SPACE = Pattern.compile("\\s");
+
+ @Test
+ public void restResponseBodyShouldBeCompactWithoutSpaces() throws Exception {
+ RestResponse response = adminRestSession.getWithHeader(ANY_REST_API, ACCEPT_STAR_HEADER);
+ assertThat(response.getStatusCode()).isEqualTo(SC_OK);
+
+ assertThat(contentWithoutMagicJson(response)).doesNotContainMatch(ANY_SPACE);
+ }
+
+ @Test
+ public void restResponseBodyShouldBeCompactWithoutSpacesWhenPPIsZero() throws Exception {
+ assertThat(contentWithoutMagicJson(prettyJsonRestResponse("prettyPrint", 0)))
+ .doesNotContainMatch(ANY_SPACE);
+ }
+
+ @Test
+ public void restResponseBodyShouldBeCompactWithoutSpacesWhenPrerryPrintIsZero() throws Exception {
+ assertThat(contentWithoutMagicJson(prettyJsonRestResponse("pp", 0)))
+ .doesNotContainMatch(ANY_SPACE);
+ }
+
+ @Test
+ public void restResponseBodyShouldBePrettyfiedWhenPPIsOne() throws Exception {
+ assertThat(contentWithoutMagicJson(prettyJsonRestResponse("pp", 1))).containsMatch(ANY_SPACE);
+ }
+
+ @Test
+ public void restResponseBodyShouldBePrettyfiedWhenPrettyPrintIsOne() throws Exception {
+ assertThat(contentWithoutMagicJson(prettyJsonRestResponse("prettyPrint", 1)))
+ .containsMatch(ANY_SPACE);
+ }
+
+ private RestResponse prettyJsonRestResponse(String ppArgument, int ppValue) throws Exception {
+ RestResponse response =
+ adminRestSession.getWithHeader(
+ ANY_REST_API + "?" + ppArgument + "=" + ppValue, ACCEPT_STAR_HEADER);
+ assertThat(response.getStatusCode()).isEqualTo(SC_OK);
+
+ return response;
+ }
+
+ private String contentWithoutMagicJson(RestResponse response) throws IOException {
+ return response.getEntityContent().substring(RestApiServlet.JSON_MAGIC.length);
+ }
+}
diff --git a/javatests/com/google/gerrit/server/cache/serialize/entities/StoredCommentLinkInfoSerializerTest.java b/javatests/com/google/gerrit/server/cache/serialize/entities/StoredCommentLinkInfoSerializerTest.java
index 3a51b70..e293493 100644
--- a/javatests/com/google/gerrit/server/cache/serialize/entities/StoredCommentLinkInfoSerializerTest.java
+++ b/javatests/com/google/gerrit/server/cache/serialize/entities/StoredCommentLinkInfoSerializerTest.java
@@ -56,4 +56,19 @@
.build();
assertThat(deserialize(serialize(autoValue))).isEqualTo(autoValue);
}
+
+ @Test
+ public void nullEnabled_roundTrip() {
+ StoredCommentLinkInfo sourceAutoValue =
+ StoredCommentLinkInfo.builder("name").setLink("<p>html").setMatch("*").build();
+
+ StoredCommentLinkInfo storedAutoValue =
+ StoredCommentLinkInfo.builder("name")
+ .setLink("<p>html")
+ .setMatch("*")
+ .setEnabled(true)
+ .build();
+
+ assertThat(deserialize(serialize(sourceAutoValue))).isEqualTo(storedAutoValue);
+ }
}
diff --git a/modules/jgit b/modules/jgit
index 5cd485e..9a1065a 160000
--- a/modules/jgit
+++ b/modules/jgit
@@ -1 +1 @@
-Subproject commit 5cd485e5dda41d2ef06226a692c64f1aa221eb25
+Subproject commit 9a1065afec18c5a76d3a95e77aa70d7a24252056
diff --git a/polygerrit-ui/app/elements/gr-app-element_html.ts b/polygerrit-ui/app/elements/gr-app-element_html.ts
index b978ed8..e1fe637 100644
--- a/polygerrit-ui/app/elements/gr-app-element_html.ts
+++ b/polygerrit-ui/app/elements/gr-app-element_html.ts
@@ -40,6 +40,8 @@
border-left: 0;
border-top: 0;
box-shadow: var(--header-box-shadow);
+ /* Make sure the header is above the main content, to preserve box-shadow visibility */
+ z-index: 1;
}
footer {
background: var(