This commit is contained in:
rfscholte 2020-10-16 20:34:10 +02:00
commit 789d75fc68
21 changed files with 568 additions and 413 deletions

View File

@ -67,22 +67,29 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
java: [8, 11, 14]
java: [8, 11, 15, 16-ea]
fail-fast: false
runs-on: ${{ matrix.os }}
steps:
- name: Collect environment context variables
shell: bash
env:
PR_HEAD_LABEL: ${{ github.event.pull_request.head.label }}
run: |
set +e
repo=maven-integration-testing
user=${GITHUB_REPOSITORY%/*}
branch=${GITHUB_REF#refs/heads/}
target_branch=master
target_user=apache
if [ "$GITHUB_EVENT_NAME" == "pull_request" ]; then
user=${PR_HEAD_LABEL%:*}
branch=${PR_HEAD_LABEL#*:}
else
user=${GITHUB_REPOSITORY%/*}
branch=${GITHUB_REF#refs/heads/}
fi
if [ $branch != "master" ]; then
git ls-remote https://github.com/$user/$repo.git | grep $GITHUB_REF > /dev/null
git ls-remote https://github.com/$user/$repo.git | grep "refs/heads/${branch}$" > /dev/null
if [ $? -eq 0 ]; then
echo "Found a branch \"$branch\" in fork \"$user/$repo\", configuring this for the integration tests to be run against."
target_branch=$branch

14
Jenkinsfile vendored
View File

@ -23,7 +23,7 @@ def buildOs = 'linux'
def buildJdk = '8'
def buildMvn = '3.6.3'
def runITsOses = ['linux', 'windows']
def runITsJdks = ['8', '11', '14', '15']
def runITsJdks = ['8', '11']
def runITsMvn = '3.6.3'
def runITscommand = "mvn clean install -Prun-its,embedded -B -U -V" // -DmavenDistro=... -Dmaven.test.failure.ignore=true
def tests
@ -52,12 +52,12 @@ node(jenkinsEnv.nodeSelection(osNode)) {
withMaven(jdk: jdkName, maven: mvnName, mavenLocalRepo:"${WORK_DIR}/.repository", options:[
artifactsPublisher(disabled: false),
junitPublisher(ignoreAttachments: false),
findbugsPublisher(disabled: false),
openTasksPublisher(disabled: false),
dependenciesFingerprintPublisher(),
invokerPublisher(),
pipelineGraphPublisher()
]) {
findbugsPublisher(disabled: true),
openTasksPublisher(disabled: true),
dependenciesFingerprintPublisher(disabled: false),
invokerPublisher(disabled: true),
pipelineGraphPublisher(disabled: false)
], publisherStrategy: 'EXPLICIT') {
// For now: maven-wrapper contains 2 poms sharing the same outputDirectory, so separate clean
sh "mvn clean"
sh "mvn ${MAVEN_GOAL} -B -U -e -fae -V -Dmaven.test.failure.ignore=true -P versionlessMavenDist"

View File

@ -20,8 +20,8 @@ Apache Maven
[![ASF Jira](https://img.shields.io/endpoint?url=https%3A%2F%2Fmaven.apache.org%2Fbadges%2Fasf_jira-MNG.json)][jira]
[![Apache License, Version 2.0, January 2004](https://img.shields.io/github/license/apache/maven.svg?label=License)][license]
[![Maven Central](https://img.shields.io/maven-central/v/org.apache.maven/apache-maven.svg?label=Maven%20Central)](https://search.maven.org/artifact/org.apache.maven/apache-maven)
[![Jenkins Status](https://img.shields.io/jenkins/s/https/builds.apache.org/job/maven-box/job/maven/job/master.svg?)][build]
[![Jenkins tests](https://img.shields.io/jenkins/t/https/builds.apache.org/job/maven-box/job/maven/job/master.svg?)][test-results]
[![Jenkins Status](https://img.shields.io/jenkins/s/https/ci-builds.apache.org/job/Maven/job/maven-box/job/maven/job/master.svg?)][build]
[![Jenkins tests](https://img.shields.io/jenkins/t/https/ci-builds.apache.org/job/Maven/job/maven-box/job/maven/job/master.svg?)][test-results]
Apache Maven is a software project management and comprehension tool. Based on
@ -40,14 +40,14 @@ the [Maven User List][users-list].
Where can I get the latest release?
-----------------------------------
You can download release source from our [download page][maven-download].
You can download the release source from our [download page][maven-download].
Contributing
------------
If you are interested in the development of Maven, please consult the
documentation first and afterwards you are welcome to join the developers
mailing list to ask question or discuss new ideas / features / bugs etc.
documentation first and afterward you are welcome to join the developers
mailing list to ask questions or discuss new ideas/features/bugs etc.
Take a look into the [contribution guidelines](CONTRIBUTING.md).
@ -59,7 +59,7 @@ See the `NOTICE` file for required notices and attributions.
Donations
---------
You like Apache Maven? Then [donate back to the ASF](https://www.apache.org/foundation/contributing.html) to support the development.
Do you like Apache Maven? Then [donate back to the ASF](https://www.apache.org/foundation/contributing.html) to support the development.
Quick Build
-------
@ -75,10 +75,10 @@ mvn -DdistributionTargetDir="$HOME/app/maven/apache-maven-3.7.x-SNAPSHOT" clean
[home]: https://maven.apache.org/
[jira]: https://issues.apache.org/jira/projects/MNG/
[license]: https://www.apache.org/licenses/LICENSE-2.0
[build]: https://builds.apache.org/job/maven-box/job/maven/job/master/
[test-results]: https://builds.apache.org/job/maven-box/job/maven/job/master/lastCompletedBuild/testReport/
[build-status]: https://img.shields.io/jenkins/s/https/builds.apache.org/job/maven-box/job/maven/job/master.svg?
[build-tests]: https://img.shields.io/jenkins/t/https/builds.apache.org/job/maven-box/job/maven/job/master.svg?
[build]: https://ci-builds.apache.org/job/Maven/job/maven-box/job/maven/job/master/
[test-results]: https://ci-builds.apache.org/job/Maven/job/maven-box/job/maven/job/master/lastCompletedBuild/testReport/
[build-status]: https://img.shields.io/jenkins/s/https/ci-builds.apache.org/job/Maven/job/maven-box/job/maven/job/master.svg?
[build-tests]: https://img.shields.io/jenkins/t/https/ci-builds.apache.org/job/Maven/job/maven-box/job/maven/job/master.svg?
[maven-home]: https://maven.apache.org/
[maven-download]: https://maven.apache.org/download.cgi
[users-list]: https://maven.apache.org/mailing-lists.html

View File

@ -66,7 +66,7 @@
Please see the file called LICENSE.
Maven URLS
Maven URLs
----------
Home Page: https://maven.apache.org/

View File

@ -1,4 +1,4 @@
https://raw.githubusercontent.com/qos-ch/slf4j/v_1.7.29/LICENSE.txt
https://raw.githubusercontent.com/qos-ch/slf4j/v_1.7.30/LICENSE.txt
Copyright (c) 2004-2017 QOS.ch
All rights reserved.

View File

@ -64,9 +64,9 @@ public class DefaultMavenExecutionRequest
private boolean interactiveMode = true;
private boolean cacheTransferError;
private boolean cacheTransferError = false;
private boolean cacheNotFound;
private boolean cacheNotFound = false;
private List<Proxy> proxies;
@ -159,7 +159,7 @@ public class DefaultMavenExecutionRequest
*
* @issue MNG-2681
*/
private boolean noSnapshotUpdates;
private boolean noSnapshotUpdates = false;
private boolean useLegacyLocalRepositoryManager = false;

View File

@ -34,6 +34,6 @@ public class BuildThreadFactory
public Thread newThread( Runnable r )
{
return new Thread( r, String.format( "%s %d", PREFIX, id.getAndIncrement() ) );
return new Thread( r, String.format( "%s-%d", PREFIX, id.getAndIncrement() ) );
}
}

