Merge "Merge branch 'stable-2.15'"
diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt
index a79b7a5..9a37f25 100644
--- a/Documentation/config-gerrit.txt
+++ b/Documentation/config-gerrit.txt
@@ -1156,6 +1156,17 @@
+
Default is `ALL`.
+[[change.allowDrafts]]change.allowDrafts::
++
+Legacy support for drafts workflow. If set to true, pushing a new change
+with draft option will create a private change. Pushing with draft option
+to an existing change will create change edit.
++
+Enabling this option allows to push to the `refs/drafts/branch`. When
+disabled any push to `refs/drafts/branch` will be rejected.
++
+Default is false.
+
[[change.cacheAutomerge]]change.cacheAutomerge::
+
When reviewing diff commits, the left-hand side shows the output of the
@@ -2424,6 +2435,14 @@
+
Default value is true.
+[[http.addUserAsResponseHeader]]http.addUserAsResponseHeader::
++
+If true, the header 'User' will be added to the list of response headers so it
+can be accessed from a reverse proxy for logging purposes.
+
++
+Default value is false.
+
[[httpd]]
=== Section httpd
diff --git a/java/com/google/gerrit/httpd/GetUserFilter.java b/java/com/google/gerrit/httpd/GetUserFilter.java
index 4b3d41d5..2199411 100644
--- a/java/com/google/gerrit/httpd/GetUserFilter.java
+++ b/java/com/google/gerrit/httpd/GetUserFilter.java
@@ -14,6 +14,7 @@
package com.google.gerrit.httpd;
+import com.google.common.collect.ImmutableMap;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.inject.Inject;
@@ -27,33 +28,49 @@
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletResponse;
import org.eclipse.jgit.lib.Config;
-/** Stores user as a request attribute, so servlets can access it outside of the request scope. */
+/**
+ * Stores user as a request attribute and/or response header, so servlets and reverse proxies can
+ * access it outside of the request/response scope.
+ */
@Singleton
public class GetUserFilter implements Filter {
- public static final String REQ_ATTR_KEY = "User";
+ public static final String USER_ATTR_KEY = "User";
public static class Module extends ServletModule {
- private final boolean enabled;
+ private final boolean reqEnabled;
+ private final boolean resEnabled;
@Inject
Module(@GerritServerConfig Config cfg) {
- enabled = cfg.getBoolean("http", "addUserAsRequestAttribute", true);
+ reqEnabled = cfg.getBoolean("http", "addUserAsRequestAttribute", true);
+ resEnabled = cfg.getBoolean("http", "addUserAsResponseHeader", false);
}
@Override
protected void configureServlets() {
- if (enabled) {
- filter("/*").through(GetUserFilter.class);
+ if (resEnabled || reqEnabled) {
+ ImmutableMap.Builder<String, String> initParams = ImmutableMap.builder();
+ if (reqEnabled) {
+ initParams.put("reqEnabled", "");
+ }
+ if (resEnabled) {
+ initParams.put("resEnabled", "");
+ }
+ filter("/*").through(GetUserFilter.class, initParams.build());
}
}
}
private final Provider<CurrentUser> userProvider;
+ private boolean reqEnabled;
+ private boolean resEnabled;
+
@Inject
GetUserFilter(Provider<CurrentUser> userProvider) {
this.userProvider = userProvider;
@@ -64,7 +81,13 @@
throws IOException, ServletException {
CurrentUser user = userProvider.get();
if (user != null && user.isIdentifiedUser()) {
- req.setAttribute(REQ_ATTR_KEY, user.asIdentifiedUser().getLoggableName());
+ String loggableName = user.asIdentifiedUser().getLoggableName();
+ if (reqEnabled) {
+ req.setAttribute(USER_ATTR_KEY, loggableName);
+ }
+ if (resEnabled && resp instanceof HttpServletResponse) {
+ ((HttpServletResponse) resp).addHeader(USER_ATTR_KEY, loggableName);
+ }
}
chain.doFilter(req, resp);
}
@@ -73,5 +96,8 @@
public void destroy() {}
@Override
- public void init(FilterConfig arg0) {}
+ public void init(FilterConfig arg0) {
+ reqEnabled = arg0.getInitParameter("reqEnabled") != null ? true : false;
+ resEnabled = arg0.getInitParameter("resEnabled") != null ? true : false;
+ }
}
diff --git a/java/com/google/gerrit/pgm/http/jetty/HttpLog.java b/java/com/google/gerrit/pgm/http/jetty/HttpLog.java
index 011ebf0..d7bc720 100644
--- a/java/com/google/gerrit/pgm/http/jetty/HttpLog.java
+++ b/java/com/google/gerrit/pgm/http/jetty/HttpLog.java
@@ -89,7 +89,7 @@
String uri = req.getRequestURI();
uri = redactQueryString(uri, req.getQueryString());
- String user = (String) req.getAttribute(GetUserFilter.REQ_ATTR_KEY);
+ String user = (String) req.getAttribute(GetUserFilter.USER_ATTR_KEY);
if (user != null) {
event.setProperty(P_USER, user);
}
diff --git a/java/com/google/gerrit/server/git/WorkQueue.java b/java/com/google/gerrit/server/git/WorkQueue.java
index 3bc44c5..74f986e 100644
--- a/java/com/google/gerrit/server/git/WorkQueue.java
+++ b/java/com/google/gerrit/server/git/WorkQueue.java
@@ -84,8 +84,7 @@
}
};
- private ScheduledExecutorService defaultQueue;
- private final int defaultQueueSize;
+ private final ScheduledExecutorService defaultQueue;
private final IdGenerator idGenerator;
private final CopyOnWriteArrayList<Executor> queues;
@@ -98,14 +97,11 @@
public WorkQueue(IdGenerator idGenerator, int defaultThreadPoolSize) {
this.idGenerator = idGenerator;
this.queues = new CopyOnWriteArrayList<>();
- this.defaultQueueSize = defaultThreadPoolSize;
+ this.defaultQueue = createQueue(defaultThreadPoolSize, "WorkQueue");
}
/** Get the default work queue, for miscellaneous tasks. */
- public synchronized ScheduledExecutorService getDefaultQueue() {
- if (defaultQueue == null) {
- defaultQueue = createQueue(defaultQueueSize, "WorkQueue");
- }
+ public ScheduledExecutorService getDefaultQueue() {
return defaultQueue;
}
diff --git a/java/com/google/gerrit/server/git/receive/ReceiveCommits.java b/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
index dbb6bcf..c93c1d7 100644
--- a/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
+++ b/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
@@ -1584,6 +1584,14 @@
return;
}
+ // TODO(davido): Remove legacy support for drafts magic branch option
+ // after repo-tool supports private and work-in-progress changes.
+ if (magicBranch.draft && !receiveConfig.allowDrafts) {
+ errors.put(ReceiveError.CODE_REVIEW, ref);
+ reject(cmd, "draft workflow is disabled");
+ return;
+ }
+
if (magicBranch.isPrivate && magicBranch.removePrivate) {
reject(cmd, "the options 'private' and 'remove-private' are mutually exclusive");
return;
diff --git a/java/com/google/gerrit/server/git/receive/ReceiveConfig.java b/java/com/google/gerrit/server/git/receive/ReceiveConfig.java
index cdbf310..b1c9f13 100644
--- a/java/com/google/gerrit/server/git/receive/ReceiveConfig.java
+++ b/java/com/google/gerrit/server/git/receive/ReceiveConfig.java
@@ -27,6 +27,7 @@
class ReceiveConfig {
final boolean checkMagicRefs;
final boolean checkReferencedObjectsAreReachable;
+ final boolean allowDrafts;
final int maxBatchCommits;
final boolean disablePrivateChanges;
private final int systemMaxBatchChanges;
@@ -37,6 +38,7 @@
checkMagicRefs = config.getBoolean("receive", null, "checkMagicRefs", true);
checkReferencedObjectsAreReachable =
config.getBoolean("receive", null, "checkReferencedObjectsAreReachable", true);
+ allowDrafts = config.getBoolean("change", null, "allowDrafts", false);
maxBatchCommits = config.getInt("receive", null, "maxBatchCommits", 10000);
systemMaxBatchChanges = config.getInt("receive", "maxBatchChanges", 0);
disablePrivateChanges = config.getBoolean("change", null, "disablePrivateChanges", false);
diff --git a/javatests/com/google/gerrit/acceptance/api/change/DisablePrivateChangesIT.java b/javatests/com/google/gerrit/acceptance/api/change/DisablePrivateChangesIT.java
index 287434d..ffb8b34 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/DisablePrivateChangesIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/DisablePrivateChangesIT.java
@@ -59,6 +59,7 @@
}
@Test
+ @GerritConfig(name = "change.allowDrafts", value = "true")
@GerritConfig(name = "change.disablePrivateChanges", value = "true")
public void pushDraftsWithDisablePrivateChangesTrue() throws Exception {
RevCommit initialHead = getRemoteHead();
@@ -81,6 +82,7 @@
}
@Test
+ @GerritConfig(name = "change.allowDrafts", value = "true")
public void pushPrivatesWithDisablePrivateChangesFalse() throws Exception {
PushOneCommit.Result result =
pushFactory.create(db, admin.getIdent(), testRepo).to("refs/for/master%private");
@@ -88,6 +90,7 @@
}
@Test
+ @GerritConfig(name = "change.allowDrafts", value = "true")
public void pushDraftsWithDisablePrivateChangesFalse() throws Exception {
RevCommit initialHead = getRemoteHead();
PushOneCommit.Result result =
diff --git a/javatests/com/google/gerrit/acceptance/git/AbstractPushForReview.java b/javatests/com/google/gerrit/acceptance/git/AbstractPushForReview.java
index df146c7..f03b19b 100644
--- a/javatests/com/google/gerrit/acceptance/git/AbstractPushForReview.java
+++ b/javatests/com/google/gerrit/acceptance/git/AbstractPushForReview.java
@@ -1967,6 +1967,16 @@
}
@Test
+ public void pushWithDraftOptionIsDisabledPerDefault() throws Exception {
+ for (String ref : ImmutableSet.of("refs/drafts/master", "refs/for/master%draft")) {
+ PushOneCommit.Result r = pushTo(ref);
+ r.assertErrorStatus();
+ r.assertMessage("draft workflow is disabled");
+ }
+ }
+
+ @GerritConfig(name = "change.allowDrafts", value = "true")
+ @Test
public void pushDraftGetsPrivateChange() throws Exception {
String changeId1 = createChange("refs/drafts/master").getChangeId();
String changeId2 = createChange("refs/for/master%draft").getChangeId();
@@ -1982,6 +1992,7 @@
assertThat(info2.revisions).hasSize(1);
}
+ @GerritConfig(name = "change.allowDrafts", value = "true")
@Sandboxed
@Test
public void pushWithDraftOptionToExistingNewChangeGetsChangeEdit() throws Exception {