Skip to content

Commit 0d363ab

Browse files
committed
[MDEP-437] mdep.link=true creates symlink instead of physical copy
Signed-off-by: Markus KARG <markus@headcrashing.eu>
1 parent 50568fc commit 0d363ab

File tree

6 files changed

+214
-1
lines changed

6 files changed

+214
-1
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
invoker.goals = clean process-sources -Dmdep.link=true
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
~ Licensed to the Apache Software Foundation (ASF) under one
4+
~ or more contributor license agreements. See the NOTICE file
5+
~ distributed with this work for additional information
6+
~ regarding copyright ownership. The ASF licenses this file
7+
~ to you under the Apache License, Version 2.0 (the
8+
~ "License"); you may not use this file except in compliance
9+
~ with the License. You may obtain a copy of the License at
10+
~
11+
~ http://www.apache.org/licenses/LICENSE-2.0
12+
~
13+
~ Unless required by applicable law or agreed to in writing,
14+
~ software distributed under the License is distributed on an
15+
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16+
~ KIND, either express or implied. See the License for the
17+
~ specific language governing permissions and limitations
18+
~ under the License.
19+
-->
20+
21+
<project xmlns="http://maven.apache.org/POM/4.0.0"
22+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
23+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
24+
<modelVersion>4.0.0</modelVersion>
25+
26+
<groupId>org.apache.maven.its.dependency</groupId>
27+
<artifactId>test</artifactId>
28+
<version>1.0-SNAPSHOT</version>
29+
30+
<name>Test</name>
31+
<description>
32+
Test dependency:copy -Dmdep.link=true
33+
</description>
34+
35+
<properties>
36+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
37+
</properties>
38+
39+
<build>
40+
<plugins>
41+
<plugin>
42+
<artifactId>maven-dependency-plugin</artifactId>
43+
<version>@project.version@</version>
44+
<executions>
45+
<execution>
46+
<id>test</id>
47+
<goals>
48+
<goal>copy</goal>
49+
</goals>
50+
<configuration>
51+
<artifactItems>
52+
<artifactItem>
53+
<groupId>org.apache.maven</groupId>
54+
<artifactId>maven-model</artifactId>
55+
<version>2.0.6</version>
56+
</artifactItem>
57+
</artifactItems>
58+
</configuration>
59+
</execution>
60+
</executions>
61+
</plugin>
62+
</plugins>
63+
</build>
64+
</project>
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
import java.nio.file.*;
21+
22+
Path libDir = basedir.toPath().resolve( "target/dependency" );
23+
24+
String[] expectedFiles = {
25+
"maven-model-2.0.6.jar",
26+
};
27+
28+
for ( String expectedFile : expectedFiles )
29+
{
30+
Path path = libDir.resolve( expectedFile );
31+
System.out.println( "Checking for existence of link " + path );
32+
if ( !Files.isSymbolicLink( path ) )
33+
{
34+
throw new Exception( "Missing symlink " + path );
35+
}
36+
}
37+
38+
return true;

src/main/java/org/apache/maven/plugins/dependency/AbstractDependencyMojo.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import org.codehaus.plexus.components.io.filemappers.FileMapper;
4545
import org.codehaus.plexus.components.io.fileselectors.IncludeExcludeFileSelector;
4646
import org.codehaus.plexus.util.FileUtils;
47+
import org.codehaus.plexus.util.NioFiles;
4748
import org.codehaus.plexus.util.ReflectionUtils;
4849
import org.codehaus.plexus.util.StringUtils;
4950

@@ -196,6 +197,38 @@ protected void copyFile( File artifact, File destFile )
196197
}
197198
}
198199