View File

@ -43,7 +43,6 @@ import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.artifact.DefaultArtifact;
import org.eclipse.aether.collection.CollectRequest;
import org.eclipse.aether.collection.DependencyCollectionException;
import org.eclipse.aether.collection.DependencyGraphTransformer;
import org.eclipse.aether.collection.DependencySelector;
import org.eclipse.aether.graph.DependencyFilter;
import org.eclipse.aether.graph.DependencyNode;
@ -61,7 +60,6 @@ import org.eclipse.aether.util.filter.AndDependencyFilter;
import org.eclipse.aether.util.filter.ScopeDependencyFilter;
import org.eclipse.aether.util.graph.manager.DependencyManagerUtils;
import org.eclipse.aether.util.graph.selector.AndDependencySelector;
import org.eclipse.aether.util.graph.transformer.ChainedDependencyGraphTransformer;
import org.eclipse.aether.util.repository.SimpleArtifactDescriptorPolicy;
/**
@ -145,7 +143,7 @@ public class DefaultPluginDependenciesResolver
List<RemoteRepository> repositories, RepositorySystemSession session )
throws PluginResolutionException
{
return resolveInternal( plugin, null /* pluginArtifact */, dependencyFilter, null /* transformer */,
return resolveInternal( plugin, null /* pluginArtifact */, dependencyFilter,
repositories, session );
}
@ -153,12 +151,11 @@ public class DefaultPluginDependenciesResolver
List<RemoteRepository> repositories, RepositorySystemSession session )
throws PluginResolutionException
{
return resolveInternal( plugin, pluginArtifact, dependencyFilter, new PlexusUtilsInjector(), repositories,
return resolveInternal( plugin, pluginArtifact, dependencyFilter, repositories,
session );
}
private DependencyNode resolveInternal( Plugin plugin, Artifact pluginArtifact, DependencyFilter dependencyFilter,
DependencyGraphTransformer transformer,
List<RemoteRepository> repositories, RepositorySystemSession session )
throws PluginResolutionException
{
@ -179,12 +176,9 @@ public class DefaultPluginDependenciesResolver
DependencySelector selector =
AndDependencySelector.newInstance( session.getDependencySelector(), new WagonExcluder() );
transformer =
ChainedDependencyGraphTransformer.newInstance( session.getDependencyGraphTransformer(), transformer );
DefaultRepositorySystemSession pluginSession = new DefaultRepositorySystemSession( session );
pluginSession.setDependencySelector( selector );
pluginSession.setDependencyGraphTransformer( transformer );
pluginSession.setDependencyGraphTransformer( session.getDependencyGraphTransformer() );
CollectRequest request = new CollectRequest();
request.setRequestContext( REPOSITORY_CONTEXT );

View File

@ -1,87 +0,0 @@
package org.apache.maven.plugin.internal;
/*
* 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.
*/
import org.eclipse.aether.RepositoryException;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.artifact.DefaultArtifact;
import org.eclipse.aether.collection.DependencyGraphTransformationContext;
import org.eclipse.aether.collection.DependencyGraphTransformer;
import org.eclipse.aether.graph.DefaultDependencyNode;
import org.eclipse.aether.graph.Dependency;
import org.eclipse.aether.graph.DependencyNode;
import org.eclipse.aether.util.artifact.JavaScopes;
/**
* Injects plexus-utils:1.1 into a plugin's class path if it doesn't already declare a dependency on plexus-utils. This
* is another legacy bit to provide backward-compat with Maven 2.x.
*
* @author Benjamin Bentmann
*/
class PlexusUtilsInjector
implements DependencyGraphTransformer
{
private static final String GID = "org.codehaus.plexus";
private static final String AID = "plexus-utils";
private static final String VER = "1.1";
private static final String EXT = "jar";
public DependencyNode transformGraph( DependencyNode node, DependencyGraphTransformationContext context )
throws RepositoryException
{
if ( findPlexusUtils( node ) == null )
{
Artifact pu = new DefaultArtifact( GID, AID, null, EXT, VER );
DefaultDependencyNode child = new DefaultDependencyNode( new Dependency( pu, JavaScopes.RUNTIME ) );
child.setRepositories( node.getRepositories() );
child.setRequestContext( node.getRequestContext() );
node.getChildren().add( child );
}
return node;
}
private DependencyNode findPlexusUtils( DependencyNode node )
{
Artifact artifact = node.getDependency().getArtifact();
if ( AID.equals( artifact.getArtifactId() ) && GID.equals( artifact.getGroupId() )
&& EXT.equals( artifact.getExtension() ) && "".equals( artifact.getClassifier() ) )
{
return node;
}
for ( DependencyNode child : node.getChildren() )
{
DependencyNode result = findPlexusUtils( child );
if ( result != null )
{
return result;
}
}
return null;
}
}

View File

@ -210,15 +210,14 @@ public class DefaultProjectBuildingHelper
exportedArtifacts.put( extensionRealm, extensionDescriptor.getExportedArtifacts() );
}
if ( !plugin.isExtensions() && artifacts.size() == 2 && artifacts.get( 0 ).getFile() != null
&& "plexus-utils".equals( artifacts.get( 1 ).getArtifactId() ) )
if ( !plugin.isExtensions() && artifacts.size() == 1 && artifacts.get( 0 ).getFile() != null )
{
/*
* This is purely for backward-compat with 2.x where <extensions> consisting of a single artifact where
* loaded into the core and hence available to plugins, in contrast to bigger extensions that were
* loaded into a dedicated realm which is invisible to plugins (MNG-2749).
*/
publicArtifacts.add( artifacts.get( 0 ) );
publicArtifacts.addAll( artifacts );
}
}

