overcommit 0.24.0 → 0.25.0

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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/config/default.yml +45 -8
  3. data/lib/overcommit/git_repo.rb +16 -5
  4. data/lib/overcommit/git_version.rb +1 -1
  5. data/lib/overcommit/hook/commit_msg/base.rb +3 -2
  6. data/lib/overcommit/hook/commit_msg/capitalized_subject.rb +2 -0
  7. data/lib/overcommit/hook/commit_msg/hard_tabs.rb +2 -0
  8. data/lib/overcommit/hook/commit_msg/single_line_subject.rb +2 -0
  9. data/lib/overcommit/hook/commit_msg/text_width.rb +2 -0
  10. data/lib/overcommit/hook/commit_msg/trailing_period.rb +2 -0
  11. data/lib/overcommit/hook/post_checkout/index_tags.rb +3 -4
  12. data/lib/overcommit/hook/post_checkout/submodule_status.rb +3 -23
  13. data/lib/overcommit/hook/post_commit/index_tags.rb +3 -4
  14. data/lib/overcommit/hook/post_commit/submodule_status.rb +3 -23
  15. data/lib/overcommit/hook/post_merge/index_tags.rb +3 -4
  16. data/lib/overcommit/hook/post_merge/submodule_status.rb +3 -23
  17. data/lib/overcommit/hook/post_rewrite/index_tags.rb +5 -2
  18. data/lib/overcommit/hook/post_rewrite/submodule_status.rb +3 -23
  19. data/lib/overcommit/hook/pre_commit/author_name.rb +2 -2
  20. data/lib/overcommit/hook/pre_commit/base.rb +1 -1
  21. data/lib/overcommit/hook/pre_commit/hard_tabs.rb +4 -5
  22. data/lib/overcommit/hook/pre_commit/{rubocop.rb → rubo_cop.rb} +1 -1
  23. data/lib/overcommit/hook/pre_commit/scalariform.rb +18 -0
  24. data/lib/overcommit/hook/pre_commit/slim_lint.rb +19 -0
  25. data/lib/overcommit/hook/pre_commit/trailing_whitespace.rb +4 -4
  26. data/lib/overcommit/hook/pre_commit/vint.rb +18 -0
  27. data/lib/overcommit/hook/pre_rebase/merged_commits.rb +29 -0
  28. data/lib/overcommit/hook/shared/index_tags.rb +10 -0
  29. data/lib/overcommit/hook/shared/submodule_status.rb +30 -0
  30. data/lib/overcommit/hook_context/base.rb +19 -5
  31. data/lib/overcommit/hook_context/commit_msg.rb +4 -0
  32. data/lib/overcommit/hook_context/pre_commit.rb +8 -1
  33. data/lib/overcommit/hook_context/run_all.rb +2 -3
  34. data/lib/overcommit/installer.rb +2 -2
  35. data/lib/overcommit/interrupt_handler.rb +6 -4
  36. data/lib/overcommit/logger.rb +1 -1
  37. data/lib/overcommit/utils.rb +1 -0
  38. data/lib/overcommit/version.rb +1 -1
  39. metadata +10 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1724df298bed7ee6665d38277209a8e87a879200
4
- data.tar.gz: 6bb28a0b762eb3e730611210601d26da60f07a1b
3
+ metadata.gz: bbe6329a0cba58948e9ee76c415c994a7853076e
4
+ data.tar.gz: 8ccb39fc02ed962de60f1dd89398ed77e6c63187
5
5
  SHA512:
6
- metadata.gz: 703cb3fb8202cecbe1a06723fe6f2e45ae224b4be04cc7b71f88fc4586b463bb560cefdbdb43ed635f3814c6fc9c785ee68a667d435cf959e3a3a8c2849779d6
7
- data.tar.gz: ea54648808464b479781a4991b08de8225bd0d00b0b95813ec080e439725dcf193c56631d648a552d2694eee26d6d9fa37302faf996bbedbb01d14d68370ec85
6
+ metadata.gz: 8239e6a77a599153d4f6d30a23b329f7aa6d2c6b46ed001ce9dc1b0f4a3014b17fa65de8f8b004956271d989eb9a200dee2ee67ebb782e1bfa82b60fa2623744
7
+ data.tar.gz: 2e569ffcb8e328e0033913866e12230674b6ff42df2c955df0d0e87b0bdaa03fc0e628628bae01b42e68ba471d5cdb3b1ff26862c9baffc0916f3e9d550b7ab4
data/config/default.yml CHANGED
@@ -204,9 +204,10 @@ PreCommit:
204
204
  install_command: 'gem install image_optim'
205
205
  include:
206
206
  - '**/*.gif'
207
- - '**/*.jpg'
208
207
  - '**/*.jpeg'
208
+ - '**/*.jpg'
209
209
  - '**/*.png'
210
+ - '**/*.svg'
210
211
 
211
212
  JavaCheckstyle:
212
213
  enabled: false
@@ -257,7 +258,7 @@ PreCommit:
257
258
  enabled: false
258
259
  description: 'Checking for local paths in Gemfile'
259
260
  required_executable: 'grep'
260
- flags: ['-IHnE', '^[^#]*((\bpath:)|(:path\s*=>))']
261
+ flags: ['-IHnE', "^[^#]*((\\bpath:)|(:path[ \t]*=>))"]
261
262
  include: '**/Gemfile'
