Author: maartenc
Date: Mon Dec 25 15:47:55 2006
New Revision: 490200

URL: http://svn.apache.org/viewvc?view=rev&rev=490200
Log:
IVY-353: ivy:retrieve should be able to create symlinks

Modified:
    incubator/ivy/trunk/CHANGES.txt
    incubator/ivy/trunk/src/java/fr/jayasoft/ivy/Ivy.java
    incubator/ivy/trunk/src/java/fr/jayasoft/ivy/ant/IvyRetrieve.java
    incubator/ivy/trunk/src/java/fr/jayasoft/ivy/util/FileUtil.java
    incubator/ivy/trunk/test/java/fr/jayasoft/ivy/RetrieveTest.java

Modified: incubator/ivy/trunk/CHANGES.txt
URL: 
http://svn.apache.org/viewvc/incubator/ivy/trunk/CHANGES.txt?view=diff&rev=490200&r1=490199&r2=490200
==============================================================================
--- incubator/ivy/trunk/CHANGES.txt (original)
+++ incubator/ivy/trunk/CHANGES.txt Mon Dec 25 15:47:55 2006
@@ -5,6 +5,10 @@
                                
 for detailed view of each issue, please consult http://jira.jayasoft.org/
 
+   version in SVN
+=====================================
+- IMPROVE: ivy:retrieve should be able to create symlinks (IVY-353) (thanks to 
John Williams)
+
    version 1.4.1 - 2006-11-09
 =====================================
 - IMPROVE: ability to rebuild all dependent projects from a leaf (IVY-101)

