snakommit 0.1.1 → 0.1.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/.github/workflows/cd.yml +81 -0
- data/.github/workflows/ci.yml +73 -0
- data/.ruby-version +1 -0
- data/Gemfile.lock +12 -10
- data/README.md +32 -55
- data/Rakefile +10 -10
- data/lib/snakommit/cli.rb +43 -79
- data/lib/snakommit/config.rb +80 -108
- data/lib/snakommit/git.rb +1 -1
- data/lib/snakommit/hooks.rb +2 -3
- data/lib/snakommit/performance.rb +12 -84
- data/lib/snakommit/prompt.rb +218 -202
- data/lib/snakommit/templates.rb +1 -4
- data/lib/snakommit/version.rb +1 -1
- data/snakommit.gemspec +1 -1
- metadata +8 -9
- data/CHANGELOG.md +0 -55
data/lib/snakommit/prompt.rb
CHANGED
@@ -30,113 +30,122 @@ module Snakommit
|
|
30
30
|
def commit_flow
|
31
31
|
return { error: 'Not in a Git repository' } unless Git.in_repo?
|
32
32
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
unstaged: @git.unstaged_files,
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
if @tty_prompt.yes?("Would you like to use your previous file selections?", default: true)
|
71
|
-
# Stage the previously selected files
|
72
|
-
stage_files(@git, saved_selections)
|
33
|
+
loop do
|
34
|
+
puts @pastel.cyan(BANNER)
|
35
|
+
puts "=" * BANNER.length
|
36
|
+
|
37
|
+
# Get repository status
|
38
|
+
repo_status = @monitor.measure(:repository_status) do
|
39
|
+
{ unstaged: @git.unstaged_files, untracked: @git.untracked_files, staged: @git.staged_files }
|
40
|
+
end
|
41
|
+
|
42
|
+
unstaged, untracked, staged = repo_status.values_at(:unstaged, :untracked, :staged)
|
43
|
+
|
44
|
+
# Exit if no changes detected
|
45
|
+
if unstaged.empty? && untracked.empty? && staged.empty?
|
46
|
+
return { error: 'No changes detected in the repository' }
|
47
|
+
end
|
48
|
+
|
49
|
+
# Show file status
|
50
|
+
puts "\nRepository status:"
|
51
|
+
puts "- #{staged.length} file(s) staged for commit"
|
52
|
+
puts "- #{unstaged.length} file(s) modified but not staged"
|
53
|
+
puts "- #{untracked.length} untracked file(s)"
|
54
|
+
|
55
|
+
if ENV['SNAKOMMIT_DEBUG']
|
56
|
+
puts "\nPerformance report:"
|
57
|
+
@monitor.report.each { |line| puts " #{line}" }
|
58
|
+
end
|
59
|
+
|
60
|
+
# Handle saved selections
|
61
|
+
saved_selections = @git.get_saved_selections
|
62
|
+
if saved_selections&.any?
|
63
|
+
puts "\nFound selections from a previous session."
|
64
|
+
if @tty_prompt.yes?("Would you like to use your previous file selections?", default: true)
|
65
|
+
stage_files(@git, saved_selections)
|
66
|
+
else
|
67
|
+
@git.clear_saved_selections
|
68
|
+
select_files(@git)
|
69
|
+
end
|
73
70
|
else
|
74
|
-
# If user doesn't want to use previous selections, clear them
|
75
|
-
@git.clear_saved_selections
|
76
|
-
# Always show file selection to user
|
77
71
|
select_files(@git)
|
78
72
|
end
|
79
|
-
|
80
|
-
#
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
# After file selection, check if we have staged files
|
88
|
-
if current_staged.empty?
|
89
|
-
return { error: 'No changes staged for commit. Please select files to commit.' }
|
90
|
-
end
|
73
|
+
|
74
|
+
# Check if any files are staged
|
75
|
+
current_staged = @git.staged_files
|
76
|
+
if current_staged.empty?
|
77
|
+
puts "\n#{@pastel.red('Error:')} No changes staged for commit. Please select files to commit."
|
78
|
+
next if @tty_prompt.yes?("Do you want to select files again?", default: true)
|
79
|
+
return { error: 'No changes staged for commit. Please select files to commit.' }
|
80
|
+
end
|
91
81
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
82
|
+
puts "\n" + "-" * 40
|
83
|
+
|
84
|
+
# Get commit info
|
85
|
+
commit_info = @monitor.measure(:get_commit_info) { get_commit_info }
|
86
|
+
|
87
|
+
if commit_info[:error]
|
88
|
+
if commit_info[:error] == 'Commit aborted'
|
89
|
+
current_staged = @git.staged_files
|
90
|
+
if current_staged.any?
|
91
|
+
puts "\nThere are still #{current_staged.length} file(s) staged."
|
92
|
+
|
93
|
+
if @tty_prompt.yes?("Do you want to continue with these staged files?", default: true)
|
94
|
+
next
|
95
|
+
elsif @tty_prompt.yes?("Do you want to unstage all files?", default: false)
|
96
|
+
unstage_files(@git, current_staged)
|
97
|
+
puts "All files have been unstaged."
|
98
|
+
next
|
99
|
+
else
|
100
|
+
return commit_info
|
101
|
+
end
|
102
|
+
else
|
103
|
+
next if @tty_prompt.yes?("Do you want to start over?", default: true)
|
104
|
+
return commit_info
|
105
|
+
end
|
106
|
+
else
|
107
|
+
return commit_info
|
108
|
+
end
|
109
|
+
end
|
100
110
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
puts "-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
# Show performance stats in debug mode
|
134
|
-
if ENV['SNAKOMMIT_DEBUG']
|
135
|
-
puts "\nFinal performance report:"
|
136
|
-
@monitor.report.each { |line| puts " #{line}" }
|
111
|
+
# Format and preview commit message
|
112
|
+
message = format_commit_message(commit_info)
|
113
|
+
|
114
|
+
puts "\nFiles to be committed:"
|
115
|
+
@git.staged_files.each { |file| puts "- #{file}" }
|
116
|
+
|
117
|
+
puts "\nCommit message preview:"
|
118
|
+
puts "-" * 40
|
119
|
+
puts message
|
120
|
+
puts "-" * 40
|
121
|
+
|
122
|
+
unless @tty_prompt.yes?('Do you want to proceed with this commit?', default: true)
|
123
|
+
next if @tty_prompt.yes?("Do you want to start over?", default: true)
|
124
|
+
return { error: 'Commit aborted by user' }
|
125
|
+
end
|
126
|
+
|
127
|
+
# Perform commit
|
128
|
+
spinner = TTY::Spinner.new("[:spinner] Committing changes... ", format: :dots)
|
129
|
+
spinner.auto_spin
|
130
|
+
|
131
|
+
@monitor.measure(:git_commit) { @git.commit(message) }
|
132
|
+
|
133
|
+
spinner.success("Changes committed successfully!")
|
134
|
+
puts "\n✓ Successfully committed: #{message.split("\n").first}"
|
135
|
+
|
136
|
+
if ENV['SNAKOMMIT_DEBUG']
|
137
|
+
puts "\nFinal performance report:"
|
138
|
+
@monitor.report.each { |line| puts " #{line}" }
|
139
|
+
end
|
140
|
+
|
141
|
+
return { success: true, message: message }
|
137
142
|
end
|
138
|
-
|
139
|
-
{
|
143
|
+
rescue PromptError => e
|
144
|
+
puts "\n#{@pastel.red('Error:')} #{e.message}"
|
145
|
+
{ error: e.message }
|
146
|
+
rescue TTY::Reader::InputInterrupt
|
147
|
+
puts "\nCommit process interrupted by user."
|
148
|
+
{ error: 'Commit aborted by user' }
|
140
149
|
rescue Git::GitError => e
|
141
150
|
puts "\nError: #{e.message}"
|
142
151
|
{ error: "Git error: #{e.message}" }
|
@@ -150,91 +159,70 @@ module Snakommit
|
|
150
159
|
# Select files to add
|
151
160
|
def select_files(git)
|
152
161
|
begin
|
153
|
-
# Get file lists with performance monitoring
|
154
162
|
repo_status = @monitor.measure(:get_files_for_selection) do
|
155
|
-
{
|
156
|
-
unstaged: git.unstaged_files,
|
157
|
-
untracked: git.untracked_files,
|
158
|
-
staged: git.staged_files
|
159
|
-
}
|
163
|
+
{ unstaged: git.unstaged_files, untracked: git.untracked_files, staged: git.staged_files }
|
160
164
|
end
|
161
165
|
|
162
|
-
unstaged = repo_status
|
163
|
-
untracked = repo_status[:untracked]
|
164
|
-
staged = repo_status[:staged]
|
165
|
-
|
166
|
-
# Combine all files that could be staged
|
166
|
+
unstaged, untracked, staged = repo_status.values_at(:unstaged, :untracked, :staged)
|
167
167
|
all_stageable_files = unstaged + untracked
|
168
168
|
|
169
|
-
#
|
169
|
+
# No files to work with
|
170
170
|
if all_stageable_files.empty? && staged.empty?
|
171
171
|
puts "No changes detected in the repository."
|
172
172
|
return
|
173
173
|
end
|
174
174
|
|
175
|
-
#
|
176
|
-
if all_stageable_files.empty? &&
|
175
|
+
# Only staged files present
|
176
|
+
if all_stageable_files.empty? && staged.any?
|
177
177
|
puts "\nCurrently staged files:"
|
178
178
|
staged.each { |file| puts "- #{file}" }
|
179
179
|
|
180
|
-
|
181
|
-
if @tty_prompt.yes?("Do you want to unstage any files?", default: false)
|
182
|
-
unstage_files(git, staged)
|
183
|
-
end
|
180
|
+
unstage_files(git, staged) if @tty_prompt.yes?("Do you want to unstage any files?", default: false)
|
184
181
|
return
|
185
182
|
end
|
186
183
|
|
187
|
-
#
|
184
|
+
# Show currently staged files
|
188
185
|
unless staged.empty?
|
189
186
|
puts "\nCurrently staged files:"
|
190
187
|
staged.each { |file| puts "- #{file}" }
|
191
188
|
end
|
192
189
|
|
193
|
-
#
|
190
|
+
# Build options for file selection
|
194
191
|
options = []
|
192
|
+
options << { name: "[ ALL FILES ]", value: :all_files } if all_stageable_files.any?
|
195
193
|
|
196
|
-
# Add "ALL FILES" option at the top if we have unstaged or untracked files
|
197
|
-
if !all_stageable_files.empty?
|
198
|
-
options << { name: "[ ALL FILES ]", value: :all_files }
|
199
|
-
end
|
200
|
-
|
201
|
-
# Add modified files with index numbers
|
202
194
|
unstaged.each_with_index do |file, idx|
|
203
195
|
options << { name: "#{idx+1}. Modified: #{file}", value: file }
|
204
196
|
end
|
205
197
|
|
206
|
-
# Add untracked files with continuing index numbers
|
207
198
|
untracked.each_with_index do |file, idx|
|
208
199
|
options << { name: "#{unstaged.length + idx + 1}. Untracked: #{file}", value: file }
|
209
200
|
end
|
210
201
|
|
211
|
-
# Skip if no options
|
212
202
|
if options.empty?
|
213
203
|
puts "No files available to stage."
|
214
204
|
return
|
215
205
|
end
|
216
206
|
|
217
|
-
#
|
207
|
+
# Get user selections
|
218
208
|
puts "\nSelect files to stage for commit:"
|
219
209
|
selected = @tty_prompt.multi_select("Choose files (use space to select, enter to confirm):", options, per_page: 15, echo: true)
|
220
210
|
|
221
|
-
#
|
211
|
+
# Handle no selection
|
222
212
|
if selected.empty?
|
223
213
|
puts "No files selected for staging."
|
224
214
|
|
225
|
-
# If we already have staged files, ask if user wants to continue with those
|
226
215
|
unless staged.empty?
|
227
216
|
puts "You already have #{staged.length} file(s) staged."
|
228
|
-
return
|
229
|
-
return select_files(git) # Recursive call to try again
|
217
|
+
return select_files(git) if @tty_prompt.yes?("Do you want to select files again?", default: true)
|
230
218
|
end
|
231
219
|
|
232
220
|
return
|
233
221
|
end
|
234
222
|
|
223
|
+
# Process selection
|
235
224
|
puts "\nSelected files to stage:"
|
236
225
|
|
237
|
-
# Handle "ALL FILES" option
|
238
226
|
if selected.include?(:all_files)
|
239
227
|
selected = all_stageable_files
|
240
228
|
puts "- All files (#{selected.length})"
|
@@ -242,24 +230,33 @@ module Snakommit
|
|
242
230
|
selected.each { |file| puts "- #{file}" }
|
243
231
|
end
|
244
232
|
|
245
|
-
#
|
233
|
+
# Confirm and stage
|
246
234
|
if @tty_prompt.yes?("Proceed with staging these files?", default: true)
|
247
|
-
# Stage the selected files
|
248
235
|
stage_files(git, selected)
|
249
236
|
else
|
250
237
|
puts "Staging canceled by user."
|
251
238
|
return
|
252
239
|
end
|
253
240
|
|
254
|
-
#
|
241
|
+
# Offer to unstage
|
255
242
|
newly_staged = git.staged_files
|
256
|
-
|
257
|
-
|
258
|
-
unstage_files(git, newly_staged)
|
259
|
-
end
|
243
|
+
if newly_staged.any? && @tty_prompt.yes?("Do you want to unstage any files?", default: false)
|
244
|
+
unstage_files(git, newly_staged)
|
260
245
|
end
|
261
246
|
rescue TTY::Reader::InputInterrupt
|
262
|
-
puts "\nFile selection
|
247
|
+
puts "\nFile selection interrupted."
|
248
|
+
|
249
|
+
# Ask the user if they want to continue or abort
|
250
|
+
begin
|
251
|
+
unless @tty_prompt.yes?("Do you want to continue with the commit process?", default: false)
|
252
|
+
puts "Commit process aborted by user."
|
253
|
+
raise PromptError, "Commit aborted by user"
|
254
|
+
end
|
255
|
+
rescue TTY::Reader::InputInterrupt
|
256
|
+
puts "\nCommit process aborted."
|
257
|
+
raise PromptError, "Commit aborted by user"
|
258
|
+
end
|
259
|
+
|
263
260
|
return
|
264
261
|
rescue => e
|
265
262
|
puts "\nError during file selection: #{e.message}"
|
@@ -305,30 +302,49 @@ module Snakommit
|
|
305
302
|
def unstage_files(git, staged_files)
|
306
303
|
return if staged_files.empty?
|
307
304
|
|
308
|
-
# Create options for unstaging
|
309
305
|
unstage_options = staged_files.map { |f| { name: f, value: f } }
|
310
|
-
|
311
|
-
# Unstage heading
|
312
306
|
puts "\nUnstage Files:"
|
313
307
|
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
unless to_unstage.empty?
|
318
|
-
spinner = TTY::Spinner.new("[:spinner] Unstaging files... ", format: :dots)
|
319
|
-
spinner.auto_spin
|
308
|
+
begin
|
309
|
+
to_unstage = @tty_prompt.multi_select("Select files to unstage:", unstage_options, per_page: 15)
|
320
310
|
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
311
|
+
unless to_unstage.empty?
|
312
|
+
spinner = TTY::Spinner.new("[:spinner] Unstaging files... ", format: :dots)
|
313
|
+
spinner.auto_spin
|
314
|
+
|
315
|
+
@monitor.measure(:batch_unstage_files) do
|
316
|
+
@batch_processor.process_files(to_unstage) do |batch|
|
317
|
+
batch.each { |file| git.reset(file) }
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
spinner.success("Files unstaged")
|
322
|
+
|
323
|
+
# Check if all files unstaged
|
324
|
+
remaining_staged = git.staged_files
|
325
|
+
if remaining_staged.empty?
|
326
|
+
puts "#{@pastel.yellow('Note:')} All files have been unstaged."
|
327
|
+
|
328
|
+
# Offer to select new files if available
|
329
|
+
unstaged_files = git.unstaged_files
|
330
|
+
untracked_files = git.untracked_files
|
331
|
+
|
332
|
+
if (unstaged_files + untracked_files).any?
|
333
|
+
begin
|
334
|
+
if @tty_prompt.yes?("Do you want to select new files now?", default: true)
|
335
|
+
select_files(git)
|
336
|
+
end
|
337
|
+
rescue Interrupt
|
338
|
+
puts "\nFile selection interrupted."
|
339
|
+
end
|
340
|
+
end
|
325
341
|
end
|
326
342
|
end
|
327
|
-
|
328
|
-
|
343
|
+
rescue TTY::Reader::InputInterrupt
|
344
|
+
puts "\nUnstaging files aborted."
|
345
|
+
rescue => e
|
346
|
+
raise PromptError, "Failed to unstage files: #{e.message}"
|
329
347
|
end
|
330
|
-
rescue => e
|
331
|
-
raise PromptError, "Failed to unstage files: #{e.message}"
|
332
348
|
end
|
333
349
|
|
334
350
|
# Get commit information
|
@@ -337,12 +353,11 @@ module Snakommit
|
|
337
353
|
|
338
354
|
puts "\nCommit Details:"
|
339
355
|
|
340
|
-
# Select commit type
|
341
356
|
info[:type] = select_type
|
342
357
|
|
343
|
-
#
|
358
|
+
# Handle scope selection
|
344
359
|
suggested_scopes = @config['scopes']
|
345
|
-
if suggested_scopes
|
360
|
+
if suggested_scopes&.any?
|
346
361
|
scope_options = suggested_scopes.map { |s| { name: s, value: s } }
|
347
362
|
scope_options << { name: '[none]', value: nil }
|
348
363
|
|
@@ -353,18 +368,17 @@ module Snakommit
|
|
353
368
|
info[:scope] = @tty_prompt.ask('Enter the scope of this change (optional, press Enter to skip):')
|
354
369
|
end
|
355
370
|
|
356
|
-
#
|
371
|
+
# Get subject
|
357
372
|
info[:subject] = @tty_prompt.ask('Enter a short description:') do |q|
|
358
373
|
q.required true
|
359
374
|
q.validate(/^.{1,#{@config['max_subject_length']}}$/, "Subject must be less than #{@config['max_subject_length']} characters")
|
360
375
|
end
|
361
376
|
|
362
|
-
#
|
377
|
+
# Get body text
|
363
378
|
puts "Enter a longer description (optional, press Enter to skip):"
|
364
379
|
puts "Type your message and press Enter when done. Leave empty to skip."
|
365
380
|
|
366
381
|
body_lines = []
|
367
|
-
# Read input until an empty line is entered
|
368
382
|
loop do
|
369
383
|
line = @tty_prompt.ask("")
|
370
384
|
break if line.nil? || line.empty?
|
@@ -373,17 +387,15 @@ module Snakommit
|
|
373
387
|
|
374
388
|
info[:body] = body_lines
|
375
389
|
|
376
|
-
#
|
390
|
+
# Breaking changes
|
377
391
|
info[:breaking] = @tty_prompt.yes?('Is this a breaking change?', default: false)
|
378
|
-
|
379
|
-
# Breaking change description
|
380
392
|
if info[:breaking]
|
381
393
|
info[:breaking_description] = @tty_prompt.ask('Enter breaking change description:') do |q|
|
382
394
|
q.required true
|
383
395
|
end
|
384
396
|
end
|
385
397
|
|
386
|
-
#
|
398
|
+
# Issue references
|
387
399
|
if @tty_prompt.yes?('Does this commit close any issues?', default: false)
|
388
400
|
info[:issues] = @tty_prompt.ask('Enter issue references (e.g., "fix #123, close #456"):') do |q|
|
389
401
|
q.required true
|
@@ -392,6 +404,25 @@ module Snakommit
|
|
392
404
|
|
393
405
|
info
|
394
406
|
rescue Interrupt
|
407
|
+
# Improved interrupt handling
|
408
|
+
puts "\n#{@pastel.yellow('Interruption:')} Commit process interrupted."
|
409
|
+
|
410
|
+
# Check if there are staged files
|
411
|
+
staged_files = @git.staged_files
|
412
|
+
if staged_files.any?
|
413
|
+
puts "There are currently #{staged_files.length} file(s) staged."
|
414
|
+
|
415
|
+
# Offer user to unstage files
|
416
|
+
begin
|
417
|
+
if @tty_prompt.yes?("Do you want to unstage these files?", default: false)
|
418
|
+
unstage_files(@git, staged_files)
|
419
|
+
puts "All files have been unstaged."
|
420
|
+
end
|
421
|
+
rescue Interrupt
|
422
|
+
puts "\nInterruption detected. Aborting commit process."
|
423
|
+
end
|
424
|
+
end
|
425
|
+
|
395
426
|
{ error: 'Commit aborted' }
|
396
427
|
rescue => e
|
397
428
|
{ error: "Failed to gather commit information: #{e.message}" }
|
@@ -399,37 +430,23 @@ module Snakommit
|
|
399
430
|
|
400
431
|
# Format the commit message according to convention
|
401
432
|
def format_commit_message(info)
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
if info[:breaking]
|
420
|
-
breaking = "\n\nBREAKING CHANGE: #{info[:breaking_description]}"
|
421
|
-
end
|
422
|
-
|
423
|
-
# Format issues
|
424
|
-
issues = info[:issues] ? "\n\n#{info[:issues]}" : ''
|
425
|
-
|
426
|
-
# Return the full commit message
|
427
|
-
message = "#{header}#{body}#{breaking}#{issues}"
|
428
|
-
|
429
|
-
message
|
430
|
-
rescue => e
|
431
|
-
raise PromptError, "Failed to format commit message: #{e.message}"
|
432
|
-
end
|
433
|
+
# Format header (type, scope, subject)
|
434
|
+
commit_type = @templates.emoji_enabled? ? @templates.format_commit_type(info[:type]) : info[:type]
|
435
|
+
|
436
|
+
header = if info[:scope] && !info[:scope].empty?
|
437
|
+
"#{commit_type}(#{info[:scope]}): #{info[:subject]}"
|
438
|
+
else
|
439
|
+
"#{commit_type}: #{info[:subject]}"
|
440
|
+
end
|
441
|
+
|
442
|
+
# Format body and additional sections
|
443
|
+
body = info[:body].empty? ? '' : "\n\n#{info[:body].join("\n")}"
|
444
|
+
breaking = info[:breaking] ? "\n\nBREAKING CHANGE: #{info[:breaking_description]}" : ''
|
445
|
+
issues = info[:issues] ? "\n\n#{info[:issues]}" : ''
|
446
|
+
|
447
|
+
"#{header}#{body}#{breaking}#{issues}"
|
448
|
+
rescue => e
|
449
|
+
raise PromptError, "Failed to format commit message: #{e.message}"
|
433
450
|
end
|
434
451
|
|
435
452
|
def select_type
|
@@ -441,7 +458,6 @@ module Snakommit
|
|
441
458
|
# Format the display name based on emoji settings
|
442
459
|
if @templates.emoji_enabled?
|
443
460
|
emoji = @templates.get_emoji_for_type(value)
|
444
|
-
# Ensure there's a space between emoji and type
|
445
461
|
name = emoji ? "#{emoji} #{value}: #{type['description']}" : "#{value}: #{type['description']}"
|
446
462
|
else
|
447
463
|
name = "#{value}: #{type['description']}"
|
data/lib/snakommit/templates.rb
CHANGED
@@ -18,7 +18,7 @@ module Snakommit
|
|
18
18
|
'perf' => '⚡️', # zap
|
19
19
|
'test' => '✅', # check mark
|
20
20
|
'build' => '🔧', # wrench
|
21
|
-
'ci' => '👷', # construction worker
|
21
|
+
'ci/cd' => '👷', # construction worker
|
22
22
|
'chore' => '🔨', # hammer
|
23
23
|
'revert' => '⏪️', # rewind
|
24
24
|
}.freeze
|
@@ -29,8 +29,6 @@ module Snakommit
|
|
29
29
|
def initialize
|
30
30
|
ensure_config_directory
|
31
31
|
@emoji_formatted_types = {} # Cache for formatted commit types
|
32
|
-
|
33
|
-
# Initialiser les valeurs par défaut avant de charger la configuration
|
34
32
|
@emoji_enabled = false
|
35
33
|
@emoji_map = DEFAULT_EMOJI_MAP.dup
|
36
34
|
|
@@ -123,7 +121,6 @@ module Snakommit
|
|
123
121
|
|
124
122
|
begin
|
125
123
|
ensure_config_directory
|
126
|
-
# Écrire le fichier en une seule opération
|
127
124
|
File.write(CONFIG_FILE, config.to_yaml)
|
128
125
|
rescue => e
|
129
126
|
handle_config_error(e, "Failed to save")
|
data/lib/snakommit/version.rb
CHANGED
data/snakommit.gemspec
CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.description = "Snakommit helps teams maintain consistent commit message formats by guiding developers through the process of creating standardized commit messages"
|
11
11
|
spec.homepage = "https://github.com/antonia-pl/snakommit"
|
12
12
|
spec.license = "MIT"
|
13
|
-
spec.required_ruby_version = Gem::Requirement.new(">=
|
13
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 3.0.0")
|
14
14
|
|
15
15
|
spec.metadata["homepage_uri"] = spec.homepage
|
16
16
|
spec.metadata["source_code_uri"] = spec.homepage
|