200+
/**
201+
* Does the actual link of the file and logging.
202+
*
203+
* @param artifact represents the file to link to.
204+
* @param destFile file name of destination link.
205+
* @throws MojoExecutionException with a message if an error occurs.
206+
*/
207+
protected void linkFile( File artifact, File destFile )
208+
throws MojoExecutionException
209+
{
210+
try
211+
{
212+
getLog().info( "Linking "
213+
+ destFile + " to "
214+
+ ( this.outputAbsoluteArtifactFilename ? artifact.getAbsolutePath() : artifact.getName() ) );
215+
216+
if ( artifact.isDirectory() )
217+
{
218+
// usual case is a future jar packaging, but there are special cases: classifier and other packaging
219+
throw new MojoExecutionException( "Artifact has not been packaged yet. When used on reactor artifact, "
220+
+ "copy should be executed after packaging: see MDEP-187." );
221+
}
222+
223+
// TODO Replace with FileUtils.linkFile(artifact, destFile); once https://github.com/codehaus-plexus/plexus-utils/pull/82 is merged
224+
NioFiles.createSymbolicLink( destFile, artifact );
225+
}
226+
catch ( IOException e )
227+
{
228+
throw new MojoExecutionException( "Error linking " + destFile + " to artifact " + artifact, e );
229+
}
230+
}
231+
199232
/**
200233
* @param artifact {@link Artifact}
201234
* @param location The location.

src/main/java/org/apache/maven/plugins/dependency/fromConfiguration/CopyMojo.java

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,13 @@
4040
public class CopyMojo
4141
extends AbstractFromConfigurationMojo
4242
{
43+
/**
44+
* Link instead of copy
45+
46+
* @since 3.1.3
47+
*/
48+
@Parameter( property = "mdep.link", defaultValue = "false" )
49+
private boolean link = false;
4350

4451
/**
4552
* Strip artifact version during copy
@@ -132,7 +139,14 @@ protected void copyArtifact( ArtifactItem artifactItem )
132139
{
133140
File destFile = new File( artifactItem.getOutputDirectory(), artifactItem.getDestFileName() );
134141

135-
copyFile( artifactItem.getArtifact().getFile(), destFile );
142+
if ( this.isLink() )
143+
{
144+
linkFile( artifactItem.getArtifact().getFile(), destFile );
145+
}
146+
else
147+
{
148+
copyFile( artifactItem.getArtifact().getFile(), destFile );
149+
}
136150
}
137151

138152
@Override
@@ -145,6 +159,22 @@ protected ArtifactItemFilter getMarkedArtifactFilter( ArtifactItem item )
145159
return destinationNameOverrideFilter;
146160
}
147161

162+
/**
163+
* @return Returns whether to link instead of copy
164+
*/
165+
public boolean isLink()
166+
{
167+
return this.link;
168+
}
169+
170+
/**
171+
* @param link Whether to link instead of copy.
172+
*/
173+
public void setLink( boolean link )
174+
{
175+
this.link = link;
176+
}
177+
148178
/**
149179
* @return Returns the stripVersion.
150180
*/

src/test/java/org/apache/maven/plugins/dependency/fromConfiguration/TestCopyMojo.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121

2222
import java.io.File;
2323
import java.io.IOException;
24+
import java.nio.file.Files;
25+
import java.nio.file.Path;
2426
import java.util.ArrayList;
2527
import java.util.Collection;
2628
import java.util.List;
@@ -144,6 +146,20 @@ public void assertFileExists( ArtifactItem item, boolean exist )
144146
assertEquals( exist, file.exists() );
145147
}
146148

149+
public void assertFilesAreLinks( Collection<ArtifactItem> items, boolean areLinks )
150+
{
151+
for ( ArtifactItem item : items )
152+
{
153+
assertFileIsLink( item, areLinks );
154+
}
155+
}
156+
157+
public void assertFileIsLink( ArtifactItem item, boolean isLink )
158+
{
159+
Path path = item.getOutputDirectory().toPath().resolve( item.getDestFileName() );
160+
assertEquals( isLink, Files.isSymbolicLink( path ) );
161+
}
162+
147163
public void testMojoDefaults()
148164
{
149165
CopyMojo themojo = new CopyMojo();
@@ -233,6 +249,20 @@ public void testCopyToLocation()
233249
assertFilesExist( list, true );
234250
}
235251

252+
public void testLink()
253+
throws Exception
254+
{
255+
List<ArtifactItem> list = stubFactory.getArtifactItems( stubFactory.getClassifiedArtifacts() );
256+
257+
mojo.setArtifactItems( createArtifactItemArtifacts( list ) );
258+
mojo.setLink( true );
259+
260+
mojo.execute();
261+
262+
assertFilesExist( list, true );
263+
assertFilesAreLinks( list, true );
264+
}
265+
236266
public void testCopyStripVersionSetInMojo()
237267
throws Exception
238268
{

0 commit comments

Comments
 (0)