262
263
 
263
264
  MergeConflicts:
@@ -265,7 +266,7 @@ PreCommit:
265
266
  description: 'Checking for merge conflicts'
266
267
  quiet: true
267
268
  required_executable: 'grep'
268
- flags: ['-IHn', '^<<<<<<<\s']
269
+ flags: ['-IHn', "^<<<<<<<[ \t]"]
269
270
 
270
271
  Pep257:
271
272
  enabled: false
@@ -327,9 +328,9 @@ PreCommit:
327
328
  - '**/Gemfile'
328
329
  - '**/Rakefile'
329
330
 
330
- Rubocop:
331
+ RuboCop:
331
332
  enabled: false
332
- description: 'Analyzing with Rubocop'
333
+ description: 'Analyzing with RuboCop'
333
334
  required_executable: 'rubocop'
334
335
  flags: ['--format=emacs', '--force-exclusion', '--display-cop-names']
335
336
  install_command: 'gem install rubocop'
@@ -350,6 +351,13 @@ PreCommit:
350
351
  - '**/*.gemspec'
351
352
  - '**/*.rb'
352
353
 
354
+ Scalariform:
355
+ enabled: false
356
+ description: 'Checking formatting with Scalariform'
357
+ required_executable: 'scalariform'
358
+ flags: ['--test']
359
+ include: '**/*.scala'
360
+
353
361
  Scalastyle:
354
362
  enabled: false
355
363
  description: 'Analyzing with Scalastyle'
@@ -378,6 +386,13 @@ PreCommit:
378
386
  flags: ['--format=gcc']
379
387
  include: '**/*.sh'
380
388
 
389
+ SlimLint:
390
+ enabled: false
391
+ description: 'Analyzing with slim-lint'
392
+ required_executable: 'slim-lint'
393
+ install_command: 'gem install slim_lint'
394
+ include: '**/*.slim'
395
+
381
396
  Standard:
382
397
  enabled: false
383
398
  description: 'Analyzing with standard'
@@ -390,7 +405,7 @@ PreCommit:
390
405
  enabled: false
391
406
  description: 'Checking for trailing whitespace'
392
407
  required_executable: 'grep'
393
- flags: ['-IHn', '\s$']
408
+ flags: ['-IHn', "[ \t]$"]
394
409
 
395
410
  TravisLint:
396
411
  enabled: false
@@ -400,6 +415,15 @@ PreCommit:
400
415
  install_command: 'gem install travis'
401
416
  include: '.travis.yml'
402
417
 
418
+ Vint:
419
+ enabled: false
420
+ description: 'Analyzing with Vint'
421
+ required_executable: 'vint'
422
+ install_command: 'pip install vim-vint'
423
+ include:
424
+ - '**/*.vim'
425
+ - '**/*.vimrc'
426
+
403
427
  W3cCss:
404
428
  enabled: false
405
429
  description: 'Analyzing with W3C CSS validation service'
@@ -428,13 +452,17 @@ PreCommit:
428
452
  description: 'Analyzing with xmllint'
429
453
  required_executable: 'xmllint'
430
454
  flags: ['--noout']
431
- include: '**/*.xml'
455
+ include:
456
+ - '**/*.xml'
457
+ - '**/*.svg'
432
458
 
433
459
  XmlSyntax:
434
460
  enabled: false
435
461
  description: 'Checking XML syntax'
436
462
  required_library: 'rexml/document'
437
- include: '**/*.xml'
463
+ include:
464
+ - '**/*.xml'
465
+ - '**/*.svg'
438
466
 
439
467
  YamlSyntax:
440
468
  enabled: false
@@ -453,6 +481,7 @@ PostCheckout:
453
481
  IndexTags:
454
482
  enabled: false
455
483
  description: 'Generating tags file from source'
484
+ quiet: true
456
485
  required_executable: 'ctags'
457
486
 
458
487
  SubmoduleStatus:
@@ -479,6 +508,7 @@ PostCommit:
479
508
  IndexTags:
480
509
  enabled: false
481
510
  description: 'Generating tags file from source'
511
+ quiet: true
482
512
  required_executable: 'ctags'
483
513
 
484
514
  SubmoduleStatus:
@@ -496,6 +526,7 @@ PostMerge:
496
526
  IndexTags:
497
527
  enabled: false
498
528
  description: 'Generating tags file from source'
529
+ quiet: true
499
530
  required_executable: 'ctags'
500
531
 
501
532
  SubmoduleStatus:
@@ -513,6 +544,7 @@ PostRewrite:
513
544
  IndexTags:
514
545
  enabled: false
515
546
  description: 'Generating tags file from source'
547
+ quiet: true
516
548
  required_executable: 'ctags'
517
549
 
518
550
  SubmoduleStatus:
@@ -546,3 +578,8 @@ PreRebase:
546
578
  requires_files: false
547
579
  required: false
548
580
  quiet: false
581
+
582
+ MergedCommits:
583
+ enabled: false
584
+ description: 'Checking for commits that have already been merged'
585
+ branches: ['master']
@@ -69,7 +69,7 @@ module Overcommit
69
69
  refs = options[:refs]
