Merge "Minor change to how Lit 3.0 will work."
diff --git a/java/com/google/gerrit/server/account/externalids/ExternalIdCacheLoader.java b/java/com/google/gerrit/server/account/externalids/ExternalIdCacheLoader.java
index 1edb284..8b53d70 100644
--- a/java/com/google/gerrit/server/account/externalids/ExternalIdCacheLoader.java
+++ b/java/com/google/gerrit/server/account/externalids/ExternalIdCacheLoader.java
@@ -43,7 +43,9 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
 import org.eclipse.jgit.errors.ConfigInvalidException;
+import org.eclipse.jgit.lib.AnyObjectId;
 import org.eclipse.jgit.lib.Config;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.ObjectReader;
@@ -184,8 +186,17 @@
         }
       }
 
-      AllExternalIds allExternalIds =
-          buildAllExternalIds(repo, oldExternalIds, additions, removals);
+      AllExternalIds allExternalIds;
+      try {
+        allExternalIds = buildAllExternalIds(repo, oldExternalIds, additions, removals);
+      } catch (IllegalArgumentException e) {
+        Set<String> additionKeys =
+            additions.keySet().stream().map(AnyObjectId::getName).collect(Collectors.toSet());
+        logger.atSevere().withCause(e).log(
+            "Failed to load external ID cache. Repository ref is %s, cache ref is %s, additions are %s",
+            extIdRef.getObjectId().getName(), parentWithCacheValue.getId().getName(), additionKeys);
+        throw e;
+      }
       reloadCounter.increment(true);
       reloadDifferential.record(System.nanoTime() - start, TimeUnit.NANOSECONDS);
       return allExternalIds;
