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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0fa7760fe40ddf90aac4e7c28b71eb1935ab5f1b9f704f990cc377a4294b724b
4
- data.tar.gz: 2f5835b7d423667bf56fee1c2df02091d7cf9502ac7b80910658c93990d6043f
3
+ metadata.gz: b512848316f57581d614018b74a7c18be9cc45444f520bb4e84e4de76e7ba9da
4
+ data.tar.gz: f74cc89501692d433a54ffc2408fea7a16a5e287abaa35672f25dd2becb0750e
5
5
  SHA512:
6
- metadata.gz: 6bf5b5878c2871fa3df4837921387a8fceadd542919c40e2b449d83da83f2aded6ef5b804f7ea32878c23028123e16796bcb4a81c6bff273410a67c92343165c
7
- data.tar.gz: 6f32299d57207644a3c9100146e1fa0066c1c82b1bfe2065b7d332d312ba41f1702e1d7d2682aafb6dde141aa1434c6e49ca04afe074bad2b4d0f8e076fd0607
6
+ metadata.gz: 22af7202575f980aec20cbb3b7fbfec9dcaa87229b33b251b5cfe5f284d46468beb66e33ffea66d99a34c691e86c93ba210af2c02ce4d248b21cb9eccec5c35a
7
+ data.tar.gz: fe48a9fac8fa84b8df4845770ab3cb4ac1471995c257348326a593771a34c558fd317edf8d637cc768bcf80645c435d9c773ffb73f72bfed9b201910c328375e
@@ -0,0 +1,81 @@
1
+ name: CD
2
+
3
+ on:
4
+ workflow_run:
5
+ workflows: ["CI"]
6
+ types:
7
+ - completed
8
+
9
+ permissions:
10
+ contents: write
11
+
12
+ jobs:
13
+ merge-to-main:
14
+ runs-on: ubuntu-latest
15
+ if: ${{ github.event.workflow_run.conclusion == 'success' }}
16
+ steps:
17
+ - name: Checkout code
18
+ uses: actions/checkout@v2
19
+ with:
20
+ fetch-depth: 0 # Needed to fetch all history and tags
21
+ token: ${{ secrets.WORKFLOW_TOKEN || secrets.GITHUB_TOKEN }}
22
+
23
+ - name: Setup Git identity
24
+ run: |
25
+ git config --global user.name "GitHub Actions"
26
+ git config --global user.email "actions@github.com"
27
+
28
+ - name: Fetch branches
29
+ run: |
30
+ git fetch origin test
31
+ git fetch origin main || echo "Main branch doesn't exist yet"
32
+
33
+ - name: Merge test into main
34
+ run: |
35
+ # Checkout or create main branch
36
+ if git show-ref --quiet refs/remotes/origin/main; then
37
+ git checkout -B main origin/main
38
+ else
39
+ git checkout -b main
40
+ fi
41
+
42
+ # Merge test into main
43
+ if ! git merge origin/test --no-commit; then
44
+ echo "Merge conflict detected, resolving in favor of test branch changes"
45
+ git checkout --theirs .
46
+ git add .
47
+ fi
48
+
49
+ git commit -m "Merge test into main" || echo "No changes to commit"
50
+ # Check if there are changes to push
51
+ git diff --quiet origin/main HEAD || git_has_changes=true
52
+
53
+ - name: Push to origin/main
54
+ run: |
55
+ git remote set-url origin https://x-access-token:${{ secrets.WORKFLOW_TOKEN || secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}
56
+ git push -f origin main
57
+
58
+ - name: Create and push new tag
59
+ run: |
60
+ # Get latest tag or default to v0.0.0
61
+ LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")
62
+ echo "Latest tag: $LATEST_TAG"
63
+
64
+ # Extract version numbers
65
+ MAJOR=$(echo "$LATEST_TAG" | cut -d. -f1 | sed 's/v//')
66
+ MINOR=$(echo "$LATEST_TAG" | cut -d. -f2)
67
+ PATCH=$(echo "$LATEST_TAG" | cut -d. -f3)
68
+
69
+ echo "Current version: $MAJOR.$MINOR.$PATCH"
70
+
71
+ # Increment patch version
72
+ PATCH=$((PATCH + 1))
73
+ NEW_TAG="v$MAJOR.$MINOR.$PATCH"
74
+ echo "Creating new tag: $NEW_TAG"
75
+
76
+ # Create tag
77
+ git tag -a "$NEW_TAG" -m "Release $NEW_TAG"
78
+
79
+ # Auth and push
80
+ git remote set-url origin https://x-access-token:${{ secrets.WORKFLOW_TOKEN || secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}
81
+ git push origin "$NEW_TAG"
@@ -0,0 +1,73 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - dev
7
+
8
+ jobs:
9
+ merge-to-test:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - name: Checkout code
13
+ uses: actions/checkout@v2
14
+ with:
15
+ fetch-depth: 0
16
+
17
+ - name: Merge dev to test
18
+ run: |
19
+ git config --global user.name "GitHub Actions"
20
+ git config --global user.email "actions@github.com"
21
+
22
+ # Check if test branch exists on remote
23
+ if git ls-remote --exit-code --heads origin test; then
24
+ echo "Branch test exists, checking out"
25
+ git fetch origin test
26
+ git checkout -B test origin/test
27
+ else
28
+ echo "Branch test does not exist, creating it"
29
+ git checkout -b test
30
+ fi
31
+
32
+ # Merge dev into test
33
+ if ! git merge origin/dev --no-commit; then
34
+ echo "Merge conflict detected, resolving in favor of dev branch changes"
35
+ git checkout --theirs .
36
+ git add .
37
+ fi
38
+
39
+ git commit -m "Merge dev into test" || echo "No changes to commit"
40
+ git push origin test
41
+
42
+
43
+ run-tests:
44
+ runs-on: ubuntu-latest
45
+ needs: merge-to-test
46
+ steps:
47
+ - name: Checkout code
48
+ uses: actions/checkout@v2
49
+ with:
50
+ ref: test
51
+
52
+ - name: Debug available rake tasks
53
+ run: |
54
+ bundle install
55
+ rake -T
56
+
57
+ - name: Run tests
58
+ run: |
59
+ rake testout@v2
60
+ with:
61
+ ref: test
62
+
63
+ - name: Set up Ruby (auto-detect from .ruby-version or Gemfile)
64
+ uses: ruby/setup-ruby@v1
65
+ with:
66
+ ruby-version: '3.2'
67
+ bundler-cache: true
68
+
69
+ - name: List available Rake tasks
70
+ run: rake -T
71
+
72
+ - name: Run tests
73
+ run: rake test
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.2.2
data/Gemfile.lock CHANGED
@@ -3,23 +3,24 @@ GEM
3
3
  specs:
