Repository can be configured with FS

On Windows, FS_Win32_Cygwin has been used if a Cygwin Git installation
is present in the PATH. Assuming that the user works with the Cygwin
Git installation may result in unnecessary overhead if he actually
does not.

Applications built on top of jgit may have more knowledge on the
actually used Git client (Cygwin or not) and hence should be able to
configure which FS to use accordingly.

Change-Id: Ifc4278078b298781d55cf5421e9647a21fa5db24
This commit is contained in:
Marc Strapetz 2010-04-20 21:01:19 +02:00 committed by Shawn O. Pearce
parent 92eedd667d
commit 936e4ab2f2
25 changed files with 249 additions and 168 deletions

View File

@ -52,6 +52,7 @@
import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.RepositoryCache; import org.eclipse.jgit.lib.RepositoryCache;
import org.eclipse.jgit.lib.RepositoryCache.FileKey; import org.eclipse.jgit.lib.RepositoryCache.FileKey;
import org.eclipse.jgit.util.FS;
/** Default resolver serving from a single root path in local filesystem. */ /** Default resolver serving from a single root path in local filesystem. */
public class FileResolver implements RepositoryResolver { public class FileResolver implements RepositoryResolver {
@ -82,7 +83,7 @@ public Repository open(final HttpServletRequest req,
final Repository db; final Repository db;
try { try {
final File gitdir = new File(basePath, repositoryName); final File gitdir = new File(basePath, repositoryName);
db = RepositoryCache.open(FileKey.lenient(gitdir), true); db = RepositoryCache.open(FileKey.lenient(gitdir, FS.DETECTED), true);
} catch (IOException e) { } catch (IOException e) {
throw new RepositoryNotFoundException(repositoryName, e); throw new RepositoryNotFoundException(repositoryName, e);
} }

View File

@ -53,6 +53,7 @@
import org.eclipse.jgit.errors.ConfigInvalidException; import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileBasedConfig; import org.eclipse.jgit.lib.FileBasedConfig;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.SystemReader; import org.eclipse.jgit.util.SystemReader;
public class MockSystemReader extends SystemReader { public class MockSystemReader extends SystemReader {
@ -102,7 +103,7 @@ public String getProperty(String key) {
} }
@Override @Override
public FileBasedConfig openUserConfig() { public FileBasedConfig openUserConfig(FS fs) {
return userGitConfig; return userGitConfig;
} }

View File

@ -64,6 +64,7 @@
import org.eclipse.jgit.treewalk.AbstractTreeIterator; import org.eclipse.jgit.treewalk.AbstractTreeIterator;
import org.eclipse.jgit.treewalk.CanonicalTreeParser; import org.eclipse.jgit.treewalk.CanonicalTreeParser;
import org.eclipse.jgit.treewalk.FileTreeIterator; import org.eclipse.jgit.treewalk.FileTreeIterator;
import org.eclipse.jgit.util.FS;
/** /**
* Custom argument handler {@link AbstractTreeIterator} from string values. * Custom argument handler {@link AbstractTreeIterator} from string values.
@ -95,7 +96,7 @@ public int parseArguments(final Parameters params) throws CmdLineException {
final String name = params.getParameter(0); final String name = params.getParameter(0);
if (new File(name).isDirectory()) { if (new File(name).isDirectory()) {
setter.addValue(new FileTreeIterator(new File(name))); setter.addValue(new FileTreeIterator(new File(name), FS.DETECTED));
return 1; return 1;
} }

View File

@ -337,7 +337,7 @@ public void testCheckout() throws Exception {
} }
public void test030_executeBit_coreModeTrue() throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, Error, Exception { public void test030_executeBit_coreModeTrue() throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, Error, Exception {
if (!FS.INSTANCE.supportsExecute()) { if (!FS.DETECTED.supportsExecute()) {
System.err.println("Test ignored since platform FS does not support the execute permission"); System.err.println("Test ignored since platform FS does not support the execute permission");
return; return;
} }
@ -392,7 +392,7 @@ public void test030_executeBit_coreModeTrue() throws IllegalArgumentException, I
} }
public void test031_executeBit_coreModeFalse() throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, Error, Exception { public void test031_executeBit_coreModeFalse() throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, Error, Exception {
if (!FS.INSTANCE.supportsExecute()) { if (!FS.DETECTED.supportsExecute()) {
System.err.println("Test ignored since platform FS does not support the execute permission"); System.err.println("Test ignored since platform FS does not support the execute permission");
return; return;
} }

View File

@ -54,13 +54,13 @@ public void testNonBareFileKey() {
File gitdir = db.getDirectory(); File gitdir = db.getDirectory();
File parent = gitdir.getParentFile(); File parent = gitdir.getParentFile();
File other = new File(parent, "notagit"); File other = new File(parent, "notagit");
assertEquals(gitdir, FileKey.exact(gitdir).getFile()); assertEquals(gitdir, FileKey.exact(gitdir, db.getFS()).getFile());
assertEquals(parent, FileKey.exact(parent).getFile()); assertEquals(parent, FileKey.exact(parent, db.getFS()).getFile());
assertEquals(other, FileKey.exact(other).getFile()); assertEquals(other, FileKey.exact(other, db.getFS()).getFile());
assertEquals(gitdir, FileKey.lenient(gitdir).getFile()); assertEquals(gitdir, FileKey.lenient(gitdir, db.getFS()).getFile());
assertEquals(gitdir, FileKey.lenient(parent).getFile()); assertEquals(gitdir, FileKey.lenient(parent, db.getFS()).getFile());
assertEquals(other, FileKey.lenient(other).getFile()); assertEquals(other, FileKey.lenient(other, db.getFS()).getFile());
} }
public void testBareFileKey() throws IOException { public void testBareFileKey() throws IOException {
@ -71,21 +71,21 @@ public void testBareFileKey() throws IOException {
assertTrue(name.endsWith(".git")); assertTrue(name.endsWith(".git"));
name = name.substring(0, name.length() - 4); name = name.substring(0, name.length() - 4);
assertEquals(gitdir, FileKey.exact(gitdir).getFile()); assertEquals(gitdir, FileKey.exact(gitdir, db.getFS()).getFile());
assertEquals(gitdir, FileKey.lenient(gitdir).getFile()); assertEquals(gitdir, FileKey.lenient(gitdir, db.getFS()).getFile());
assertEquals(gitdir, FileKey.lenient(new File(parent, name)).getFile()); assertEquals(gitdir, FileKey.lenient(new File(parent, name), db.getFS()).getFile());
} }
public void testFileKeyOpenExisting() throws IOException { public void testFileKeyOpenExisting() throws IOException {
Repository r; Repository r;
r = new FileKey(db.getDirectory()).open(true); r = new FileKey(db.getDirectory(), db.getFS()).open(true);
assertNotNull(r); assertNotNull(r);
assertEquals(db.getDirectory(), r.getDirectory()); assertEquals(db.getDirectory(), r.getDirectory());
r.close(); r.close();
r = new FileKey(db.getDirectory()).open(false); r = new FileKey(db.getDirectory(), db.getFS()).open(false);
assertNotNull(r); assertNotNull(r);
assertEquals(db.getDirectory(), r.getDirectory()); assertEquals(db.getDirectory(), r.getDirectory());
r.close(); r.close();
@ -99,13 +99,13 @@ public void testFileKeyOpenNew() throws IOException {
assertFalse(gitdir.exists()); assertFalse(gitdir.exists());
try { try {
new FileKey(gitdir).open(true); new FileKey(gitdir, db.getFS()).open(true);
fail("incorrectly opened a non existant repository"); fail("incorrectly opened a non existant repository");
} catch (RepositoryNotFoundException e) { } catch (RepositoryNotFoundException e) {
assertEquals("repository not found: " + gitdir, e.getMessage()); assertEquals("repository not found: " + gitdir, e.getMessage());
} }
final Repository o = new FileKey(gitdir).open(false); final Repository o = new FileKey(gitdir, db.getFS()).open(false);
assertNotNull(o); assertNotNull(o);
assertEquals(gitdir, o.getDirectory()); assertEquals(gitdir, o.getDirectory());
assertFalse(gitdir.exists()); assertFalse(gitdir.exists());
@ -114,18 +114,18 @@ public void testFileKeyOpenNew() throws IOException {
public void testCacheRegisterOpen() throws Exception { public void testCacheRegisterOpen() throws Exception {
final File dir = db.getDirectory(); final File dir = db.getDirectory();
RepositoryCache.register(db); RepositoryCache.register(db);
assertSame(db, RepositoryCache.open(FileKey.exact(dir))); assertSame(db, RepositoryCache.open(FileKey.exact(dir, db.getFS())));
assertEquals(".git", dir.getName()); assertEquals(".git", dir.getName());
final File parent = dir.getParentFile(); final File parent = dir.getParentFile();
assertSame(db, RepositoryCache.open(FileKey.lenient(parent))); assertSame(db, RepositoryCache.open(FileKey.lenient(parent, db.getFS())));
} }
public void testCacheOpen() throws Exception { public void testCacheOpen() throws Exception {
final FileKey loc = FileKey.exact(db.getDirectory()); final FileKey loc = FileKey.exact(db.getDirectory(), db.getFS());
final Repository d2 = RepositoryCache.open(loc); final Repository d2 = RepositoryCache.open(loc);
assertNotSame(db, d2); assertNotSame(db, d2);
assertSame(d2, RepositoryCache.open(FileKey.exact(loc.getFile()))); assertSame(d2, RepositoryCache.open(FileKey.exact(loc.getFile(), db.getFS())));
d2.close(); d2.close();
d2.close(); d2.close();
} }

View File

@ -54,6 +54,7 @@
import org.eclipse.jgit.errors.ConfigInvalidException; import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.junit.MockSystemReader; import org.eclipse.jgit.junit.MockSystemReader;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.SystemReader; import org.eclipse.jgit.util.SystemReader;
/** /**
@ -116,7 +117,7 @@ public void test007_readUserConfig() {
final MockSystemReader mockSystemReader = new MockSystemReader(); final MockSystemReader mockSystemReader = new MockSystemReader();
SystemReader.setInstance(mockSystemReader); SystemReader.setInstance(mockSystemReader);
final String hostname = mockSystemReader.getHostname(); final String hostname = mockSystemReader.getHostname();
final Config userGitConfig = mockSystemReader.openUserConfig(); final Config userGitConfig = mockSystemReader.openUserConfig(FS.DETECTED);
final Config localConfig = new Config(userGitConfig); final Config localConfig = new Config(userGitConfig);
mockSystemReader.clearProperties(); mockSystemReader.clearProperties();

View File

@ -77,7 +77,7 @@ public void setUp() throws Exception {
public void testEmptyIfRootIsFile() throws Exception { public void testEmptyIfRootIsFile() throws Exception {
final File r = new File(trash, paths[0]); final File r = new File(trash, paths[0]);
assertTrue(r.isFile()); assertTrue(r.isFile());
final FileTreeIterator fti = new FileTreeIterator(r); final FileTreeIterator fti = new FileTreeIterator(r, db.getFS());
assertTrue(fti.first()); assertTrue(fti.first());
assertTrue(fti.eof()); assertTrue(fti.eof());
} }
@ -85,7 +85,7 @@ public void testEmptyIfRootIsFile() throws Exception {
public void testEmptyIfRootDoesNotExist() throws Exception { public void testEmptyIfRootDoesNotExist() throws Exception {
final File r = new File(trash, "not-existing-file"); final File r = new File(trash, "not-existing-file");
assertFalse(r.exists()); assertFalse(r.exists());
final FileTreeIterator fti = new FileTreeIterator(r); final FileTreeIterator fti = new FileTreeIterator(r, db.getFS());
assertTrue(fti.first()); assertTrue(fti.first());
assertTrue(fti.eof()); assertTrue(fti.eof());
} }
@ -96,13 +96,13 @@ public void testEmptyIfRootIsEmpty() throws Exception {
r.mkdir(); r.mkdir();
assertTrue(r.isDirectory()); assertTrue(r.isDirectory());
final FileTreeIterator fti = new FileTreeIterator(r); final FileTreeIterator fti = new FileTreeIterator(r, db.getFS());
assertTrue(fti.first()); assertTrue(fti.first());
assertTrue(fti.eof()); assertTrue(fti.eof());
} }
public void testSimpleIterate() throws Exception { public void testSimpleIterate() throws Exception {
final FileTreeIterator top = new FileTreeIterator(trash); final FileTreeIterator top = new FileTreeIterator(trash, db.getFS());
assertTrue(top.first()); assertTrue(top.first());
assertFalse(top.eof()); assertFalse(top.eof());
@ -149,7 +149,7 @@ public void testSimpleIterate() throws Exception {
} }
public void testComputeFileObjectId() throws Exception { public void testComputeFileObjectId() throws Exception {
final FileTreeIterator top = new FileTreeIterator(trash); final FileTreeIterator top = new FileTreeIterator(trash, db.getFS());
final MessageDigest md = Constants.newMessageDigest(); final MessageDigest md = Constants.newMessageDigest();
md.update(Constants.encodeASCII(Constants.TYPE_BLOB)); md.update(Constants.encodeASCII(Constants.TYPE_BLOB));

View File

@ -71,7 +71,6 @@
import org.eclipse.jgit.dircache.DirCache; import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.errors.CorruptObjectException; import org.eclipse.jgit.errors.CorruptObjectException;
import org.eclipse.jgit.errors.NotSupportedException; import org.eclipse.jgit.errors.NotSupportedException;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.RawParseUtils; import org.eclipse.jgit.util.RawParseUtils;
/** /**
@ -328,16 +327,16 @@ private void checkWriteOk() throws IOException {
} }
} }
static boolean File_canExecute( File f){ private boolean File_canExecute(File f){
return FS.INSTANCE.canExecute(f); return db.getFS().canExecute(f);
} }
static boolean File_setExecute(File f, boolean value) { private boolean File_setExecute(File f, boolean value) {
return FS.INSTANCE.setExecute(f, value); return db.getFS().setExecute(f, value);
} }
static boolean File_hasExecute() { private boolean File_hasExecute() {
return FS.INSTANCE.supportsExecute(); return db.getFS().supportsExecute();
} }
static byte[] makeKey(File wd, File f) { static byte[] makeKey(File wd, File f) {

View File

@ -88,6 +88,8 @@ public class ObjectDirectory extends ObjectDatabase {
private final File[] alternateObjectDir; private final File[] alternateObjectDir;
private final FS fs;
/** /**
* Initialize a reference to an on-disk object directory. * Initialize a reference to an on-disk object directory.
* *
@ -95,14 +97,18 @@ public class ObjectDirectory extends ObjectDatabase {
* the location of the <code>objects</code> directory. * the location of the <code>objects</code> directory.
* @param alternateObjectDir * @param alternateObjectDir
* a list of alternate object directories * 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; objects = dir;
this.alternateObjectDir = alternateObjectDir; this.alternateObjectDir = alternateObjectDir;
infoDirectory = new File(objects, "info"); infoDirectory = new File(objects, "info");
packDirectory = new File(objects, "pack"); packDirectory = new File(objects, "pack");
alternatesFile = new File(infoDirectory, "alternates"); alternatesFile = new File(infoDirectory, "alternates");
packList = new AtomicReference<PackList>(NO_PACKS); packList = new AtomicReference<PackList>(NO_PACKS);
this.fs = fs;
} }
/** /**
@ -485,17 +491,17 @@ private static BufferedReader open(final File f)
private ObjectDatabase openAlternate(final String location) private ObjectDatabase openAlternate(final String location)
throws IOException { throws IOException {
final File objdir = FS.resolve(objects, location); final File objdir = fs.resolve(objects, location);
return openAlternate(objdir); return openAlternate(objdir);
} }
private ObjectDatabase openAlternate(File objdir) throws IOException { private ObjectDatabase openAlternate(File objdir) throws IOException {
final File parent = objdir.getParentFile(); final File parent = objdir.getParentFile();
if (FileKey.isGitRepository(parent)) { if (FileKey.isGitRepository(parent, fs)) {
final Repository db = RepositoryCache.open(FileKey.exact(parent)); final Repository db = RepositoryCache.open(FileKey.exact(parent, fs));
return new AlternateRepositoryDatabase(db); return new AlternateRepositoryDatabase(db);
} }
return new ObjectDirectory(objdir, null); return new ObjectDirectory(objdir, null, fs);
} }
private static final class PackList { private static final class PackList {

View File

@ -151,12 +151,13 @@ public class RefDirectory extends RefDatabase {
private final AtomicInteger lastNotifiedModCnt = new AtomicInteger(); private final AtomicInteger lastNotifiedModCnt = new AtomicInteger();
RefDirectory(final Repository db) { RefDirectory(final Repository db) {
final FS fs = db.getFS();
parent = db; parent = db;
gitDir = db.getDirectory(); gitDir = db.getDirectory();
refsDir = FS.resolve(gitDir, R_REFS); refsDir = fs.resolve(gitDir, R_REFS);
logsDir = FS.resolve(gitDir, LOGS); logsDir = fs.resolve(gitDir, LOGS);
logsRefsDir = FS.resolve(gitDir, LOGS + '/' + R_REFS); logsRefsDir = fs.resolve(gitDir, LOGS + '/' + R_REFS);
packedRefsFile = FS.resolve(gitDir, PACKED_REFS); packedRefsFile = fs.resolve(gitDir, PACKED_REFS);
looseRefs.set(RefList.<LooseRef> emptyList()); looseRefs.set(RefList.<LooseRef> emptyList());
packedRefs.set(PackedRefList.NO_PACKED_REFS); packedRefs.set(PackedRefList.NO_PACKED_REFS);

View File

@ -102,6 +102,8 @@ public class Repository {
private final File gitDir; private final File gitDir;
private final FS fs;
private final FileBasedConfig userConfig; private final FileBasedConfig userConfig;
private final RepositoryConfig config; private final RepositoryConfig config;
@ -185,6 +187,41 @@ public Repository(final File d, final File workTree) throws IOException {
*/ */
public Repository(final File d, final File workTree, final File objectDir, public Repository(final File d, final File workTree, final File objectDir,
final File[] alternateObjectDir, final File indexFile) throws IOException { final File[] alternateObjectDir, final File indexFile) throws IOException {
this(d, workTree, objectDir, alternateObjectDir, indexFile, FS.DETECTED);
}
/**
* Construct a representation of a Git repository using the given parameters
* possibly overriding default conventions.
*
* @param d
* GIT_DIR (the location of the repository metadata). May be null
* for default value in which case it depends on GIT_WORK_TREE.
* @param workTree
* GIT_WORK_TREE (the root of the checkout). May be null for
* default value if GIT_DIR is
* @param objectDir
* GIT_OBJECT_DIRECTORY (where objects and are stored). May be
* null for default value. Relative names ares resolved against
* GIT_WORK_TREE
* @param alternateObjectDir
* GIT_ALTERNATE_OBJECT_DIRECTORIES (where more objects are read
* from). May be null for default value. Relative names ares
* resolved against GIT_WORK_TREE
* @param indexFile
* GIT_INDEX_FILE (the location of the index file). May be null
* for default value. Relative names ares resolved against
* GIT_WORK_TREE.
* @param fs
* the file system abstraction which will be necessary to
* perform certain file system operations.
* @throws IOException
* the repository appears to already exist but cannot be
* accessed.
*/
public Repository(final File d, final File workTree, final File objectDir,
final File[] alternateObjectDir, final File indexFile,
FS fs) throws IOException {
if (workTree != null) { if (workTree != null) {
workDir = workTree; workDir = workTree;
@ -199,8 +236,10 @@ public Repository(final File d, final File workTree, final File objectDir,
throw new IllegalArgumentException(JGitText.get().eitherGIT_DIRorGIT_WORK_TREEmustBePassed); throw new IllegalArgumentException(JGitText.get().eitherGIT_DIRorGIT_WORK_TREEmustBePassed);
} }
userConfig = SystemReader.getInstance().openUserConfig(); this.fs = fs;
config = new RepositoryConfig(userConfig, FS.resolve(gitDir, "config"));
userConfig = SystemReader.getInstance().openUserConfig(fs);
config = new RepositoryConfig(userConfig, fs.resolve(gitDir, "config"));
loadUserConfig(); loadUserConfig();
loadConfig(); loadConfig();
@ -208,7 +247,7 @@ public Repository(final File d, final File workTree, final File objectDir,
if (workDir == null) { if (workDir == null) {
String workTreeConfig = getConfig().getString("core", null, "worktree"); String workTreeConfig = getConfig().getString("core", null, "worktree");
if (workTreeConfig != null) { if (workTreeConfig != null) {
workDir = FS.resolve(d, workTreeConfig); workDir = fs.resolve(d, workTreeConfig);
} else { } else {
workDir = gitDir.getParentFile(); workDir = gitDir.getParentFile();
} }
@ -216,11 +255,11 @@ public Repository(final File d, final File workTree, final File objectDir,
refs = new RefDirectory(this); refs = new RefDirectory(this);
if (objectDir != null) if (objectDir != null)
objectDatabase = new ObjectDirectory(FS.resolve(objectDir, ""), objectDatabase = new ObjectDirectory(fs.resolve(objectDir, ""),
alternateObjectDir); alternateObjectDir, fs);
else else
objectDatabase = new ObjectDirectory(FS.resolve(gitDir, "objects"), objectDatabase = new ObjectDirectory(fs.resolve(gitDir, "objects"),
alternateObjectDir); alternateObjectDir, fs);
if (indexFile != null) if (indexFile != null)
this.indexFile = indexFile; this.indexFile = indexFile;
@ -351,6 +390,13 @@ public RepositoryConfig getConfig() {
return config; return config;
} }
/**
* @return the used file system abstraction
*/
public FS getFS() {
return fs;
}
/** /**
* Construct a filename where the loose object having a specified SHA-1 * Construct a filename where the loose object having a specified SHA-1
* should be stored. If the object is stored in a shared repository the path * should be stored. If the object is stored in a shared repository the path

View File

@ -120,7 +120,7 @@ public static Repository open(final Key location, final boolean mustExist)
* repository to register. * repository to register.
*/ */
public static void register(final Repository db) { public static void register(final Repository db) {
cache.registerRepository(FileKey.exact(db.getDirectory()), db); cache.registerRepository(FileKey.exact(db.getDirectory(), db.getFS()), db);
} }
/** /**
@ -133,7 +133,7 @@ public static void register(final Repository db) {
* repository to unregister. * repository to unregister.
*/ */
public static void close(final Repository db) { public static void close(final Repository db) {
cache.unregisterRepository(FileKey.exact(db.getDirectory())); cache.unregisterRepository(FileKey.exact(db.getDirectory(), db.getFS()));
} }
/** Unregister all repositories from the cache. */ /** Unregister all repositories from the cache. */
@ -248,11 +248,14 @@ public static class FileKey implements Key {
* *
* @param directory * @param directory
* location where the repository database is. * location where the repository database is.
* @param fs
* the file system abstraction which will be necessary to
* perform certain file system operations.
* @return a key for the given directory. * @return a key for the given directory.
* @see #lenient(File) * @see #lenient(File, FS)
*/ */
public static FileKey exact(final File directory) { public static FileKey exact(final File directory, FS fs) {
return new FileKey(directory); return new FileKey(directory, fs);
} }
/** /**
@ -268,22 +271,30 @@ public static FileKey exact(final File directory) {
* *
* @param directory * @param directory
* location where the repository database might be. * location where the repository database might be.
* @param fs
* the file system abstraction which will be necessary to
* perform certain file system operations.
* @return a key for the given directory. * @return a key for the given directory.
* @see #exact(File) * @see #exact(File, FS)
*/ */
public static FileKey lenient(final File directory) { public static FileKey lenient(final File directory, FS fs) {
final File gitdir = resolve(directory); final File gitdir = resolve(directory, fs);
return new FileKey(gitdir != null ? gitdir : directory); return new FileKey(gitdir != null ? gitdir : directory, fs);
} }
private final File path; private final File path;
private final FS fs;
/** /**
* @param directory * @param directory
* exact location of the repository. * exact location of the repository.
* @param fs
* the file system abstraction which will be necessary to
* perform certain file system operations.
*/ */
protected FileKey(final File directory) { protected FileKey(final File directory, FS fs) {
path = canonical(directory); path = canonical(directory);
this.fs = fs;
} }
private static File canonical(final File path) { private static File canonical(final File path) {
@ -300,7 +311,7 @@ public final File getFile() {
} }
public Repository open(final boolean mustExist) throws IOException { public Repository open(final boolean mustExist) throws IOException {
if (mustExist && !isGitRepository(path)) if (mustExist && !isGitRepository(path, fs))
throw new RepositoryNotFoundException(path); throw new RepositoryNotFoundException(path);
return new Repository(path); return new Repository(path);
} }
@ -328,13 +339,16 @@ public String toString() {
* *
* @param dir * @param dir
* the location of the directory to examine. * the location of the directory to examine.
* @param fs
* the file system abstraction which will be necessary to
* perform certain file system operations.
* @return true if the directory "looks like" a Git repository; false if * @return true if the directory "looks like" a Git repository; false if
* it doesn't look enough like a Git directory to really be a * it doesn't look enough like a Git directory to really be a
* Git directory. * Git directory.
*/ */
public static boolean isGitRepository(final File dir) { public static boolean isGitRepository(final File dir, FS fs) {
return FS.resolve(dir, "objects").exists() return fs.resolve(dir, "objects").exists()
&& FS.resolve(dir, "refs").exists() && fs.resolve(dir, "refs").exists()
&& isValidHead(new File(dir, Constants.HEAD)); && isValidHead(new File(dir, Constants.HEAD));
} }
@ -371,18 +385,21 @@ private static String readFirstLine(final File head) {
* *
* @param directory * @param directory
* location to guess from. Several permutations are tried. * location to guess from. Several permutations are tried.
* @param fs
* the file system abstraction which will be necessary to
* perform certain file system operations.
* @return the actual directory location if a better match is found; * @return the actual directory location if a better match is found;
* null if there is no suitable match. * null if there is no suitable match.
*/ */
public static File resolve(final File directory) { public static File resolve(final File directory, FS fs) {
if (isGitRepository(directory)) if (isGitRepository(directory, fs))
return directory; return directory;
if (isGitRepository(new File(directory, Constants.DOT_GIT))) if (isGitRepository(new File(directory, Constants.DOT_GIT), fs))
return new File(directory, Constants.DOT_GIT); return new File(directory, Constants.DOT_GIT);
final String name = directory.getName(); final String name = directory.getName();
final File parent = directory.getParentFile(); final File parent = directory.getParentFile();
if (isGitRepository(new File(parent, name + Constants.DOT_GIT_EXT))) if (isGitRepository(new File(parent, name + Constants.DOT_GIT_EXT), fs))
return new File(parent, name + Constants.DOT_GIT_EXT); return new File(parent, name + Constants.DOT_GIT_EXT);
return null; return null;
} }

View File

@ -63,6 +63,7 @@
import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.RepositoryCache; import org.eclipse.jgit.lib.RepositoryCache;
import org.eclipse.jgit.lib.RepositoryCache.FileKey; import org.eclipse.jgit.lib.RepositoryCache.FileKey;
import org.eclipse.jgit.util.FS;
/** Basic daemon for the anonymous <code>git://</code> transport protocol. */ /** Basic daemon for the anonymous <code>git://</code> transport protocol. */
public class Daemon { public class Daemon {
@ -368,7 +369,7 @@ Repository openRepository(String name) {
} }
for (final File baseDir : exportBase) { 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)) if (gitdir != null && canExport(gitdir))
return openRepository(gitdir); return openRepository(gitdir);
} }
@ -377,7 +378,7 @@ Repository openRepository(String name) {
private static Repository openRepository(final File gitdir) { private static Repository openRepository(final File gitdir) {
try { try {
return RepositoryCache.open(FileKey.exact(gitdir)); return RepositoryCache.open(FileKey.exact(gitdir, FS.DETECTED));
} catch (IOException err) { } catch (IOException err) {
// null signals it "wasn't found", which is all that is suitable // null signals it "wasn't found", which is all that is suitable
// for the remote client to know. // for the remote client to know.

View File

@ -82,10 +82,13 @@ public class OpenSshConfig {
* requests are cached and are automatically updated if the user modifies * requests are cached and are automatically updated if the user modifies
* the configuration file since the last time it was cached. * 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. * @return a caching reader of the user's configuration file.
*/ */
public static OpenSshConfig get() { public static OpenSshConfig get(FS fs) {
File home = FS.userHome(); File home = fs.userHome();
if (home == null) if (home == null)
home = new File(".").getAbsoluteFile(); home = new File(".").getAbsoluteFile();

View File

@ -83,15 +83,18 @@ public abstract class SshConfigSessionFactory extends SshSessionFactory {
@Override @Override
public synchronized Session getSession(String user, String pass, public synchronized Session getSession(String user, String pass,
String host, int port) throws JSchException { String host, int port, FS fs) throws JSchException {
final OpenSshConfig.Host hc = getConfig().lookup(host); if (config == null)
config = OpenSshConfig.get(fs);
final OpenSshConfig.Host hc = config.lookup(host);
host = hc.getHostName(); host = hc.getHostName();
if (port <= 0) if (port <= 0)
port = hc.getPort(); port = hc.getPort();
if (user == null) if (user == null)
user = hc.getUser(); user = hc.getUser();
final Session session = createSession(hc, user, host, port); final Session session = createSession(hc, user, host, port, fs);
if (pass != null) if (pass != null)
session.setPassword(pass); session.setPassword(pass);
final String strictHostKeyCheckingPolicy = hc final String strictHostKeyCheckingPolicy = hc
@ -117,14 +120,17 @@ public synchronized Session getSession(String user, String pass,
* server name to connect to. * server name to connect to.
* @param port * @param port
* port number of the SSH daemon (typically 22). * 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. * @return new session instance, but otherwise unconfigured.
* @throws JSchException * @throws JSchException
* the session could not be created. * the session could not be created.
*/ */
protected Session createSession(final OpenSshConfig.Host hc, 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 { 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 * @param hc
* host configuration * host configuration
* @param fs
* the file system abstraction which will be necessary to
* perform certain file system operations.
* @return the JSch instance to use. * @return the JSch instance to use.
* @throws JSchException * @throws JSchException
* the user configuration could not be created. * the user configuration could not be created.
*/ */
protected JSch getJSch(final OpenSshConfig.Host hc) throws JSchException { protected JSch getJSch(final OpenSshConfig.Host hc, FS fs) throws JSchException {
final JSch def = getDefaultJSch(); if (defaultJSch == null) {
defaultJSch = createDefaultJSch(fs);
for (Object name : defaultJSch.getIdentityNames()) {
byIdentityFile.put((String) name, defaultJSch);
}
}
final File identityFile = hc.getIdentityFile(); final File identityFile = hc.getIdentityFile();
if (identityFile == null) { if (identityFile == null) {
return def; return defaultJSch;
} }
final String identityKey = identityFile.getAbsolutePath(); final String identityKey = identityFile.getAbsolutePath();
JSch jsch = byIdentityFile.get(identityKey); JSch jsch = byIdentityFile.get(identityKey);
if (jsch == null) { if (jsch == null) {
jsch = new JSch(); jsch = new JSch();
jsch.setHostKeyRepository(def.getHostKeyRepository()); jsch.setHostKeyRepository(defaultJSch.getHostKeyRepository());
jsch.addIdentity(identityKey); jsch.addIdentity(identityKey);
byIdentityFile.put(identityKey, jsch); byIdentityFile.put(identityKey, jsch);
} }
return 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. * @return the new default JSch implementation.
* @throws JSchException * @throws JSchException
* known host keys cannot be loaded. * known host keys cannot be loaded.
*/ */
protected JSch createDefaultJSch() throws JSchException { protected JSch createDefaultJSch(FS fs) throws JSchException {
final JSch jsch = new JSch(); final JSch jsch = new JSch();
knownHosts(jsch); knownHosts(jsch, fs);
identities(jsch); identities(jsch, fs);
return jsch; return jsch;
} }
private OpenSshConfig getConfig() { private static void knownHosts(final JSch sch, FS fs) throws JSchException {
if (config == null) final File home = fs.userHome();
config = OpenSshConfig.get();
return config;
}
private static void knownHosts(final JSch sch) throws JSchException {
final File home = FS.userHome();
if (home == null) if (home == null)
return; return;
final File known_hosts = new File(new File(home, ".ssh"), "known_hosts"); 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) { private static void identities(final JSch sch, FS fs) {
final File home = FS.userHome(); final File home = fs.userHome();
if (home == null) if (home == null)
return; return;
final File sshdir = new File(home, ".ssh"); final File sshdir = new File(home, ".ssh");

View File

@ -44,6 +44,8 @@
package org.eclipse.jgit.transport; package org.eclipse.jgit.transport;
import org.eclipse.jgit.util.FS;
import com.jcraft.jsch.JSchException; import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session; import com.jcraft.jsch.Session;
@ -109,19 +111,22 @@ public static void setInstance(final SshSessionFactory newFactory) {
* @param port * @param port
* port number the server is listening for connections on. May be <= * port number the server is listening for connections on. May be <=
* 0 to indicate the IANA registered port of 22 should be used. * 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. * @return a session that can contact the remote host.
* @throws JSchException * @throws JSchException
* the session could not be created. * the session could not be created.
*/ */
public abstract Session getSession(String user, String pass, String host, 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. * Close (or recycle) a session to a host.
* *
* @param session * @param session
* a session previously obtained from this factory's * 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) { public void releaseSession(final Session session) {
if (session.isConnected()) if (session.isConnected())

View File

@ -128,7 +128,7 @@ protected void initSession() throws TransportException {
final String host = uri.getHost(); final String host = uri.getHost();
final int port = uri.getPort(); final int port = uri.getPort();
try { try {
sock = sch.getSession(user, pass, host, port); sock = sch.getSession(user, pass, host, port, local.getFS());
if (!sock.isConnected()) if (!sock.isConnected())
sock.connect(tms); sock.connect(tms);
} catch (JSchException je) { } catch (JSchException je) {

View File

@ -66,6 +66,7 @@
import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.TransferConfig; import org.eclipse.jgit.lib.TransferConfig;
import org.eclipse.jgit.util.FS;
/** /**
* Connects two Git repositories together and copies objects between them. * Connects two Git repositories together and copies objects between them.
@ -323,9 +324,11 @@ private static boolean doesNotExist(final RemoteConfig cfg) {
* *
* @param remote * @param remote
* location of the remote repository. * location of the remote repository.
* @param fs
* type of filesystem the local repository is stored on.
* @return true if the protocol is supported. * @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)) if (TransportGitSsh.canHandle(remote))
return true; return true;
@ -341,10 +344,10 @@ else if (TransportGitAnon.canHandle(remote))
else if (TransportAmazonS3.canHandle(remote)) else if (TransportAmazonS3.canHandle(remote))
return true; return true;
else if (TransportBundleFile.canHandle(remote)) else if (TransportBundleFile.canHandle(remote, fs))
return true; return true;
else if (TransportLocal.canHandle(remote)) else if (TransportLocal.canHandle(remote, fs))
return true; return true;
return false; return false;
@ -378,10 +381,10 @@ else if (TransportGitAnon.canHandle(remote))
else if (TransportAmazonS3.canHandle(remote)) else if (TransportAmazonS3.canHandle(remote))
return new TransportAmazonS3(local, remote); return new TransportAmazonS3(local, remote);
else if (TransportBundleFile.canHandle(remote)) else if (TransportBundleFile.canHandle(remote, local.getFS()))
return new TransportBundleFile(local, remote); return new TransportBundleFile(local, remote);
else if (TransportLocal.canHandle(remote)) else if (TransportLocal.canHandle(remote, local.getFS()))
return new TransportLocal(local, remote); return new TransportLocal(local, remote);
throw new NotSupportedException(MessageFormat.format(JGitText.get().URINotSupported, remote)); throw new NotSupportedException(MessageFormat.format(JGitText.get().URINotSupported, remote));

View File

@ -69,7 +69,6 @@
import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.SymbolicRef; import org.eclipse.jgit.lib.SymbolicRef;
import org.eclipse.jgit.lib.Ref.Storage; import org.eclipse.jgit.lib.Ref.Storage;
import org.eclipse.jgit.util.FS;
/** /**
* Transport over the non-Git aware Amazon S3 protocol. * Transport over the non-Git aware Amazon S3 protocol.
@ -130,7 +129,7 @@ static boolean canHandle(final URIish uri) {
Properties props = null; Properties props = null;
File propsFile = new File(local.getDirectory(), uri.getUser()); File propsFile = new File(local.getDirectory(), uri.getUser());
if (!propsFile.isFile()) if (!propsFile.isFile())
propsFile = new File(FS.userHome(), uri.getUser()); propsFile = new File(local.getFS().userHome(), uri.getUser());
if (propsFile.isFile()) { if (propsFile.isFile()) {
try { try {
props = AmazonS3.properties(propsFile); props = AmazonS3.properties(propsFile);

View File

@ -58,13 +58,13 @@
import org.eclipse.jgit.util.FS; import org.eclipse.jgit.util.FS;
class TransportBundleFile extends Transport implements TransportBundle { 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 if (uri.getHost() != null || uri.getPort() > 0 || uri.getUser() != null
|| uri.getPass() != null || uri.getPath() == null) || uri.getPass() != null || uri.getPath() == null)
return false; return false;
if ("file".equals(uri.getScheme()) || uri.getScheme() == null) { 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"); return f.isFile() || f.getName().endsWith(".bundle");
} }
@ -75,7 +75,7 @@ static boolean canHandle(final URIish uri) {
TransportBundleFile(final Repository local, final URIish uri) { TransportBundleFile(final Repository local, final URIish uri) {
super(local, uri); super(local, uri);
bundle = FS.resolve(new File("."), uri.getPath()).getAbsoluteFile(); bundle = local.getFS().resolve(new File("."), uri.getPath()).getAbsoluteFile();
} }
@Override @Override

View File

@ -91,13 +91,13 @@
class TransportLocal extends Transport implements PackTransport { class TransportLocal extends Transport implements PackTransport {
private static final String PWD = "."; 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 if (uri.getHost() != null || uri.getPort() > 0 || uri.getUser() != null
|| uri.getPass() != null || uri.getPath() == null) || uri.getPass() != null || uri.getPath() == null)
return false; return false;
if ("file".equals(uri.getScheme()) || uri.getScheme() == null) 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; return false;
} }
@ -106,7 +106,7 @@ static boolean canHandle(final URIish uri) {
TransportLocal(final Repository local, final URIish uri) { TransportLocal(final Repository local, final URIish uri) {
super(local, 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()) if (new File(d, Constants.DOT_GIT).isDirectory())
d = new File(d, Constants.DOT_GIT); d = new File(d, Constants.DOT_GIT);
remoteGitDir = d; remoteGitDir = d;

View File

@ -65,6 +65,7 @@
*/ */
public class FileTreeIterator extends WorkingTreeIterator { public class FileTreeIterator extends WorkingTreeIterator {
private final File directory; private final File directory;
private final FS fs;
/** /**
* Create a new iterator to traverse the given directory and its children. * Create a new iterator to traverse the given directory and its children.
@ -72,9 +73,13 @@ public class FileTreeIterator extends WorkingTreeIterator {
* @param root * @param root
* the starting directory. This directory should correspond to * the starting directory. This directory should correspond to
* the root of the repository. * 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; directory = root;
this.fs = fs;
init(entries()); init(entries());
} }
@ -83,20 +88,24 @@ public FileTreeIterator(final File root) {
* *
* @param p * @param p
* the parent iterator we were created from. * 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 * @param root
* the subdirectory. This should be a directory contained within * the subdirectory. This should be a directory contained within
* the parent directory. * the parent directory.
*/ */
protected FileTreeIterator(final FileTreeIterator p, final File root) { protected FileTreeIterator(final FileTreeIterator p, final File root, FS fs) {
super(p); super(p);
directory = root; directory = root;
this.fs = fs;
init(entries()); init(entries());
} }
@Override @Override
public AbstractTreeIterator createSubtreeIterator(final Repository repo) public AbstractTreeIterator createSubtreeIterator(final Repository repo)
throws IncorrectObjectTypeException, IOException { throws IncorrectObjectTypeException, IOException {
return new FileTreeIterator(this, ((FileEntry) current()).file); return new FileTreeIterator(this, ((FileEntry) current()).file, fs);
} }
private Entry[] entries() { private Entry[] entries() {
@ -105,7 +114,7 @@ private Entry[] entries() {
return EOF; return EOF;
final Entry[] r = new Entry[all.length]; final Entry[] r = new Entry[all.length];
for (int i = 0; i < r.length; i++) for (int i = 0; i < r.length; i++)
r[i] = new FileEntry(all[i]); r[i] = new FileEntry(all[i], fs);
return r; return r;
} }
@ -121,7 +130,7 @@ static public class FileEntry extends Entry {
private long lastModified; private long lastModified;
FileEntry(final File f) { FileEntry(final File f, FS fs) {
file = f; file = f;
if (f.isDirectory()) { if (f.isDirectory()) {
@ -129,7 +138,7 @@ static public class FileEntry extends Entry {
mode = FileMode.GITLINK; mode = FileMode.GITLINK;
else else
mode = FileMode.TREE; mode = FileMode.TREE;
} else if (FS.INSTANCE.canExecute(file)) } else if (fs.canExecute(file))
mode = FileMode.EXECUTABLE_FILE; mode = FileMode.EXECUTABLE_FILE;
else else
mode = FileMode.REGULAR_FILE; mode = FileMode.REGULAR_FILE;

View File

@ -49,19 +49,28 @@
/** Abstraction to support various file system operations not in Java. */ /** Abstraction to support various file system operations not in Java. */
public abstract class FS { public abstract class FS {
/** The implementation selected for this operating system and JRE. */ /** The auto-detected implementation selected for this operating system and JRE. */
public static final FS INSTANCE; public static final FS DETECTED;
static { static {
if (FS_Win32.detect()) { if (FS_Win32.detect()) {
if (FS_Win32_Cygwin.detect()) if (FS_Win32_Cygwin.detect())
INSTANCE = new FS_Win32_Cygwin(); DETECTED = new FS_Win32_Cygwin();
else else
INSTANCE = new FS_Win32(); DETECTED = new FS_Win32();
} else if (FS_POSIX_Java6.detect()) } else if (FS_POSIX_Java6.detect())
INSTANCE = new FS_POSIX_Java6(); DETECTED = new FS_POSIX_Java6();
else 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. <code>new File(dir,name)</code> if this * @return the translated path. <code>new File(dir,name)</code> if this
* platform does not require path name translation. * platform does not require path name translation.
*/ */
public static File resolve(final File dir, final String name) { public 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.
* <p>
* 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.
* <p>
* 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. <code>new File(dir,name)</code> if this
* platform does not require path name translation.
*/
protected File resolveImpl(final File dir, final String name) {
final File abspn = new File(name); final File abspn = new File(name);
if (abspn.isAbsolute()) if (abspn.isAbsolute())
return abspn; 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. * @return the user's home directory; null if the user does not have one.
*/ */
public static File userHome() { public File userHome() {
return USER_HOME.home; return userHome;
}
private static class USER_HOME {
static final File home = INSTANCE.userHomeImpl();
} }
/** /**

View File

@ -72,7 +72,7 @@ public String run() {
return false; return false;
} }
protected File resolveImpl(final File dir, final String pn) { public File resolve(final File dir, final String pn) {
try { try {
final Process p; final Process p;
@ -103,7 +103,7 @@ protected File resolveImpl(final File dir, final String pn) {
// Fall through and use the default return. // Fall through and use the default return.
// //
} }
return super.resolveImpl(dir, pn); return super.resolve(dir, pn);
} }
@Override @Override
@ -116,6 +116,6 @@ public String run() {
}); });
if (home == null || home.length() == 0) if (home == null || home.length() == 0)
return super.userHomeImpl(); return super.userHomeImpl();
return resolveImpl(new File("."), home); return resolve(new File("."), home);
} }
} }

View File

@ -72,8 +72,8 @@ public String getProperty(String key) {
return System.getProperty(key); return System.getProperty(key);
} }
public FileBasedConfig openUserConfig() { public FileBasedConfig openUserConfig(FS fs) {
final File home = FS.userHome(); final File home = fs.userHome();
return new FileBasedConfig(new File(home, ".gitconfig")); return new FileBasedConfig(new File(home, ".gitconfig"));
} }
@ -136,9 +136,12 @@ public static void setInstance(SystemReader newReader) {
public abstract String getProperty(String key); 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 * @return the git configuration found in the user home
*/ */
public abstract FileBasedConfig openUserConfig(); public abstract FileBasedConfig openUserConfig(FS fs);
/** /**
* @return the current system time * @return the current system time