55using System . IO . Abstractions ;
66using Elastic . Documentation . Diagnostics ;
77using Elastic . Documentation . Tooling . ExternalCommands ;
8+
89namespace Documentation . Builder . Tracking ;
910
10- public partial class LocalGitRepositoryTracker ( DiagnosticsCollector collector , IDirectoryInfo workingDirectory ) : ExternalCommandExecutor ( collector , workingDirectory ) , IRepositoryTracker
11+ public record GitChange ( string FilePath , GitChangeType ChangeType ) ;
12+ public record RenamedGitChange ( string OldFilePath , string NewFilePath , GitChangeType ChangeType ) : GitChange ( OldFilePath , ChangeType ) ;
13+
14+ public class LocalGitRepositoryTracker ( DiagnosticsCollector collector , IDirectoryInfo workingDirectory ) : ExternalCommandExecutor ( collector , workingDirectory ) , IRepositoryTracker
1115{
12- public IEnumerable < string > GetChangedFiles ( string lookupPath )
16+ public IEnumerable < GitChange > GetChangedFiles ( string lookupPath )
1317 {
1418 var defaultBranch = GetDefaultBranch ( ) ;
1519 var commitChanges = CaptureMultiple ( "git" , "diff" , "--name-status" , $ "{ defaultBranch } ...HEAD", "--" , $ "./{ lookupPath } ") ;
1620 var localChanges = CaptureMultiple ( "git" , "status" , "--porcelain" ) ;
17- List < string > output = [
18- .. commitChanges
19- . Where ( line => line . StartsWith ( 'R' ) || line . StartsWith ( 'D' ) || line . StartsWith ( 'A' ) )
20- . Select ( line => line . Split ( '\t ' ) [ 1 ] ) ,
21- .. localChanges
22- . Select ( x => x . TrimStart ( ) )
23- . Where ( line => line . StartsWith ( 'R' ) || line . StartsWith ( 'D' ) || line . StartsWith ( "A " , StringComparison . Ordinal ) || line . StartsWith ( "??" ) )
24- . Select ( line => line . Split ( ' ' , StringSplitOptions . RemoveEmptyEntries | StringSplitOptions . TrimEntries ) [ 1 ] )
25- ] ;
26- return output . Where ( line => line . StartsWith ( lookupPath ) ) ;
21+
22+ return [ .. GetCommitChanges ( commitChanges ) , .. GetLocalChanges ( localChanges ) ] ;
2723 }
2824
2925 private string GetDefaultBranch ( )
@@ -34,4 +30,53 @@ private string GetDefaultBranch()
3430 return "master" ;
3531 return Capture ( "git" , "symbolic-ref" , "refs/remotes/origin/HEAD" ) . Split ( '/' ) . Last ( ) ;
3632 }
33+
34+ private static IEnumerable < GitChange > GetCommitChanges ( string [ ] changes )
35+ {
36+ foreach ( var change in changes )
37+ {
38+ var parts = change . AsSpan ( ) . TrimStart ( ) ;
39+ if ( parts . Length < 2 )
40+ continue ;
41+
42+ var changeType = parts [ 0 ] switch
43+ {
44+ 'A' => GitChangeType . Added ,
45+ 'M' => GitChangeType . Modified ,
46+ 'D' => GitChangeType . Deleted ,
47+ 'R' => GitChangeType . Renamed ,
48+ _ => GitChangeType . Other
49+ } ;
50+
51+ yield return new GitChange ( change . Split ( '\t ' ) [ 1 ] , changeType ) ;
52+ }
53+ }
54+
55+ private static IEnumerable < GitChange > GetLocalChanges ( string [ ] changes )
56+ {
57+ foreach ( var change in changes )
58+ {
59+ var changeStatusCode = change . AsSpan ( ) ;
60+ if ( changeStatusCode . Length < 2 )
61+ continue ;
62+
63+ var changeType = ( changeStatusCode [ 0 ] , changeStatusCode [ 1 ] ) switch
64+ {
65+ ( 'R' , _ ) or ( _, 'R' ) => GitChangeType . Renamed ,
66+ ( 'D' , _ ) or ( _, 'D' ) when changeStatusCode [ 0 ] != 'A' => GitChangeType . Deleted ,
67+ ( '?' , '?' ) => GitChangeType . Untracked ,
68+ ( 'A' , _ ) or ( _, 'A' ) => GitChangeType . Added ,
69+ ( 'M' , _ ) or ( _, 'M' ) => GitChangeType . Modified ,
70+ _ => GitChangeType . Other
71+ } ;
72+
73+ var changeParts = change . Split ( ' ' , StringSplitOptions . RemoveEmptyEntries | StringSplitOptions . TrimEntries ) ;
74+
75+ yield return changeType switch
76+ {
77+ GitChangeType . Renamed => new RenamedGitChange ( changeParts [ 1 ] , changeParts [ 3 ] , changeType ) ,
78+ _ => new GitChange ( changeParts [ 1 ] , changeType )
79+ } ;
80+ }
81+ }
3782}
0 commit comments