Merge "Remove opt_ prefix"
diff --git a/Documentation/rest-api-changes.txt b/Documentation/rest-api-changes.txt
index d8a95ef..a35f508 100644
--- a/Documentation/rest-api-changes.txt
+++ b/Documentation/rest-api-changes.txt
@@ -1385,6 +1385,33 @@
The change could not be rebased due to a path conflict during merge.
----
+Rebasing a change is allowed for the change owner, users with the
+link:access-control.html#category_rebase[Rebase] permission and users
+with the link:access-control.html#category_submit[Submit] permission.
+
+In addition, the rebaser or the original uploader, if rebasing is done
+on behalf of the uploader (see `rebase_on_behalf_of_uploader` option in
+link:#rebase-input[RebaseInput]), needs to have all permissions that
+are required to create the new patch set:
+
+* the link:access-control.html#category_push[Push] permission
+* the link:access-control.html#category_add_patch_set[Add Patch Set]
+ permission (only if the user is not the change owner)
+* the link:access-control.html#category_forge_author[Forge Author]
+ permission (only if the commit author is forged)
+* the link:access-control.html#category_forge_server[Forge Server]
+ permission (only if the commit author is the server identity)
+
+The same permissions were required for the upload of the original patch
+set. This means if the rebase is done on behalf of the uploader these
+permission checks should just pass, unless the uploader lost
+permissions after the upload of the original patch set. In this case
+rebasing on behalf of the uploader is not possible and a normal rebase
+(on behalf of the rebaser) must be done, which means that the rebaser
+becomes the uploader and takes over the change. If self approvals are
+disallowed, this means that the rebaser can no longer approve the
+change (as approvals of the uploader are ignored).
+
[[rebase-chain]]
=== Rebase Chain
--
diff --git a/java/com/google/gerrit/acceptance/PushOneCommit.java b/java/com/google/gerrit/acceptance/PushOneCommit.java
index 5b1fa9b..9f38fcb 100644
--- a/java/com/google/gerrit/acceptance/PushOneCommit.java
+++ b/java/com/google/gerrit/acceptance/PushOneCommit.java
@@ -41,6 +41,7 @@
import com.google.inject.assistedinject.AssistedInject;
import java.util.Arrays;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import org.eclipse.jgit.api.TagCommand;
@@ -490,12 +491,14 @@
public void assertMessage(String expectedMessage) {
RemoteRefUpdate refUpdate = result.getRemoteUpdate(ref);
assertThat(refUpdate).isNotNull();
- assertThat(message(refUpdate).toLowerCase()).contains(expectedMessage.toLowerCase());
+ assertThat(message(refUpdate).toLowerCase(Locale.US))
+ .contains(expectedMessage.toLowerCase(Locale.US));
}
public void assertNotMessage(String message) {
RemoteRefUpdate refUpdate = result.getRemoteUpdate(ref);
- assertThat(message(refUpdate).toLowerCase()).doesNotContain(message.toLowerCase());
+ assertThat(message(refUpdate).toLowerCase(Locale.US))
+ .doesNotContain(message.toLowerCase(Locale.US));
}
public String getMessage() {
diff --git a/java/com/google/gerrit/common/data/GlobalCapability.java b/java/com/google/gerrit/common/data/GlobalCapability.java
index 0a42d09..c7a9a63 100644
--- a/java/com/google/gerrit/common/data/GlobalCapability.java
+++ b/java/com/google/gerrit/common/data/GlobalCapability.java
@@ -22,6 +22,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.List;
+import java.util.Locale;
/**
* Server wide capabilities. Represented as {@link Permission} objects.
@@ -162,7 +163,7 @@
NAMES_LC = new ArrayList<>(NAMES_ALL.size());
for (String name : NAMES_ALL) {
- NAMES_LC.add(name.toLowerCase());
+ NAMES_LC.add(name.toLowerCase(Locale.US));
}
}
@@ -173,7 +174,7 @@
/** Returns true if the name is recognized as a capability name. */
public static boolean isGlobalCapability(String varName) {
- return NAMES_LC.contains(varName.toLowerCase());
+ return NAMES_LC.contains(varName.toLowerCase(Locale.US));
}
/** Returns true if the capability should have a range attached. */
diff --git a/java/com/google/gerrit/common/data/ParameterizedString.java b/java/com/google/gerrit/common/data/ParameterizedString.java
index 84bb535..c8c2b2b 100644
--- a/java/com/google/gerrit/common/data/ParameterizedString.java
+++ b/java/com/google/gerrit/common/data/ParameterizedString.java
@@ -19,6 +19,7 @@
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
/** Performs replacements on strings such as <code>Hello ${user}</code>. */
@@ -213,7 +214,7 @@
new Function() {
@Override
String apply(String a) {
- return a.toLowerCase();
+ return a.toLowerCase(Locale.US);
}
});
m.put(
@@ -221,7 +222,7 @@
new Function() {
@Override
String apply(String a) {
- return a.toUpperCase();
+ return a.toUpperCase(Locale.US);
}
});
m.put(
diff --git a/java/com/google/gerrit/entities/EmailHeader.java b/java/com/google/gerrit/entities/EmailHeader.java
index e43b6a3..d3710c4 100644
--- a/java/com/google/gerrit/entities/EmailHeader.java
+++ b/java/com/google/gerrit/entities/EmailHeader.java
@@ -115,8 +115,8 @@
byte[] buf = new String(Character.toChars(cp)).getBytes(UTF_8);
for (byte b : buf) {
r.append('=');
- r.append(Integer.toHexString((b >>> 4) & 0x0f).toUpperCase());
- r.append(Integer.toHexString(b & 0x0f).toUpperCase());
+ r.append(Integer.toHexString((b >>> 4) & 0x0f).toUpperCase(Locale.US));
+ r.append(Integer.toHexString(b & 0x0f).toUpperCase(Locale.US));
}
} else {
diff --git a/java/com/google/gerrit/entities/LabelTypes.java b/java/com/google/gerrit/entities/LabelTypes.java
index a2f2e0b..fa7b741 100644
--- a/java/com/google/gerrit/entities/LabelTypes.java
+++ b/java/com/google/gerrit/entities/LabelTypes.java
@@ -19,6 +19,7 @@
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Optional;
@@ -38,11 +39,11 @@
}
public Optional<LabelType> byLabel(LabelId labelId) {
- return Optional.ofNullable(byLabel().get(labelId.get().toLowerCase()));
+ return Optional.ofNullable(byLabel().get(labelId.get().toLowerCase(Locale.US)));
}
public Optional<LabelType> byLabel(String labelName) {
- return Optional.ofNullable(byLabel().get(labelName.toLowerCase()));
+ return Optional.ofNullable(byLabel().get(labelName.toLowerCase(Locale.US)));
}
private Map<String, LabelType> byLabel() {
@@ -52,7 +53,7 @@
Map<String, LabelType> l = new HashMap<>();
if (labelTypes != null) {
for (LabelType t : labelTypes) {
- l.put(t.getName().toLowerCase(), t);
+ l.put(t.getName().toLowerCase(Locale.US), t);
}
}
byLabel = l;
diff --git a/java/com/google/gerrit/entities/Permission.java b/java/com/google/gerrit/entities/Permission.java
index 6a50711..2a34579 100644
--- a/java/com/google/gerrit/entities/Permission.java
+++ b/java/com/google/gerrit/entities/Permission.java
@@ -22,6 +22,7 @@
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
+import java.util.Locale;
import java.util.function.Consumer;
/** A single permission within an {@link AccessSection} of a project. */
@@ -64,37 +65,37 @@
static {
NAMES_LC = new ArrayList<>();
- NAMES_LC.add(ABANDON.toLowerCase());
- NAMES_LC.add(ADD_PATCH_SET.toLowerCase());
- NAMES_LC.add(CREATE.toLowerCase());
- NAMES_LC.add(CREATE_SIGNED_TAG.toLowerCase());
- NAMES_LC.add(CREATE_TAG.toLowerCase());
- NAMES_LC.add(DELETE.toLowerCase());
- NAMES_LC.add(DELETE_CHANGES.toLowerCase());
- NAMES_LC.add(DELETE_OWN_CHANGES.toLowerCase());
- NAMES_LC.add(EDIT_HASHTAGS.toLowerCase());
- NAMES_LC.add(EDIT_TOPIC_NAME.toLowerCase());
- NAMES_LC.add(FORGE_AUTHOR.toLowerCase());
- NAMES_LC.add(FORGE_COMMITTER.toLowerCase());
- NAMES_LC.add(FORGE_SERVER.toLowerCase());
- NAMES_LC.add(LABEL.toLowerCase());
- NAMES_LC.add(LABEL_AS.toLowerCase());
- NAMES_LC.add(REMOVE_LABEL.toLowerCase());
- NAMES_LC.add(OWNER.toLowerCase());
- NAMES_LC.add(PUSH.toLowerCase());
- NAMES_LC.add(PUSH_MERGE.toLowerCase());
- NAMES_LC.add(READ.toLowerCase());
- NAMES_LC.add(REBASE.toLowerCase());
- NAMES_LC.add(REMOVE_REVIEWER.toLowerCase());
- NAMES_LC.add(REVERT.toLowerCase());
- NAMES_LC.add(SUBMIT.toLowerCase());
- NAMES_LC.add(SUBMIT_AS.toLowerCase());
- NAMES_LC.add(TOGGLE_WORK_IN_PROGRESS_STATE.toLowerCase());
- NAMES_LC.add(VIEW_PRIVATE_CHANGES.toLowerCase());
+ NAMES_LC.add(ABANDON.toLowerCase(Locale.US));
+ NAMES_LC.add(ADD_PATCH_SET.toLowerCase(Locale.US));
+ NAMES_LC.add(CREATE.toLowerCase(Locale.US));
+ NAMES_LC.add(CREATE_SIGNED_TAG.toLowerCase(Locale.US));
+ NAMES_LC.add(CREATE_TAG.toLowerCase(Locale.US));
+ NAMES_LC.add(DELETE.toLowerCase(Locale.US));
+ NAMES_LC.add(DELETE_CHANGES.toLowerCase(Locale.US));
+ NAMES_LC.add(DELETE_OWN_CHANGES.toLowerCase(Locale.US));
+ NAMES_LC.add(EDIT_HASHTAGS.toLowerCase(Locale.US));
+ NAMES_LC.add(EDIT_TOPIC_NAME.toLowerCase(Locale.US));
+ NAMES_LC.add(FORGE_AUTHOR.toLowerCase(Locale.US));
+ NAMES_LC.add(FORGE_COMMITTER.toLowerCase(Locale.US));
+ NAMES_LC.add(FORGE_SERVER.toLowerCase(Locale.US));
+ NAMES_LC.add(LABEL.toLowerCase(Locale.US));
+ NAMES_LC.add(LABEL_AS.toLowerCase(Locale.US));
+ NAMES_LC.add(REMOVE_LABEL.toLowerCase(Locale.US));
+ NAMES_LC.add(OWNER.toLowerCase(Locale.US));
+ NAMES_LC.add(PUSH.toLowerCase(Locale.US));
+ NAMES_LC.add(PUSH_MERGE.toLowerCase(Locale.US));
+ NAMES_LC.add(READ.toLowerCase(Locale.US));
+ NAMES_LC.add(REBASE.toLowerCase(Locale.US));
+ NAMES_LC.add(REMOVE_REVIEWER.toLowerCase(Locale.US));
+ NAMES_LC.add(REVERT.toLowerCase(Locale.US));
+ NAMES_LC.add(SUBMIT.toLowerCase(Locale.US));
+ NAMES_LC.add(SUBMIT_AS.toLowerCase(Locale.US));
+ NAMES_LC.add(TOGGLE_WORK_IN_PROGRESS_STATE.toLowerCase(Locale.US));
+ NAMES_LC.add(VIEW_PRIVATE_CHANGES.toLowerCase(Locale.US));
LABEL_INDEX = NAMES_LC.indexOf(Permission.LABEL);
- LABEL_AS_INDEX = NAMES_LC.indexOf(Permission.LABEL_AS.toLowerCase());
- REMOVE_LABEL_INDEX = NAMES_LC.indexOf(Permission.REMOVE_LABEL.toLowerCase());
+ LABEL_AS_INDEX = NAMES_LC.indexOf(Permission.LABEL_AS.toLowerCase(Locale.US));
+ REMOVE_LABEL_INDEX = NAMES_LC.indexOf(Permission.REMOVE_LABEL.toLowerCase(Locale.US));
}
/** Returns true if the name is recognized as a permission name. */
@@ -102,7 +103,7 @@
return isLabel(varName)
|| isLabelAs(varName)
|| isRemoveLabel(varName)
- || NAMES_LC.contains(varName.toLowerCase());
+ || NAMES_LC.contains(varName.toLowerCase(Locale.US));
}
public static boolean hasRange(String varName) {
@@ -226,7 +227,7 @@
return REMOVE_LABEL_INDEX;
}
- int index = NAMES_LC.indexOf(a.getName().toLowerCase());
+ int index = NAMES_LC.indexOf(a.getName().toLowerCase(Locale.US));
return 0 <= index ? index : NAMES_LC.size();
}
diff --git a/java/com/google/gerrit/extensions/client/GerritTopMenu.java b/java/com/google/gerrit/extensions/client/GerritTopMenu.java
index b7e1a5a..b9a395e 100644
--- a/java/com/google/gerrit/extensions/client/GerritTopMenu.java
+++ b/java/com/google/gerrit/extensions/client/GerritTopMenu.java
@@ -14,6 +14,8 @@
package com.google.gerrit.extensions.client;
+import java.util.Locale;
+
public enum GerritTopMenu {
ALL,
MY,
@@ -25,6 +27,6 @@
public final String menuName;
GerritTopMenu() {
- menuName = name().substring(0, 1) + name().substring(1).toLowerCase();
+ menuName = name().substring(0, 1) + name().substring(1).toLowerCase(Locale.US);
}
}
diff --git a/java/com/google/gerrit/extensions/common/WebLinkInfo.java b/java/com/google/gerrit/extensions/common/WebLinkInfo.java
index eeed284..fbd8d2f 100644
--- a/java/com/google/gerrit/extensions/common/WebLinkInfo.java
+++ b/java/com/google/gerrit/extensions/common/WebLinkInfo.java
@@ -14,7 +14,6 @@
package com.google.gerrit.extensions.common;
-import com.google.errorprone.annotations.InlineMe;
import java.util.Objects;
public class WebLinkInfo {
@@ -23,12 +22,6 @@
public String imageUrl;
public String url;
- @InlineMe(replacement = "this(name, imageUrl, url)")
- @Deprecated
- public WebLinkInfo(String name, String imageUrl, String url, String target) {
- this(name, imageUrl, url);
- }
-
public WebLinkInfo(String name, String imageUrl, String url) {
this.name = name;
this.imageUrl = imageUrl;
diff --git a/java/com/google/gerrit/gpg/GerritPublicKeyChecker.java b/java/com/google/gerrit/gpg/GerritPublicKeyChecker.java
index 71dff97..fff4045 100644
--- a/java/com/google/gerrit/gpg/GerritPublicKeyChecker.java
+++ b/java/com/google/gerrit/gpg/GerritPublicKeyChecker.java
@@ -37,6 +37,7 @@
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
@@ -82,7 +83,7 @@
if (strs.length != 0) {
Map<Long, Fingerprint> fps = Maps.newHashMapWithExpectedSize(strs.length);
for (String str : strs) {
- str = CharMatcher.whitespace().removeFrom(str).toUpperCase();
+ str = CharMatcher.whitespace().removeFrom(str).toUpperCase(Locale.US);
Fingerprint fp = new Fingerprint(BaseEncoding.base16().decode(str));
fps.put(fp.getId(), fp);
}
diff --git a/java/com/google/gerrit/gpg/server/GpgKeys.java b/java/com/google/gerrit/gpg/server/GpgKeys.java
index b3a2f53..00a0f57 100644
--- a/java/com/google/gerrit/gpg/server/GpgKeys.java
+++ b/java/com/google/gerrit/gpg/server/GpgKeys.java
@@ -48,6 +48,7 @@
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.Locale;
import java.util.Map;
import org.bouncycastle.bcpg.ArmoredOutputStream;
import org.bouncycastle.openpgp.PGPException;
@@ -106,7 +107,7 @@
static ExternalId findGpgKey(String str, Iterable<ExternalId> existingExtIds)
throws ResourceNotFoundException {
- str = CharMatcher.whitespace().removeFrom(str).toUpperCase();
+ str = CharMatcher.whitespace().removeFrom(str).toUpperCase(Locale.US);
if ((str.length() != 8 && str.length() != 40)
|| !CharMatcher.anyOf("0123456789ABCDEF").matchesAllOf(str)) {
throw new ResourceNotFoundException(str);
diff --git a/java/com/google/gerrit/httpd/gitweb/GitwebServlet.java b/java/com/google/gerrit/httpd/gitweb/GitwebServlet.java
index e909701..d6718ca 100644
--- a/java/com/google/gerrit/httpd/gitweb/GitwebServlet.java
+++ b/java/com/google/gerrit/httpd/gitweb/GitwebServlet.java
@@ -79,6 +79,7 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
@@ -159,7 +160,7 @@
if (!_env.envMap.containsKey("SystemRoot")) {
String os = System.getProperty("os.name");
- if (os != null && os.toLowerCase().contains("windows")) {
+ if (os != null && os.toLowerCase(Locale.US).contains("windows")) {
String sysroot = System.getenv("SystemRoot");
if (sysroot == null || sysroot.isEmpty()) {
sysroot = "C:\\WINDOWS";
@@ -576,7 +577,7 @@
for (String name : getHeaderNames(req)) {
final String value = req.getHeader(name);
- env.set("HTTP_" + name.toUpperCase().replace('-', '_'), value);
+ env.set("HTTP_" + name.toUpperCase(Locale.US).replace('-', '_'), value);
}
Project.NameKey nameKey = projectState.getNameKey();
diff --git a/java/com/google/gerrit/index/IndexType.java b/java/com/google/gerrit/index/IndexType.java
index 75f8351..d8c8f6a 100644
--- a/java/com/google/gerrit/index/IndexType.java
+++ b/java/com/google/gerrit/index/IndexType.java
@@ -19,6 +19,7 @@
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableSet;
import com.google.gerrit.common.Nullable;
+import java.util.Locale;
import java.util.Optional;
/**
@@ -51,7 +52,7 @@
if (Strings.isNullOrEmpty(value)) {
return Optional.empty();
}
- value = value.toUpperCase().replace("-", "_");
+ value = value.toUpperCase(Locale.US).replace("-", "_");
IndexType type = new IndexType(value);
if (!Strings.isNullOrEmpty(System.getenv(ENV_VAR))) {
checkArgument(
@@ -67,7 +68,7 @@
}
public IndexType(@Nullable String type) {
- this.type = type == null ? getDefault() : type.toLowerCase();
+ this.type = type == null ? getDefault() : type.toLowerCase(Locale.US);
}
public static String getDefault() {
diff --git a/java/com/google/gerrit/index/IndexedField.java b/java/com/google/gerrit/index/IndexedField.java
index 99004bb..94943d6 100644
--- a/java/com/google/gerrit/index/IndexedField.java
+++ b/java/com/google/gerrit/index/IndexedField.java
@@ -36,6 +36,7 @@
import java.lang.reflect.Type;
import java.sql.Timestamp;
import java.util.HashMap;
+import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.stream.StreamSupport;
@@ -351,7 +352,8 @@
private static String checkName(String name) {
String allowedCharacters = "abcdefghijklmnopqrstuvwxyz0123456789_";
- CharMatcher m = CharMatcher.anyOf(allowedCharacters + allowedCharacters.toUpperCase());
+ CharMatcher m =
+ CharMatcher.anyOf(allowedCharacters + allowedCharacters.toUpperCase(Locale.US));
checkArgument(name != null && m.matchesAllOf(name), "illegal field name: %s", name);
return name;
}
diff --git a/java/com/google/gerrit/index/query/IndexPredicate.java b/java/com/google/gerrit/index/query/IndexPredicate.java
index de81c47..0bde640 100644
--- a/java/com/google/gerrit/index/query/IndexPredicate.java
+++ b/java/com/google/gerrit/index/query/IndexPredicate.java
@@ -23,6 +23,7 @@
import com.google.common.primitives.Longs;
import com.google.gerrit.index.FieldType;
import com.google.gerrit.index.SchemaFieldDefs.SchemaField;
+import java.util.Locale;
import java.util.Objects;
import java.util.Set;
import java.util.stream.StreamSupport;
@@ -117,7 +118,8 @@
}
private static ImmutableSet<String> tokenizeString(String value) {
- return StreamSupport.stream(FULL_TEXT_SPLITTER.split(value.toLowerCase()).spliterator(), false)
+ return StreamSupport.stream(
+ FULL_TEXT_SPLITTER.split(value.toLowerCase(Locale.US)).spliterator(), false)
.filter(s -> !s.trim().isEmpty())
.collect(toImmutableSet());
}
diff --git a/java/com/google/gerrit/launcher/GerritLauncher.java b/java/com/google/gerrit/launcher/GerritLauncher.java
index 6be78d9..8783593 100644
--- a/java/com/google/gerrit/launcher/GerritLauncher.java
+++ b/java/com/google/gerrit/launcher/GerritLauncher.java
@@ -44,6 +44,7 @@
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.NavigableMap;
import java.util.Properties;
@@ -195,7 +196,7 @@
String cn = programClassName(name);
clazz = Class.forName(PKG + "." + cn, true, loader);
} catch (ClassNotFoundException cnfe) {
- if (name.equals(name.toLowerCase())) {
+ if (name.equals(name.toLowerCase(Locale.US))) {
clazz = Class.forName(PKG + "." + name, true, loader);
} else {
throw cnfe;
@@ -239,7 +240,7 @@
}
private static String programClassName(String cn) {
- if (cn.equals(cn.toLowerCase())) {
+ if (cn.equals(cn.toLowerCase(Locale.US))) {
StringBuilder buf = new StringBuilder();
buf.append(Character.toUpperCase(cn.charAt(0)));
for (int i = 1; i < cn.length(); i++) {
diff --git a/java/com/google/gerrit/mail/RawMailParser.java b/java/com/google/gerrit/mail/RawMailParser.java
index 929e9f9..79d1cb8f 100644
--- a/java/com/google/gerrit/mail/RawMailParser.java
+++ b/java/com/google/gerrit/mail/RawMailParser.java
@@ -26,6 +26,7 @@
import java.io.IOException;
import java.io.InputStreamReader;
import java.time.Instant;
+import java.util.Locale;
import org.apache.james.mime4j.MimeException;
import org.apache.james.mime4j.dom.Entity;
import org.apache.james.mime4j.dom.Message;
@@ -90,7 +91,7 @@
// Add additional headers
mimeMessage.getHeader().getFields().stream()
- .filter(f -> !MAIN_HEADERS.contains(f.getName().toLowerCase()))
+ .filter(f -> !MAIN_HEADERS.contains(f.getName().toLowerCase(Locale.US)))
.forEach(f -> messageBuilder.addAdditionalHeader(f.getName() + ": " + f.getBody()));
// Add text and html body parts
diff --git a/java/com/google/gerrit/pgm/init/api/ConsoleUI.java b/java/com/google/gerrit/pgm/init/api/ConsoleUI.java
index 7666076..865f7d7 100644
--- a/java/com/google/gerrit/pgm/init/api/ConsoleUI.java
+++ b/java/com/google/gerrit/pgm/init/api/ConsoleUI.java
@@ -20,6 +20,7 @@
import com.google.gerrit.common.Nullable;
import java.io.Console;
import java.util.EnumSet;
+import java.util.Locale;
import java.util.Set;
/** Console based interaction with the invoking user. */
@@ -165,15 +166,15 @@
String def, Set<String> allowedValues, @FormatString String fmt, Object... args) {
for (; ; ) {
String r = readString(def, fmt, args);
- if (allowedValues.contains(r.toLowerCase())) {
- return r.toLowerCase();
+ if (allowedValues.contains(r.toLowerCase(Locale.US))) {
+ return r.toLowerCase(Locale.US);
}
if (!"?".equals(r)) {
console.printf("error: '%s' is not a valid choice\n", r);
}
console.printf(" Supported options are:\n");
for (String v : allowedValues) {
- console.printf(" %s\n", v.toLowerCase());
+ console.printf(" %s\n", v.toLowerCase(Locale.US));
}
}
}
@@ -210,7 +211,8 @@
T def, A options, String fmt, Object... args) {
final String prompt = String.format(fmt, args);
for (; ; ) {
- String r = console.readLine("%-30s [%s/?]: ", prompt, def.toString().toLowerCase());
+ String r =
+ console.readLine("%-30s [%s/?]: ", prompt, def.toString().toLowerCase(Locale.US));
if (r == null) {
throw abort();
}
@@ -228,7 +230,7 @@
}
console.printf(" Supported options are:\n");
for (T e : options) {
- console.printf(" %s\n", e.toString().toLowerCase());
+ console.printf(" %s\n", e.toString().toLowerCase(Locale.US));
}
}
}
diff --git a/java/com/google/gerrit/pgm/util/AbstractProgram.java b/java/com/google/gerrit/pgm/util/AbstractProgram.java
index 96b042a..00cba31 100644
--- a/java/com/google/gerrit/pgm/util/AbstractProgram.java
+++ b/java/com/google/gerrit/pgm/util/AbstractProgram.java
@@ -18,6 +18,7 @@
import com.google.gerrit.util.cli.CmdLineParser;
import com.google.gerrit.util.cli.OptionHandlers;
import java.io.StringWriter;
+import java.util.Locale;
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.Option;
@@ -35,7 +36,7 @@
if (0 < dot) {
n = n.substring(dot + 1);
}
- return n.toLowerCase();
+ return n.toLowerCase(Locale.US);
}
public final int main(String[] argv) throws Exception {
diff --git a/java/com/google/gerrit/server/ChangeUtil.java b/java/com/google/gerrit/server/ChangeUtil.java
index 2c5b539..2265055 100644
--- a/java/com/google/gerrit/server/ChangeUtil.java
+++ b/java/com/google/gerrit/server/ChangeUtil.java
@@ -31,6 +31,7 @@
import java.security.SecureRandom;
import java.util.Collection;
import java.util.List;
+import java.util.Locale;
import java.util.Optional;
import java.util.Random;
import java.util.Set;
@@ -149,7 +150,7 @@
}
public static String status(Change c) {
- return c != null ? c.getStatus().name().toLowerCase() : "deleted";
+ return c != null ? c.getStatus().name().toLowerCase(Locale.US) : "deleted";
}
private static final Pattern LINK_CHANGE_ID_PATTERN = Pattern.compile("I[0-9a-f]{40}");
diff --git a/java/com/google/gerrit/server/approval/testing/TestPatchSetApprovalUuidGenerator.java b/java/com/google/gerrit/server/approval/testing/TestPatchSetApprovalUuidGenerator.java
index 89727c7..676640d 100644
--- a/java/com/google/gerrit/server/approval/testing/TestPatchSetApprovalUuidGenerator.java
+++ b/java/com/google/gerrit/server/approval/testing/TestPatchSetApprovalUuidGenerator.java
@@ -20,6 +20,7 @@
import com.google.gerrit.entities.PatchSetApproval.UUID;
import com.google.gerrit.server.approval.PatchSetApprovalUuidGenerator;
import java.time.Instant;
+import java.util.Locale;
import javax.inject.Singleton;
/**
@@ -44,6 +45,6 @@
value,
invocationCount)
.replace("-", "_")
- .toLowerCase());
+ .toLowerCase(Locale.US));
}
}
diff --git a/java/com/google/gerrit/server/cache/PerThreadProjectCache.java b/java/com/google/gerrit/server/cache/PerThreadProjectCache.java
index 86f1d2d..8394343 100644
--- a/java/com/google/gerrit/server/cache/PerThreadProjectCache.java
+++ b/java/com/google/gerrit/server/cache/PerThreadProjectCache.java
@@ -15,6 +15,7 @@
package com.google.gerrit.server.cache;
import com.google.common.collect.Maps;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.gerrit.entities.Project;
import java.util.Map;
import java.util.function.Supplier;
@@ -39,6 +40,7 @@
private PerThreadProjectCache() {}
+ @CanIgnoreReturnValue
public static <T> T getOrCompute(PerThreadCache.Key<Project.NameKey> key, Supplier<T> loader) {
PerThreadCache perThreadCache = PerThreadCache.get();
if (perThreadCache != null) {
diff --git a/java/com/google/gerrit/server/change/ArchiveFormatInternal.java b/java/com/google/gerrit/server/change/ArchiveFormatInternal.java
index f6e9ff9..0ed1f11 100644
--- a/java/com/google/gerrit/server/change/ArchiveFormatInternal.java
+++ b/java/com/google/gerrit/server/change/ArchiveFormatInternal.java
@@ -17,6 +17,7 @@
import java.io.Closeable;
import java.io.IOException;
import java.io.OutputStream;
+import java.util.Locale;
import org.apache.commons.compress.archivers.ArchiveOutputStream;
import org.eclipse.jgit.api.ArchiveCommand;
import org.eclipse.jgit.api.ArchiveCommand.Format;
@@ -47,7 +48,7 @@
}
public String getShortName() {
- return name().toLowerCase();
+ return name().toLowerCase(Locale.US);
}
public String getMimeType() {
diff --git a/java/com/google/gerrit/server/config/ConfigUpdatedEvent.java b/java/com/google/gerrit/server/config/ConfigUpdatedEvent.java
index 7fd075e..5e6a520 100644
--- a/java/com/google/gerrit/server/config/ConfigUpdatedEvent.java
+++ b/java/com/google/gerrit/server/config/ConfigUpdatedEvent.java
@@ -18,6 +18,7 @@
import com.google.common.collect.Multimap;
import java.util.Collections;
import java.util.LinkedHashSet;
+import java.util.Locale;
import java.util.Objects;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
@@ -139,7 +140,7 @@
@Override
public String toString() {
- return StringUtils.capitalize(name().toLowerCase());
+ return StringUtils.capitalize(name().toLowerCase(Locale.US));
}
}
diff --git a/java/com/google/gerrit/server/config/DownloadConfig.java b/java/com/google/gerrit/server/config/DownloadConfig.java
index 8ac858c..4fdbd4a 100644
--- a/java/com/google/gerrit/server/config/DownloadConfig.java
+++ b/java/com/google/gerrit/server/config/DownloadConfig.java
@@ -29,6 +29,7 @@
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
+import java.util.Locale;
import java.util.Set;
import org.eclipse.jgit.lib.Config;
@@ -101,7 +102,7 @@
@Nullable
private static String toCoreScheme(String s) {
try {
- Field f = CoreDownloadSchemes.class.getField(s.toUpperCase());
+ Field f = CoreDownloadSchemes.class.getField(s.toUpperCase(Locale.US));
int m = Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL;
if ((f.getModifiers() & m) == m && f.getType() == String.class) {
return (String) f.get(null);
diff --git a/java/com/google/gerrit/server/git/MultiProgressMonitor.java b/java/com/google/gerrit/server/git/MultiProgressMonitor.java
index c76c78e..ab5c988 100644
--- a/java/com/google/gerrit/server/git/MultiProgressMonitor.java
+++ b/java/com/google/gerrit/server/git/MultiProgressMonitor.java
@@ -170,6 +170,11 @@
public String getTotalDisplay(int total) {
return String.valueOf(total);
}
+
+ @Override
+ public void showDuration(boolean enabled) {
+ // not implemented
+ }
}
/** Handle for a sub-task whose total work can be updated while the task is in progress. */
diff --git a/java/com/google/gerrit/server/git/receive/ReceiveCommits.java b/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
index 7b8c0d2..0e9f7ca 100644
--- a/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
+++ b/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
@@ -195,6 +195,7 @@
import com.google.gerrit.server.update.SuperprojectUpdateOnSubmission;
import com.google.gerrit.server.update.UpdateException;
import com.google.gerrit.server.update.context.RefUpdateContext;
+import com.google.gerrit.server.update.context.RefUpdateContext.RefUpdateType;
import com.google.gerrit.server.util.LabelVote;
import com.google.gerrit.server.util.MagicBranch;
import com.google.gerrit.server.util.RequestScopePropagator;
@@ -891,7 +892,10 @@
case UPDATE:
case UPDATE_NONFASTFORWARD:
Task closeProgress = progress.beginSubTask("closed", UNKNOWN);
- autoCloseChanges(c, closeProgress);
+ try (RefUpdateContext ctx =
+ RefUpdateContext.open(RefUpdateType.AUTO_CLOSE_CHANGES)) {
+ autoCloseChanges(c, closeProgress);
+ }
closeProgress.end();
break;
diff --git a/java/com/google/gerrit/server/index/account/AccountField.java b/java/com/google/gerrit/server/index/account/AccountField.java
index ed58a0b..cc86ffc 100644
--- a/java/com/google/gerrit/server/index/account/AccountField.java
+++ b/java/com/google/gerrit/server/index/account/AccountField.java
@@ -150,7 +150,7 @@
.build(
a -> {
String preferredEmail = a.account().preferredEmail();
- return preferredEmail != null ? preferredEmail.toLowerCase() : null;
+ return preferredEmail != null ? preferredEmail.toLowerCase(Locale.US) : null;
});
public static final IndexedField<AccountState, String>.SearchSpec
diff --git a/java/com/google/gerrit/server/index/change/ChangeField.java b/java/com/google/gerrit/server/index/change/ChangeField.java
index 92e722d..1d5818a 100644
--- a/java/com/google/gerrit/server/index/change/ChangeField.java
+++ b/java/com/google/gerrit/server/index/change/ChangeField.java
@@ -1042,7 +1042,7 @@
public static String formatLabel(
String label, int value, @Nullable Account.Id accountId, @Nullable Integer count) {
- return label.toLowerCase()
+ return label.toLowerCase(Locale.US)
+ (value >= 0 ? "+" : "")
+ value
+ (accountId != null ? "," + formatAccount(accountId) : "")
@@ -1055,7 +1055,7 @@
public static String formatLabel(
String label, String value, @Nullable Account.Id accountId, @Nullable Integer count) {
- return label.toLowerCase()
+ return label.toLowerCase(Locale.US)
+ "="
+ value
+ (accountId != null ? "," + formatAccount(accountId) : "")
@@ -1567,7 +1567,7 @@
continue;
}
for (SubmitRecord.Label label : rec.labels) {
- String sl = label.status.toString() + ',' + label.label.toLowerCase();
+ String sl = label.status.toString() + ',' + label.label.toLowerCase(Locale.US);
result.add(sl);
String slc = sl + ',';
if (label.appliedBy != null) {
@@ -1596,28 +1596,28 @@
result.add(
SubmitRecord.Label.Status.OK.name()
+ ","
- + srResult.submitRequirement().name().toLowerCase());
+ + srResult.submitRequirement().name().toLowerCase(Locale.US));
result.add(
SubmitRecord.Label.Status.MAY.name()
+ ","
- + srResult.submitRequirement().name().toLowerCase());
+ + srResult.submitRequirement().name().toLowerCase(Locale.US));
break;
case UNSATISFIED:
result.add(
SubmitRecord.Label.Status.NEED.name()
+ ","
- + srResult.submitRequirement().name().toLowerCase());
+ + srResult.submitRequirement().name().toLowerCase(Locale.US));
result.add(
SubmitRecord.Label.Status.REJECT.name()
+ ","
- + srResult.submitRequirement().name().toLowerCase());
+ + srResult.submitRequirement().name().toLowerCase(Locale.US));
break;
case NOT_APPLICABLE:
case ERROR:
result.add(
SubmitRecord.Label.Status.IMPOSSIBLE.name()
+ ","
- + srResult.submitRequirement().name().toLowerCase());
+ + srResult.submitRequirement().name().toLowerCase(Locale.US));
}
}
return result;
diff --git a/java/com/google/gerrit/server/ioutil/HostPlatform.java b/java/com/google/gerrit/server/ioutil/HostPlatform.java
index e27d17c..b912c52 100644
--- a/java/com/google/gerrit/server/ioutil/HostPlatform.java
+++ b/java/com/google/gerrit/server/ioutil/HostPlatform.java
@@ -16,6 +16,7 @@
import java.security.AccessController;
import java.security.PrivilegedAction;
+import java.util.Locale;
public final class HostPlatform {
private static final boolean win32 = compute("windows");
@@ -34,7 +35,7 @@
final String osDotName =
AccessController.doPrivileged(
(PrivilegedAction<String>) () -> System.getProperty("os.name"));
- return osDotName != null && osDotName.toLowerCase().contains(platform);
+ return osDotName != null && osDotName.toLowerCase(Locale.US).contains(platform);
}
private HostPlatform() {}
diff --git a/java/com/google/gerrit/server/mail/send/ChangeEmail.java b/java/com/google/gerrit/server/mail/send/ChangeEmail.java
index d298f1c..ec81cf6 100644
--- a/java/com/google/gerrit/server/mail/send/ChangeEmail.java
+++ b/java/com/google/gerrit/server/mail/send/ChangeEmail.java
@@ -24,6 +24,7 @@
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Account;
+import com.google.gerrit.entities.Address;
import com.google.gerrit.entities.AttentionSetUpdate;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.ChangeSizeBucket;
@@ -465,7 +466,18 @@
}
@Override
- protected boolean isVisibleTo(Account.Id to) throws PermissionBackendException {
+ protected boolean isRecipientAllowed(Address addr) throws PermissionBackendException {
+ if (!projectState.statePermitsRead()) {
+ return false;
+ }
+ return args.permissionBackend
+ .user(args.anonymousUser.get())
+ .change(changeData)
+ .test(ChangePermission.READ);
+ }
+
+ @Override
+ protected boolean isRecipientAllowed(Account.Id to) throws PermissionBackendException {
if (!projectState.statePermitsRead()) {
return false;
}
diff --git a/java/com/google/gerrit/server/mail/send/OutgoingEmail.java b/java/com/google/gerrit/server/mail/send/OutgoingEmail.java
index fa4f04e..d00c874 100644
--- a/java/com/google/gerrit/server/mail/send/OutgoingEmail.java
+++ b/java/com/google/gerrit/server/mail/send/OutgoingEmail.java
@@ -528,6 +528,45 @@
* Adds a recipient that the email will be sent to.
*
* @param rt category of recipient (TO, CC, BCC)
+ * @param addr Name and email of the recipient.
+ */
+ public final void addByEmail(RecipientType rt, Address addr) {
+ addByEmail(rt, addr, false);
+ }
+
+ /**
+ * Adds a recipient that the email will be sent to.
+ *
+ * @param rt category of recipient (TO, CC, BCC).
+ * @param addr Name and email of the recipient.
+ * @param override if the recipient was added previously and override is false no change is made
+ * regardless of {@code rt}.
+ */
+ public final void addByEmail(RecipientType rt, Address addr, boolean override) {
+ try {
+ if (isRecipientAllowed(addr)) {
+ add(rt, addr, override);
+ }
+ } catch (PermissionBackendException e) {
+ logger.atSevere().withCause(e).log("Error checking permissions for email address: %s", addr);
+ }
+ }
+
+ /**
+ * Returns whether this email is allowed to be sent to the given address
+ *
+ * @param addr email address of recipient.
+ * @throws PermissionBackendException thrown if checking a permission fails due to an error in the
+ * permission backend
+ */
+ protected boolean isRecipientAllowed(Address addr) throws PermissionBackendException {
+ return true;
+ }
+
+ /**
+ * Adds a recipient that the email will be sent to.
+ *
+ * @param rt category of recipient (TO, CC, BCC)
* @param to Gerrit Account of the recipient.
*/
protected void addByAccountId(RecipientType rt, Account.Id to) {
@@ -544,45 +583,27 @@
*/
protected void addByAccountId(RecipientType rt, Account.Id to, boolean override) {
try {
- if (!rcptTo.contains(to) && isVisibleTo(to)) {
+ if (!rcptTo.contains(to) && isRecipientAllowed(to)) {
rcptTo.add(to);
- addByEmail(rt, toAddress(to), override);
+ add(rt, toAddress(to), override);
}
} catch (PermissionBackendException e) {
- logger.atSevere().withCause(e).log("Error reading database for account: %s", to);
+ logger.atSevere().withCause(e).log("Error checking permissions for account: %s", to);
}
}
/**
- * Returns whether this email is visible to the given account
+ * Returns whether this email is allowed to be sent to the given account
*
* @param to account.
* @throws PermissionBackendException thrown if checking a permission fails due to an error in the
* permission backend
*/
- protected boolean isVisibleTo(Account.Id to) throws PermissionBackendException {
+ protected boolean isRecipientAllowed(Account.Id to) throws PermissionBackendException {
return true;
}
- /**
- * Adds a recipient that the email will be sent to.
- *
- * @param rt category of recipient (TO, CC, BCC)
- * @param addr Name and email of the recipient.
- */
- public final void addByEmail(RecipientType rt, Address addr) {
- addByEmail(rt, addr, false);
- }
-
- /**
- * Adds a recipient that the email will be sent to.
- *
- * @param rt category of recipient (TO, CC, BCC).
- * @param addr Name and email of the recipient.
- * @param override if the recipient was added previously and override is false no change is made
- * regardless of {@code rt}.
- */
- public final void addByEmail(RecipientType rt, Address addr, boolean override) {
+ private final void add(RecipientType rt, Address addr, boolean override) {
if (addr != null && addr.email() != null && addr.email().length() > 0) {
if (!args.validator.isValid(addr.email())) {
logger.atWarning().log("Not emailing %s (invalid email address)", addr.email());
diff --git a/java/com/google/gerrit/server/notedb/ChangeNotesCommit.java b/java/com/google/gerrit/server/notedb/ChangeNotesCommit.java
index 38ab8e9..84de569 100644
--- a/java/com/google/gerrit/server/notedb/ChangeNotesCommit.java
+++ b/java/com/google/gerrit/server/notedb/ChangeNotesCommit.java
@@ -25,6 +25,7 @@
import com.google.gerrit.server.git.InsertedObject;
import java.io.IOException;
import java.util.List;
+import java.util.Locale;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.lib.AnyObjectId;
@@ -125,10 +126,10 @@
List<FooterLine> src = getFooterLines();
footerLines = MultimapBuilder.hashKeys(src.size()).arrayListValues(1).build();
for (FooterLine fl : src) {
- footerLines.put(fl.getKey().toLowerCase(), fl.getValue());
+ footerLines.put(fl.getKey().toLowerCase(Locale.US), fl.getValue());
}
}
- return footerLines.get(key.getName().toLowerCase());
+ return footerLines.get(key.getName().toLowerCase(Locale.US));
}
public boolean isAttentionSetCommitOnly(boolean hasChangeMessage) {
@@ -137,7 +138,7 @@
.keySet()
.equals(
Sets.newHashSet(
- FOOTER_PATCH_SET.getName().toLowerCase(),
- FOOTER_ATTENTION.getName().toLowerCase()));
+ FOOTER_PATCH_SET.getName().toLowerCase(Locale.US),
+ FOOTER_ATTENTION.getName().toLowerCase(Locale.US)));
}
}
diff --git a/java/com/google/gerrit/server/notedb/ChangeNotesParser.java b/java/com/google/gerrit/server/notedb/ChangeNotesParser.java
index 0ee0689..951a478 100644
--- a/java/com/google/gerrit/server/notedb/ChangeNotesParser.java
+++ b/java/com/google/gerrit/server/notedb/ChangeNotesParser.java
@@ -93,6 +93,7 @@
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
@@ -760,7 +761,7 @@
throw expectedOneFooter(FOOTER_STATUS, statusLines);
}
Change.Status status =
- Enums.getIfPresent(Change.Status.class, statusLines.get(0).toUpperCase()).orNull();
+ Enums.getIfPresent(Change.Status.class, statusLines.get(0).toUpperCase(Locale.US)).orNull();
if (status == null) {
throw invalidFooter(FOOTER_STATUS, statusLines.get(0));
}
@@ -802,7 +803,7 @@
PatchSetState state =
Enums.getIfPresent(
PatchSetState.class,
- withParens.substring(1, withParens.length() - 1).toUpperCase())
+ withParens.substring(1, withParens.length() - 1).toUpperCase(Locale.US))
.orNull();
if (state != null) {
return state;
diff --git a/java/com/google/gerrit/server/notedb/ChangeUpdate.java b/java/com/google/gerrit/server/notedb/ChangeUpdate.java
index f8c7426..0a895fb 100644
--- a/java/com/google/gerrit/server/notedb/ChangeUpdate.java
+++ b/java/com/google/gerrit/server/notedb/ChangeUpdate.java
@@ -95,6 +95,7 @@
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
@@ -741,7 +742,7 @@
}
if (status != null) {
- addFooter(msg, FOOTER_STATUS, status.name().toLowerCase());
+ addFooter(msg, FOOTER_STATUS, status.name().toLowerCase(Locale.US));
if (status.equals(Change.Status.ABANDONED)) {
clearAttentionSet("Change was abandoned");
}
@@ -1129,7 +1130,7 @@
private void addPatchSetFooter(StringBuilder sb, PatchSet.Id ps) {
addFooter(sb, FOOTER_PATCH_SET).append(ps.get());
if (psState != null) {
- sb.append(" (").append(psState.name().toLowerCase()).append(')');
+ sb.append(" (").append(psState.name().toLowerCase(Locale.US)).append(')');
}
sb.append('\n');
}
diff --git a/java/com/google/gerrit/server/project/ProjectConfig.java b/java/com/google/gerrit/server/project/ProjectConfig.java
index f9eaa906..6c8087e0 100644
--- a/java/com/google/gerrit/server/project/ProjectConfig.java
+++ b/java/com/google/gerrit/server/project/ProjectConfig.java
@@ -720,7 +720,7 @@
Map<String, String> lowerNames = Maps.newHashMapWithExpectedSize(2);
extensionPanelSections = new LinkedHashMap<>();
for (String name : rc.getSubsections(EXTENSION_PANELS)) {
- String lower = name.toLowerCase();
+ String lower = name.toLowerCase(Locale.US);
if (lowerNames.containsKey(lower)) {
error(
String.format(
@@ -970,7 +970,7 @@
submitRequirementSections = new LinkedHashMap<>();
for (String name : rc.getSubsections(SUBMIT_REQUIREMENT)) {
checkDuplicateSrDefinition(rc, name);
- String lower = name.toLowerCase();
+ String lower = name.toLowerCase(Locale.US);
if (lowerNames.containsKey(lower)) {
error(
String.format(
@@ -1102,7 +1102,7 @@
Map<String, String> lowerNames = Maps.newHashMapWithExpectedSize(2);
labelSections = new LinkedHashMap<>();
for (String name : rc.getSubsections(LABEL)) {
- String lower = name.toLowerCase();
+ String lower = name.toLowerCase(Locale.US);
if (lowerNames.containsKey(lower)) {
error(String.format("Label \"%s\" conflicts with \"%s\"", name, lowerNames.get(lower)));
}
@@ -1530,7 +1530,7 @@
if (capability != null) {
Set<String> have = new HashSet<>();
for (Permission permission : sort(capability.getPermissions())) {
- have.add(permission.getName().toLowerCase());
+ have.add(permission.getName().toLowerCase(Locale.US));
boolean needRange = GlobalCapability.hasRange(permission.getName());
List<String> rules = new ArrayList<>();
@@ -1544,7 +1544,7 @@
rc.setStringList(CAPABILITY, null, permission.getName(), rules);
}
for (String varName : rc.getNames(CAPABILITY)) {
- if (!have.contains(varName.toLowerCase())) {
+ if (!have.contains(varName.toLowerCase(Locale.US))) {
rc.unset(CAPABILITY, null, varName);
}
}
@@ -1575,7 +1575,7 @@
Set<String> have = new HashSet<>();
for (Permission permission : sort(as.getPermissions())) {
- have.add(permission.getName().toLowerCase());
+ have.add(permission.getName().toLowerCase(Locale.US));
boolean needRange = Permission.hasRange(permission.getName());
List<String> rules = new ArrayList<>();
@@ -1591,7 +1591,7 @@
for (String varName : rc.getNames(ACCESS, refName)) {
if (isCoreOrPluginPermission(convertLegacyPermission(varName))
- && !have.contains(varName.toLowerCase())) {
+ && !have.contains(varName.toLowerCase(Locale.US))) {
rc.unset(ACCESS, refName, varName);
}
}
diff --git a/java/com/google/gerrit/server/project/ProjectState.java b/java/com/google/gerrit/server/project/ProjectState.java
index 6352f66..9899a6d 100644
--- a/java/com/google/gerrit/server/project/ProjectState.java
+++ b/java/com/google/gerrit/server/project/ProjectState.java
@@ -56,6 +56,7 @@
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
@@ -380,7 +381,7 @@
Map<String, SubmitRequirement> requirements = new LinkedHashMap<>();
for (ProjectState s : treeInOrder()) {
for (SubmitRequirement requirement : s.getConfig().getSubmitRequirementSections().values()) {
- String lowerName = requirement.name().toLowerCase();
+ String lowerName = requirement.name().toLowerCase(Locale.US);
SubmitRequirement old = requirements.get(lowerName);
if (old == null || old.allowOverrideInChildProjects()) {
requirements.put(lowerName, requirement);
@@ -395,7 +396,7 @@
Map<String, LabelType> types = new LinkedHashMap<>();
for (ProjectState s : treeInOrder()) {
for (LabelType type : s.getConfig().getLabelSections().values()) {
- String lower = type.getName().toLowerCase();
+ String lower = type.getName().toLowerCase(Locale.US);
LabelType old = types.get(lower);
if (old == null || old.isCanOverride()) {
types.put(lower, type);
@@ -449,11 +450,11 @@
public List<CommentLinkInfo> getCommentLinks() {
Map<String, CommentLinkInfo> cls = new LinkedHashMap<>();
for (CommentLinkInfo cl : commentLinks) {
- cls.put(cl.name.toLowerCase(), cl);
+ cls.put(cl.name.toLowerCase(Locale.US), cl);
}
for (ProjectState s : treeInOrder()) {
for (StoredCommentLinkInfo cl : s.getConfig().getCommentLinkSections().values()) {
- String name = cl.getName().toLowerCase();
+ String name = cl.getName().toLowerCase(Locale.US);
if (cl.getOverrideOnly()) {
CommentLinkInfo parent = cls.get(name);
if (parent == null) {
diff --git a/java/com/google/gerrit/server/project/SubmitRequirementsEvaluatorImpl.java b/java/com/google/gerrit/server/project/SubmitRequirementsEvaluatorImpl.java
index 870fc3e..0991f20 100644
--- a/java/com/google/gerrit/server/project/SubmitRequirementsEvaluatorImpl.java
+++ b/java/com/google/gerrit/server/project/SubmitRequirementsEvaluatorImpl.java
@@ -36,6 +36,7 @@
import com.google.inject.Module;
import com.google.inject.Provider;
import com.google.inject.Scopes;
+import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
@@ -207,7 +208,8 @@
return globalSubmitRequirements.stream()
.collect(
toImmutableMap(
- globalRequirement -> globalRequirement.name().toLowerCase(), Function.identity()));
+ globalRequirement -> globalRequirement.name().toLowerCase(Locale.US),
+ Function.identity()));
}
/** Evaluate the predicate recursively using change data. */
diff --git a/java/com/google/gerrit/server/project/SubmitRequirementsUtil.java b/java/com/google/gerrit/server/project/SubmitRequirementsUtil.java
index e54e5af..403e526 100644
--- a/java/com/google/gerrit/server/project/SubmitRequirementsUtil.java
+++ b/java/com/google/gerrit/server/project/SubmitRequirementsUtil.java
@@ -28,6 +28,7 @@
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.util.HashMap;
+import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
@@ -142,10 +143,12 @@
// (projectConfigRequirements should not contain legacy entries)
// TODO(ghareeb): remove the filter statement
.filter(entry -> !entry.getValue().isLegacy())
- .collect(Collectors.toMap(sr -> sr.getKey().name().toLowerCase(), sr -> sr.getValue()));
+ .collect(
+ Collectors.toMap(
+ sr -> sr.getKey().name().toLowerCase(Locale.US), sr -> sr.getValue()));
for (Map.Entry<SubmitRequirement, SubmitRequirementResult> legacy :
legacyRequirements.entrySet()) {
- String srName = legacy.getKey().name().toLowerCase();
+ String srName = legacy.getKey().name().toLowerCase(Locale.US);
SubmitRequirementResult projectConfigResult = requirementsByName.get(srName);
SubmitRequirementResult legacyResult = legacy.getValue();
// If there's no project config requirement with the same name as the legacy requirement
diff --git a/java/com/google/gerrit/server/query/approval/ApprovalQueryBuilder.java b/java/com/google/gerrit/server/query/approval/ApprovalQueryBuilder.java
index 11749cc..ed876c1 100644
--- a/java/com/google/gerrit/server/query/approval/ApprovalQueryBuilder.java
+++ b/java/com/google/gerrit/server/query/approval/ApprovalQueryBuilder.java
@@ -28,6 +28,7 @@
import com.google.gerrit.server.group.GroupResolver;
import com.google.inject.Inject;
import java.util.Arrays;
+import java.util.Locale;
import java.util.Optional;
public class ApprovalQueryBuilder extends QueryBuilder<ApprovalContext, ApprovalQueryBuilder> {
@@ -113,7 +114,7 @@
private static <T extends Enum<T>> Optional<T> parseEnumValue(Class<T> clazz, String value) {
return Optional.ofNullable(
- Enums.getIfPresent(clazz, value.toUpperCase().replace('-', '_')).orNull());
+ Enums.getIfPresent(clazz, value.toUpperCase(Locale.US).replace('-', '_')).orNull());
}
private <T extends Enum<T>> String formatEnumValues(Class<T> clazz) {
diff --git a/java/com/google/gerrit/server/query/change/BranchSetIndexPredicate.java b/java/com/google/gerrit/server/query/change/BranchSetIndexPredicate.java
new file mode 100644
index 0000000..eb35b14
--- /dev/null
+++ b/java/com/google/gerrit/server/query/change/BranchSetIndexPredicate.java
@@ -0,0 +1,61 @@
+// Copyright (C) 2023 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.server.query.change;
+
+import com.google.gerrit.entities.BranchNameKey;
+import com.google.gerrit.entities.Change;
+import com.google.gerrit.exceptions.StorageException;
+import com.google.gerrit.index.query.OrPredicate;
+import com.google.gerrit.index.query.Predicate;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/** A Predicate to match any number of BranchNameKeys with O(1) efficiency */
+public class BranchSetIndexPredicate extends OrPredicate<ChangeData> {
+ private final String name;
+ private final Set<BranchNameKey> branches;
+
+ public BranchSetIndexPredicate(String name, Set<BranchNameKey> branches) throws StorageException {
+ super(getPredicates(branches));
+ this.name = name;
+ this.branches = branches;
+ }
+
+ @Override
+ public boolean match(ChangeData changeData) {
+ Change change = changeData.change();
+ if (change == null) {
+ return false;
+ }
+
+ return branches.contains(change.getDest());
+ }
+
+ @Override
+ public String toString() {
+ return "BranchSetIndexPredicate[" + name + "]" + super.toString();
+ }
+
+ private static List<Predicate<ChangeData>> getPredicates(Set<BranchNameKey> branches) {
+ return branches.stream()
+ .map(
+ branchNameKey ->
+ Predicate.and(
+ ChangePredicates.project(branchNameKey.project()),
+ ChangePredicates.ref(branchNameKey.branch())))
+ .collect(Collectors.toList());
+ }
+}
diff --git a/java/com/google/gerrit/server/query/change/ChangePredicates.java b/java/com/google/gerrit/server/query/change/ChangePredicates.java
index e9bf3c2..528d0ce 100644
--- a/java/com/google/gerrit/server/query/change/ChangePredicates.java
+++ b/java/com/google/gerrit/server/query/change/ChangePredicates.java
@@ -202,14 +202,14 @@
public static Predicate<ChangeData> hashtag(String hashtag) {
// Use toLowerCase without locale to match behavior in ChangeField.
return new ChangeIndexPredicate(
- ChangeField.HASHTAG_SPEC, HashtagsUtil.cleanupHashtag(hashtag).toLowerCase());
+ ChangeField.HASHTAG_SPEC, HashtagsUtil.cleanupHashtag(hashtag).toLowerCase(Locale.US));
}
/** Returns a predicate that matches changes tagged with the provided {@code hashtag}. */
public static Predicate<ChangeData> fuzzyHashtag(String hashtag) {
// Use toLowerCase without locale to match behavior in ChangeField.
return new ChangeIndexPredicate(
- ChangeField.FUZZY_HASHTAG, HashtagsUtil.cleanupHashtag(hashtag).toLowerCase());
+ ChangeField.FUZZY_HASHTAG, HashtagsUtil.cleanupHashtag(hashtag).toLowerCase(Locale.US));
}
/**
@@ -218,7 +218,7 @@
public static Predicate<ChangeData> prefixHashtag(String hashtag) {
// Use toLowerCase without locale to match behavior in ChangeField.
return new ChangeIndexPredicate(
- ChangeField.PREFIX_HASHTAG, HashtagsUtil.cleanupHashtag(hashtag).toLowerCase());
+ ChangeField.PREFIX_HASHTAG, HashtagsUtil.cleanupHashtag(hashtag).toLowerCase(Locale.US));
}
/** Returns a predicate that matches changes that modified the provided {@code file}. */
diff --git a/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java b/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
index 14b1d11..ef067a1 100644
--- a/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
+++ b/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
@@ -65,6 +65,7 @@
import com.google.gerrit.server.account.GroupBackend;
import com.google.gerrit.server.account.GroupBackends;
import com.google.gerrit.server.account.GroupMembers;
+import com.google.gerrit.server.account.QueryList;
import com.google.gerrit.server.account.VersionedAccountDestinations;
import com.google.gerrit.server.account.VersionedAccountQueries;
import com.google.gerrit.server.change.ChangeTriplet;
@@ -101,6 +102,7 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
@@ -490,7 +492,8 @@
protected final Arguments args;
protected Map<String, String> hasOperandAliases = Collections.emptyMap();
- private Map<Account.Id, DestinationList> destinationListByAccount = new HashMap<>();
+ private final Map<Account.Id, DestinationList> destinationListByAccount = new HashMap<>();
+ private final Map<Account.Id, QueryList> queryListByAccount = new HashMap<>();
private static final Splitter RULE_SPLITTER = Splitter.on("=");
private static final Splitter PLUGIN_SPLITTER = Splitter.on("_");
@@ -1102,7 +1105,7 @@
// submit record status, interpret as a submit record query.
int eq = name.indexOf('=');
if (eq > 0) {
- String statusName = name.substring(eq + 1).toUpperCase();
+ String statusName = name.substring(eq + 1).toUpperCase(Locale.US);
if (!isInt(statusName) && !MagicLabelValue.tryParse(statusName).isPresent()) {
SubmitRecord.Label.Status status =
Enums.getIfPresent(SubmitRecord.Label.Status.class, statusName).orNull();
@@ -1414,16 +1417,16 @@
String name = null;
Account.Id account = null;
- try (Repository git = args.repoManager.openRepository(args.allUsersName)) {
- // [name=]<name>
- if (inputArgs.keyValue.containsKey(ARG_ID_NAME)) {
- name = inputArgs.keyValue.get(ARG_ID_NAME).value();
- } else if (inputArgs.positional.size() == 1) {
- name = Iterables.getOnlyElement(inputArgs.positional);
- } else if (inputArgs.positional.size() > 1) {
- throw new QueryParseException("Error parsing named query: " + value);
- }
+ // [name=]<name>
+ if (inputArgs.keyValue.containsKey(ARG_ID_NAME)) {
+ name = inputArgs.keyValue.get(ARG_ID_NAME).value();
+ } else if (inputArgs.positional.size() == 1) {
+ name = Iterables.getOnlyElement(inputArgs.positional);
+ } else if (inputArgs.positional.size() > 1) {
+ throw new QueryParseException("Error parsing named query: " + value);
+ }
+ try {
// [,user=<user>]
if (inputArgs.keyValue.containsKey(ARG_ID_USER)) {
Set<Account.Id> accounts = parseAccount(inputArgs.keyValue.get(ARG_ID_USER).value());
@@ -1437,9 +1440,7 @@
account = self();
}
- VersionedAccountQueries q = VersionedAccountQueries.forUser(account);
- q.load(args.allUsersName, git);
- String query = q.getQueryList().getQuery(name);
+ String query = getQueryList(account).getQuery(name);
if (query != null) {
return parse(query);
}
@@ -1452,6 +1453,23 @@
throw new QueryParseException("Unknown named query: " + name);
}
+ protected QueryList getQueryList(Account.Id account) throws ConfigInvalidException, IOException {
+ QueryList ql = queryListByAccount.get(account);
+ if (ql == null) {
+ ql = loadQueryList(account);
+ queryListByAccount.put(account, ql);
+ }
+ return ql;
+ }
+
+ protected QueryList loadQueryList(Account.Id account) throws ConfigInvalidException, IOException {
+ VersionedAccountQueries q = VersionedAccountQueries.forUser(account);
+ try (Repository git = args.repoManager.openRepository(args.allUsersName)) {
+ q.load(args.allUsersName, git);
+ }
+ return q.getQueryList();
+ }
+
@Operator
public Predicate<ChangeData> reviewedby(String who)
throws QueryParseException, IOException, ConfigInvalidException {
@@ -1465,16 +1483,16 @@
String name = null;
Account.Id account = null;
- try (Repository git = args.repoManager.openRepository(args.allUsersName)) {
- // [name=]<name>
- if (inputArgs.keyValue.containsKey(ARG_ID_NAME)) {
- name = inputArgs.keyValue.get(ARG_ID_NAME).value();
- } else if (inputArgs.positional.size() == 1) {
- name = Iterables.getOnlyElement(inputArgs.positional);
- } else if (inputArgs.positional.size() > 1) {
- throw new QueryParseException("Error parsing named destination: " + value);
- }
+ // [name=]<name>
+ if (inputArgs.keyValue.containsKey(ARG_ID_NAME)) {
+ name = inputArgs.keyValue.get(ARG_ID_NAME).value();
+ } else if (inputArgs.positional.size() == 1) {
+ name = Iterables.getOnlyElement(inputArgs.positional);
+ } else if (inputArgs.positional.size() > 1) {
+ throw new QueryParseException("Error parsing named destination: " + value);
+ }
+ try {
// [,user=<user>]
if (inputArgs.keyValue.containsKey(ARG_ID_USER)) {
Set<Account.Id> accounts = parseAccount(inputArgs.keyValue.get(ARG_ID_USER).value());
@@ -1488,9 +1506,9 @@
account = self();
}
- Set<BranchNameKey> destinations = getDestinationList(git, account).getDestinations(name);
+ Set<BranchNameKey> destinations = getDestinationList(account).getDestinations(name);
if (destinations != null && !destinations.isEmpty()) {
- return new DestinationPredicate(destinations, value);
+ return new BranchSetIndexPredicate(FIELD_DESTINATION + ":" + value, destinations);
}
} catch (RepositoryNotFoundException e) {
throw new QueryParseException(
@@ -1501,20 +1519,22 @@
throw new QueryParseException("Unknown named destination: " + name);
}
- protected DestinationList getDestinationList(Repository git, Account.Id account)
+ protected DestinationList getDestinationList(Account.Id account)
throws ConfigInvalidException, RepositoryNotFoundException, IOException {
DestinationList dl = destinationListByAccount.get(account);
if (dl == null) {
- dl = loadDestinationList(git, account);
+ dl = loadDestinationList(account);
destinationListByAccount.put(account, dl);
}
return dl;
}
- protected DestinationList loadDestinationList(Repository git, Account.Id account)
+ protected DestinationList loadDestinationList(Account.Id account)
throws ConfigInvalidException, RepositoryNotFoundException, IOException {
VersionedAccountDestinations d = VersionedAccountDestinations.forUser(account);
- d.load(args.allUsersName, git);
+ try (Repository git = args.repoManager.openRepository(args.allUsersName)) {
+ d.load(args.allUsersName, git);
+ }
return d.getDestinationList();
}
diff --git a/java/com/google/gerrit/server/query/change/ChangeStatusPredicate.java b/java/com/google/gerrit/server/query/change/ChangeStatusPredicate.java
index fa48511..d949ea8 100644
--- a/java/com/google/gerrit/server/query/change/ChangeStatusPredicate.java
+++ b/java/com/google/gerrit/server/query/change/ChangeStatusPredicate.java
@@ -26,6 +26,7 @@
import com.google.gerrit.server.index.change.ChangeField;
import java.util.ArrayList;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.NavigableMap;
import java.util.Objects;
@@ -74,11 +75,11 @@
}
public static String canonicalize(Change.Status status) {
- return status.name().toLowerCase();
+ return status.name().toLowerCase(Locale.US);
}
public static Predicate<ChangeData> parse(String value) throws QueryParseException {
- String lower = value.toLowerCase();
+ String lower = value.toLowerCase(Locale.US);
NavigableMap<String, Predicate<ChangeData>> head = PREDICATES.tailMap(lower, true);
if (!head.isEmpty()) {
// Assume no statuses share a common prefix so we can only walk one entry.
diff --git a/java/com/google/gerrit/server/query/change/DestinationPredicate.java b/java/com/google/gerrit/server/query/change/DestinationPredicate.java
deleted file mode 100644
index 3c3d70f..0000000
--- a/java/com/google/gerrit/server/query/change/DestinationPredicate.java
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (C) 2015 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.server.query.change;
-
-import com.google.gerrit.entities.BranchNameKey;
-import com.google.gerrit.entities.Change;
-import com.google.gerrit.index.query.PostFilterPredicate;
-import java.util.Set;
-
-public class DestinationPredicate extends PostFilterPredicate<ChangeData> {
- protected Set<BranchNameKey> destinations;
-
- public DestinationPredicate(Set<BranchNameKey> destinations, String value) {
- super(ChangeQueryBuilder.FIELD_DESTINATION, value);
- this.destinations = destinations;
- }
-
- @Override
- public boolean match(ChangeData object) {
- Change change = object.change();
- if (change == null) {
- return false;
- }
- return destinations.contains(change.getDest());
- }
-
- @Override
- public int getCost() {
- return 1;
- }
-}
diff --git a/java/com/google/gerrit/server/query/change/SubmitRecordPredicate.java b/java/com/google/gerrit/server/query/change/SubmitRecordPredicate.java
index 1ea6c41..243712d 100644
--- a/java/com/google/gerrit/server/query/change/SubmitRecordPredicate.java
+++ b/java/com/google/gerrit/server/query/change/SubmitRecordPredicate.java
@@ -20,12 +20,13 @@
import com.google.gerrit.entities.SubmitRecord;
import com.google.gerrit.index.query.Predicate;
import com.google.gerrit.server.index.change.ChangeField;
+import java.util.Locale;
import java.util.Set;
public class SubmitRecordPredicate extends ChangeIndexPredicate {
public static Predicate<ChangeData> create(
String label, SubmitRecord.Label.Status status, Set<Account.Id> accounts) {
- String lowerLabel = label.toLowerCase();
+ String lowerLabel = label.toLowerCase(Locale.US);
if (accounts == null || accounts.isEmpty()) {
return new SubmitRecordPredicate(status.name() + ',' + lowerLabel);
}
diff --git a/java/com/google/gerrit/server/query/project/ProjectQueryBuilderImpl.java b/java/com/google/gerrit/server/query/project/ProjectQueryBuilderImpl.java
index f7135982..599683e 100644
--- a/java/com/google/gerrit/server/query/project/ProjectQueryBuilderImpl.java
+++ b/java/com/google/gerrit/server/query/project/ProjectQueryBuilderImpl.java
@@ -26,6 +26,7 @@
import com.google.gerrit.index.query.QueryParseException;
import com.google.inject.Inject;
import java.util.List;
+import java.util.Locale;
/** Parses a query string meant to be applied to project objects. */
public class ProjectQueryBuilderImpl extends QueryBuilder<ProjectData, ProjectQueryBuilderImpl>
@@ -72,7 +73,7 @@
}
ProjectState parsedState;
try {
- parsedState = ProjectState.valueOf(state.replace('-', '_').toUpperCase());
+ parsedState = ProjectState.valueOf(state.replace('-', '_').toUpperCase(Locale.US));
} catch (IllegalArgumentException e) {
throw error("state operator must be either 'active' or 'read-only'", e);
}
diff --git a/java/com/google/gerrit/server/restapi/account/GetCapabilities.java b/java/com/google/gerrit/server/restapi/account/GetCapabilities.java
index 6ab2c44..c45694e 100644
--- a/java/com/google/gerrit/server/restapi/account/GetCapabilities.java
+++ b/java/com/google/gerrit/server/restapi/account/GetCapabilities.java
@@ -45,6 +45,7 @@
import com.google.inject.Singleton;
import java.util.HashSet;
import java.util.LinkedHashMap;
+import java.util.Locale;
import java.util.Map;
import java.util.Set;
import org.kohsuke.args4j.Option;
@@ -124,7 +125,7 @@
}
private boolean want(String name) {
- return query == null || query.contains(name.toLowerCase());
+ return query == null || query.contains(name.toLowerCase(Locale.US));
}
private void addRanges(Map<String, Object> have, AccountLimits limits) {
diff --git a/java/com/google/gerrit/server/restapi/change/AllowedFormats.java b/java/com/google/gerrit/server/restapi/change/AllowedFormats.java
index e3ab135..763212d 100644
--- a/java/com/google/gerrit/server/restapi/change/AllowedFormats.java
+++ b/java/com/google/gerrit/server/restapi/change/AllowedFormats.java
@@ -22,6 +22,7 @@
import com.google.gerrit.server.config.DownloadConfig;
import com.google.inject.Inject;
import com.google.inject.Singleton;
+import java.util.Locale;
import java.util.Set;
@Singleton
@@ -36,7 +37,7 @@
for (String ext : format.getSuffixes()) {
exts.put(ext, format);
}
- exts.put(format.name().toLowerCase(), format);
+ exts.put(format.name().toLowerCase(Locale.US), format);
}
extensions = exts.build();
diff --git a/java/com/google/gerrit/server/restapi/change/ChangesCollection.java b/java/com/google/gerrit/server/restapi/change/ChangesCollection.java
index 84cf209..9715a5d 100644
--- a/java/com/google/gerrit/server/restapi/change/ChangesCollection.java
+++ b/java/com/google/gerrit/server/restapi/change/ChangesCollection.java
@@ -83,7 +83,7 @@
}
/**
- * Parses {@link ChangeResource} from {@link Change.Id}
+ * Parses {@link ChangeResource} from {@link com.google.gerrit.entities.Change.Id}
*
* <p>Reads the change from index, since project is unknown.
*/
@@ -106,7 +106,8 @@
}
/**
- * Parses {@link ChangeResource} from {@link Change.Id} in {@code project} at {@code metaRevId}
+ * Parses {@link ChangeResource} from {@link com.google.gerrit.entities.Change.Id} in {@code
+ * project} at {@code metaRevId}
*
* <p>Read change from ChangeNotesCache, so the method can be used upon creation, when the change
* might not be yet available in the index.
@@ -123,7 +124,7 @@
}
/**
- * Parses {@link ChangeResource} from {@link Change.Id}
+ * Parses {@link ChangeResource} from {@link com.google.gerrit.entities.Change.Id}
*
* <p>Reads the change from index, since project is unknown.
*/
diff --git a/java/com/google/gerrit/server/restapi/change/OnPostReview.java b/java/com/google/gerrit/server/restapi/change/OnPostReview.java
index b179d02..4999f18 100644
--- a/java/com/google/gerrit/server/restapi/change/OnPostReview.java
+++ b/java/com/google/gerrit/server/restapi/change/OnPostReview.java
@@ -18,6 +18,7 @@
import com.google.gerrit.extensions.annotations.ExtensionPoint;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.notedb.ChangeNotes;
+import java.time.Instant;
import java.util.Map;
import java.util.Optional;
@@ -28,6 +29,7 @@
* Allows implementors to return a message that should be included into the change message that is
* posted on post review.
*
+ * @param when the timestamp at which the review is posted
* @param user the user that posts the review
* @param changeNotes the change on which post review is performed
* @param patchSet the patch set on which post review is performed
@@ -37,6 +39,7 @@
* {@link Optional#empty()} if the change message should not be extended
*/
default Optional<String> getChangeMessageAddOn(
+ Instant when,
IdentifiedUser user,
ChangeNotes changeNotes,
PatchSet patchSet,
diff --git a/java/com/google/gerrit/server/restapi/change/PostReviewOp.java b/java/com/google/gerrit/server/restapi/change/PostReviewOp.java
index 0036d87..a8f8adf 100644
--- a/java/com/google/gerrit/server/restapi/change/PostReviewOp.java
+++ b/java/com/google/gerrit/server/restapi/change/PostReviewOp.java
@@ -1035,7 +1035,8 @@
onPostReviews.runEach(
onPostReview ->
onPostReview
- .getChangeMessageAddOn(user, ctx.getNotes(), ps, oldApprovals, approvals)
+ .getChangeMessageAddOn(
+ ctx.getWhen(), user, ctx.getNotes(), ps, oldApprovals, approvals)
.ifPresent(
pluginMessage ->
pluginMessages.add(
diff --git a/java/com/google/gerrit/server/restapi/change/RevertSubmission.java b/java/com/google/gerrit/server/restapi/change/RevertSubmission.java
index 4c7c352..691fc75 100644
--- a/java/com/google/gerrit/server/restapi/change/RevertSubmission.java
+++ b/java/com/google/gerrit/server/restapi/change/RevertSubmission.java
@@ -85,6 +85,7 @@
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
+import java.util.Locale;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -196,7 +197,8 @@
}
if (topic == null) {
return String.format(
- "revert-%s-%s", submissionId, RandomStringUtils.randomAlphabetic(10).toUpperCase());
+ "revert-%s-%s",
+ submissionId, RandomStringUtils.randomAlphabetic(10).toUpperCase(Locale.US));
}
return topic;
}
diff --git a/java/com/google/gerrit/server/restapi/config/ReloadConfig.java b/java/com/google/gerrit/server/restapi/config/ReloadConfig.java
index 9ce7ffd..c8f2ed6 100644
--- a/java/com/google/gerrit/server/restapi/config/ReloadConfig.java
+++ b/java/com/google/gerrit/server/restapi/config/ReloadConfig.java
@@ -33,6 +33,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;
@@ -59,7 +60,8 @@
updates.asMap().entrySet().stream()
.collect(
Collectors.toMap(
- e -> e.getKey().name().toLowerCase(), e -> toEntryInfos(e.getValue()))));
+ e -> e.getKey().name().toLowerCase(Locale.US),
+ e -> toEntryInfos(e.getValue()))));
}
private static List<ConfigUpdateEntryInfo> toEntryInfos(
diff --git a/java/com/google/gerrit/server/rules/PrologRuleEvaluator.java b/java/com/google/gerrit/server/rules/PrologRuleEvaluator.java
index cab5b45..bfcbffc 100644
--- a/java/com/google/gerrit/server/rules/PrologRuleEvaluator.java
+++ b/java/com/google/gerrit/server/rules/PrologRuleEvaluator.java
@@ -51,6 +51,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Locale;
/**
* Evaluates a submit-like Prolog rule found in the rules.pl file of the current project and filters
@@ -381,7 +382,7 @@
String typeName = typeTerm.name();
try {
- return SubmitTypeRecord.OK(SubmitType.valueOf(typeName.toUpperCase()));
+ return SubmitTypeRecord.OK(SubmitType.valueOf(typeName.toUpperCase(Locale.US)));
} catch (IllegalArgumentException e) {
return typeError(
"Submit type rule "
diff --git a/java/com/google/gerrit/server/update/context/RefUpdateContext.java b/java/com/google/gerrit/server/update/context/RefUpdateContext.java
index 1144e4f..56d536a 100644
--- a/java/com/google/gerrit/server/update/context/RefUpdateContext.java
+++ b/java/com/google/gerrit/server/update/context/RefUpdateContext.java
@@ -113,6 +113,8 @@
* <p>If a plugin updates one of a special refs - it must also open a nested context.
*/
PLUGIN,
+ /** A ref is updated as a part of auto-close-changes. */
+ AUTO_CLOSE_CHANGES
}
/** Opens a provided context. */
diff --git a/java/com/google/gerrit/sshd/commands/ReviewCommand.java b/java/com/google/gerrit/sshd/commands/ReviewCommand.java
index e0805c0..143b060 100644
--- a/java/com/google/gerrit/sshd/commands/ReviewCommand.java
+++ b/java/com/google/gerrit/sshd/commands/ReviewCommand.java
@@ -56,6 +56,7 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
+import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
@@ -358,7 +359,7 @@
}
private static String asOptionName(LabelType type) {
- return "--" + type.getName().toLowerCase();
+ return "--" + type.getName().toLowerCase(Locale.US);
}
private static Option newApproveOption(LabelType type, String usage) {
diff --git a/java/com/google/gerrit/testing/GerritTestName.java b/java/com/google/gerrit/testing/GerritTestName.java
index d287837..14493b6 100644
--- a/java/com/google/gerrit/testing/GerritTestName.java
+++ b/java/com/google/gerrit/testing/GerritTestName.java
@@ -15,6 +15,7 @@
package com.google.gerrit.testing;
import com.google.common.base.CharMatcher;
+import java.util.Locale;
import org.junit.BeforeClass;
import org.junit.rules.TestName;
import org.junit.rules.TestRule;
@@ -30,7 +31,7 @@
}
public String getSanitizedMethodName() {
- String name = delegate.getMethodName().toLowerCase();
+ String name = delegate.getMethodName().toLowerCase(Locale.US);
name =
CharMatcher.inRange('a', 'z')
.or(CharMatcher.inRange('A', 'Z'))
diff --git a/java/com/google/gerrit/testing/InMemoryRepositoryManager.java b/java/com/google/gerrit/testing/InMemoryRepositoryManager.java
index 8d1130c..8c87405 100644
--- a/java/com/google/gerrit/testing/InMemoryRepositoryManager.java
+++ b/java/com/google/gerrit/testing/InMemoryRepositoryManager.java
@@ -49,6 +49,7 @@
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NavigableSet;
@@ -135,6 +136,11 @@
private RefUpdateContextValidator() {}
public void validateRefUpdateContext(ReceiveCommand cmd) {
+ String refName = cmd.getRefName();
+
+ if (RefUpdateContextCollector.enabled()) {
+ RefUpdateContextCollector.register(refName, RefUpdateContext.getOpenedContexts());
+ }
if (TestActionRefUpdateContext.isOpen()
|| RefUpdateContext.hasOpen(OFFLINE_OPERATION)
|| RefUpdateContext.hasOpen(INIT_REPO)
@@ -143,8 +149,6 @@
return;
}
- String refName = cmd.getRefName();
-
Optional<ImmutableList<RefUpdateType>> allowedRefUpdateTypes =
RefUpdateContextValidator.INSTANCE.getAllowedRefUpdateTypes(refName);
@@ -300,6 +304,6 @@
}
private static String normalize(Project.NameKey name) {
- return name.get().toLowerCase();
+ return name.get().toLowerCase(Locale.US);
}
}
diff --git a/java/com/google/gerrit/testing/IndexVersions.java b/java/com/google/gerrit/testing/IndexVersions.java
index 3810707..2e843fe 100644
--- a/java/com/google/gerrit/testing/IndexVersions.java
+++ b/java/com/google/gerrit/testing/IndexVersions.java
@@ -26,6 +26,7 @@
import com.google.gerrit.index.SchemaDefinitions;
import java.util.ArrayList;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.NavigableMap;
import org.eclipse.jgit.lib.Config;
@@ -73,13 +74,14 @@
* if any of the specified schema versions doesn't exist
*/
public static <V> ImmutableList<Integer> get(SchemaDefinitions<V> schemaDef) {
- String envVar = schemaDef.getName().toUpperCase() + "_INDEX_VERSIONS";
+ String envVar = schemaDef.getName().toUpperCase(Locale.US) + "_INDEX_VERSIONS";
String value = System.getenv(envVar);
if (!Strings.isNullOrEmpty(value)) {
return get(schemaDef, "env variable " + envVar, value);
}
- String systemProperty = "gerrit.index." + schemaDef.getName().toLowerCase() + ".versions";
+ String systemProperty =
+ "gerrit.index." + schemaDef.getName().toLowerCase(Locale.US) + ".versions";
value = System.getProperty(systemProperty);
return get(schemaDef, "system property " + systemProperty, value);
}
@@ -138,7 +140,10 @@
i -> {
Config cfg = baseConfig;
cfg.setInt(
- "index", "lucene", schemaDef.getName().toLowerCase() + "TestVersion", i);
+ "index",
+ "lucene",
+ schemaDef.getName().toLowerCase(Locale.US) + "TestVersion",
+ i);
return cfg;
}));
}
diff --git a/java/com/google/gerrit/testing/RefUpdateContextCollector.java b/java/com/google/gerrit/testing/RefUpdateContextCollector.java
new file mode 100644
index 0000000..88232d2
--- /dev/null
+++ b/java/com/google/gerrit/testing/RefUpdateContextCollector.java
@@ -0,0 +1,92 @@
+// Copyright (C) 2023 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.testing;
+
+import static com.google.common.collect.ImmutableList.toImmutableList;
+
+import com.google.common.collect.ImmutableList;
+import com.google.gerrit.server.update.context.RefUpdateContext;
+import com.google.gerrit.server.update.context.RefUpdateContext.RefUpdateType;
+import java.util.AbstractMap.SimpleImmutableEntry;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+/**
+ * Stores information about each updated ref in tests, together with associated RefUpdateContext(s).
+ *
+ * <p>This is a {@link TestRule}, which clears the stored data after each test.
+ *
+ * <p>Usage:
+ *
+ * <pre>{@code
+ * class ...Test {
+ * \@Rule
+ * public RefUpdateContextCollector refContextCollector = new RefUpdateContextCollector();
+ * ...
+ * public void test() {
+ * // some actions
+ * assertThat(refContextCollector.getContextsByRef("refs/heads/main")).contains(...)
+ * }
+ * }
+ * }</pre>
+ */
+public class RefUpdateContextCollector implements TestRule {
+ private static ConcurrentLinkedQueue<Entry<String, ImmutableList<RefUpdateContext>>>
+ touchedRefsWithContexts = null;
+
+ @Override
+ public Statement apply(Statement statement, Description description) {
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ try {
+ touchedRefsWithContexts = new ConcurrentLinkedQueue<>();
+ statement.evaluate();
+ } finally {
+ touchedRefsWithContexts = null;
+ }
+ }
+ };
+ }
+
+ public static boolean enabled() {
+ return touchedRefsWithContexts != null;
+ }
+
+ public static void register(String refName, ImmutableList<RefUpdateContext> openedContexts) {
+ if (touchedRefsWithContexts == null) {
+ return;
+ }
+ touchedRefsWithContexts.add(new SimpleImmutableEntry<>(refName, openedContexts));
+ }
+
+ public ImmutableList<String> getRefsByUpdateType(RefUpdateType refUpdateType) {
+ return touchedRefsWithContexts.stream()
+ .filter(
+ entry ->
+ entry.getValue().stream()
+ .map(RefUpdateContext::getUpdateType)
+ .anyMatch(refUpdateType::equals))
+ .map(Entry::getKey)
+ .collect(toImmutableList());
+ }
+
+ public void clear() {
+ touchedRefsWithContexts.clear();
+ }
+}
diff --git a/java/com/google/gerrit/testing/SshMode.java b/java/com/google/gerrit/testing/SshMode.java
index 41633bd..60bd5187 100644
--- a/java/com/google/gerrit/testing/SshMode.java
+++ b/java/com/google/gerrit/testing/SshMode.java
@@ -18,6 +18,7 @@
import com.google.common.base.Enums;
import com.google.common.base.Strings;
+import java.util.Locale;
/**
* Whether to enable/disable tests using SSH by inspecting the global environment.
@@ -43,7 +44,7 @@
if (Strings.isNullOrEmpty(value)) {
return YES;
}
- value = value.toUpperCase();
+ value = value.toUpperCase(Locale.US);
SshMode mode = Enums.getIfPresent(SshMode.class, value).orNull();
if (!Strings.isNullOrEmpty(System.getenv(ENV_VAR))) {
checkArgument(
diff --git a/javatests/com/google/gerrit/acceptance/api/change/AbandonIT.java b/javatests/com/google/gerrit/acceptance/api/change/AbandonIT.java
index 80431ee..b80ff9b 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/AbandonIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/AbandonIT.java
@@ -46,6 +46,7 @@
import com.google.gerrit.testing.TestTimeUtil;
import com.google.inject.Inject;
import java.util.List;
+import java.util.Locale;
import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.ObjectId;
@@ -65,7 +66,8 @@
gApi.changes().id(changeId).abandon();
ChangeInfo info = get(changeId, MESSAGES);
assertThat(info.status).isEqualTo(ChangeStatus.ABANDONED);
- assertThat(Iterables.getLast(info.messages).message.toLowerCase()).contains("abandoned");
+ assertThat(Iterables.getLast(info.messages).message.toLowerCase(Locale.US))
+ .contains("abandoned");
ResourceConflictException thrown =
assertThrows(ResourceConflictException.class, () -> gApi.changes().id(changeId).abandon());
@@ -82,13 +84,17 @@
ChangeInfo info = get(a.getChangeId(), MESSAGES);
assertThat(info.status).isEqualTo(ChangeStatus.ABANDONED);
- assertThat(Iterables.getLast(info.messages).message.toLowerCase()).contains("abandoned");
- assertThat(Iterables.getLast(info.messages).message.toLowerCase()).contains("deadbeef");
+ assertThat(Iterables.getLast(info.messages).message.toLowerCase(Locale.US))
+ .contains("abandoned");
+ assertThat(Iterables.getLast(info.messages).message.toLowerCase(Locale.US))
+ .contains("deadbeef");
info = get(b.getChangeId(), MESSAGES);
assertThat(info.status).isEqualTo(ChangeStatus.ABANDONED);
- assertThat(Iterables.getLast(info.messages).message.toLowerCase()).contains("abandoned");
- assertThat(Iterables.getLast(info.messages).message.toLowerCase()).contains("deadbeef");
+ assertThat(Iterables.getLast(info.messages).message.toLowerCase(Locale.US))
+ .contains("abandoned");
+ assertThat(Iterables.getLast(info.messages).message.toLowerCase(Locale.US))
+ .contains("deadbeef");
}
@Test
@@ -292,7 +298,8 @@
gApi.changes().id(changeId).restore();
ChangeInfo info = get(changeId, MESSAGES);
assertThat(info.status).isEqualTo(ChangeStatus.NEW);
- assertThat(Iterables.getLast(info.messages).message.toLowerCase()).contains("restored");
+ assertThat(Iterables.getLast(info.messages).message.toLowerCase(Locale.US))
+ .contains("restored");
ResourceConflictException thrown =
assertThrows(ResourceConflictException.class, () -> gApi.changes().id(changeId).restore());
diff --git a/javatests/com/google/gerrit/acceptance/api/change/PostReviewIT.java b/javatests/com/google/gerrit/acceptance/api/change/PostReviewIT.java
index bb8f3f3..a0f0fe6 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/PostReviewIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/PostReviewIT.java
@@ -86,6 +86,7 @@
import com.google.inject.Inject;
import com.google.inject.Module;
import java.sql.Timestamp;
+import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -1064,6 +1065,7 @@
@Override
public Optional<String> getChangeMessageAddOn(
+ Instant when,
IdentifiedUser user,
ChangeNotes changeNotes,
PatchSet patchSet,
diff --git a/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java b/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java
index 142a45c..9456a31 100644
--- a/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java
@@ -114,6 +114,7 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.stream.Stream;
import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
@@ -463,7 +464,7 @@
@Test
public void createDuplicateInternalGroupCaseInsensitiveName() throws Exception {
String dupGroupName = name("dupGroupA");
- String dupGroupNameLowerCase = name("dupGroupA").toLowerCase();
+ String dupGroupNameLowerCase = name("dupGroupA").toLowerCase(Locale.US);
gApi.groups().create(dupGroupName);
gApi.groups().create(dupGroupNameLowerCase);
assertThat(gApi.groups().list().getAsMap().keySet()).contains(dupGroupName);
diff --git a/javatests/com/google/gerrit/acceptance/git/AbstractSubmitOnPush.java b/javatests/com/google/gerrit/acceptance/git/AbstractSubmitOnPush.java
index 0cdac5a..8295550 100644
--- a/javatests/com/google/gerrit/acceptance/git/AbstractSubmitOnPush.java
+++ b/javatests/com/google/gerrit/acceptance/git/AbstractSubmitOnPush.java
@@ -41,7 +41,9 @@
import com.google.gerrit.server.events.ChangeMergedEvent;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.query.change.ChangeData;
+import com.google.gerrit.server.update.context.RefUpdateContext.RefUpdateType;
import com.google.gerrit.testing.FakeEmailSender.Message;
+import com.google.gerrit.testing.RefUpdateContextCollector;
import com.google.inject.Inject;
import java.util.List;
import org.eclipse.jgit.api.errors.GitAPIException;
@@ -54,12 +56,16 @@
import org.eclipse.jgit.transport.RefSpec;
import org.eclipse.jgit.transport.RemoteRefUpdate;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
public abstract class AbstractSubmitOnPush extends AbstractDaemonTest {
@Inject private ApprovalsUtil approvalsUtil;
@Inject private ProjectOperations projectOperations;
+ @Rule
+ public RefUpdateContextCollector refUpdateContextCollector = new RefUpdateContextCollector();
+
@Before
public void blockAnonymous() throws Exception {
blockAnonymousRead();
@@ -229,6 +235,25 @@
}
@Test
+ public void pushAutoclosesChanges_changeMetaInAutoClosesChangesContext() throws Exception {
+ projectOperations
+ .project(project)
+ .forUpdate()
+ .add(allow(Permission.PUSH).ref("refs/heads/master").group(adminGroupUuid()))
+ .update();
+ PushOneCommit.Result r = push("refs/for/master", PushOneCommit.SUBJECT, "one.txt", "One");
+ String refPrefix = r.getChange().getId().toRefPrefix();
+ assertThat(refUpdateContextCollector.getRefsByUpdateType(RefUpdateType.DIRECT_PUSH)).isEmpty();
+ assertThat(refUpdateContextCollector.getRefsByUpdateType(RefUpdateType.AUTO_CLOSE_CHANGES))
+ .isEmpty();
+ git().push().setRefSpecs(new RefSpec(r.getCommit().name() + ":refs/heads/master")).call();
+ assertThat(refUpdateContextCollector.getRefsByUpdateType(RefUpdateType.DIRECT_PUSH))
+ .containsExactly("refs/heads/master", refPrefix + "meta");
+ assertThat(refUpdateContextCollector.getRefsByUpdateType(RefUpdateType.AUTO_CLOSE_CHANGES))
+ .containsExactly(refPrefix + "meta");
+ }
+
+ @Test
public void mergeOnPushToBranchWithChangeMergedInOther() throws Exception {
enableCreateNewChangeForAllNotInTarget();
String master = "refs/heads/master";
diff --git a/javatests/com/google/gerrit/acceptance/git/ImplicitMergeCheckIT.java b/javatests/com/google/gerrit/acceptance/git/ImplicitMergeCheckIT.java
index 80cc508..e352e2d 100644
--- a/javatests/com/google/gerrit/acceptance/git/ImplicitMergeCheckIT.java
+++ b/javatests/com/google/gerrit/acceptance/git/ImplicitMergeCheckIT.java
@@ -22,6 +22,7 @@
import com.google.gerrit.entities.BooleanProjectConfig;
import com.google.gerrit.extensions.client.InheritableBoolean;
import com.google.gerrit.git.ObjectIds;
+import java.util.Locale;
import org.eclipse.jgit.lib.ObjectId;
import org.junit.Test;
@@ -61,7 +62,8 @@
PushOneCommit.Result m = push("refs/heads/master", "1", "f", "1");
PushOneCommit.Result c = push("refs/for/stable", "2", "f", "2");
- assertThat(c.getMessage().toLowerCase()).doesNotContain(implicitMergeOf(m.getCommit()));
+ assertThat(c.getMessage().toLowerCase(Locale.US))
+ .doesNotContain(implicitMergeOf(m.getCommit()));
}
@Test
@@ -74,7 +76,8 @@
PushOneCommit.Result m = push("refs/heads/master", "1", "f", "1");
PushOneCommit.Result c = push("refs/for/master", "2", "f", "2");
- assertThat(c.getMessage().toLowerCase()).doesNotContain(implicitMergeOf(m.getCommit()));
+ assertThat(c.getMessage().toLowerCase(Locale.US))
+ .doesNotContain(implicitMergeOf(m.getCommit()));
}
private String implicitMergeOf(ObjectId commit) throws Exception {
diff --git a/javatests/com/google/gerrit/acceptance/rest/account/EmailIT.java b/javatests/com/google/gerrit/acceptance/rest/account/EmailIT.java
index 62ef118..f40910a 100644
--- a/javatests/com/google/gerrit/acceptance/rest/account/EmailIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/account/EmailIT.java
@@ -52,6 +52,7 @@
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.util.List;
+import java.util.Locale;
import java.util.Optional;
import java.util.Set;
import org.junit.Test;
@@ -179,7 +180,7 @@
assertThat(gApi.accounts().self().get().email).isNotEqualTo(email);
requestScopeOperations.resetCurrentApiUser();
- String emailOtherCase = email.toUpperCase();
+ String emailOtherCase = email.toUpperCase(Locale.US);
gApi.accounts().self().email(emailOtherCase).setPreferred();
assertThat(gApi.accounts().self().get().email).isEqualTo(email);
}
diff --git a/javatests/com/google/gerrit/acceptance/rest/account/ExternalIdIT.java b/javatests/com/google/gerrit/acceptance/rest/account/ExternalIdIT.java
index 39a32af..61164f7 100644
--- a/javatests/com/google/gerrit/acceptance/rest/account/ExternalIdIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/account/ExternalIdIT.java
@@ -949,7 +949,7 @@
extIdNotes.insert(extId);
extIdNotes.commit(md);
assertThat(getAccountId(extIdNotes, scheme, id)).isEqualTo(accountId.get());
- assertThat(getExternalId(extIdNotes, scheme, id.toLowerCase()).isPresent()).isFalse();
+ assertThat(getExternalId(extIdNotes, scheme, id.toLowerCase(Locale.US)).isPresent()).isFalse();
}
private void testCaseInsensitiveExternalIdKey(
@@ -959,7 +959,8 @@
extIdNotes.insert(extId);
extIdNotes.commit(md);
assertThat(getAccountId(extIdNotes, scheme, id)).isEqualTo(accountId.get());
- assertThat(getAccountId(extIdNotes, scheme, id.toLowerCase())).isEqualTo(accountId.get());
+ assertThat(getAccountId(extIdNotes, scheme, id.toLowerCase(Locale.US)))
+ .isEqualTo(accountId.get());
}
/**
diff --git a/javatests/com/google/gerrit/acceptance/rest/account/PutUsernameIT.java b/javatests/com/google/gerrit/acceptance/rest/account/PutUsernameIT.java
index f46cf0c..f4e9457 100644
--- a/javatests/com/google/gerrit/acceptance/rest/account/PutUsernameIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/account/PutUsernameIT.java
@@ -20,6 +20,7 @@
import com.google.gerrit.acceptance.RestResponse;
import com.google.gerrit.acceptance.config.GerritConfig;
import com.google.gerrit.extensions.api.accounts.UsernameInput;
+import java.util.Locale;
import org.junit.Test;
public class PutUsernameIT extends AbstractDaemonTest {
@@ -46,7 +47,7 @@
@GerritConfig(name = "auth.userNameCaseInsensitive", value = "true")
public void setExistingCaseInsensitive_Conflict() throws Exception {
UsernameInput in = new UsernameInput();
- in.username = admin.username().toUpperCase();
+ in.username = admin.username().toUpperCase(Locale.US);
adminRestSession
.put("/accounts/" + accountCreator.create().id().get() + "/username", in)
.assertConflict();
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/SuggestReviewersIT.java b/javatests/com/google/gerrit/acceptance/rest/change/SuggestReviewersIT.java
index 80bedcd..6dfa82b 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/SuggestReviewersIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/SuggestReviewersIT.java
@@ -47,6 +47,7 @@
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.inject.Inject;
import java.util.List;
+import java.util.Locale;
import java.util.Set;
import java.util.stream.IntStream;
import org.junit.Before;
@@ -336,7 +337,7 @@
reviewers = suggestReviewers(changeId, user1.username() + " example");
assertThat(reviewers).hasSize(1);
- reviewers = suggestReviewers(changeId, user4.email().toLowerCase());
+ reviewers = suggestReviewers(changeId, user4.email().toLowerCase(Locale.US));
assertThat(reviewers).hasSize(1);
assertThat(reviewers.get(0).account.email).isEqualTo(user4.email());
}
diff --git a/javatests/com/google/gerrit/acceptance/server/account/AccountResolverIT.java b/javatests/com/google/gerrit/acceptance/server/account/AccountResolverIT.java
index 6f3aa15..35ecceb 100644
--- a/javatests/com/google/gerrit/acceptance/server/account/AccountResolverIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/account/AccountResolverIT.java
@@ -43,6 +43,7 @@
import com.google.gerrit.testing.ConfigSuite;
import com.google.inject.Inject;
import com.google.inject.Provider;
+import java.util.Locale;
import java.util.Optional;
import org.eclipse.jgit.lib.Config;
import org.junit.Test;
@@ -176,7 +177,7 @@
assertThat(resolve(existingUsername)).containsExactly(idWithUsername);
assertThat(resolve(existingMixedCaseUsername)).containsExactly(idWithMixedCaseUsername);
- assertThat(resolve(existingMixedCaseUsername.toLowerCase()))
+ assertThat(resolve(existingMixedCaseUsername.toLowerCase(Locale.US)))
.containsExactly(idWithMixedCaseUsername);
}
diff --git a/javatests/com/google/gerrit/acceptance/server/mail/ChangeNotificationsIT.java b/javatests/com/google/gerrit/acceptance/server/mail/ChangeNotificationsIT.java
index cced47f..28c795d 100644
--- a/javatests/com/google/gerrit/acceptance/server/mail/ChangeNotificationsIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/mail/ChangeNotificationsIT.java
@@ -17,6 +17,7 @@
import static com.google.common.truth.Truth.assertWithMessage;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allow;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allowLabel;
+import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.block;
import static com.google.gerrit.entities.NotifyConfig.NotifyType.ABANDONED_CHANGES;
import static com.google.gerrit.entities.NotifyConfig.NotifyType.ALL_COMMENTS;
import static com.google.gerrit.entities.NotifyConfig.NotifyType.NEW_CHANGES;
@@ -28,6 +29,7 @@
import static com.google.gerrit.extensions.api.changes.NotifyHandling.OWNER_REVIEWERS;
import static com.google.gerrit.extensions.client.GeneralPreferencesInfo.EmailStrategy.CC_ON_OWN_COMMENTS;
import static com.google.gerrit.extensions.client.GeneralPreferencesInfo.EmailStrategy.ENABLED;
+import static com.google.gerrit.server.group.SystemGroupBackend.ANONYMOUS_USERS;
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
import static com.google.gerrit.server.project.testing.TestLabels.labelBuilder;
import static com.google.gerrit.server.project.testing.TestLabels.value;
@@ -306,6 +308,25 @@
addReviewerToReviewableChange(batch());
}
+ @Test
+ public void addReviewerToChangeNoAnonymousUsersNotified() throws Exception {
+ StagedChange sc = stageReviewableChange();
+ // Remove read permission for anonymous users.
+ projectOperations
+ .project(project)
+ .forUpdate()
+ .add(block(Permission.READ).ref("refs/*").group(ANONYMOUS_USERS))
+ .add(allow(Permission.READ).ref("refs/*").group(REGISTERED_USERS))
+ .update();
+
+ TestAccount reviewer = accountCreator.create("added", "added@example.com", "added", null);
+ addReviewer(singly(), sc.changeId, sc.owner, reviewer.email());
+
+ // No BY_EMAIL cc's.
+ assertThat(sender).sent("newchange", sc).to(reviewer).cc(sc.reviewer).noOneElse();
+ assertThat(sender).didNotSend();
+ }
+
private void addReviewerToReviewableChangeByOwnerCcingSelf(Adder adder) throws Exception {
StagedChange sc = stageReviewableChange();
TestAccount reviewer = accountCreator.create("added", "added@example.com", "added", null);
@@ -672,6 +693,30 @@
}
@Test
+ public void commentOnChangeNotVisibleToAnonymousByReviewer() throws Exception {
+ StagedChange sc = stageReviewableChange();
+
+ // Remove read permission for anonymous users.
+ projectOperations
+ .project(project)
+ .forUpdate()
+ .add(block(Permission.READ).ref("refs/*").group(ANONYMOUS_USERS))
+ .add(allow(Permission.READ).ref("refs/*").group(REGISTERED_USERS))
+ .update();
+
+ review(sc.reviewer, sc.changeId, ENABLED);
+ // Not cc'ed to BY_EMAIL added addresses.
+ assertThat(sender)
+ .sent("comment", sc)
+ .to(sc.owner)
+ .cc(sc.ccer)
+ .bcc(sc.starrer)
+ .bcc(ALL_COMMENTS)
+ .noOneElse();
+ assertThat(sender).didNotSend();
+ }
+
+ @Test
public void commentOnReviewableChangeByOwnerCcingSelf() throws Exception {
StagedChange sc = stageReviewableChange();
review(sc.owner, sc.changeId, CC_ON_OWN_COMMENTS);
diff --git a/javatests/com/google/gerrit/acceptance/server/mail/EmailValidatorIT.java b/javatests/com/google/gerrit/acceptance/server/mail/EmailValidatorIT.java
index cc61dfb..3145234 100644
--- a/javatests/com/google/gerrit/acceptance/server/mail/EmailValidatorIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/mail/EmailValidatorIT.java
@@ -26,6 +26,7 @@
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
+import java.util.Locale;
import org.junit.After;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -83,12 +84,13 @@
continue;
}
if (tld.startsWith(UNSUPPORTED_PREFIX)) {
- String test = "test@example." + tld.toLowerCase().substring(UNSUPPORTED_PREFIX.length());
+ String test =
+ "test@example." + tld.toLowerCase(Locale.US).substring(UNSUPPORTED_PREFIX.length());
assertWithMessage("expected invalid TLD \"" + test + "\"")
.that(validator.isValid(test))
.isFalse();
} else {
- String test = "test@example." + tld.toLowerCase();
+ String test = "test@example." + tld.toLowerCase(Locale.US);
assertWithMessage("failed to validate TLD \"" + test + "\"")
.that(validator.isValid(test))
.isTrue();
diff --git a/javatests/com/google/gerrit/gpg/PublicKeyStoreTest.java b/javatests/com/google/gerrit/gpg/PublicKeyStoreTest.java
index 3727d38..a01807a 100644
--- a/javatests/com/google/gerrit/gpg/PublicKeyStoreTest.java
+++ b/javatests/com/google/gerrit/gpg/PublicKeyStoreTest.java
@@ -33,6 +33,7 @@
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
+import java.util.Locale;
import java.util.Set;
import java.util.TreeSet;
import org.bouncycastle.openpgp.PGPPublicKey;
@@ -80,7 +81,7 @@
PGPPublicKey key = validKeyWithoutExpiration().getPublicKey();
String objId = keyObjectId(key.getKeyID()).name();
assertEquals("ed0625dc46328a8c000000000000000000000000", objId);
- assertEquals(keyIdToString(key.getKeyID()).toLowerCase(), objId.substring(8, 16));
+ assertEquals(keyIdToString(key.getKeyID()).toLowerCase(Locale.US), objId.substring(8, 16));
}
@Test
diff --git a/javatests/com/google/gerrit/httpd/raw/ResourceServletTest.java b/javatests/com/google/gerrit/httpd/raw/ResourceServletTest.java
index 36641fe..8a2de7d 100644
--- a/javatests/com/google/gerrit/httpd/raw/ResourceServletTest.java
+++ b/javatests/com/google/gerrit/httpd/raw/ResourceServletTest.java
@@ -40,6 +40,7 @@
import java.time.LocalDateTime;
import java.time.Month;
import java.time.ZoneOffset;
+import java.util.Locale;
import java.util.concurrent.atomic.AtomicLong;
import java.util.zip.GZIPInputStream;
import org.junit.Before;
@@ -331,7 +332,7 @@
}
private static void assertCacheable(FakeHttpServletResponse res, boolean revalidate) {
- String header = res.getHeader("Cache-Control").toLowerCase();
+ String header = res.getHeader("Cache-Control").toLowerCase(Locale.US);
assertThat(header).contains("public");
if (revalidate) {
assertThat(header).contains("must-revalidate");
diff --git a/javatests/com/google/gerrit/server/IdentifiedUserTest.java b/javatests/com/google/gerrit/server/IdentifiedUserTest.java
index 30ae4aa..ce045f7 100644
--- a/javatests/com/google/gerrit/server/IdentifiedUserTest.java
+++ b/javatests/com/google/gerrit/server/IdentifiedUserTest.java
@@ -37,6 +37,7 @@
import com.google.inject.Injector;
import java.util.Arrays;
import java.util.HashSet;
+import java.util.Locale;
import java.util.Set;
import org.eclipse.jgit.lib.Config;
import org.junit.Before;
@@ -114,14 +115,14 @@
@Test
public void emailsExistence() {
assertThat(identifiedUser.hasEmailAddress(TEST_CASES[0])).isTrue();
- assertThat(identifiedUser.hasEmailAddress(TEST_CASES[1].toLowerCase())).isTrue();
+ assertThat(identifiedUser.hasEmailAddress(TEST_CASES[1].toLowerCase(Locale.US))).isTrue();
assertThat(identifiedUser.hasEmailAddress(TEST_CASES[1])).isTrue();
- assertThat(identifiedUser.hasEmailAddress(TEST_CASES[1].toUpperCase())).isTrue();
+ assertThat(identifiedUser.hasEmailAddress(TEST_CASES[1].toUpperCase(Locale.US))).isTrue();
/* assert again to test cached email address by IdentifiedUser.validEmails */
assertThat(identifiedUser.hasEmailAddress(TEST_CASES[1])).isTrue();
assertThat(identifiedUser.hasEmailAddress(TEST_CASES[2])).isTrue();
- assertThat(identifiedUser.hasEmailAddress(TEST_CASES[2].toLowerCase())).isTrue();
+ assertThat(identifiedUser.hasEmailAddress(TEST_CASES[2].toLowerCase(Locale.US))).isTrue();
assertThat(identifiedUser.hasEmailAddress("non-exist@email.com")).isFalse();
/* assert again to test cached email address by IdentifiedUser.invalidEmails */
diff --git a/javatests/com/google/gerrit/server/cache/PerThreadProjectCacheTest.java b/javatests/com/google/gerrit/server/cache/PerThreadProjectCacheTest.java
index b9c1897..055b95d 100644
--- a/javatests/com/google/gerrit/server/cache/PerThreadProjectCacheTest.java
+++ b/javatests/com/google/gerrit/server/cache/PerThreadProjectCacheTest.java
@@ -25,7 +25,7 @@
try (PerThreadCache cache = PerThreadCache.create()) {
PerThreadCache.Key<Project.NameKey> key =
PerThreadCache.Key.create(Project.NameKey.class, Project.nameKey("test-project"));
- String unused = PerThreadProjectCache.getOrCompute(key, () -> "cached");
+ PerThreadProjectCache.getOrCompute(key, () -> "cached");
String value = PerThreadProjectCache.getOrCompute(key, () -> "directly served");
assertThat(value).isEqualTo("cached");
}
@@ -38,12 +38,12 @@
for (int i = 0; i < 50; i++) {
PerThreadCache.Key<Project.NameKey> key =
PerThreadCache.Key.create(Project.NameKey.class, Project.nameKey("test-project" + i));
- String unused = PerThreadProjectCache.getOrCompute(key, () -> "cached");
+ PerThreadProjectCache.getOrCompute(key, () -> "cached");
}
// Assert that the value was not persisted
PerThreadCache.Key<Project.NameKey> key =
PerThreadCache.Key.create(Project.NameKey.class, "Project" + 1000);
- String unused = PerThreadProjectCache.getOrCompute(key, () -> "new value");
+ PerThreadProjectCache.getOrCompute(key, () -> "new value");
String value = PerThreadProjectCache.getOrCompute(key, () -> "directly served");
assertThat(value).isEqualTo("directly served");
}
diff --git a/javatests/com/google/gerrit/server/index/IndexedFieldTest.java b/javatests/com/google/gerrit/server/index/IndexedFieldTest.java
index dacc37d..5029334 100644
--- a/javatests/com/google/gerrit/server/index/IndexedFieldTest.java
+++ b/javatests/com/google/gerrit/server/index/IndexedFieldTest.java
@@ -61,7 +61,6 @@
import org.junit.runner.RunWith;
/** Tests for {@link com.google.gerrit.index.IndexedField} */
-@SuppressWarnings("serial")
@RunWith(Theories.class)
public class IndexedFieldTest {
diff --git a/javatests/com/google/gerrit/server/query/account/AbstractQueryAccountsTest.java b/javatests/com/google/gerrit/server/query/account/AbstractQueryAccountsTest.java
index 1fede32..aea4b95 100644
--- a/javatests/com/google/gerrit/server/query/account/AbstractQueryAccountsTest.java
+++ b/javatests/com/google/gerrit/server/query/account/AbstractQueryAccountsTest.java
@@ -94,6 +94,7 @@
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
+import java.util.Locale;
import java.util.Optional;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
@@ -242,7 +243,7 @@
assertQuery(user5.email, user5);
assertQuery("email:" + user5.email, user5);
- assertQuery("email:" + user5.email.toUpperCase(), user5);
+ assertQuery("email:" + user5.email.toUpperCase(Locale.US), user5);
}
@Test
@@ -289,7 +290,7 @@
assertQuery(user1.username, user1);
assertQuery("username:" + user1.username, user1);
- assertQuery("username:" + user1.username.toUpperCase(), user1);
+ assertQuery("username:" + user1.username.toUpperCase(Locale.US), user1);
}
@Test
diff --git a/javatests/com/google/gerrit/util/http/testutil/FakeHttpServletResponse.java b/javatests/com/google/gerrit/util/http/testutil/FakeHttpServletResponse.java
index f39b875..18714ac 100644
--- a/javatests/com/google/gerrit/util/http/testutil/FakeHttpServletResponse.java
+++ b/javatests/com/google/gerrit/util/http/testutil/FakeHttpServletResponse.java
@@ -171,7 +171,7 @@
@Override
public void addHeader(String name, String value) {
- headers.put(name.toLowerCase(), value);
+ headers.put(name.toLowerCase(Locale.US), value);
}
@Override
@@ -181,7 +181,7 @@
@Override
public boolean containsHeader(String name) {
- return headers.containsKey(name.toLowerCase());
+ return headers.containsKey(name.toLowerCase(Locale.US));
}
@Override
@@ -232,13 +232,13 @@
@Override
public void setHeader(String name, String value) {
- headers.removeAll(name.toLowerCase());
+ headers.removeAll(name.toLowerCase(Locale.US));
addHeader(name, value);
}
@Override
public void setIntHeader(String name, int value) {
- headers.removeAll(name.toLowerCase());
+ headers.removeAll(name.toLowerCase(Locale.US));
addIntHeader(name, value);
}
@@ -262,7 +262,7 @@
@Override
public String getHeader(String name) {
- return Iterables.getFirst(headers.get(requireNonNull(name.toLowerCase())), null);
+ return Iterables.getFirst(headers.get(requireNonNull(name.toLowerCase(Locale.US))), null);
}
@Override
@@ -272,7 +272,7 @@
@Override
public Collection<String> getHeaders(String name) {
- return headers.get(requireNonNull(name.toLowerCase()));
+ return headers.get(requireNonNull(name.toLowerCase(Locale.US)));
}
public byte[] getActualBody() {
diff --git a/modules/jgit b/modules/jgit
index 176f17d..0687c73 160000
--- a/modules/jgit
+++ b/modules/jgit
@@ -1 +1 @@
-Subproject commit 176f17d05ec154ce455ab2bde7429017d43d67fb
+Subproject commit 0687c73a12b5157c350de430f62ea8243d813e19
diff --git a/plugins/package.json b/plugins/package.json
index 612062b..2299a93 100644
--- a/plugins/package.json
+++ b/plugins/package.json
@@ -32,7 +32,7 @@
"@codemirror/theme-one-dark": "^6.1.1",
"@codemirror/view": "^6.9.1",
"lit": "^2.2.3",
- "rxjs": "^6.6.7",
+ "rxjs": "^7.8.0",
"sinon": "^13.0.0"
},
"license": "Apache-2.0",
diff --git a/plugins/reviewnotes b/plugins/reviewnotes
index 10db2cf..158435d 160000
--- a/plugins/reviewnotes
+++ b/plugins/reviewnotes
@@ -1 +1 @@
-Subproject commit 10db2cf772989d031c6f3558010c51fe07cf9722
+Subproject commit 158435d2aa9f8729e4e78835969e54701af9203b
diff --git a/plugins/webhooks b/plugins/webhooks
index 16110f3..1dc0a71 160000
--- a/plugins/webhooks
+++ b/plugins/webhooks
@@ -1 +1 @@
-Subproject commit 16110f320dd5b6a40af87eaba4bf3af60cb0efd1
+Subproject commit 1dc0a718839f8872a59c189da7243ee77a4fe782
diff --git a/plugins/yarn.lock b/plugins/yarn.lock
index 3156f4c..bad5fcc 100644
--- a/plugins/yarn.lock
+++ b/plugins/yarn.lock
@@ -2480,12 +2480,12 @@
dependencies:
queue-microtask "^1.2.2"
-rxjs@^6.6.7:
- version "6.6.7"
- resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9"
- integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==
+rxjs@^7.8.0:
+ version "7.8.0"
+ resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.0.tgz#90a938862a82888ff4c7359811a595e14e1e09a4"
+ integrity sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==
dependencies:
- tslib "^1.9.0"
+ tslib "^2.1.0"
safe-buffer@5.2.1, safe-buffer@~5.2.0:
version "5.2.1"
@@ -2681,10 +2681,10 @@
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==
-tslib@^1.9.0:
- version "1.14.1"
- resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
- integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
+tslib@^2.1.0:
+ version "2.5.0"
+ resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf"
+ integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==
tsscmp@1.0.6:
version "1.0.6"
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-action-bar/gr-change-list-action-bar_test.ts b/polygerrit-ui/app/elements/change-list/gr-change-list-action-bar/gr-change-list-action-bar_test.ts
index 7a4f97c..4b7f0a3 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list-action-bar/gr-change-list-action-bar_test.ts
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list-action-bar/gr-change-list-action-bar_test.ts
@@ -19,7 +19,7 @@
} from '../../../test/test-utils';
import {ChangeInfo, NumericChangeId} from '../../../types/common';
import './gr-change-list-action-bar';
-import type {GrChangeListActionBar} from './gr-change-list-action-bar';
+import {GrChangeListActionBar} from './gr-change-list-action-bar';
const change1 = {...createChange(), _number: 1 as NumericChangeId, actions: {}};
const change2 = {...createChange(), _number: 2 as NumericChangeId, actions: {}};
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-hashtag-flow/gr-change-list-hashtag-flow_test.ts b/polygerrit-ui/app/elements/change-list/gr-change-list-hashtag-flow/gr-change-list-hashtag-flow_test.ts
index 0cc3e18..af997a9 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list-hashtag-flow/gr-change-list-hashtag-flow_test.ts
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list-hashtag-flow/gr-change-list-hashtag-flow_test.ts
@@ -32,7 +32,7 @@
import {GrAutocomplete} from '../../shared/gr-autocomplete/gr-autocomplete';
import {GrButton} from '../../shared/gr-button/gr-button';
import './gr-change-list-hashtag-flow';
-import type {GrChangeListHashtagFlow} from './gr-change-list-hashtag-flow';
+import {GrChangeListHashtagFlow} from './gr-change-list-hashtag-flow';
suite('gr-change-list-hashtag-flow tests', () => {
let element: GrChangeListHashtagFlow;
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-reviewer-flow/gr-change-list-reviewer-flow_test.ts b/polygerrit-ui/app/elements/change-list/gr-change-list-reviewer-flow/gr-change-list-reviewer-flow_test.ts
index 85e6212..d2f5fa2 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list-reviewer-flow/gr-change-list-reviewer-flow_test.ts
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list-reviewer-flow/gr-change-list-reviewer-flow_test.ts
@@ -41,7 +41,7 @@
import {GrButton} from '../../shared/gr-button/gr-button';
import {GrDialog} from '../../shared/gr-dialog/gr-dialog';
import './gr-change-list-reviewer-flow';
-import type {GrChangeListReviewerFlow} from './gr-change-list-reviewer-flow';
+import {GrChangeListReviewerFlow} from './gr-change-list-reviewer-flow';
const accounts: AccountInfo[] = [
createAccountWithIdNameAndEmail(0),
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-topic-flow/gr-change-list-topic-flow_test.ts b/polygerrit-ui/app/elements/change-list/gr-change-list-topic-flow/gr-change-list-topic-flow_test.ts
index d2dced2..489d8ee 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list-topic-flow/gr-change-list-topic-flow_test.ts
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list-topic-flow/gr-change-list-topic-flow_test.ts
@@ -32,7 +32,7 @@
import {GrAutocomplete} from '../../shared/gr-autocomplete/gr-autocomplete';
import {GrButton} from '../../shared/gr-button/gr-button';
import './gr-change-list-topic-flow';
-import type {GrChangeListTopicFlow} from './gr-change-list-topic-flow';
+import {GrChangeListTopicFlow} from './gr-change-list-topic-flow';
suite('gr-change-list-topic-flow tests', () => {
let element: GrChangeListTopicFlow;
diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.ts b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.ts
index 38acf80..7c85bb6 100644
--- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.ts
+++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.ts
@@ -89,7 +89,6 @@
fireError,
fire,
fireNoBubble,
- fireNoBubbleNoCompose,
fireIronAnnounce,
fireReload,
fireServerError,
@@ -121,7 +120,7 @@
import {customElement, property, state, query} from 'lit/decorators.js';
import {subscribe} from '../../lit/subscription-controller';
import {configModelToken} from '../../../models/config/config-model';
-import {hasHumanReviewer, isOwner} from '../../../utils/change-util';
+import {hasHumanReviewer} from '../../../utils/change-util';
import {commentsModelToken} from '../../../models/comments/comments-model';
import {
CommentEditingChangedDetail,
@@ -301,9 +300,6 @@
reviewerPendingConfirmation: SuggestedReviewerGroupInfo | null = null;
@state()
- sendButtonLabel?: string;
-
- @state()
savingComments = false;
@state()
@@ -336,14 +332,14 @@
newAttentionSet: Set<UserId> = new Set();
@state()
- sendDisabled?: boolean;
-
- @state()
patchsetLevelDraftIsResolved = true;
@state()
patchsetLevelComment?: UnsavedInfo | DraftInfo;
+ @state()
+ isOwner = false;
+
private readonly restApiService: RestApiService =
getAppContext().restApiService;
@@ -619,6 +615,11 @@
);
subscribe(
this,
+ () => this.getChangeModel().isOwner$,
+ x => (this.isOwner = x)
+ );
+ subscribe(
+ this,
() => this.getCommentsModel().mentionedUsersInDrafts$,
x => {
this.mentionedUsers = x;
@@ -712,10 +713,6 @@
}
if (changedProperties.has('canBeStarted')) {
this.computeMessagePlaceholder();
- this.computeSendButtonLabel();
- }
- if (changedProperties.has('sendDisabled')) {
- this.sendDisabledChanged();
}
if (changedProperties.has('attentionExpanded')) {
this.onAttentionExpandedChange();
@@ -743,7 +740,6 @@
override render() {
if (!this.change) return;
- this.sendDisabled = this.computeSendButtonDisabled();
return html`
<div tabindex="-1">
<section class="peopleContainer">
@@ -1015,7 +1011,7 @@
<gr-button
class="edit-attention-button"
@click=${this.handleAttentionModify}
- ?disabled=${this.sendDisabled}
+ ?disabled=${this.isSendDisabled()}
link
position-below
data-label="Edit"
@@ -1214,10 +1210,12 @@
<gr-button
id="sendButton"
primary
- ?disabled=${this.sendDisabled}
+ ?disabled=${this.isSendDisabled()}
class="action send"
- @click=${this.sendTapHandler}
- >${this.sendButtonLabel}
+ @click=${this.sendClickHandler}
+ >${this.canBeStarted
+ ? ButtonLabels.SEND + ' and ' + ButtonLabels.START_REVIEW
+ : ButtonLabels.SEND}
</gr-button>
</gr-tooltip-content>
</div>
@@ -1352,6 +1350,7 @@
);
}
+ // visible for testing
async send(includeComments: boolean, startReview: boolean) {
this.reporting.time(Timing.SEND_REPLY);
const labels = this.getLabelScores().getLabelValues();
@@ -1473,16 +1472,11 @@
}
chooseFocusTarget() {
- if (!isOwner(this.change, this.account)) return FocusTarget.BODY;
+ if (!this.isOwner) return FocusTarget.BODY;
if (hasHumanReviewer(this.change)) return FocusTarget.BODY;
return FocusTarget.REVIEWERS;
}
- isOwner(account?: AccountInfo, change?: ParsedChangeInfo | ChangeInfo) {
- if (!account || !change || !change.owner) return false;
- return account._account_id === change.owner._account_id;
- }
-
handle400Error(r?: Response | null) {
if (!r) throw new Error('Response is empty.');
let response: Response = r;
@@ -1557,8 +1551,8 @@
fire(this, 'iron-resize', {});
}
- computeAttentionButtonTitle(sendDisabled?: boolean) {
- return sendDisabled
+ computeAttentionButtonTitle() {
+ return this.isSendDisabled()
? 'Modify the attention set by adding a comment or use the account ' +
'hovercard in the change page.'
: 'Edit attention set changes';
@@ -1606,7 +1600,6 @@
? this.draftCommentThreads
: [];
const hasVote = !!this.labelsChanged;
- const isOwner = this.isOwner(this.account, this.change);
const isUploader = this.uploader?._account_id === this.account._account_id;
this.attentionCcsCount = removeServiceUsers(this.ccs).length;
@@ -1640,7 +1633,7 @@
.filter(
r =>
isAccountNewlyAdded(r, ReviewerState.REVIEWER, this.change) ||
- (this.canBeStarted && isOwner)
+ (this.canBeStarted && this.isOwner)
)
.filter(notIsReviewerAndHasDraftOrLabel)
.forEach(r => newAttention.add((r as AccountInfo)._account_id!));
@@ -1649,7 +1642,7 @@
if (this.uploader?._account_id && !isUploader) {
newAttention.add(this.uploader._account_id);
}
- if (this.change.owner?._account_id && !isOwner) {
+ if (this.change.owner?._account_id && !this.isOwner) {
newAttention.add(this.change.owner._account_id);
}
}
@@ -1677,18 +1670,11 @@
}
computeShowAttentionTip() {
- if (
- !this.account ||
- !this.change?.owner ||
- !this.currentAttentionSet ||
- !this.newAttentionSet
- )
- return false;
- const isOwner = this.account._account_id === this.change.owner._account_id;
+ if (!this.currentAttentionSet || !this.newAttentionSet) return false;
const addedIds = [...this.newAttentionSet].filter(
id => !this.currentAttentionSet.has(id)
);
- return isOwner && addedIds.length > 2;
+ return this.isOwner && addedIds.length > 2;
}
computeCommentAccounts(threads: CommentThread[]) {
@@ -1710,13 +1696,15 @@
}
computeShowNoAttentionUpdate() {
- return this.sendDisabled || this.computeNewAttentionAccounts().length === 0;
+ return (
+ this.isSendDisabled() || this.computeNewAttentionAccounts().length === 0
+ );
}
computeDoNotUpdateMessage() {
if (!this.currentAttentionSet || !this.newAttentionSet) return '';
if (
- this.sendDisabled ||
+ this.isSendDisabled() ||
areSetsEqual(this.currentAttentionSet, this.newAttentionSet)
) {
return 'No changes to the attention set.';
@@ -1828,32 +1816,30 @@
this.rebuildReviewerArrays();
}
- saveClickHandler(e: Event) {
+ private saveClickHandler(e: Event) {
e.preventDefault();
- if (!this.ccsList?.submitEntryText()) {
- // Do not proceed with the save if there is an invalid email entry in
- // the text field of the CC entry.
- return;
+ this.submit(false);
+ }
+
+ private sendClickHandler(e: Event) {
+ e.preventDefault();
+ this.submit(this.canBeStarted);
+ }
+
+ private submit(startReview?: boolean) {
+ if (startReview === undefined) {
+ startReview = this.isOwner && this.canBeStarted;
}
- this.send(this.includeComments, false);
- }
-
- sendTapHandler(e: Event) {
- e.preventDefault();
- this.submit();
- }
-
- submit() {
if (!this.ccsList?.submitEntryText()) {
// Do not proceed with the send if there is an invalid email entry in
// the text field of the CC entry.
return;
}
- if (this.sendDisabled) {
+ if (this.isSendDisabled()) {
fireAlert(this, EMPTY_REPLY_MESSAGE);
return;
}
- return this.send(this.includeComments, this.canBeStarted).catch(err => {
+ return this.send(this.includeComments, startReview).catch(err => {
fireError(this, `Error submitting review ${err}`);
});
}
@@ -1965,12 +1951,6 @@
this.cancel();
}
- computeSendButtonLabel() {
- this.sendButtonLabel = this.canBeStarted
- ? ButtonLabels.SEND + ' and ' + ButtonLabels.START_REVIEW
- : ButtonLabels.SEND;
- }
-
computeSendButtonTooltip(canBeStarted?: boolean, commentEditing?: boolean) {
if (commentEditing) {
return ButtonTooltips.DISABLED_COMMENT_EDITING;
@@ -1982,7 +1962,8 @@
return savingComments ? 'saving' : '';
}
- computeSendButtonDisabled() {
+ // visible for testing
+ isSendDisabled() {
if (
this.canBeStarted === undefined ||
this.patchsetLevelDraftMessage === undefined ||
@@ -2030,10 +2011,6 @@
this.pluginMessage = message;
}
- sendDisabledChanged() {
- fireNoBubbleNoCompose(this, 'send-disabled-changed', {});
- }
-
getReviewerSuggestionsProvider(change?: ChangeInfo | ParsedChangeInfo) {
if (!change) return;
const provider = new GrReviewerSuggestionsProvider(
diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.ts b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.ts
index 465f64d..126343e 100644
--- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.ts
+++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.ts
@@ -16,7 +16,11 @@
stubRestApi,
waitUntilVisible,
} from '../../../test/test-utils';
-import {ChangeStatus, ReviewerState} from '../../../constants/constants';
+import {
+ ChangeStatus,
+ DraftsAction,
+ ReviewerState,
+} from '../../../constants/constants';
import {JSON_PREFIX} from '../../shared/gr-rest-api-interface/gr-rest-apis/gr-rest-api-helper';
import {StandardLabels} from '../../../utils/label-util';
import {
@@ -65,6 +69,7 @@
CommentsModel,
commentsModelToken,
} from '../../../models/comments/comments-model';
+import {isOwner} from '../../../utils/change-util';
function cloneableResponse(status: number, text: string) {
return {
@@ -177,9 +182,9 @@
);
}
- function interceptSaveReview() {
+ function interceptSaveReview(): Promise<ReviewInput> {
let resolver: (review: ReviewInput) => void;
- const promise = new Promise(resolve => {
+ const promise = new Promise<ReviewInput>(resolve => {
resolver = resolve;
});
stubSaveReview((review: ReviewInput) => {
@@ -257,7 +262,7 @@
<span> No changes to the attention set. </span>
<gr-tooltip-content
has-tooltip=""
- title="Edit attention set changes"
+ title="Modify the attention set by adding a comment or use the account hovercard in the change page."
>
<gr-button
aria-disabled="true"
@@ -459,14 +464,17 @@
const review = await saveReviewPromise;
assert.deepEqual(review, {
- drafts: 'PUBLISH_ALL_REVISIONS',
+ drafts: DraftsAction.PUBLISH_ALL_REVISIONS,
labels: {
'Code-Review': 0,
Verified: 0,
},
reviewers: [],
add_to_attention_set: [
- {reason: '<GERRIT_ACCOUNT_1> replied on the change', user: 999},
+ {
+ reason: '<GERRIT_ACCOUNT_1> replied on the change',
+ user: 999 as UserId,
+ },
],
remove_from_attention_set: [],
ignore_automatic_attention_set_rules: true,
@@ -492,13 +500,16 @@
const review = await saveReviewPromise;
assert.deepEqual(review, {
- drafts: 'PUBLISH_ALL_REVISIONS',
+ drafts: DraftsAction.PUBLISH_ALL_REVISIONS,
labels: {
'Code-Review': 0,
Verified: 0,
},
add_to_attention_set: [
- {reason: '<GERRIT_ACCOUNT_123> replied on the change', user: 314},
+ {
+ reason: '<GERRIT_ACCOUNT_123> replied on the change',
+ user: 314 as UserId,
+ },
],
reviewers: [],
ready: true,
@@ -523,14 +534,17 @@
const review = await saveReviewPromise;
assert.deepEqual(review, {
- drafts: 'PUBLISH_ALL_REVISIONS',
+ drafts: DraftsAction.PUBLISH_ALL_REVISIONS,
labels: {
'Code-Review': 0,
Verified: 0,
},
add_to_attention_set: [
// Name coming from createUserConfig in test-data-generator
- {reason: 'Name of user not set replied on the change', user: 314},
+ {
+ reason: 'Name of user not set replied on the change',
+ user: 314 as UserId,
+ },
],
reviewers: [],
ready: true,
@@ -598,6 +612,7 @@
element._ccs = [];
element.draftCommentThreads = draftThreads;
element.includeComments = includeComments;
+ element.isOwner = isOwner(change, element.account);
await element.updateComplete;
@@ -1067,6 +1082,7 @@
// If the change is "work in progress" and the owner sends a reply, then
// add all reviewers.
element.canBeStarted = true;
+ element.isOwner = isOwner(element.change, element.account);
element.computeNewAttention();
await element.updateComplete;
assert.sameMembers(
@@ -1076,6 +1092,7 @@
// ... but not when someone else replies.
element.account = {_account_id: 4 as AccountId};
+ element.isOwner = isOwner(element.change, element.account);
element.computeNewAttention();
assert.sameMembers([...element.newAttentionSet], []);
});
@@ -1195,14 +1212,17 @@
await waitUntil(() => element.disabled === false);
assert.equal(element.patchsetLevelDraftMessage.length, 0);
assert.deepEqual(review, {
- drafts: 'PUBLISH_ALL_REVISIONS',
+ drafts: DraftsAction.PUBLISH_ALL_REVISIONS,
labels: {
'Code-Review': -1,
Verified: -1,
},
reviewers: [],
add_to_attention_set: [
- {user: 999, reason: '<GERRIT_ACCOUNT_1> replied on the change'},
+ {
+ user: 999 as UserId,
+ reason: '<GERRIT_ACCOUNT_1> replied on the change',
+ },
],
remove_from_attention_set: [],
ignore_automatic_attention_set_rules: true,
@@ -1231,14 +1251,17 @@
const review = await saveReviewPromise;
await element.updateComplete;
assert.deepEqual(review, {
- drafts: 'KEEP',
+ drafts: DraftsAction.KEEP,
labels: {
'Code-Review': 0,
Verified: 0,
},
reviewers: [],
add_to_attention_set: [
- {reason: '<GERRIT_ACCOUNT_1> replied on the change', user: 999},
+ {
+ reason: '<GERRIT_ACCOUNT_1> replied on the change',
+ user: 999 as UserId,
+ },
],
remove_from_attention_set: [],
ignore_automatic_attention_set_rules: true,
@@ -1636,10 +1659,10 @@
});
test('chooseFocusTarget', () => {
- element.account = undefined;
+ element.isOwner = false;
assert.equal(element.chooseFocusTarget(), element.FocusTarget.BODY);
- element.account = element.change!.owner;
+ element.isOwner = true;
assert.equal(element.chooseFocusTarget(), element.FocusTarget.REVIEWERS);
element.change!.reviewers.REVIEWER = [createAccountWithId(314)];
@@ -2087,16 +2110,26 @@
pressKey(element, Key.ENTER);
});
- test('emit send on ctrl+enter key', async () => {
- // required so that "Send" button is enabled
+ test('send and start review on ctrl+enter for owner', async () => {
element.canBeStarted = true;
+ element.isOwner = true;
await element.updateComplete;
- stubSaveReview(() => undefined);
- const promise = mockPromise();
- element.addEventListener('send', () => promise.resolve());
+ const savePromise = interceptSaveReview();
pressKey(element, Key.ENTER, Modifier.CTRL_KEY);
- await promise;
+ const reviewInput = await savePromise;
+ assert.isTrue(reviewInput.ready);
+ });
+
+ test('save on ctrl+enter for reviewer', async () => {
+ element.canBeStarted = true;
+ element.isOwner = false;
+ await element.updateComplete;
+
+ const savePromise = interceptSaveReview();
+ pressKey(element, Key.ENTER, Modifier.CTRL_KEY);
+ const reviewInput = await savePromise;
+ assert.isUndefined(reviewInput.ready);
});
test('computeMessagePlaceholder', async () => {
@@ -2112,14 +2145,14 @@
);
});
- test('computeSendButtonLabel', async () => {
+ test('sendButton text', async () => {
element.canBeStarted = false;
await element.updateComplete;
- assert.equal(element.sendButtonLabel, 'Send');
+ assert.equal(element.sendButton?.innerText, 'SEND');
element.canBeStarted = true;
await element.updateComplete;
- assert.equal(element.sendButtonLabel, 'Send and Start review');
+ assert.equal(element.sendButton?.innerText, 'SEND AND START REVIEW');
});
test('handle400Error reviewers and CCs', async () => {
@@ -2239,7 +2272,7 @@
});
});
- test('computeSendButtonDisabled_canBeStarted', () => {
+ test('isSendDisabled_canBeStarted', () => {
// Mock canBeStarted
element.canBeStarted = true;
element.draftCommentThreads = [];
@@ -2250,10 +2283,10 @@
element.disabled = false;
element.commentEditing = false;
element.account = makeAccount();
- assert.isFalse(element.computeSendButtonDisabled());
+ assert.isFalse(element.isSendDisabled());
});
- test('computeSendButtonDisabled_allFalse', () => {
+ test('isSendDisabled_allFalse', () => {
// Mock everything false
element.canBeStarted = false;
element.draftCommentThreads = [];
@@ -2264,10 +2297,10 @@
element.disabled = false;
element.commentEditing = false;
element.account = makeAccount();
- assert.isTrue(element.computeSendButtonDisabled());
+ assert.isTrue(element.isSendDisabled());
});
- test('computeSendButtonDisabled_draftCommentsSend', () => {
+ test('isSendDisabled_draftCommentsSend', () => {
// Mock nonempty comment draft array; with sending comments.
element.canBeStarted = false;
element.draftCommentThreads = [{...createCommentThread([createComment()])}];
@@ -2278,10 +2311,10 @@
element.disabled = false;
element.commentEditing = false;
element.account = makeAccount();
- assert.isFalse(element.computeSendButtonDisabled());
+ assert.isFalse(element.isSendDisabled());
});
- test('computeSendButtonDisabled_draftCommentsDoNotSend', () => {
+ test('isSendDisabled_draftCommentsDoNotSend', () => {
// Mock nonempty comment draft array; without sending comments.
element.canBeStarted = false;
element.draftCommentThreads = [{...createCommentThread([createComment()])}];
@@ -2293,10 +2326,10 @@
element.commentEditing = false;
element.account = makeAccount();
- assert.isTrue(element.computeSendButtonDisabled());
+ assert.isTrue(element.isSendDisabled());
});
- test('computeSendButtonDisabled_changeMessage', () => {
+ test('isSendDisabled_changeMessage', () => {
// Mock nonempty change message.
element.canBeStarted = false;
element.draftCommentThreads = [{...createCommentThread([createComment()])}];
@@ -2308,10 +2341,10 @@
element.commentEditing = false;
element.account = makeAccount();
- assert.isFalse(element.computeSendButtonDisabled());
+ assert.isFalse(element.isSendDisabled());
});
- test('computeSendButtonDisabledreviewersChanged', () => {
+ test('isSendDisabledreviewersChanged', () => {
// Mock reviewers mutated.
element.canBeStarted = false;
element.draftCommentThreads = [{...createCommentThread([createComment()])}];
@@ -2323,10 +2356,10 @@
element.commentEditing = false;
element.account = makeAccount();
- assert.isFalse(element.computeSendButtonDisabled());
+ assert.isFalse(element.isSendDisabled());
});
- test('computeSendButtonDisabled_labelsChanged', () => {
+ test('isSendDisabled_labelsChanged', () => {
// Mock labels changed.
element.canBeStarted = false;
element.draftCommentThreads = [{...createCommentThread([createComment()])}];
@@ -2338,10 +2371,10 @@
element.commentEditing = false;
element.account = makeAccount();
- assert.isFalse(element.computeSendButtonDisabled());
+ assert.isFalse(element.isSendDisabled());
});
- test('computeSendButtonDisabled_dialogDisabled', () => {
+ test('isSendDisabled_dialogDisabled', () => {
// Whole dialog is disabled.
element.canBeStarted = false;
element.draftCommentThreads = [{...createCommentThread([createComment()])}];
@@ -2353,10 +2386,10 @@
element.commentEditing = false;
element.account = makeAccount();
- assert.isTrue(element.computeSendButtonDisabled());
+ assert.isTrue(element.isSendDisabled());
});
- test('computeSendButtonDisabled_existingVote', async () => {
+ test('isSendDisabled_existingVote', async () => {
const account = createAccountWithId();
(
element.change!.labels![StandardLabels.CODE_REVIEW]! as DetailedLabelInfo
@@ -2372,7 +2405,7 @@
element.account = account;
// User has already voted.
- assert.isFalse(element.computeSendButtonDisabled());
+ assert.isFalse(element.isSendDisabled());
});
test('_submit blocked when no mutations exist', async () => {
@@ -2428,19 +2461,19 @@
});
test('send button updates state as text is typed in patchset comment', async () => {
- assert.isTrue(element.computeSendButtonDisabled());
+ assert.isTrue(element.isSendDisabled());
queryAndAssert<GrComment>(element, '#patchsetLevelComment').messageText =
'hello';
await waitUntil(() => element.patchsetLevelDraftMessage === 'hello');
- assert.isFalse(element.computeSendButtonDisabled());
+ assert.isFalse(element.isSendDisabled());
queryAndAssert<GrComment>(element, '#patchsetLevelComment').messageText =
'';
await waitUntil(() => element.patchsetLevelDraftMessage === '');
- assert.isTrue(element.computeSendButtonDisabled());
+ assert.isTrue(element.isSendDisabled());
});
test('sending patchset level comment', async () => {
@@ -2468,14 +2501,17 @@
assert.deepEqual(autoSaveStub.callCount, 1);
assert.deepEqual(review, {
- drafts: 'PUBLISH_ALL_REVISIONS',
+ drafts: DraftsAction.PUBLISH_ALL_REVISIONS,
labels: {
'Code-Review': 0,
Verified: 0,
},
reviewers: [],
add_to_attention_set: [
- {reason: '<GERRIT_ACCOUNT_1> replied on the change', user: 999},
+ {
+ reason: '<GERRIT_ACCOUNT_1> replied on the change',
+ user: 999 as UserId,
+ },
],
remove_from_attention_set: [],
ignore_automatic_attention_set_rules: true,
diff --git a/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.ts b/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.ts
index de6a39c..c38e788 100644
--- a/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.ts
+++ b/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.ts
@@ -237,7 +237,7 @@
* This is triggered when the user types into the editing textarea. We then
* debounce it and call autoSave().
*/
- private autoSaveTrigger$ = new Subject();
+ private autoSaveTrigger$ = new Subject<void>();
/**
* Set to the content of DraftInfo when entering editing mode.
diff --git a/polygerrit-ui/app/elements/shared/gr-editable-label/gr-editable-label.ts b/polygerrit-ui/app/elements/shared/gr-editable-label/gr-editable-label.ts
index c8574cd..b82c023 100644
--- a/polygerrit-ui/app/elements/shared/gr-editable-label/gr-editable-label.ts
+++ b/polygerrit-ui/app/elements/shared/gr-editable-label/gr-editable-label.ts
@@ -120,6 +120,7 @@
.inputContainer {
background-color: var(--dialog-background-color);
padding: var(--spacing-m);
+ white-space: nowrap;
}
/* This makes inputContainer on one line. */
.inputContainer gr-autocomplete,
diff --git a/polygerrit-ui/app/models/checks/checks-model_test.ts b/polygerrit-ui/app/models/checks/checks-model_test.ts
index da4e3f1..35a8465 100644
--- a/polygerrit-ui/app/models/checks/checks-model_test.ts
+++ b/polygerrit-ui/app/models/checks/checks-model_test.ts
@@ -139,6 +139,9 @@
// emits at 'trailing' of throttle interval
assert.equal(fetchSpy.callCount, 1);
+ // 600 ms is greater than the 500 ms throttle time.
+ clock.tick(600);
+
model.reload('test-plugin');
model.reload('test-plugin');
model.reload('test-plugin');
diff --git a/polygerrit-ui/app/package.json b/polygerrit-ui/app/package.json
index edf0206..32aff91 100644
--- a/polygerrit-ui/app/package.json
+++ b/polygerrit-ui/app/package.json
@@ -42,7 +42,7 @@
"polymer-bridges": "file:../../polymer-bridges/",
"polymer-resin": "^2.0.1",
"resemblejs": "^4.0.0",
- "rxjs": "^6.6.7",
+ "rxjs": "^7.8.0",
"safevalues": "^0.3.1",
"web-vitals": "^3.0.0"
},
diff --git a/polygerrit-ui/app/yarn.lock b/polygerrit-ui/app/yarn.lock
index e056a35..c021046 100644
--- a/polygerrit-ui/app/yarn.lock
+++ b/polygerrit-ui/app/yarn.lock
@@ -846,12 +846,12 @@
dependencies:
glob "^7.1.3"
-rxjs@^6.6.7:
- version "6.6.7"
- resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9"
- integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==
+rxjs@^7.8.0:
+ version "7.8.0"
+ resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.0.tgz#90a938862a82888ff4c7359811a595e14e1e09a4"
+ integrity sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==
dependencies:
- tslib "^1.9.0"
+ tslib "^2.1.0"
safe-buffer@~5.1.0, safe-buffer@~5.1.1:
version "5.1.2"
@@ -954,10 +954,10 @@
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=
-tslib@^1.9.0:
- version "1.14.1"
- resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
- integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
+tslib@^2.1.0:
+ version "2.5.0"
+ resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf"
+ integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==
util-deprecate@~1.0.1:
version "1.0.2"