Merge "Merge branch 'stable-3.10'"
diff --git a/Documentation/linux-quickstart.txt b/Documentation/linux-quickstart.txt
index 13873ed..67f0565 100644
--- a/Documentation/linux-quickstart.txt
+++ b/Documentation/linux-quickstart.txt
@@ -29,10 +29,10 @@
. Download the desired Gerrit archive.
To view previous archives, see
-link:https://gerrit-releases.storage.googleapis.com/index.html[Gerrit Code Review: Releases,role=external,window=_blank]. The steps below install Gerrit 3.5.1:
+link:https://gerrit-releases.storage.googleapis.com/index.html[Gerrit Code Review: Releases,role=external,window=_blank]. The steps below install Gerrit 3.9.4:
....
-wget https://gerrit-releases.storage.googleapis.com/gerrit-3.5.1.war
+wget https://gerrit-releases.storage.googleapis.com/gerrit-3.9.4.war
....
NOTE: To build and install Gerrit from the source files, see
diff --git a/java/com/google/gerrit/server/cache/h2/H2CacheFactory.java b/java/com/google/gerrit/server/cache/h2/H2CacheFactory.java
index ddfee38..6b19906 100644
--- a/java/com/google/gerrit/server/cache/h2/H2CacheFactory.java
+++ b/java/com/google/gerrit/server/cache/h2/H2CacheFactory.java
@@ -61,6 +61,24 @@
class H2CacheFactory extends PersistentCacheBaseFactory implements LifecycleListener {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
+ static class PeriodicCachePruner implements Runnable {
+ private final H2CacheImpl<?, ?> cache;
+
+ PeriodicCachePruner(H2CacheImpl<?, ?> cache) {
+ this.cache = cache;
+ }
+
+ @Override
+ public String toString() {
+ return "Disk Cache Pruner (" + cache.getCacheName() + ")";
+ }
+
+ @Override
+ public void run() {
+ cache.prune();
+ }
+ }
+
private final List<H2CacheImpl<?, ?>> caches;
private final DynamicMap<Cache<?, ?>> cacheMap;
private final ExecutorService executor;
@@ -118,13 +136,13 @@
if (pruneOnStartup) {
@SuppressWarnings("unused")
Future<?> possiblyIgnoredError =
- cleanup.schedule(() -> cache.prune(), 30, TimeUnit.SECONDS);
+ cleanup.schedule(new PeriodicCachePruner(cache), 30, TimeUnit.SECONDS);
}
@SuppressWarnings("unused")
Future<?> possiblyIgnoredError =
cleanup.scheduleAtFixedRate(
- () -> cache.prune(),
+ new PeriodicCachePruner(cache),
schedule.initialDelay(),
schedule.interval(),
TimeUnit.MILLISECONDS);
diff --git a/java/com/google/gerrit/server/cache/h2/H2CacheImpl.java b/java/com/google/gerrit/server/cache/h2/H2CacheImpl.java
index a869946..c31f58a 100644
--- a/java/com/google/gerrit/server/cache/h2/H2CacheImpl.java
+++ b/java/com/google/gerrit/server/cache/h2/H2CacheImpl.java
@@ -234,6 +234,10 @@
logger.atFine().log("Finished pruning cache %s...", cacheName);
}
+ String getCacheName() {
+ return cacheName;
+ }
+
static class ValueHolder<V> {
final V value;
final Instant created;
diff --git a/java/com/google/gerrit/server/project/SubmitRequirementsAdapter.java b/java/com/google/gerrit/server/project/SubmitRequirementsAdapter.java
index 7f73cd3..ec376e0 100644
--- a/java/com/google/gerrit/server/project/SubmitRequirementsAdapter.java
+++ b/java/com/google/gerrit/server/project/SubmitRequirementsAdapter.java
@@ -186,7 +186,12 @@
}
ImmutableList.Builder<SubmitRequirementResult> result = ImmutableList.builder();
for (Label label : record.labels) {
- if (skipSubmitRequirementFor(label)) {
+ if (skipSubmitRequirementFor(label)
+ ||
+ // If SubmitRecord is a PASS, then skip all the requirements
+ // that are not a PASS as they would block the overall submit requirement
+ // status from being a PASS
+ (mapStatus(record) == Status.PASS && mapStatus(label) != Status.PASS)) {
continue;
}
String expressionString = String.format("label:%s=%s", label.label, ruleName);
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/AttentionSetIT.java b/javatests/com/google/gerrit/acceptance/rest/change/AttentionSetIT.java
index c7672d1..92da64e 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/AttentionSetIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/AttentionSetIT.java
@@ -3024,8 +3024,8 @@
String.format(
"Attention is currently required from: %s, %s.\n"
+ "\n"
- + "%s has posted comments on this change.",
- admin.fullName(), user.fullName(), approver.fullName()));
+ + "%s has posted comments on this change by %s.",
+ admin.fullName(), user.fullName(), approver.fullName(), admin.fullName()));
assertThat(message.body()).doesNotContain("\nPatch Set 2: Code-Review+2\n");
assertThat(message.body())
.contains("The change is no longer submittable: Code-Review is unsatisfied now.\n");
@@ -3110,8 +3110,8 @@
String.format(
"Attention is currently required from: %s, %s.\n"
+ "\n"
- + "%s has posted comments on this change.",
- admin.fullName(), user.fullName(), approver.fullName()));
+ + "%s has posted comments on this change by %s.",
+ admin.fullName(), user.fullName(), approver.fullName(), admin.fullName()));
assertThat(message.body()).doesNotContain("\nPatch Set 2: Code-Review+2\n");
assertThat(message.body()).contains("\nPatch Set 2: Code-Review+1\n");
assertThat(message.body())
@@ -3198,8 +3198,8 @@
String.format(
"Attention is currently required from: %s, %s.\n"
+ "\n"
- + "%s has posted comments on this change.",
- admin.fullName(), user.fullName(), approver.fullName()));
+ + "%s has posted comments on this change by %s.",
+ admin.fullName(), user.fullName(), approver.fullName(), admin.fullName()));
assertThat(message.body()).contains("\nPatch Set 2: Code-Review-2\n");
assertThat(message.body())
.contains("The change is no longer submittable: Code-Review is unsatisfied now.\n");
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/ChangeNoLongerSubmittableIT.java b/javatests/com/google/gerrit/acceptance/rest/change/ChangeNoLongerSubmittableIT.java
index 1094a42..5bb6dc4 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/ChangeNoLongerSubmittableIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/ChangeNoLongerSubmittableIT.java
@@ -83,8 +83,8 @@
String.format(
"Attention is currently required from: %s, %s.\n"
+ "\n"
- + "%s has posted comments on this change.",
- admin.fullName(), user.fullName(), approver.fullName()));
+ + "%s has posted comments on this change by %s.",
+ admin.fullName(), user.fullName(), approver.fullName(), admin.fullName()));
assertThat(message.body())
.contains("The change is no longer submittable: Code-Review is unsatisfied now.\n");
assertThat(message.htmlBody())
@@ -127,8 +127,8 @@
String.format(
"Attention is currently required from: %s, %s.\n"
+ "\n"
- + "%s has posted comments on this change.",
- admin.fullName(), user.fullName(), approver.fullName()));
+ + "%s has posted comments on this change by %s.",
+ admin.fullName(), user.fullName(), approver.fullName(), admin.fullName()));
assertThat(message.body())
.contains("The change is no longer submittable: Code-Review is unsatisfied now.\n");
assertThat(message.htmlBody())
@@ -172,8 +172,8 @@
String.format(
"Attention is currently required from: %s, %s.\n"
+ "\n"
- + "%s has posted comments on this change.",
- admin.fullName(), user.fullName(), approver.fullName()));
+ + "%s has posted comments on this change by %s.",
+ admin.fullName(), user.fullName(), approver.fullName(), admin.fullName()));
assertThat(message.body())
.contains("The change is no longer submittable: Code-Review is unsatisfied now.\n");
assertThat(message.htmlBody())
@@ -263,8 +263,8 @@
String.format(
"Attention is currently required from: %s, %s.\n"
+ "\n"
- + "%s has posted comments on this change.",
- admin.fullName(), user.fullName(), approver.fullName()));
+ + "%s has posted comments on this change by %s.",
+ admin.fullName(), user.fullName(), approver.fullName(), admin.fullName()));
assertThat(message.body())
.contains(
"The change is no longer submittable:"
@@ -315,8 +315,8 @@
String.format(
"Attention is currently required from: %s, %s.\n"
+ "\n"
- + "%s has posted comments on this change.",
- admin.fullName(), user.fullName(), approver.fullName()));
+ + "%s has posted comments on this change by %s.",
+ admin.fullName(), user.fullName(), approver.fullName(), admin.fullName()));
assertThat(message.body()).doesNotContain("The change is no longer submittable");
assertThat(message.htmlBody()).doesNotContain("The change is no longer submittable");
}
@@ -361,8 +361,8 @@
String.format(
"Attention is currently required from: %s, %s.\n"
+ "\n"
- + "%s has posted comments on this change.",
- admin.fullName(), user.fullName(), approver.fullName()));
+ + "%s has posted comments on this change by %s.",
+ admin.fullName(), user.fullName(), approver.fullName(), admin.fullName()));
assertThat(message.body()).doesNotContain("The change is no longer submittable");
assertThat(message.htmlBody()).doesNotContain("The change is no longer submittable");
}
@@ -398,8 +398,8 @@
String.format(
"Attention is currently required from: %s, %s.\n"
+ "\n"
- + "%s has posted comments on this change.",
- admin.fullName(), user.fullName(), approver.fullName()));
+ + "%s has posted comments on this change by %s.",
+ admin.fullName(), user.fullName(), approver.fullName(), admin.fullName()));
assertThat(message.body()).doesNotContain("The change is no longer submittable");
assertThat(message.htmlBody()).doesNotContain("The change is no longer submittable");
}
@@ -435,8 +435,8 @@
String.format(
"Attention is currently required from: %s, %s.\n"
+ "\n"
- + "%s has posted comments on this change.",
- admin.fullName(), user.fullName(), approver.fullName()));
+ + "%s has posted comments on this change by %s.",
+ admin.fullName(), user.fullName(), approver.fullName(), admin.fullName()));
assertThat(message.body()).doesNotContain("The change is no longer submittable");
assertThat(message.htmlBody()).doesNotContain("The change is no longer submittable");
}
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/ChangeReviewersIT.java b/javatests/com/google/gerrit/acceptance/rest/change/ChangeReviewersIT.java
index 77841b2..d618e2f 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/ChangeReviewersIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/ChangeReviewersIT.java
@@ -450,7 +450,9 @@
Message m = messages.get(0);
assertThat(m.rcpt()).containsExactly(user.getNameEmail(), observer.getNameEmail());
- assertThat(m.body()).contains(admin.fullName() + " has posted comments on this change.");
+ assertThat(m.body())
+ .contains(
+ admin.fullName() + " has posted comments on this change by " + admin.fullName() + ".");
assertThat(m.body()).contains("Change subject: " + PushOneCommit.SUBJECT + "\n");
assertThat(m.body()).contains("Patch Set 1: Code-Review+2");
diff --git a/javatests/com/google/gerrit/server/project/SubmitRequirementsAdapterTest.java b/javatests/com/google/gerrit/server/project/SubmitRequirementsAdapterTest.java
index 0f4bd2e..e651302 100644
--- a/javatests/com/google/gerrit/server/project/SubmitRequirementsAdapterTest.java
+++ b/javatests/com/google/gerrit/server/project/SubmitRequirementsAdapterTest.java
@@ -337,6 +337,29 @@
}
@Test
+ public void customSubmitRule_withLabels_withStatusOk() {
+ SubmitRecord submitRecord =
+ createSubmitRecord(
+ "gerrit~PrologRule",
+ Status.OK,
+ Arrays.asList(
+ createLabel("custom-need-label-1", Label.Status.NEED),
+ createLabel("custom-pass-label-2", Label.Status.OK),
+ createLabel("custom-may-label-3", Label.Status.MAY)));
+
+ ImmutableList<SubmitRequirementResult> requirements =
+ SubmitRequirementsAdapter.createResult(submitRecord, labelTypes, psCommitId, false);
+
+ assertThat(requirements).hasSize(1);
+ assertResult(
+ requirements.get(0),
+ /* reqName= */ "custom-pass-label-2",
+ /* submitExpression= */ "label:custom-pass-label-2=gerrit~PrologRule",
+ SubmitRequirementResult.Status.SATISFIED,
+ SubmitRequirementExpressionResult.Status.PASS);
+ }
+
+ @Test
public void customSubmitRule_withMixOfPassingAndFailingLabels() {
SubmitRecord submitRecord =
createSubmitRecord(
diff --git a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.ts b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.ts
index f5e403d..650fe41 100644
--- a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.ts
@@ -1265,6 +1265,7 @@
private getHashtagSuggestions(
input: string
): Promise<AutocompleteSuggestion[]> {
+ const inputReg = input.startsWith('^') ? new RegExp(input) : null;
return this.restApiService
.getChangesWithSimilarHashtag(input, throwingErrorCallback)
.then(response =>
@@ -1272,6 +1273,9 @@
.flatMap(change => change.hashtags ?? [])
.filter(isDefined)
.filter(unique)
+ .filter(hashtag =>
+ inputReg ? inputReg.test(hashtag) : hashtag.includes(input)
+ )
.map(hashtag => {
return {name: hashtag, value: hashtag};
})
diff --git a/resources/com/google/gerrit/server/mail/Comment.soy b/resources/com/google/gerrit/server/mail/Comment.soy
index 4b621b5..8c1840c 100644
--- a/resources/com/google/gerrit/server/mail/Comment.soy
+++ b/resources/com/google/gerrit/server/mail/Comment.soy
@@ -29,7 +29,7 @@
{@param unsatisfiedSubmitRequirements: ?}
{@param oldSubmitRequirements: ?}
{@param newSubmitRequirements: ?}
- {$fromName} has posted comments on this change.
+ {$fromName} has posted comments on this change by {$change.ownerName}.
{if $email.changeUrl} ( {$email.changeUrl} ){/if}{\n}
{if $unsatisfiedSubmitRequirements}
{\n}