diff --git a/pom.xml b/pom.xml index 942e48e1..3c2144e1 100644 --- a/pom.xml +++ b/pom.xml @@ -415,6 +415,12 @@ under the License. + + org.apache.maven.scm + maven-scm-api + 2.1.0 + + org.apache.commons commons-lang3 diff --git a/src/it/projects/site-inheritance/sub_module/pom.xml b/src/it/projects/site-inheritance/sub_module/pom.xml index f5514101..6dcd1011 100644 --- a/src/it/projects/site-inheritance/sub_module/pom.xml +++ b/src/it/projects/site-inheritance/sub_module/pom.xml @@ -30,6 +30,14 @@ under the License. ../module + + + website + + file:///@project.build.directory@/it/site-inheritance/webhost.company.com/deploy/www/website/module/submodule + + + sub_module Sub-Module diff --git a/src/main/java/org/apache/maven/plugins/site/deploy/AbstractDeployMojo.java b/src/main/java/org/apache/maven/plugins/site/deploy/AbstractDeployMojo.java index 204f2fc6..b3283014 100644 --- a/src/main/java/org/apache/maven/plugins/site/deploy/AbstractDeployMojo.java +++ b/src/main/java/org/apache/maven/plugins/site/deploy/AbstractDeployMojo.java @@ -20,9 +20,11 @@ import java.io.File; import java.net.MalformedURLException; +import java.net.URI; import java.net.URL; import java.util.List; import java.util.Locale; +import java.util.Objects; import org.apache.maven.doxia.site.inheritance.URIPathDescriptor; import org.apache.maven.doxia.tools.SiteTool; @@ -35,6 +37,7 @@ import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.site.AbstractSiteMojo; import org.apache.maven.project.MavenProject; +import org.apache.maven.scm.provider.ScmUrlUtils; import org.apache.maven.settings.Proxy; import org.apache.maven.settings.Server; import org.apache.maven.settings.Settings; @@ -523,18 +526,69 @@ protected MavenProject getTopLevelProject(MavenProject project) throws MojoExecu return oldProject; } - // MSITE-600 - URIPathDescriptor siteURI = new URIPathDescriptor(URIEncoder.encodeURI(site.getUrl()), ""); - URIPathDescriptor oldSiteURI = new URIPathDescriptor(URIEncoder.encodeURI(oldSite.getUrl()), ""); - - if (!siteURI.sameSite(oldSiteURI.getBaseURI())) { + try { + if (!isSameSite(site.getUrl(), oldSite.getUrl())) { + return oldProject; + } + } catch (IllegalArgumentException e) { + getLog().warn("Failed to parse distributionManagement.site.url of project \"" + getFullName(oldProject) + + "\" or project \"" + getFullName(parent) + "\": " + e.getMessage()); return oldProject; } } - return parent; } + /** + * Returns {@code true} if the URIs are probably pointing to the same site which means + * . + * @param parentUri + * @param uri + * @return {@code true} if the URIs are probably pointing to the same site + * @throws IllegalArgumentException if the given URIs cannot be parsed + */ + static boolean isSameSite(String parentUri, String uri) { + // this just normalizes the paths in it + URIPathDescriptor siteURI = + new URIPathDescriptor(URIEncoder.encodeURI(extractProviderSpecificPartFromScmUri(parentUri)), ""); + URIPathDescriptor oldSiteURI = + new URIPathDescriptor(URIEncoder.encodeURI(extractProviderSpecificPartFromScmUri(uri)), ""); + // compare host and path (port and scheme should not matter) + return isSameSite(siteURI.getBaseURI(), oldSiteURI.getBaseURI()); + } + + private static boolean isSameSite(URI parentUri, URI uri) { + // host must be equal + if (!Objects.equals(uri.getHost(), parentUri.getHost())) { + return false; + } + // path must be a subpath + if (uri.getPath() == null + || parentUri.getPath() == null + || !uri.getPath().startsWith(parentUri.getPath())) { + return false; + } + return true; + } + + /** + * Unwraps SCM URLs to get the provider specific part. + * @param uri + * @return the provider specific part if the given URI is a SCM URI, otherwise just the uri + * + */ + static String extractProviderSpecificPartFromScmUri(String uri) { + if (ScmUrlUtils.isValid(uri)) { + return ScmUrlUtils.getProviderSpecificPart(uri); + } else { + return uri; + } + } + private static class URIEncoder { private static final String MARK = "-_.!~*'()"; private static final String RESERVED = ";/?:@&=+$,"; diff --git a/src/test/java/org/apache/maven/plugins/site/deploy/AbstractDeployMojoTest.java b/src/test/java/org/apache/maven/plugins/site/deploy/AbstractDeployMojoTest.java new file mode 100644 index 00000000..7e2e79a1 --- /dev/null +++ b/src/test/java/org/apache/maven/plugins/site/deploy/AbstractDeployMojoTest.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.maven.plugins.site.deploy; + +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; + +public class AbstractDeployMojoTest { + + @Test + public void testIsSameSite() { + assertTrue(AbstractDeployMojo.isSameSite( + "scm:svn:https://svn.apache.org/repos/asf/maven/website/components/${maven.site.path}", + "scm:svn:https://svn.apache.org/repos/asf/maven/website/components/${maven.site.path}")); + assertTrue(AbstractDeployMojo.isSameSite( + "https://svn.apache.org/repos/asf/maven/website/components/${maven.site.path}", + "https://svn.apache.org/repos/asf/maven/website/components/${maven.site.path}")); + // different scheme (encapsulated in SCM URL) and subpath + assertTrue(AbstractDeployMojo.isSameSite( + "scm:svn:http://svn.apache.org/repos/asf/maven/website", + "scm:svn:https://svn.apache.org/repos/asf/maven/website/components")); + assertTrue(AbstractDeployMojo.isSameSite( + "scm:git:ssh://github.com/codehaus-plexus/plexus-pom.git/", + "scm:git:ssh://github.com/codehaus-plexus/plexus-pom.git/")); + assertTrue( + AbstractDeployMojo.isSameSite( + "file:////Users/konradwindszus/git/maven/maven-site-plugin/target/it/site-inheritance/webhost.company.com/deploy/www/website/module", + "file:////Users/konradwindszus/git/maven/maven-site-plugin/target/it/site-inheritance/webhost.company.com/deploy/www/website/module/submodule")); + // sibling paths + assertFalse(AbstractDeployMojo.isSameSite( + "scm:svn:https://svn.apache.org/repos/asf/maven/website/a/${maven.site.path}", + "scm:svn:https://svn.apache.org/repos/asf/maven/website/b/${maven.site.path}")); + // sibling paths + assertFalse(AbstractDeployMojo.isSameSite( + "scm:git:ssh://github.com/codehaus-plexus/plexus-pom.git/", + "scm:git:ssh://git@github.com/codehaus-plexus/plexus-sec-dispatcher.git/")); + // SCM URLs which are opaque (i.e. non hierarchical URIs) + assertThrows( + IllegalArgumentException.class, + () -> AbstractDeployMojo.isSameSite( + "scm:local:/usr/modules:my_module", "scm:local:/usr/modules:my_module")); + } +}