Skip to content

Commit 28f05d8

Browse files
author
jinzhongjia
committed
feat(gitcommit): add support for excluding files from diff output
- implement file exclusion logic in Git module using glob patterns - add setup method to configure excluded files - update get_staged_diff and get_contextual_diff to filter diffs - pass exclude_files option from init setup - document exclude_files option in types
1 parent bab3b85 commit 28f05d8

File tree

3 files changed

+94
-6
lines changed

3 files changed

+94
-6
lines changed

lua/codecompanion/_extensions/gitcommit/git.lua

Lines changed: 88 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,77 @@
11
---@class CodeCompanion.GitCommit.Git
22
local Git = {}
33

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+
475
---Check if current directory is inside a git repository
576
---@return boolean
677
function Git.is_repository()
@@ -68,20 +139,20 @@ function Git.get_staged_diff()
68139
-- First try to get staged changes
69140
local staged_diff = vim.fn.system("git diff --no-ext-diff --staged")
70141
if vim.v.shell_error == 0 and vim.trim(staged_diff) ~= "" then
71-
return staged_diff
142+
return Git._filter_diff(staged_diff)
72143
end
73144

74145
-- If no staged changes and we're in amend mode, get the last commit's changes
75146
if Git.is_amending() then
76147
local last_commit_diff = vim.fn.system("git diff --no-ext-diff HEAD~1")
77148
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)
79150
end
80151

81152
-- Fallback: if HEAD~1 doesn't exist (initial commit), show all files
82153
local show_diff = vim.fn.system("git show --no-ext-diff --format= HEAD")
83154
if vim.v.shell_error == 0 and vim.trim(show_diff) ~= "" then
84-
return show_diff
155+
return Git._filter_diff(show_diff)
85156
end
86157
end
87158

@@ -99,21 +170,32 @@ function Git.get_contextual_diff()
99170
-- Check for staged changes first
100171
local staged_diff = vim.fn.system("git diff --no-ext-diff --staged")
101172
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
103179
end
104180

105181
-- Check if we're amending
106182
if Git.is_amending() then
107183
-- Try to get the last commit's diff
108184
local last_commit_diff = vim.fn.system("git diff --no-ext-diff HEAD~1")
109185
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
111190
end
112191

113192
-- Fallback for initial commit amend
114193
local show_diff = vim.fn.system("git show --no-ext-diff --format= HEAD")
115194
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
117199
end
118200
end
119201

lua/codecompanion/_extensions/gitcommit/init.lua

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ return {
5151
setup = function(opts)
5252
opts = opts or {}
5353

54+
-- Setup Git module with file exclusion configuration
55+
Git.setup({
56+
exclude_files = opts.exclude_files,
57+
})
58+
5459
-- Setup generator with adapter and model configuration
5560
Generator.setup(opts.adapter, opts.model)
5661

lua/codecompanion/_extensions/gitcommit/types.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
---@field adapter? string? The adapter to use for generation
1515
---@field model? string? The model of the adapter to use for generation
1616
---@field languages? string[] List of languages to use for generation
17+
---@field exclude_files? string[] List of file patterns to exclude from diff (supports glob patterns like "*.pb.go")
1718

1819
---@class CodeCompanion.GitCommit.Exports
1920
---@field generate fun(callback: fun(result: string|nil, error: string|nil)): nil

0 commit comments

Comments
 (0)