@@ -90,4 +90,109 @@ func TruncateDiff(diff string, maxChars int) string {
9090 return diff
9191 }
9292 return diff [:maxChars ] + "\n ... (diff truncated)"
93+ }
94+
95+ type FileGroup struct {
96+ Files []string
97+ Diff string
98+ Insertions int
99+ Deletions int
100+ }
101+
102+ func GroupStagedFiles (diff * DiffInfo ) []FileGroup {
103+ groups := make (map [string ][]string )
104+
105+ for _ , file := range diff .StagedFiles {
106+ category := categorizeFile (file )
107+ groups [category ] = append (groups [category ], file )
108+ }
109+
110+ if len (groups ) <= 1 {
111+ return []FileGroup {
112+ {
113+ Files : diff .StagedFiles ,
114+ Diff : diff .Diff ,
115+ Insertions : diff .Insertions ,
116+ Deletions : diff .Deletions ,
117+ },
118+ }
119+ }
120+
121+ result := []FileGroup {}
122+ for _ , files := range groups {
123+ result = append (result , FileGroup {
124+ Files : files ,
125+ })
126+ }
127+ return result
128+ }
129+
130+ func categorizeFile (file string ) string {
131+ lower := strings .ToLower (file )
132+
133+ switch {
134+ case strings .Contains (lower , "auth" ) ||
135+ strings .Contains (lower , "login" ) ||
136+ strings .Contains (lower , "jwt" ) ||
137+ strings .Contains (lower , "session" ):
138+ return "auth"
139+
140+ case strings .Contains (lower , "test" ) ||
141+ strings .Contains (lower , "_test.go" ) ||
142+ strings .Contains (lower , "spec" ):
143+ return "tests"
144+
145+ case strings .Contains (lower , "readme" ) ||
146+ strings .Contains (lower , ".md" ) ||
147+ strings .Contains (lower , "doc" ):
148+ return "docs"
149+
150+ case strings .Contains (lower , "docker" ) ||
151+ strings .Contains (lower , "ci" ) ||
152+ strings .Contains (lower , "yml" ) ||
153+ strings .Contains (lower , "yaml" ) ||
154+ strings .Contains (lower , "makefile" ):
155+ return "config"
156+
157+ case strings .Contains (lower , "ui" ) ||
158+ strings .Contains (lower , "component" ) ||
159+ strings .Contains (lower , "style" ) ||
160+ strings .Contains (lower , "css" ) ||
161+ strings .Contains (lower , "html" ):
162+ return "ui"
163+
164+ case strings .Contains (lower , "db" ) ||
165+ strings .Contains (lower , "database" ) ||
166+ strings .Contains (lower , "migration" ) ||
167+ strings .Contains (lower , "schema" ):
168+ return "database"
169+
170+ case strings .Contains (lower , "api" ) ||
171+ strings .Contains (lower , "route" ) ||
172+ strings .Contains (lower , "handler" ) ||
173+ strings .Contains (lower , "controller" ):
174+ return "api"
175+
176+ default :
177+ return "general"
178+ }
179+ }
180+
181+ func GetFileDiff (file string ) string {
182+ out , err := exec .Command (
183+ "git" , "diff" , "--cached" , "--" , file ,
184+ ).Output ()
185+ if err != nil {
186+ return ""
187+ }
188+ return string (out )
189+ }
190+
191+ func StageFiles (files []string ) error {
192+ args := append ([]string {"add" }, files ... )
193+ out , err := exec .Command ("git" , args ... ).CombinedOutput ()
194+ if err != nil {
195+ return fmt .Errorf ("failed to stage files: %s" , string (out ))
196+ }
197+ return nil
93198}
0 commit comments