Merge branch 'stable-2.14' into stable-2.15 * stable-2.14: Upgrade bazlets to latest stable-2.14 to build with 2.14.21 API Change-Id: I019248f4eaf54c1df186a13a53f4832c86cf7b1e
diff --git a/WORKSPACE b/WORKSPACE index bec0fab..663727a 100644 --- a/WORKSPACE +++ b/WORKSPACE
@@ -3,7 +3,7 @@ load("//:bazlets.bzl", "load_bazlets") load_bazlets( - commit = "78c35a7eb33ee5ea0980923e246c7dba37347193", + commit = "f53f51fb660552d0581aa0ba52c3836ed63d56a3", #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);