70
70
  subcmd = options[:subcmd] || 'diff'
71
71
 
72
- `git #{subcmd} --no-ext-diff -U0 #{flags} #{refs} -- '#{file_path}'`.
72
+ `git #{subcmd} --no-ext-diff -U0 #{flags} #{refs} -- "#{file_path}"`.
73
73
  scan(DIFF_HUNK_REGEX) do |start_line, lines_added|
74
74
  lines_added = (lines_added || 1).to_i # When blank, one line was added
75
75
  cur_line = start_line.to_i
@@ -134,7 +134,7 @@ module Overcommit
134
134
  #
135
135
  # Restored via [#restore_merge_state].
136
136
  def store_merge_state
137
- merge_head = `git rev-parse MERGE_HEAD 2> /dev/null`.chomp
137
+ merge_head = `git rev-parse MERGE_HEAD 2> #{File::NULL}`.chomp
138
138
 
139
139
  # Store the merge state if we're in the middle of resolving a merge
140
140
  # conflict. This is necessary since stashing removes the merge state.
@@ -151,7 +151,7 @@ module Overcommit
151
151
  #
152
152
  # Restored via [#restore_cherry_pick_state].
153
153
  def store_cherry_pick_state
154
- cherry_head = `git rev-parse CHERRY_PICK_HEAD 2> /dev/null`.chomp
154
+ cherry_head = `git rev-parse CHERRY_PICK_HEAD 2> #{File::NULL}`.chomp
155
155
 
156
156
  # Store the merge state if we're in the middle of resolving a merge
157
157
  # conflict. This is necessary since stashing removes the merge state.
@@ -167,7 +167,7 @@ module Overcommit
167
167
  FileUtils.touch(File.expand_path('MERGE_MODE', Overcommit::Utils.git_dir))
168
168
 
169
169
  File.open(File.expand_path('MERGE_HEAD', Overcommit::Utils.git_dir), 'w') do |f|
170
- f.write("#{@merge_head}\n")
170
+ f.write(@merge_head)
171
171
  end
172
172
  @merge_head = nil
173
173
  end
@@ -186,7 +186,7 @@ module Overcommit
186
186
  if @cherry_head
187
187
  File.open(File.expand_path('CHERRY_PICK_HEAD',
188
188
  Overcommit::Utils.git_dir), 'w') do |f|
189
- f.write("#{@cherry_head}\n")
189
+ f.write(@cherry_head)
190
190
  end
191
191
  @cherry_head = nil
192
192
  end
@@ -248,5 +248,16 @@ module Overcommit
248
248
  raise Overcommit::Exceptions::GitSubmoduleError,
249
249
  "Unable to read submodule information from #{ref}:.gitmodules file: #{ex.message}"
250
250
  end
251
+
252
+ # Returns the names of all branches containing the given commit.
253
+ #
254
+ # @param commit_ref [String] git tree ref that resolves to a commit
255
+ # @return [Array<String>] list of branches containing the given commit
256
+ def branches_containing_commit(commit_ref)
257
+ `git branch --column=dense --contains #{commit_ref}`.
258
+ sub(/\((HEAD )?detached (from|at) .*?\)/, ''). # ignore detached HEAD
259
+ split(/\s+/).
260
+ reject { |s| s.empty? || s == '*' }
261
+ end
251
262
  end
252
263
  end
@@ -9,7 +9,7 @@
9
9
  # end
10
10
  module Overcommit
11
11
  GIT_VERSION = begin
12
- version = `git --version`.chomp[/[\d\.]+/, 0]
12
+ version = `git --version`.chomp[/\d+(\.\d+)+/, 0]
13
13
  Overcommit::Utils::Version.new(version)
14
14
  end
15
15
  end
@@ -5,7 +5,8 @@ module Overcommit::Hook::CommitMsg
5
5
  class Base < Overcommit::Hook::Base
6
6
  extend Forwardable
7
7
 
8
- def_delegators :@context, :commit_message, :update_commit_message,
9
- :commit_message_lines, :commit_message_file
8
+ def_delegators :@context, :empty_message?, :commit_message,
9
+ :update_commit_message, :commit_message_lines,
10
+ :commit_message_file
10
11
  end
11
12
  end
@@ -2,6 +2,8 @@ module Overcommit::Hook::CommitMsg
2
2
  # Ensures commit message subject lines start with a capital letter.
3
3
  class CapitalizedSubject < Base
4
4
  def run
5
+ return :pass if empty_message?
6
+
5
7
  first_letter = commit_message_lines[0].to_s.match(/^[[:punct:]]*(.)/)[1]
6
8
  unless first_letter.match(/[[:upper:]]/)
7
9
  return :warn, 'Subject should start with a capital letter'
@@ -2,6 +2,8 @@ module Overcommit::Hook::CommitMsg
2
2
  # Checks for hard tabs in commit messages.
3
3
  class HardTabs < Base
4
4
  def run
5
+ return :pass if empty_message?
6
+
5
7
  # Catches hard tabs entered by the user (not auto-generated)
6
8
  if commit_message.index(/\t/)
7
9
  return :warn, "Don't use hard tabs in commit messages"
@@ -2,6 +2,8 @@ module Overcommit::Hook::CommitMsg
2
2
  # Ensures commit message subject lines are followed by a blank line.
