Merge "Make default CacheBasedWebSession maxAge public" into stable-3.3
diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt
index 95078c1..10baed2 100644
--- a/Documentation/config-gerrit.txt
+++ b/Documentation/config-gerrit.txt
@@ -2132,7 +2132,7 @@
or "http://example.com:8080/gerrit/" so Gerrit can output links that point
back to itself.
+
-Setting this is highly recommended, as its necessary for the upload
+Setting this is highly recommended, as it is necessary for the upload
code invoked by "git push" or "repo upload" to output hyperlinks
to the newly uploaded changes.
diff --git a/Documentation/dev-plugins.txt b/Documentation/dev-plugins.txt
index f6e63d7..03e8ce6 100644
--- a/Documentation/dev-plugins.txt
+++ b/Documentation/dev-plugins.txt
@@ -2721,7 +2721,7 @@
Plugins may also decide not to vote on a given change by returning an
`Optional.empty()` (ie: the plugin is not enabled for this repository).
-If a plugin decides not to vote, it's name will not be displayed in the UI and
+If a plugin decides not to vote, its name will not be displayed in the UI and
it will not be recoded in the database.
.Gerrit's Pre-submit handling with three plugins
diff --git a/Documentation/note-db.txt b/Documentation/note-db.txt
index a13cbfb..7b436a9 100644
--- a/Documentation/note-db.txt
+++ b/Documentation/note-db.txt
@@ -192,5 +192,5 @@
In case of rollback from NoteDB to ReviewDB, all the meta refs and the
sequence ref need to be removed.
-The [remove-notedb-refs.sh,role=external,window=_blank](https://gerrit.googlesource.com/gerrit/+/refs/heads/master/contrib/remove-notedb-refs.sh)
+The link:https://gerrit.googlesource.com/gerrit/+/refs/heads/master/contrib/remove-notedb-refs.sh[remove-notedb-refs.sh,role=external,window=_blank]
script has been written to automate this process.
diff --git a/WORKSPACE b/WORKSPACE
index d0f7561..bba5818 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -255,12 +255,6 @@
)
maven_jar(
- name = "log4j",
- artifact = "log4j:log4j:1.2.17",
- sha1 = "5af35056b4d257e4b64b9e8069c0746e8b08629f",
-)
-
-maven_jar(
name = "json-smart",
artifact = "net.minidev:json-smart:1.1.1",
sha1 = "24a2f903d25e004de30ac602c5b47f2d4e420a59",
diff --git a/java/com/google/gerrit/elasticsearch/ElasticVersion.java b/java/com/google/gerrit/elasticsearch/ElasticVersion.java
index c6400df..47fa383 100644
--- a/java/com/google/gerrit/elasticsearch/ElasticVersion.java
+++ b/java/com/google/gerrit/elasticsearch/ElasticVersion.java
@@ -18,9 +18,7 @@
import java.util.regex.Pattern;
public enum ElasticVersion {
- V7_6("7.6.*"),
- V7_7("7.7.*"),
- V7_8("7.8.*");
+ V7_16("7.16.*");
private final String version;
private final Pattern pattern;
diff --git a/java/com/google/gerrit/httpd/auth/openid/OpenIdServiceImpl.java b/java/com/google/gerrit/httpd/auth/openid/OpenIdServiceImpl.java
index b685011..c655b6c 100644
--- a/java/com/google/gerrit/httpd/auth/openid/OpenIdServiceImpl.java
+++ b/java/com/google/gerrit/httpd/auth/openid/OpenIdServiceImpl.java
@@ -172,7 +172,7 @@
aReq.addExtension(pape);
}
} catch (MessageException | ConsumerException e) {
- logger.atSevere().withCause(e).log("Cannot create OpenID redirect for %s" + openidIdentifier);
+ logger.atSevere().withCause(e).log("Cannot create OpenID redirect for %s", openidIdentifier);
return new DiscoveryResult(DiscoveryResult.Status.ERROR);
}
diff --git a/java/com/google/gerrit/mail/ParserUtil.java b/java/com/google/gerrit/mail/ParserUtil.java
index 4b292f3..40c5a95 100644
--- a/java/com/google/gerrit/mail/ParserUtil.java
+++ b/java/com/google/gerrit/mail/ParserUtil.java
@@ -115,7 +115,8 @@
int numConsecutiveDigits = 0;
int maxConsecutiveDigits = 0;
int numDigitGroups = 0;
- for (char c : s.toCharArray()) {
+ for (int i = 0; i < s.length(); i++) {
+ char c = s.charAt(i);
if (c >= '0' && c <= '9') {
numConsecutiveDigits++;
} else if (numConsecutiveDigits > 0) {
diff --git a/java/com/google/gerrit/server/git/DelegateRepository.java b/java/com/google/gerrit/server/git/DelegateRepository.java
index 2816429..5ebe358 100644
--- a/java/com/google/gerrit/server/git/DelegateRepository.java
+++ b/java/com/google/gerrit/server/git/DelegateRepository.java
@@ -62,6 +62,10 @@
this.delegate = delegate;
}
+ Repository delegate() {
+ return delegate;
+ }
+
@Override
public void create(boolean bare) throws IOException {
delegate.create(bare);
diff --git a/java/com/google/gerrit/server/git/GarbageCollection.java b/java/com/google/gerrit/server/git/GarbageCollection.java
index 9b52f48..c37572d 100644
--- a/java/com/google/gerrit/server/git/GarbageCollection.java
+++ b/java/com/google/gerrit/server/git/GarbageCollection.java
@@ -86,7 +86,12 @@
try (Repository repo = repoManager.openRepository(p)) {
logGcConfiguration(p, repo, aggressive);
print(writer, "collecting garbage for \"" + p + "\":\n");
- GarbageCollectCommand gc = Git.wrap(repo).gc();
+ GarbageCollectCommand gc =
+ Git.wrap(
+ repo instanceof DelegateRepository
+ ? ((DelegateRepository) repo).delegate()
+ : repo)
+ .gc();
gc.setAggressive(aggressive);
logGcInfo(p, "before:", gc.getStatistics());
gc.setProgressMonitor(
diff --git a/java/com/google/gerrit/server/git/GitRepositoryManagerModule.java b/java/com/google/gerrit/server/git/GitRepositoryManagerModule.java
index 354b69f..e4137b0 100644
--- a/java/com/google/gerrit/server/git/GitRepositoryManagerModule.java
+++ b/java/com/google/gerrit/server/git/GitRepositoryManagerModule.java
@@ -15,6 +15,7 @@
package com.google.gerrit.server.git;
import com.google.gerrit.lifecycle.LifecycleModule;
+import com.google.gerrit.server.ModuleImpl;
import com.google.gerrit.server.config.RepositoryConfig;
import com.google.inject.Inject;
@@ -22,7 +23,9 @@
* Module to install {@link MultiBaseLocalDiskRepositoryManager} rather than {@link
* LocalDiskRepositoryManager} if needed.
*/
+@ModuleImpl(name = GitRepositoryManagerModule.MANAGER_MODULE)
public class GitRepositoryManagerModule extends LifecycleModule {
+ public static final String MANAGER_MODULE = "git-manager";
private final RepositoryConfig repoConfig;
diff --git a/java/com/google/gerrit/server/git/MergeUtil.java b/java/com/google/gerrit/server/git/MergeUtil.java
index 8666f26..e0b101b 100644
--- a/java/com/google/gerrit/server/git/MergeUtil.java
+++ b/java/com/google/gerrit/server/git/MergeUtil.java
@@ -304,13 +304,13 @@
int nameLength = Math.max(oursName.length(), theirsName.length());
String oursNameFormatted =
String.format(
- "%0$-" + nameLength + "s (%s %s)",
+ "%-" + nameLength + "s (%s %s)",
oursName,
abbreviateName(ours, NAME_ABBREV_LEN),
oursMsg.substring(0, Math.min(oursMsg.length(), 60)));
String theirsNameFormatted =
String.format(
- "%0$-" + nameLength + "s (%s %s)",
+ "%-" + nameLength + "s (%s %s)",
theirsName,
abbreviateName(theirs, NAME_ABBREV_LEN),
theirsMsg.substring(0, Math.min(theirsMsg.length(), 60)));
diff --git a/java/com/google/gerrit/server/git/MultiProgressMonitor.java b/java/com/google/gerrit/server/git/MultiProgressMonitor.java
index 2d854a5..15fbe3f 100644
--- a/java/com/google/gerrit/server/git/MultiProgressMonitor.java
+++ b/java/com/google/gerrit/server/git/MultiProgressMonitor.java
@@ -28,6 +28,8 @@
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ProgressMonitor;
@@ -123,6 +125,64 @@
return count;
}
}
+
+ public int getTotal() {
+ return total;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getTotalDisplay(int total) {
+ return String.valueOf(total);
+ }
+ }
+
+ /** Handle for a sub-task whose total work can be updated while the task is in progress. */
+ public class VolatileTask extends Task {
+ protected AtomicInteger volatileTotal;
+ protected AtomicBoolean isTotalFinalized = new AtomicBoolean(false);
+
+ public VolatileTask(String subTaskName) {
+ super(subTaskName, UNKNOWN);
+ volatileTotal = new AtomicInteger(UNKNOWN);
+ }
+
+ /**
+ * Update the total work for this sub-task.
+ *
+ * <p>Intended to be called from a worker thread.
+ *
+ * @param workUnits number of work units to be added to existing total work.
+ */
+ public void updateTotal(int workUnits) {
+ if (!isTotalFinalized.get()) {
+ volatileTotal.addAndGet(workUnits);
+ } else {
+ logger.atWarning().log(
+ "Total work has been finalized on sub-task %s and cannot be updated", getName());
+ }
+ }
+
+ /**
+ * Mark the total on this sub-task as unmodifiable.
+ *
+ * <p>Intended to be called from a worker thread.
+ */
+ public void finalizeTotal() {
+ isTotalFinalized.set(true);
+ }
+
+ @Override
+ public int getTotal() {
+ return volatileTotal.get();
+ }
+
+ @Override
+ public String getTotalDisplay(int total) {
+ return super.getTotalDisplay(total) + (isTotalFinalized.get() ? "" : "+");
+ }
}
private final OutputStream out;
@@ -180,6 +240,7 @@
* calls {@link #end()}, the future has an additional {@code maxInterval} to finish before it is
* forcefully cancelled and {@link ExecutionException} is thrown.
*
+ * @see #waitForNonFinalTask(Future, long, TimeUnit)
* @param workerFuture a future that returns when worker threads are finished.
* @param timeoutTime overall timeout for the task; the future is forcefully cancelled if the task
* exceeds the timeout. Non-positive values indicate no timeout.
@@ -189,6 +250,45 @@
*/
public <T> T waitFor(Future<T> workerFuture, long timeoutTime, TimeUnit timeoutUnit)
throws TimeoutException {
+ T t = waitForNonFinalTask(workerFuture, timeoutTime, timeoutUnit);
+ synchronized (this) {
+ if (!done) {
+ // The worker may not have called end() explicitly, which is likely a
+ // programming error.
+ logger.atWarning().log("MultiProgressMonitor worker did not call end() before returning");
+ end();
+ }
+ }
+ sendDone();
+ return t;
+ }
+
+ /**
+ * Wait for a non-final task managed by a {@link Future}, with no timeout.
+ *
+ * @see #waitForNonFinalTask(Future, long, TimeUnit)
+ */
+ public <T> T waitForNonFinalTask(Future<T> workerFuture) {
+ try {
+ return waitForNonFinalTask(workerFuture, 0, null);
+ } catch (TimeoutException e) {
+ throw new IllegalStateException("timout exception without setting a timeout", e);
+ }
+ }
+
+ /**
+ * Wait for a task managed by a {@link Future}. This call does not expect the worker thread to
+ * call {@link #end()}. It is intended to be used to track a non-final task.
+ *
+ * @param workerFuture a future that returns when worker threads are finished.
+ * @param timeoutTime overall timeout for the task; the future is forcefully cancelled if the task
+ * exceeds the timeout. Non-positive values indicate no timeout.
+ * @param timeoutUnit unit for overall task timeout.
+ * @throws TimeoutException if this thread or a worker thread was interrupted, the worker was
+ * cancelled, or timed out waiting for a worker to call {@link #end()}.
+ */
+ public <T> T waitForNonFinalTask(Future<T> workerFuture, long timeoutTime, TimeUnit timeoutUnit)
+ throws TimeoutException {
long overallStart = System.nanoTime();
long deadline;
if (timeoutTime > 0) {
@@ -199,7 +299,7 @@
synchronized (this) {
long left = maxIntervalNanos;
- while (!done) {
+ while (!workerFuture.isDone() && !done) {
long start = System.nanoTime();
try {
NANOSECONDS.timedWait(this, left);
@@ -228,14 +328,8 @@
left = maxIntervalNanos;
}
sendUpdate();
- if (!done && workerFuture.isDone()) {
- // The worker may not have called end() explicitly, which is likely a
- // programming error.
- logger.atWarning().log("MultiProgressMonitor worker did not call end() before returning");
- end();
- }
}
- sendDone();
+ wakeUp();
}
// The loop exits as soon as the worker calls end(), but we give it another
@@ -271,6 +365,18 @@
}
/**
+ * Begin a sub-task whose total work can be updated.
+ *
+ * @param subTask sub-task name.
+ * @return sub-task handle.
+ */
+ public VolatileTask beginVolatileSubTask(String subTask) {
+ VolatileTask task = new VolatileTask(subTask);
+ tasks.add(task);
+ return task;
+ }
+
+ /**
* End the overall task.
*
* <p>Must be called from a worker thread.
@@ -313,6 +419,7 @@
boolean first = true;
for (Task t : tasks) {
int count = t.getCount();
+ int total = t.getTotal();
if (count == 0) {
continue;
}
@@ -327,10 +434,11 @@
if (!Strings.isNullOrEmpty(t.name)) {
s.append(t.name).append(": ");
}
- if (t.total == UNKNOWN) {
+ if (total == UNKNOWN) {
s.append(count);
} else {
- s.append(String.format("%d%% (%d/%d)", count * 100 / t.total, count, t.total));
+ s.append(
+ String.format("%d%% (%d/%s)", count * 100 / total, count, t.getTotalDisplay(total)));
}
}
}
diff --git a/java/com/google/gerrit/server/index/change/AllChangesIndexer.java b/java/com/google/gerrit/server/index/change/AllChangesIndexer.java
index f466ad6..d6b8ef9 100644
--- a/java/com/google/gerrit/server/index/change/AllChangesIndexer.java
+++ b/java/com/google/gerrit/server/index/change/AllChangesIndexer.java
@@ -14,7 +14,6 @@
package com.google.gerrit.server.index.change;
-import static com.google.common.base.Preconditions.checkState;
import static com.google.common.util.concurrent.Futures.successfulAsList;
import static com.google.common.util.concurrent.Futures.transform;
import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
@@ -22,9 +21,8 @@
import com.google.auto.value.AutoValue;
import com.google.common.base.Stopwatch;
-import com.google.common.collect.Sets;
+import com.google.common.collect.ImmutableSortedSet;
import com.google.common.flogger.FluentLogger;
-import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.UncheckedExecutionException;
@@ -34,6 +32,7 @@
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.MultiProgressMonitor;
import com.google.gerrit.server.git.MultiProgressMonitor.Task;
+import com.google.gerrit.server.git.MultiProgressMonitor.VolatileTask;
import com.google.gerrit.server.index.IndexExecutor;
import com.google.gerrit.server.index.OnlineReindexMode;
import com.google.gerrit.server.notedb.ChangeNotes;
@@ -44,18 +43,13 @@
import com.google.inject.Inject;
import java.io.IOException;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
-import java.util.Set;
import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
-import java.util.stream.Collectors;
import org.eclipse.jgit.lib.ProgressMonitor;
import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.lib.TextProgressMonitor;
/**
* Implementation that can index all changes on a host or within a project. Used by Gerrit's
@@ -64,6 +58,9 @@
*/
public class AllChangesIndexer extends SiteIndexer<Change.Id, ChangeData, ChangeIndex> {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
+ private MultiProgressMonitor mpm;
+ private VolatileTask doneTask;
+ private Task failedTask;
private static final int PROJECT_SLICE_MAX_REFS = 1000;
private static class ProjectsCollectionFailure extends Exception {
@@ -130,55 +127,18 @@
// in 2020.
Stopwatch sw = Stopwatch.createStarted();
- List<ProjectSlice> projectSlices;
+ AtomicBoolean ok = new AtomicBoolean(true);
+ mpm = new MultiProgressMonitor(progressOut, "Reindexing changes");
+ doneTask = mpm.beginVolatileSubTask("changes");
+ failedTask = mpm.beginSubTask("failed", MultiProgressMonitor.UNKNOWN);
+ List<ListenableFuture<?>> futures;
try {
- projectSlices = new SliceCreator().create();
- } catch (ProjectsCollectionFailure | InterruptedException | ExecutionException e) {
+ futures = new SliceScheduler(index, ok).schedule();
+ } catch (ProjectsCollectionFailure e) {
logger.atSevere().log(e.getMessage());
return Result.create(sw, false, 0, 0);
}
- // Since project slices are created in parallel, they are somewhat shuffled already. However,
- // the number of threads used to create the project slices doesn't guarantee good randomization.
- // If the slices are not shuffled well, then multiple threads would typically work concurrently
- // on different slices of the same project. While this is not a big issue, shuffling the list
- // beforehand helps with ungrouping the project slices, so different slices are less likely to
- // be worked on concurrently.
- // This shuffling gave a 6% runtime reduction for Wikimedia's Gerrit in 2020.
- Collections.shuffle(projectSlices);
- return indexAll(index, projectSlices);
- }
-
- private SiteIndexer.Result indexAll(ChangeIndex index, List<ProjectSlice> projectSlices) {
- Stopwatch sw = Stopwatch.createStarted();
- MultiProgressMonitor mpm = new MultiProgressMonitor(progressOut, "Reindexing changes");
- Task projTask = mpm.beginSubTask("project-slices", projectSlices.size());
- checkState(totalWork >= 0);
- Task doneTask = mpm.beginSubTask(null, totalWork);
- Task failedTask = mpm.beginSubTask("failed", MultiProgressMonitor.UNKNOWN);
-
- List<ListenableFuture<?>> futures = new ArrayList<>();
- AtomicBoolean ok = new AtomicBoolean(true);
-
- for (ProjectSlice projectSlice : projectSlices) {
- Project.NameKey name = projectSlice.name();
- int slice = projectSlice.slice();
- int slices = projectSlice.slices();
- ListenableFuture<?> future =
- executor.submit(
- reindexProject(
- indexerFactory.create(executor, index),
- name,
- slice,
- slices,
- projectSlice.scanResult(),
- doneTask,
- failedTask));
- String description = "project " + name + " (" + slice + "/" + slices + ")";
- addErrorListener(future, description, projTask, ok);
- futures.add(future);
- }
-
try {
mpm.waitFor(
transform(
@@ -308,30 +268,53 @@
}
}
- private class SliceCreator {
- final Set<ProjectSlice> projectSlices = Sets.newConcurrentHashSet();
+ private class SliceScheduler {
+ final ChangeIndex index;
+ final AtomicBoolean ok;
final AtomicInteger changeCount = new AtomicInteger(0);
final AtomicInteger projectsFailed = new AtomicInteger(0);
- final ProgressMonitor pm = new TextProgressMonitor();
+ final List<ListenableFuture<?>> sliceIndexerFutures = new ArrayList<>();
+ final List<ListenableFuture<?>> sliceCreationFutures = new ArrayList<>();
+ VolatileTask projTask = mpm.beginVolatileSubTask("project-slices");
+ Task slicingProjects;
- private List<ProjectSlice> create()
- throws ProjectsCollectionFailure, InterruptedException, ExecutionException {
- List<ListenableFuture<?>> futures = new ArrayList<>();
- pm.beginTask("Collecting projects", ProgressMonitor.UNKNOWN);
- for (Project.NameKey name : projectCache.all()) {
- futures.add(executor.submit(new ProjectSliceCreator(name)));
+ public SliceScheduler(ChangeIndex index, AtomicBoolean ok) {
+ this.index = index;
+ this.ok = ok;
+ }
+
+ private List<ListenableFuture<?>> schedule() throws ProjectsCollectionFailure {
+ ImmutableSortedSet<Project.NameKey> projects = projectCache.all();
+ int projectCount = projects.size();
+ slicingProjects = mpm.beginSubTask("Slicing projects", projectCount);
+ for (Project.NameKey name : projects) {
+ sliceCreationFutures.add(executor.submit(new ProjectSliceCreator(name)));
}
- Futures.allAsList(futures).get();
+ try {
+ mpm.waitForNonFinalTask(
+ transform(
+ successfulAsList(sliceCreationFutures),
+ x -> {
+ projTask.finalizeTotal();
+ doneTask.finalizeTotal();
+ return null;
+ },
+ directExecutor()));
+ } catch (UncheckedExecutionException e) {
+ logger.atSevere().withCause(e).log("Error project slice creation");
+ ok.set(false);
+ }
- if (projectsFailed.get() > projectCache.all().size() / 2) {
+ if (projectsFailed.get() > projectCount / 2) {
throw new ProjectsCollectionFailure(
"Over 50%% of the projects could not be collected: aborted");
}
- pm.endTask();
+ slicingProjects.endTask();
setTotalWork(changeCount.get());
- return projectSlices.stream().collect(Collectors.toList());
+
+ return sliceIndexerFutures;
}
private class ProjectSliceCreator implements Callable<Void> {
@@ -353,15 +336,32 @@
verboseWriter.println(
"Submitting " + name + " for indexing in " + slices + " slices");
}
+
+ doneTask.updateTotal(size);
+ projTask.updateTotal(slices);
+
for (int slice = 0; slice < slices; slice++) {
- projectSlices.add(ProjectSlice.create(name, slice, slices, sr));
+ ProjectSlice projectSlice = ProjectSlice.create(name, slice, slices, sr);
+ ListenableFuture<?> future =
+ executor.submit(
+ reindexProject(
+ indexerFactory.create(executor, index),
+ name,
+ slice,
+ slices,
+ projectSlice.scanResult(),
+ doneTask,
+ failedTask));
+ String description = "project " + name + " (" + slice + "/" + slices + ")";
+ addErrorListener(future, description, projTask, ok);
+ sliceIndexerFutures.add(future);
}
}
} catch (IOException e) {
logger.atSevere().withCause(e).log("Error collecting project %s", name);
projectsFailed.incrementAndGet();
}
- pm.update(1);
+ slicingProjects.update(1);
return null;
}
}
diff --git a/javatests/com/google/gerrit/acceptance/pgm/ElasticReindexIT.java b/javatests/com/google/gerrit/acceptance/pgm/ElasticReindexIT.java
index f23cc10..8480a6d 100644
--- a/javatests/com/google/gerrit/acceptance/pgm/ElasticReindexIT.java
+++ b/javatests/com/google/gerrit/acceptance/pgm/ElasticReindexIT.java
@@ -26,7 +26,7 @@
@ConfigSuite.Default
public static Config elasticsearchV7() {
- return getConfig(ElasticVersion.V7_8);
+ return getConfig(ElasticVersion.V7_16);
}
@Override
diff --git a/javatests/com/google/gerrit/acceptance/ssh/ElasticIndexIT.java b/javatests/com/google/gerrit/acceptance/ssh/ElasticIndexIT.java
index f35bcb7..e72d806 100644
--- a/javatests/com/google/gerrit/acceptance/ssh/ElasticIndexIT.java
+++ b/javatests/com/google/gerrit/acceptance/ssh/ElasticIndexIT.java
@@ -28,7 +28,7 @@
@ConfigSuite.Default
public static Config elasticsearchV7() {
- return getConfig(ElasticVersion.V7_8);
+ return getConfig(ElasticVersion.V7_16);
}
@Override
diff --git a/javatests/com/google/gerrit/elasticsearch/ElasticContainer.java b/javatests/com/google/gerrit/elasticsearch/ElasticContainer.java
index c330961..b4fb153 100644
--- a/javatests/com/google/gerrit/elasticsearch/ElasticContainer.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticContainer.java
@@ -39,12 +39,8 @@
private static String getImageName(ElasticVersion version) {
switch (version) {
- case V7_6:
- return "blacktop/elasticsearch:7.6.2";
- case V7_7:
- return "blacktop/elasticsearch:7.7.1";
- case V7_8:
- return "blacktop/elasticsearch:7.8.1";
+ case V7_16:
+ return "gerritforge/elasticsearch:7.16.2";
}
throw new IllegalStateException("No tests for version: " + version.name());
}
diff --git a/javatests/com/google/gerrit/elasticsearch/ElasticV7QueryAccountsTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticV7QueryAccountsTest.java
index 4826490..39517d5 100644
--- a/javatests/com/google/gerrit/elasticsearch/ElasticV7QueryAccountsTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticV7QueryAccountsTest.java
@@ -36,7 +36,7 @@
public static void startIndexService() {
if (container == null) {
// Only start Elasticsearch once
- container = ElasticContainer.createAndStart(ElasticVersion.V7_8);
+ container = ElasticContainer.createAndStart(ElasticVersion.V7_16);
}
}
diff --git a/javatests/com/google/gerrit/elasticsearch/ElasticV7QueryChangesTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticV7QueryChangesTest.java
index d9a4d2e..5d64d0a 100644
--- a/javatests/com/google/gerrit/elasticsearch/ElasticV7QueryChangesTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticV7QueryChangesTest.java
@@ -46,7 +46,7 @@
public static void startIndexService() {
if (container == null) {
// Only start Elasticsearch once
- container = ElasticContainer.createAndStart(ElasticVersion.V7_8);
+ container = ElasticContainer.createAndStart(ElasticVersion.V7_16);
client = HttpAsyncClients.createDefault();
client.start();
}
diff --git a/javatests/com/google/gerrit/elasticsearch/ElasticV7QueryGroupsTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticV7QueryGroupsTest.java
index 0fc96f8..645f889 100644
--- a/javatests/com/google/gerrit/elasticsearch/ElasticV7QueryGroupsTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticV7QueryGroupsTest.java
@@ -36,7 +36,7 @@
public static void startIndexService() {
if (container == null) {
// Only start Elasticsearch once
- container = ElasticContainer.createAndStart(ElasticVersion.V7_8);
+ container = ElasticContainer.createAndStart(ElasticVersion.V7_16);
}
}
diff --git a/javatests/com/google/gerrit/elasticsearch/ElasticV7QueryProjectsTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticV7QueryProjectsTest.java
index 1e56af9..8d7f5f8 100644
--- a/javatests/com/google/gerrit/elasticsearch/ElasticV7QueryProjectsTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticV7QueryProjectsTest.java
@@ -36,7 +36,7 @@
public static void startIndexService() {
if (container == null) {
// Only start Elasticsearch once
- container = ElasticContainer.createAndStart(ElasticVersion.V7_8);
+ container = ElasticContainer.createAndStart(ElasticVersion.V7_16);
}
}
diff --git a/javatests/com/google/gerrit/elasticsearch/ElasticVersionTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticVersionTest.java
index 2ce3a2c..bfb332e 100644
--- a/javatests/com/google/gerrit/elasticsearch/ElasticVersionTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticVersionTest.java
@@ -22,14 +22,7 @@
public class ElasticVersionTest {
@Test
public void supportedVersion() throws Exception {
- assertThat(ElasticVersion.forVersion("7.6.0")).isEqualTo(ElasticVersion.V7_6);
- assertThat(ElasticVersion.forVersion("7.6.1")).isEqualTo(ElasticVersion.V7_6);
-
- assertThat(ElasticVersion.forVersion("7.7.0")).isEqualTo(ElasticVersion.V7_7);
- assertThat(ElasticVersion.forVersion("7.7.1")).isEqualTo(ElasticVersion.V7_7);
-
- assertThat(ElasticVersion.forVersion("7.8.0")).isEqualTo(ElasticVersion.V7_8);
- assertThat(ElasticVersion.forVersion("7.8.1")).isEqualTo(ElasticVersion.V7_8);
+ assertThat(ElasticVersion.forVersion("7.16.2")).isEqualTo(ElasticVersion.V7_16);
}
@Test
diff --git a/javatests/com/google/gerrit/mail/data/NonUTF8Message.java b/javatests/com/google/gerrit/mail/data/NonUTF8Message.java
index 60368eb..86a0b56 100644
--- a/javatests/com/google/gerrit/mail/data/NonUTF8Message.java
+++ b/javatests/com/google/gerrit/mail/data/NonUTF8Message.java
@@ -45,7 +45,8 @@
public int[] rawChars() {
int[] arr = new int[raw.length()];
int i = 0;
- for (char c : raw.toCharArray()) {
+ for (int j = 0; j < raw.length(); j++) {
+ char c = raw.charAt(j);
arr[i++] = c;
}
return arr;
diff --git a/javatests/com/google/gerrit/server/config/GitwebConfigTest.java b/javatests/com/google/gerrit/server/config/GitwebConfigTest.java
index cb6de34..7316074 100644
--- a/javatests/com/google/gerrit/server/config/GitwebConfigTest.java
+++ b/javatests/com/google/gerrit/server/config/GitwebConfigTest.java
@@ -24,7 +24,8 @@
@Test
public void validPathSeparator() {
- for (char c : VALID_CHARACTERS.toCharArray()) {
+ for (int i = 0; i < VALID_CHARACTERS.length(); i++) {
+ char c = VALID_CHARACTERS.charAt(i);
assertWithMessage("valid character rejected: " + c)
.that(GitwebConfig.isValidPathSeparator(c))
.isTrue();
@@ -33,7 +34,8 @@
@Test
public void inalidPathSeparator() {
- for (char c : SOME_INVALID_CHARACTERS.toCharArray()) {
+ for (int i = 0; i < SOME_INVALID_CHARACTERS.length(); i++) {
+ char c = SOME_INVALID_CHARACTERS.charAt(i);
assertWithMessage("invalid character accepted: " + c)
.that(GitwebConfig.isValidPathSeparator(c))
.isFalse();
diff --git a/javatests/com/google/gerrit/server/git/GarbageCollectionTest.java b/javatests/com/google/gerrit/server/git/GarbageCollectionTest.java
new file mode 100644
index 0000000..41b5d79
--- /dev/null
+++ b/javatests/com/google/gerrit/server/git/GarbageCollectionTest.java
@@ -0,0 +1,101 @@
+// Copyright (C) 2022 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.git;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import com.google.common.collect.ImmutableList;
+import com.google.gerrit.entities.Project;
+import com.google.gerrit.entities.Project.NameKey;
+import com.google.gerrit.extensions.registration.DynamicSet;
+import com.google.gerrit.server.config.GcConfig;
+import com.google.gerrit.server.config.SitePaths;
+import com.google.gerrit.server.plugincontext.PluginContext.PluginMetrics;
+import com.google.gerrit.server.plugincontext.PluginSetContext;
+import java.io.IOException;
+import org.eclipse.jgit.errors.RepositoryNotFoundException;
+import org.eclipse.jgit.lib.Config;
+import org.eclipse.jgit.lib.Repository;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+public class GarbageCollectionTest {
+ private static final Project.NameKey FOO = Project.nameKey("foo");
+
+ @Rule public final MockitoRule mockito = MockitoJUnit.rule();
+ @Rule public TemporaryFolder temporaryFolder = new TemporaryFolder();
+
+ @Mock private GcConfig gcConfig;
+ @Mock private DelegateRepository wrapper;
+
+ private SitePaths site;
+ private Config cfg;
+
+ @Before
+ public void setup() throws Exception {
+ site = new SitePaths(temporaryFolder.newFolder().toPath());
+ site.resolve("git").toFile().mkdir();
+ cfg = new Config();
+ cfg.setString("gerrit", null, "basePath", "git");
+ }
+
+ @Test
+ public void shouldCallGcOnDelegatedRepositoryWhenDelegateRepositoryIsPassed() throws IOException {
+ // given
+ GarbageCollection objectUnderTest = prepareObjectForTesting();
+
+ // when
+ objectUnderTest.run(ImmutableList.of(FOO), false, null);
+
+ // then
+ verify(wrapper).delegate();
+ }
+
+ private GarbageCollection prepareObjectForTesting() throws IOException {
+ LocalDiskRepositoryManager repoManager = new DelegatedRepositoryManager(site, cfg, wrapper);
+ try (Repository repo = repoManager.createRepository(FOO)) {
+ assertThat(repo).isNotNull();
+ }
+ return new GarbageCollection(
+ repoManager,
+ new GarbageCollectionQueue(),
+ gcConfig,
+ new PluginSetContext<>(new DynamicSet<>(), PluginMetrics.DISABLED_INSTANCE));
+ }
+
+ private static final class DelegatedRepositoryManager extends LocalDiskRepositoryManager {
+ private final DelegateRepository wrapper;
+
+ private DelegatedRepositoryManager(SitePaths site, Config cfg, DelegateRepository wrapper) {
+ super(site, cfg);
+ this.wrapper = wrapper;
+ }
+
+ @Override
+ public Repository openRepository(NameKey name) throws RepositoryNotFoundException {
+ Repository opened = super.openRepository(name);
+ when(wrapper.delegate()).thenReturn(opened);
+ when(wrapper.getConfig()).thenReturn(opened.getConfig());
+ return wrapper;
+ }
+ }
+}
diff --git a/lib/nongoogle_test.sh b/lib/nongoogle_test.sh
index 57afb1b..dc980c2 100755
--- a/lib/nongoogle_test.sh
+++ b/lib/nongoogle_test.sh
@@ -32,6 +32,7 @@
jackson-core
jna
jruby
+log4j
mina-core
nekohtml
objenesis
diff --git a/tools/maven/gerrit-acceptance-framework_pom.xml b/tools/maven/gerrit-acceptance-framework_pom.xml
index c2fbcfe..5736e4d 100644
--- a/tools/maven/gerrit-acceptance-framework_pom.xml
+++ b/tools/maven/gerrit-acceptance-framework_pom.xml
@@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.google.gerrit</groupId>
<artifactId>gerrit-acceptance-framework</artifactId>
- <version>3.3.9-SNAPSHOT</version>
+ <version>3.3.10-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Gerrit Code Review - Acceptance Test Framework</name>
<description>Framework for Gerrit's acceptance tests</description>
diff --git a/tools/maven/gerrit-extension-api_pom.xml b/tools/maven/gerrit-extension-api_pom.xml
index 4de5ce7..09c7b55 100644
--- a/tools/maven/gerrit-extension-api_pom.xml
+++ b/tools/maven/gerrit-extension-api_pom.xml
@@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.google.gerrit</groupId>
<artifactId>gerrit-extension-api</artifactId>
- <version>3.3.9-SNAPSHOT</version>
+ <version>3.3.10-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Gerrit Code Review - Extension API</name>
<description>API for Gerrit Extensions</description>
diff --git a/tools/maven/gerrit-plugin-api_pom.xml b/tools/maven/gerrit-plugin-api_pom.xml
index 1178656..b7f1bab 100644
--- a/tools/maven/gerrit-plugin-api_pom.xml
+++ b/tools/maven/gerrit-plugin-api_pom.xml
@@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.google.gerrit</groupId>
<artifactId>gerrit-plugin-api</artifactId>
- <version>3.3.9-SNAPSHOT</version>
+ <version>3.3.10-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Gerrit Code Review - Plugin API</name>
<description>API for Gerrit Plugins</description>
diff --git a/tools/maven/gerrit-war_pom.xml b/tools/maven/gerrit-war_pom.xml
index e11b3c5..48d5f0b 100644
--- a/tools/maven/gerrit-war_pom.xml
+++ b/tools/maven/gerrit-war_pom.xml
@@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.google.gerrit</groupId>
<artifactId>gerrit-war</artifactId>
- <version>3.3.9-SNAPSHOT</version>
+ <version>3.3.10-SNAPSHOT</version>
<packaging>war</packaging>
<name>Gerrit Code Review - WAR</name>
<description>Gerrit WAR</description>
diff --git a/tools/nongoogle.bzl b/tools/nongoogle.bzl
index b5bcb6f..394cf0e 100644
--- a/tools/nongoogle.bzl
+++ b/tools/nongoogle.bzl
@@ -10,6 +10,12 @@
"""
maven_jar(
+ name = "log4j",
+ artifact = "ch.qos.reload4j:reload4j:1.2.18.0",
+ sha1 = "03b2b708403ab00eb0678bffdbbd567070bbdfab",
+ )
+
+ maven_jar(
name = "j2objc",
artifact = "com.google.j2objc:j2objc-annotations:1.1",
sha1 = "ed28ded51a8b1c6b112568def5f4b455e6809019",
diff --git a/version.bzl b/version.bzl
index c29e21a..116ce2e 100644
--- a/version.bzl
+++ b/version.bzl
@@ -2,4 +2,4 @@
# Used by :api_install and :api_deploy targets
# when talking to the destination repository.
#
-GERRIT_VERSION = "3.3.9-SNAPSHOT"
+GERRIT_VERSION = "3.3.10-SNAPSHOT"