View File

@ -111,7 +111,7 @@ public class ProjectModelResolver
this.externalRepositories = original.externalRepositories;
this.repositories = new ArrayList<>( original.repositories );
this.repositoryMerging = original.repositoryMerging;
this.repositoryIds = new HashSet<>( original.repositoryIds );
this.repositoryIds = new HashSet<>();
this.modelPool = original.modelPool;
}

View File

@ -69,6 +69,7 @@ under the License.
<exportedPackage>org.eclipse.aether.resolution</exportedPackage>
<exportedPackage>org.eclipse.aether.spi</exportedPackage>
<exportedPackage>org.eclipse.aether.transfer</exportedPackage>
<exportedPackage>org.eclipse.aether.transform</exportedPackage>
<exportedPackage>org.eclipse.aether.version</exportedPackage>
<!-- plexus-classworlds -->

View File

@ -36,6 +36,7 @@ import java.util.Properties;
import org.apache.maven.AbstractCoreMavenComponentTestCase;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.Plugin;
import org.apache.maven.model.building.FileModelSource;
import org.apache.maven.model.building.ModelBuildingRequest;
import org.apache.maven.model.building.ModelSource;
@ -330,4 +331,17 @@ public class ProjectBuilderTest
assertEquals( 1, project.getMailingLists().size() );
assertEquals( 1, project.getResources().size() );
}
public void testPropertyInPluginManagementGroupId()
throws Exception
{
File pom = getProject( "MNG-6983" );
MavenSession session = createMavenSession( pom );
MavenProject project = session.getCurrentProject();
for (Plugin buildPlugin : project.getBuildPlugins()) {
assertNotNull( "Missing version for build plugin " + buildPlugin.getKey(), buildPlugin.getVersion() );
}
}
}

View File

@ -0,0 +1,38 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<codehaus.groupId>org.codehaus.mojo</codehaus.groupId>
</properties>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>${codehaus.groupId}</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<id>add-source-config</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>.</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

View File