3
3
  class SingleLineSubject < Base
4
4
  def run
5
+ return :pass if empty_message?
6
+
5
7
  unless commit_message_lines[1].to_s.strip.empty?
6
8
  return :warn, 'Subject should be one line and followed by a blank line'
7
9
  end
@@ -3,6 +3,8 @@ module Overcommit::Hook::CommitMsg
3
3
  # under the preferred limits.
4
4
  class TextWidth < Base
5
5
  def run
6
+ return :pass if empty_message?
7
+
6
8
  @errors = []
7
9
 
8
10
  find_errors_in_subject(commit_message_lines.first)
@@ -2,6 +2,8 @@ module Overcommit::Hook::CommitMsg
2
2
  # Ensures commit message subject lines do not have a trailing period
3
3
  class TrailingPeriod < Base
4
4
  def run
5
+ return :pass if empty_message?
6
+
5
7
  if commit_message_lines.first.rstrip.end_with?('.')
6
8
  return :warn, 'Please omit trailing period from commit message subject'
7
9
  end
@@ -1,9 +1,8 @@
1
+ require 'overcommit/hook/shared/index_tags'
2
+
1
3
  module Overcommit::Hook::PostCheckout
2
4
  # Updates ctags index for all source code in the repository.
3
5
  class IndexTags < Base
4
- def run
5
- execute_in_background([Overcommit::Utils.script_path('index-tags')])
6
- :pass
7
- end
6
+ include Overcommit::Hook::Shared::IndexTags
8
7
  end
9
8
  end
@@ -1,30 +1,10 @@
1
+ require 'overcommit/hook/shared/submodule_status'
2
+
1
3
  module Overcommit::Hook::PostCheckout
2
4
  # Checks the status of submodules in the current repository and
3
5
  # notifies the user if any are uninitialized, out of date with
4
6
  # the current index, or contain merge conflicts.
5
7
  class SubmoduleStatus < Base
6
- def run
7
- messages = []
8
- submodule_statuses.each do |submodule_status|
9
- path = submodule_status.path
10
- if submodule_status.uninitialized?
11
- messages << "Submodule #{path} is uninitialized."
12
- elsif submodule_status.outdated?
13
- messages << "Submodule #{path} is out of date with the current index."
14
- elsif submodule_status.merge_conflict?
15
- messages << "Submodule #{path} has merge conflicts."
16
- end
17
- end
18
-
19
- return :pass if messages.empty?
20
-
21
- [:warn, messages.join("\n")]
22
- end
23
-
24
- private
25
-
26
- def submodule_statuses
27
- Overcommit::GitRepo.submodule_statuses(recursive: config['recursive'])
28
- end
8
+ include Overcommit::Hook::Shared::SubmoduleStatus
29
9
  end
30
10
  end
@@ -1,9 +1,8 @@
1
+ require 'overcommit/hook/shared/index_tags'
2
+
1
3
  module Overcommit::Hook::PostCommit
2
4
  # Updates ctags index for all source code in the repository.
3
5
  class IndexTags < Base
4
- def run
5
- execute_in_background([Overcommit::Utils.script_path('index-tags')])
6
- :pass
7
- end
6
+ include Overcommit::Hook::Shared::IndexTags
8
7
  end
9
8
  end
@@ -1,30 +1,10 @@
1
+ require 'overcommit/hook/shared/submodule_status'
2
+
1
3
  module Overcommit::Hook::PostCommit
2
4
  # Checks the status of submodules in the current repository and
3
5
  # notifies the user if any are uninitialized, out of date with
4
6
  # the current index, or contain merge conflicts.
5
7
  class SubmoduleStatus < Base
6
- def run
7
- messages = []
8
- submodule_statuses.each do |submodule_status|
9
- path = submodule_status.path
10
- if submodule_status.uninitialized?
11
- messages << "Submodule #{path} is uninitialized."
12
- elsif submodule_status.outdated?
13
- messages << "Submodule #{path} is out of date with the current index."
14
- elsif submodule_status.merge_conflict?
15
- messages << "Submodule #{path} has merge conflicts."
16
- end
17
- end
18
-
19
- return :pass if messages.empty?
20
-
21
- [:warn, messages.join("\n")]
22
- end
23
-
24
- private
25
-
26
- def submodule_statuses
27
- Overcommit::GitRepo.submodule_statuses(recursive: config['recursive'])
28
- end
8
+ include Overcommit::Hook::Shared::SubmoduleStatus
29
9
  end
30
10
  end
@@ -1,9 +1,8 @@
1
+ require 'overcommit/hook/shared/index_tags'
2
+
1
3
  module Overcommit::Hook::PostMerge
2
4
  # Updates ctags index for all source code in the repository.
3
5
  class IndexTags < Base
4
- def run
5
- execute_in_background([Overcommit::Utils.script_path('index-tags')])
6
- :pass
7
- end
6
+ include Overcommit::Hook::Shared::IndexTags
8
7
  end
9
8
  end
@@ -1,30 +1,10 @@
1
+ require 'overcommit/hook/shared/submodule_status'
2
+
1
3
  module Overcommit::Hook::PostMerge
2
4
  # Checks the status of submodules in the current repository and
3
5
  # notifies the user if any are uninitialized, out of date with
