objects
directory.
* @param alternateObjectDir
* a list of alternate object directories
+ * @param fs
+ * the file system abstraction which will be necessary to
+ * perform certain file system operations.
*/
- public ObjectDirectory(final File dir, File[] alternateObjectDir) {
+ public ObjectDirectory(final File dir, File[] alternateObjectDir, FS fs) {
objects = dir;
this.alternateObjectDir = alternateObjectDir;
infoDirectory = new File(objects, "info");
packDirectory = new File(objects, "pack");
alternatesFile = new File(infoDirectory, "alternates");
packList = new AtomicReferencegit://
transport protocol. */
public class Daemon {
@@ -368,7 +369,7 @@ Repository openRepository(String name) {
}
for (final File baseDir : exportBase) {
- final File gitdir = FileKey.resolve(new File(baseDir, name));
+ final File gitdir = FileKey.resolve(new File(baseDir, name), FS.DETECTED);
if (gitdir != null && canExport(gitdir))
return openRepository(gitdir);
}
@@ -377,7 +378,7 @@ Repository openRepository(String name) {
private static Repository openRepository(final File gitdir) {
try {
- return RepositoryCache.open(FileKey.exact(gitdir));
+ return RepositoryCache.open(FileKey.exact(gitdir, FS.DETECTED));
} catch (IOException err) {
// null signals it "wasn't found", which is all that is suitable
// for the remote client to know.
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/OpenSshConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/OpenSshConfig.java
index e7a307f80..20f3174b2 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/OpenSshConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/OpenSshConfig.java
@@ -82,10 +82,13 @@ public class OpenSshConfig {
* requests are cached and are automatically updated if the user modifies
* the configuration file since the last time it was cached.
*
+ * @param fs
+ * the file system abstraction which will be necessary to
+ * perform certain file system operations.
* @return a caching reader of the user's configuration file.
*/
- public static OpenSshConfig get() {
- File home = FS.userHome();
+ public static OpenSshConfig get(FS fs) {
+ File home = fs.userHome();
if (home == null)
home = new File(".").getAbsoluteFile();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/SshConfigSessionFactory.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/SshConfigSessionFactory.java
index c30d32d9f..daa6f4ca2 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/SshConfigSessionFactory.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/SshConfigSessionFactory.java
@@ -83,15 +83,18 @@ public abstract class SshConfigSessionFactory extends SshSessionFactory {
@Override
public synchronized Session getSession(String user, String pass,
- String host, int port) throws JSchException {
- final OpenSshConfig.Host hc = getConfig().lookup(host);
+ String host, int port, FS fs) throws JSchException {
+ if (config == null)
+ config = OpenSshConfig.get(fs);
+
+ final OpenSshConfig.Host hc = config.lookup(host);
host = hc.getHostName();
if (port <= 0)
port = hc.getPort();
if (user == null)
user = hc.getUser();
- final Session session = createSession(hc, user, host, port);
+ final Session session = createSession(hc, user, host, port, fs);
if (pass != null)
session.setPassword(pass);
final String strictHostKeyCheckingPolicy = hc
@@ -117,14 +120,17 @@ public synchronized Session getSession(String user, String pass,
* server name to connect to.
* @param port
* port number of the SSH daemon (typically 22).
+ * @param fs
+ * the file system abstraction which will be necessary to
+ * perform certain file system operations.
* @return new session instance, but otherwise unconfigured.
* @throws JSchException
* the session could not be created.
*/
protected Session createSession(final OpenSshConfig.Host hc,
- final String user, final String host, final int port)
+ final String user, final String host, final int port, FS fs)
throws JSchException {
- return getJSch(hc).getSession(user, host, port);
+ return getJSch(hc, fs).getSession(user, host, port);
}
/**
@@ -143,58 +149,54 @@ protected Session createSession(final OpenSshConfig.Host hc,
*
* @param hc
* host configuration
+ * @param fs
+ * the file system abstraction which will be necessary to
+ * perform certain file system operations.
* @return the JSch instance to use.
* @throws JSchException
* the user configuration could not be created.
*/
- protected JSch getJSch(final OpenSshConfig.Host hc) throws JSchException {
- final JSch def = getDefaultJSch();
+ protected JSch getJSch(final OpenSshConfig.Host hc, FS fs) throws JSchException {
+ if (defaultJSch == null) {
+ defaultJSch = createDefaultJSch(fs);
+ for (Object name : defaultJSch.getIdentityNames()) {
+ byIdentityFile.put((String) name, defaultJSch);
+ }
+ }
+
final File identityFile = hc.getIdentityFile();
if (identityFile == null) {
- return def;
+ return defaultJSch;
}
final String identityKey = identityFile.getAbsolutePath();
JSch jsch = byIdentityFile.get(identityKey);
if (jsch == null) {
jsch = new JSch();
- jsch.setHostKeyRepository(def.getHostKeyRepository());
+ jsch.setHostKeyRepository(defaultJSch.getHostKeyRepository());
jsch.addIdentity(identityKey);
byIdentityFile.put(identityKey, jsch);
}
return jsch;
}
- private JSch getDefaultJSch() throws JSchException {
- if (defaultJSch == null) {
- defaultJSch = createDefaultJSch();
- for (Object name : defaultJSch.getIdentityNames()) {
- byIdentityFile.put((String) name, defaultJSch);
- }
- }
- return defaultJSch;
- }
-
/**
+ * @param fs
+ * the file system abstraction which will be necessary to
+ * perform certain file system operations.
* @return the new default JSch implementation.
* @throws JSchException
* known host keys cannot be loaded.
*/
- protected JSch createDefaultJSch() throws JSchException {
+ protected JSch createDefaultJSch(FS fs) throws JSchException {
final JSch jsch = new JSch();
- knownHosts(jsch);
- identities(jsch);
+ knownHosts(jsch, fs);
+ identities(jsch, fs);
return jsch;
}
- private OpenSshConfig getConfig() {
- if (config == null)
- config = OpenSshConfig.get();
- return config;
- }
-
- private static void knownHosts(final JSch sch) throws JSchException {
- final File home = FS.userHome();
+ private static void knownHosts(final JSch sch, FS fs) throws JSchException {
+ final File home = fs.userHome();
if (home == null)
return;
final File known_hosts = new File(new File(home, ".ssh"), "known_hosts");
@@ -212,8 +214,8 @@ private static void knownHosts(final JSch sch) throws JSchException {
}
}
- private static void identities(final JSch sch) {
- final File home = FS.userHome();
+ private static void identities(final JSch sch, FS fs) {
+ final File home = fs.userHome();
if (home == null)
return;
final File sshdir = new File(home, ".ssh");
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/SshSessionFactory.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/SshSessionFactory.java
index 810b04ce4..d10010fcf 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/SshSessionFactory.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/SshSessionFactory.java
@@ -44,6 +44,8 @@
package org.eclipse.jgit.transport;
+import org.eclipse.jgit.util.FS;
+
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
@@ -109,19 +111,22 @@ public static void setInstance(final SshSessionFactory newFactory) {
* @param port
* port number the server is listening for connections on. May be <=
* 0 to indicate the IANA registered port of 22 should be used.
+ * @param fs
+ * the file system abstraction which will be necessary to
+ * perform certain file system operations.
* @return a session that can contact the remote host.
* @throws JSchException
* the session could not be created.
*/
public abstract Session getSession(String user, String pass, String host,
- int port) throws JSchException;
+ int port, FS fs) throws JSchException;
/**
* Close (or recycle) a session to a host.
*
* @param session
* a session previously obtained from this factory's
- * {@link #getSession(String,String, String, int)} method.s
+ * {@link #getSession(String,String, String, int, FS)} method.s
*/
public void releaseSession(final Session session) {
if (session.isConnected())
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/SshTransport.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/SshTransport.java
index d25a7b618..f642ac1ea 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/SshTransport.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/SshTransport.java
@@ -128,7 +128,7 @@ protected void initSession() throws TransportException {
final String host = uri.getHost();
final int port = uri.getPort();
try {
- sock = sch.getSession(user, pass, host, port);
+ sock = sch.getSession(user, pass, host, port, local.getFS());
if (!sock.isConnected())
sock.connect(tms);
} catch (JSchException je) {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/Transport.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/Transport.java
index 2fe3cb932..e1988a6c8 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/Transport.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/Transport.java
@@ -66,6 +66,7 @@
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.TransferConfig;
+import org.eclipse.jgit.util.FS;
/**
* Connects two Git repositories together and copies objects between them.
@@ -323,9 +324,11 @@ private static boolean doesNotExist(final RemoteConfig cfg) {
*
* @param remote
* location of the remote repository.
+ * @param fs
+ * type of filesystem the local repository is stored on.
* @return true if the protocol is supported.
*/
- public static boolean canHandleProtocol(final URIish remote) {
+ public static boolean canHandleProtocol(final URIish remote, final FS fs) {
if (TransportGitSsh.canHandle(remote))
return true;
@@ -341,10 +344,10 @@ else if (TransportGitAnon.canHandle(remote))
else if (TransportAmazonS3.canHandle(remote))
return true;
- else if (TransportBundleFile.canHandle(remote))
+ else if (TransportBundleFile.canHandle(remote, fs))
return true;
- else if (TransportLocal.canHandle(remote))
+ else if (TransportLocal.canHandle(remote, fs))
return true;
return false;
@@ -378,10 +381,10 @@ else if (TransportGitAnon.canHandle(remote))
else if (TransportAmazonS3.canHandle(remote))
return new TransportAmazonS3(local, remote);
- else if (TransportBundleFile.canHandle(remote))
+ else if (TransportBundleFile.canHandle(remote, local.getFS()))
return new TransportBundleFile(local, remote);
- else if (TransportLocal.canHandle(remote))
+ else if (TransportLocal.canHandle(remote, local.getFS()))
return new TransportLocal(local, remote);
throw new NotSupportedException(MessageFormat.format(JGitText.get().URINotSupported, remote));
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportAmazonS3.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportAmazonS3.java
index bcf6e873f..56a5c9796 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportAmazonS3.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportAmazonS3.java
@@ -69,7 +69,6 @@
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.SymbolicRef;
import org.eclipse.jgit.lib.Ref.Storage;
-import org.eclipse.jgit.util.FS;
/**
* Transport over the non-Git aware Amazon S3 protocol.
@@ -130,7 +129,7 @@ static boolean canHandle(final URIish uri) {
Properties props = null;
File propsFile = new File(local.getDirectory(), uri.getUser());
if (!propsFile.isFile())
- propsFile = new File(FS.userHome(), uri.getUser());
+ propsFile = new File(local.getFS().userHome(), uri.getUser());
if (propsFile.isFile()) {
try {
props = AmazonS3.properties(propsFile);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportBundleFile.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportBundleFile.java
index 0245818fe..c47833f21 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportBundleFile.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportBundleFile.java
@@ -58,13 +58,13 @@
import org.eclipse.jgit.util.FS;
class TransportBundleFile extends Transport implements TransportBundle {
- static boolean canHandle(final URIish uri) {
+ static boolean canHandle(final URIish uri, FS fs) {
if (uri.getHost() != null || uri.getPort() > 0 || uri.getUser() != null
|| uri.getPass() != null || uri.getPath() == null)
return false;
if ("file".equals(uri.getScheme()) || uri.getScheme() == null) {
- final File f = FS.resolve(new File("."), uri.getPath());
+ final File f = fs.resolve(new File("."), uri.getPath());
return f.isFile() || f.getName().endsWith(".bundle");
}
@@ -75,7 +75,7 @@ static boolean canHandle(final URIish uri) {
TransportBundleFile(final Repository local, final URIish uri) {
super(local, uri);
- bundle = FS.resolve(new File("."), uri.getPath()).getAbsoluteFile();
+ bundle = local.getFS().resolve(new File("."), uri.getPath()).getAbsoluteFile();
}
@Override
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportLocal.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportLocal.java
index cf4dbd539..08fd8901d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportLocal.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportLocal.java
@@ -91,13 +91,13 @@
class TransportLocal extends Transport implements PackTransport {
private static final String PWD = ".";
- static boolean canHandle(final URIish uri) {
+ static boolean canHandle(final URIish uri, FS fs) {
if (uri.getHost() != null || uri.getPort() > 0 || uri.getUser() != null
|| uri.getPass() != null || uri.getPath() == null)
return false;
if ("file".equals(uri.getScheme()) || uri.getScheme() == null)
- return FS.resolve(new File(PWD), uri.getPath()).isDirectory();
+ return fs.resolve(new File(PWD), uri.getPath()).isDirectory();
return false;
}
@@ -106,7 +106,7 @@ static boolean canHandle(final URIish uri) {
TransportLocal(final Repository local, final URIish uri) {
super(local, uri);
- File d = FS.resolve(new File(PWD), uri.getPath()).getAbsoluteFile();
+ File d = local.getFS().resolve(new File(PWD), uri.getPath()).getAbsoluteFile();
if (new File(d, Constants.DOT_GIT).isDirectory())
d = new File(d, Constants.DOT_GIT);
remoteGitDir = d;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/FileTreeIterator.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/FileTreeIterator.java
index 19db39a8f..8dfab8aa5 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/FileTreeIterator.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/FileTreeIterator.java
@@ -65,6 +65,7 @@
*/
public class FileTreeIterator extends WorkingTreeIterator {
private final File directory;
+ private final FS fs;
/**
* Create a new iterator to traverse the given directory and its children.
@@ -72,9 +73,13 @@ public class FileTreeIterator extends WorkingTreeIterator {
* @param root
* the starting directory. This directory should correspond to
* the root of the repository.
+ * @param fs
+ * the file system abstraction which will be necessary to
+ * perform certain file system operations.
*/
- public FileTreeIterator(final File root) {
+ public FileTreeIterator(final File root, FS fs) {
directory = root;
+ this.fs = fs;
init(entries());
}
@@ -83,20 +88,24 @@ public FileTreeIterator(final File root) {
*
* @param p
* the parent iterator we were created from.
+ * @param fs
+ * the file system abstraction which will be necessary to
+ * perform certain file system operations.
* @param root
* the subdirectory. This should be a directory contained within
* the parent directory.
*/
- protected FileTreeIterator(final FileTreeIterator p, final File root) {
+ protected FileTreeIterator(final FileTreeIterator p, final File root, FS fs) {
super(p);
directory = root;
+ this.fs = fs;
init(entries());
}
@Override
public AbstractTreeIterator createSubtreeIterator(final Repository repo)
throws IncorrectObjectTypeException, IOException {
- return new FileTreeIterator(this, ((FileEntry) current()).file);
+ return new FileTreeIterator(this, ((FileEntry) current()).file, fs);
}
private Entry[] entries() {
@@ -105,7 +114,7 @@ private Entry[] entries() {
return EOF;
final Entry[] r = new Entry[all.length];
for (int i = 0; i < r.length; i++)
- r[i] = new FileEntry(all[i]);
+ r[i] = new FileEntry(all[i], fs);
return r;
}
@@ -121,7 +130,7 @@ static public class FileEntry extends Entry {
private long lastModified;
- FileEntry(final File f) {
+ FileEntry(final File f, FS fs) {
file = f;
if (f.isDirectory()) {
@@ -129,7 +138,7 @@ static public class FileEntry extends Entry {
mode = FileMode.GITLINK;
else
mode = FileMode.TREE;
- } else if (FS.INSTANCE.canExecute(file))
+ } else if (fs.canExecute(file))
mode = FileMode.EXECUTABLE_FILE;
else
mode = FileMode.REGULAR_FILE;
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 c4f4242f9..b8d433762 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java
@@ -49,19 +49,28 @@
/** Abstraction to support various file system operations not in Java. */
public abstract class FS {
- /** The implementation selected for this operating system and JRE. */
- public static final FS INSTANCE;
+ /** The auto-detected implementation selected for this operating system and JRE. */
+ public static final FS DETECTED;
static {
if (FS_Win32.detect()) {
if (FS_Win32_Cygwin.detect())
- INSTANCE = new FS_Win32_Cygwin();
+ DETECTED = new FS_Win32_Cygwin();
else
- INSTANCE = new FS_Win32();
+ DETECTED = new FS_Win32();
} else if (FS_POSIX_Java6.detect())
- INSTANCE = new FS_POSIX_Java6();
+ DETECTED = new FS_POSIX_Java6();
else
- INSTANCE = new FS_POSIX_Java5();
+ DETECTED = new FS_POSIX_Java5();
+ }
+
+ private final File userHome;
+
+ /**
+ * Constructs a file system abstraction.
+ */
+ protected FS() {
+ this.userHome = userHomeImpl();
}
/**
@@ -117,29 +126,7 @@ public abstract class FS {
* @return the translated path. new File(dir,name)
if this
* platform does not require path name translation.
*/
- public static File resolve(final File dir, final String name) {
- return INSTANCE.resolveImpl(dir, name);
- }
-
- /**
- * Resolve this file to its actual path name that the JRE can use.
- * - * This method can be relatively expensive. Computing a translation may - * require forking an external process per path name translated. Callers - * should try to minimize the number of translations necessary by caching - * the results. - *
- * Not all platforms and JREs require path name translation. Currently only
- * Cygwin on Win32 require translation for Cygwin based paths.
- *
- * @param dir
- * directory relative to which the path name is.
- * @param name
- * path name to translate.
- * @return the translated path. new File(dir,name)
if this
- * platform does not require path name translation.
- */
- protected File resolveImpl(final File dir, final String name) {
+ public File resolve(final File dir, final String name) {
final File abspn = new File(name);
if (abspn.isAbsolute())
return abspn;
@@ -157,12 +144,8 @@ protected File resolveImpl(final File dir, final String name) {
*
* @return the user's home directory; null if the user does not have one.
*/
- public static File userHome() {
- return USER_HOME.home;
- }
-
- private static class USER_HOME {
- static final File home = INSTANCE.userHomeImpl();
+ public File userHome() {
+ return userHome;
}
/**
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 f72708486..39f2c03a0 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
@@ -72,7 +72,7 @@ public String run() {
return false;
}
- protected File resolveImpl(final File dir, final String pn) {
+ public File resolve(final File dir, final String pn) {
try {
final Process p;
@@ -103,7 +103,7 @@ protected File resolveImpl(final File dir, final String pn) {
// Fall through and use the default return.
//
}
- return super.resolveImpl(dir, pn);
+ return super.resolve(dir, pn);
}
@Override
@@ -116,6 +116,6 @@ public String run() {
});
if (home == null || home.length() == 0)
return super.userHomeImpl();
- return resolveImpl(new File("."), home);
+ return resolve(new File("."), home);
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java
index 771e77058..9d7feb08f 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java
@@ -72,8 +72,8 @@ public String getProperty(String key) {
return System.getProperty(key);
}
- public FileBasedConfig openUserConfig() {
- final File home = FS.userHome();
+ public FileBasedConfig openUserConfig(FS fs) {
+ final File home = fs.userHome();
return new FileBasedConfig(new File(home, ".gitconfig"));
}
@@ -136,9 +136,12 @@ public static void setInstance(SystemReader newReader) {
public abstract String getProperty(String key);
/**
+ * @param fs
+ * the file system abstraction which will be necessary to
+ * perform certain file system operations.
* @return the git configuration found in the user home
*/
- public abstract FileBasedConfig openUserConfig();
+ public abstract FileBasedConfig openUserConfig(FS fs);
/**
* @return the current system time