@@ -22,63 +22,106 @@ func IsRepository(path string) bool {
2222 return strings .TrimSpace (string (output )) == "true"
2323}
2424
25- // filterBinaryFiles filters out binary files from git diff --name-status output
26- func filterBinaryFiles (nameStatusOutput string ) string {
27- if nameStatusOutput == "" {
28- return ""
25+ // parseGitStatusLine represents a parsed git status line
26+ type parseGitStatusLine struct {
27+ status string
28+ filenames []string
29+ }
30+
31+ // parseGitNameStatus parses a single line from git diff --name-status output
32+ // Handles various git status codes including rename (R) and copy (C) operations
33+ func parseGitNameStatus (line string ) parseGitStatusLine {
34+ if line == "" {
35+ return parseGitStatusLine {}
2936 }
3037
31- lines := strings .Split (strings .TrimSpace (nameStatusOutput ), "\n " )
32- var filteredLines []string
38+ parts := strings .Fields (line )
39+ if len (parts ) < 2 {
40+ return parseGitStatusLine {}
41+ }
3342
34- for _ , line := range lines {
35- if line == "" {
36- continue
37- }
38-
39- // Parse git diff --name-status format (e.g., "M filename" or "A filename")
40- parts := strings .Fields (line )
41- if len (parts ) >= 2 {
42- filename := strings .Join (parts [1 :], " " ) // Handle filenames with spaces
43- if ! utils .IsBinaryFile (filename ) {
44- filteredLines = append (filteredLines , line )
43+ status := parts [0 ]
44+
45+ // Handle rename/copy status codes (e.g., "R100", "C75")
46+ if len (status ) > 1 && (status [0 ] == 'R' || status [0 ] == 'C' ) {
47+ // For rename/copy, we expect: "R100 oldname newname" or "C75 oldname newname"
48+ if len (parts ) >= 3 {
49+ // For renames/copies, both old and new filenames need to be checked
50+ oldFile := parts [1 ]
51+ newFile := strings .Join (parts [2 :], " " ) // Handle spaces in new filename
52+ return parseGitStatusLine {
53+ status : status ,
54+ filenames : []string {oldFile , newFile },
4555 }
4656 }
4757 }
4858
49- if len (filteredLines ) == 0 {
50- return ""
59+ // Handle regular status codes (M, A, D, etc.)
60+ filename := strings .Join (parts [1 :], " " ) // Handle filenames with spaces
61+ return parseGitStatusLine {
62+ status : status ,
63+ filenames : []string {filename },
5164 }
52-
53- return strings .Join (filteredLines , "\n " )
5465}
5566
56- // extractNonBinaryFiles extracts non-binary filenames from git diff --name-status output
57- func extractNonBinaryFiles (nameStatusOutput string ) []string {
67+ // processGitStatusOutput processes git diff --name-status output and returns filtered results
68+ func processGitStatusOutput (nameStatusOutput string , returnFilenames bool ) ( []string , [] string ) {
5869 if nameStatusOutput == "" {
59- return nil
70+ return nil , nil
6071 }
6172
6273 lines := strings .Split (strings .TrimSpace (nameStatusOutput ), "\n " )
74+ var filteredLines []string
6375 var nonBinaryFiles []string
6476
6577 for _ , line := range lines {
6678 if line == "" {
6779 continue
6880 }
6981
70- // Parse git diff --name-status format (e.g., "M filename" or "A filename")
71- parts := strings .Fields (line )
72- if len (parts ) >= 2 {
73- filename := strings .Join (parts [1 :], " " ) // Handle filenames with spaces
74- if ! utils .IsBinaryFile (filename ) {
75- nonBinaryFiles = append (nonBinaryFiles , filename )
82+ parsed := parseGitNameStatus (line )
83+ if len (parsed .filenames ) == 0 {
84+ continue
85+ }
86+
87+ // Check if any of the filenames are binary
88+ hasBinaryFile := false
89+ for _ , filename := range parsed .filenames {
90+ if utils .IsBinaryFile (filename ) {
91+ hasBinaryFile = true
92+ break
93+ }
94+ }
95+
96+ // If no binary files found, include this line/files
97+ if ! hasBinaryFile {
98+ filteredLines = append (filteredLines , line )
99+ if returnFilenames {
100+ nonBinaryFiles = append (nonBinaryFiles , parsed .filenames ... )
76101 }
77102 }
78103 }
79104
105+ return filteredLines , nonBinaryFiles
106+ }
107+
108+ // filterBinaryFiles filters out binary files from git diff --name-status output
109+ func filterBinaryFiles (nameStatusOutput string ) string {
110+ filteredLines , _ := processGitStatusOutput (nameStatusOutput , false )
111+
112+ if len (filteredLines ) == 0 {
113+ return ""
114+ }
115+
116+ return strings .Join (filteredLines , "\n " )
117+ }
118+
119+ // extractNonBinaryFiles extracts non-binary filenames from git diff --name-status output
120+ func extractNonBinaryFiles (nameStatusOutput string ) []string {
121+ _ , nonBinaryFiles := processGitStatusOutput (nameStatusOutput , true )
80122 return nonBinaryFiles
81123}
124+ }
82125
83126// GetChanges retrieves all Git changes including staged, unstaged, and untracked files
84127func GetChanges (config * types.RepoConfig ) (string , error ) {
0 commit comments