4
6
  # the current index, or contain merge conflicts.
5
7
  class SubmoduleStatus < Base
6
- def run
7
- messages = []
8
- submodule_statuses.each do |submodule_status|
9
- path = submodule_status.path
10
- if submodule_status.uninitialized?
11
- messages << "Submodule #{path} is uninitialized."
12
- elsif submodule_status.outdated?
13
- messages << "Submodule #{path} is out of date with the current index."
14
- elsif submodule_status.merge_conflict?
15
- messages << "Submodule #{path} has merge conflicts."
16
- end
17
- end
18
-
19
- return :pass if messages.empty?
20
-
21
- [:warn, messages.join("\n")]
22
- end
23
-
24
- private
25
-
26
- def submodule_statuses
27
- Overcommit::GitRepo.submodule_statuses(recursive: config['recursive'])
28
- end
8
+ include Overcommit::Hook::Shared::SubmoduleStatus
29
9
  end
30
10
  end
@@ -1,12 +1,15 @@
1
+ require 'overcommit/hook/shared/index_tags'
2
+
1
3
  module Overcommit::Hook::PostRewrite
2
4
  # Updates ctags index for all source code in the repository.
3
5
  class IndexTags < Base
6
+ include Overcommit::Hook::Shared::IndexTags
7
+
4
8
  def run
5
9
  # Ignore unless this is a rebase (amends are covered by post-commit hook)
6
10
  return :pass unless rebase?
7
11
 
8
- execute_in_background([Overcommit::Utils.script_path('index-tags')])
9
- :pass
12
+ super
10
13
  end
11
14
  end
12
15
  end
@@ -1,30 +1,10 @@
1
+ require 'overcommit/hook/shared/submodule_status'
2
+
1
3
  module Overcommit::Hook::PostRewrite
2
4
  # Checks the status of submodules in the current repository and
3
5
  # notifies the user if any are uninitialized, out of date with
4
6
  # the current index, or contain merge conflicts.
5
7
  class SubmoduleStatus < Base
6
- def run
7
- messages = []
8
- submodule_statuses.each do |submodule_status|
9
- path = submodule_status.path
10
- if submodule_status.uninitialized?
11
- messages << "Submodule #{path} is uninitialized."
12
- elsif submodule_status.outdated?
13
- messages << "Submodule #{path} is out of date with the current index."
14
- elsif submodule_status.merge_conflict?
15
- messages << "Submodule #{path} has merge conflicts."
16
- end
17
- end
18
-
19
- return :pass if messages.empty?
20
-
21
- [:warn, messages.join("\n")]
22
- end
23
-
24
- private
25
-
26
- def submodule_statuses
27
- Overcommit::GitRepo.submodule_statuses(recursive: config['recursive'])
28
- end
8
+ include Overcommit::Hook::Shared::SubmoduleStatus
29
9
  end
30
10
  end
@@ -7,8 +7,8 @@ module Overcommit::Hook::PreCommit
7
7
 
8
8
  unless name.split(' ').count >= 2
9
9
  return :fail,
10
- "Author must have at least first and last name, but was: #{name}." \
11
- "\nSet your name with `git config --global user.name 'Your Name'`"
10
+ "Author must have at least first and last name, but was: #{name}.\n" \
11
+ 'Set your name with `git config --global user.name "Your Name"`'
12
12
  end
13
13
 
14
14
  :pass
@@ -32,7 +32,7 @@ module Overcommit::Hook::PreCommit
32
32
  end
33
33
 
34
34
  file = extract_file(match, message)
35
- line = extract_line(match, message) unless match[:line].nil?
35
+ line = extract_line(match, message) if match.names.include?('line') && match[:line]
36
36
  type = extract_type(match, message, type_categorizer)
37
37
 
38
38
  Overcommit::Hook::Message.new(type, file, line, message)
@@ -2,13 +2,12 @@ module Overcommit::Hook::PreCommit
2
2
  # Checks for hard tabs in files.
3
3
  class HardTabs < Base
4
4
  def run
5
- # Catches hard tabs
6
5
  result = execute(command + applicable_files)
7
- unless result.stdout.empty?
8
- return :fail, "Hard tabs detected:\n#{result.stdout}"
9
- end
10
6
 
11
- :pass
7
+ extract_messages(
8
+ result.stdout.split("\n"),
9
+ /^(?<file>[^:]+):(?<line>\d+)/,
10
+ )
12
11
  end
13
12
  end
14
13
  end
@@ -1,6 +1,6 @@
1
1
  module Overcommit::Hook::PreCommit
2
2
  # Runs `rubocop` against any modified Ruby files.
3
- class Rubocop < Base
3
+ class RuboCop < Base
4
4
  MESSAGE_TYPE_CATEGORIZER = lambda do |type|
5
5
  type.include?('W') ? :warning : :error
6
6
  end
