|
|
@@ -78,6 +78,15 @@ public class FileTreeIterator extends WorkingTreeIterator { |
|
|
|
*/ |
|
|
|
protected final FS fs; |
|
|
|
|
|
|
|
/** |
|
|
|
* the strategy used to compute the FileMode for a FileEntry. Can be used to |
|
|
|
* control things such as whether to recurse into a directory or create a |
|
|
|
* gitlink. |
|
|
|
* |
|
|
|
* @since 4.3 |
|
|
|
*/ |
|
|
|
protected final FileModeStrategy fileModeStrategy; |
|
|
|
|
|
|
|
/** |
|
|
|
* Create a new iterator to traverse the work tree and its children. |
|
|
|
* |
|
|
@@ -85,8 +94,24 @@ public class FileTreeIterator extends WorkingTreeIterator { |
|
|
|
* the repository whose working tree will be scanned. |
|
|
|
*/ |
|
|
|
public FileTreeIterator(Repository repo) { |
|
|
|
this(repo, DefaultFileModeStrategy.INSTANCE); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Create a new iterator to traverse the work tree and its children. |
|
|
|
* |
|
|
|
* @param repo |
|
|
|
* the repository whose working tree will be scanned. |
|
|
|
* @param fileModeStrategy |
|
|
|
* the strategy to use to determine the FileMode for a FileEntry; |
|
|
|
* controls gitlinks etc. |
|
|
|
* |
|
|
|
* @since 4.3 |
|
|
|
*/ |
|
|
|
public FileTreeIterator(Repository repo, FileModeStrategy fileModeStrategy) { |
|
|
|
this(repo.getWorkTree(), repo.getFS(), |
|
|
|
repo.getConfig().get(WorkingTreeOptions.KEY)); |
|
|
|
repo.getConfig().get(WorkingTreeOptions.KEY), |
|
|
|
fileModeStrategy); |
|
|
|
initRootIterator(repo); |
|
|
|
} |
|
|
|
|
|
|
@@ -103,9 +128,32 @@ public class FileTreeIterator extends WorkingTreeIterator { |
|
|
|
* working tree options to be used |
|
|
|
*/ |
|
|
|
public FileTreeIterator(final File root, FS fs, WorkingTreeOptions options) { |
|
|
|
this(root, fs, options, DefaultFileModeStrategy.INSTANCE); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Create a new iterator to traverse the given directory and its children. |
|
|
|
* |
|
|
|
* @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. |
|
|
|
* @param options |
|
|
|
* working tree options to be used |
|
|
|
* @param fileModeStrategy |
|
|
|
* the strategy to use to determine the FileMode for a FileEntry; |
|
|
|
* controls gitlinks etc. |
|
|
|
* |
|
|
|
* @since 4.3 |
|
|
|
*/ |
|
|
|
public FileTreeIterator(final File root, FS fs, WorkingTreeOptions options, |
|
|
|
FileModeStrategy fileModeStrategy) { |
|
|
|
super(options); |
|
|
|
directory = root; |
|
|
|
this.fs = fs; |
|
|
|
this.fileModeStrategy = fileModeStrategy; |
|
|
|
init(entries()); |
|
|
|
} |
|
|
|
|
|
|
@@ -114,25 +162,71 @@ public class FileTreeIterator extends WorkingTreeIterator { |
|
|
|
* |
|
|
|
* @param p |
|
|
|
* the parent iterator we were created from. |
|
|
|
* @param root |
|
|
|
* the subdirectory. This should be a directory contained within |
|
|
|
* the parent directory. |
|
|
|
* @param fs |
|
|
|
* the file system abstraction which will be necessary to perform |
|
|
|
* certain file system operations. |
|
|
|
* @since 4.3 |
|
|
|
* @deprecated use {@link #FileTreeIterator(FileTreeIterator, File, FS)} |
|
|
|
* instead. |
|
|
|
*/ |
|
|
|
protected FileTreeIterator(final WorkingTreeIterator p, final File root, |
|
|
|
FS fs) { |
|
|
|
this(p, root, fs, DefaultFileModeStrategy.INSTANCE); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Create a new iterator to traverse a subdirectory. |
|
|
|
* |
|
|
|
* @param p |
|
|
|
* the parent iterator we were created from. |
|
|
|
* @param root |
|
|
|
* the subdirectory. This should be a directory contained within |
|
|
|
* the parent directory. |
|
|
|
* @param fs |
|
|
|
* the file system abstraction which will be necessary to perform |
|
|
|
* certain file system operations. |
|
|
|
* |
|
|
|
* @since 4.3 |
|
|
|
*/ |
|
|
|
protected FileTreeIterator(final WorkingTreeIterator p, final File root, |
|
|
|
protected FileTreeIterator(final FileTreeIterator p, final File root, |
|
|
|
FS fs) { |
|
|
|
this(p, root, fs, p.fileModeStrategy); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Create a new iterator to traverse a subdirectory, given the specified |
|
|
|
* FileModeStrategy. |
|
|
|
* |
|
|
|
* @param p |
|
|
|
* the parent iterator we were created from. |
|
|
|
* @param root |
|
|
|
* the subdirectory. This should be a directory contained within |
|
|
|
* the parent directory |
|
|
|
* @param fs |
|
|
|
* the file system abstraction which will be necessary to perform |
|
|
|
* certain file system operations. |
|
|
|
* @param fileModeStrategy |
|
|
|
* the strategy to use to determine the FileMode for a given |
|
|
|
* FileEntry. |
|
|
|
* |
|
|
|
* @since 4.3 |
|
|
|
*/ |
|
|
|
protected FileTreeIterator(final WorkingTreeIterator p, final File root, |
|
|
|
FS fs, FileModeStrategy fileModeStrategy) { |
|
|
|
super(p); |
|
|
|
directory = root; |
|
|
|
this.fs = fs; |
|
|
|
this.fileModeStrategy = fileModeStrategy; |
|
|
|
init(entries()); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public AbstractTreeIterator createSubtreeIterator(final ObjectReader reader) |
|
|
|
throws IncorrectObjectTypeException, IOException { |
|
|
|
return new FileTreeIterator(this, ((FileEntry) current()).getFile(), fs); |
|
|
|
return new FileTreeIterator(this, ((FileEntry) current()).getFile(), fs, fileModeStrategy); |
|
|
|
} |
|
|
|
|
|
|
|
private Entry[] entries() { |
|
|
@@ -141,10 +235,62 @@ public class FileTreeIterator extends WorkingTreeIterator { |
|
|
|
return EOF; |
|
|
|
final Entry[] r = new Entry[all.length]; |
|
|
|
for (int i = 0; i < r.length; i++) |
|
|
|
r[i] = new FileEntry(all[i], fs); |
|
|
|
r[i] = new FileEntry(all[i], fs, fileModeStrategy); |
|
|
|
return r; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* An interface representing the methods used to determine the FileMode for |
|
|
|
* a FileEntry. |
|
|
|
* |
|
|
|
* @since 4.3 |
|
|
|
*/ |
|
|
|
public interface FileModeStrategy { |
|
|
|
/** |
|
|
|
* Compute the FileMode for a given File, based on its attributes. |
|
|
|
* |
|
|
|
* @param f |
|
|
|
* the file to return a FileMode for |
|
|
|
* @param attributes |
|
|
|
* the attributes of a file |
|
|
|
* @return a FileMode indicating whether the file is a regular file, a |
|
|
|
* directory, a gitlink, etc. |
|
|
|
*/ |
|
|
|
FileMode getMode(File f, FS.Attributes attributes); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* A default implementation of a FileModeStrategy; defaults to treating |
|
|
|
* nested .git directories as gitlinks, etc. |
|
|
|
* |
|
|
|
* @since 4.3 |
|
|
|
*/ |
|
|
|
static public class DefaultFileModeStrategy implements FileModeStrategy { |
|
|
|
/** |
|
|
|
* a singleton instance of the default FileModeStrategy |
|
|
|
*/ |
|
|
|
public final static DefaultFileModeStrategy INSTANCE = |
|
|
|
new DefaultFileModeStrategy(); |
|
|
|
|
|
|
|
@Override |
|
|
|
public FileMode getMode(File f, FS.Attributes attributes) { |
|
|
|
if (attributes.isSymbolicLink()) { |
|
|
|
return FileMode.SYMLINK; |
|
|
|
} else if (attributes.isDirectory()) { |
|
|
|
if (new File(f, Constants.DOT_GIT).exists()) { |
|
|
|
return FileMode.GITLINK; |
|
|
|
} else { |
|
|
|
return FileMode.TREE; |
|
|
|
} |
|
|
|
} else if (attributes.isExecutable()) { |
|
|
|
return FileMode.EXECUTABLE_FILE; |
|
|
|
} else { |
|
|
|
return FileMode.REGULAR_FILE; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* Wrapper for a standard Java IO file |
|
|
|
*/ |
|
|
@@ -164,20 +310,27 @@ public class FileTreeIterator extends WorkingTreeIterator { |
|
|
|
* file system |
|
|
|
*/ |
|
|
|
public FileEntry(File f, FS fs) { |
|
|
|
this(f, fs, DefaultFileModeStrategy.INSTANCE); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Create a new file entry given the specified FileModeStrategy |
|
|
|
* |
|
|
|
* @param f |
|
|
|
* file |
|
|
|
* @param fs |
|
|
|
* file system |
|
|
|
* @param fileModeStrategy |
|
|
|
* the strategy to use when determining the FileMode of a |
|
|
|
* file; controls gitlinks etc. |
|
|
|
* |
|
|
|
* @since 4.3 |
|
|
|
*/ |
|
|
|
public FileEntry(File f, FS fs, FileModeStrategy fileModeStrategy) { |
|
|
|
this.fs = fs; |
|
|
|
f = fs.normalize(f); |
|
|
|
attributes = fs.getAttributes(f); |
|
|
|
if (attributes.isSymbolicLink()) |
|
|
|
mode = FileMode.SYMLINK; |
|
|
|
else if (attributes.isDirectory()) { |
|
|
|
if (new File(f, Constants.DOT_GIT).exists()) |
|
|
|
mode = FileMode.GITLINK; |
|
|
|
else |
|
|
|
mode = FileMode.TREE; |
|
|
|
} else if (attributes.isExecutable()) |
|
|
|
mode = FileMode.EXECUTABLE_FILE; |
|
|
|
else |
|
|
|
mode = FileMode.REGULAR_FILE; |
|
|
|
mode = fileModeStrategy.getMode(f, attributes); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |