Merge branch 'stable-2.14' into stable-2.15
* stable-2.14:
Bazel: Migrate workspace status script to python
Change-Id: Ic4877ce81c885f1b36c96745b7b9ef8772522a61
diff --git a/WORKSPACE b/WORKSPACE
index 8518b38..7c19745 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -3,7 +3,7 @@
load("//:bazlets.bzl", "load_bazlets")
load_bazlets(
- commit = "e48c6a61d5a3f9ab4589f324fc85b8e3777d8854",
+ commit = "d735ef54dfd38f99106d5635228156139c0b57fd",
#local_path = "/home/<user>/projects/bazlets",
)
diff --git a/external_plugin_deps.bzl b/external_plugin_deps.bzl
index 1d8851b..c1932a9 100644
--- a/external_plugin_deps.bzl
+++ b/external_plugin_deps.bzl
@@ -3,8 +3,8 @@
def external_plugin_deps():
maven_jar(
name = "mockito",
- artifact = "org.mockito:mockito-core:2.27.0",
- sha1 = "835fc3283b481f4758b8ef464cd560c649c08b00",
+ artifact = "org.mockito:mockito-core:2.28.2",
+ sha1 = "91110215a8cb9b77a46e045ee758f77d79167cc0",
deps = [
"@byte-buddy//jar",
"@byte-buddy-agent//jar",
diff --git a/src/main/java/com/ericsson/gerrit/plugins/goimport/GoImportFilter.java b/src/main/java/com/ericsson/gerrit/plugins/goimport/GoImportFilter.java
index e728713..2a370d4 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/goimport/GoImportFilter.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/goimport/GoImportFilter.java
@@ -14,6 +14,7 @@
package com.ericsson.gerrit.plugins.goimport;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;
import com.google.gerrit.httpd.AllRequestFilter;
import com.google.gerrit.httpd.HtmlDomUtil;
@@ -30,6 +31,7 @@
import java.net.URISyntaxException;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.util.regex.Pattern;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
@@ -39,6 +41,25 @@
@Singleton
public class GoImportFilter extends AllRequestFilter {
+ @VisibleForTesting static final String CONTENT_PLH = "${content}";
+
+ @VisibleForTesting
+ static final String PAGE_200 =
+ "<!DOCTYPE html>\n"
+ + "<html>\n"
+ + "<head>\n"
+ + " <title>Gerrit-Go-Import</title>\n"
+ + " <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"/>\n"
+ + " <meta name=\"go-import\" content=\""
+ + CONTENT_PLH
+ + "\"/>\n"
+ + "</head>\n"
+ + "<body>\n"
+ + "<div>\n"
+ + " Gerrit-Go-Import\n"
+ + "</div>\n"
+ + "</body>\n"
+ + "</html>";
private static final String PAGE_404 =
"<!DOCTYPE html>\n"
@@ -52,21 +73,7 @@
+ "</body>\n"
+ "</html>";
- private static final String PAGE_200 =
- "<!DOCTYPE html>\n"
- + "<html>\n"
- + "<head>\n"
- + " <title>Gerrit-Go-Import</title>\n"
- + " <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"/>\n"
- + " <meta name=\"go-import\" content=\"${content}\"/>\n"
- + "</head>\n"
- + "<body>\n"
- + "<div>\n"
- + " Gerrit-Go-Import\n"
- + "</div>\n"
- + "</body>\n"
- + "</html>";
-
+ private static final Pattern AUTHENTICATED_REQ = Pattern.compile("^/a/.*");
private final ProjectCache projectCache;
final String webUrl;
final String projectPrefix;
@@ -90,8 +97,11 @@
if (request instanceof HttpServletRequest) {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse rsp = (HttpServletResponse) response;
- String servletPath = req.getServletPath();
if ("1".equals(req.getParameter("go-get"))) {
+ boolean authenticated = AUTHENTICATED_REQ.matcher(req.getServletPath()).matches();
+ // For authenticated requests remove prefix "/a" to get project name.
+ String path =
+ authenticated ? req.getServletPath().replaceFirst("^/a/", "/") : req.getServletPath();
// Because Gerrit allows for arbitrary-depth project names
// (that is, both "a" and "a/b/c" are both legal), we are going
// to find the most specific such project that matches the path.
@@ -104,11 +114,11 @@
// 3. If the requested path is "a/c", then project "a" would be chosen.
// 4. If the requested path is "a/b/c/d", then project "a/b" would be chosen.
// 5. If the requested path is "x/y/z", then this will fail with a 404 error.
- String existent = getLongestMatch(getProjectName(servletPath));
+ String existent = getLongestMatch(getProjectName(path));
byte[] toSend = PAGE_404.getBytes();
rsp.setStatus(404);
if (!Strings.isNullOrEmpty(existent)) {
- toSend = PAGE_200.replace("${content}", getContent(existent)).getBytes();
+ toSend = PAGE_200.replace(CONTENT_PLH, getContent(existent, authenticated)).getBytes();
rsp.setStatus(200);
}
CacheHeaders.setNotCacheable(rsp);
@@ -145,8 +155,14 @@
return servletPath.replaceFirst("/", "");
}
- private CharSequence getContent(String projectName) {
- return projectPrefix + projectName + " git " + webUrl + "a/" + projectName;
+ private CharSequence getContent(String projectName, boolean authenticated) {
+ return projectPrefix
+ + (authenticated ? "a/" : "")
+ + projectName
+ + " git "
+ + webUrl
+ + "a/"
+ + projectName;
}
private boolean projectExists(String projectName) {
diff --git a/src/main/resources/Documentation/build.md b/src/main/resources/Documentation/build.md
index 8e5bbf7..47eb5a9 100644
--- a/src/main/resources/Documentation/build.md
+++ b/src/main/resources/Documentation/build.md
@@ -61,7 +61,7 @@
To execute the tests run:
```
- bazel test plugins/@PLUGIN@:go_import_tests
+ bazel test plugins/@PLUGIN@:go-import_tests
```
How to build the Gerrit Plugin API is described in the [Gerrit
diff --git a/src/test/java/com/ericsson/gerrit/plugins/goimport/GoImportFilterTest.java b/src/test/java/com/ericsson/gerrit/plugins/goimport/GoImportFilterTest.java
index d00e03e..4ecd9e9 100644
--- a/src/test/java/com/ericsson/gerrit/plugins/goimport/GoImportFilterTest.java
+++ b/src/test/java/com/ericsson/gerrit/plugins/goimport/GoImportFilterTest.java
@@ -14,6 +14,8 @@
package com.ericsson.gerrit.plugins.goimport;
+import static com.ericsson.gerrit.plugins.goimport.GoImportFilter.CONTENT_PLH;
+import static com.ericsson.gerrit.plugins.goimport.GoImportFilter.PAGE_200;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.any;
@@ -40,22 +42,25 @@
@RunWith(MockitoJUnitRunner.class)
public class GoImportFilterTest {
+ private static final String PROD_FQDN = "gerrit-review.googlesource.com";
+ private static final String PROD_URL = "https://" + PROD_FQDN;
+ private static final String PROJECT_NAME = "projectName";
+ private static final String CONTENT_FORMAT = "%1$s/%3$s git %2$s/%3$s";
+ private static final String CONTENT =
+ String.format(CONTENT_FORMAT, PROD_FQDN, auth(PROD_URL), PROJECT_NAME);
+ private static final String AUTH_CONTENT =
+ String.format(CONTENT_FORMAT, auth(PROD_FQDN), auth(PROD_URL), PROJECT_NAME);
- private static final String PROD_URL = "https://gerrit-review.googlesource.com";
- private static final String PAGE_200 =
- "<!DOCTYPE html>\n"
- + "<html>\n"
- + "<head>\n"
- + " <title>Gerrit-Go-Import</title>\n"
- + " <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"/>\n"
- + " <meta name=\"go-import\" content=\"gerrit-review.googlesource.com/projectName git https://gerrit-review.googlesource.com/a/projectName\"/>\n"
- + "</head>\n"
- + "<body>\n"
- + "<div>\n"
- + " Gerrit-Go-Import\n"
- + "</div>\n"
- + "</body>\n"
- + "</html>";
+ /** URLs that require authentication has an additional "/a" ($BASE/a/$ENDPOINT). */
+ private static String auth(String baseUrl) {
+ return baseUrl + "/a";
+ }
+
+ private static byte[] response200(boolean authenticated) {
+ return authenticated
+ ? PAGE_200.replace(CONTENT_PLH, AUTH_CONTENT).getBytes()
+ : PAGE_200.replace(CONTENT_PLH, CONTENT).getBytes();
+ }
private GoImportFilter unitUnderTest;
@@ -95,7 +100,6 @@
@Test
public void testDoFilterWithoutGoGetParameter() throws Exception {
- when(mockRequest.getServletPath()).thenReturn("/projectName");
when(mockRequest.getParameter("go-get")).thenReturn(null);
unitUnderTest.doFilter(mockRequest, mockResponse, mockChain);
verify(mockOutputStream, times(0)).write(any(byte[].class));
@@ -104,7 +108,6 @@
@Test
public void testDoFilterWithWrongGoGetParameterValue() throws Exception {
- when(mockRequest.getServletPath()).thenReturn("/projectName");
when(mockRequest.getParameter("go-get")).thenReturn("2");
unitUnderTest.doFilter(mockRequest, mockResponse, mockChain);
verify(mockOutputStream, times(0)).write(any(byte[].class));
@@ -113,11 +116,23 @@
@Test
public void testDoFilterWithExistingProject() throws Exception {
- when(mockRequest.getServletPath()).thenReturn("/projectName");
+ when(mockRequest.getServletPath()).thenReturn("/" + PROJECT_NAME);
when(mockRequest.getParameter("go-get")).thenReturn("1");
- when(mockProjectCache.get(new Project.NameKey("projectName"))).thenReturn(mockProjectState);
+ when(mockProjectCache.get(new Project.NameKey(PROJECT_NAME))).thenReturn(mockProjectState);
unitUnderTest.doFilter(mockRequest, mockResponse, mockChain);
- verify(mockOutputStream, times(1)).write(PAGE_200.getBytes());
+ verify(mockOutputStream, times(1)).write(response200(false));
+ verify(mockChain, times(0)).doFilter(mockRequest, mockResponse);
+ verify(mockProjectCache, times(1)).get(any(Project.NameKey.class));
+ verify(mockResponse, times(1)).setStatus(200);
+ }
+
+ @Test
+ public void testDoFilterAuthenticatedWithExistingProject() throws Exception {
+ when(mockRequest.getServletPath()).thenReturn("/a/" + PROJECT_NAME);
+ when(mockRequest.getParameter("go-get")).thenReturn("1");
+ when(mockProjectCache.get(new Project.NameKey(PROJECT_NAME))).thenReturn(mockProjectState);
+ unitUnderTest.doFilter(mockRequest, mockResponse, mockChain);
+ verify(mockOutputStream, times(1)).write(response200(true));
verify(mockChain, times(0)).doFilter(mockRequest, mockResponse);
verify(mockProjectCache, times(1)).get(any(Project.NameKey.class));
verify(mockResponse, times(1)).setStatus(200);
@@ -125,11 +140,11 @@
@Test
public void testDoFilterWithExistingProjectAndPackage() throws Exception {
- when(mockRequest.getServletPath()).thenReturn("/projectName/my/package");
+ when(mockRequest.getServletPath()).thenReturn("/" + PROJECT_NAME + "/my/package");
when(mockRequest.getParameter("go-get")).thenReturn("1");
- when(mockProjectCache.get(new Project.NameKey("projectName"))).thenReturn(mockProjectState);
+ when(mockProjectCache.get(new Project.NameKey(PROJECT_NAME))).thenReturn(mockProjectState);
unitUnderTest.doFilter(mockRequest, mockResponse, mockChain);
- verify(mockOutputStream, times(1)).write(PAGE_200.getBytes());
+ verify(mockOutputStream, times(1)).write(response200(false));
verify(mockChain, times(0)).doFilter(mockRequest, mockResponse);
verify(mockProjectCache, times(3)).get(any(Project.NameKey.class));
verify(mockResponse, times(1)).setStatus(200);
@@ -137,7 +152,7 @@
@Test
public void testDoFilterWithNonExistingProject() throws Exception {
- when(mockRequest.getServletPath()).thenReturn("/projectName");
+ when(mockRequest.getServletPath()).thenReturn("/" + PROJECT_NAME);
when(mockRequest.getParameter("go-get")).thenReturn("1");
when(mockProjectCache.get(any(Project.NameKey.class))).thenReturn(null);
unitUnderTest.doFilter(mockRequest, mockResponse, mockChain);
@@ -150,7 +165,7 @@
@Test
public void testDoFilterWithIOException() throws Exception {
String msg = "test-io-error";
- when(mockRequest.getServletPath()).thenReturn("/projectName");
+ when(mockRequest.getServletPath()).thenReturn("/" + PROJECT_NAME);
when(mockRequest.getParameter("go-get")).thenReturn("1");
doThrow(new IOException(msg)).when(mockOutputStream).write(any(byte[].class));
when(mockProjectCache.get(any(Project.NameKey.class))).thenReturn(mockProjectState);