overcommit 0.24.0 → 0.25.0

Sign up to get free protection for your applications and to get access to all the features.
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