Modified: incubator/ivy/trunk/src/java/fr/jayasoft/ivy/Ivy.java
URL: 
http://svn.apache.org/viewvc/incubator/ivy/trunk/src/java/fr/jayasoft/ivy/Ivy.java?view=diff&rev=490200&r1=490199&r2=490200
==============================================================================
--- incubator/ivy/trunk/src/java/fr/jayasoft/ivy/Ivy.java (original)
+++ incubator/ivy/trunk/src/java/fr/jayasoft/ivy/Ivy.java Mon Dec 25 15:47:55 
2006
@@ -1914,6 +1914,9 @@
        return retrieve(moduleId, confs, cache, destFilePattern, 
destIvyPattern, artifactFilter, false, false);
     }
     public int retrieve(ModuleId moduleId, String[] confs, final File cache, 
String destFilePattern, String destIvyPattern, Filter artifactFilter, boolean 
sync, boolean useOrigin) {
+       return retrieve(moduleId, confs, cache, destFilePattern, 
destIvyPattern, artifactFilter, sync, useOrigin, false);
+    }
+    public int retrieve(ModuleId moduleId, String[] confs, final File cache, 
String destFilePattern, String destIvyPattern, Filter artifactFilter, boolean 
sync, boolean useOrigin, boolean makeSymlinks) {
        if (artifactFilter == null) {
                artifactFilter = FilterHelper.NO_FILTER;
        }
@@ -1956,7 +1959,11 @@
                     File destFile = new File((String)it2.next());
                     if (!_checkUpToDate || !upToDate(archive, destFile)) {
                         Message.verbose("\t\tto "+destFile);
-                        FileUtil.copy(archive, destFile, null);
+                        if (makeSymlinks) {
+                            FileUtil.symlink(archive, destFile, null, false);
+                        } else {
+                            FileUtil.copy(archive, destFile, null);
+                        }
                         targetsCopied++;
                     } else {
                         Message.verbose("\t\tto "+destFile+" [NOT REQUIRED]");

Modified: incubator/ivy/trunk/src/java/fr/jayasoft/ivy/ant/IvyRetrieve.java
URL: 
http://svn.apache.org/viewvc/incubator/ivy/trunk/src/java/fr/jayasoft/ivy/ant/IvyRetrieve.java?view=diff&rev=490200&r1=490199&r2=490200
==============================================================================
--- incubator/ivy/trunk/src/java/fr/jayasoft/ivy/ant/IvyRetrieve.java (original)
+++ incubator/ivy/trunk/src/java/fr/jayasoft/ivy/ant/IvyRetrieve.java Mon Dec 
25 15:47:55 2006
@@ -19,6 +19,7 @@
     private String _pattern;
     private String _ivypattern = null;
     private boolean _sync = false;
+    private boolean _symlink = false;
     
     public String getPattern() {
         return _pattern;
@@ -33,7 +34,7 @@
         _pattern = getProperty(_pattern, getIvyInstance(), 
"ivy.retrieve.pattern");
         try {
                Filter artifactFilter = getArtifactFilter();
-            int targetsCopied = 
getIvyInstance().retrieve(getResolvedModuleId(), splitConfs(getConf()), 
getCache(), _pattern, _ivypattern, artifactFilter, _sync, isUseOrigin());
+            int targetsCopied = 
getIvyInstance().retrieve(getResolvedModuleId(), splitConfs(getConf()), 
getCache(), _pattern, _ivypattern, artifactFilter, _sync, isUseOrigin(), 
_symlink);
             boolean haveTargetsBeenCopied = targetsCopied > 0;
             getProject().setProperty("ivy.nb.targets.copied", 
String.valueOf(targetsCopied));
             getProject().setProperty("ivy.targets.copied", 
String.valueOf(haveTargetsBeenCopied));
@@ -53,5 +54,11 @@
        public void setSync(boolean sync) {
                _sync = sync;
        }
-    
+
+    /**
+     * Option to create symlinks instead of copying.
+     */
+    public void setSymlink(boolean symlink) {
+        _symlink = symlink;
+    }
 }

Modified: incubator/ivy/trunk/src/java/fr/jayasoft/ivy/util/FileUtil.java
URL: 
http://svn.apache.org/viewvc/incubator/ivy/trunk/src/java/fr/jayasoft/ivy/util/FileUtil.java?view=diff&rev=490200&r1=490199&r2=490200
==============================================================================
--- incubator/ivy/trunk/src/java/fr/jayasoft/ivy/util/FileUtil.java (original)
+++ incubator/ivy/trunk/src/java/fr/jayasoft/ivy/util/FileUtil.java Mon Dec 25 
15:47:55 2006
@@ -11,6 +11,9 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.io.StringWriter;
 import java.io.OutputStream;
 import java.net.URL;
 import java.util.ArrayList;
@@ -20,6 +23,7 @@
 
 import fr.jayasoft.ivy.url.URLHandlerRegistry;
 
+
 /**
  * @author x.hanin
  *
@@ -27,7 +31,53 @@
 public class FileUtil {
     // tried some other values with empty files... seems to be the best one 
(512 * 1024 is very bad)
     // 8 * 1024 is also the size used by ant in its FileUtils... maybe they've 
done more study about it ;-)
-    private static final int BUFFER_SIZE = 8 * 1024; 
+    private static final int BUFFER_SIZE = 8 * 1024;
+
+    public static void symlink(File src, File dest, CopyProgressListener l, 
boolean overwrite) throws IOException {
+        try {
+            if (dest.exists()) {
+               if (!dest.isFile()) {
+                    throw new IOException("impossible to copy: destination is 
not a file: "+dest);
+               }
+               if (!overwrite) {
+                    Message.verbose(dest+" already exists, nothing done");
+                    return;
+               }
+            }
+            if (dest.getParentFile() != null) {
+                dest.getParentFile().mkdirs();
+            }
+            
+            Runtime runtime = Runtime.getRuntime();
+            Process process = runtime.exec("ln", new String[] {"-s", "-f", 
src.getAbsolutePath(), dest.getPath()});
+            
+            if (process.waitFor() != 0) {
+                InputStream errorStream = process.getErrorStream();
+                InputStreamReader isr = new InputStreamReader(errorStream);
+                BufferedReader br = new BufferedReader(isr);
+
+                StringBuffer error = new StringBuffer();
+                String line;
+                while ((line = br.readLine()) != null) {
+                  error.append(line);
+                  error.append('\n');
+                }
+                
+                throw new IOException("error symlinking " + src + " to " + 
dest + ":\n" + error);
+            }
+        }
+        catch (IOException x) {
+            Message.verbose("symlink failed; falling back to copy");
+            StringWriter buffer = new StringWriter();
+            x.printStackTrace(new PrintWriter(buffer));
+            Message.debug(buffer.toString());
+            copy(src, dest, l, overwrite);
+        }
+        catch (InterruptedException x) {
+            Thread.currentThread().interrupt();
+        }
+    }
+  
     public static void copy(File src, File dest, CopyProgressListener l) 
throws IOException {
         copy(src, dest, l, false);
     }

Modified: incubator/ivy/trunk/test/java/fr/jayasoft/ivy/RetrieveTest.java
URL: 
http://svn.apache.org/viewvc/incubator/ivy/trunk/test/java/fr/jayasoft/ivy/RetrieveTest.java?view=diff&rev=490200&r1=490199&r2=490200
==============================================================================
--- incubator/ivy/trunk/test/java/fr/jayasoft/ivy/RetrieveTest.java (original)
+++ incubator/ivy/trunk/test/java/fr/jayasoft/ivy/RetrieveTest.java Mon Dec 25 
15:47:55 2006
@@ -6,10 +6,12 @@
 package fr.jayasoft.ivy;
 
 import java.io.File;
+import java.io.IOException;
 
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.taskdefs.Delete;
 
+import fr.jayasoft.ivy.filter.FilterHelper;
 import fr.jayasoft.ivy.report.ResolveReport;
 import fr.jayasoft.ivy.util.IvyPatternHelper;
 
@@ -63,6 +65,43 @@
         pattern = 
"build/test/retrieve/[module]/[conf]/[type]s/[artifact]-[revision].[ext]";
         _ivy.retrieve(md.getModuleRevisionId().getModuleId(), 
md.getConfigurationsNames(), _cache, pattern);
         assertTrue(new File(IvyPatternHelper.substitute(pattern, "org1", 
"mod1.2", "2.0", "mod1.2", "jar", "jar", "default")).exists());
+    }
+
+    public void testRetrieveWithSymlinks() throws Exception {
+        // mod1.1 depends on mod1.2
+        ResolveReport report = _ivy.resolve(new 
File("test/repositories/1/org1/mod1.1/ivys/ivy-1.0.xml").toURL(),
+                null, new String[] {"*"}, _cache, null, true);
+        assertNotNull(report);
+        ModuleDescriptor md = report.getModuleDescriptor();
+        assertNotNull(md);
+        
+        String pattern = 
"build/test/retrieve/[module]/[conf]/[artifact]-[revision].[ext]";
+        _ivy.retrieve(md.getModuleRevisionId().getModuleId(), 
md.getConfigurationsNames(), _cache, pattern, null, FilterHelper.NO_FILTER, 
false, false, true);
+        assertLink(IvyPatternHelper.substitute(pattern, "org1", "mod1.2", 
"2.0", "mod1.2", "jar", "jar", "default"));
+
+        pattern = 
"build/test/retrieve/[module]/[conf]/[type]s/[artifact]-[revision].[ext]";
+        _ivy.retrieve(md.getModuleRevisionId().getModuleId(), 
md.getConfigurationsNames(), _cache, pattern, null, FilterHelper.NO_FILTER, 
false, false, true);
+        assertLink(IvyPatternHelper.substitute(pattern, "org1", "mod1.2", 
"2.0", "mod1.2", "jar", "jar", "default"));
+    }
+
+    private void assertLink(String filename) throws IOException {
+       // if the OS is known to support symlink, check that the file is a 
symlink,
+       // otherwise just check the file exist.
+       
+       File file = new File(filename);
+       assertTrue("The file " + filename + " doesn't exist", file.exists());
+       
+        String os = System.getProperty("os.name");
+        if (os.equals("Linux") ||
+            os.equals("Solaris") ||
+            os.equals("FreeBSD")) {
+               // these OS should support symnlink, so check that the file is 
actually a symlink.
+               // this is done be checking that the canonical path is 
different from the absolute
+               // path.
+               File absFile = file.getAbsoluteFile();
+               File canFile = file.getCanonicalFile();
+               assertFalse("The file " + filename + " isn't a symlink", 
absFile.equals(canFile));
+        }
     }
 
     public void testRetrieveWithVariable() throws Exception {


Reply via email to