4
4
  addressable (2.8.7)
5
5
  public_suffix (>= 2.0.2, < 7.0)
6
- ast (2.4.2)
7
- diff-lcs (1.6.0)
6
+ ast (2.4.3)
7
+ diff-lcs (1.6.1)
8
8
  git (1.19.1)
9
9
  addressable (~> 2.8)
10
10
  rchardet (~> 1.8)
11
- minitest (5.25.4)
12
- parallel (1.24.0)
13
- parser (3.3.7.1)
11
+ minitest (5.25.5)
12
+ parallel (1.26.3)
13
+ parser (3.3.7.4)
14
14
  ast (~> 2.4.1)
15
15
  racc
16
16
  pastel (0.8.0)
17
17
  tty-color (~> 0.5)
18
- public_suffix (5.1.1)
18
+ prism (1.4.0)
19
+ public_suffix (6.0.1)
19
20
  racc (1.8.1)
20
21
  rainbow (3.1.1)
21
22
  rake (13.2.1)
22
- rchardet (1.8.0)
23
+ rchardet (1.9.0)
23
24
  regexp_parser (2.10.0)
24
25
  rexml (3.4.1)
25
26
  rspec (3.13.0)
@@ -44,8 +45,9 @@ GEM
44
45
  rubocop-ast (>= 1.15.1, < 2.0)
45
46
  ruby-progressbar (~> 1.7)
46
47
  unicode-display_width (>= 1.4.0, < 3.0)
