destination
will be created if they
+ * don't already exist. destination
will be overwritten if it already exists.
+ *
+ * @param source An existing non-directory File
to link to.
+ * @param destination A non-directory File
becoming the link (possibly overwriting).
+ * @throws IOException if source
does not exist, destination
cannot be created, or an
+ * IO error occurs during linking.
+ * @throws java.io.FileNotFoundException if destination
is a directory (use
+ * {@link #copyFileToDirectory}).
+ */
+ public static void linkFile( final File source, final File destination )
+ throws IOException
+ {
+ // check source exists
+ if ( !source.exists() )
+ {
+ final String message = "File " + source + " does not exist";
+ throw new IOException( message );
+ }
+
+ // check source != destination, see PLXUTILS-10
+ if ( source.getCanonicalPath().equals( destination.getCanonicalPath() ) )
+ {
+ // if they are equal, we can exit the method without doing any work
+ return;
+ }
+ mkdirsFor( destination );
+
+ NioFiles.createSymbolicLink( destination, source );
+ }
+
/**
* Copy file from source to destination only if source timestamp is later than the destination timestamp. The
* directories up to destination
will be created if they don't already exist. destination
diff --git a/src/test/java/org/codehaus/plexus/util/FileUtilsTest.java b/src/test/java/org/codehaus/plexus/util/FileUtilsTest.java
index f29dd418..4f7724f6 100644
--- a/src/test/java/org/codehaus/plexus/util/FileUtilsTest.java
+++ b/src/test/java/org/codehaus/plexus/util/FileUtilsTest.java
@@ -34,6 +34,7 @@
import java.io.Reader;
import java.io.Writer;
import java.net.URL;
+import java.nio.file.Files;
import java.util.Properties;
import org.junit.Before;
@@ -428,6 +429,50 @@ public void testCopyFile3()
assertTrue( "Check Full copy", destination.length() == testFile2Size );
}
+ // linkFile
+ @Test
+ public void testLinkFile1()
+ throws Exception
+ {
+ final File destination = new File( getTestDirectory(), "link1.txt" );
+ FileUtils.linkFile( testFile1, destination );
+ assertTrue( "Check Exist", destination.exists() );
+ assertTrue( "Check File length", destination.length() == testFile1Size );
+ assertTrue( "Check is link", Files.isSymbolicLink(destination.toPath()));
+ }
+
+ @Test
+ public void testLinkFile2()
+ throws Exception
+ {
+ final File destination = new File( getTestDirectory(), "link2.txt" );
+ FileUtils.linkFile( testFile1, destination );
+ assertTrue( "Check Exist", destination.exists() );
+ assertTrue( "Check File length", destination.length() == testFile2Size );
+ assertTrue( "Check is link", Files.isSymbolicLink(destination.toPath()));
+ }
+
+ /**
+ * ensure we create directory tree for destination
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testLinkFile3()
+ throws Exception
+ {
+ File destDirectory = new File( getTestDirectory(), "foo/bar/testlink" );
+ if ( destDirectory.exists() )
+ {
+ destDirectory.delete();
+ }
+ final File destination = new File( destDirectory, "link2.txt" );
+ FileUtils.linkFile( testFile1, destination );
+ assertTrue( "Check Exist", destination.exists() );
+ assertTrue( "Check File length", destination.length() == testFile2Size );
+ assertTrue( "Check is link", Files.isSymbolicLink(destination.toPath()));
+ }
+
// copyFileIfModified
@Test