@@ -0,0 +1,18 @@
1
+ module Overcommit::Hook::PreCommit
2
+ # Runs `scalariform` against any modified Scala files.
3
+ class Scalariform < Base
4
+ MESSAGE_REGEX = /^\[(?<type>FAILED|ERROR)\]\s+(?<file>.+)/
5
+
6
+ def run
7
+ result = execute(command + applicable_files)
8
+
9
+ # example message:
10
+ # [FAILED] path/to/file.scala
11
+ extract_messages(
12
+ result.stdout.split("\n").grep(MESSAGE_REGEX),
13
+ MESSAGE_REGEX,
14
+ lambda { |type| type == 'ERROR' ? :error : :warning }
15
+ )
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,19 @@
1
+ module Overcommit::Hook::PreCommit
2
+ # Runs `slim-lint` against any modified Slim templates.
3
+ class SlimLint < Base
4
+ MESSAGE_TYPE_CATEGORIZER = lambda do |type|
5
+ type.include?('W') ? :warning : :error
6
+ end
7
+
8
+ def run
9
+ result = execute(command + applicable_files)
10
+ return :pass if result.success?
11
+
12
+ extract_messages(
13
+ result.stdout.split("\n"),
14
+ /^(?<file>[^:]+):(?<line>\d+)[^ ]* (?<type>[^ ]+)/,
15
+ MESSAGE_TYPE_CATEGORIZER,
16
+ )
17
+ end
18
+ end
19
+ end
@@ -3,11 +3,11 @@ module Overcommit::Hook::PreCommit
3
3
  class TrailingWhitespace < Base
4
4
  def run
5
5
  result = execute(command + applicable_files)
6
- unless result.stdout.empty?
7
- return :fail, "Trailing whitespace detected:\n#{result.stdout}"
8
- end
9
6
 
10
- :pass
7
+ extract_messages(
8
+ result.stdout.split("\n"),
9
+ /^(?<file>[^:]+):(?<line>\d+)/,
10
+ )
11
11
  end
12
12
  end
13
13
  end
@@ -0,0 +1,18 @@
1
+ module Overcommit::Hook::PreCommit
2
+ # Runs `vint` against any modified Vim script files.
3
+ class Vint < Base
4
+ def run
5
+ result = execute(command + applicable_files)
6
+ return :pass if result.success?
7
+
8
+ return [:fail, result.stderr] unless result.stderr.empty?
9
+
10
+ # example message:
11
+ # path/to/file.vim:1:1: Error message
12
+ extract_messages(
13
+ result.stdout.split("\n"),
14
+ /^(?<file>[^:]+):(?<line>\d+)/
15
+ )
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,29 @@
1
+ module Overcommit::Hook::PreRebase
2
+ # Prevents rebasing commits that have already been merged into one of
3
+ # a specified set of branches.
4
+ class MergedCommits < Base
5
+ def run
6
+ # Allow rebasing a detached HEAD since no refs are changed.
7
+ return :pass if detached_head? || illegal_commits.empty?
8
+
9
+ message = 'Cannot rebase commits that have already been merged into ' \
10
+ "one of #{branches.join(', ')}"
11
+
12
+ [:fail, message]
13
+ end
14
+
15
+ private
16
+
17
+ def branches
18
+ @branches ||= config['branches']
19
+ end
20
+
21
+ def illegal_commits
22
+ @illegal_commits ||= rebased_commits.select do |commit_sha1|
23
+ branches_containing_commit =
24
+ Overcommit::GitRepo.branches_containing_commit(commit_sha1)
25
+ (branches_containing_commit & branches).any?
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,10 @@
1
+ module Overcommit::Hook::Shared
2
+ # Shared code used by all IndexTags hooks. It runs ctags in the background so
3
+ # your tag definitions are up-to-date.
4
+ module IndexTags
5
+ def run
6
+ execute_in_background([Overcommit::Utils.script_path('index-tags')])
7
+ :pass
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,30 @@
1
+ module Overcommit::Hook::Shared
2
+ # Shared code used by all `SubmoduleStatus` hooks to notify the user if any
3
+ # submodules are uninitialized, out of date with the current index, or contain
4
+ # merge conflicts.
5
+ module SubmoduleStatus
6
+ def run
7
+ messages = []
8
+ submodule_statuses.each do |submodule_status|
9
+ path = submodule_status.path
10
+ if submodule_status.uninitialized?
11
+ messages << "Submodule #{path} is uninitialized."
12
+ elsif submodule_status.outdated?
13
+ messages << "Submodule #{path} is out of date with the current index."
14
+ elsif submodule_status.merge_conflict?
15
+ messages << "Submodule #{path} has merge conflicts."
16
+ end
17
+ end
18
+
19
+ return :pass if messages.empty?
20
+
21
+ [:warn, messages.join("\n")]
22
+ end
23
+
24
+ private
25
+
26
+ def submodule_statuses
27
+ Overcommit::GitRepo.submodule_statuses(recursive: config['recursive'])
28
+ end
29
+ end
30
+ end
@@ -1,5 +1,3 @@
1
- require 'set'
2
-
3
1
  module Overcommit::HookContext
4
2
  # Contains helpers related to the context with which a hook is being run.
5
3
  #
@@ -10,9 +8,14 @@ module Overcommit::HookContext
10
8
  # This is also important to house in a separate object so that any
11
9
  # calculations can be memoized across all hooks in a single object, which
12
10
  # helps with performance.
11
+ #
12
+ # @abstract
13
13
  class Base
14
+ # Creates a hook context from the given configuration and input options.
15
+ #
14
16
  # @param config [Overcommit::Configuration]
