Merge branch 'stable-3.3' into master
* stable-3.3: (33 commits) Update git submodules Update git submodules Add z-index to gr-main-header Compact the REST-API output JSON unconditionally Remove requesting DETAILED_LABELS for the dashboard Update git submodules Honor toogleWipState permission for %ready %wip push options Update JGit to 9a1065afe Update JGit to 8f422e9a9 Update JGit to c9d871f15 Update JGit to 5.3.9.202012012026-r Update JGit to 5.1.15.202012011955-r Set version to 3.3.1-SNAPSHOT Set version to 3.3.0 Auto-enable git wire protocol v2 in jgit Fix NPE with StoredCommentLinkInfoSerializer when enabled is null Auto-disable auto gc in jgit Bump up jetty version to 9.4.33.v20201020 Update zero-downtime documentation in config-gerrit.txt Improve message if submit fails due to non-fulfilled submit requirements Upgrade JGit to d1801402 Upgrade JGit to ad902087 Upgrade JGit to 5cd485e5 Upgrade JGit to 5.3.8.202011260953-r Include repo config into CommitReceivedEvent MergeValidationListener: Also provide RevWalk to the onPreMerge method Add fatal to consistency and validation error enums Upgrade JGit to 5.1.14.202011251942-r Fix flaky test for group renaming in ProjectConfig ProjectConfig: Write resolved groups to file Fix bazel run_shell usage for newer versions Use strict equality Add a warning if submitting a change with an open change edit Change-Id: I87c8a326f41fd9622034206fa512548380dc666a
This commit is contained in:
		@@ -2336,8 +2336,8 @@ Defaults to the full hostname of the Gerrit server.
 | 
			
		||||
[[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 @@ of the following steps:
 | 
			
		||||
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 @@ Supported versions:
 | 
			
		||||
 | 
			
		||||
[[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
 | 
			
		||||
------
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										16
									
								
								WORKSPACE
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								WORKSPACE
									
									
									
									
									
								
							@@ -899,48 +899,48 @@ maven_jar(
 | 
			
		||||
    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(
 | 
			
		||||
 
 | 
			
		||||
@@ -1348,7 +1348,7 @@ public class RestApiServlet extends HttpServlet {
 | 
			
		||||
    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 @@ public class RestApiServlet extends HttpServlet {
 | 
			
		||||
        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 @@ public class RestApiServlet extends HttpServlet {
 | 
			
		||||
    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);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										102
									
								
								java/com/google/gerrit/pgm/init/InitJGitConfig.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								java/com/google/gerrit/pgm/init/InitJGitConfig.java
									
									
									
									
									
										Normal file
									
								
							@@ -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);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -40,6 +40,7 @@ public class InitModule extends FactoryModule {
 | 
			
		||||
    // 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);
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,7 @@ import static com.google.common.base.Strings.nullToEmpty;
 | 
			
		||||
 | 
			
		||||
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 @@ public class StoredCommentLinkInfoSerializer {
 | 
			
		||||
        .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();
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@ import static com.google.gerrit.git.ObjectIds.abbreviateName;
 | 
			
		||||
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 @@ class ReceiveCommits {
 | 
			
		||||
 | 
			
		||||
        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);
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 
 | 
			
		||||
@@ -20,8 +20,8 @@ public final class ReceiveConstants {
 | 
			
		||||
  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";
 | 
			
		||||
 
 | 
			
		||||
@@ -899,7 +899,19 @@ public abstract class AbstractPushForReview extends AbstractDaemonTest {
 | 
			
		||||
    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
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -56,4 +56,19 @@ public class StoredCommentLinkInfoSerializerTest {
 | 
			
		||||
            .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);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
 Submodule modules/jgit updated: 5cd485e5dd...9a1065afec
									
								
							@@ -40,6 +40,8 @@ export const htmlTemplate = html`
 | 
			
		||||
      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(
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user