summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuca Milanesio <luca.milanesio@gmail.com>2021-09-24 01:05:44 +0100
committerLuca Milanesio <luca.milanesio@gmail.com>2021-09-24 01:05:44 +0100
commit72d88d3db230179c389c369eba7cc3d8822d7d71 (patch)
tree1386ac9a24e8e49111f7f0caeabe1e20d03b498d
parent91bea9c579170a95ec58f9e5cfdf055f07d7bc17 (diff)
parent130c4f7cf28fcd06dd9c6cbaa7aef01994777f5c (diff)
Merge branch 'stable-3.2' into stable-3.3
* stable-3.2: Unify getRefs() and getRefsByPrefix() in permission-aware refdb rest-api-projects: Fix typo referring to /groups/ Log the result of git-upload-pack command in httpd_log Fix serialization of AllUsersName and AllProjectsName Update git submodules Update jgit to 84707715108a65a366ef35f2ae04aabecd0b35f6 Add PluginServletContext#getVirtualServerName Allow moving of merge commits Change-Id: Ie2633fca8ee097171738fd871ef7fec3c44c8cc0
-rw-r--r--Documentation/intro-user.txt2
-rw-r--r--Documentation/logs.txt5
-rw-r--r--Documentation/rest-api-projects.txt4
-rw-r--r--java/com/google/gerrit/httpd/GitOverHttpServlet.java56
-rw-r--r--java/com/google/gerrit/httpd/plugins/PluginServletContext.java7
-rw-r--r--java/com/google/gerrit/pgm/http/jetty/HttpLog.java4
-rw-r--r--java/com/google/gerrit/pgm/http/jetty/HttpLogJsonLayout.java3
-rw-r--r--java/com/google/gerrit/pgm/http/jetty/HttpLogLayout.java3
-rw-r--r--java/com/google/gerrit/server/events/EventGsonProvider.java2
-rw-r--r--java/com/google/gerrit/server/git/PermissionAwareReadOnlyRefDatabase.java42
-rw-r--r--java/com/google/gerrit/server/restapi/change/Move.java3
-rw-r--r--javatests/com/google/gerrit/acceptance/rest/change/MoveChangeIT.java8
-rw-r--r--javatests/com/google/gerrit/server/events/EventDeserializerTest.java27
m---------modules/jgit0
14 files changed, 124 insertions, 42 deletions
diff --git a/Documentation/intro-user.txt b/Documentation/intro-user.txt
index eb2025c980..9909aac0ed 100644
--- a/Documentation/intro-user.txt
+++ b/Documentation/intro-user.txt
@@ -459,7 +459,7 @@ abandon permission] on the change and link:access-control.html#category_push[
push permission] on the destination branch.
The move operation will not update the change's parent and users will have
-to link:#rebase[rebase] the change. Also, merge commits cannot be moved.
+to link:#rebase[rebase] the change.
[[abandon]]
[[restore]]
diff --git a/Documentation/logs.txt b/Documentation/logs.txt
index 6624366044..f072984036 100644
--- a/Documentation/logs.txt
+++ b/Documentation/logs.txt
@@ -51,6 +51,11 @@ if a log field is not present, a "-" is substituted:
* `referer`: the `Referer` HTTP request header. This gives the site that
the client reports having been referred from.
* `client agent`: the client agent which sent the request.
+* `command status`: the overall result of the git command over HTTP. Currently
+ populated only for the transfer phase of `git-upload-pack` commands.
+ Possible values:
+** `-1`: The `git-upload-pack` transfer was ultimately not successful
+** `0`: The `git-upload-pack` transfer was ultimately successful
Example:
```
diff --git a/Documentation/rest-api-projects.txt b/Documentation/rest-api-projects.txt
index d53bd9c256..84da169b92 100644
--- a/Documentation/rest-api-projects.txt
+++ b/Documentation/rest-api-projects.txt
@@ -421,11 +421,11 @@ Query the first 25 projects in project list.
----
The `/projects/` URL also accepts a start integer in the `start`
-parameter. The results will skip `start` groups from project list.
+parameter. The results will skip `start` projects from project list.
Query 25 projects starting from index 50.
----
- GET /groups/?query=<query>&limit=25&start=50 HTTP/1.0
+ GET /projects/?query=<query>&limit=25&start=50 HTTP/1.0
----
[[project-query-options]]
diff --git a/java/com/google/gerrit/httpd/GitOverHttpServlet.java b/java/com/google/gerrit/httpd/GitOverHttpServlet.java
index 6e22704534..3e2d3efb07 100644
--- a/java/com/google/gerrit/httpd/GitOverHttpServlet.java
+++ b/java/com/google/gerrit/httpd/GitOverHttpServlet.java
@@ -14,11 +14,15 @@
package com.google.gerrit.httpd;
+import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
+import static org.eclipse.jgit.http.server.GitSmartHttpTools.sendError;
+
import com.google.common.annotations.VisibleForTesting;
import com.google.common.cache.Cache;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Lists;
+import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.data.Capable;
import com.google.gerrit.entities.Project;
import com.google.gerrit.extensions.registration.DynamicSet;
@@ -54,6 +58,7 @@ import com.google.inject.Singleton;
import com.google.inject.TypeLiteral;
import com.google.inject.name.Named;
import java.io.IOException;
+import java.text.MessageFormat;
import java.time.Duration;
import java.util.Arrays;
import java.util.Collections;
@@ -70,10 +75,13 @@ import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
+import org.eclipse.jgit.errors.PackProtocolException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.http.server.GitServlet;
import org.eclipse.jgit.http.server.GitSmartHttpTools;
+import org.eclipse.jgit.http.server.HttpServerText;
import org.eclipse.jgit.http.server.ServletUtils;
+import org.eclipse.jgit.http.server.UploadPackErrorHandler;
import org.eclipse.jgit.http.server.resolver.AsIsFileService;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
@@ -100,6 +108,23 @@ public class GitOverHttpServlet extends GitServlet {
private static final String ID_CACHE = "adv_bases";
public static final String URL_REGEX;
+ public static final String GIT_COMMAND_STATUS_HEADER = "X-git-command-status";
+
+ private enum GIT_COMMAND_STATUS {
+ OK(0),
+ FAIL(-1);
+
+ private final int exitStatus;
+
+ GIT_COMMAND_STATUS(int exitStatus) {
+ this.exitStatus = exitStatus;
+ }
+
+ @Override
+ public String toString() {
+ return Integer.toString(exitStatus);
+ }
+ }
static {
StringBuilder url = new StringBuilder();
@@ -212,12 +237,14 @@ public class GitOverHttpServlet extends GitServlet {
Resolver resolver,
UploadFactory upload,
UploadFilter uploadFilter,
+ GerritUploadPackErrorHandler uploadPackErrorHandler,
ReceivePackFactory<HttpServletRequest> receive,
ReceiveFilter receiveFilter) {
setRepositoryResolver(resolver);
setAsIsFileService(AsIsFileService.DISABLED);
setUploadPackFactory(upload);
+ setUploadPackErrorHandler(uploadPackErrorHandler);
addUploadPackFilter(uploadFilter);
setReceivePackFactory(receive);
@@ -456,6 +483,35 @@ public class GitOverHttpServlet extends GitServlet {
public void destroy() {}
}
+ static class GerritUploadPackErrorHandler implements UploadPackErrorHandler {
+ private static final FluentLogger logger = FluentLogger.forEnclosingClass();
+
+ @Override
+ public void upload(HttpServletRequest req, HttpServletResponse rsp, UploadPackRunnable r)
+ throws IOException {
+ rsp.setHeader(GIT_COMMAND_STATUS_HEADER, GIT_COMMAND_STATUS.FAIL.toString());
+ try {
+ r.upload();
+ rsp.setHeader(GIT_COMMAND_STATUS_HEADER, GIT_COMMAND_STATUS.OK.toString());
+ } catch (ServiceMayNotContinueException e) {
+ if (!e.isOutput() && !rsp.isCommitted()) {
+ rsp.reset();
+ sendError(req, rsp, e.getStatusCode(), e.getMessage());
+ }
+ } catch (Throwable e) {
+ logger.atSevere().withCause(e).log(
+ MessageFormat.format(
+ HttpServerText.get().internalErrorDuringUploadPack,
+ ServletUtils.getRepository(req)));
+ if (!rsp.isCommitted()) {
+ rsp.reset();
+ String msg = e instanceof PackProtocolException ? e.getMessage() : null;
+ sendError(req, rsp, SC_INTERNAL_SERVER_ERROR, msg);
+ }
+ }
+ }
+ }
+
static class ReceiveFactory implements ReceivePackFactory<HttpServletRequest> {
private final AsyncReceiveCommits.Factory factory;
private final Provider<CurrentUser> userProvider;
diff --git a/java/com/google/gerrit/httpd/plugins/PluginServletContext.java b/java/com/google/gerrit/httpd/plugins/PluginServletContext.java
index 40083e441e..5a8fa31c25 100644
--- a/java/com/google/gerrit/httpd/plugins/PluginServletContext.java
+++ b/java/com/google/gerrit/httpd/plugins/PluginServletContext.java
@@ -199,6 +199,11 @@ class PluginServletContext {
String v = Version.getVersion();
return "Gerrit Code Review/" + (v != null ? v : "dev");
}
+
+ @Override
+ public String getVirtualServerName() {
+ return null;
+ }
}
interface API {
@@ -255,5 +260,7 @@ class PluginServletContext {
int getMinorVersion();
String getServerInfo();
+
+ String getVirtualServerName();
}
}
diff --git a/java/com/google/gerrit/pgm/http/jetty/HttpLog.java b/java/com/google/gerrit/pgm/http/jetty/HttpLog.java
index 4e4c93b57b..27a53c2052 100644
--- a/java/com/google/gerrit/pgm/http/jetty/HttpLog.java
+++ b/java/com/google/gerrit/pgm/http/jetty/HttpLog.java
@@ -14,6 +14,8 @@
package com.google.gerrit.pgm.http.jetty;
+import static com.google.gerrit.httpd.GitOverHttpServlet.GIT_COMMAND_STATUS_HEADER;
+
import com.google.common.base.Strings;
import com.google.gerrit.httpd.GetUserFilter;
import com.google.gerrit.httpd.restapi.LogRedactUtil;
@@ -51,6 +53,7 @@ class HttpLog extends AbstractLifeCycle implements RequestLog {
protected static final String P_LATENCY = "Latency";
protected static final String P_REFERER = "Referer";
protected static final String P_USER_AGENT = "User-Agent";
+ protected static final String P_COMMAND_STATUS = "Command-Status";
private final AsyncAppender async;
@@ -113,6 +116,7 @@ class HttpLog extends AbstractLifeCycle implements RequestLog {
set(event, P_LATENCY, System.currentTimeMillis() - req.getTimeStamp());
set(event, P_REFERER, req.getHeader("Referer"));
set(event, P_USER_AGENT, req.getHeader("User-Agent"));
+ set(event, P_COMMAND_STATUS, rsp.getHeader(GIT_COMMAND_STATUS_HEADER));
async.append(event);
}
diff --git a/java/com/google/gerrit/pgm/http/jetty/HttpLogJsonLayout.java b/java/com/google/gerrit/pgm/http/jetty/HttpLogJsonLayout.java
index 95a5b07689..807b311745 100644
--- a/java/com/google/gerrit/pgm/http/jetty/HttpLogJsonLayout.java
+++ b/java/com/google/gerrit/pgm/http/jetty/HttpLogJsonLayout.java
@@ -14,6 +14,7 @@
package com.google.gerrit.pgm.http.jetty;
+import static com.google.gerrit.pgm.http.jetty.HttpLog.P_COMMAND_STATUS;
import static com.google.gerrit.pgm.http.jetty.HttpLog.P_CONTENT_LENGTH;
import static com.google.gerrit.pgm.http.jetty.HttpLog.P_HOST;
import static com.google.gerrit.pgm.http.jetty.HttpLog.P_LATENCY;
@@ -50,6 +51,7 @@ public class HttpLogJsonLayout extends JsonLayout {
public String latency;
public String referer;
public String userAgent;
+ public String commandStatus;
public HttpJsonLogEntry(LoggingEvent event) {
this.host = getMdcString(event, P_HOST);
@@ -64,6 +66,7 @@ public class HttpLogJsonLayout extends JsonLayout {
this.latency = getMdcString(event, P_LATENCY);
this.referer = getMdcString(event, P_REFERER);
this.userAgent = getMdcString(event, P_USER_AGENT);
+ this.commandStatus = getMdcString(event, P_COMMAND_STATUS);
}
}
}
diff --git a/java/com/google/gerrit/pgm/http/jetty/HttpLogLayout.java b/java/com/google/gerrit/pgm/http/jetty/HttpLogLayout.java
index 268f59fdbe..b83fcc55b0 100644
--- a/java/com/google/gerrit/pgm/http/jetty/HttpLogLayout.java
+++ b/java/com/google/gerrit/pgm/http/jetty/HttpLogLayout.java
@@ -71,6 +71,9 @@ public final class HttpLogLayout extends Layout {
buf.append(' ');
dq_opt(buf, event, HttpLog.P_USER_AGENT);
+ buf.append(' ');
+ dq_opt(buf, event, HttpLog.P_COMMAND_STATUS);
+
buf.append('\n');
return buf.toString();
}
diff --git a/java/com/google/gerrit/server/events/EventGsonProvider.java b/java/com/google/gerrit/server/events/EventGsonProvider.java
index 688507bfe3..ab51518e01 100644
--- a/java/com/google/gerrit/server/events/EventGsonProvider.java
+++ b/java/com/google/gerrit/server/events/EventGsonProvider.java
@@ -30,7 +30,7 @@ public class EventGsonProvider implements Provider<Gson> {
.registerTypeAdapter(Supplier.class, new SupplierSerializer())
.registerTypeAdapter(Supplier.class, new SupplierDeserializer())
.registerTypeAdapter(Change.Key.class, new ChangeKeyAdapter())
- .registerTypeAdapter(Project.NameKey.class, new ProjectNameKeyAdapter())
+ .registerTypeHierarchyAdapter(Project.NameKey.class, new ProjectNameKeyAdapter())
.create();
}
}
diff --git a/java/com/google/gerrit/server/git/PermissionAwareReadOnlyRefDatabase.java b/java/com/google/gerrit/server/git/PermissionAwareReadOnlyRefDatabase.java
index b7dc2b3258..7950dc6edf 100644
--- a/java/com/google/gerrit/server/git/PermissionAwareReadOnlyRefDatabase.java
+++ b/java/com/google/gerrit/server/git/PermissionAwareReadOnlyRefDatabase.java
@@ -14,7 +14,6 @@
package com.google.gerrit.server.git;
-import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;
import com.google.common.base.Preconditions;
@@ -95,20 +94,11 @@ public class PermissionAwareReadOnlyRefDatabase extends DelegateRefDatabase {
return Iterables.getOnlyElement(result);
}
+ // WARNING: This method is deprecated in JGit's RefDatabase and it will be removed on master.
+ // Do not add any logic here but rather enrich the getRefsByPrefix method below.
@Override
public Map<String, Ref> getRefs(String prefix) throws IOException {
- List<Ref> refs = getDelegate().getRefDatabase().getRefsByPrefix(prefix);
- if (refs.isEmpty()) {
- return Collections.emptyMap();
- }
-
- Collection<Ref> result;
- try {
- result = forProject.filter(refs, getDelegate(), RefFilterOptions.defaults());
- } catch (PermissionBackendException e) {
- throw new IOException("", e);
- }
- return buildPrefixRefMap(prefix, result);
+ return buildPrefixRefMap(prefix, getRefsByPrefix(prefix));
}
private Map<String, Ref> buildPrefixRefMap(String prefix, Collection<Ref> refs) {
@@ -125,26 +115,18 @@ public class PermissionAwareReadOnlyRefDatabase extends DelegateRefDatabase {
@Override
public List<Ref> getRefsByPrefix(String prefix) throws IOException {
- Map<String, Ref> coarseRefs;
- int lastSlash = prefix.lastIndexOf('/');
- if (lastSlash == -1) {
- coarseRefs = getRefs(ALL);
- } else {
- coarseRefs = getRefs(prefix.substring(0, lastSlash + 1));
+ List<Ref> refs = getDelegate().getRefDatabase().getRefsByPrefix(prefix);
+ if (refs.isEmpty()) {
+ return Collections.emptyList();
}
- List<Ref> result;
- if (lastSlash + 1 == prefix.length()) {
- result = coarseRefs.values().stream().collect(toList());
- } else {
- String p = prefix.substring(lastSlash + 1);
- result =
- coarseRefs.entrySet().stream()
- .filter(e -> e.getKey().startsWith(p))
- .map(e -> e.getValue())
- .collect(toList());
+ Collection<Ref> result;
+ try {
+ result = forProject.filter(refs, getDelegate(), RefFilterOptions.defaults());
+ } catch (PermissionBackendException e) {
+ throw new IOException("", e);
}
- return Collections.unmodifiableList(result);
+ return result.stream().collect(Collectors.toList());
}
@Override
diff --git a/java/com/google/gerrit/server/restapi/change/Move.java b/java/com/google/gerrit/server/restapi/change/Move.java
index 577174f184..ecfb96d2bc 100644
--- a/java/com/google/gerrit/server/restapi/change/Move.java
+++ b/java/com/google/gerrit/server/restapi/change/Move.java
@@ -191,9 +191,6 @@ public class Move implements RestModifyView<ChangeResource, MoveInput>, UiAction
RevWalk revWalk = new RevWalk(repo)) {
RevCommit currPatchsetRevCommit =
revWalk.parseCommit(psUtil.current(ctx.getNotes()).commitId());
- if (currPatchsetRevCommit.getParentCount() > 1) {
- throw new ResourceConflictException("Merge commit cannot be moved");
- }
ObjectId refId = repo.resolve(input.destinationBranch);
// Check if destination ref exists in project repo
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/MoveChangeIT.java b/javatests/com/google/gerrit/acceptance/rest/change/MoveChangeIT.java
index d5881ea7a2..987d646711 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/MoveChangeIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/MoveChangeIT.java
@@ -169,11 +169,9 @@ public class MoveChangeIT extends AbstractDaemonTest {
BranchNameKey newBranch =
BranchNameKey.create(r1.getChange().change().getProject(), "moveTest");
createBranch(newBranch);
- ResourceConflictException thrown =
- assertThrows(
- ResourceConflictException.class,
- () -> move(GitUtil.getChangeId(testRepo, c).get(), newBranch.branch()));
- assertThat(thrown).hasMessageThat().contains("Merge commit cannot be moved");
+ String changeId = GitUtil.getChangeId(testRepo, c).get();
+ move(changeId, newBranch.branch());
+ assertThat(gApi.changes().id(changeId).get().branch).isEqualTo("moveTest");
}
@Test
diff --git a/javatests/com/google/gerrit/server/events/EventDeserializerTest.java b/javatests/com/google/gerrit/server/events/EventDeserializerTest.java
index e0223e4885..97f6e4e64a 100644
--- a/javatests/com/google/gerrit/server/events/EventDeserializerTest.java
+++ b/javatests/com/google/gerrit/server/events/EventDeserializerTest.java
@@ -22,6 +22,8 @@ import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.Project;
+import com.google.gerrit.server.config.AllProjectsName;
+import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.data.AccountAttribute;
import com.google.gerrit.server.data.ChangeAttribute;
import com.google.gerrit.server.data.RefUpdateAttribute;
@@ -240,6 +242,31 @@ public class EventDeserializerTest {
assertSameChangeEvent(e, orig);
}
+ @Test
+ public void shouldSerializeAllProjectsToString() {
+ String allProjectsString = "foobar";
+ AllProjectsName allProjectsNameKey = new AllProjectsName(allProjectsString);
+
+ assertThat(gson.toJson(allProjectsNameKey))
+ .isEqualTo(String.format("\"%s\"", allProjectsString));
+ }
+
+ @Test
+ public void shouldSerializeAllUsersToString() {
+ String allUsersString = "foobar";
+ AllUsersName allUsersNameKey = new AllUsersName(allUsersString);
+
+ assertThat(gson.toJson(allUsersNameKey)).isEqualTo(String.format("\"%s\"", allUsersString));
+ }
+
+ @Test
+ public void shouldSerializeProjectNameKeyToString() {
+ String projectString = "foobar";
+ Project.NameKey projectNameKey = Project.nameKey(projectString);
+
+ assertThat(gson.toJson(projectNameKey)).isEqualTo(String.format("\"%s\"", projectString));
+ }
+
private <T> Supplier<T> createSupplier(T value) {
return Suppliers.memoize(() -> value);
}
diff --git a/modules/jgit b/modules/jgit
-Subproject 24d6d605388c82201092cf1699b51095299380a
+Subproject 84707715108a65a366ef35f2ae04aabecd0b35f