You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by eo...@apache.org on 2020/05/10 14:07:49 UTC

[maven-studies] 05/23: [MNG-4660] --resume-from flag resolves inter-module dependencies

This is an automated email from the ASF dual-hosted git repository.

eolivelli pushed a commit to branch maven-metrics
in repository https://gitbox.apache.org/repos/asf/maven-studies.git

commit ec92934bf08f11e8541e897c0f466f1f03c73a78
Author: Maarten Mulders <mt...@users.noreply.github.com>
AuthorDate: Tue Apr 14 22:04:55 2020 +0200

    [MNG-4660] --resume-from flag resolves inter-module dependencies
    
    Co-authored-by: Martin Kanters <Ma...@infosupport.com>
---
 .../main/java/org/apache/maven/ReactorReader.java  | 105 +++++++++++++++++++--
 .../org/apache/maven/execution/MavenSession.java   |   2 +-
 .../project/artifact/MavenMetadataSource.java      |   9 +-
 pom.xml                                            |   7 +-
 4 files changed, 111 insertions(+), 12 deletions(-)

diff --git a/maven-core/src/main/java/org/apache/maven/ReactorReader.java b/maven-core/src/main/java/org/apache/maven/ReactorReader.java
index 831a4b6..03463df 100644
--- a/maven-core/src/main/java/org/apache/maven/ReactorReader.java
+++ b/maven-core/src/main/java/org/apache/maven/ReactorReader.java
@@ -20,14 +20,20 @@ package org.apache.maven;
  */
 
 import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Stream;
 
 import javax.inject.Inject;
 import javax.inject.Named;
@@ -37,6 +43,7 @@ import org.apache.maven.execution.MavenSession;
 import org.apache.maven.model.Model;
 import org.apache.maven.project.MavenProject;
 import org.apache.maven.repository.internal.MavenWorkspaceReader;
+import org.codehaus.plexus.logging.Logger;
 import org.eclipse.aether.artifact.Artifact;
 import org.eclipse.aether.repository.WorkspaceRepository;
 import org.eclipse.aether.util.artifact.ArtifactIdUtils;
@@ -57,6 +64,10 @@ class ReactorReader
     private static final Collection<String> COMPILE_PHASE_TYPES =
         Arrays.asList( "jar", "ejb-client", "war", "rar", "ejb3", "par", "sar", "wsr", "har", "app-client" );
 
+    private Logger logger;
+
+    private MavenSession session;
+
     private Map<String, MavenProject> projectsByGAV;
 
     private Map<String, List<MavenProject>> projectsByGA;
@@ -64,9 +75,16 @@ class ReactorReader
     private WorkspaceRepository repository;
 
     @Inject
-    ReactorReader( MavenSession session )
+    ReactorReader( MavenSession session, Logger logger )
     {
-        projectsByGAV = session.getProjectMap();
+        this.logger = logger;
+        this.session = session;
+        this.projectsByGAV = new HashMap<>( session.getAllProjects().size() * 2 );
+        session.getAllProjects().forEach( project ->
+        {
+            String projectId = ArtifactUtils.key( project.getGroupId(), project.getArtifactId(), project.getVersion() );
+            this.projectsByGAV.put( projectId, project );
+        } );
 
         projectsByGA = new HashMap<>( projectsByGAV.size() * 2 );
         for ( MavenProject project : projectsByGAV.values() )
@@ -152,12 +170,19 @@ class ReactorReader
         }
 
         Artifact projectArtifact = findMatchingArtifact( project, artifact );
+        File packagedArtifactFile = determinePreviouslyPackagedArtifactFile( project, projectArtifact );
 
         if ( hasArtifactFileFromPackagePhase( projectArtifact ) )
         {
             return projectArtifact.getFile();
         }
-        else if ( !hasBeenPackaged( project ) )
+        // Check whether an earlier Maven run might have produced an artifact that is still on disk.
+        else if ( packagedArtifactFile != null && packagedArtifactFile.exists()
+                && isPackagedArtifactUpToDate( project, packagedArtifactFile ) )
+        {
+            return packagedArtifactFile;
+        }
+        else if ( !hasBeenPackagedDuringThisSession( project ) )
         {
             // fallback to loose class files only if artifacts haven't been packaged yet
             // and only for plain old jars. Not war files, not ear files, not anything else.
@@ -172,9 +197,21 @@ class ReactorReader
             else
             {
                 String type = artifact.getProperty( "type", "" );
-                if ( project.hasLifecyclePhase( "compile" ) && COMPILE_PHASE_TYPES.contains( type ) )
+                File outputDirectory = new File( project.getBuild().getOutputDirectory() );
+
+                // Check if the project is being built during this session, and if we can expect any output.
+                // There is no need to check if the build has created any outputs, see MNG-2222.
+                boolean projectCompiledDuringThisSession
+                        = project.hasLifecyclePhase( "compile" ) && COMPILE_PHASE_TYPES.contains( type );
+
+                // Check if the project is part of the session (not filtered by -pl, -rf, etc). If so, we check
+                // if a possible earlier Maven invocation produced some output for that project which we can use.
+                boolean projectHasOutputFromPreviousSession
+                        = !session.getProjects().contains( project ) && outputDirectory.exists();
+
+                if ( projectHasOutputFromPreviousSession || projectCompiledDuringThisSession )
                 {
-                    return new File( project.getBuild().getOutputDirectory() );
+                    return outputDirectory;
                 }
             }
         }
@@ -184,12 +221,68 @@ class ReactorReader
         return null;
     }
 
