Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[egit-dev] [JGit-RFC-PATCH 3/3] Incorporate current FileSystem Util implementations to the SPI

From: Imran M Yousuf <imyousuf@xxxxxxxxxxxxxxxxxxxxxx>

Operations such as setting executable bits if supported and resolving
relative path is incorporated with this change, as a result now it should
be possible to completely replace the currently being used util FS and
java.io.File.

Signed-off-by: Imran M Yousuf <imyousuf@xxxxxxxxxxxxxxxxxxxxxx>
---
 .../src/org/eclipse/jgit/io/Entry.java             |   35 ++++-
 .../src/org/eclipse/jgit/io/StorageSystem.java     |   17 ++-
 .../eclipse/jgit/io/localfs/LocalFileEntry.java    |   52 ++++++-
 .../eclipse/jgit/io/localfs/LocalFileSystem.java   |  162 +++++++++++++++++++-
 4 files changed, 259 insertions(+), 7 deletions(-)

diff --git a/org.eclipse.jgit.io/src/org/eclipse/jgit/io/Entry.java b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/Entry.java
index b8c3236..67d2af5 100644
--- a/org.eclipse.jgit.io/src/org/eclipse/jgit/io/Entry.java
+++ b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/Entry.java
@@ -78,6 +78,24 @@
     public boolean isExists();
 
     /**
+     * Does this operating system and JRE support the execute flag on entries?
+     *
+     * @return true if this implementation can provide reasonably accurate
+     *         executable bit information; false otherwise.
+     */
+    public boolean isExecutableSupported();
+
+    /**
+     * Determine if the entry is executable (or not).
+     * <p>
+     * Not all platforms and JREs support executable flags on entries. If the
+     * feature is unsupported this method will always return false.
+     *
+     * @return true if the entry is believed to be executable by the user.
+     */
+    public boolean isExecutable();
+
+    /**
      * Make directories upto the entry represented by this instance, provided
      * that this instance itself is a directory.
      * @return True if directories were created.
@@ -85,6 +103,19 @@
     public boolean mkdirs();
 
     /**
+     * Set an entry to be executable by the user.
+     * <p>
+     * Not all platforms and JREs support executable flags on entries. If the
+     * feature is unsupported this method will always return false and no
+     * changes will be made to the entry specified.
+     *
+     * @param executable
+     *            true to enable execution; false to disable it.
+     * @return true if the change succeeded; false otherwise.
+     */
+    public boolean setExecutable(boolean executable);
+
+    /**
      * Retrieves the URI of this entry. URI in this case acts as a primary key
      * to identify an entry.
      * @return URI to identify this entry instance
@@ -101,7 +132,7 @@
     /**
      * Retrieves the InputStream for reading the content of the entry
      * @return Input stream to read entry content
-     * @throws IOException If no such file exists or there is any other error
+     * @throws IOException If no such entry exists or there is any other error
      */
     public InputStream getInputStream()
             throws IOException;
@@ -111,7 +142,7 @@ public InputStream getInputStream()
      * opened to either overwrite it or append to it.
      * @param overwrite False if to write in append mode else true
      * @return Output stream to write content to
-     * @throws IOException If no such file exists in append mode or there is any
+     * @throws IOException If no such entry exists in append mode or there is any
      *                     error in retrieving it.
      */
     public OutputStream getOutputStream(boolean overwrite)
diff --git a/org.eclipse.jgit.io/src/org/eclipse/jgit/io/StorageSystem.java b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/StorageSystem.java
index d3e60ab..46c663b 100644
--- a/org.eclipse.jgit.io/src/org/eclipse/jgit/io/StorageSystem.java
+++ b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/StorageSystem.java
@@ -65,5 +65,20 @@
      * @return Entry for current working directory.
      */
     public Entry getWorkingDirectory();
-    
+
+    /**
+     * Retrieve the home directory of the current user
+     * @return Home directory
+     */
+    public Entry getHomeDirectory();
+
+    /**
+     * Resolve relative path with respect to a path and return the absolute
+     * entry representing the relative path.
+     * @param entry The point of reference for the relative path
+     * @param path The relative path
+     * @return The absolute entry representing the relative path entry
+     */
+    public Entry resolve(Entry entry,
+                         String path);
 }
