git_auto 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +22 -3
- data/exe/git-auto +7 -0
- data/lib/git_auto/commands/commit_message_command.rb +34 -26
- data/lib/git_auto/commands/config_command.rb +11 -2
- data/lib/git_auto/config/settings.rb +5 -0
- data/lib/git_auto/services/ai_service.rb +129 -80
- data/lib/git_auto/services/git_service.rb +7 -2
- data/lib/git_auto/validators/commit_message_validator.rb +16 -7
- data/lib/git_auto/version.rb +1 -1
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ca7a9199ac933b3d076abc6bcd1f82c5cc096a1c95604294aca7fd15dcccd05c
|
4
|
+
data.tar.gz: 128c56d3c6bee577a8f152c22f101b98f597524fc40b3cae42d5f63baf463e23
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9fa153d36b6081843dd3966c3835faa674c78ac3d742f3bce2e72c94bf388196096112531ca1df2abdc3c7e2cce70d6930c4af0c7e5cce73d8176dc4f7a23898
|
7
|
+
data.tar.gz: c10bf42f067af9a7947cd42c34b94928fccd1f2410d1349e81117182b6dbdd13f14e9bded9ae8725a02d5aa673ae89f1e82524d0f72ec52d12fa1c401bb25901
|
data/CHANGELOG.md
CHANGED
@@ -5,14 +5,33 @@ All notable changes to this project will be documented in this file.
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
7
|
|
8
|
-
## [0.2.
|
8
|
+
## [0.2.2] - 2025-03-22
|
9
9
|
|
10
10
|
### Fixed
|
11
|
+
- Fixed API key storage in credential store when using `config set` command
|
12
|
+
- Fixed commit message validation to properly handle different styles (conventional, minimal, simple, detailed)
|
13
|
+
- Extended conventional commit scope pattern to allow dots in file names (e.g., `index.js`)
|
14
|
+
- Improved AI prompts to consistently generate lowercase commit messages
|
15
|
+
|
16
|
+
### Added
|
17
|
+
- Enhanced detailed commit style to include multi-line messages with:
|
18
|
+
- Concise summary line
|
19
|
+
- Detailed bullet points explaining changes
|
20
|
+
- Technical context and reasoning
|
21
|
+
|
22
|
+
## [0.2.1] - 2024-12-19
|
23
|
+
|
24
|
+
### Fixed
|
25
|
+
- Improve Claude AI response handling for conventional commit messages
|
26
|
+
- Make system prompts more explicit to ensure consistent output format
|
11
27
|
- Fixed error when displaying repository status with no staged files
|
12
28
|
- Improved error handling in repository status display
|
13
|
-
- Simplified status output when no changes are staged
|
14
29
|
|
15
|
-
|
30
|
+
### Changed
|
31
|
+
- Update system prompts to be more strict and specific
|
32
|
+
- Enhance commit message validation for Claude responses
|
33
|
+
|
34
|
+
## [0.2.0] - 2024-12-15
|
16
35
|
|
17
36
|
### Added
|
18
37
|
- Support for multiple AI providers (OpenAI and Anthropic)
|
data/exe/git-auto
ADDED
@@ -19,6 +19,7 @@ module GitAuto
|
|
19
19
|
@git_service = Services::GitService.new
|
20
20
|
@ai_service = Services::AIService.new(@settings)
|
21
21
|
@history_service = Services::HistoryService.new
|
22
|
+
@validator = Validators::CommitMessageValidator.new(get_commit_style)
|
22
23
|
@retry_count = 0
|
23
24
|
end
|
24
25
|
|
@@ -27,8 +28,11 @@ module GitAuto
|
|
27
28
|
status = @git_service.repository_status
|
28
29
|
validate_repository(status)
|
29
30
|
|
31
|
+
# Get staged files
|
32
|
+
staged_files = @git_service.get_staged_files
|
33
|
+
|
30
34
|
# Get and validate changes
|
31
|
-
diff = @git_service.get_staged_diff
|
35
|
+
diff = @git_service.get_staged_diff(staged_files)
|
32
36
|
validate_changes(diff)
|
33
37
|
|
34
38
|
# Show diff preview if requested
|
@@ -112,6 +116,24 @@ module GitAuto
|
|
112
116
|
message
|
113
117
|
end
|
114
118
|
|
119
|
+
# Message Validation Methods
|
120
|
+
def validate_message(message)
|
121
|
+
result = @validator.validate(message)
|
122
|
+
|
123
|
+
if result[:errors].any?
|
124
|
+
puts "\n❌ Validation errors:".red
|
125
|
+
result[:errors].each { |error| puts @validator.format_error(error) }
|
126
|
+
end
|
127
|
+
|
128
|
+
if result[:warnings].any?
|
129
|
+
puts "\n⚠️ Suggestions:".yellow
|
130
|
+
result[:warnings].each { |warning| puts @validator.format_warning(warning) }
|
131
|
+
end
|
132
|
+
|
133
|
+
puts "\nPlease edit the message to fix these errors." if result[:errors].any?
|
134
|
+
result
|
135
|
+
end
|
136
|
+
|
115
137
|
# Message Handling Methods
|
116
138
|
def handle_message(message, diff)
|
117
139
|
formatted = Formatters::MessageFormatter.new.format(message)
|
@@ -124,37 +146,23 @@ module GitAuto
|
|
124
146
|
end
|
125
147
|
end
|
126
148
|
|
127
|
-
def validate_message(message)
|
128
|
-
validator = Validators::CommitMessageValidator.new
|
129
|
-
validator.validate(message)
|
130
|
-
end
|
131
|
-
|
132
149
|
def display_message_and_validation(formatted_message, validation)
|
133
|
-
|
134
|
-
model = @settings.get(:ai_model)
|
135
|
-
model_info = "(#{provider}/#{model})".light_black
|
136
|
-
|
137
|
-
puts "\n📝 Generated commit message #{model_info}:".blue
|
150
|
+
puts "\n📝 Generated commit message (#{@settings.get(:ai_provider)}/#{@settings.get(:ai_model)}):".blue
|
138
151
|
puts formatted_message
|
139
152
|
|
140
|
-
|
153
|
+
return unless validation[:errors].any? || validation[:warnings].any?
|
141
154
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
155
|
+
if validation[:errors].any?
|
156
|
+
puts "\n❌ Validation errors:".red
|
157
|
+
validation[:errors].each { |error| puts @validator.format_error(error) }
|
158
|
+
end
|
146
159
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
puts "\nPlease edit the message to fix these errors.".yellow
|
152
|
-
end
|
160
|
+
if validation[:warnings].any?
|
161
|
+
puts "\n⚠️ Suggestions:".yellow
|
162
|
+
validation[:warnings].each { |warning| puts @validator.format_warning(warning) }
|
163
|
+
end
|
153
164
|
|
154
|
-
|
155
|
-
puts "\n⚠️ Suggestions:".yellow
|
156
|
-
validator = Validators::CommitMessageValidator.new
|
157
|
-
warnings.each { |warning| puts validator.format_warning(warning) }
|
165
|
+
puts "\nPlease edit the message to fix these errors." if validation[:errors].any?
|
158
166
|
end
|
159
167
|
|
160
168
|
def prompt_user_action
|
@@ -58,8 +58,17 @@ module GitAuto
|
|
58
58
|
exit 1
|
59
59
|
end
|
60
60
|
|
61
|
-
|
62
|
-
|
61
|
+
case key.to_s
|
62
|
+
when "openai_api_key"
|
63
|
+
@credential_store.store_api_key(value, "openai")
|
64
|
+
puts "✓ OpenAI API key updated".green
|
65
|
+
when "claude_api_key"
|
66
|
+
@credential_store.store_api_key(value, "claude")
|
67
|
+
puts "✓ Claude API key updated".green
|
68
|
+
else
|
69
|
+
@settings.set(key.to_sym, value)
|
70
|
+
puts "✓ Setting '#{key}' updated to '#{value}'".green
|
71
|
+
end
|
63
72
|
end
|
64
73
|
|
65
74
|
def interactive_config
|
@@ -39,10 +39,13 @@ module GitAuto
|
|
39
39
|
@@temperature ||= TEMPERATURE_VARIATIONS[0]
|
40
40
|
@request_count = 0
|
41
41
|
@previous_suggestions = []
|
42
|
+
@debug_mode = ENV["GIT_AUTO_DEBUG"] == "true"
|
42
43
|
end
|
43
44
|
|
44
45
|
def log_api_request(provider, payload, temperature)
|
45
|
-
|
46
|
+
return unless @debug_mode
|
47
|
+
|
48
|
+
puts "\n=== API Request ##{@request_count += 1} ===".yellow
|
46
49
|
puts "Provider: #{provider}"
|
47
50
|
puts "Temperature: #{temperature}"
|
48
51
|
puts "Full Payload:"
|
@@ -51,7 +54,9 @@ module GitAuto
|
|
51
54
|
end
|
52
55
|
|
53
56
|
def log_api_response(response_body)
|
54
|
-
|
57
|
+
return unless @debug_mode
|
58
|
+
|
59
|
+
puts "\n=== API Response ===".yellow
|
55
60
|
puts JSON.pretty_generate(JSON.parse(response_body.to_s))
|
56
61
|
puts "===================="
|
57
62
|
end
|
@@ -73,14 +78,45 @@ module GitAuto
|
|
73
78
|
"1. ALWAYS start with a type from the list above\n" \
|
74
79
|
"2. NEVER include a scope\n" \
|
75
80
|
"3. Keep the message under 72 characters\n" \
|
76
|
-
"4.
|
81
|
+
"4. ALWAYS use lowercase - this is mandatory\n" \
|
77
82
|
"5. Use present tense\n" \
|
78
83
|
"6. Be descriptive but concise\n" \
|
79
84
|
"7. Do not include a period at the end"
|
80
85
|
when "conventional"
|
81
|
-
"You are an expert in writing conventional commit messages
|
86
|
+
"You are an expert in writing conventional commit messages that follow the format: <type>(<scope>): <description>\n" \
|
87
|
+
"Rules:\n" \
|
88
|
+
"1. ALWAYS start with a type from the list above\n" \
|
89
|
+
"2. Include a scope in parentheses when relevant\n" \
|
90
|
+
"3. Keep the message under 72 characters\n" \
|
91
|
+
"4. ALWAYS use lowercase - this is mandatory\n" \
|
92
|
+
"5. Use present tense\n" \
|
93
|
+
"6. Be descriptive but concise\n" \
|
94
|
+
"7. Do not include a period at the end"
|
95
|
+
when "detailed"
|
96
|
+
"You are an expert in writing detailed commit messages. Your message MUST follow this format:\n" \
|
97
|
+
"<summary line>\n" \
|
98
|
+
"\n" \
|
99
|
+
"<detailed description>\n" \
|
100
|
+
"\n" \
|
101
|
+
"Rules:\n" \
|
102
|
+
"1. First line is a summary under 72 characters\n" \
|
103
|
+
"2. ALWAYS use lowercase - this is mandatory\n" \
|
104
|
+
"3. ALWAYS include a blank line after the summary\n" \
|
105
|
+
"4. ALWAYS include a detailed description explaining:\n" \
|
106
|
+
" - What changes were made\n" \
|
107
|
+
" - Why the changes were necessary\n" \
|
108
|
+
" - Any technical details worth noting\n" \
|
109
|
+
"5. Use bullet points for multiple changes\n" \
|
110
|
+
"6. Use present tense\n" \
|
111
|
+
"7. You can use periods in the detailed description"
|
82
112
|
else
|
83
|
-
"You are an expert in writing clear and concise git commit messages
|
113
|
+
"You are an expert in writing clear and concise git commit messages.\n" \
|
114
|
+
"Rules:\n" \
|
115
|
+
"1. Keep the message under 72 characters\n" \
|
116
|
+
"2. ALWAYS use lowercase - this is mandatory\n" \
|
117
|
+
"3. Use present tense\n" \
|
118
|
+
"4. Be descriptive but concise\n" \
|
119
|
+
"5. Do not include a period at the end"
|
84
120
|
end
|
85
121
|
|
86
122
|
# Add variation for retries
|
@@ -115,51 +151,17 @@ module GitAuto
|
|
115
151
|
end
|
116
152
|
|
117
153
|
def generate_commit_message(diff, style: :conventional, scope: nil)
|
118
|
-
raise EmptyDiffError
|
154
|
+
raise EmptyDiffError, "No changes to commit" if diff.empty?
|
119
155
|
|
120
156
|
# If diff is too large, use the summarized version
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
message = case @settings.get(:ai_provider)
|
125
|
-
when "openai"
|
126
|
-
generate_openai_commit_message(diff, style)
|
127
|
-
when "claude"
|
128
|
-
generate_claude_commit_message(diff, style)
|
129
|
-
end
|
130
|
-
|
131
|
-
# Extract type and description from the message
|
132
|
-
if message =~ /^(\w+):\s*(.+)$/
|
133
|
-
type = ::Regexp.last_match(1)
|
134
|
-
description = ::Regexp.last_match(2)
|
135
|
-
return "#{type}: #{description}"
|
136
|
-
end
|
137
|
-
|
138
|
-
return message
|
139
|
-
elsif style.to_s == "conventional" && scope.nil?
|
140
|
-
# Generate both scope and message in one call
|
141
|
-
message = case @settings.get(:ai_provider)
|
142
|
-
when "openai"
|
143
|
-
generate_openai_commit_message(diff, style)
|
144
|
-
when "claude"
|
145
|
-
generate_claude_commit_message(diff, style)
|
146
|
-
end
|
147
|
-
|
148
|
-
# Extract type and scope from the message
|
149
|
-
if message =~ /^(\w+)(?:\(([\w-]+)\))?:\s*(.+)$/
|
150
|
-
type = ::Regexp.last_match(1)
|
151
|
-
existing_scope = ::Regexp.last_match(2)
|
152
|
-
description = ::Regexp.last_match(3)
|
153
|
-
|
154
|
-
# If we got a scope in the message, use it, otherwise generate one
|
155
|
-
scope ||= existing_scope || infer_scope_from_diff(diff)
|
156
|
-
return scope ? "#{type}(#{scope}): #{description}" : "#{type}: #{description}"
|
157
|
-
end
|
158
|
-
|
159
|
-
# If message doesn't match expected format, just return it as is
|
160
|
-
return message
|
157
|
+
if diff.length > MAX_DIFF_SIZE
|
158
|
+
puts "\n⚠️ Diff is large, using summarized version...".yellow if @debug_mode
|
159
|
+
diff = @diff_summarizer.summarize(diff)
|
161
160
|
end
|
162
161
|
|
162
|
+
# Store the commit style in settings for use in handle_response
|
163
|
+
@settings.set(:commit_style, style.to_s)
|
164
|
+
|
163
165
|
retries = 0
|
164
166
|
begin
|
165
167
|
case @settings.get(:ai_provider)
|
@@ -211,7 +213,7 @@ module GitAuto
|
|
211
213
|
"1. ALWAYS start with a type from the list above\n" \
|
212
214
|
"2. NEVER include a scope\n" \
|
213
215
|
"3. Keep the message under 72 characters\n" \
|
214
|
-
"4.
|
216
|
+
"4. ALWAYS use lowercase - this is mandatory\n" \
|
215
217
|
"5. Use present tense\n" \
|
216
218
|
"6. Be descriptive but concise\n" \
|
217
219
|
"7. Do not include a period at the end"
|
@@ -221,14 +223,39 @@ module GitAuto
|
|
221
223
|
"2. Use format: <type>(<scope>): <description>\n" \
|
222
224
|
"3. Valid types are: #{commit_types}\n" \
|
223
225
|
"4. Keep under 72 characters\n" \
|
224
|
-
"5.
|
226
|
+
"5. ALWAYS use lowercase - this is mandatory\n" \
|
225
227
|
"6. Use present tense\n" \
|
226
228
|
"7. Be descriptive but concise\n" \
|
227
229
|
"8. No period at the end\n" \
|
228
230
|
"9. NO explanations or additional text\n" \
|
229
231
|
"10. NO markdown formatting"
|
232
|
+
when "detailed"
|
233
|
+
"You are a commit message generator that MUST follow this format EXACTLY:\n" \
|
234
|
+
"<summary line>\n" \
|
235
|
+
"\n" \
|
236
|
+
"<detailed description>\n" \
|
237
|
+
"\n" \
|
238
|
+
"Rules:\n" \
|
239
|
+
"1. First line is a summary under 72 characters\n" \
|
240
|
+
"2. ALWAYS use lowercase - this is mandatory\n" \
|
241
|
+
"3. ALWAYS include a blank line after the summary\n" \
|
242
|
+
"4. ALWAYS include a detailed description explaining:\n" \
|
243
|
+
" - What changes were made\n" \
|
244
|
+
" - Why the changes were necessary\n" \
|
245
|
+
" - Any technical details worth noting\n" \
|
246
|
+
"5. Use bullet points for multiple changes\n" \
|
247
|
+
"6. Use present tense\n" \
|
248
|
+
"7. You can use periods in the detailed description\n" \
|
249
|
+
"8. NO explanations or additional text\n" \
|
250
|
+
"9. NO markdown formatting"
|
230
251
|
else
|
231
|
-
"You are an expert in writing clear and concise git commit messages
|
252
|
+
"You are an expert in writing clear and concise git commit messages.\n" \
|
253
|
+
"Rules:\n" \
|
254
|
+
"1. Keep the message under 72 characters\n" \
|
255
|
+
"2. ALWAYS use lowercase - this is mandatory\n" \
|
256
|
+
"3. Use present tense\n" \
|
257
|
+
"4. Be descriptive but concise\n" \
|
258
|
+
"5. Do not include a period at the end"
|
232
259
|
end
|
233
260
|
|
234
261
|
user_message = if scope
|
@@ -246,13 +273,14 @@ module GitAuto
|
|
246
273
|
temperature: temperature
|
247
274
|
}
|
248
275
|
|
249
|
-
|
250
|
-
# log_api_request("openai", payload, temperature) if ENV["DEBUG"]
|
276
|
+
log_api_request("openai", payload, temperature) if @debug_mode
|
251
277
|
|
252
278
|
response = HTTP.auth("Bearer #{api_key}")
|
253
279
|
.headers(accept: "application/json")
|
254
280
|
.post(OPENAI_API_URL, json: payload)
|
255
281
|
|
282
|
+
log_api_response(response.body) if @debug_mode
|
283
|
+
|
256
284
|
handle_response(response)
|
257
285
|
end
|
258
286
|
|
@@ -273,7 +301,7 @@ module GitAuto
|
|
273
301
|
"1. ALWAYS start with a type from the list above\n" \
|
274
302
|
"2. NEVER include a scope\n" \
|
275
303
|
"3. Keep the message under 72 characters\n" \
|
276
|
-
"4.
|
304
|
+
"4. ALWAYS use lowercase - this is mandatory\n" \
|
277
305
|
"5. Use present tense\n" \
|
278
306
|
"6. Be descriptive but concise\n" \
|
279
307
|
"7. Do not include a period at the end"
|
@@ -283,14 +311,39 @@ module GitAuto
|
|
283
311
|
"2. Use format: <type>(<scope>): <description>\n" \
|
284
312
|
"3. Valid types are: #{commit_types}\n" \
|
285
313
|
"4. Keep under 72 characters\n" \
|
286
|
-
"5.
|
314
|
+
"5. ALWAYS use lowercase - this is mandatory\n" \
|
287
315
|
"6. Use present tense\n" \
|
288
316
|
"7. Be descriptive but concise\n" \
|
289
317
|
"8. No period at the end\n" \
|
290
318
|
"9. NO explanations or additional text\n" \
|
291
319
|
"10. NO markdown formatting"
|
320
|
+
when "detailed"
|
321
|
+
"You are a commit message generator that MUST follow this format EXACTLY:\n" \
|
322
|
+
"<summary line>\n" \
|
323
|
+
"\n" \
|
324
|
+
"<detailed description>\n" \
|
325
|
+
"\n" \
|
326
|
+
"Rules:\n" \
|
327
|
+
"1. First line is a summary under 72 characters\n" \
|
328
|
+
"2. ALWAYS use lowercase - this is mandatory\n" \
|
329
|
+
"3. ALWAYS include a blank line after the summary\n" \
|
330
|
+
"4. ALWAYS include a detailed description explaining:\n" \
|
331
|
+
" - What changes were made\n" \
|
332
|
+
" - Why the changes were necessary\n" \
|
333
|
+
" - Any technical details worth noting\n" \
|
334
|
+
"5. Use bullet points for multiple changes\n" \
|
335
|
+
"6. Use present tense\n" \
|
336
|
+
"7. You can use periods in the detailed description\n" \
|
337
|
+
"8. NO explanations or additional text\n" \
|
338
|
+
"9. NO markdown formatting"
|
292
339
|
else
|
293
|
-
"You are an expert in writing clear and concise git commit messages
|
340
|
+
"You are an expert in writing clear and concise git commit messages.\n" \
|
341
|
+
"Rules:\n" \
|
342
|
+
"1. Keep the message under 72 characters\n" \
|
343
|
+
"2. ALWAYS use lowercase - this is mandatory\n" \
|
344
|
+
"3. Use present tense\n" \
|
345
|
+
"4. Be descriptive but concise\n" \
|
346
|
+
"5. Do not include a period at the end"
|
294
347
|
end
|
295
348
|
|
296
349
|
user_message = if scope
|
@@ -319,16 +372,16 @@ module GitAuto
|
|
319
372
|
]
|
320
373
|
}
|
321
374
|
|
322
|
-
|
323
|
-
|
324
|
-
# log_api_response(response.body)
|
325
|
-
|
375
|
+
log_api_request("claude", payload, temperature) if @debug_mode
|
376
|
+
|
326
377
|
response = HTTP.headers({
|
327
378
|
"Content-Type" => "application/json",
|
328
379
|
"x-api-key" => api_key,
|
329
380
|
"anthropic-version" => "2023-06-01"
|
330
381
|
}).post(CLAUDE_API_URL, json: payload)
|
331
382
|
|
383
|
+
log_api_response(response.body) if @debug_mode
|
384
|
+
|
332
385
|
message = handle_response(response)
|
333
386
|
message = message.downcase.strip
|
334
387
|
message = message.sub(/\.$/, "") # Remove trailing period if present
|
@@ -346,6 +399,8 @@ module GitAuto
|
|
346
399
|
"commit scope suggestion"
|
347
400
|
when :minimal, "minimal"
|
348
401
|
"minimal commit message"
|
402
|
+
when :detailed, "detailed"
|
403
|
+
"detailed commit message"
|
349
404
|
else
|
350
405
|
"commit message"
|
351
406
|
end
|
@@ -355,38 +410,32 @@ module GitAuto
|
|
355
410
|
case response.code
|
356
411
|
when 200
|
357
412
|
json = JSON.parse(response.body.to_s)
|
358
|
-
puts "\nDebug - API Response: #{json.inspect}"
|
359
413
|
|
360
414
|
case @settings.get(:ai_provider)
|
361
415
|
when "openai"
|
362
416
|
message = json.dig("choices", 0, "message", "content")
|
363
|
-
if message.nil? || message.empty?
|
364
|
-
puts "Debug - No content in response: #{json}"
|
365
|
-
raise Error, "No message content in response"
|
366
|
-
end
|
417
|
+
raise Error, "No message content in response" if message.nil? || message.empty?
|
367
418
|
|
368
|
-
|
369
|
-
|
419
|
+
# For detailed style, keep the full message
|
420
|
+
if @settings.get(:commit_style) == "detailed"
|
421
|
+
message.strip
|
422
|
+
else
|
423
|
+
message.split("\n").first.strip
|
424
|
+
end
|
370
425
|
|
371
426
|
when "claude"
|
372
427
|
content = json.dig("content", 0, "text")
|
373
|
-
|
374
|
-
|
375
|
-
if content.nil? || content.empty?
|
376
|
-
puts "Debug - No content in response: #{json}"
|
377
|
-
raise Error, "No message content in response"
|
378
|
-
end
|
379
|
-
|
380
|
-
# Extract the first actual commit message from the response
|
381
|
-
commit_message = content.scan(/(?:feat|fix|docs|style|refactor|test|chore|perf|ci|build|revert)(?:\([^)]+\))?:.*/)&.first
|
428
|
+
raise Error, "No message content in response" if content.nil? || content.empty?
|
382
429
|
|
383
|
-
|
384
|
-
|
385
|
-
|
430
|
+
# For detailed style, keep the full message
|
431
|
+
if @settings.get(:commit_style) == "detailed"
|
432
|
+
content.strip
|
433
|
+
else
|
434
|
+
# Extract the first actual commit message from the response
|
435
|
+
commit_message = content.scan(/(?:feat|fix|docs|style|refactor|test|chore|perf|ci|build|revert)(?:\([^)]+\))?:.*/)&.first
|
436
|
+
raise Error, "No valid commit message found in response" if commit_message.nil?
|
437
|
+
commit_message.strip
|
386
438
|
end
|
387
|
-
|
388
|
-
puts "Debug - Extracted commit message: #{commit_message}"
|
389
|
-
commit_message.strip
|
390
439
|
end
|
391
440
|
when 401
|
392
441
|
raise APIKeyError, "Invalid API key" unless ENV["RACK_ENV"] == "test"
|
@@ -7,9 +7,14 @@ module GitAuto
|
|
7
7
|
class GitService
|
8
8
|
class Error < StandardError; end
|
9
9
|
|
10
|
-
def get_staged_diff
|
10
|
+
def get_staged_diff(files = nil)
|
11
11
|
validate_git_repository!
|
12
|
-
|
12
|
+
if files
|
13
|
+
files = [files] unless files.is_a?(Array)
|
14
|
+
execute_git_command("diff", "--cached", "--", *files)
|
15
|
+
else
|
16
|
+
execute_git_command("diff", "--cached")
|
17
|
+
end
|
13
18
|
end
|
14
19
|
|
15
20
|
def get_staged_files
|
@@ -28,11 +28,15 @@ module GitAuto
|
|
28
28
|
|
29
29
|
CONVENTIONAL_COMMIT_PATTERN = %r{
|
30
30
|
^(?<type>#{TYPES.keys.join("|")}) # Commit type
|
31
|
-
(\((?<scope>[a-z0-9/_
|
31
|
+
(\((?<scope>[a-z0-9/_\.-]+)\))? # Optional scope in parentheses
|
32
32
|
:\s # Colon and space separator
|
33
33
|
(?<description>.+) # Commit description
|
34
34
|
}x
|
35
35
|
|
36
|
+
def initialize(style = "conventional")
|
37
|
+
@style = style.to_s
|
38
|
+
end
|
39
|
+
|
36
40
|
def validate(message)
|
37
41
|
errors = []
|
38
42
|
warnings = []
|
@@ -77,12 +81,17 @@ module GitAuto
|
|
77
81
|
|
78
82
|
errors << "Header exceeds #{HEADER_MAX_LENGTH} characters" if header.length > HEADER_MAX_LENGTH
|
79
83
|
|
80
|
-
# Validate header format
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
errors << "Header must follow
|
84
|
+
# Validate header format based on style
|
85
|
+
case @style
|
86
|
+
when "conventional"
|
87
|
+
errors << "Header must follow conventional format: <type>(<scope>): <description>" unless CONVENTIONAL_COMMIT_PATTERN.match?(header)
|
88
|
+
when "minimal"
|
89
|
+
errors << "Header must follow minimal format: <type>: <description>" unless MINIMAL_COMMIT_PATTERN.match?(header)
|
90
|
+
when "simple", "detailed"
|
91
|
+
# No specific format required for simple and detailed styles
|
92
|
+
else
|
93
|
+
# For unknown styles, suggest using conventional format
|
94
|
+
warnings << "Unknown style '#{@style}', consider using conventional format: <type>(<scope>): <description>"
|
86
95
|
end
|
87
96
|
|
88
97
|
# Suggest using lowercase for consistency
|
data/lib/git_auto/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: git_auto
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Guillermo Diaz
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-03-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -212,6 +212,7 @@ description: GitAuto streamlines your git workflow by automatically generating m
|
|
212
212
|
email:
|
213
213
|
- diazgdev@gmail.com
|
214
214
|
executables:
|
215
|
+
- git-auto
|
215
216
|
- git_auto
|
216
217
|
extensions: []
|
217
218
|
extra_rdoc_files: []
|
@@ -219,6 +220,7 @@ files:
|
|
219
220
|
- CHANGELOG.md
|
220
221
|
- LICENSE.txt
|
221
222
|
- README.md
|
223
|
+
- exe/git-auto
|
222
224
|
- exe/git_auto
|
223
225
|
- lib/git_auto.rb
|
224
226
|
- lib/git_auto/cli.rb
|
@@ -261,7 +263,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
261
263
|
- !ruby/object:Gem::Version
|
262
264
|
version: '0'
|
263
265
|
requirements: []
|
264
|
-
rubygems_version: 3.5.
|
266
|
+
rubygems_version: 3.5.22
|
265
267
|
signing_key:
|
266
268
|
specification_version: 4
|
267
269
|
summary: AI-powered git commit messages using OpenAI or Anthropic APIs
|