47
- rubocop-ast (1.30.0)
48
- parser (>= 3.2.1.0)
48
+ rubocop-ast (1.44.0)
49
+ parser (>= 3.3.7.2)
50
+ prism (~> 1.4)
49
51
  ruby-progressbar (1.13.0)
50
52
  tty-color (0.6.0)
51
53
  tty-cursor (0.7.1)
@@ -78,4 +80,4 @@ DEPENDENCIES
78
80
  tty-spinner (~> 0.9.3)
79
81
 
80
82
  BUNDLED WITH
81
- 1.17.2
83
+ 2.6.7
data/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # Snakommit
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/snakommit.svg)](https://badge.fury.io/rb/snakommit)
4
+ [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
5
+
3
6
  Snakommit is a high-performance, interactive commit manager tool similar to Commitizen. It helps teams maintain consistent commit message formats by guiding developers through the process of creating standardized commit messages.
4
7
 
5
8
  ## Features
@@ -18,7 +21,20 @@ Snakommit is a high-performance, interactive commit manager tool similar to Comm
18
21
  - Ruby >= 2.5
19
22
  - Git
20
23
 
21
- ### Install from source
24
+ ### Option 1: Install from RubyGems (Recommended)
25
+
26
+ ```bash
27
+ # Install the gem
28
+ gem install snakommit
29
+ ```
30
+
31
+ Or add to your Gemfile:
32
+
33
+ ```ruby
34
+ gem 'snakommit'
35
+ ```
36
+
37
+ ### Option 2: Install from source
22
38
 
23
39
  You have multiple options to install Snakommit:
24
40
 
@@ -70,12 +86,6 @@ bundle install
70
86
  ruby -Ilib bin/snakommit
71
87
  ```
72
88
 
73
- ### Install via Homebrew (Coming soon)
74
-
75
- ```bash
76
- /!\ - (coming soon) - TODO
77
- ```
78
-
79
89
  ## Usage
80
90
 
81
91
  Simply run `snakommit` (or its shorter alias `sk`) in your Git repository:
@@ -138,8 +148,8 @@ If you encounter a "command not found" error after installation:
138
148
 
139
149
  If you encounter permission issues during installation:
140
150
 
141
- 1. Try the alternative installation methods that don't require sudo
142
- 2. Ensure your Ruby environment has the correct permissions
151
+ 1. Try the alternative installation methods that don't require sudo.
152
+ 2. Ensure your Ruby environment has the correct permissions.
143
153
  3. Check that the executable bit is set on the bin/snakommit file:
144
154
 
145
155
  ```bash
@@ -148,55 +158,15 @@ chmod +x bin/snakommit
148
158
 
149
159
  ## Development
150
160
 
151
- ### Testing
152
-
153
- Snakommit has a comprehensive test suite that covers its functionality. The test suite is built using Minitest and includes unit tests, integration tests, and performance tests.
154
-
155
- #### Running Tests
156
-
157
- Run all the tests:
158
-
159
- ```bash
160
- bundle exec rake test
161
- ```
162
-
163
- Run specific types of tests:
164
-
165
- ```bash
166
- # Run only unit tests (fast)
167
- bundle exec rake test_unit
168
-
169
- # Run only performance tests
170
- bundle exec rake test_performance
171
-
172
- # Run tests for a specific component
173
- bundle exec rake test_git
174
- bundle exec rake test_config
175
- bundle exec rake test_templates
176
- bundle exec rake test_hooks
177
-
178
- # Run tests with verbose output
179
- bundle exec rake test_verbose
180
-
181
- # Run both tests and linting
182
- bundle exec rake
183
- ```
184
-
185
- #### Writing Tests
186
-
187
- When adding new features or fixing bugs, please add or update the corresponding tests. The test files are located in the `test/` directory and follow the pattern `test/component_test.rb`.
188
-
189
- Each test file contains a class that inherits from `Minitest::Test` and includes test methods that start with `test_`.
190
-
191
- For more detailed information about testing Snakommit, see [TESTING.md](TESTING.md).
192
-
193
- ### CI/CD
161
+ ### CI/CD Workflow
194
162
 
195
163
  Snakommit uses GitHub Actions for continuous integration and deployment:
196
164
 
197
- - **Automated testing** on multiple Ruby versions for all pushes and pull requests
198
- - **Automated releases** to RubyGems when a new version is tagged
199
- - **Automated version bumping** via workflow dispatch
165
+ - **Automated Testing**: Tests run automatically on multiple Ruby versions (2.7, 3.0, 3.1, 3.2) for all pushes to main and dev branches, as well as pull requests.
166
+ - **Code Quality**: Automatic linting with Rubocop ensures consistent code style.
167
+ - **Automated Releases**: New versions are published to RubyGems automatically when a release is triggered.
168
+
169
+ #### Release Process
200
170
 
201
171
  To create a new release:
202
172
 
@@ -273,3 +243,10 @@ Snakommit has been optimized to offer the best possible performance, even on lar
273
243
  - Command pooling to minimize process creation overhead
274
244
 
275
245
  These optimizations allow Snakommit to remain fast and responsive even on large repositories with many files.
246
+
247
+ ## Contributing
248
+
249
+ This project uses GitHub Actions for CI/CD:
250
+ - Automated tests run on all PRs to main
251
+ - Automatic version tagging on merge to main
252
+ - Automatic gem publishing when tagged
data/Rakefile CHANGED
@@ -4,17 +4,17 @@ require "rake/testtask"
4
4
  # Standard test task
5
5
  desc "Run tests"
6
6
  Rake::TestTask.new(:test) do |t|
7
- t.libs << "test"
7
+ t.libs << "tests"
8
8
  t.libs << "lib"
9
- t.test_files = FileList["test/**/*_test.rb"]
9
+ t.test_files = FileList["tests/**/*_test.rb"]
10
10
  end
11
11
 
12
12
  # Verbose test task
13
13
  desc "Run tests with verbose output"
14
14
  Rake::TestTask.new(:test_verbose) do |t|
15
- t.libs << "test"
15
+ t.libs << "tests"
16
16
  t.libs << "lib"
17
- t.test_files = FileList["test/**/*_test.rb"]
17
+ t.test_files = FileList["tests/**/*_test.rb"]
18
18
  t.verbose = true
19
19
  t.warning = true
20
20
  end
@@ -22,27 +22,27 @@ end
22
22
  # Performance tests only
23
23
  desc "Run only performance tests"
24
24
  Rake::TestTask.new(:test_performance) do |t|
25
- t.libs << "test"
25
+ t.libs << "tests"
26
26
  t.libs << "lib"
27
- t.test_files = FileList["test/performance_test.rb"]
27
+ t.test_files = FileList["tests/performance_test.rb"]
28
28
  t.verbose = true
29
29
  end
30
30
 
31
31
  # Unit tests only (excluding performance tests)
32
32
  desc "Run unit tests (excluding performance tests)"
33
33
  Rake::TestTask.new(:test_unit) do |t|
34
- t.libs << "test"
34
+ t.libs << "tests"
35
35
  t.libs << "lib"
36
- t.test_files = FileList["test/**/*_test.rb"] - FileList["test/performance_test.rb"]
36
+ t.test_files = FileList["tests/**/*_test.rb"] - FileList["tests/performance_test.rb"]
37
37
  end
38
38
 
39
39
  # Individual component tests
40
40
  %w[config git templates hooks].each do |component|
41
41
  desc "Run #{component} tests"
42
42
  Rake::TestTask.new("test_#{component}") do |t|
43
- t.libs << "test"
43
+ t.libs << "tests"
44
44
  t.libs << "lib"
45
- t.test_files = FileList["test/#{component}_test.rb"]
45
+ t.test_files = FileList["tests/#{component}_test.rb"]
46
46
  end
47
47
  end
48
48
 
data/lib/snakommit/cli.rb CHANGED
@@ -26,16 +26,12 @@ module Snakommit
26
26
 
27
27
  def run(args)
28
28
  command = args.shift || 'commit'
29
-
30
- # Start monitoring execution time
31
29
  trace_start = Time.now
32
30
 
33
- # Execute the command with performance monitoring
34
31
  result = @monitor.measure(:command_execution) do
35
32
  execute_command(command, args)
36
33
  end
37
34
 
38
- # Record command execution metrics if in debug mode
39
35
  if ENV['SNAKOMMIT_DEBUG']
40
36
  trace_end = Time.now
41
37
  puts "\nCommand execution completed in #{(trace_end - trace_start).round(3)}s"
@@ -52,28 +48,17 @@ module Snakommit
52
48
 
53
49
  def execute_command(command, args)
54
50
  case command
55
- when 'commit'
56
- handle_commit
57
- when 'version', '-v', '--version'
58
- show_version
59
- when 'help', '-h', '--help'
60
- show_help
61
- when 'hooks'
62
- handle_hooks(args)
63
- when 'templates'
64
- handle_templates(args)
65
- when 'emoji'
66
- handle_emoji_toggle(args)
67
- when 'update'
68
- check_for_updates(args.include?('--force'))
69
- when 'validate-message'
70
- validate_commit_message(args.first)
71
- when 'prepare-message'
72
- prepare_commit_message
73
- when 'log-commit'
74
- log_commit(args.first)
75
- else
76
- unknown_command(command)
51
+ when 'commit' then handle_commit
52
+ when 'version', '-v', '--version' then show_version
53
+ when 'help', '-h', '--help' then show_help
54
+ when 'hooks' then handle_hooks(args)
55
+ when 'templates' then handle_templates(args)
56
+ when 'emoji' then handle_emoji_toggle(args)
57
+ when 'update' then check_for_updates(args.include?('--force'))
58
+ when 'validate-message' then validate_commit_message(args.first)
59
+ when 'prepare-message' then prepare_commit_message
60
+ when 'log-commit' then log_commit(args.first)
61
+ else unknown_command(command)
77
62
  end
78
63
  end
79
64
 
@@ -177,9 +162,7 @@ module Snakommit
177
162
  puts "#{hook_name}: #{status[hook_name] || 'unknown'}"
178
163
  else
179
164
  puts "Git hooks status:"
180
- status.each do |hook, state|
181
- puts " #{hook}: #{state}"
182
- end
165
+ status.each { |hook, state| puts " #{hook}: #{state}" }
183
166
  end
184
167
  end
185
168
 
@@ -187,12 +170,9 @@ module Snakommit
187
170
  subcommand = args.shift || 'list'
188
171
 
189
172
  case subcommand
190
- when 'list'
191
- list_emoji_mappings
192
- when 'update'
193
- update_emoji_mapping(args)
194
- when 'reset'
195
- reset_emoji_mappings
173
+ when 'list' then list_emoji_mappings
174
+ when 'update' then update_emoji_mapping(args)
175
+ when 'reset' then reset_emoji_mappings
196
176
  else
197
177
  puts "Unknown templates subcommand: #{subcommand}"
198
178
  show_help
@@ -201,16 +181,14 @@ module Snakommit
201
181
  end
202
182
 
203
183
  def list_emoji_mappings
204
- mappings = @templates.list_emoji_mappings
205
184
  puts "Emoji mappings for commit types:"
206
- mappings.each do |mapping|
185
+ @templates.list_emoji_mappings.each do |mapping|
207
186
  puts " #{mapping[:type]}: #{mapping[:emoji]}"
208
187
  end
209
188
  end
210
189
 
211
190
  def update_emoji_mapping(args)
212
- type = args.shift
213
- emoji = args.shift
191
+ type, emoji = args.shift(2)
214
192
 
215
193
  if type && emoji
216
194
  begin
@@ -249,15 +227,13 @@ module Snakommit
249
227
 
250
228
  def prepare_commit_message
251
229
  # This would normally invoke the interactive prompt
252
- # For now, just return a simple message for testing
253
230
  puts "chore: automated commit message from snakommit"
254
231
  exit 0
255
232
  end
256
233
 
257
234
  def log_commit(commit_hash)
258
235
  # In the future, this will store commit stats
259
- exit 0 if commit_hash
260
- exit 1
236
+ exit commit_hash ? 0 : 1
261
237
  end
262
238
 
263
239
  def check_for_updates(force = false)
@@ -268,16 +244,14 @@ module Snakommit
268
244
 
269
245
  begin
270
246
  # Get the latest version from RubyGems
271
- response = nil
272
- @monitor.measure(:fetch_rubygems) do
273
- response = URI.open("https://rubygems.org/api/v1/gems/snakommit.json").read
247
+ response = @monitor.measure(:fetch_rubygems) do
248
+ URI.open("https://rubygems.org/api/v1/gems/snakommit.json").read
274
249
  end
275
250
 
276
251
  data = JSON.parse(response)
277
252
  latest_version = data["version"]
278
253
  current_version = Snakommit::VERSION
279
254
 
280
- # Compare versions
281
255
  if force || latest_version > current_version
282
256
  update_gem(latest_version, current_version)
283
257
  else
@@ -289,7 +263,6 @@ module Snakommit
289
263
  end
290
264
  end
291
265
 
292
- # Update to the latest gem version
293
266
  def update_gem(latest_version, current_version)
294
267
  puts "New version available: #{latest_version} (current: #{current_version})"
295
268
 
@@ -323,21 +296,17 @@ module Snakommit
323
296
 
324
297
  # Handle initialization errors in a user-friendly way
325
298
  def handle_initialization_error(error)
326
- case error
327
- when Prompt::PromptError
328
- puts "Error initializing prompt: #{error.message}"
329
- when Templates::TemplateError
330
- puts "Error initializing templates: #{error.message}"
331
- when Hooks::HookError
332
- puts "Error initializing hooks: #{error.message}"
333
- when Config::ConfigError
334
- puts "Error loading configuration: #{error.message}"
335
- when Git::GitError
336
- puts "Git error: #{error.message}"
337
- else
338
- puts "Initialization error: #{error.message}"
339
- puts "Backtrace:\n #{error.backtrace.join("\n ")}" if ENV['SNAKOMMIT_DEBUG']
340
- end
299
+ error_msg = case error
300
+ when Prompt::PromptError then "Error initializing prompt: #{error.message}"
301
+ when Templates::TemplateError then "Error initializing templates: #{error.message}"
302
+ when Hooks::HookError then "Error initializing hooks: #{error.message}"
303
+ when Config::ConfigError then "Error loading configuration: #{error.message}"
304
+ when Git::GitError then "Git error: #{error.message}"
305
+ else "Initialization error: #{error.message}"
306
+ end
307
+
308
+ puts error_msg
309
+ puts "Backtrace:\n #{error.backtrace.join("\n ")}" if ENV['SNAKOMMIT_DEBUG']
341
310
 
342
311
  puts "\nTrying to run snakommit in a non-Git repository? Make sure you're in a valid Git repository."
343
312
  puts "For more information, run 'snakommit help'"
@@ -346,23 +315,18 @@ module Snakommit
346
315
 
347
316
  # Handle runtime errors in a user-friendly way
348
317
  def handle_runtime_error(error)
349
- case error
350
- when Prompt::PromptError
351
- puts "Error during prompt: #{error.message}"
352
- when Templates::TemplateError
353
- puts "Template error: #{error.message}"
354
- when Hooks::HookError
355
- puts "Hook error: #{error.message}"
356
- when Config::ConfigError
357
- puts "Configuration error: #{error.message}"
358
- when Git::GitError
359
- puts "Git error: #{error.message}"
360
- when CLIError
361
- puts "CLI error: #{error.message}"
362
- else
363
- puts "Error: #{error.message}"
364
- puts "Backtrace:\n #{error.backtrace.join("\n ")}" if ENV['SNAKOMMIT_DEBUG']
365
- end
318
+ error_msg = case error
319
+ when Prompt::PromptError then "Error during prompt: #{error.message}"
320
+ when Templates::TemplateError then "Template error: #{error.message}"
321
+ when Hooks::HookError then "Hook error: #{error.message}"
322
+ when Config::ConfigError then "Configuration error: #{error.message}"
323
+ when Git::GitError then "Git error: #{error.message}"
324
+ when CLIError then "CLI error: #{error.message}"
325
+ else "Error: #{error.message}"
326
+ end
327
+
328
+ puts error_msg
329
+ puts "Backtrace:\n #{error.backtrace.join("\n ")}" if ENV['SNAKOMMIT_DEBUG']
366
330
 
367
331
  puts "\nFor help, run 'snakommit help'"
368
332
  exit 1