+    private File determinePreviouslyPackagedArtifactFile( MavenProject project, Artifact artifact )
+    {
+        if ( artifact == null )
+        {
+            return null;
+        }
+
+        String fileName = String.format( "%s.%s", project.getBuild().getFinalName(), artifact.getExtension() );
+        return new File( project.getBuild().getDirectory(), fileName );
+    }
+
     private boolean hasArtifactFileFromPackagePhase( Artifact projectArtifact )
     {
         return projectArtifact != null && projectArtifact.getFile() != null && projectArtifact.getFile().exists();
     }
 
-    private boolean hasBeenPackaged( MavenProject project )
+    private boolean isPackagedArtifactUpToDate( MavenProject project, File packagedArtifactFile )
+    {
+        Path outputDirectory = Paths.get( project.getBuild().getOutputDirectory() );
+        if ( !outputDirectory.toFile().exists() )
+        {
+            return true;
+        }
+
+        try ( Stream<Path> outputFiles = Files.walk( outputDirectory ) )
+        {
+            // Not using File#lastModified() to avoid a Linux JDK8 milliseconds precision bug: JDK-8177809.
+            long artifactLastModified = Files.getLastModifiedTime( packagedArtifactFile.toPath() ).toMillis();
+
+            if ( session.getProjectBuildingRequest().getBuildStartTime() != null )
+            {
+                long buildStartTime = session.getProjectBuildingRequest().getBuildStartTime().getTime();
+                if ( artifactLastModified > buildStartTime )
+                {
+                    return true;
+                }
+            }
+
+            Iterator<Path> iterator = outputFiles.iterator();
+            while ( iterator.hasNext() )
+            {
+                Path outputFile = iterator.next();
+                long outputFileLastModified = Files.getLastModifiedTime( outputFile ).toMillis();
+                if ( outputFileLastModified > artifactLastModified )
+                {
+                    logger.warn( "Packaged artifact is not up-to-date compared to the build output directory" );
+                    return false;
+                }
+            }
+
+            return true;
+        }
+        catch ( IOException e )
+        {
+            logger.warn( "An I/O error occurred while checking if the packaged artifact is up-to-date "
+                    + "against the build output directory. "
+                    + "Continuing with the assumption that it is up-to-date.", e );
+            return true;
+        }
+    }
+
+    private boolean hasBeenPackagedDuringThisSession( MavenProject project )
     {
         return project.hasLifecyclePhase( "package" ) || project.hasLifecyclePhase( "install" )
             || project.hasLifecyclePhase( "deploy" );
diff --git a/maven-core/src/main/java/org/apache/maven/execution/MavenSession.java b/maven-core/src/main/java/org/apache/maven/execution/MavenSession.java
index 5b56df3..8da252f 100644
--- a/maven-core/src/main/java/org/apache/maven/execution/MavenSession.java
+++ b/maven-core/src/main/java/org/apache/maven/execution/MavenSession.java
@@ -297,7 +297,7 @@ public class MavenSession
     private final Settings settings;
     
     @Deprecated
-    /** @deprecated This appears to only be used in the ReactorReader and we can do any processing required there */
+    /** @deprecated This appears not to be used anywhere within Maven itself. */
     public Map<String, MavenProject> getProjectMap() 
     {
         return projectMap;
diff --git a/maven-core/src/main/java/org/apache/maven/project/artifact/MavenMetadataSource.java b/maven-core/src/main/java/org/apache/maven/project/artifact/MavenMetadataSource.java
index a8f382e..4073f1d 100644
--- a/maven-core/src/main/java/org/apache/maven/project/artifact/MavenMetadataSource.java
+++ b/maven-core/src/main/java/org/apache/maven/project/artifact/MavenMetadataSource.java
@@ -38,7 +38,6 @@ import javax.inject.Singleton;
 
 import org.apache.maven.RepositoryUtils;
 import org.apache.maven.artifact.Artifact;
-import org.apache.maven.artifact.ArtifactUtils;
 import org.apache.maven.artifact.factory.ArtifactFactory;
 import org.apache.maven.artifact.metadata.ArtifactMetadataRetrievalException;
 import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
@@ -197,9 +196,11 @@ public class MavenMetadataSource
             DependencyManagement dependencyManagement = model.getDependencyManagement();
             managedDependencies = dependencyManagement == null ? null : dependencyManagement.getDependencies();
             MavenSession session = legacySupport.getSession();
-            MavenProject project = session.getProjectMap().get(
-                ArtifactUtils.key( artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion() ) );
-            pomRepositories = project.getRemoteArtifactRepositories();
+            pomRepositories = session.getProjects().stream()
+                    .filter( p -> artifact.equals( p.getArtifact() ) )
+                    .map( MavenProject::getRemoteArtifactRepositories )
+                    .findFirst()
+                    .orElseGet( ArrayList::new );
         }
         else if ( artifact instanceof ArtifactWithDependencies )
         {
diff --git a/pom.xml b/pom.xml
index 5dc9f45..5cfac55 100644
--- a/pom.xml
+++ b/pom.xml
@@ -158,7 +158,12 @@ under the License.
       <name>Mike Mol (MNG-6665)</name>
     </contributor>
     <contributor>
-      <name>Martin Kanters (MNG-6665, MNG-6065)</name>
+      <name>Martin Kanters</name>
+      <organization>Info Support</organization>
+    </contributor>
+    <contributor>
+      <name>Maarten Mulders</name>
+      <organization>Info Support</organization>
     </contributor>
     <contributor>
       <name>Luc Klaassen (MNG-6065)</name>