diff --git a/src/java/org/apache/ivy/util/FileUtil.java b/src/java/org/apache/ivy/util/FileUtil.java
index 5963d4e6..29687089 100644
--- a/src/java/org/apache/ivy/util/FileUtil.java
+++ b/src/java/org/apache/ivy/util/FileUtil.java
@@ -77,8 +77,20 @@ public final class FileUtil {
*/
public static boolean symlink(final File target, final File link, final boolean overwrite)
throws IOException {
- if (!prepareCopy(target, link, overwrite)) {
- return false;
+ // prepare for symlink
+ if (target.isFile()) {
+ // it's a file that is being symlinked, so do the necessary preparation
+ // for the linking, similar to what we do with preparation for copying
+ if (!prepareCopy(target, link, overwrite)) {
+ return false;
+ }
+ } else {
+ // it's a directory being symlinked, make sure the "link" that is being
+ // created has the necessary parent directories in place before triggering
+ // symlink creation
+ if (link.getParentFile() != null) {
+ link.getParentFile().mkdirs();
+ }
}
Files.createSymbolicLink(link.toPath(), target.getAbsoluteFile().toPath());
return true;
diff --git a/test/java/org/apache/ivy/core/retrieve/RetrieveTest.java b/test/java/org/apache/ivy/core/retrieve/RetrieveTest.java
index f5b18af6..239cd36c 100644
--- a/test/java/org/apache/ivy/core/retrieve/RetrieveTest.java
+++ b/test/java/org/apache/ivy/core/retrieve/RetrieveTest.java
@@ -27,6 +27,7 @@ import org.apache.ivy.core.event.retrieve.EndRetrieveEvent;
import org.apache.ivy.core.event.retrieve.StartRetrieveArtifactEvent;
import org.apache.ivy.core.event.retrieve.StartRetrieveEvent;
import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
+import org.apache.ivy.core.module.id.ModuleId;
import org.apache.ivy.core.module.id.ModuleRevisionId;
import org.apache.ivy.core.report.ArtifactDownloadReport;
import org.apache.ivy.core.report.ResolveReport;
@@ -254,6 +255,32 @@ public class RetrieveTest {
"jar", "default"));
}
+ /**
+ * Tests that retrieve, when invoked with "symlink" enabled, creates the necessary symlink
+ * when the artifact being retrieved is a directory instead of a regular file
+ *
+ * @throws Exception
+ * @see IVY-1594
+ */
+ @Test
+ public void testRetrieveZipArtifactWithSymlinks() throws Exception {
+ // resolve (inline) with org1:mod1.1:3.0 as a dependency
+ final ResolveReport report = ivy.resolve(new ModuleRevisionId(new ModuleId("org1", "mod1.1"), "3.0"),
+ getResolveOptions(new String[]{"*"}), false);
+ assertNotNull("Resolution report is null", report);
+ final ModuleDescriptor md = report.getModuleDescriptor();
+ assertNotNull("Module descriptor is null", md);
+
+ final String retrievePattern = "build/test/retrieve/[module]/[conf]/[artifact]-[revision]";
+ ivy.retrieve(md.getModuleRevisionId(),
+ getRetrieveOptions().setMakeSymlinks(true).setDestArtifactPattern(retrievePattern));
+
+ final String expectedRetrieveLocation = IvyPatternHelper.substitute(retrievePattern, "org1", "mod1.1",
+ "3.0", "zipped-artifact", null, null, "default");
+ // make sure it's retrieved as a symlink (on systems that support symlink)
+ assertLinkOrExists(expectedRetrieveLocation);
+ }
+
/**
* This test is here to just test the deprecated {@code symlinkmass} option for retrieve task.
* A version or two down the line, after 2.5 release, we can remove this test and the option
diff --git a/test/repositories/1/org1/mod1.1/ivys/ivy-3.0.xml b/test/repositories/1/org1/mod1.1/ivys/ivy-3.0.xml
new file mode 100644
index 00000000..373ca31e
--- /dev/null
+++ b/test/repositories/1/org1/mod1.1/ivys/ivy-3.0.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
diff --git a/test/repositories/1/org1/mod1.1/jars/zipped-artifact-3.0.zip b/test/repositories/1/org1/mod1.1/jars/zipped-artifact-3.0.zip
new file mode 100644
index 00000000..df0b4caf
Binary files /dev/null and b/test/repositories/1/org1/mod1.1/jars/zipped-artifact-3.0.zip differ