You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by sl...@apache.org on 2021/04/08 20:16:38 UTC

[maven-dependency-plugin] 01/03: [MDEP-437] mdep.link=true creates symlink instead of physical copy

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

slachiewicz pushed a commit to branch MDEP-437
in repository https://gitbox.apache.org/repos/asf/maven-dependency-plugin.git

commit cd4186399ef0db073e8e072ef54ab591a87986d5
Author: Markus KARG <ma...@headcrashing.eu>
AuthorDate: Wed Jul 29 20:55:23 2020 +0000

    [MDEP-437] mdep.link=true creates symlink instead of physical copy
    
    Signed-off-by: Markus KARG <ma...@headcrashing.eu>
---
 .../projects/copy-using-symlink/invoker.properties | 18 ++++++
 src/it/projects/copy-using-symlink/pom.xml         | 64 ++++++++++++++++++++++
 src/it/projects/copy-using-symlink/verify.bsh      | 38 +++++++++++++
 .../plugins/dependency/AbstractDependencyMojo.java | 33 +++++++++++
 .../dependency/fromConfiguration/CopyMojo.java     | 32 ++++++++++-
 .../dependency/fromConfiguration/TestCopyMojo.java | 30 ++++++++++
 6 files changed, 214 insertions(+), 1 deletion(-)

diff --git a/src/it/projects/copy-using-symlink/invoker.properties b/src/it/projects/copy-using-symlink/invoker.properties
new file mode 100644
index 0000000..6592030
--- /dev/null
+++ b/src/it/projects/copy-using-symlink/invoker.properties
@@ -0,0 +1,18 @@
+# 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.
+
+invoker.goals = clean process-sources -Dmdep.link=true
diff --git a/src/it/projects/copy-using-symlink/pom.xml b/src/it/projects/copy-using-symlink/pom.xml
new file mode 100644
index 0000000..d683399
--- /dev/null
+++ b/src/it/projects/copy-using-symlink/pom.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+
+<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.apache.maven.its.dependency</groupId>
+  <artifactId>test</artifactId>
+  <version>1.0-SNAPSHOT</version>
+
+  <name>Test</name>
+  <description>
+    Test dependency:copy -Dmdep.link=true
+  </description>
+
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+
+  <build>
+    <plugins>
+      <plugin>
+        <artifactId>maven-dependency-plugin</artifactId>
+        <version>@project.version@</version>
+        <executions>
+          <execution>
+            <id>test</id>
+            <goals>
+              <goal>copy</goal>
+            </goals>
+            <configuration>
+              <artifactItems>
+                <artifactItem>
+                  <groupId>org.apache.maven</groupId>
+                  <artifactId>maven-model</artifactId>
+                  <version>2.0.6</version>
+                </artifactItem>
+              </artifactItems>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/src/it/projects/copy-using-symlink/verify.bsh b/src/it/projects/copy-using-symlink/verify.bsh
new file mode 100644
index 0000000..0cd89dc
--- /dev/null
+++ b/src/it/projects/copy-using-symlink/verify.bsh
@@ -0,0 +1,38 @@
+/*
+ * 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 java.nio.file.*;
+
+Path libDir = basedir.toPath().resolve( "target/dependency" );
+
+String[] expectedFiles = {
+    "maven-model-2.0.6.jar",
+};
+
+for ( String expectedFile : expectedFiles )
+{
+    Path path = libDir.resolve( expectedFile );
+    System.out.println( "Checking for existence of link " + path );
+    if ( !Files.isSymbolicLink( path ) )
+    {
+        throw new Exception( "Missing symlink " + path );
+    }
+}
+
+return true;
diff --git a/src/main/java/org/apache/maven/plugins/dependency/AbstractDependencyMojo.java b/src/main/java/org/apache/maven/plugins/dependency/AbstractDependencyMojo.java
index 07df9f6..ec79e95 100644
--- a/src/main/java/org/apache/maven/plugins/dependency/AbstractDependencyMojo.java
+++ b/src/main/java/org/apache/maven/plugins/dependency/AbstractDependencyMojo.java
@@ -44,6 +44,7 @@ import org.codehaus.plexus.archiver.zip.ZipUnArchiver;
 import org.codehaus.plexus.components.io.filemappers.FileMapper;
 import org.codehaus.plexus.components.io.fileselectors.IncludeExcludeFileSelector;
 import org.codehaus.plexus.util.FileUtils;
+import org.codehaus.plexus.util.NioFiles;
 import org.codehaus.plexus.util.ReflectionUtils;
 import org.codehaus.plexus.util.StringUtils;
 
@@ -197,6 +198,38 @@ public abstract class AbstractDependencyMojo
     }
 
     /**
+     * Does the actual link of the file and logging.
+     *
+     * @param artifact represents the file to link to.
+     * @param destFile file name of destination link.
+     * @throws MojoExecutionException with a message if an error occurs.
+     */
+    protected void linkFile( File artifact, File destFile )
+        throws MojoExecutionException
+    {
+        try
+        {
+            getLog().info( "Linking "
+                + destFile + " to "
+                + ( this.outputAbsoluteArtifactFilename ? artifact.getAbsolutePath() : artifact.getName() ) );
+
+            if ( artifact.isDirectory() )
+            {
+                // usual case is a future jar packaging, but there are special cases: classifier and other packaging
+                throw new MojoExecutionException( "Artifact has not been packaged yet. When used on reactor artifact, "
+                    + "copy should be executed after packaging: see MDEP-187." );
+            }
+
+            // TODO Replace with FileUtils.linkFile(artifact, destFile); once https://github.com/codehaus-plexus/plexus-utils/pull/82 is merged
+            NioFiles.createSymbolicLink( destFile, artifact );
+        }
+        catch ( IOException e )
+        {
+            throw new MojoExecutionException( "Error linking " + destFile + " to artifact " + artifact, e );
+        }
+    }
+
+    /**
      * @param artifact {@link Artifact}
      * @param location The location.
      * @param encoding The encoding.
diff --git a/src/main/java/org/apache/maven/plugins/dependency/fromConfiguration/CopyMojo.java b/src/main/java/org/apache/maven/plugins/dependency/fromConfiguration/CopyMojo.java
index a2f2d35..32065f1 100644
--- a/src/main/java/org/apache/maven/plugins/dependency/fromConfiguration/CopyMojo.java
+++ b/src/main/java/org/apache/maven/plugins/dependency/fromConfiguration/CopyMojo.java
@@ -40,6 +40,13 @@ import java.util.List;
 public class CopyMojo
     extends AbstractFromConfigurationMojo
 {
+    /**
+     * Link instead of copy
+
+     * @since 3.1.3
+     */
+    @Parameter( property = "mdep.link", defaultValue = "false" )
+    private boolean link = false;
 
     /**
      * Strip artifact version during copy
@@ -132,7 +139,14 @@ public class CopyMojo
     {
         File destFile = new File( artifactItem.getOutputDirectory(), artifactItem.getDestFileName() );
 
-        copyFile( artifactItem.getArtifact().getFile(), destFile );
+        if ( this.isLink() )
+        {
+            linkFile( artifactItem.getArtifact().getFile(), destFile );
+        }
+        else
+        {
+            copyFile( artifactItem.getArtifact().getFile(), destFile );
+        }
     }
 
     @Override
@@ -146,6 +160,22 @@ public class CopyMojo
     }
 
     /**
+     * @return Returns whether to link instead of copy
+     */
+    public boolean isLink()
+    {
+        return this.link;
+    }
+
+    /**
+     * @param link Whether to link instead of copy.
+     */
+    public void setLink( boolean link )
+    {
+        this.link = link;
+    }
+
+    /**
      * @return Returns the stripVersion.
      */
     public boolean isStripVersion()
