@@ -28,7 +28,7 @@ pub fn git_hooks_dir() -> Result<PathBuf> {
2828 Ok ( PathBuf :: from ( path. trim ( ) ) )
2929}
3030
31- #[ derive( Debug , Deserialize , Eq , PartialEq ) ]
31+ #[ derive( Debug , Deserialize , Eq , PartialEq , Ord , PartialOrd ) ]
3232#[ serde( rename_all = "snake_case" ) ]
3333pub enum FileType {
3434 Symlink ,
@@ -42,6 +42,7 @@ pub enum FileType {
4242 Binary ,
4343}
4444
45+ #[ derive( Eq , PartialEq , Ord , PartialOrd ) ]
4546pub struct FileInfo {
4647 pub path : PathBuf ,
4748 pub ty : FileType ,
@@ -82,7 +83,7 @@ pub fn git_tree_files(top_level: &Path, treeish: &str) -> Result<Vec<FileInfo>>
8283 bail ! ( "git ls-tree command failed" ) ;
8384 }
8485
85- process_file_info ( & command. stdout )
86+ process_file_info ( top_level , & command. stdout )
8687}
8788
8889/// Get info on all of the staged files.
@@ -105,7 +106,7 @@ pub fn git_staged_files(top_level: &Path) -> Result<Vec<FileInfo>> {
105106 bail ! ( "git ls-files command failed" ) ;
106107 }
107108
108- process_file_info ( & command. stdout )
109+ process_file_info ( top_level , & command. stdout )
109110}
110111
111112/// List of files changed in the working directory (not staged).
@@ -125,7 +126,7 @@ pub fn git_diff_unstaged(top_level: &Path) -> Result<Vec<u8>> {
125126 Ok ( output. stdout )
126127}
127128
128- fn process_file_info ( ls_files_stdout : & [ u8 ] ) -> Result < Vec < FileInfo > > {
129+ fn process_file_info ( top_level : & Path , ls_files_stdout : & [ u8 ] ) -> Result < Vec < FileInfo > > {
129130 ls_files_stdout
130131 . split ( |& b| b == 0 )
131132 . tuples ( )
@@ -149,7 +150,8 @@ fn process_file_info(ls_files_stdout: &[u8]) -> Result<Vec<FileInfo>> {
149150 } else {
150151 // Read the first 8000 bytes and look for a null byte. This is how
151152 // Git decides if it's binary.
152- let mut file = std:: fs:: File :: open ( & path) ?;
153+ let full_path = top_level. join ( path) ;
154+ let mut file = std:: fs:: File :: open ( & full_path) ?;
153155 let mut buf = [ 0 ; 8000 ] ;
154156 let len = read_up_to ( & mut file, & mut buf) ?;
155157 let contents = & buf[ ..len] ;
@@ -214,3 +216,51 @@ fn read_up_to(file: &mut impl std::io::Read, mut buf: &mut [u8]) -> Result<usize
214216 }
215217 Ok ( buf_len - buf. len ( ) )
216218}
219+
220+
221+ #[ cfg( test) ]
222+ mod test {
223+ use super :: * ;
224+ use tempfile:: tempdir;
225+
226+ #[ test]
227+ fn test_process_file_info ( ) {
228+ let dir = tempdir ( ) . expect ( "Failed to create temp dir" ) ;
229+
230+ let text_path = dir. path ( ) . join ( "test.txt" ) ;
231+ std:: fs:: write ( & text_path, "Hello, world!" ) . expect ( "Failed to write test text file" ) ;
232+ let bin_path = dir. path ( ) . join ( "test.bin" ) ;
233+ std:: fs:: write ( & bin_path, b"Hello \x00 !" ) . expect ( "Failed to write test binary file" ) ;
234+
235+ let output = Command :: new ( "git" )
236+ . arg ( "init" )
237+ . current_dir ( dir. path ( ) )
238+ . output ( )
239+ . expect ( "Failed to run git init" ) ;
240+ assert ! ( output. status. success( ) ) ;
241+
242+ let output = Command :: new ( "git" )
243+ . arg ( "add" )
244+ . arg ( & text_path)
245+ . arg ( & bin_path)
246+ . current_dir ( dir. path ( ) )
247+ . output ( )
248+ . expect ( "Failed to run git add" ) ;
249+ assert ! ( output. status. success( ) ) ;
250+
251+ let output = Command :: new ( "git" )
252+ . arg ( "commit" )
253+ . arg ( "-m" )
254+ . arg ( "Test commit" )
255+ . current_dir ( dir. path ( ) )
256+ . output ( )
257+ . expect ( "Failed to run git commit" ) ;
258+ assert ! ( output. status. success( ) ) ;
259+
260+ let mut files = git_tree_files ( dir. path ( ) , "HEAD" ) . expect ( "Failed to get git tree files" ) ;
261+ files. sort ( ) ;
262+ assert_eq ! ( files. len( ) , 2 ) ;
263+ assert_eq ! ( files[ 0 ] . ty, FileType :: Binary ) ;
264+ assert_eq ! ( files[ 1 ] . ty, FileType :: Text ) ;
265+ }
266+ }
0 commit comments