summaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit/src
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.jgit/src')
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java225
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java27
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX_Java5.java21
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX_Java6.java27
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/FS_Win32.java21
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/FS_Win32_Cygwin.java26
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java31
8 files changed, 347 insertions, 32 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
index bd211e7e91..29bec97ee7 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
@@ -242,6 +242,7 @@ public class JGitText extends TranslationBundle {
/***/ public String errorListing;
/***/ public String errorOccurredDuringUnpackingOnTheRemoteEnd;
/***/ public String errorReadingInfoRefs;
+ /***/ public String errorSymlinksNotSupported;
/***/ public String exceptionCaughtDuringExecutionOfAddCommand;
/***/ public String exceptionCaughtDuringExecutionOfCherryPickCommand;
/***/ public String exceptionCaughtDuringExecutionOfCommitCommand;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java
index ae6197838c..1b68801ae0 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java
@@ -53,11 +53,51 @@ import java.security.PrivilegedAction;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicBoolean;
+import org.eclipse.jgit.errors.SymlinksNotSupportedException;
+import org.eclipse.jgit.internal.JGitText;
+
/** Abstraction to support various file system operations not in Java. */
public abstract class FS {
+ /**
+ * This class creates FS instances. It will be overridden by a Java7 variant
+ * if such can be detected in {@link #detect(Boolean)}.
+ *
+ * @since 3.0
+ */
+ public static class FSFactory {
+ /**
+ * Constructor
+ */
+ protected FSFactory() {
+ // empty
+ }
+
+ /**
+ * Detect the file system
+ *
+ * @param cygwinUsed
+ * @return FS instance
+ */
+ public FS detect(Boolean cygwinUsed) {
+ if (SystemReader.getInstance().isWindows()) {
+ if (cygwinUsed == null)
+ cygwinUsed = Boolean.valueOf(FS_Win32_Cygwin.isCygwin());
+ if (cygwinUsed.booleanValue())
+ return new FS_Win32_Cygwin();
+ else
+ return new FS_Win32();
+ } else if (FS_POSIX_Java6.hasExecute())
+ return new FS_POSIX_Java6();
+ else
+ return new FS_POSIX_Java5();
+ }
+ }
+
/** The auto-detected implementation selected for this operating system and JRE. */
public static final FS DETECTED = detect();
+ private static FSFactory factory;
+
/**
* Auto-detect the appropriate file system abstraction.
*
@@ -89,17 +129,25 @@ public abstract class FS {
* @return detected file system abstraction
*/
public static FS detect(Boolean cygwinUsed) {
- if (SystemReader.getInstance().isWindows()) {
- if (cygwinUsed == null)
- cygwinUsed = Boolean.valueOf(FS_Win32_Cygwin.isCygwin());
- if (cygwinUsed.booleanValue())
- return new FS_Win32_Cygwin();
- else
- return new FS_Win32();
- } else if (FS_POSIX_Java6.hasExecute())
- return new FS_POSIX_Java6();
- else
- return new FS_POSIX_Java5();
+ if (factory == null) {
+ try {
+ Class<?> activatorClass = Class
+ .forName("org.eclipse.jgit.util.Java7FSFactory"); //$NON-NLS-1$
+ // found Java7
+ factory = (FSFactory) activatorClass.newInstance();
+ } catch (ClassNotFoundException e) {
+ // Java7 module not found
+ factory = new FS.FSFactory();
+ // Silently ignore failure to find Java7 FS factory
+ } catch (UnsupportedClassVersionError e) {
+ // Java7 module not accessible
+ factory = new FS.FSFactory();
+ } catch (Exception e) {
+ factory = new FS.FSFactory();
+ throw new Error(e);
+ }
+ }
+ return factory.detect(cygwinUsed);
}
private volatile Holder<File> userHome;
@@ -136,6 +184,17 @@ public abstract class FS {
public abstract boolean supportsExecute();
/**
+ * Does this operating system and JRE supports symbolic links. The
+ * capability to handle symbolic links is detected at runtime.
+ *
+ * @return true if symbolic links may be used
+ * @since 3.0
+ */
+ public boolean supportsSymlinks() {
+ return false;
+ }
+
+ /**
* Is this file system case sensitive
*
* @return true if this implementation is case sensitive
@@ -147,6 +206,10 @@ public abstract class FS {
* <p>
* Not all platforms and JREs support executable flags on files. If the
* feature is unsupported this method will always return false.
+ * <p>
+ * <em>If the platform supports symbolic links and <code>f</code> is a symbolic link
+ * this method returns false, rather than the state of the executable flags
+ * on the target file.</em>
*
* @param f
* abstract path to test.
@@ -170,6 +233,46 @@ public abstract class FS {
public abstract boolean setExecute(File f, boolean canExec);
/**
+ * Get the last modified time of a file system object. If the OS/JRE support
+ * symbolic links, the modification time of the link is returned, rather
+ * than that of the link target.
+ *
+ * @param f
+ * @return last modified time of f
+ * @throws IOException
+ * @since 3.0
+ */
+ public long lastModified(File f) throws IOException {
+ return f.lastModified();
+ }
+
+ /**
+ * Set the last modified time of a file system object. If the OS/JRE support
+ * symbolic links, the link is modified, not the target,
+ *
+ * @param f
+ * @param time
+ * @throws IOException
+ * @since 3.0
+ */
+ public void setLastModified(File f, long time) throws IOException {
+ f.setLastModified(time);
+ }
+
+ /**
+ * Get the length of a file or link, If the OS/JRE supports symbolic links
+ * it's the length of the link, else the length of the target.
+ *
+ * @param path
+ * @return length of a file
+ * @throws IOException
+ * @since 3.0
+ */
+ public long length(File path) throws IOException {
+ return path.length();
+ }
+
+ /**
* Resolve this file to its actual path name that the JRE can use.
* <p>
* This method can be relatively expensive. Computing a translation may
@@ -260,8 +363,9 @@ public abstract class FS {
* @param lookFor
* Files to search for in the given path
* @return the first match found, or null
+ * @since 3.0
**/
- static File searchPath(final String path, final String... lookFor) {
+ protected static File searchPath(final String path, final String... lookFor) {
if (path == null)
return null;
@@ -398,6 +502,103 @@ public abstract class FS {
}
/**
+ * Check if a file is a symbolic link and read it
+ *
+ * @param path
+ * @return target of link or null
+ * @throws IOException
+ * @since 3.0
+ */
+ public String readSymLink(File path) throws IOException {
+ throw new SymlinksNotSupportedException(
+ JGitText.get().errorSymlinksNotSupported);
+ }
+
+ /**
+ * @param path
+ * @return true if the path is a symbolic link (and we support these)
+ * @throws IOException
+ * @since 3.0
+ */
+ public boolean isSymLink(File path) throws IOException {
+ return false;
+ }
+
+ /**
+ * Tests if the path exists, in case of a symbolic link, true even if the
+ * target does not exist
+ *
+ * @param path
+ * @return true if path exists
+ * @since 3.0
+ */
+ public boolean exists(File path) {
+ return path.exists();
+ }
+
+ /**
+ * Check if path is a directory. If the OS/JRE supports symbolic links and
+ * path is a symbolic link to a directory, this method returns false.
+ *
+ * @param path
+ * @return true if file is a directory,
+ * @since 3.0
+ */
+ public boolean isDirectory(File path) {
+ return path.isDirectory();
+ }
+
+ /**
+ * Examine if path represents a regular file. If the OS/JRE supports
+ * symbolic links the test returns false if path represents a symbolic link.
+ *
+ * @param path
+ * @return true if path represents a regular file
+ * @since 3.0
+ */
+ public boolean isFile(File path) {
+ return path.isFile();
+ }
+
+ /**
+ * @param path
+ * @return true if path is hidden, either starts with . on unix or has the
+ * hidden attribute in windows
+ * @throws IOException
+ * @since 3.0
+ */
+ public boolean isHidden(File path) throws IOException {
+ return path.isHidden();
+ }
+
+ /**
+ * Set the hidden attribute for file whose name starts with a period.
+ *
+ * @param path
+ * @param hidden
+ * @throws IOException
+ * @since 3.0
+ */
+ public void setHidden(File path, boolean hidden) throws IOException {
+ if (!path.getName().startsWith(".")) //$NON-NLS-1$
+ throw new IllegalArgumentException(
+ "Hiding only allowed for names that start with a period");
+ }
+
+ /**
+ * Create a symbolic link
+ *
+ * @param path
+ * @param target
+ * @throws IOException
+ * @since 3.0
+ */
+ public void createSymLink(File path, String target) throws IOException {
+ throw new SymlinksNotSupportedException(
+ JGitText.get().errorSymlinksNotSupported);
+ }
+
+ /**
* Initialize a ProcesssBuilder to run a command using the system shell.
*
* @param cmd
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java
index b6b5595902..b7de056ee4 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java
@@ -43,12 +43,19 @@
package org.eclipse.jgit.util;
import java.io.File;
+import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-abstract class FS_POSIX extends FS {
+
+/**
+ * Base FS for POSIX based systems
+ *
+ * @since 3.0
+ */
+public abstract class FS_POSIX extends FS {
@Override
protected File discoverGitPrefix() {
String path = SystemReader.getInstance().getenv("PATH"); //$NON-NLS-1$
@@ -75,11 +82,20 @@ abstract class FS_POSIX extends FS {
return null;
}
- FS_POSIX() {
+ /**
+ * Default constructor
+ */
+ protected FS_POSIX() {
super();
}
- FS_POSIX(FS src) {
+ /**
+ * Constructor
+ *
+ * @param src
+ * FS to copy some settings from
+ */
+ protected FS_POSIX(FS src) {
super(src);
}
@@ -89,6 +105,11 @@ abstract class FS_POSIX extends FS {
}
@Override
+ public void setHidden(File path, boolean hidden) throws IOException {
+ // Do nothing
+ }
+
+ @Override
public ProcessBuilder runInShell(String cmd, String[] args) {
List<String> argv = new ArrayList<String>(4 + args.length);
argv.add("sh"); //$NON-NLS-1$
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX_Java5.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX_Java5.java
index c79bbe69bd..46ea2aa3fe 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX_Java5.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX_Java5.java
@@ -45,12 +45,27 @@ package org.eclipse.jgit.util;
import java.io.File;
-class FS_POSIX_Java5 extends FS_POSIX {
- FS_POSIX_Java5() {
+
+/**
+ * FS implementaton for Java5
+ *
+ * @since 3.0
+ */
+public class FS_POSIX_Java5 extends FS_POSIX {
+ /**
+ * Constructor
+ */
+ public FS_POSIX_Java5() {
super();
}
- FS_POSIX_Java5(FS src) {
+ /**
+ * Constructor
+ *
+ * @param src
+ * instance whose attributes to copy
+ */
+ public FS_POSIX_Java5(FS src) {
super(src);
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX_Java6.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX_Java6.java
index 05025479b5..47a7a68e4d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX_Java6.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX_Java6.java
@@ -49,7 +49,13 @@ import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
-class FS_POSIX_Java6 extends FS_POSIX {
+
+/**
+ * FS implementation for POSIX systems using Java6
+ *
+ * @since 3.0
+ */
+public class FS_POSIX_Java6 extends FS_POSIX {
private static final Method canExecute;
private static final Method setExecute;
@@ -59,7 +65,11 @@ class FS_POSIX_Java6 extends FS_POSIX {
setExecute = needMethod(File.class, "setExecutable", Boolean.TYPE); //$NON-NLS-1$
}
- static boolean hasExecute() {
+ /**
+ * @return true if Java has the ability to set and get the executable flag
+ * on files
+ */
+ public static boolean hasExecute() {
return canExecute != null && setExecute != null;
}
@@ -74,11 +84,20 @@ class FS_POSIX_Java6 extends FS_POSIX {
}
}
- FS_POSIX_Java6() {
+ /**
+ * Constructor
+ */
+ public FS_POSIX_Java6() {
super();
}
- FS_POSIX_Java6(FS src) {
+ /**
+ * Constructor
+ *
+ * @param src
+ * instance whose attributes to copy
+ */
+ public FS_POSIX_Java6(FS src) {
super(src);
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_Win32.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_Win32.java
index 73f9161ca3..5822dcfae1 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_Win32.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_Win32.java
@@ -50,12 +50,27 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-class FS_Win32 extends FS {
- FS_Win32() {
+
+/**
+ * FS implementation for Windows
+ *
+ * @since 3.0
+ */
+public class FS_Win32 extends FS {
+ /**
+ * Constructor
+ */
+ public FS_Win32() {
super();
}
- FS_Win32(FS src) {
+ /**
+ * Constructor
+ *
+ * @param src
+ * instance whose attributes to copy
+ */
+ protected FS_Win32(FS src) {
super(src);
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_Win32_Cygwin.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_Win32_Cygwin.java
index af2d5a9a72..81f2001125 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_Win32_Cygwin.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_Win32_Cygwin.java
@@ -50,10 +50,19 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-class FS_Win32_Cygwin extends FS_Win32 {
+
+/**
+ * FS implementation for Cygwin on Windows
+ *
+ * @since 3.0
+ */
+public class FS_Win32_Cygwin extends FS_Win32 {
private static String cygpath;
- static boolean isCygwin() {
+ /**
+ * @return true if cygwin is found
+ */
+ public static boolean isCygwin() {
final String path = AccessController
.doPrivileged(new PrivilegedAction<String>() {
public String run() {
@@ -68,11 +77,20 @@ class FS_Win32_Cygwin extends FS_Win32 {
return cygpath != null;
}
- FS_Win32_Cygwin() {
+ /**
+ * Constructor
+ */
+ public FS_Win32_Cygwin() {
super();
}
- FS_Win32_Cygwin(FS src) {
+ /**
+ * Constructor
+ *
+ * @param src
+ * instance whose attributes to copy
+ */
+ protected FS_Win32_Cygwin(FS src) {
super(src);
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java
index c4fdd6fff9..834cc85f49 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java
@@ -126,10 +126,11 @@ public class FileUtils {
* exception is not thrown when IGNORE_ERRORS is set.
*/
public static void delete(final File f, int options) throws IOException {
- if ((options & SKIP_MISSING) != 0 && !f.exists())
+ FS fs = FS.DETECTED;
+ if ((options & SKIP_MISSING) != 0 && !fs.exists(f))
return;
- if ((options & RECURSIVE) != 0 && f.isDirectory()) {
+ if ((options & RECURSIVE) != 0 && fs.isDirectory(f)) {
final File[] items = f.listFiles();
if (items != null) {
List<File> files = new ArrayList<File>();
@@ -164,7 +165,7 @@ public class FileUtils {
}
if (delete && !f.delete()) {
- if ((options & RETRY) != 0 && f.exists()) {
+ if ((options & RETRY) != 0 && fs.exists(f)) {
for (int i = 1; i < 10; i++) {
try {
Thread.sleep(100);
@@ -337,4 +338,28 @@ public class FileUtils {
throw new IOException(MessageFormat.format(
JGitText.get().createNewFileFailed, f));
}
+
+ /**
+ * Create a symbolic link
+ *
+ * @param path
+ * @param target
+ * @throws IOException
+ * @since 3.0
+ */
+ public static void createSymLink(File path, String target)
+ throws IOException {
+ FS.DETECTED.createSymLink(path, target);
+ }
+
+ /**
+ * @param path
+ * @return the target of the symbolic link, or null if it is not a symbolic
+ * link
+ * @throws IOException
+ * @since 3.0
+ */
+ public static String readSymLink(File path) throws IOException {
+ return FS.DETECTED.readSymLink(path);
+ }
}