@ -0,0 +1,22 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.example</groupId>
<artifactId>parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>./parent-pom.xml</relativePath>
</parent>
<artifactId>child</artifactId>
<packaging>jar</packaging>
<build>
<plugins>
<plugin>
<groupId>${codehaus.groupId}</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@ -103,6 +103,7 @@ import java.io.InputStream;
import java.io.PrintStream;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
@ -112,6 +113,7 @@ import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -147,6 +149,8 @@ public class MavenCli
public static final String STYLE_COLOR_PROPERTY = "style.color";
private static final String[] DEPRECATED_OPTIONS = { "up", "npu", "cpu", "npr" };
private ClassWorld classWorld;
private LoggerManager plexusLoggerManager;
@ -1334,287 +1338,63 @@ public class MavenCli
return defaultLocation;
}
private MavenExecutionRequest populateRequest( CliRequest cliRequest )
protected MavenExecutionRequest populateRequest( CliRequest cliRequest )
{
return populateRequest( cliRequest, cliRequest.request );
}
@SuppressWarnings( "checkstyle:methodlength" )
private MavenExecutionRequest populateRequest( CliRequest cliRequest, MavenExecutionRequest request )
{
slf4jLoggerFactory = LoggerFactory.getILoggerFactory();
CommandLine commandLine = cliRequest.commandLine;
String workingDirectory = cliRequest.workingDirectory;
boolean quiet = cliRequest.quiet;
boolean showErrors = cliRequest.showErrors;
String[] deprecatedOptions = { "up", "npu", "cpu", "npr" };
for ( String deprecatedOption : deprecatedOptions )
{
if ( commandLine.hasOption( deprecatedOption ) )
{
slf4jLogger.warn( "Command line option -{} is deprecated and will be removed in future Maven versions.",
deprecatedOption );
}
}
// ----------------------------------------------------------------------
// Now that we have everything that we need we will fire up plexus and
// bring the maven component to life for use.
// ----------------------------------------------------------------------
if ( commandLine.hasOption( CLIManager.BATCH_MODE ) )
{
request.setInteractiveMode( false );
}
boolean noSnapshotUpdates = false;
if ( commandLine.hasOption( CLIManager.SUPRESS_SNAPSHOT_UPDATES ) )
{
noSnapshotUpdates = true;
}
// ----------------------------------------------------------------------
//
// ----------------------------------------------------------------------
List<String> goals = commandLine.getArgList();
boolean recursive = true;
// this is the default behavior.
String reactorFailureBehaviour = MavenExecutionRequest.REACTOR_FAIL_FAST;
slf4jLoggerFactory = LoggerFactory.getILoggerFactory();
if ( commandLine.hasOption( CLIManager.NON_RECURSIVE ) )
{
recursive = false;
}
if ( commandLine.hasOption( CLIManager.FAIL_FAST ) )
{
reactorFailureBehaviour = MavenExecutionRequest.REACTOR_FAIL_FAST;
}
else if ( commandLine.hasOption( CLIManager.FAIL_AT_END ) )
{
reactorFailureBehaviour = MavenExecutionRequest.REACTOR_FAIL_AT_END;
}
else if ( commandLine.hasOption( CLIManager.FAIL_NEVER ) )
{
reactorFailureBehaviour = MavenExecutionRequest.REACTOR_FAIL_NEVER;
}
if ( commandLine.hasOption( CLIManager.OFFLINE ) )
{
request.setOffline( true );
}
boolean updateSnapshots = false;
if ( commandLine.hasOption( CLIManager.UPDATE_SNAPSHOTS ) )
{
updateSnapshots = true;
}
String globalChecksumPolicy = null;
if ( commandLine.hasOption( CLIManager.CHECKSUM_FAILURE_POLICY ) )
{
globalChecksumPolicy = MavenExecutionRequest.CHECKSUM_POLICY_FAIL;
}
else if ( commandLine.hasOption( CLIManager.CHECKSUM_WARNING_POLICY ) )
{
globalChecksumPolicy = MavenExecutionRequest.CHECKSUM_POLICY_WARN;
}
request.setShowErrors( cliRequest.showErrors ); // default: false
File baseDirectory = new File( workingDirectory, "" ).getAbsoluteFile();
// ----------------------------------------------------------------------
// Profile Activation
// ----------------------------------------------------------------------
handleDeprecatedOptions( commandLine );
List<String> activeProfiles = new ArrayList<>();
List<String> inactiveProfiles = new ArrayList<>();
if ( commandLine.hasOption( CLIManager.ACTIVATE_PROFILES ) )
{
String[] profileOptionValues = commandLine.getOptionValues( CLIManager.ACTIVATE_PROFILES );
if ( profileOptionValues != null )
{
for ( String profileOptionValue : profileOptionValues )
{
StringTokenizer profileTokens = new StringTokenizer( profileOptionValue, "," );
while ( profileTokens.hasMoreTokens() )
{
String profileAction = profileTokens.nextToken().trim();
if ( profileAction.startsWith( "-" ) || profileAction.startsWith( "!" ) )
{
inactiveProfiles.add( profileAction.substring( 1 ) );
}
else if ( profileAction.startsWith( "+" ) )
{
activeProfiles.add( profileAction.substring( 1 ) );
}
else
{
activeProfiles.add( profileAction );
}
}
}
}
}
TransferListener transferListener;
if ( quiet || cliRequest.commandLine.hasOption( CLIManager.NO_TRANSFER_PROGRESS ) )
{
transferListener = new QuietMavenTransferListener();
}
else if ( request.isInteractiveMode() && !cliRequest.commandLine.hasOption( CLIManager.LOG_FILE ) )
{
//
// If we're logging to a file then we don't want the console transfer listener as it will spew
// download progress all over the place
//
transferListener = getConsoleTransferListener( cliRequest.commandLine.hasOption( CLIManager.DEBUG ) );
}
else
{
transferListener = getBatchTransferListener();
}
ExecutionListener executionListener = new ExecutionEventLogger();
if ( eventSpyDispatcher != null )
{
executionListener = eventSpyDispatcher.chainListener( executionListener );
}
String alternatePomFile = null;
if ( commandLine.hasOption( CLIManager.ALTERNATE_POM_FILE ) )
{
alternatePomFile = commandLine.getOptionValue( CLIManager.ALTERNATE_POM_FILE );
}
request.setBaseDirectory( baseDirectory ).setGoals( goals ).setSystemProperties(
cliRequest.systemProperties ).setUserProperties( cliRequest.userProperties ).setReactorFailureBehavior(
reactorFailureBehaviour ) // default: fail fast
.setRecursive( recursive ) // default: true
.setShowErrors( showErrors ) // default: false
.addActiveProfiles( activeProfiles ) // optional
.addInactiveProfiles( inactiveProfiles ) // optional
.setExecutionListener( executionListener ).setTransferListener(
transferListener ) // default: batch mode which goes along with interactive
.setUpdateSnapshots( updateSnapshots ) // default: false
.setNoSnapshotUpdates( noSnapshotUpdates ) // default: false
.setGlobalChecksumPolicy( globalChecksumPolicy ) // default: warn
.setMultiModuleProjectDirectory( cliRequest.multiModuleProjectDirectory );
if ( alternatePomFile != null )
{
File pom = resolveFile( new File( alternatePomFile ), workingDirectory );
if ( pom.isDirectory() )
{
pom = new File( pom, "pom.xml" );
}
request.setPom( pom );
}
else if ( modelProcessor != null )
{
File pom = modelProcessor.locatePom( baseDirectory );
if ( pom.isFile() )
{
request.setPom( pom );
}
}
disableOnPresentOption( commandLine, CLIManager.BATCH_MODE, request::setInteractiveMode );
enableOnPresentOption( commandLine, CLIManager.SUPRESS_SNAPSHOT_UPDATES, request::setNoSnapshotUpdates );
request.setGoals( commandLine.getArgList() );
request.setReactorFailureBehavior( determineReactorFailureBehaviour ( commandLine ) );
disableOnPresentOption( commandLine, CLIManager.NON_RECURSIVE, request::setRecursive );
enableOnPresentOption( commandLine, CLIManager.OFFLINE, request::setOffline );
enableOnPresentOption( commandLine, CLIManager.UPDATE_SNAPSHOTS, request::setUpdateSnapshots );
request.setGlobalChecksumPolicy( determineGlobalCheckPolicy( commandLine ) );
request.setBaseDirectory( baseDirectory );
request.setSystemProperties( cliRequest.systemProperties );
request.setUserProperties( cliRequest.userProperties );
request.setMultiModuleProjectDirectory( cliRequest.multiModuleProjectDirectory );
request.setPom( determinePom( commandLine, workingDirectory, baseDirectory ) );
request.setTransferListener( determineTransferListener( quiet, commandLine, request ) );
request.setExecutionListener( determineExecutionListener() );
if ( ( request.getPom() != null ) && ( request.getPom().getParentFile() != null ) )
{
request.setBaseDirectory( request.getPom().getParentFile() );
}
if ( commandLine.hasOption( CLIManager.RESUME ) )
{
request.setResume( true );
}
if ( commandLine.hasOption( CLIManager.RESUME_FROM ) )
{
request.setResumeFrom( commandLine.getOptionValue( CLIManager.RESUME_FROM ) );
}
if ( commandLine.hasOption( CLIManager.PROJECT_LIST ) )
{
String[] projectOptionValues = commandLine.getOptionValues( CLIManager.PROJECT_LIST );
List<String> inclProjects = new ArrayList<>();
List<String> exclProjects = new ArrayList<>();
if ( projectOptionValues != null )
{
for ( String projectOptionValue : projectOptionValues )
{
StringTokenizer projectTokens = new StringTokenizer( projectOptionValue, "," );
while ( projectTokens.hasMoreTokens() )
{
String projectAction = projectTokens.nextToken().trim();
if ( projectAction.startsWith( "-" ) || projectAction.startsWith( "!" ) )
{
exclProjects.add( projectAction.substring( 1 ) );
}
else if ( projectAction.startsWith( "+" ) )
{
inclProjects.add( projectAction.substring( 1 ) );
}
else
{
inclProjects.add( projectAction );
}
}
}
}
request.setSelectedProjects( inclProjects );
request.setExcludedProjects( exclProjects );
}
if ( commandLine.hasOption( CLIManager.ALSO_MAKE ) && !commandLine.hasOption(
CLIManager.ALSO_MAKE_DEPENDENTS ) )
{
request.setMakeBehavior( MavenExecutionRequest.REACTOR_MAKE_UPSTREAM );
}
else if ( !commandLine.hasOption( CLIManager.ALSO_MAKE ) && commandLine.hasOption(
CLIManager.ALSO_MAKE_DEPENDENTS ) )
{
request.setMakeBehavior( MavenExecutionRequest.REACTOR_MAKE_DOWNSTREAM );
}
else if ( commandLine.hasOption( CLIManager.ALSO_MAKE ) && commandLine.hasOption(
CLIManager.ALSO_MAKE_DEPENDENTS ) )
{
request.setMakeBehavior( MavenExecutionRequest.REACTOR_MAKE_BOTH );
}
String localRepoProperty = request.getUserProperties().getProperty( MavenCli.LOCAL_REPO_PROPERTY );
if ( localRepoProperty == null )
{
localRepoProperty = request.getSystemProperties().getProperty( MavenCli.LOCAL_REPO_PROPERTY );
}
if ( localRepoProperty != null )
{
request.setLocalRepositoryPath( localRepoProperty );
}
enableOnPresentOption( commandLine, CLIManager.RESUME, request::setResume );
request.setMakeBehavior( determineMakeBehavior( commandLine ) );
request.setCacheNotFound( true );
request.setCacheTransferError( false );
final ProjectActivation projectActivation = determineProjectActivation( commandLine );
request.setSelectedProjects( projectActivation.activeProjects );
request.setExcludedProjects( projectActivation.inactiveProjects );
final ProfileActivation profileActivation = determineProfileActivation( commandLine );
request.addActiveProfiles( profileActivation.activeProfiles );
request.addInactiveProfiles( profileActivation.inactiveProfiles );
final String localRepositoryPath = determineLocalRepositoryPath( request );
if ( localRepositoryPath != null )
{
request.setLocalRepositoryPath( localRepositoryPath );
}
//
// Builder, concurrency and parallelism
//
@ -1623,9 +1403,7 @@ public class MavenCli
// parameters but this is sufficient for now. Ultimately we want components like Builders to provide a way to
// extend the command line to accept its own configuration parameters.
//
final String threadConfiguration = commandLine.hasOption( CLIManager.THREADS )
? commandLine.getOptionValue( CLIManager.THREADS )
: null;
final String threadConfiguration = commandLine.getOptionValue( CLIManager.THREADS );
if ( threadConfiguration != null )
{
@ -1647,14 +1425,278 @@ public class MavenCli
//
// Allow the builder to be overridden by the user if requested. The builders are now pluggable.
//
if ( commandLine.hasOption( CLIManager.BUILDER ) )
{
request.setBuilderId( commandLine.getOptionValue( CLIManager.BUILDER ) );
}
request.setBuilderId( commandLine.getOptionValue( CLIManager.BUILDER, request.getBuilderId() ) );
return request;
}
private String determineLocalRepositoryPath( final MavenExecutionRequest request )
{
String userDefinedLocalRepo = request.getUserProperties().getProperty( MavenCli.LOCAL_REPO_PROPERTY );
if ( userDefinedLocalRepo != null )
{
return userDefinedLocalRepo;
}
return request.getSystemProperties().getProperty( MavenCli.LOCAL_REPO_PROPERTY );
}
private File determinePom( final CommandLine commandLine, final String workingDirectory, final File baseDirectory )
{
String alternatePomFile = null;
if ( commandLine.hasOption( CLIManager.ALTERNATE_POM_FILE ) )
{
alternatePomFile = commandLine.getOptionValue( CLIManager.ALTERNATE_POM_FILE );
}
if ( alternatePomFile != null )
{
File pom = resolveFile( new File( alternatePomFile ), workingDirectory );
if ( pom.isDirectory() )
{
pom = new File( pom, "pom.xml" );
}
return pom;
}
else if ( modelProcessor != null )
{
File pom = modelProcessor.locatePom( baseDirectory );
if ( pom.isFile() )
{
return pom;
}
}
return null;
}
// Visible for testing
static ProjectActivation determineProjectActivation ( final CommandLine commandLine )
{
final ProjectActivation projectActivation = new ProjectActivation();
if ( commandLine.hasOption( CLIManager.PROJECT_LIST ) )
{
String[] projectOptionValues = commandLine.getOptionValues( CLIManager.PROJECT_LIST );
if ( projectOptionValues != null )
{
for ( String projectOptionValue : projectOptionValues )
{
StringTokenizer projectTokens = new StringTokenizer( projectOptionValue, "," );
while ( projectTokens.hasMoreTokens() )
{
String projectAction = projectTokens.nextToken().trim();
if ( projectAction.startsWith( "-" ) || projectAction.startsWith( "!" ) )
{
projectActivation.deactivate( projectAction.substring( 1 ) );
}
else if ( projectAction.startsWith( "+" ) )
{
projectActivation.activate( projectAction.substring( 1 ) );
}
else
{
projectActivation.activate( projectAction );
}
}
}
}
}
return projectActivation;
}
// Visible for testing
static ProfileActivation determineProfileActivation( final CommandLine commandLine )
{
final ProfileActivation result = new ProfileActivation();
if ( commandLine.hasOption( CLIManager.ACTIVATE_PROFILES ) )
{
String[] profileOptionValues = commandLine.getOptionValues( CLIManager.ACTIVATE_PROFILES );
if ( profileOptionValues != null )
{
for ( String profileOptionValue : profileOptionValues )
{
StringTokenizer profileTokens = new StringTokenizer( profileOptionValue, "," );
while ( profileTokens.hasMoreTokens() )
{
String profileAction = profileTokens.nextToken().trim();
if ( profileAction.startsWith( "-" ) || profileAction.startsWith( "!" ) )
{
result.deactivate( profileAction.substring( 1 ) );
}
else if ( profileAction.startsWith( "+" ) )
{
result.activate( profileAction.substring( 1 ) );
}
else
{
result.activate( profileAction );
}
}
}
}
}
return result;
}
private ExecutionListener determineExecutionListener()
{
ExecutionListener executionListener = new ExecutionEventLogger();
if ( eventSpyDispatcher != null )
{
return eventSpyDispatcher.chainListener( executionListener );
}
else
{
return executionListener;
}
}
private void handleDeprecatedOptions( final CommandLine commandLine )
{
Arrays.stream( DEPRECATED_OPTIONS )
.filter( commandLine::hasOption )
.forEach( deprecatedOption -> slf4jLogger.warn(
"Command line option -{} is deprecated and will be removed in future Maven versions.",
deprecatedOption )
);
}
private String determineReactorFailureBehaviour( final CommandLine commandLine )
{
if ( commandLine.hasOption( CLIManager.FAIL_FAST ) )
{
return MavenExecutionRequest.REACTOR_FAIL_FAST;
}
else if ( commandLine.hasOption( CLIManager.FAIL_AT_END ) )
{
return MavenExecutionRequest.REACTOR_FAIL_AT_END;
}
else if ( commandLine.hasOption( CLIManager.FAIL_NEVER ) )
{
return MavenExecutionRequest.REACTOR_FAIL_NEVER;
}
else
{
// this is the default behavior.
return MavenExecutionRequest.REACTOR_FAIL_FAST;
}
}
private TransferListener determineTransferListener( final boolean quiet,
final CommandLine commandLine,
final MavenExecutionRequest request )
{
if ( quiet || commandLine.hasOption( CLIManager.NO_TRANSFER_PROGRESS ) )
{
return new QuietMavenTransferListener();
}
else if ( request.isInteractiveMode() && !commandLine.hasOption( CLIManager.LOG_FILE ) )
{
//
// If we're logging to a file then we don't want the console transfer listener as it will spew
// download progress all over the place
//
return getConsoleTransferListener( commandLine.hasOption( CLIManager.DEBUG ) );
}
else
{
// default: batch mode which goes along with interactive
return getBatchTransferListener();
}
}
private String determineMakeBehavior( final CommandLine cl )
{
if ( cl.hasOption( CLIManager.ALSO_MAKE ) && !cl.hasOption( CLIManager.ALSO_MAKE_DEPENDENTS ) )
{
return MavenExecutionRequest.REACTOR_MAKE_UPSTREAM;
}
else if ( !cl.hasOption( CLIManager.ALSO_MAKE ) && cl.hasOption( CLIManager.ALSO_MAKE_DEPENDENTS ) )
{
return MavenExecutionRequest.REACTOR_MAKE_DOWNSTREAM;
}
else if ( cl.hasOption( CLIManager.ALSO_MAKE ) && cl.hasOption( CLIManager.ALSO_MAKE_DEPENDENTS ) )
{
return MavenExecutionRequest.REACTOR_MAKE_BOTH;
}
else
{
return null;
}
}
private String determineGlobalCheckPolicy( final CommandLine commandLine )
{
if ( commandLine.hasOption( CLIManager.CHECKSUM_FAILURE_POLICY ) )
{
return MavenExecutionRequest.CHECKSUM_POLICY_FAIL;
}
else if ( commandLine.hasOption( CLIManager.CHECKSUM_WARNING_POLICY ) )
{
return MavenExecutionRequest.CHECKSUM_POLICY_WARN;
}
else
{
return null;
}
}
private void disableOnPresentOption( final CommandLine commandLine,
final String option,
final Consumer<Boolean> setting )
{
if ( commandLine.hasOption( option ) )
{
setting.accept( false );
}
}
private void disableOnPresentOption( final CommandLine commandLine,
final char option,
final Consumer<Boolean> setting )
{
disableOnPresentOption( commandLine, String.valueOf( option ), setting );
}
private void enableOnPresentOption( final CommandLine commandLine,
final String option,
final Consumer<Boolean> setting )
{
if ( commandLine.hasOption( option ) )
{
setting.accept( true );
}
}
private void enableOnPresentOption( final CommandLine commandLine,
final char option,
final Consumer<Boolean> setting )
{
enableOnPresentOption( commandLine, String.valueOf( option ), setting );
}
private void enableOnAbsentOption( final CommandLine commandLine,
final char option,
final Consumer<Boolean> setting )
{
if ( !commandLine.hasOption( option ) )
{
setting.accept( true );
}
}
int calculateDegreeOfConcurrencyWithCoreMultiplier( String threadConfiguration )
{
int procs = Runtime.getRuntime().availableProcessors();
@ -1769,4 +1811,46 @@ public class MavenCli
{
return container.lookup( ModelProcessor.class );
}
// Visible for testing
static class ProfileActivation
{
final List<String> activeProfiles = new ArrayList<>();
final List<String> inactiveProfiles = new ArrayList<>();
public void deactivate( final String profile )
{
inactiveProfiles.add( profile );
}
public void activate( final String profile )
{
activeProfiles.add( profile );
}
}
// Visible for testing
static class ProjectActivation
{
List<String> activeProjects;
List<String> inactiveProjects;
public void deactivate( final String project )
{
if ( inactiveProjects == null )
{
inactiveProjects = new ArrayList<>();
}
inactiveProjects.add( project );
}
public void activate( final String project )
{
if ( activeProjects == null )
{
activeProjects = new ArrayList<>();
}
activeProjects.add( project );
}
}
}

View File

@ -20,14 +20,19 @@ package org.apache.maven.cli;
*/
import static java.util.Arrays.asList;
import static org.apache.maven.cli.MavenCli.determineProfileActivation;
import static org.apache.maven.cli.MavenCli.determineProjectActivation;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.hamcrest.collection.IsIterableContainingInOrder.contains;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
@ -36,9 +41,14 @@ import java.io.File;
import java.util.Collections;
import java.util.List;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.maven.Maven;
import org.apache.maven.eventspy.internal.EventSpyDispatcher;
import org.apache.maven.execution.MavenExecutionRequest;
import org.apache.maven.project.MavenProject;
import org.apache.maven.shared.utils.logging.MessageUtils;
import org.apache.maven.toolchain.building.ToolchainsBuildingRequest;
@ -47,6 +57,7 @@ import org.codehaus.plexus.DefaultPlexusContainer;
import org.codehaus.plexus.PlexusContainer;
import org.eclipse.sisu.plexus.PlexusBeanModule;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InOrder;
@ -81,6 +92,54 @@ public class MavenCliTest
}
}
@Test
public void testDetermineProfileActivation() throws ParseException
{
MavenCli.ProfileActivation result;
Options options = new Options();
options.addOption( Option.builder( Character.toString( CLIManager.ACTIVATE_PROFILES ) ).hasArg().build() );
result = determineProfileActivation( new GnuParser().parse( options, new String[]{ "-P", "test1,+test2" } ) );
assertThat( result.activeProfiles.size(), is( 2 ) );
assertThat( result.activeProfiles, contains( "test1", "test2" ) );
result = determineProfileActivation( new GnuParser().parse( options, new String[]{ "-P", "!test1,-test2" } ) );
assertThat( result.inactiveProfiles.size(), is( 2 ) );
assertThat( result.inactiveProfiles, contains( "test1", "test2" ) );
result = determineProfileActivation( new GnuParser().parse( options, new String[]{ "-P", "-test1,+test2" } ) );
assertThat( result.activeProfiles.size(), is( 1 ) );
assertThat( result.activeProfiles, contains( "test2" ) );
assertThat( result.inactiveProfiles.size(), is( 1 ) );
assertThat( result.inactiveProfiles, contains( "test1" ) );
}
@Test
public void testDetermineProjectActivation() throws ParseException
{
MavenCli.ProjectActivation result;
Options options = new Options();
options.addOption( Option.builder( CLIManager.PROJECT_LIST ).hasArg().build() );
result = determineProjectActivation( new GnuParser().parse( options, new String[0] ) );
assertThat( result.activeProjects, is( nullValue() ) );
assertThat( result.inactiveProjects, is( nullValue() ) );
result = determineProjectActivation( new GnuParser().parse( options, new String[]{ "-pl", "test1,+test2" } ) );
assertThat( result.activeProjects.size(), is( 2 ) );
assertThat( result.activeProjects, contains( "test1", "test2" ) );
result = determineProjectActivation( new GnuParser().parse( options, new String[]{ "-pl", "!test1,-test2" } ) );
assertThat( result.inactiveProjects.size(), is( 2 ) );
assertThat( result.inactiveProjects, contains( "test1", "test2" ) );
result = determineProjectActivation( new GnuParser().parse( options, new String[]{ "-pl" ,"-test1,+test2" } ) );
assertThat( result.activeProjects.size(), is( 1 ) );
assertThat( result.activeProjects, contains( "test2" ) );
assertThat( result.inactiveProjects.size(), is( 1 ) );
assertThat( result.inactiveProjects, contains( "test1" ) );
}
@Test
public void testCalculateDegreeOfConcurrencyWithCoreMultiplier()
{
@ -377,6 +436,36 @@ public class MavenCliTest
assertThat( selector, is( "group-a:module" ) );
}
@Test
public void verifyLocalRepositoryPath()
{
MavenCli cli = new MavenCli();
CliRequest request = new CliRequest( new String[] { }, null );
request.commandLine = new CommandLine.Builder().build();
MavenExecutionRequest executionRequest;
// Use default
executionRequest = cli.populateRequest( request );
assertThat( executionRequest.getLocalRepositoryPath(),
is( nullValue() ) );
// System-properties override default
request.getSystemProperties().setProperty( MavenCli.LOCAL_REPO_PROPERTY, "." + File.separatorChar + "custom1" );
executionRequest = cli.populateRequest( request );
assertThat( executionRequest.getLocalRepositoryPath(),
is( notNullValue() ) );
assertThat( executionRequest.getLocalRepositoryPath().toString(),
is( "." + File.separatorChar + "custom1" ) );
// User-properties override system properties
request.getUserProperties().setProperty( MavenCli.LOCAL_REPO_PROPERTY, "." + File.separatorChar + "custom2" );
executionRequest = cli.populateRequest( request );
assertThat( executionRequest.getLocalRepositoryPath(),
is( notNullValue() ) );
assertThat( executionRequest.getLocalRepositoryPath().toString(),
is( "." + File.separatorChar + "custom2" ) );
}
private MavenProject createMavenProject( String groupId, String artifactId )
{
MavenProject project = new MavenProject();

View File

@ -1191,16 +1191,16 @@
</description>
<fields>
<field>
<name>artifactId</name>
<name>groupId</name>
<version>4.0.0+</version>
<description>The artifact ID of the project to exclude.</description>
<description>The group ID of the project to exclude.</description>
<type>String</type>
<required>true</required>
</field>
<field>
<name>groupId</name>
<name>artifactId</name>
<version>4.0.0+</version>
<description>The group ID of the project to exclude.</description>
<description>The artifact ID of the project to exclude.</description>
<type>String</type>
<required>true</required>
</field>
@ -2314,18 +2314,12 @@
return id.toString();
}
//TODO we shall reset key variable when groupId/artifactId change
private String key = null;
/**
* @return the key of the plugin, ie <code>groupId:artifactId</code>
*/
public String getKey()
{
if ( key == null )
{
key = constructKey( groupId, artifactId );
}
return key;
return constructKey( groupId, artifactId );
}
/**

View File

@ -103,7 +103,7 @@ class DefaultModelResolver
this.remoteRepositoryManager = original.remoteRepositoryManager;
this.repositories = new ArrayList<>( original.repositories );
this.externalRepositories = original.externalRepositories;
this.repositoryIds = new HashSet<>( original.repositoryIds );
this.repositoryIds = new HashSet<>();
}
@Override

View File

@ -57,7 +57,7 @@ under the License.
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant</artifactId>
<version>1.10.4</version>
<version>1.10.8</version>
<scope>test</scope>
</dependency>
</dependencies>

View File

@ -65,8 +65,8 @@ under the License.
<cipherVersion>1.8</cipherVersion>
<modelloVersion>1.11</modelloVersion>
<jxpathVersion>1.3</jxpathVersion>
<resolverVersion>1.4.2</resolverVersion>
<slf4jVersion>1.7.29</slf4jVersion>
<resolverVersion>1.6.1</resolverVersion>
<slf4jVersion>1.7.30</slf4jVersion>
<xmlunitVersion>2.6.4</xmlunitVersion>
<maven.test.redirectTestOutputToFile>true</maven.test.redirectTestOutputToFile>
<!-- Control the name of the distribution and information output by mvn -->
@ -112,7 +112,7 @@ under the License.
</issueManagement>
<ciManagement>
<system>Jenkins</system>
<url>https://builds.apache.org/job/maven-box/job/maven/</url>
<url>https://ci-builds.apache.org/job/Maven/job/maven-box/job/maven/</url>
</ciManagement>
<distributionManagement>
<downloadUrl>https://maven.apache.org/download.html</downloadUrl>