@ -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 File TreeIterator 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