diff --git a/org.eclipse.jgit.io/src/org/eclipse/jgit/io/localfs/LocalFileEntry.java b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/localfs/LocalFileEntry.java
index 20a64cb..3d5fab4 100644
--- a/org.eclipse.jgit.io/src/org/eclipse/jgit/io/localfs/LocalFileEntry.java
+++ b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/localfs/LocalFileEntry.java
@@ -43,6 +43,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.lang.reflect.InvocationTargetException;
 import java.net.URI;
 import org.eclipse.jgit.io.Entry;
 import org.eclipse.jgit.io.StorageSystem;
@@ -60,7 +61,7 @@
         implements Entry {
 
     private File localFile;
-    private StorageSystem storageSystem;
+    private LocalFileSystem storageSystem;
 
     /**
      * Contructs an entry based of on the local file system storage and a file
@@ -70,7 +71,7 @@
      * @throws IllegalArgumentException If either argument is NULL
      */
     protected LocalFileEntry(File localFile,
-                             StorageSystem storageSystem)
+                             LocalFileSystem storageSystem)
             throws IllegalArgumentException {
         setLocalFile(localFile);
         setStorageSystem(storageSystem);
@@ -81,7 +82,7 @@ protected LocalFileEntry(File localFile,
      * @param storageSystem Storage system
      * @throws IllegalArgumentException IF storageSystem is null
      */
-    protected void setStorageSystem(StorageSystem storageSystem)
+    protected void setStorageSystem(LocalFileSystem storageSystem)
             throws IllegalArgumentException {
         if (storageSystem == null) {
             throw new IllegalArgumentException("Storage system can't be NULL!");
@@ -216,4 +217,49 @@ public StorageSystem getStorageSystem() {
     public long length() {
         return getLocalFile().length();
     }
+
+    public boolean isExecutableSupported() {
+        return LocalFileSystem.platform.isExecutableSupproted();
+    }
+
+    public boolean isExecutable() {
+        if (LocalFileSystem.platform.isExecutableSupproted()) {
+            try {
+                final Object r = LocalFileSystem.canExecute.invoke(
+                        getLocalFile(),
+                        (Object[]) null);
+                return ((Boolean) r).booleanValue();
+            }
+            catch (IllegalArgumentException e) {
+                throw new Error(e);
+            }
+            catch (IllegalAccessException e) {
+                throw new Error(e);
+            }
+            catch (InvocationTargetException e) {
+                throw new Error(e);
+            }
+        }
+        else {
+            return false;
+        }
+    }
+
+    public boolean setExecutable(boolean executable) {
+        try {
+            final Object r;
+            r = LocalFileSystem.setExecute.invoke(getLocalFile(), new Object[] {
+                        Boolean.valueOf(executable)});
+            return ((Boolean) r).booleanValue();
+        }
+        catch (IllegalArgumentException e) {
+            throw new Error(e);
+        }
+        catch (IllegalAccessException e) {
+            throw new Error(e);
+        }
+        catch (InvocationTargetException e) {
+            throw new Error(e);
+        }
+    }
 }
diff --git a/org.eclipse.jgit.io/src/org/eclipse/jgit/io/localfs/LocalFileSystem.java b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/localfs/LocalFileSystem.java
index cf289ec..f18dbde 100644
--- a/org.eclipse.jgit.io/src/org/eclipse/jgit/io/localfs/LocalFileSystem.java
+++ b/org.eclipse.jgit.io/src/org/eclipse/jgit/io/localfs/LocalFileSystem.java
@@ -36,8 +36,14 @@
  */
 package org.eclipse.jgit.io.localfs;
 
+import java.io.BufferedReader;
 import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.lang.reflect.Method;
 import java.net.URI;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import org.eclipse.jgit.io.Entry;
 import org.eclipse.jgit.io.StorageSystem;
 
@@ -48,14 +54,23 @@
  */
 public class LocalFileSystem
         implements StorageSystem {
+
     public static final String PROTOCOL_FILE = "file";
+    public static final Platform platform;
+    public static Method canExecute;
+    public static Method setExecute;
+    public static String cygpath;
+
+    static {
+        platform = Platform.detect();
+    }
 
     public String getURIScheme() {
         return PROTOCOL_FILE;
     }
 
     public Entry getEntry(URI uri) {
-        if(uri == null) {
+        if (uri == null) {
             return null;
         }
         else {
@@ -67,4 +82,149 @@ public Entry getWorkingDirectory() {
         String curDir = System.getProperty("user.dir");
         return new LocalFileEntry(new File(curDir), this);
     }
+
+    public Entry resolve(Entry entry,
+                         String path) {
+        if (!(entry instanceof LocalFileEntry)) {
+            return null;
+        }
+        LocalFileEntry fileEntry = (LocalFileEntry) entry;
+        File localFile = fileEntry.getLocalFile();
+        if (platform.equals(Platform.WIN32_CYGWIN)) {
+            try {
+                final Process p;
+
+                p = Runtime.getRuntime().exec(
+                        new String[] {cygpath, "--windows", "--absolute", path},
+                        null, localFile);
+                p.getOutputStream().close();
+
+                final BufferedReader lineRead = new BufferedReader(
+                        new InputStreamReader(p.getInputStream(), "UTF-8"));
+                String r = null;
+                try {
+                    r = lineRead.readLine();
+                }
+                finally {
+                    lineRead.close();
+                }
+
+                for (;;) {
+                    try {
+                        if (p.waitFor() == 0 && r != null && r.length() > 0) {
+                            return new LocalFileEntry(new File(r), this);
+                        }
+                        break;
+                    }
+                    catch (InterruptedException ie) {
+                        // Stop bothering me, I have a zombie to reap.
+                    }
+                }
+            }
+            catch (IOException ioe) {
+                // Fall through and use the default return.
+            }
+
+        }
+        final File abspn = new File(path);
+        if (abspn.isAbsolute()) {
+            return new LocalFileEntry(abspn, this);
+        }
+        return new LocalFileEntry(new File(localFile, path), this);
+    }
+
+    public Entry getHomeDirectory() {
+        if (platform.equals(Platform.WIN32_CYGWIN)) {
+            final String home = AccessController.doPrivileged(new PrivilegedAction<String>() {
+
+                public String run() {
+                    return System.getenv("HOME");
+                }
+            });
+            if (!(home == null || home.length() == 0)) {
+                return resolve(new LocalFileEntry(new File("."), this), home);
+            }
+        }
+        final String home = AccessController.doPrivileged(new PrivilegedAction<String>() {
+
+            public String run() {
+                return System.getProperty("user.home");
+            }
+        });
+        if (home == null || home.length() == 0) {
+            return null;
+        }
+        return new LocalFileEntry(new File(home).getAbsoluteFile(), this);
+    }
+
+    public enum Platform {
+
+        WIN32_CYGWIN(false),
+        WIN32(false),
+        POSIX_JAVA5(false),
+        POSIX_JAVA6(true);
+        private boolean executableSupproted;
+
+        private Platform(boolean executableSupproted) {
+            this.executableSupproted = executableSupproted;
+        }
+
+        public boolean isExecutableSupproted() {
+            return executableSupproted;
+        }
+
+        public static Platform detect() {
+            final String osDotName = AccessController.doPrivileged(new PrivilegedAction<String>() {
+
+                public String run() {
+                    return System.getProperty("os.name");
+                }
+            });
+            if (osDotName != null &&
+                osDotName.toLowerCase().indexOf("windows") != -1) {
+                final String path = AccessController.doPrivileged(new PrivilegedAction<String>() {
+
+                    public String run() {
+                        return System.getProperty("java.library.path");
+                    }
+                });
+                if (path == null) {
+                    return WIN32;
+                }
+                for (final String p : path.split(";")) {
+                    final File e = new File(p, "cygpath.exe");
+                    if (e.isFile()) {
+                        cygpath = e.getAbsolutePath();
+                        return WIN32_CYGWIN;
+                    }
+                }
+                return WIN32;
+            }
+            else {
+                canExecute = needMethod(File.class, "canExecute");
+                setExecute = needMethod(File.class, "setExecutable",
+                        Boolean.TYPE);
+                if (canExecute != null && setExecute != null) {
+                    return POSIX_JAVA6;
+                }
+                else {
+                    return POSIX_JAVA5;
+                }
+            }
+        }
+
+        private static Method needMethod(final Class<?> on,
+                                         final String name,
+                                         final Class<?>... args) {
+            try {
+                return on.getMethod(name, args);
+            }
+            catch (SecurityException e) {
+                return null;
+            }
+            catch (NoSuchMethodException e) {
+                return null;
+            }
+        }
+    }
 }
-- 
1.6.2.1



Back to the top