@@ -28,8 +28,12 @@ pub enum FileEvent {
2828 NoEvent ,
2929}
3030
31- pub fn parse_file_meta_line ( line : & str , git_diff_name : bool ) -> ( String , FileEvent ) {
32- match line {
31+ pub fn parse_file_meta_line (
32+ line : & str ,
33+ git_diff_name : bool ,
34+ relative_path_base : Option < & str > ,
35+ ) -> ( String , FileEvent ) {
36+ let ( mut path, file_event) = match line {
3337 line if line. starts_with ( "--- " ) || line. starts_with ( "+++ " ) => {
3438 let offset = 4 ;
3539 let file = match & line[ offset..] {
@@ -56,7 +60,47 @@ pub fn parse_file_meta_line(line: &str, git_diff_name: bool) -> (String, FileEve
5660 ( line[ 8 ..] . to_string ( ) , FileEvent :: Copy ) // "copy to ".len()
5761 }
5862 _ => ( "" . to_string ( ) , FileEvent :: NoEvent ) ,
63+ } ;
64+
65+ if let Some ( base) = relative_path_base {
66+ if let Some ( relative_path) = pathdiff:: diff_paths ( & path, base) {
67+ if let Some ( relative_path) = relative_path. to_str ( ) {
68+ path = relative_path. to_owned ( ) ;
69+ }
70+ }
71+ }
72+
73+ ( path, file_event)
74+ }
75+
76+ // A regex to capture the path, and the content from the pipe onwards, in lines
77+ // like these:
78+ // " src/delta.rs | 14 ++++++++++----"
79+ // " src/config.rs | 2 ++"
80+ lazy_static ! {
81+ static ref DIFF_STAT_LINE_REGEX : Regex =
82+ Regex :: new( r" ([^\| ][^\|]+[^\| ]) +(\| +[0-9]+ .+)" ) . unwrap( ) ;
83+ }
84+
85+ pub fn relativize_path_in_diff_stat_line (
86+ line : & str ,
87+ cwd_relative_to_repo_root : & str ,
88+ diff_stat_align_width : usize ,
89+ ) -> Option < String > {
90+ if let Some ( caps) = DIFF_STAT_LINE_REGEX . captures ( line) {
91+ let path_relative_to_repo_root = caps. get ( 1 ) . unwrap ( ) . as_str ( ) ;
92+ if let Some ( relative_path) =
93+ pathdiff:: diff_paths ( path_relative_to_repo_root, cwd_relative_to_repo_root)
94+ {
95+ if let Some ( relative_path) = relative_path. to_str ( ) {
96+ let suffix = caps. get ( 2 ) . unwrap ( ) . as_str ( ) ;
97+ let pad_width = diff_stat_align_width. saturating_sub ( relative_path. len ( ) ) ;
98+ let padding = " " . repeat ( pad_width) ;
99+ return Some ( format ! ( " {}{}{}" , relative_path, padding, suffix) ) ;
100+ }
101+ }
59102 }
103+ None
60104}
61105
62106pub fn get_file_extension_from_file_meta_line_file_path ( path : & str ) -> Option < & str > {
@@ -245,45 +289,45 @@ mod tests {
245289 #[ test]
246290 fn test_get_file_path_from_git_file_meta_line ( ) {
247291 assert_eq ! (
248- parse_file_meta_line( "--- /dev/null" , true ) ,
292+ parse_file_meta_line( "--- /dev/null" , true , None ) ,
249293 ( "/dev/null" . to_string( ) , FileEvent :: Change )
250294 ) ;
251295 for prefix in & DIFF_PREFIXES {
252296 assert_eq ! (
253- parse_file_meta_line( & format!( "--- {}src/delta.rs" , prefix) , true ) ,
297+ parse_file_meta_line( & format!( "--- {}src/delta.rs" , prefix) , true , None ) ,
254298 ( "src/delta.rs" . to_string( ) , FileEvent :: Change )
255299 ) ;
256300 }
257301 assert_eq ! (
258- parse_file_meta_line( "--- src/delta.rs" , true ) ,
302+ parse_file_meta_line( "--- src/delta.rs" , true , None ) ,
259303 ( "src/delta.rs" . to_string( ) , FileEvent :: Change )
260304 ) ;
261305 assert_eq ! (
262- parse_file_meta_line( "+++ src/delta.rs" , true ) ,
306+ parse_file_meta_line( "+++ src/delta.rs" , true , None ) ,
263307 ( "src/delta.rs" . to_string( ) , FileEvent :: Change )
264308 ) ;
265309 }
266310
267311 #[ test]
268312 fn test_get_file_path_from_git_file_meta_line_containing_spaces ( ) {
269313 assert_eq ! (
270- parse_file_meta_line( "+++ a/my src/delta.rs" , true ) ,
314+ parse_file_meta_line( "+++ a/my src/delta.rs" , true , None ) ,
271315 ( "my src/delta.rs" . to_string( ) , FileEvent :: Change )
272316 ) ;
273317 assert_eq ! (
274- parse_file_meta_line( "+++ my src/delta.rs" , true ) ,
318+ parse_file_meta_line( "+++ my src/delta.rs" , true , None ) ,
275319 ( "my src/delta.rs" . to_string( ) , FileEvent :: Change )
276320 ) ;
277321 assert_eq ! (
278- parse_file_meta_line( "+++ a/src/my delta.rs" , true ) ,
322+ parse_file_meta_line( "+++ a/src/my delta.rs" , true , None ) ,
279323 ( "src/my delta.rs" . to_string( ) , FileEvent :: Change )
280324 ) ;
281325 assert_eq ! (
282- parse_file_meta_line( "+++ a/my src/my delta.rs" , true ) ,
326+ parse_file_meta_line( "+++ a/my src/my delta.rs" , true , None ) ,
283327 ( "my src/my delta.rs" . to_string( ) , FileEvent :: Change )
284328 ) ;
285329 assert_eq ! (
286- parse_file_meta_line( "+++ b/my src/my enough/my delta.rs" , true ) ,
330+ parse_file_meta_line( "+++ b/my src/my enough/my delta.rs" , true , None ) ,
287331 (
288332 "my src/my enough/my delta.rs" . to_string( ) ,
289333 FileEvent :: Change
@@ -294,27 +338,27 @@ mod tests {
294338 #[ test]
295339 fn test_get_file_path_from_git_file_meta_line_rename ( ) {
296340 assert_eq ! (
297- parse_file_meta_line( "rename from nospace/file2.el" , true ) ,
341+ parse_file_meta_line( "rename from nospace/file2.el" , true , None ) ,
298342 ( "nospace/file2.el" . to_string( ) , FileEvent :: Rename )
299343 ) ;
300344 }
301345
302346 #[ test]
303347 fn test_get_file_path_from_git_file_meta_line_rename_containing_spaces ( ) {
304348 assert_eq ! (
305- parse_file_meta_line( "rename from with space/file1.el" , true ) ,
349+ parse_file_meta_line( "rename from with space/file1.el" , true , None ) ,
306350 ( "with space/file1.el" . to_string( ) , FileEvent :: Rename )
307351 ) ;
308352 }
309353
310354 #[ test]
311355 fn test_parse_file_meta_line ( ) {
312356 assert_eq ! (
313- parse_file_meta_line( "--- src/delta.rs" , false ) ,
357+ parse_file_meta_line( "--- src/delta.rs" , false , None ) ,
314358 ( "src/delta.rs" . to_string( ) , FileEvent :: Change )
315359 ) ;
316360 assert_eq ! (
317- parse_file_meta_line( "+++ src/delta.rs" , false ) ,
361+ parse_file_meta_line( "+++ src/delta.rs" , false , None ) ,
318362 ( "src/delta.rs" . to_string( ) , FileEvent :: Change )
319363 ) ;
320364 }
@@ -369,4 +413,38 @@ mod tests {
369413 assert_eq ! ( line_numbers_and_hunk_lengths[ 1 ] , ( 358 , 15 ) , ) ;
370414 assert_eq ! ( line_numbers_and_hunk_lengths[ 2 ] , ( 358 , 16 ) , ) ;
371415 }
416+
417+ #[ test]
418+ fn test_relative_path ( ) {
419+ for ( path, cwd_relative_to_repo_root, expected) in & [
420+ ( "file.rs" , "" , "file.rs" ) ,
421+ ( "file.rs" , "a/" , "../file.rs" ) ,
422+ ( "a/file.rs" , "a/" , "file.rs" ) ,
423+ ( "a/b/file.rs" , "a" , "b/file.rs" ) ,
424+ ( "c/d/file.rs" , "a/b/" , "../../c/d/file.rs" ) ,
425+ ] {
426+ assert_eq ! (
427+ pathdiff:: diff_paths( path, cwd_relative_to_repo_root) ,
428+ Some ( expected. into( ) )
429+ )
430+ }
431+ }
432+
433+ #[ test]
434+ fn test_diff_stat_line_regex_1 ( ) {
435+ let caps = DIFF_STAT_LINE_REGEX . captures ( " src/delta.rs | 14 ++++++++++----" ) ;
436+ assert ! ( caps. is_some( ) ) ;
437+ let caps = caps. unwrap ( ) ;
438+ assert_eq ! ( caps. get( 1 ) . unwrap( ) . as_str( ) , "src/delta.rs" ) ;
439+ assert_eq ! ( caps. get( 2 ) . unwrap( ) . as_str( ) , "| 14 ++++++++++----" ) ;
440+ }
441+
442+ #[ test]
443+ fn test_diff_stat_line_regex_2 ( ) {
444+ let caps = DIFF_STAT_LINE_REGEX . captures ( " src/config.rs | 2 ++" ) ;
445+ assert ! ( caps. is_some( ) ) ;
446+ let caps = caps. unwrap ( ) ;
447+ assert_eq ! ( caps. get( 1 ) . unwrap( ) . as_str( ) , "src/config.rs" ) ;
448+ assert_eq ! ( caps. get( 2 ) . unwrap( ) . as_str( ) , "| 2 ++" ) ;
449+ }
372450}
0 commit comments