1
1
--- @class CodeCompanion.GitCommit.Git
2
2
local Git = {}
3
3
4
+ -- 存储配置
5
+ local config = {}
6
+
7
+ --- Setup Git module with configuration
8
+ --- @param opts ? table Configuration options
9
+ function Git .setup (opts )
10
+ config = vim .tbl_deep_extend (" force" , {
11
+ exclude_files = {},
12
+ }, opts or {})
13
+ end
14
+
15
+ --- Filter diff content to exclude specified file patterns
16
+ --- @param diff_content string The original diff content
17
+ --- @return string filtered_diff The filtered diff content
18
+ function Git ._filter_diff (diff_content )
19
+ if not config .exclude_files or # config .exclude_files == 0 then
20
+ return diff_content
21
+ end
22
+
23
+ local lines = vim .split (diff_content , " \n " )
24
+ local filtered_lines = {}
25
+ local current_file = nil
26
+ local skip_current_file = false
27
+
28
+ for _ , line in ipairs (lines ) do
29
+ -- Check for file header (diff --git a/file b/file)
30
+ local file_match = line :match (" ^diff %-%-git a/(.*) b/" )
31
+ if file_match then
32
+ current_file = file_match
33
+ skip_current_file = Git ._should_exclude_file (current_file )
34
+ end
35
+
36
+ -- Check for traditional diff format (+++ b/file, --- a/file)
37
+ local plus_file = line :match (" ^%+%+%+ b/(.*)" )
38
+ local minus_file = line :match (" ^%-%-%-a/(.*)" )
39
+ if plus_file then
40
+ current_file = plus_file
41
+ skip_current_file = Git ._should_exclude_file (current_file )
42
+ elseif minus_file then
43
+ current_file = minus_file
44
+ skip_current_file = Git ._should_exclude_file (current_file )
45
+ end
46
+
47
+ -- Only include line if we're not skipping current file
48
+ if not skip_current_file then
49
+ table.insert (filtered_lines , line )
50
+ end
51
+ end
52
+
53
+ return table.concat (filtered_lines , " \n " )
54
+ end
55
+
56
+ --- Check if file should be excluded based on patterns
57
+ --- @param filepath string The file path to check
58
+ --- @return boolean should_exclude True if file should be excluded
59
+ function Git ._should_exclude_file (filepath )
60
+ if not config .exclude_files then
61
+ return false
62
+ end
63
+
64
+ for _ , pattern in ipairs (config .exclude_files ) do
65
+ -- Convert glob pattern to Lua pattern
66
+ local lua_pattern = pattern :gsub (" %*" , " .*" ):gsub (" ?" , " ." )
67
+ if filepath :match (lua_pattern ) then
68
+ return true
69
+ end
70
+ end
71
+
72
+ return false
73
+ end
74
+
4
75
--- Check if current directory is inside a git repository
5
76
--- @return boolean
6
77
function Git .is_repository ()
@@ -68,20 +139,20 @@ function Git.get_staged_diff()
68
139
-- First try to get staged changes
69
140
local staged_diff = vim .fn .system (" git diff --no-ext-diff --staged" )
70
141
if vim .v .shell_error == 0 and vim .trim (staged_diff ) ~= " " then
71
- return staged_diff
142
+ return Git . _filter_diff ( staged_diff )
72
143
end
73
144
74
145
-- If no staged changes and we're in amend mode, get the last commit's changes
75
146
if Git .is_amending () then
76
147
local last_commit_diff = vim .fn .system (" git diff --no-ext-diff HEAD~1" )
77
148
if vim .v .shell_error == 0 and vim .trim (last_commit_diff ) ~= " " then
78
- return last_commit_diff
149
+ return Git . _filter_diff ( last_commit_diff )
79
150
end
80
151
81
152
-- Fallback: if HEAD~1 doesn't exist (initial commit), show all files
82
153
local show_diff = vim .fn .system (" git show --no-ext-diff --format= HEAD" )
83
154
if vim .v .shell_error == 0 and vim .trim (show_diff ) ~= " " then
84
- return show_diff
155
+ return Git . _filter_diff ( show_diff )
85
156
end
86
157
end
87
158
@@ -99,21 +170,32 @@ function Git.get_contextual_diff()
99
170
-- Check for staged changes first
100
171
local staged_diff = vim .fn .system (" git diff --no-ext-diff --staged" )
101
172
if vim .v .shell_error == 0 and vim .trim (staged_diff ) ~= " " then
102
- return staged_diff , " staged"
173
+ local filtered_diff = Git ._filter_diff (staged_diff )
174
+ if vim .trim (filtered_diff ) ~= " " then
175
+ return filtered_diff , " staged"
176
+ else
177
+ return nil , " no_changes_after_filter"
178
+ end
103
179
end
104
180
105
181
-- Check if we're amending
106
182
if Git .is_amending () then
107
183
-- Try to get the last commit's diff
108
184
local last_commit_diff = vim .fn .system (" git diff --no-ext-diff HEAD~1" )
109
185
if vim .v .shell_error == 0 and vim .trim (last_commit_diff ) ~= " " then
110
- return last_commit_diff , " amend_with_parent"
186
+ local filtered_diff = Git ._filter_diff (last_commit_diff )
187
+ if vim .trim (filtered_diff ) ~= " " then
188
+ return filtered_diff , " amend_with_parent"
189
+ end
111
190
end
112
191
113
192
-- Fallback for initial commit amend
114
193
local show_diff = vim .fn .system (" git show --no-ext-diff --format= HEAD" )
115
194
if vim .v .shell_error == 0 and vim .trim (show_diff ) ~= " " then
116
- return show_diff , " amend_initial"
195
+ local filtered_diff = Git ._filter_diff (show_diff )
196
+ if vim .trim (filtered_diff ) ~= " " then
197
+ return filtered_diff , " amend_initial"
198
+ end
117
199
end
118
200
end
119
201
0 commit comments