@@ -3,6 +3,7 @@ package analyzer
33import (
44 "bufio"
55 "path/filepath"
6+ "regexp"
67 "strings"
78
89 "gitmit/internal/config"
@@ -44,7 +45,7 @@ func NewAnalyzer(changes []*parser.Change, cfg *config.Config) *Analyzer {
4445}
4546
4647// AnalyzeChanges analyzes the git changes and returns a CommitMessage
47- func (a * Analyzer ) AnalyzeChanges (totalAdded , totalRemoved int ) * CommitMessage {
48+ func (a * Analyzer ) AnalyzeChanges (totalAdded , totalRemoved int , branchName string ) * CommitMessage {
4849 if len (a .changes ) == 0 {
4950 return nil
5051 }
@@ -141,6 +142,25 @@ func (a *Analyzer) AnalyzeChanges(totalAdded, totalRemoved int) *CommitMessage {
141142 }
142143 }
143144
145+ // NEW: Extract intent from branch name
146+ if branchName != "" {
147+ branchAction , branchScope := a .parseBranchName (branchName )
148+ if branchAction != "" {
149+ commitMessage .Action = branchAction
150+ }
151+ if branchScope != "" {
152+ commitMessage .Scope = branchScope
153+ }
154+ }
155+
156+ // NEW: Learning from recent commit history (Commit History Consistency)
157+ if historyScope := a .analyzeHistoryScopes (); historyScope != "" {
158+ // Only override if scope is empty or "core"
159+ if commitMessage .Scope == "" || commitMessage .Scope == "core" {
160+ commitMessage .Scope = historyScope
161+ }
162+ }
163+
144164 // Use commit history context to suggest consistent topics
145165 if commitMessage .Topic == "" || commitMessage .Topic == "core" {
146166 // Try to get topic from recent commit history
@@ -1151,3 +1171,91 @@ func (a *Analyzer) analyzeDiffStat(totalAdded, totalRemoved int) string {
11511171
11521172 return ""
11531173}
1174+
1175+ // parseBranchName extracts type and scope from branch name
1176+ func (a * Analyzer ) parseBranchName (branch string ) (string , string ) {
1177+ // Patterns like feature/auth-login or bugfix/fix-memleak
1178+ // Format: <type>/<scope>-<description> or <type>/<description>
1179+ parts := strings .Split (branch , "/" )
1180+ if len (parts ) < 2 {
1181+ return "" , ""
1182+ }
1183+
1184+ branchType := strings .ToLower (parts [0 ])
1185+ description := parts [1 ]
1186+
1187+ action := ""
1188+ switch branchType {
1189+ case "feature" , "feat" :
1190+ action = "feat"
1191+ case "bugfix" , "fix" :
1192+ action = "fix"
1193+ case "hotfix" :
1194+ action = "fix"
1195+ case "refactor" :
1196+ action = "refactor"
1197+ case "chore" :
1198+ action = "chore"
1199+ case "docs" :
1200+ action = "docs"
1201+ case "style" :
1202+ action = "style"
1203+ case "perf" :
1204+ action = "perf"
1205+ case "test" :
1206+ action = "test"
1207+ case "ci" :
1208+ action = "ci"
1209+ case "build" :
1210+ action = "build"
1211+ }
1212+
1213+ scope := ""
1214+ // Try to extract scope from description: scope-description or scope_description
1215+ descParts := regexp .MustCompile (`[-_]` ).Split (description , 2 )
1216+ if len (descParts ) > 1 {
1217+ scope = descParts [0 ]
1218+ } else if len (description ) > 0 {
1219+ // If it's just feature/auth, then auth is the scope
1220+ scope = description
1221+ }
1222+
1223+ return action , scope
1224+ }
1225+
1226+ // analyzeHistoryScopes analyzes the last 5 commits for common scopes
1227+ func (a * Analyzer ) analyzeHistoryScopes () string {
1228+ commits , err := history .GetRecentCommits (5 )
1229+ if err != nil || len (commits ) == 0 {
1230+ return ""
1231+ }
1232+ return a .calculateHistoryScope (commits )
1233+ }
1234+
1235+ // calculateHistoryScope calculates the most frequent scope from a list of commit messages
1236+ func (a * Analyzer ) calculateHistoryScope (commits []string ) string {
1237+ scopeCounts := make (map [string ]int )
1238+ re := regexp .MustCompile (`^[a-z]+\(([^)]+)\):` )
1239+
1240+ for _ , msg := range commits {
1241+ matches := re .FindStringSubmatch (msg )
1242+ if len (matches ) > 1 {
1243+ scope := matches [1 ]
1244+ scopeCounts [scope ]++
1245+ }
1246+ }
1247+
1248+ totalCommits := len (commits )
1249+ if totalCommits == 0 {
1250+ return ""
1251+ }
1252+
1253+ for scope , count := range scopeCounts {
1254+ // If a single scope appears in more than 50% of the commits
1255+ if float64 (count )/ float64 (totalCommits ) > 0.5 {
1256+ return scope
1257+ }
1258+ }
1259+
1260+ return ""
1261+ }
0 commit comments