diff --git a/src/test/java/org/apache/maven/plugins/dependency/fromConfiguration/TestCopyMojo.java b/src/test/java/org/apache/maven/plugins/dependency/fromConfiguration/TestCopyMojo.java
index 52fa4e9..f060723 100644
--- a/src/test/java/org/apache/maven/plugins/dependency/fromConfiguration/TestCopyMojo.java
+++ b/src/test/java/org/apache/maven/plugins/dependency/fromConfiguration/TestCopyMojo.java
@@ -21,6 +21,8 @@ package org.apache.maven.plugins.dependency.fromConfiguration;
 
 import java.io.File;
 import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
@@ -144,6 +146,20 @@ public class TestCopyMojo
         assertEquals( exist, file.exists() );
     }
 
+    public void assertFilesAreLinks( Collection<ArtifactItem> items, boolean areLinks )
+    {
+        for ( ArtifactItem item : items )
+        {
+            assertFileIsLink( item, areLinks );
+        }
+    }
+
+    public void assertFileIsLink( ArtifactItem item, boolean isLink )
+    {
+        Path path = item.getOutputDirectory().toPath().resolve( item.getDestFileName() );
+        assertEquals( isLink, Files.isSymbolicLink( path ) );
+    }
+
     public void testMojoDefaults()
     {
         CopyMojo themojo = new CopyMojo();
@@ -233,6 +249,20 @@ public class TestCopyMojo
         assertFilesExist( list, true );
     }
 
+    public void testLink()
+        throws Exception
+    {
+        List<ArtifactItem> list = stubFactory.getArtifactItems( stubFactory.getClassifiedArtifacts() );
+
+        mojo.setArtifactItems( createArtifactItemArtifacts( list ) );
+        mojo.setLink( true );
+
+        mojo.execute();
+
+        assertFilesExist( list, true );
+        assertFilesAreLinks( list, true );
+    }
+
     public void testCopyStripVersionSetInMojo()
         throws Exception
     {