15
17
  # @param args [Array<String>]
18
+ # @param input [IO] standard input stream
16
19
  def initialize(config, args, input)
17
20
  @config = config
18
21
  @args = args
@@ -20,16 +23,22 @@ module Overcommit::HookContext
20
23
  end
21
24
 
22
25
  # Returns the camel-cased type of this hook (e.g. PreCommit)
26
+ #
27
+ # @return [String]
23
28
  def hook_class_name
24
29
  self.class.name.split('::').last
25
30
  end
26
31
 
27
32
  # Returns the snake-cased type of this hook (e.g. pre_commit)
33
+ #
34
+ # @return [String]
28
35
  def hook_type_name
29
36
  Overcommit::Utils.snake_case(hook_class_name)
30
37
  end
31
38
 
32
39
  # Returns the actual name of the hook script being run (e.g. pre-commit).
40
+ #
41
+ # @return [String]
33
42
  def hook_script_name
34
43
  hook_type_name.gsub('_', '-')
35
44
  end
@@ -39,7 +48,7 @@ module Overcommit::HookContext
39
48
  # This is called before the hooks are run by the [HookRunner]. Different
40
49
  # hook types can perform different setup.
41
50
  def setup_environment
42
- # Implemented by subclass
51
+ # Implemented by subclass, if applicable
43
52
  end
44
53
 
45
54
  # Resets the environment to an appropriate state.
@@ -48,18 +57,23 @@ module Overcommit::HookContext
48
57
  # Different hook types can perform different cleanup operations, which are
49
58
  # intended to "undo" the results of the call to {#setup_environment}.
50
59
  def cleanup_environment
51
- # Implemented by subclass
60
+ # Implemented by subclass, if applicable
52
61
  end
53
62
 
54
63
  # Returns a list of files that have been modified.
55
64
  #
56
65
  # By default, this returns an empty list. Subclasses should implement if
57
66
  # there is a concept of files changing for the type of hook being run.
67
+ #
68
+ # @return [Array<String>]
58
69
  def modified_files
59
70
  []
60
71
  end
61
72
 
62
- # Returns an array of lines passed to the hook via STDIN.
73
+ # Returns an array of lines passed to the hook via the standard input
74
+ # stream.
75
+ #
76
+ # @return [Array<String>]
63
77
  def input_lines
64
78
  @input_lines ||= @input.read.split("\n")
65
79
  end
@@ -1,6 +1,10 @@
1
1
  module Overcommit::HookContext
2
2
  # Contains helpers related to contextual information used by commit-msg hooks.
3
3
  class CommitMsg < Base
4
+ def empty_message?
5
+ commit_message.strip.empty?
6
+ end
7
+
4
8
  # User commit message stripped of comments and diff (from verbose output).
5
9
  def commit_message
6
10
  commit_message_lines.join