diff --git a/java/com/google/gerrit/server/change/ChangeJson.java b/java/com/google/gerrit/server/change/ChangeJson.java
index 4875978..e6fc4e7 100644
--- a/java/com/google/gerrit/server/change/ChangeJson.java
+++ b/java/com/google/gerrit/server/change/ChangeJson.java
@@ -446,7 +446,8 @@
         Joiner.on('~')
             .join(Url.encode(info.project), Url.encode(info.branch), Url.encode(info.changeId));
     if (experimentFeatures.isFeatureEnabled(
-        ExperimentFeaturesConstants.GERRIT_BACKEND_FEATURE_RETURN_NEW_CHANGE_INFO_ID)) {
+        ExperimentFeaturesConstants.GERRIT_BACKEND_FEATURE_RETURN_NEW_CHANGE_INFO_ID,
+        Project.nameKey(info.project))) {
       info.id =
           Joiner.on('~').join(Url.encode(info.project), Url.encode(String.valueOf(info._number)));
     } else {
diff --git a/java/com/google/gerrit/server/project/ProjectState.java b/java/com/google/gerrit/server/project/ProjectState.java
index 9899a6d..a3f8009 100644
--- a/java/com/google/gerrit/server/project/ProjectState.java
+++ b/java/com/google/gerrit/server/project/ProjectState.java
@@ -476,19 +476,19 @@
    * {@code PluginConfig#withInheritance(ProjectState.Factory)}
    */
   public PluginConfig getPluginConfig(String pluginName) {
-    if (getConfig().getPluginConfigs().containsKey(pluginName)) {
-      Config config = new Config();
+    Config config = new Config();
+    String cachedPluginConfig = getConfig().getPluginConfigs().get(pluginName);
+    if (cachedPluginConfig != null) {
       try {
-        config.fromText(getConfig().getPluginConfigs().get(pluginName));
+        config.fromText(cachedPluginConfig);
       } catch (ConfigInvalidException e) {
         // This is OK to propagate as IllegalStateException because it's a programmer error.
         // The config was converted to a String using Config#toText. So #fromText must not
         // throw a ConfigInvalidException
         throw new IllegalStateException("invalid plugin config for " + pluginName, e);
       }
-      return PluginConfig.create(pluginName, config, getConfig());
     }
-    return PluginConfig.create(pluginName, new Config(), getConfig());
+    return PluginConfig.create(pluginName, config, getConfig());
   }
 
   public Optional<BranchOrderSection> getBranchOrderSection() {
diff --git a/java/com/google/gerrit/server/query/change/OutputStreamQuery.java b/java/com/google/gerrit/server/query/change/OutputStreamQuery.java
index 716cf10..961404a 100644
--- a/java/com/google/gerrit/server/query/change/OutputStreamQuery.java
+++ b/java/com/google/gerrit/server/query/change/OutputStreamQuery.java
@@ -30,7 +30,6 @@
 import com.google.gerrit.index.query.QueryResult;
 import com.google.gerrit.server.DynamicOptions;
 import com.google.gerrit.server.account.AccountAttributeLoader;
-import com.google.gerrit.server.cache.PerThreadCache;
 import com.google.gerrit.server.config.TrackingFooters;
 import com.google.gerrit.server.data.ChangeAttribute;
 import com.google.gerrit.server.data.PatchSetAttribute;
@@ -211,7 +210,7 @@
         return;
       }
 
-      try (PerThreadCache ignored = PerThreadCache.create()) {
+      try {
         final QueryStatsAttribute stats = new QueryStatsAttribute();
         stats.runTimeMilliseconds = TimeUtil.nowMs();
 
diff --git a/java/com/google/gerrit/sshd/SshCommand.java b/java/com/google/gerrit/sshd/SshCommand.java
index 9df263b..a4e427d 100644
--- a/java/com/google/gerrit/sshd/SshCommand.java
+++ b/java/com/google/gerrit/sshd/SshCommand.java
@@ -23,6 +23,7 @@
 import com.google.gerrit.server.InvalidDeadlineException;
 import com.google.gerrit.server.RequestInfo;
 import com.google.gerrit.server.RequestListener;
+import com.google.gerrit.server.cache.PerThreadCache;
 import com.google.gerrit.server.cancellation.RequestCancelledException;
 import com.google.gerrit.server.cancellation.RequestStateContext;
 import com.google.gerrit.server.config.GerritServerConfig;
@@ -62,7 +63,8 @@
   public void start(ChannelSession channel, Environment env) throws IOException {
     startThread(
         () -> {
-          try (DynamicOptions pluginOptions = new DynamicOptions(injector, dynamicBeans)) {
+          try (PerThreadCache ignored = PerThreadCache.create();
+              DynamicOptions pluginOptions = new DynamicOptions(injector, dynamicBeans)) {
             parseCommandLine(pluginOptions);
             stdout = toPrintWriter(out);
             stderr = toPrintWriter(err);
diff --git a/modules/jgit b/modules/jgit
index 5ae8d28..74fa245 160000
--- a/modules/jgit
+++ b/modules/jgit
@@ -1 +1 @@
-Subproject commit 5ae8d28faaf6168921f673c89a4e6d601ffad78d
+Subproject commit 74fa245b3c3ccf13afcbec7911c7c8459e48527d
diff --git a/polygerrit-ui/app/BUILD b/polygerrit-ui/app/BUILD
index 6df4456..925820c 100644
--- a/polygerrit-ui/app/BUILD
+++ b/polygerrit-ui/app/BUILD
@@ -180,9 +180,9 @@
             "**/*_test.ts",
         ],
     ) + [
+        "@npm//typescript",
         "@ui_dev_npm//:node_modules",
         "@ui_npm//:node_modules",
-        "@npm//typescript",
     ],
 )
 
diff --git a/polygerrit-ui/app/elements/shared/gr-account-list/gr-account-list.ts b/polygerrit-ui/app/elements/shared/gr-account-list/gr-account-list.ts
index 8339df9..07209db 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-list/gr-account-list.ts
+++ b/polygerrit-ui/app/elements/shared/gr-account-list/gr-account-list.ts
@@ -36,6 +36,7 @@
 import {PaperInputElement} from '@polymer/paper-input/paper-input';
 import {IronInputElement} from '@polymer/iron-input';
 import {ReviewerState} from '../../../api/rest-api';
+import {repeat} from 'lit/directives/repeat.js';
 
 const VALID_EMAIL_ALERT = 'Please input a valid email.';
 const VALID_USER_GROUP_ALERT = 'Please input a valid user or group.';
@@ -186,7 +187,9 @@
 
   override render() {
     return html`<div class="list">
-        ${this.accounts.map(
+        ${repeat(
+          this.accounts,
+          account => getUserId(account),
           account => html`
             <gr-account-chip
               .account=${account}
diff --git a/polygerrit-ui/app/embed/diff/gr-diff/gr-diff-group.ts b/polygerrit-ui/app/embed/diff/gr-diff/gr-diff-group.ts
index 2ec0a2e..6d80d78 100644
--- a/polygerrit-ui/app/embed/diff/gr-diff/gr-diff-group.ts
+++ b/polygerrit-ui/app/embed/diff/gr-diff/gr-diff-group.ts
@@ -428,7 +428,10 @@
 
   /** Returns true if it is, or contains, a skip group. */
   hasSkipGroup() {
-    return !!this.skip || this.contextGroups?.some(g => !!g.skip);
+    return (
+      this.skip !== undefined ||
+      this.contextGroups?.some(g => g.skip !== undefined)
+    );
   }
 
   containsLine(side: Side, line: LineNumber) {
@@ -444,7 +447,10 @@
     // For both CONTEXT_CONTROL groups and SKIP groups the `lines` array will
     // be empty. So we have to use `lineRange` instead of looking at the first
     // line.
-    if (this.type === GrDiffGroupType.CONTEXT_CONTROL || this.skip) {
+    if (
+      this.type === GrDiffGroupType.CONTEXT_CONTROL ||
+      this.skip !== undefined
+    ) {
       return side === Side.LEFT
         ? this.lineRange.left.start_line
         : this.lineRange.right.start_line;
@@ -498,7 +504,7 @@
     // The LOST or FILE lines may be hidden and thus never resolve an
     // untilRendered() promise.
     if (
-      this.skip ||
+      this.skip !== undefined ||
       lineNumber === 'LOST' ||
       lineNumber === 'FILE' ||
       this.type === GrDiffGroupType.CONTEXT_CONTROL
diff --git a/polygerrit-ui/app/embed/diff/gr-diff/gr-diff-group_test.ts b/polygerrit-ui/app/embed/diff/gr-diff/gr-diff-group_test.ts
index 06bf92920..7ead68f 100644
--- a/polygerrit-ui/app/embed/diff/gr-diff/gr-diff-group_test.ts
+++ b/polygerrit-ui/app/embed/diff/gr-diff/gr-diff-group_test.ts
@@ -284,6 +284,15 @@
       });
       assert.equal(group.startLine(Side.LEFT), 3);
       assert.equal(group.startLine(Side.RIGHT), 6);
+
+      const group2 = new GrDiffGroup({
+        type: GrDiffGroupType.BOTH,
+        skip: 0,
+        offsetLeft: 3,
+        offsetRight: 6,
+      });
+      assert.equal(group2.startLine(Side.LEFT), 3);
+      assert.equal(group2.startLine(Side.RIGHT), 6);
     });
 
     test('FILE', () => {
diff --git a/tools/deps.bzl b/tools/deps.bzl
index 4c21ae6..7d4499a 100644
--- a/tools/deps.bzl
+++ b/tools/deps.bzl
@@ -20,7 +20,7 @@
 # When updating Bouncy Castle, also update it in bazlets.
 BC_VERS = "1.72"
 HTTPCOMP_VERS = "4.5.2"
-JETTY_VERS = "9.4.49.v20220914"
+JETTY_VERS = "9.4.51.v20230217"
 BYTE_BUDDY_VERSION = "1.10.7"
 
 def java_dependencies():
@@ -121,8 +121,8 @@
     # When upgrading commons-compress, also upgrade tukaani-xz
     maven_jar(
         name = "commons-compress",
-        artifact = "org.apache.commons:commons-compress:1.20",
-        sha1 = "b8df472b31e1f17c232d2ad78ceb1c84e00c641b",
+        artifact = "org.apache.commons:commons-compress:1.22",
+        sha1 = "691a8b4e6cf4248c3bc72c8b719337d5cb7359fa",
     )
 
     maven_jar(
@@ -626,50 +626,50 @@
     maven_jar(
         name = "jetty-servlet",
         artifact = "org.eclipse.jetty:jetty-servlet:" + JETTY_VERS,
-        sha1 = "53ca0898f02e72b6830551031ee0062430134a05",
+        sha1 = "3ec1be0b1ca49b633dd7de0733d0054bb4763965",
     )
 
     maven_jar(
         name = "jetty-security",
         artifact = "org.eclipse.jetty:jetty-security:" + JETTY_VERS,
-        sha1 = "057a67eeb12078b620131664b3b7a37ea4c5aefe",
+        sha1 = "a3342214ce480cc5bb8e74fe7589dd0436a5d903",
     )
 
     maven_jar(
         name = "jetty-server",
         artifact = "org.eclipse.jetty:jetty-server:" + JETTY_VERS,
-        sha1 = "502f99eed028139e71a4afebefa291ace12b9c1c",
+        sha1 = "d0572c8460eb26adf8420e78535d95859c89a936",
     )
 
     maven_jar(
         name = "jetty-jmx",
         artifact = "org.eclipse.jetty:jetty-jmx:" + JETTY_VERS,
-        sha1 = "5e24afaedcc746f03fb0f60e6c0bdb2af6e6c9e8",
+        sha1 = "a69e9b0a223a5f661606f6fb36d3b3fcf6216432",
     )
 
     maven_jar(
         name = "jetty-http",
         artifact = "org.eclipse.jetty:jetty-http:" + JETTY_VERS,
-        sha1 = "ef1e3bde212115eb4bb0740aaf79029b624d4e30",
+        sha1 = "fe37568aded59dd8e437e0f670fe5f809071fe8f",
     )
 
     maven_jar(
         name = "jetty-io",
         artifact = "org.eclipse.jetty:jetty-io:" + JETTY_VERS,
-        sha1 = "cb33d9a3bdb6e2173b9b9cfc94c0b45f9a21a1af",
+        sha1 = "a11a0713b17334a5b6e694602fbd1a9457cb5fdd",
     )
 
     maven_jar(
         name = "jetty-util",
         artifact = "org.eclipse.jetty:jetty-util:" + JETTY_VERS,
-        sha1 = "29008dbc6dfac553d209f54193b505d73c253a41",
+        sha1 = "a11df06530a3a28c9af7ff336730a2f8e18e7205",
     )
 
     maven_jar(
         name = "jetty-util-ajax",
         artifact = "org.eclipse.jetty:jetty-util-ajax:" + JETTY_VERS,
-        sha1 = "3b267b5ae59b7b826d5b579f2ee8b8914b286547",
-        src_sha1 = "adba851ccfbf5b2bece305d0f0bb9179852fbffb",
+        sha1 = "3b2a998a5ed1f93bc1878fa89d65e307d8b8ebaf",
+        src_sha1 = "027a15819d3fd1f18e1890bd1bf04b7d48cb3da4",
     )
 
     maven_jar(