Merge "Allow to remove specific scores while leaving the reviewer listed"
diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt
index c9bea0a..af0daf4 100644
--- a/Documentation/config-gerrit.txt
+++ b/Documentation/config-gerrit.txt
@@ -897,7 +897,7 @@
Default is "Submit all ${topicSize} changes of the same topic (${submitSize}
changes including ancestors and other changes related by topic)".
-[[change.submitWholeTopic]]change.submitWholeTopic::
+[[change.submitWholeTopic]]change.submitWholeTopic (*Experimental*)::
+
Determines if the submit button submits the whole topic instead of
just the current change.
@@ -1404,7 +1404,8 @@
httpd and sshd threads as some request processing code paths may
need multiple connections.
+
-Default is 8.
+Default is <<sshd.threads, sshd.threads>>
+ + <<httpd.maxThreads, httpd.maxThreads>> + 2.
+
This setting only applies if
<<database.connectionPool,database.connectionPool>> is true.
@@ -1422,7 +1423,7 @@
Maximum number of connections to keep idle in the pool. If there
are more idle connections, connections will be closed instead of
being returned back to the pool.
-Default is 4.
+Default is min(<<database.poolLimit, database.poolLimit>>, 16).
+
This setting only applies if
<<database.connectionPool,database.connectionPool>> is true.
@@ -3142,6 +3143,8 @@
+
A size of 0 bytes disables rules, same as rules.enable = false.
+
+Common unit suffixes of 'k', 'm', or 'g' are supported.
++
Default is 128 KiB.
[[rules.maxPrologDatabaseSize]]rules.maxPrologDatabaseSize::
@@ -3429,7 +3432,7 @@
If additional requests are received while all threads are busy they
are queued and serviced in a first-come-first-served order.
+
-By default, 1.5x the number of CPUs available to the JVM.
+By default, 2x the number of CPUs available to the JVM.
[[sshd.batchThreads]]sshd.batchThreads::
+
diff --git a/Documentation/dev-plugins.txt b/Documentation/dev-plugins.txt
index e6bf2a4..13b6978 100644
--- a/Documentation/dev-plugins.txt
+++ b/Documentation/dev-plugins.txt
@@ -283,6 +283,7 @@
private final ConsoleUI ui;
private final AllProjectsConfig allProjectsConfig;
+ @Inject
public MyInitStep(@PluginName String pluginName, ConsoleUI ui,
AllProjectsConfig allProjectsConfig) {
this.pluginName = pluginName;
diff --git a/Documentation/rest-api-changes.txt b/Documentation/rest-api-changes.txt
index 0b853c0..07d3cc3 100644
--- a/Documentation/rest-api-changes.txt
+++ b/Documentation/rest-api-changes.txt
@@ -224,7 +224,7 @@
* `ALL_REVISIONS`: describe all revisions, not just current.
--
-[[download_commands]]
+[[download-commands]]
--
* `DOWNLOAD_COMMANDS`: include the `commands` field in the
link:#fetch-info[FetchInfo] for revisions. Only valid when the
@@ -1104,7 +1104,7 @@
blocked by Verified
----
-[[submitted_together]]
+[[submitted-together]]
=== Changes submitted together
--
'GET /changes/link:#change-id[\{change-id\}]/submitted_together'
@@ -4307,7 +4307,7 @@
|`commands` |optional|
The download commands for this patch set as a map that maps the command
names to the commands. +
-Only set if link:#download_commands[download commands] are requested.
+Only set if link:#download-commands[download commands] are requested.
|==========================
[[file-info]]
diff --git a/ReleaseNotes/ReleaseNotes-2.12.txt b/ReleaseNotes/ReleaseNotes-2.12.txt
index 4bfe90d..1dfba72 100644
--- a/ReleaseNotes/ReleaseNotes-2.12.txt
+++ b/ReleaseNotes/ReleaseNotes-2.12.txt
@@ -35,7 +35,7 @@
This release includes the following new features. See the sections below for
further details.
-* New "Submit Whole Topic" / "Submitted Together" workflow.
+* New change submission workflows, "Submit Whole Topic" and "Submitted Together".
* Support for GPG Keys and signed pushes.
@@ -43,8 +43,8 @@
New Features
------------
-New Change Submission Workflow
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+New Change Submission Workflows
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* New "Submit Whole Topic" setting.
+
@@ -53,7 +53,7 @@
`change.submitWholeTopic`] setting is enabled, all changes belonging to the same
topic will be submitted at the same time.
+
-This setting is disabled by default.
+This setting should be considered experimental, and is disabled by default.
* Submission of changes may include ancestors.
+
@@ -297,7 +297,7 @@
* Upgrade Jetty to 9.2.13.v20150730
-* Upgrade JGit to 4.1.0.201509280440-r
+* Upgrade JGit to 4.1.1.201511131810-r
* Upgrade joda-time to 2.8
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/BuckUtils.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/BuckUtils.java
index a182663..0b4a02e 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/BuckUtils.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/BuckUtils.java
@@ -14,9 +14,9 @@
package com.google.gerrit.httpd.raw;
+import static com.google.common.base.MoreObjects.firstNonNull;
import static java.nio.charset.StandardCharsets.UTF_8;
-import com.google.common.base.MoreObjects;
import com.google.common.escape.Escaper;
import com.google.common.html.HtmlEscapers;
import com.google.common.io.ByteStreams;
@@ -27,12 +27,12 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.io.PrintWriter;
+import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Properties;
@@ -47,7 +47,7 @@
throws IOException, BuildFailureException {
log.info("buck build " + target);
Properties properties = loadBuckProperties(gen);
- String buck = MoreObjects.firstNonNull(properties.getProperty("buck"), "buck");
+ String buck = firstNonNull(properties.getProperty("buck"), "buck");
ProcessBuilder proc = new ProcessBuilder(buck, "build", target)
.directory(root.toFile())
.redirectErrorStream(true);
@@ -77,12 +77,13 @@
log.info(String.format("UPDATED %s in %.3fs", target, time / 1000.0));
}
- private static Properties loadBuckProperties(Path gen)
- throws FileNotFoundException, IOException {
+ private static Properties loadBuckProperties(Path gen) throws IOException {
Properties properties = new Properties();
- try (InputStream in = new FileInputStream(
- gen.resolve(Paths.get("tools/buck/buck.properties")).toFile())) {
+ Path p = gen.resolve(Paths.get("tools/buck/buck.properties"));
+ try (InputStream in = Files.newInputStream(p)) {
properties.load(in);
+ } catch (NoSuchFileException e) {
+ // Ignore; will be run from PATH, with a descriptive error if it fails.
}
return properties;
}
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/ResourceServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/ResourceServlet.java
index 2036f83..c6eece2 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/ResourceServlet.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/ResourceServlet.java
@@ -136,28 +136,25 @@
}
Resource r = cache.getIfPresent(p);
- if (r == null && maybeStream(p, req, rsp)) {
+ try {
+ if (r == null) {
+ if (maybeStream(p, req, rsp)) {
+ return; // Bypass cache for large resource.
+ }
+ r = cache.get(p, newLoader(p));
+ }
+ if (refresh && r.isStale(p, this)) {
+ cache.invalidate(p);
+ r = cache.get(p, newLoader(p));
+ }
+ } catch (ExecutionException e) {
+ log.warn("Cannot load static resource " + req.getPathInfo(), e);
+ CacheHeaders.setNotCacheable(rsp);
+ rsp.setStatus(SC_INTERNAL_SERVER_ERROR);
return;
}
-
- if (r == null) {
- Callable<Resource> loader = newLoader(p);
- try {
- r = cache.get(p, loader);
- if (refresh && r.isStale(p, this)) {
- cache.invalidate(p);
- r = cache.get(p, loader);
- }
- } catch (ExecutionException | IOException e) {
- log.warn("Cannot load static resource " + req.getPathInfo(), e);
- CacheHeaders.setNotCacheable(rsp);
- rsp.setStatus(SC_INTERNAL_SERVER_ERROR);
- return;
- }
- }
-
if (r == Resource.NOT_FOUND) {
- notFound(rsp);
+ notFound(rsp); // Cached not found response.
return;
}
diff --git a/gerrit-openid/BUCK b/gerrit-openid/BUCK
index 78abce8..0a6363b 100644
--- a/gerrit-openid/BUCK
+++ b/gerrit-openid/BUCK
@@ -3,6 +3,9 @@
srcs = glob(['src/main/java/**/*.java']),
resources = glob(['src/main/resources/**/*']),
deps = [
+ '//lib/openid:consumer',
+ ],
+ provided_deps = [
'//gerrit-common:annotations',
'//gerrit-common:server',
'//gerrit-extension-api:api',
@@ -12,13 +15,12 @@
'//gerrit-server:server',
'//lib:guava',
'//lib:gwtorm',
+ '//lib:servlet-api-3_1',
'//lib/commons:codec',
'//lib/guice:guice',
'//lib/guice:guice-servlet',
'//lib/jgit:jgit',
'//lib/log:api',
- '//lib/openid:consumer',
],
- provided_deps = ['//lib:servlet-api-3_1'],
visibility = ['PUBLIC'],
)
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/JettyServer.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/JettyServer.java
index 0684650..adfea594 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/JettyServer.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/JettyServer.java
@@ -23,6 +23,7 @@
import com.google.gerrit.reviewdb.client.AuthType;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.SitePaths;
+import com.google.gerrit.server.config.ThreadSettingsConfig;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Singleton;
@@ -127,11 +128,14 @@
private boolean reverseProxy;
@Inject
- JettyServer(@GerritServerConfig final Config cfg, final SitePaths site,
- final JettyEnv env, final HttpLogFactory httpLogFactory) {
+ JettyServer(@GerritServerConfig Config cfg,
+ ThreadSettingsConfig threadSettingsConfig,
+ SitePaths site,
+ JettyEnv env,
+ HttpLogFactory httpLogFactory) {
this.site = site;
- httpd = new Server(threadPool(cfg));
+ httpd = new Server(threadPool(cfg, threadSettingsConfig));
httpd.setConnectors(listen(httpd, cfg));
Handler app = makeContext(env, cfg);
@@ -315,8 +319,8 @@
return site.resolve(path);
}
- private ThreadPool threadPool(Config cfg) {
- int maxThreads = cfg.getInt("httpd", null, "maxthreads", 25);
+ private ThreadPool threadPool(Config cfg, ThreadSettingsConfig threadSettingsConfig) {
+ int maxThreads = threadSettingsConfig.getHttpdMaxThreads();
int minThreads = cfg.getInt("httpd", null, "minthreads", 5);
int maxQueued = cfg.getInt("httpd", null, "maxqueued", 200);
int idleTimeout = (int)MILLISECONDS.convert(60, SECONDS);
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/SiteLibraryBasedDataSourceProvider.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/SiteLibraryBasedDataSourceProvider.java
index 7f6313d..6443e21 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/SiteLibraryBasedDataSourceProvider.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/SiteLibraryBasedDataSourceProvider.java
@@ -18,6 +18,7 @@
import com.google.gerrit.metrics.MetricMaker;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.SitePaths;
+import com.google.gerrit.server.config.ThreadSettingsConfig;
import com.google.gerrit.server.schema.DataSourceProvider;
import com.google.gerrit.server.schema.DataSourceType;
import com.google.inject.Inject;
@@ -39,9 +40,10 @@
SiteLibraryBasedDataSourceProvider(SitePaths site,
@GerritServerConfig Config cfg,
MetricMaker metrics,
+ ThreadSettingsConfig tsc,
DataSourceProvider.Context ctx,
DataSourceType dst) {
- super(cfg, metrics, ctx, dst);
+ super(cfg, metrics, tsc, ctx, dst);
libdir = site.lib_dir;
}
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/ThreadLimiter.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/ThreadLimiter.java
index 44361aa..dfe0403 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/ThreadLimiter.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/ThreadLimiter.java
@@ -15,7 +15,7 @@
package com.google.gerrit.pgm.util;
import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.gerrit.server.schema.DataSourceProvider;
+import com.google.gerrit.server.config.ThreadSettingsConfig;
import com.google.gerrit.server.schema.DataSourceType;
import com.google.inject.Injector;
import com.google.inject.Key;
@@ -34,14 +34,15 @@
return limitThreads(
dbInjector.getInstance(Key.get(Config.class, GerritServerConfig.class)),
dbInjector.getInstance(DataSourceType.class),
+ dbInjector.getInstance(ThreadSettingsConfig.class),
threads);
}
- private static int limitThreads(Config cfg, DataSourceType dst, int threads) {
+ private static int limitThreads(Config cfg, DataSourceType dst,
+ ThreadSettingsConfig threadSettingsConfig, int threads) {
boolean usePool = cfg.getBoolean("database", "connectionpool",
dst.usePool());
- int poolLimit = cfg.getInt("database", "poollimit",
- DataSourceProvider.DEFAULT_POOL_LIMIT);
+ int poolLimit = threadSettingsConfig.getDatabasePoolLimit();
if (usePool && threads > poolLimit) {
log.warn("Limiting program to " + poolLimit
+ " threads due to database.poolLimit");
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/ThreadSettingsConfig.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/ThreadSettingsConfig.java
new file mode 100644
index 0000000..c62583e
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/ThreadSettingsConfig.java
@@ -0,0 +1,55 @@
+// 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.config;
+
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+
+import org.eclipse.jgit.lib.Config;
+
+@Singleton
+public class ThreadSettingsConfig {
+ private final int sshdThreads;
+ private final int httpdMaxThreads;
+ private final int sshdBatchThreads;
+ private final int databasePoolLimit;
+
+ @Inject
+ ThreadSettingsConfig(@GerritServerConfig Config cfg) {
+ int cores = Runtime.getRuntime().availableProcessors();
+ sshdThreads = cfg.getInt("sshd", "threads", 2 * cores);
+ httpdMaxThreads = cfg.getInt("httpd", "maxThreads", 25);
+ int defaultDatabasePoolLimit = sshdThreads + httpdMaxThreads + 2;
+ databasePoolLimit =
+ cfg.getInt("database", "poolLimit", defaultDatabasePoolLimit);
+ sshdBatchThreads = cores == 1 ? 1 : 2;
+ }
+
+ public int getDatabasePoolLimit() {
+ return databasePoolLimit;
+ }
+
+ public int getHttpdMaxThreads() {
+ return httpdMaxThreads;
+ }
+
+ public int getSshdThreads() {
+ return sshdThreads;
+ }
+
+ public int getSshdBatchTreads() {
+ return sshdBatchThreads;
+ }
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOp.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOp.java
index a2d71fb..e809e67 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOp.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOp.java
@@ -888,6 +888,7 @@
break;
case PATH_CONFLICT:
+ case REBASE_MERGE_CONFLICT:
case MANUAL_RECURSIVE_MERGE:
case CANNOT_CHERRY_PICK_ROOT:
case NOT_FAST_FORWARD:
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ScanningChangeCacheImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ScanningChangeCacheImpl.java
index 19e23b7..faf3776 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/ScanningChangeCacheImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/ScanningChangeCacheImpl.java
@@ -26,6 +26,7 @@
import com.google.gerrit.server.cache.CacheModule;
import com.google.gerrit.server.util.ManualRequestContext;
import com.google.gerrit.server.util.OneOffRequestContext;
+import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Module;
import com.google.inject.Singleton;
@@ -37,6 +38,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
@@ -97,25 +99,29 @@
public List<Change> load(Project.NameKey key) throws Exception {
try (Repository repo = repoManager.openRepository(key);
ManualRequestContext ctx = requestContext.open()) {
- ReviewDb db = ctx.getReviewDbProvider().get();
- Map<String, Ref> refs =
- repo.getRefDatabase().getRefs(RefNames.REFS_CHANGES);
- Set<Change.Id> ids = new LinkedHashSet<>();
- for (Ref r : refs.values()) {
- Change.Id id = Change.Id.fromRef(r.getName());
- if (id != null) {
- ids.add(id);
- }
- }
- List<Change> changes = new ArrayList<>(ids.size());
- // A batch size of N may overload get(Iterable), so use something smaller,
- // but still >1.
- for (List<Change.Id> batch : Iterables.partition(ids, 30)) {
- Iterables.addAll(changes, db.changes().get(batch));
- }
- return changes;
+ return scan(repo, ctx.getReviewDbProvider().get());
}
}
}
+
+ public static List<Change> scan(Repository repo, ReviewDb db)
+ throws OrmException, IOException {
+ Map<String, Ref> refs =
+ repo.getRefDatabase().getRefs(RefNames.REFS_CHANGES);
+ Set<Change.Id> ids = new LinkedHashSet<>();
+ for (Ref r : refs.values()) {
+ Change.Id id = Change.Id.fromRef(r.getName());
+ if (id != null) {
+ ids.add(id);
+ }
+ }
+ List<Change> changes = new ArrayList<>(ids.size());
+ // A batch size of N may overload get(Iterable), so use something smaller,
+ // but still >1.
+ for (List<Change.Id> batch : Iterables.partition(ids, 30)) {
+ Iterables.addAll(changes, db.changes().get(batch));
+ }
+ return changes;
+ }
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/index/ReindexAfterUpdate.java b/gerrit-server/src/main/java/com/google/gerrit/server/index/ReindexAfterUpdate.java
index 31fbb40..9d573e1 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/index/ReindexAfterUpdate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/index/ReindexAfterUpdate.java
@@ -69,6 +69,11 @@
@Override
public void onGitReferenceUpdated(final Event event) {
+ if (event.getRefName().startsWith(RefNames.REFS_CHANGES)
+ || event.getRefName().startsWith(RefNames.REFS_DRAFT_COMMENTS)
+ || event.getRefName().startsWith(RefNames.REFS_USERS)) {
+ return;
+ }
Futures.transformAsync(
executor.submit(new GetChanges(event)),
new AsyncFunction<List<Change>, List<Void>>() {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/index/SiteIndexer.java b/gerrit-server/src/main/java/com/google/gerrit/server/index/SiteIndexer.java
index 1bc6b05..53af8ad 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/index/SiteIndexer.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/index/SiteIndexer.java
@@ -33,11 +33,11 @@
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.gerrit.server.git.ChangeCache;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.MergeUtil;
import com.google.gerrit.server.git.MultiProgressMonitor;
import com.google.gerrit.server.git.MultiProgressMonitor.Task;
+import com.google.gerrit.server.git.ScanningChangeCacheImpl;
import com.google.gerrit.server.patch.PatchListLoader;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gwtorm.server.SchemaFactory;
@@ -112,7 +112,6 @@
}
private final SchemaFactory<ReviewDb> schemaFactory;
- private final ChangeCache changeCache;
private final ChangeData.Factory changeDataFactory;
private final GitRepositoryManager repoManager;
private final ListeningExecutorService executor;
@@ -126,14 +125,12 @@
@Inject
SiteIndexer(SchemaFactory<ReviewDb> schemaFactory,
- ChangeCache changeCache,
ChangeData.Factory changeDataFactory,
GitRepositoryManager repoManager,
@IndexExecutor(BATCH) ListeningExecutorService executor,
ChangeIndexer.Factory indexerFactory,
@GerritServerConfig Config config) {
this.schemaFactory = schemaFactory;
- this.changeCache = changeCache;
this.changeDataFactory = changeDataFactory;
this.repoManager = repoManager;
this.executor = executor;
@@ -241,7 +238,7 @@
try (Repository repo = repoManager.openRepository(project);
ReviewDb db = schemaFactory.open()) {
Map<String, Ref> refs = repo.getRefDatabase().getRefs(ALL);
- for (Change c : changeCache.get(project)) {
+ for (Change c : ScanningChangeCacheImpl.scan(repo, db)) {
Ref r = refs.get(c.currentPatchSetId().toRefName());
if (r != null) {
byId.put(r.getObjectId(), changeDataFactory.create(db, c));
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/DataSourceProvider.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/DataSourceProvider.java
index e0482f9..0c3bf67 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/schema/DataSourceProvider.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/DataSourceProvider.java
@@ -27,6 +27,7 @@
import com.google.gerrit.server.config.ConfigSection;
import com.google.gerrit.server.config.ConfigUtil;
import com.google.gerrit.server.config.GerritServerConfig;
+import com.google.gerrit.server.config.ThreadSettingsConfig;
import com.google.gwtorm.jdbc.SimpleDataSource;
import com.google.inject.Inject;
import com.google.inject.Provider;
@@ -47,21 +48,22 @@
@Singleton
public class DataSourceProvider implements Provider<DataSource>,
LifecycleListener {
- public static final int DEFAULT_POOL_LIMIT = 8;
-
private final Config cfg;
private final MetricMaker metrics;
private final Context ctx;
private final DataSourceType dst;
+ private final ThreadSettingsConfig threadSettingsConfig;
private DataSource ds;
@Inject
protected DataSourceProvider(@GerritServerConfig Config cfg,
MetricMaker metrics,
+ ThreadSettingsConfig threadSettingsConfig,
Context ctx,
DataSourceType dst) {
this.cfg = cfg;
this.metrics = metrics;
+ this.threadSettingsConfig = threadSettingsConfig;
this.ctx = ctx;
this.dst = dst;
}
@@ -127,9 +129,11 @@
if (password != null && !password.isEmpty()) {
ds.setPassword(password);
}
- ds.setMaxActive(cfg.getInt("database", "poollimit", DEFAULT_POOL_LIMIT));
+ int poolLimit = threadSettingsConfig.getDatabasePoolLimit();
+ ds.setMaxActive(poolLimit);
ds.setMinIdle(cfg.getInt("database", "poolminidle", 4));
- ds.setMaxIdle(cfg.getInt("database", "poolmaxidle", 4));
+ ds.setMaxIdle(
+ cfg.getInt("database", "poolmaxidle", Math.min(poolLimit, 16)));
ds.setMaxWait(ConfigUtil.getTimeUnit(cfg, "database", null,
"poolmaxwait", MILLISECONDS.convert(30, SECONDS), MILLISECONDS));
ds.setInitialSize(ds.getMinIdle());
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_108.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_108.java
index cfafb37..4e76325 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_108.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_108.java
@@ -14,14 +14,17 @@
package com.google.gerrit.server.schema;
+import com.google.common.base.Joiner;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.SetMultimap;
+import com.google.common.collect.Sets;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Change.Status;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.Project.NameKey;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.git.GitRepositoryManager;
@@ -44,6 +47,7 @@
import java.util.Collection;
import java.util.Map;
import java.util.Set;
+import java.util.SortedSet;
public class Schema_108 extends SchemaVersion {
private final GitRepositoryManager repoManager;
@@ -59,7 +63,7 @@
protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException {
ui.message("Listing all changes ...");
SetMultimap<Project.NameKey, Change.Id> openByProject =
- getOpenChangesByProject(db);
+ getOpenChangesByProject(db, ui);
ui.message("done");
ui.message("Updating groups for open changes ...");
@@ -140,7 +144,9 @@
}
private SetMultimap<Project.NameKey, Change.Id> getOpenChangesByProject(
- ReviewDb db) throws OrmException {
+ ReviewDb db, UpdateUI ui) throws OrmException {
+ SortedSet<NameKey> projects = repoManager.list();
+ SortedSet<NameKey> nonExistentProjects = Sets.newTreeSet();
SetMultimap<Project.NameKey, Change.Id> openByProject =
HashMultimap.create();
for (Change c : db.changes().all()) {
@@ -149,10 +155,22 @@
continue;
}
- // The old "submitted" state is not supported anymore
- // (thus status is null) but it was an opened state and needs
- // to be migrated as such
- openByProject.put(c.getProject(), c.getId());
+ NameKey projectKey = c.getProject();
+ if (!projects.contains(projectKey)) {
+ nonExistentProjects.add(projectKey);
+ } else {
+ // The old "submitted" state is not supported anymore
+ // (thus status is null) but it was an opened state and needs
+ // to be migrated as such
+ openByProject.put(projectKey, c.getId());
+ }
+ }
+
+ if (!nonExistentProjects.isEmpty()) {
+ ui.message("Detected open changes referring to the following non-existent projects:");
+ ui.message(Joiner.on(", ").join(nonExistentProjects));
+ ui.message("It is highly recommended to remove\n"
+ + "the obsolete open changes, comments and patch-sets from your DB.\n");
}
return openByProject;
}
diff --git a/gerrit-server/src/main/resources/com/google/gerrit/server/tools/root/hooks/commit-msg b/gerrit-server/src/main/resources/com/google/gerrit/server/tools/root/hooks/commit-msg
index 6988459..5370156 100644
--- a/gerrit-server/src/main/resources/com/google/gerrit/server/tools/root/hooks/commit-msg
+++ b/gerrit-server/src/main/resources/com/google/gerrit/server/tools/root/hooks/commit-msg
@@ -63,6 +63,10 @@
AWK=/usr/xpg4/bin/awk
fi
+ # Get core.commentChar from git config or use default symbol
+ commentChar=`git config --get core.commentChar`
+ commentChar=${commentChar:-#}
+
# How this works:
# - parse the commit message as (textLine+ blankLine*)*
# - assume textLine+ to be a footer until proven otherwise
@@ -81,8 +85,8 @@
blankLines = 0
}
- # Skip lines starting with "#" without any spaces before it.
- /^#/ { next }
+ # Skip lines starting with commentChar without any spaces before it.
+ /^'"$commentChar"'/ { next }
# Skip the line starting with the diff command and everything after it,
# up to the end of the file, assuming it is only patch data.
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/CommandExecutorQueueProvider.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/CommandExecutorQueueProvider.java
index f78aba4..88e1142 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/CommandExecutorQueueProvider.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/CommandExecutorQueueProvider.java
@@ -15,6 +15,7 @@
package com.google.gerrit.sshd;
import com.google.gerrit.server.config.GerritServerConfig;
+import com.google.gerrit.server.config.ThreadSettingsConfig;
import com.google.gerrit.server.git.QueueProvider;
import com.google.gerrit.server.git.WorkQueue;
import com.google.inject.Inject;
@@ -31,11 +32,13 @@
private final WorkQueue.Executor batchExecutor;
@Inject
- public CommandExecutorQueueProvider(@GerritServerConfig final Config config,
- final WorkQueue queues) {
- final int cores = Runtime.getRuntime().availableProcessors();
- poolSize = config.getInt("sshd", "threads", 3 * cores / 2);
- batchThreads = config.getInt("sshd", "batchThreads", cores == 1 ? 1 : 2);
+ public CommandExecutorQueueProvider(
+ @GerritServerConfig Config config,
+ ThreadSettingsConfig threadsSettingsConfig,
+ WorkQueue queues) {
+ poolSize = threadsSettingsConfig.getSshdThreads();
+ batchThreads = config.getInt("sshd", "batchThreads",
+ threadsSettingsConfig.getSshdBatchTreads());
if (batchThreads > poolSize) {
poolSize += batchThreads;
}
diff --git a/lib/jgit/BUCK b/lib/jgit/BUCK
index 9cdfbf4..837d347 100644
--- a/lib/jgit/BUCK
+++ b/lib/jgit/BUCK
@@ -1,13 +1,13 @@
include_defs('//lib/maven.defs')
REPO = MAVEN_CENTRAL # Leave here even if set to MAVEN_CENTRAL.
-VERS = '4.1.0.201509280440-r'
+VERS = '4.1.1.201511131810-r'
maven_jar(
name = 'jgit',
id = 'org.eclipse.jgit:org.eclipse.jgit:' + VERS,
- bin_sha1 = '6410f290b796184df95d321a18d4c3665ba542a8',
- src_sha1 = 'a681c59ec854b3e55f3abff8442e3e4ece31fa70',
+ bin_sha1 = '17cf7d0cb7da8bbcc16e43f0ab5dbfc43b5cb539',
+ src_sha1 = 'e65acfcdca36ae3cbdcbd5496648612eebe54be7',
license = 'jgit',
repository = REPO,
unsign = True,
@@ -22,7 +22,7 @@
maven_jar(
name = 'jgit-servlet',
id = 'org.eclipse.jgit:org.eclipse.jgit.http.server:' + VERS,
- sha1 = '2f86ccebd5b5e0837757d35f63f04471432c13b8',
+ sha1 = '3bbeaab1ddfd87319c4938145c9c2c276ec8de17',
license = 'jgit',
repository = REPO,
deps = [':jgit'],
@@ -36,7 +36,7 @@
maven_jar(
name = 'jgit-archive',
id = 'org.eclipse.jgit:org.eclipse.jgit.archive:' + VERS,
- sha1 = 'd6d0ec8d77cea3b7efeac9789140f8373c10454b',
+ sha1 = 'aae0cc90ab568182bdd1cb5a32bee5b44780e1a7',
license = 'jgit',
repository = REPO,
deps = [':jgit',
@@ -53,7 +53,7 @@
maven_jar(
name = 'junit',
id = 'org.eclipse.jgit:org.eclipse.jgit.junit:' + VERS,
- sha1 = '69ef53175d9f150bc4072f8f5ba9046bf14cc55f',
+ sha1 = '63fd8d96849c7c20d5c70c91575ff8dda12718e0',
license = 'DO_NOT_DISTRIBUTE',
repository = REPO,
unsign = True,
diff --git a/polygerrit-ui/app/elements/gr-account-dropdown.html b/polygerrit-ui/app/elements/gr-account-dropdown.html
new file mode 100644
index 0000000..fbc9a68
--- /dev/null
+++ b/polygerrit-ui/app/elements/gr-account-dropdown.html
@@ -0,0 +1,61 @@
+<!--
+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.
+-->
+
+<link rel="import" href="../bower_components/polymer/polymer.html">
+
+<dom-module id="gr-account-dropdown">
+ <template>
+ <style>
+ :not(.loggedIn):not(.loggedOut) .loginButton,
+ :not(.loggedIn):not(.loggedOut) .logoutButton,
+ .loggedIn .loginButton,
+ .loggedOut .logoutButton {
+ display: none;
+ }
+ </style>
+ <div class$="[[_computeContainerClass(account)]]">
+ <a class="loginButton" href="/login" on-tap="_loginTapHandler">Login</a>
+ <a class="logoutButton" href="/logout">Logout</a>
+ </div>
+ </template>
+ <script>
+ (function() {
+ 'use strict';
+
+ Polymer({
+ is: 'gr-account-dropdown',
+
+ properties: {
+ account: Object,
+ },
+
+ _loginTapHandler: function(e) {
+ e.preventDefault();
+ page('/login/' + encodeURIComponent(
+ window.location.pathname + window.location.hash));
+ },
+
+ _computeContainerClass: function(account) {
+ if (Object.keys(account).length == 0) {
+ return 'loggedOut';
+ }
+ return 'loggedIn';
+ },
+
+ });
+ })();
+ </script>
+</dom-module>
diff --git a/polygerrit-ui/app/elements/gr-account-manager.html b/polygerrit-ui/app/elements/gr-account-manager.html
new file mode 100644
index 0000000..10b6052
--- /dev/null
+++ b/polygerrit-ui/app/elements/gr-account-manager.html
@@ -0,0 +1,60 @@
+<!--
+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.
+-->
+
+<link rel="import" href="../bower_components/polymer/polymer.html">
+
+<dom-module id="gr-account-manager">
+ <template>
+ <iron-ajax id="xhr"
+ auto
+ url="/accounts/self/detail"
+ json-prefix=")]}'"></iron-ajax>
+ </template>
+ <script>
+ (function() {
+ 'use strict';
+
+ Polymer({
+ is: 'gr-account-manager',
+
+ hostAttributes: {
+ hidden: true
+ },
+
+ properties: {
+ account: {
+ type: Object,
+ notify: true,
+ },
+ },
+
+ listeners: {
+ 'xhr.response': '_handleResponse',
+ 'xhr.error': '_handleResponse',
+ },
+
+ _handleResponse: function(e, req) {
+ if (req.status >= 200 && req.status < 300) {
+ this.account = req.response;
+ } else {
+ this.account = {};
+ }
+ },
+
+ });
+ })();
+ </script>
+</dom-module>
diff --git a/polygerrit-ui/app/elements/gr-app.html b/polygerrit-ui/app/elements/gr-app.html
index 3007585..9f1ed1a 100644
--- a/polygerrit-ui/app/elements/gr-app.html
+++ b/polygerrit-ui/app/elements/gr-app.html
@@ -16,6 +16,8 @@
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../styles/app-theme.html">
+<link rel="import" href="gr-account-dropdown.html">
+<link rel="import" href="gr-account-manager.html">
<link rel="import" href="gr-change-list-view.html">
<link rel="import" href="gr-change-view.html">
<link rel="import" href="gr-diff-view.html">
@@ -56,7 +58,7 @@
.bigTitle:hover {
text-decoration: underline;
}
- .searchContainer {
+ .headerRightItems {
display: flex;
flex: 1;
justify-content: flex-end;
@@ -64,11 +66,18 @@
gr-search-bar {
width: 500px;
}
+ gr-account-dropdown {
+ align-items: center;
+ display: flex;
+ margin-left: var(--default-horizontal-margin);
+ }
</style>
+ <gr-account-manager account="{{account}}"></gr-account-manager>
<header role="banner">
<a href="/" class="bigTitle">PolyGerrit</a>
- <div class="searchContainer">
+ <div class="headerRightItems">
<gr-search-bar value="{{params.query}}" role="search"></gr-search-bar>
+ <gr-account-dropdown account="[[account]]"></gr-account-dropdown>
</div>
</header>
<main>
@@ -92,6 +101,7 @@
is: 'gr-app',
properties: {
+ account: Object,
constrained: {
type: Boolean,
value: false,
diff --git a/polygerrit-ui/app/elements/gr-diff-view.html b/polygerrit-ui/app/elements/gr-diff-view.html
index 502b2df..874cbd0 100644
--- a/polygerrit-ui/app/elements/gr-diff-view.html
+++ b/polygerrit-ui/app/elements/gr-diff-view.html
@@ -23,41 +23,41 @@
:host {
background-color: var(--view-background-color);
display: block;
- margin: 1em 1.25rem;
}
h3 {
- border-bottom: 1px solid #eee;
- padding: .75em 1em;
+ margin-top: 1em;
+ padding: .75em var(--default-horizontal-margin);
}
.mainContainer {
- max-width: 100%;
- overflow: auto;
+ border-bottom: 1px solid #eee;
+ border-collapse: collapse;
+ border-top: 1px solid #eee;
+ width: 100%;
+ }
+ .diffNumbers,
+ .diffContent {
+ vertical-align: top;
}
.diffContainer {
- display: flex;
font-family: 'Source Code Pro', monospace;
white-space: pre;
}
.diffNumbers {
- background-color: #ddd;
+ background-color: #eee;
color: #666;
padding: 0 .75em;
text-align: right;
}
.diffContent {
- border-right: 1px solid #ddd;
- min-width: calc(80ch + 2px);
- overflow-x: auto;
- padding-left: 2px;
- width: calc(80ch + 2px);
+ min-width: 80ch;
+ max-width: 120ch;
+ overflow: hidden;
}
.diffContainer.leftOnly .diffContent,
.diffContainer.rightOnly .diffContent {
overflow: visible;
}
- .diffContainer.leftOnly .right {
- display: none;
- }
+ .diffContainer.leftOnly .right,
.diffContainer.rightOnly .left {
display: none;
}
@@ -129,14 +129,14 @@
<a href$="[[_computeChangePath(_changeNum)]]">[[_changeNum]]</a><span>:</span>
<span>[[_change.subject]]</span> — <span>[[params.path]]</span>
</h3>
- <div class="mainContainer">
- <div class="diffContainer" id="diffContainer">
- <div class="diffNumbers left" id="leftDiffNumbers"></div>
- <div class="diffContent left" id="leftDiffContent"></div>
- <div class="diffNumbers right" id="rightDiffNumbers"></div>
- <div class="diffContent right" id="rightDiffContent"></div>
- </div>
- </div>
+ <table class="mainContainer">
+ <tr class="diffContainer" id="diffContainer">
+ <td class="diffNumbers left" id="leftDiffNumbers"></td>
+ <td class="diffContent left" id="leftDiffContent"></td>
+ <td class="diffNumbers right" id="rightDiffNumbers"></td>
+ <td class="diffContent right" id="rightDiffContent"></td>
+ </tr>
+ </table>
</template>
<script>
(function() {
@@ -362,7 +362,7 @@
this.$.diffContainer.classList.toggle('rightOnly',
diff.change_type == Changes.DiffType.ADDED);
this.$.diffContainer.classList.toggle('leftOnly',
- diff.change_type == Changes.DiffType.REMOVED);
+ diff.change_type == Changes.DiffType.DELETED);
var initialLineNum = 0 + (diff.content.skip || 0);
var ctx = {
diff --git a/polygerrit-ui/app/scripts/app.js b/polygerrit-ui/app/scripts/app.js
index 7014074..7f3e05c 100644
--- a/polygerrit-ui/app/scripts/app.js
+++ b/polygerrit-ui/app/scripts/app.js
@@ -18,10 +18,10 @@
// See https://github.com/Polymer/polymer/issues/1381
window.addEventListener('WebComponentsReady', function() {
// Middleware
- function scrollToTop(ctx, next) {
+ page(function(ctx, next) {
document.body.scrollTop = 0;
next();
- }
+ });
// Routes.
page('/', function() {
@@ -33,19 +33,19 @@
app.params = data.params;
}
- page('/q/:query,:offset', scrollToTop, queryHandler);
- page('/q/:query', scrollToTop, queryHandler);
+ page('/q/:query,:offset', queryHandler);
+ page('/q/:query', queryHandler);
- page(/^\/(\d+)\/?/, scrollToTop, function(ctx) {
+ page(/^\/(\d+)\/?/, function(ctx) {
page.redirect('/c/' + ctx.params[0]);
});
- page('/c/:changeNum', scrollToTop, function(data) {
+ page('/c/:changeNum', function(data) {
app.route = 'gr-change-view';
app.params = data.params;
});
- page(/^\/c\/(\d+)\/((\d+)(\.\.(\d+))?)\/(.+)/, scrollToTop, function(ctx) {
+ page(/^\/c\/(\d+)\/((\d+)(\.\.(\d+))?)\/(.+)/, function(ctx) {
app.route = 'gr-diff-view';
var params = {
changeNum: ctx.params[0],
diff --git a/polygerrit-ui/bower.json b/polygerrit-ui/bower.json
index a50f1cc..e3c3cfc 100644
--- a/polygerrit-ui/bower.json
+++ b/polygerrit-ui/bower.json
@@ -12,18 +12,7 @@
},
"devDependencies": {
"web-component-tester": "*",
- "iron-test-helpers": "PolymerElements/iron-test-helpers#^1.0",
+ "iron-test-helpers": "PolymerElements/iron-test-helpers#~1.0.6",
"test-fixture": "PolymerElements/test-fixture#^1.0.0"
- "polymer": "Polymer/polymer#^1.2.1",
- "page": "visionmedia/page.js#~1.6.4",
- "iron-ajax": "PolymerElements/iron-ajax#~1.0.9",
- "iron-a11y-keys": "PolymerElements/iron-a11y-keys#~1.0.3",
- "iron-input": "PolymerElements/iron-input#~1.0.6"
- },
- "devDependencies": {
- "web-component-tester": "*",
- "iron-test-helpers": "PolymerElements/iron-test-helpers#~1.0",
- "test-fixture": "PolymerElements/test-fixture#^1.0.0",
- "iron-test-helpers": "PolymerElements/iron-test-helpers#~1.0.6"
}
}
diff --git a/polygerrit-ui/server.go b/polygerrit-ui/server.go
index 008fe1d..29b81f4 100644
--- a/polygerrit-ui/server.go
+++ b/polygerrit-ui/server.go
@@ -68,6 +68,7 @@
return
}
defer res.Body.Close()
+ w.WriteHeader(res.StatusCode)
if _, err := io.Copy(w, res.Body); err != nil {
log.Println("Error copying response to ResponseWriter:", err)
return