@@ -20,7 +20,7 @@ module Overcommit::HookContext
20
20
  @amendment = !(/\s#{amend_pattern}/ =~ cmd).nil?
21
21
 
22
22
  # Check for git aliases that call `commit --amend`
23
- `git config --get-regexp '^alias\\.' '#{amend_pattern}'`.
23
+ `git config --get-regexp "^alias\\." "#{amend_pattern}"`.
24
24
  scan(/alias\.([-\w]+)/). # Extract the alias
25
25
  each do |match|
26
26
  return @amendment if
@@ -94,6 +94,13 @@ module Overcommit::HookContext
94
94
  if amendment?
95
95
  subcmd = 'show --format=%n'
96
96
  @modified_files += Overcommit::GitRepo.modified_files(subcmd: subcmd)
97
+
98
+ # Filter out directories. This could happen when changing a symlink to
99
+ # a directory as part of an amendment, since the symlink will still
100
+ # appear as a file, but the actual working tree will have a directory.
101
+ @modified_files.reject! do |file|
102
+ File.directory?(file) && !File.symlink?(file)
103
+ end
97
104
  end
98
105
  end
99
106
  @modified_files
@@ -17,7 +17,7 @@ module Overcommit::HookContext
17
17
  # @return [Set]
18
18
  def modified_lines_in_file(file)
19
19
  @modified_lines_in_file ||= {}
20
- @modified_lines_in_file[file] ||= Set.new(1..(count_lines(file) + 1))
20
+ @modified_lines_in_file[file] ||= Set.new(1..count_lines(file))
21
21
  end
22
22
 
23
23
  def hook_class_name
@@ -35,8 +35,7 @@ module Overcommit::HookContext
35
35
  private
36
36
 
37
37
  def count_lines(file)
38
- result = Overcommit::Utils.execute(%w[wc -l] + [file])
39
- result.success? ? result.stdout.to_i : 0
38
+ File.foreach(file).count
40
39
  end
41
40
  end
42
41
  end
@@ -100,7 +100,7 @@ module Overcommit
100
100
  end
101
101
 
102
102
  def uninstall_master_hook
103
- FileUtils.rm_rf(master_hook_install_path)
103
+ FileUtils.rm_rf(master_hook_install_path, secure: true)
104
104
  end
105
105
 
106
106
  def install_hook_symlinks
@@ -162,7 +162,7 @@ module Overcommit
162
162
 
163
163
  Dir.chdir(hooks_path) do
164
164
  Overcommit::Utils.supported_hook_types.each do |hook_type|
165
- FileUtils.rm_rf(hook_type) if overcommit_hook?(hook_type)
165
+ FileUtils.rm_rf(hook_type, secure: true) if overcommit_hook?(hook_type)
166
166
  end
167
167
  end
168
168
  end
@@ -7,6 +7,7 @@ class InterruptHandler
7
7
 
8
8
  attr_accessor :isolate_signals, :signal_received, :reenable_on_interrupt
9
9
 
10
+ # Initialize safe interrupt signal handling.
10
11
  def initialize
11
12
  self.isolate_signals = false
12
13
  self.signal_received = false
@@ -64,14 +65,19 @@ class InterruptHandler
64
65
  instance.isolate_signals = true
65
66
  end
66
67
 
68
+ # Disable interrupt isolation.
67
69
  def disable!
68
70
  instance.isolate_signals = false
69
71
  end
70
72
 
73
+ # Enable interrupt isolation.
71
74
  def enable!
72
75
  instance.isolate_signals = true
73
76
  end
74
77
 
78
+ # Enable interrupt isolation while executing the provided block.
79
+ #
80
+ # @yield block to execute with interrupt isolation
75
81
  def isolate_from_interrupts
76
82
  instance.signal_received = false
77
83
  instance.isolate_signals = true
@@ -79,9 +85,5 @@ class InterruptHandler
79
85
  instance.isolate_signals = false
80
86
  result
81
87
  end
82
-
83
- def signal_received?
84
- instance.signal_received
85
- end
86
88
  end
87
89
  end
@@ -3,7 +3,7 @@ module Overcommit
3
3
  class Logger
4
4
  # Helper for creating a logger which outputs nothing.
5
5
  def self.silent
6
- new(File.open('/dev/null', 'w'))
6
+ new(File.open(File::NULL, 'w'))
7
7
  end
8
8
 
9
9
  # Creates a logger that will write to the given output stream.
@@ -91,6 +91,7 @@ module Overcommit
91
91
  def supported_hook_types
92
92
  Dir[File.join(HOOK_DIRECTORY, '*')].
93
93
  select { |file| File.directory?(file) }.
94
+ reject { |file| File.basename(file) == 'shared' }.
94
95
  map { |file| File.basename(file).gsub('_', '-') }
95
96
  end
96
97
 
@@ -1,4 +1,4 @@
1
1
  # Defines the gem version.
2
2
  module Overcommit
3
- VERSION = '0.24.0'
3
+ VERSION = '0.25.0'
4
4
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: overcommit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.24.0
4
+ version: 0.25.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brigade Engineering
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-04-13 00:00:00.000000000 Z
12
+ date: 2015-05-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: childprocess
@@ -158,15 +158,18 @@ files:
158
158
  - lib/overcommit/hook/pre_commit/python_flake8.rb
159
159
  - lib/overcommit/hook/pre_commit/rails_schema_up_to_date.rb
160
160
  - lib/overcommit/hook/pre_commit/reek.rb
161
- - lib/overcommit/hook/pre_commit/rubocop.rb
161
+ - lib/overcommit/hook/pre_commit/rubo_cop.rb
162
162
  - lib/overcommit/hook/pre_commit/ruby_lint.rb
163
+ - lib/overcommit/hook/pre_commit/scalariform.rb
163
164
  - lib/overcommit/hook/pre_commit/scalastyle.rb
164
165
  - lib/overcommit/hook/pre_commit/scss_lint.rb
165
166
  - lib/overcommit/hook/pre_commit/semi_standard.rb
166
167
  - lib/overcommit/hook/pre_commit/shell_check.rb
168
+ - lib/overcommit/hook/pre_commit/slim_lint.rb
167
169
  - lib/overcommit/hook/pre_commit/standard.rb
168
170
  - lib/overcommit/hook/pre_commit/trailing_whitespace.rb
169
171
  - lib/overcommit/hook/pre_commit/travis_lint.rb
172
+ - lib/overcommit/hook/pre_commit/vint.rb
170
173
  - lib/overcommit/hook/pre_commit/w3c_css.rb
171
174
  - lib/overcommit/hook/pre_commit/w3c_html.rb
172
175
  - lib/overcommit/hook/pre_commit/xml_lint.rb
@@ -176,6 +179,9 @@ files:
176
179
  - lib/overcommit/hook/pre_push/protected_branches.rb
177
180
  - lib/overcommit/hook/pre_push/r_spec.rb
178
181
  - lib/overcommit/hook/pre_rebase/base.rb
182
+ - lib/overcommit/hook/pre_rebase/merged_commits.rb
183
+ - lib/overcommit/hook/shared/index_tags.rb
184
+ - lib/overcommit/hook/shared/submodule_status.rb
179
185
  - lib/overcommit/hook_context.rb
180
186
  - lib/overcommit/hook_context/base.rb
181
187
  - lib/overcommit/hook_context/commit_msg.rb
@@ -232,7 +238,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
232
238
  version: '0'
233
239
  requirements: []
234
240
  rubyforge_project:
235
- rubygems_version: 2.2.2
241
+ rubygems_version: 2.4.5
236
242
  signing_key:
237
243
  specification_version: 4
238
244
  summary: Git hook manager