overcommit 0.17.0 → 0.18.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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/bin/overcommit +1 -3
  3. data/config/default.yml +38 -2
  4. data/lib/overcommit/cli.rb +37 -2
  5. data/lib/overcommit/configuration.rb +79 -15
  6. data/lib/overcommit/configuration_loader.rb +1 -1
  7. data/lib/overcommit/configuration_validator.rb +1 -1
  8. data/lib/overcommit/git_repo.rb +3 -3
  9. data/lib/overcommit/hook/base.rb +30 -2
  10. data/lib/overcommit/hook/post_checkout/index_tags.rb +1 -1
  11. data/lib/overcommit/hook/pre_commit/berksfile_check.rb +1 -5
  12. data/lib/overcommit/hook/pre_commit/brakeman.rb +1 -5
  13. data/lib/overcommit/hook/pre_commit/broken_symlinks.rb +15 -0
  14. data/lib/overcommit/hook/pre_commit/bundle_check.rb +2 -6
  15. data/lib/overcommit/hook/pre_commit/chamber_security.rb +1 -5
  16. data/lib/overcommit/hook/pre_commit/coffee_lint.rb +1 -5
  17. data/lib/overcommit/hook/pre_commit/css_lint.rb +1 -5
  18. data/lib/overcommit/hook/pre_commit/go_lint.rb +1 -5
  19. data/lib/overcommit/hook/pre_commit/haml_lint.rb +1 -5
  20. data/lib/overcommit/hook/pre_commit/image_optim.rb +2 -2
  21. data/lib/overcommit/hook/pre_commit/js_hint.rb +1 -5
  22. data/lib/overcommit/hook/pre_commit/jscs.rb +1 -5
  23. data/lib/overcommit/hook/pre_commit/jsx_hint.rb +1 -5
  24. data/lib/overcommit/hook/pre_commit/python_flake8.rb +1 -5
  25. data/lib/overcommit/hook/pre_commit/rails_schema_up_to_date.rb +2 -2
  26. data/lib/overcommit/hook/pre_commit/rubocop.rb +1 -5
  27. data/lib/overcommit/hook/pre_commit/scss_lint.rb +1 -5
  28. data/lib/overcommit/hook/pre_commit/travis_lint.rb +1 -5
  29. data/lib/overcommit/hook_context/commit_msg.rb +1 -1
  30. data/lib/overcommit/hook_context/pre_commit.rb +3 -1
  31. data/lib/overcommit/hook_loader/base.rb +1 -1
  32. data/lib/overcommit/hook_loader/plugin_hook_loader.rb +3 -3
  33. data/lib/overcommit/hook_runner.rb +1 -1
  34. data/lib/overcommit/hook_signer.rb +1 -1
  35. data/lib/overcommit/installer.rb +1 -1
  36. data/lib/overcommit/logger.rb +16 -15
  37. data/lib/overcommit/printer.rb +1 -1
  38. data/lib/overcommit/user_input.rb +1 -1
  39. data/lib/overcommit/utils.rb +10 -1
  40. data/lib/overcommit/version.rb +1 -1
  41. metadata +7 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 34fb07971b06d936af3a8a4b2cbd4584bfd96506
4
- data.tar.gz: a6201349bc528c292c3173d3b4c631dd0fdf76aa
3
+ metadata.gz: b609412f41e430a857ae1b1b9b5a3d31cf97eb9b
4
+ data.tar.gz: 1f3ebdf4981de86e51503d69fdc7ed851cb91aca
5
5
  SHA512:
6
- metadata.gz: 35ab2d145525645843ce83eada23ffda314dd443b792213e01dac7e19642a286c5e4fd719f14afcc25505a4fdd1a27f65ea7f1c721af0f572870dfd025d3d970
7
- data.tar.gz: 7074b3298a4276c38096f5f6020bf669148cf46591c4be95b67ecfe3af12caddfb09d4c380eab8d3372fae16bc0c8d12f85269beaca362c2725445b2f9252f31
6
+ metadata.gz: 46b3a66583a3522bbec747ba4a0a579839b5fe09ea77ac62b57149b52e7413b05388fbd1db399d953d2503ff590331f6d8bf789191f45983027aea6dd11bcbb2
7
+ data.tar.gz: 072a5ce0c265bc2da606332369a5e2ea53e77f4f4aec07b3f94f056fb2e8644358737192ff6c495a4e5fda27fd5fa9b3e5625ad58f916a562056195895e88d26
data/bin/overcommit CHANGED
@@ -5,6 +5,4 @@ require 'overcommit/cli'
5
5
 
6
6
  logger = Overcommit::Logger.new(STDOUT)
7
7
 
8
- Overcommit::CLI.new(ARGV, logger).tap do |cli|
9
- cli.run
10
- end
8
+ Overcommit::CLI.new(ARGV, logger).run
data/config/default.yml CHANGED
@@ -22,8 +22,8 @@ PostCheckout:
22
22
  required: false
23
23
  quiet: false
24
24
  IndexTags:
25
- description: 'Generating tags file from source'
26
25
  enabled: false
26
+ description: 'Generating tags file from source'
27
27
 
28
28
  # Hooks that are run after `git commit` is executed, before the commit message
29
29
  # editor is displayed. These hooks are ideal for syntax checkers, linters, and
@@ -50,6 +50,8 @@ PreCommit:
50
50
 
51
51
  BerksfileCheck:
52
52
  description: 'Checking Berksfile lock'
53
+ required_executable: 'berks'
54
+ install_command: 'gem install berks'
53
55
  include:
54
56
  - 'Berksfile'
55
57
  - 'Berksfile.lock'
@@ -57,11 +59,19 @@ PreCommit:
57
59
  Brakeman:
58
60
  enabled: false
59
61
  description: 'Checking for security vulnerabilities'
62
+ required_executable: 'brakeman'
63
+ install_command: 'gem install brakeman'
60
64
  include:
61
65
  - '**/*.rb'
62
66
 
67
+ BrokenSymlinks:
68
+ description: 'Checking for broken symlinks'
69
+ quiet: true
70
+
63
71
  BundleCheck:
64
72
  description: 'Checking Gemfile dependencies'
73
+ required_executable: 'bundle'
74
+ install_command: 'gem install bundler'
65
75
  include:
66
76
  - 'Gemfile'
67
77
  - 'Gemfile.lock'
@@ -70,22 +80,34 @@ PreCommit:
70
80
  ChamberSecurity:
71
81
  enabled: false
72
82
  description: 'Checking that settings have been secured with Chamber'
73
- include: 'config/settings.yml'
83
+ required_executable: 'chamber'
84
+ install_command: 'gem install chamber'
85
+ include:
86
+ - 'config/settings.yml'
87
+ - 'config/settings/**/*.yml'
74
88
 
75
89
  CoffeeLint:
76
90
  description: 'Analyzing with coffeelint'
91
+ required_executable: 'coffeelint'
92
+ install_command: 'npm install -g coffeelint'
77
93
  include: '**/*.coffee'
78
94
 
79
95
  CssLint:
80
96
  description: 'Analyzing with csslint'
97
+ required_executable: 'csslint'
98
+ install_command: 'npm install -g csslint'
81
99
  include: '**/*.css'
82
100
 
83
101
  GoLint:
84
102
  description: 'Analyzing with golint'
103
+ required_executable: 'golint'
104
+ install_command: 'go get github.com/golang/lint/golint'
85
105
  include: '**/*.go'
86
106
 
87
107
  HamlLint:
88
108
  description: 'Analyzing with haml-lint'
109
+ required_executable: 'haml-lint'
110
+ install_command: 'gem install haml-lint'
89
111
  include: '**/*.haml'
90
112
 
91
113
  HardTabs:
@@ -105,10 +127,14 @@ PreCommit:
105
127
 
106
128
  Jscs:
107
129
  description: 'Analyzing with JSCS'
130
+ required_executable: 'jscs'
131
+ install_command: 'npm install -g jscs'
108
132
  include: '**/*.js'
109
133
 
110
134
  JsHint:
111
135
  description: 'Analyzing with JSHint'
136
+ required_executable: 'jshint'
137
+ install_command: 'npm install -g jshint'
112
138
  include: '**/*.js'
113
139
 
114
140
  JsonSyntax:
@@ -117,6 +143,8 @@ PreCommit:
117
143
 
118
144
  JsxHint:
119
145
  description: 'Analyzing with JSXHint'
146
+ required_executable: 'jsxhint'
147
+ install_command: 'npm install -g jsxhint'
120
148
  include: '**/*.jsx'
121
149
 
122
150
  LocalPathsInGemfile:
@@ -134,6 +162,8 @@ PreCommit:
134
162
 
135
163
  PythonFlake8:
136
164
  description: 'Analyzing with flake8'
165
+ required_executable: 'flake8'
166
+ install_command: 'pip install flake8'
137
167
  include: '**/*.py'
138
168
 
139
169
  RailsSchemaUpToDate:
@@ -145,6 +175,8 @@ PreCommit:
145
175
 
146
176
  Rubocop:
147
177
  description: 'Analyzing with Rubocop'
178
+ required_executable: 'rubocop'
179
+ install_command: 'gem install rubocop'
148
180
  include:
149
181
  - '**/*.gemspec'
150
182
  - '**/*.rake'
@@ -154,6 +186,8 @@ PreCommit:
154
186
 
155
187
  ScssLint:
156
188
  description: 'Analyzing with scss-lint'
189
+ required_executable: 'scss-lint'
190
+ install_command: 'gem install scss-lint'
157
191
  include: '**/*.scss'
158
192
 
159
193
  TrailingWhitespace:
@@ -163,6 +197,8 @@ PreCommit:
163
197
 
164
198
  TravisLint:
165
199
  description: 'Checking Travis CI configuration'
200
+ required_executable: 'travis-lint'
201
+ install_command: 'gem install travis-lint'
166
202
  include: '.travis.yml'
167
203
 
168
204
  YamlSyntax:
@@ -3,7 +3,7 @@ require 'optparse'
3
3
  module Overcommit
4
4
  # Responsible for parsing command-line options and executing appropriate
5
5
  # application logic based on those options.
6
- class CLI
6
+ class CLI # rubocop:disable ClassLength
7
7
  def initialize(arguments, logger)
8
8
  @arguments = arguments
9
9
  @log = logger
@@ -21,7 +21,7 @@ module Overcommit
21
21
  end
22
22
  end
23
23
 
24
- private
24
+ private
25
25
 
26
26
  attr_reader :log
27
27
 
@@ -59,6 +59,10 @@ module Overcommit
59
59
  opts.on_tail('-v', '--version', 'Show version') do
60
60
  print_version(opts.program_name)
61
61
  end
62
+
63
+ opts.on_tail('-l', '--list-hooks', 'List installed hooks') do
64
+ print_installed_hooks
65
+ end
62
66
  end
63
67
 
64
68
  def add_installation_options(opts)
@@ -122,6 +126,37 @@ module Overcommit
122
126
  halt
123
127
  end
124
128
 
129
+ # Prints the hooks available in the current repo and whether they're
130
+ # enabled/disabled.
131
+ def print_installed_hooks
132
+ config = Overcommit::ConfigurationLoader.load_repo_config
133
+
134
+ config.all_hook_configs.each do |hook_type, hook_configs|
135
+ print_hooks_for_hook_type(config, hook_configs, hook_type)
136
+ end
137
+
138
+ halt
139
+ end
140
+
141
+ def print_hooks_for_hook_type(repo_config, hook_configs, hook_type)
142
+ log.log "#{hook_type}:"
143
+ hook_configs.each do |hook_name, config|
144
+ log.partial " #{hook_name}: "
145
+
146
+ if config['enabled']
147
+ log.success('enabled', true)
148
+ else
149
+ log.error('disabled', true)
150
+ end
151
+
152
+ if repo_config.plugin_hook?(hook_type, hook_name)
153
+ log.warning(' (plugin)')
154
+ else
155
+ log.log
156
+ end
157
+ end
158
+ end
159
+
125
160
  # Used for ease of stubbing in tests
126
161
  def halt(status = 0)
127
162
  exit status
@@ -1,6 +1,6 @@
1
1
  module Overcommit
2
2
  # Stores configuration for Overcommit and the hooks it runs.
3
- class Configuration
3
+ class Configuration # rubocop:disable ClassLength
4
4
  # Creates a configuration from the given hash.
5
5
  def initialize(hash)
6
6
  @hash = ConfigurationValidator.new.validate(hash)
@@ -21,6 +21,58 @@ module Overcommit
21
21
  @hash['verify_plugin_signatures'] != false
22
22
  end
23
23
 
24
+ # Returns configuration for all hooks in each hook type.
25
+ #
26
+ # @return [Hash]
27
+ def all_hook_configs
28
+ smart_merge(all_builtin_hook_configs, all_plugin_hook_configs)
29
+ end
30
+
31
+ # Returns configuration for all built-in hooks in each hook type.
32
+ #
33
+ # @return [Hash]
34
+ def all_builtin_hook_configs
35
+ hook_configs = {}
36
+
37
+ Overcommit::Utils.supported_hook_type_classes.each do |hook_type|
38
+ hook_names = @hash[hook_type].keys.reject { |name| name == 'ALL' }
39
+
40
+ hook_configs[hook_type] = Hash[
41
+ hook_names.map do |hook_name|
42
+ [hook_name, for_hook(hook_name, hook_type)]
43
+ end
44
+ ]
45
+ end
46
+
47
+ hook_configs
48
+ end
49
+
50
+ # Returns configuration for all plugin hooks in each hook type.
51
+ #
52
+ # @return [Hash]
53
+ def all_plugin_hook_configs
54
+ hook_configs = {}
55
+
56
+ Overcommit::Utils.supported_hook_types.each do |hook_type|
57
+ hook_type_class_name = Overcommit::Utils.camel_case(hook_type)
58
+
59
+ directory = File.join(plugin_directory, hook_type.gsub('-', '_'))
60
+ plugin_paths = Dir[File.join(directory, '*.rb')].sort
61
+
62
+ hook_names = plugin_paths.map do |path|
63
+ Overcommit::Utils.camel_case(File.basename(path, '.rb'))
64
+ end
65
+
66
+ hook_configs[hook_type_class_name] = Hash[
67
+ hook_names.map do |hook_name|
68
+ [hook_name, for_hook(hook_name, Overcommit::Utils.camel_case(hook_type))]
69
+ end
70
+ ]
71
+ end
72
+
73
+ hook_configs
74
+ end
75
+
24
76
  # Returns the built-in hooks that have been enabled for a hook type.
25
77
  def enabled_builtin_hooks(hook_context)
26
78
  @hash[hook_context.hook_class_name].keys.
@@ -38,7 +90,13 @@ module Overcommit
38
90
  end
39
91
 
40
92
  # Merge hook configuration with special 'ALL' config
41
- smart_merge(@hash[hook_type]['ALL'], @hash[hook_type][hook] || {}).freeze
93
+ hook_config = smart_merge(@hash[hook_type]['ALL'], @hash[hook_type][hook] || {})
94
+
95
+ # Need to specially handle `enabled` option since not setting it does not
96
+ # necessarily mean the hook is disabled
97
+ hook_config['enabled'] = hook_enabled?(hook_type, hook)
98
+
99
+ hook_config.freeze
42
100
  end
43
101
 
44
102
  # Merges the given configuration with this one, returning a new
@@ -66,11 +124,23 @@ module Overcommit
66
124
  end
67
125
  end
68
126
 
69
- protected
127
+ def plugin_hook?(hook_context_or_type, hook_name)
128
+ hook_type_name =
129
+ if hook_context_or_type.is_a?(String)
130
+ Overcommit::Utils.snake_case(hook_context_or_type)
131
+ else
132
+ hook_context_or_type.hook_type_name
133
+ end
134
+ hook_name = Overcommit::Utils.snake_case(hook_name)
135
+
136
+ File.exist?(File.join(plugin_directory, hook_type_name, "#{hook_name}.rb"))
137
+ end
138
+
139
+ protected
70
140
 
71
141
  attr_reader :hash
72
142
 
73
- private
143
+ private
74
144
 
75
145
  def built_in_hook?(hook_context, hook_name)
76
146
  hook_name = Overcommit::Utils.snake_case(hook_name)
@@ -79,22 +149,16 @@ module Overcommit
79
149
  hook_context.hook_type_name, "#{hook_name}.rb"))
80
150
  end
81
151
 
82
- def plugin_hook?(hook_context, hook_name)
83
- hook_name = Overcommit::Utils.snake_case(hook_name)
84
-
85
- File.exist?(File.join(plugin_directory,
86
- hook_context.hook_type_name,
87
- "#{hook_name}.rb"))
88
- end
89
-
90
152
  def hook_exists?(hook_context, hook_name)
91
153
  built_in_hook?(hook_context, hook_name) ||
92
154
  plugin_hook?(hook_context, hook_name)
93
155
  end
94
156
 
95
- def hook_enabled?(hook_context, hook_name)
96
- hook_type = hook_context.hook_class_name
97
- individual_enabled = @hash[hook_type][hook_name]['enabled']
157
+ def hook_enabled?(hook_context_or_type, hook_name)
158
+ hook_type = hook_context_or_type.is_a?(String) ? hook_context_or_type :
159
+ hook_context_or_type.hook_class_name
160
+
161
+ individual_enabled = @hash[hook_type].fetch(hook_name, {})['enabled']
98
162
  return individual_enabled unless individual_enabled.nil?
99
163
 
100
164
  all_enabled = @hash[hook_type]['ALL']['enabled']
@@ -21,7 +21,7 @@ module Overcommit
21
21
  @default_config ||= load_from_file(DEFAULT_CONFIG_PATH)
22
22
  end
23
23
 
24
- private
24
+ private
25
25
 
26
26
  # Loads a configuration, ensuring it extends the default configuration.
27
27
  def load_file(file)
@@ -9,7 +9,7 @@ module Overcommit
9
9
  hash
10
10
  end
11
11
 
12
- private
12
+ private
13
13
 
14
14
  # Ensures that keys for all supported hook types exist (PreCommit,
15
15
  # CommitMsg, etc.)
@@ -66,10 +66,10 @@ module Overcommit
66
66
  # conflict. This is necessary since stashing removes the merge state.
67
67
  if merge_head != 'MERGE_HEAD'
68
68
  @merge_head = merge_head
69
-
70
- merge_msg_file = File.expand_path('.git/MERGE_MSG', Overcommit::Utils.repo_root)
71
- @merge_msg = File.open(merge_msg_file).read if File.exist?(merge_msg_file)
72
69
  end
70
+
71
+ merge_msg_file = File.expand_path('.git/MERGE_MSG', Overcommit::Utils.repo_root)
72
+ @merge_msg = File.open(merge_msg_file).read if File.exist?(merge_msg_file)
73
73
  end
74
74
 
75
75
  # Store any relevant files that are present when repo is in the middle of a
@@ -8,6 +8,8 @@ module Overcommit::Hook
8
8
  def_delegators :@context, :modified_files
9
9
  attr_reader :config
10
10
 
11
+ # @param config [Overcommit::Configuration]
12
+ # @param context [Overcommit::HookContext]
11
13
  def initialize(config, context)
12
14
  @config = config.for_hook(self)
13
15
  @context = context
@@ -25,7 +27,11 @@ module Overcommit::Hook
25
27
  # implement `#run`, and we needed a wrapper step to transform the status
26
28
  # based on any custom configuration.
27
29
  def run_and_transform
28
- status, output = run
30
+ if output = check_for_executable
31
+ status = :fail
32
+ else
33
+ status, output = run
34
+ end
29
35
 
30
36
  [transform_status(status), output]
31
37
  end
@@ -68,13 +74,21 @@ module Overcommit::Hook
68
74
  Overcommit::Utils.execute(cmd)
69
75
  end
70
76
 
77
+ def executable
78
+ @config['required_executable']
79
+ end
80
+
81
+ def install_command
82
+ @config['install_command']
83
+ end
84
+
71
85
  # Gets a list of staged files that apply to this hook based on its
72
86
  # configured `include` and `exclude` lists.
73
87
  def applicable_files
74
88
  @applicable_files ||= modified_files.select { |file| applicable_file?(file) }
75
89
  end
76
90
 
77
- private
91
+ private
78
92
 
79
93
  def requires_modified_files?
80
94
  @config['requires_files']
@@ -107,6 +121,20 @@ module Overcommit::Hook
107
121
  )
108
122
  end
109
123
 
124
+ # If the hook defines a required executable, check if it's in the path and
125
+ # display the install command if one exists.
126
+ def check_for_executable
127
+ return unless executable && !in_path?(executable)
128
+
129
+ output = "'#{executable}' is not installed (or is not in your PATH)"
130
+
131
+ if install_command
132
+ output += "\nInstall it by running: #{install_command}"
133
+ end
134
+
135
+ output
136
+ end
137
+
110
138
  # Transforms the hook's status based on custom configuration.
111
139
  #
112
140
  # This allows users to change failures into warnings, or vice versa.
@@ -12,7 +12,7 @@ module Overcommit::Hook::PostCheckout
12
12
  :pass
13
13
  end
14
14
 
15
- private
15
+ private
16
16
 
17
17
  SCRIPT_LOCATION = Overcommit::Utils.script_path('index-tags')
18
18
 
@@ -5,15 +5,11 @@ module Overcommit::Hook::PreCommit
5
5
  LOCK_FILE = 'Berksfile.lock'
6
6
 
7
7
  def run
8
- unless in_path?('berks')
9
- return :warn, 'Berkshelf not installed -- run `gem install berkshelf`'
10
- end
11
-
12
8
  # Ignore if Berksfile.lock is not tracked by git
13
9
  ignored_files = execute(%w[git ls-files -o -i --exclude-standard]).stdout.split("\n")
14
10
  return :pass if ignored_files.include?(LOCK_FILE)
15
11
 
16
- result = execute(%w[berks list --quiet])
12
+ result = execute(%W[#{executable} list --quiet])
17
13
  unless result.success?
18
14
  return :fail, result.stderr
19
15
  end
@@ -2,11 +2,7 @@ module Overcommit::Hook::PreCommit
2
2
  # Runs `brakeman` against any modified Ruby/Rails files.
3
3
  class Brakeman < Base
4
4
  def run
5
- unless in_path?('brakeman')
6
- return :warn, 'Run `gem install brakeman`'
7
- end
8
-
9
- result = execute(%w[brakeman --exit-on-warn --quiet --summary --only-files] +
5
+ result = execute(%W[#{executable} --exit-on-warn --quiet --summary --only-files] +
10
6
  applicable_files)
11
7
  return :pass if result.success?
12
8
 
@@ -0,0 +1,15 @@
1
+ module Overcommit::Hook::PreCommit
2
+ # Checks for broken symlinks.
3
+ class BrokenSymlinks < Base
4
+ def run
5
+ broken_symlinks = applicable_files.
6
+ select { |file| Overcommit::Utils.broken_symlink?(file) }
7
+
8
+ if broken_symlinks.any?
9
+ return :fail, "Broken symlinks detected:\n#{broken_symlinks.join("\n")}"
10
+ end
11
+
12
+ :pass
13
+ end
14
+ end
15
+ end
@@ -5,22 +5,18 @@ module Overcommit::Hook::PreCommit
5
5
  LOCK_FILE = 'Gemfile.lock'
6
6
 
7
7
  def run
8
- unless in_path?('bundle')
9
- return :warn, 'bundler not installed -- run `gem install bundler`'
10
- end
11
-
12
8
  # Ignore if Gemfile.lock is not tracked by git
13
9
  ignored_files = execute(%w[git ls-files -o -i --exclude-standard]).stdout.split("\n")
14
10
  return :pass if ignored_files.include?(LOCK_FILE)
15
11
 
16
- result = execute(%w[bundle check])
12
+ result = execute(%W[#{executable} check])
17
13
  unless result.success?
18
14
  return :fail, result.stdout
19
15
  end
20
16
 
21
17
  result = execute(%w[git diff --quiet --] + [LOCK_FILE])
22
18
  unless result.success?
23
- return :fail, "#{LOCK_FILE} is not up-to-date -- run `bundle check`"
19
+ return :fail, "#{LOCK_FILE} is not up-to-date -- run `#{executable} check`"
24
20
  end
25
21
 
26
22
  :pass
@@ -2,11 +2,7 @@ module Overcommit::Hook::PreCommit
2
2
  # Runs `chamber secure` against any modified Chamber settings files
3
3
  class ChamberSecurity < Base
4
4
  def run
5
- unless in_path?('chamber')
6
- return :warn, 'Run `gem install chamber`'
7
- end
8
-
9
- result = execute(%w[chamber secure --echo --files] + applicable_files)
5
+ result = execute(%W[#{executable} secure --files] + applicable_files)
10
6
 
11
7
  return :pass if result.stdout.empty?
12
8
  [:fail, "These settings appear to need to be secured but were not: #{result.stdout}"]
@@ -2,11 +2,7 @@ module Overcommit::Hook::PreCommit
2
2
  # Runs `coffeelint` against any modified CoffeeScript files.
3
3
  class CoffeeLint < Base
4
4
  def run
5
- unless in_path?('coffeelint')
6
- return :warn, 'Run `npm install -g coffeelint`'
7
- end
8
-
9
- result = execute(%w[coffeelint --quiet] + applicable_files)
5
+ result = execute(%W[#{executable} --quiet] + applicable_files)
10
6
  return :pass if result.success?
11
7
 
12
8
  [:fail, result.stdout]
@@ -2,11 +2,7 @@ module Overcommit::Hook::PreCommit
2
2
  # Runs `csslint` against any modified CSS files.
3
3
  class CssLint < Base
4
4
  def run
5
- unless in_path?('csslint')
6
- return :warn, 'csslint not installed -- run `npm install -g csslint`'
7
- end
8
-
9
- result = execute(%w[csslint --quiet --format=compact] + applicable_files)
5
+ result = execute(%W[#{executable} --quiet --format=compact] + applicable_files)
10
6
  return :pass if result.stdout !~ /Error - (?!Unknown @ rule)/
11
7
 
12
8
  [:fail, result.stdout]
@@ -2,11 +2,7 @@ module Overcommit::Hook::PreCommit
2
2
  # Runs `golint` against any modified Golang files.
3
3
  class GoLint < Base
4
4
  def run
5
- unless in_path?('golint')
6
- return :warn, 'Run `go get `github.com/golang/lint/golint`'
7
- end
8
-
9
- result = execute(%w[golint] + applicable_files)
5
+ result = execute([executable] + applicable_files)
10
6
  # Unfortunately the exit code is always 0
11
7
  return :pass if result.stdout.empty?
12
8
 
@@ -2,11 +2,7 @@ module Overcommit::Hook::PreCommit
2
2
  # Runs `haml-lint` against any modified HAML files.
3
3
  class HamlLint < Base
4
4
  def run
5
- unless in_path?('haml-lint')
6
- return :warn, 'haml-lint not installed -- run `gem install haml-lint`'
7
- end
8
-
9
- result = execute(%w[haml-lint] + applicable_files)
5
+ result = execute([executable] + applicable_files)
10
6
  return :pass if result.success?
11
7
 
12
8
  # Keep lines from the output for files that we actually modified
@@ -11,7 +11,7 @@ module Overcommit::Hook::PreCommit
11
11
  optimized_images =
12
12
  begin
13
13
  optimize_images(applicable_files)
14
- rescue ::ImageOptim::BinNotFoundError => e
14
+ rescue ::ImageOptim::BinResolver::BinNotFound => e
15
15
  return :fail, "#{e.message}. The image_optim gem is dependendent on this binary."
16
16
  end
17
17
 
@@ -25,7 +25,7 @@ module Overcommit::Hook::PreCommit
25
25
  :pass
26
26
  end
27
27
 
28
- private
28
+ private
29
29
 
30
30
  def optimize_images(image_paths)
31
31
  image_optim = ::ImageOptim.new(:pngout => false)
@@ -2,11 +2,7 @@ module Overcommit::Hook::PreCommit
2
2
  # Runs `jshint` against any modified JavaScript files.
3
3
  class JsHint < Base
4
4
  def run
5
- unless in_path?('jshint')
6
- return :warn, 'jshint not installed -- run `npm install -g jshint`'
7
- end
8
-
9
- result = execute(%w[jshint] + applicable_files)
5
+ result = execute([executable] + applicable_files)
10
6
  output = result.stdout
11
7
 
12
8
  return :pass if output.empty?
@@ -3,11 +3,7 @@ module Overcommit::Hook::PreCommit
3
3
  # files.
4
4
  class Jscs < Base
5
5
  def run
6
- unless in_path?('jscs')
7
- return :warn, 'jscs not installed -- run `npm install -g jscs`'
8
- end
9
-
10
- result = execute(%w[jscs --reporter=inline] + applicable_files)
6
+ result = execute(%W[#{executable} --reporter=inline] + applicable_files)
11
7
  return :pass if result.success?
12
8
 
13
9
  if result.status == 1
@@ -2,11 +2,7 @@ module Overcommit::Hook::PreCommit
2
2
  # Runs `jsxhint` against any modified JSX files.
3
3
  class JsxHint < Base
4
4
  def run
5
- unless in_path?('jsxhint')
6
- return :warn, 'jsxhint not installed -- run `npm install -g jsxhint`'
7
- end
8
-
9
- result = execute(%w[jsxhint] + applicable_files)
5
+ result = execute([executable] + applicable_files)
10
6
  output = result.stdout
11
7
 
12
8
  return :pass if output.empty?
@@ -2,11 +2,7 @@ module Overcommit::Hook::PreCommit
2
2
  # Runs `flake8` against any modified Python files.
3
3
  class PythonFlake8 < Base
4
4
  def run
5
- unless in_path?('flake8')
6
- return :warn, 'flake8 not installed -- run `pip install flake8`'
7
- end
8
-
9
- result = execute(%w[flake8] + applicable_files)
5
+ result = execute([executable] + applicable_files)
10
6
  return :pass if result.success?
11
7
 
12
8
  [:fail, result.stdout]
@@ -1,7 +1,7 @@
1
1
  module Overcommit::Hook::PreCommit
2
2
  # Check to see whether the schema file is in line with the migrations
3
3
  class RailsSchemaUpToDate < Base
4
- def run # rubocop:disable CyclomaticComplexity
4
+ def run # rubocop:disable CyclomaticComplexity, PerceivedComplexity
5
5
  if migration_files.any? && schema_files.none?
6
6
  return :fail, "It looks like you're adding a migration, but did not update the schema file"
7
7
  elsif migration_files.none? && schema_files.any?
@@ -28,7 +28,7 @@ module Overcommit::Hook::PreCommit
28
28
  :pass
29
29
  end
30
30
 
31
- private
31
+ private
32
32
 
33
33
  def migration_files
34
34
  @migration_files ||= applicable_files.select do |file|
@@ -2,11 +2,7 @@ module Overcommit::Hook::PreCommit
2
2
  # Runs `rubocop` against any modified Ruby files.
3
3
  class Rubocop < Base
4
4
  def run
5
- unless in_path?('rubocop')
6
- return :warn, 'Rubocop not installed -- run `gem install rubocop`'
7
- end
8
-
9
- result = execute(%w[rubocop --format=emacs --force-exclusion] + applicable_files)
5
+ result = execute(%W[#{executable} --format=emacs --force-exclusion] + applicable_files)
10
6
  return :pass if result.success?
11
7
 
12
8
  output = result.stdout + result.stderr
@@ -2,11 +2,7 @@ module Overcommit::Hook::PreCommit
2
2
  # Runs `scss-lint` against any modified SCSS files.
3
3
  class ScssLint < Base
4
4
  def run
5
- unless in_path?('scss-lint')
6
- return :warn, 'scss-lint not installed -- run `gem install scss-lint`'
7
- end
8
-
9
- result = execute(%w[scss-lint] + applicable_files)
5
+ result = execute([executable] + applicable_files)
10
6
  return :pass if result.success?
11
7
 
12
8
  # Keep lines from the output for files that we actually modified
@@ -2,11 +2,7 @@ module Overcommit::Hook::PreCommit
2
2
  # Runs `travis-lint` against any modified Travis CI files.
3
3
  class TravisLint < Base
4
4
  def run
5
- unless in_path?('travis-lint')
6
- return :warn, 'Run `gem install travis-lint`'
7
- end
8
-
9
- result = execute(%w[travis-lint] + applicable_files)
5
+ result = execute([executable] + applicable_files)
10
6
  return :pass if result.success?
11
7
 
12
8
  [:fail, result.stdout.strip]
@@ -23,7 +23,7 @@ module Overcommit::HookContext
23
23
  @args[0]
24
24
  end
25
25
 
26
- private
26
+ private
27
27
 
28
28
  def raw_commit_message_lines
29
29
  ::IO.readlines(commit_message_file)
@@ -67,7 +67,7 @@ module Overcommit::HookContext
67
67
  @modified_lines[file] ||= Overcommit::GitRepo.extract_modified_lines(file, :staged => true)
68
68
  end
69
69
 
70
- private
70
+ private
71
71
 
72
72
  # Clears the working tree so that the stash can be applied.
73
73
  def clear_working_tree
@@ -114,6 +114,7 @@ module Overcommit::HookContext
114
114
  @modified_times = {}
115
115
 
116
116
  modified_files.each do |file|
117
+ next if Overcommit::Utils.broken_symlink?(file)
117
118
  @modified_times[file] = File.mtime(file)
118
119
  end
119
120
  end
@@ -122,6 +123,7 @@ module Overcommit::HookContext
122
123
  # appear like they never changed.
123
124
  def restore_modified_times
124
125
  modified_files.each do |file|
126
+ next if Overcommit::Utils.broken_symlink?(file)
125
127
  time = @modified_times[file]
126
128
  File.utime(time, time, file)
127
129
  end
@@ -20,7 +20,7 @@ module Overcommit::HookLoader
20
20
  raise NotImplementedError
21
21
  end
22
22
 
23
- private
23
+ private
24
24
 
25
25
  attr_reader :log
26
26
 
@@ -18,12 +18,12 @@ module Overcommit::HookLoader
18
18
  end
19
19
  end
20
20
 
21
- private
21
+ private
22
22
 
23
23
  def check_for_modified_plugins(plugin_paths)
24
24
  modified_plugins = plugin_paths.
25
25
  map { |path| Overcommit::HookSigner.new(path, @config, @context) }.
26
- select { |signer| signer.signature_changed? }
26
+ select(&:signature_changed?)
27
27
 
28
28
  return if modified_plugins.empty?
29
29
 
@@ -45,7 +45,7 @@ module Overcommit::HookLoader
45
45
  raise Overcommit::Exceptions::HookCancelled
46
46
  end
47
47
 
48
- modified_plugins.each { |signer| signer.update_signature! }
48
+ modified_plugins.each(&:update_signature!)
49
49
  end
50
50
  end
51
51
  end
@@ -31,7 +31,7 @@ module Overcommit
31
31
  end
32
32
  end
33
33
 
34
- private
34
+ private
35
35
 
36
36
  attr_reader :log
37
37
 
@@ -38,7 +38,7 @@ module Overcommit
38
38
  end
39
39
  end
40
40
 
41
- private
41
+ private
42
42
 
43
43
  # Calculates a hash of a hook using a combination of its configuration and
44
44
  # file contents.
@@ -23,7 +23,7 @@ module Overcommit
23
23
  end
24
24
  end
25
25
 
26
- private
26
+ private
27
27
 
28
28
  attr_reader :log
29
29
 
@@ -18,34 +18,35 @@ module Overcommit
18
18
  @out.puts(*args)
19
19
  end
20
20
 
21
- def bold(str)
22
- color('1', str)
21
+ def bold(*args)
22
+ color('1', *args)
23
23
  end
24
24
 
25
- def error(str)
26
- color(31, str)
25
+ def error(*args)
26
+ color(31, *args)
27
27
  end
28
28
 
29
- def bold_error(str)
30
- color('1;31', str)
29
+ def bold_error(*args)
30
+ color('1;31', *args)
31
31
  end
32
32
 
33
- def success(str)
34
- color(32, str)
33
+ def success(*args)
34
+ color(32, *args)
35
35
  end
36
36
 
37
- def warning(str)
38
- color(33, str)
37
+ def warning(*args)
38
+ color(33, *args)
39
39
  end
40
40
 
41
- def bold_warning(str)
42
- color('1;33', str)
41
+ def bold_warning(*args)
42
+ color('1;33', *args)
43
43
  end
44
44
 
45
- private
45
+ private
46
46
 
47
- def color(code, str)
48
- log(@out.tty? ? "\033[#{code}m#{str}\033[0m" : str)
47
+ def color(code, str, partial = false)
48
+ send(partial ? :partial : :log,
49
+ @out.tty? ? "\033[#{code}m#{str}\033[0m" : str)
49
50
  end
50
51
  end
51
52
  end
@@ -59,7 +59,7 @@ module Overcommit
59
59
  print_result(hook, status, output)
60
60
  end
61
61
 
62
- private
62
+ private
63
63
 
64
64
  def print_header(hook)
65
65
  hook_name = "[#{hook.name}] "
@@ -13,7 +13,7 @@ module Overcommit
13
13
  @io.gets
14
14
  end
15
15
 
16
- private
16
+ private
17
17
 
18
18
  # Git hooks are not interactive and will close STDIN by default.
19
19
  def reopen_tty
@@ -42,7 +42,7 @@ module Overcommit
42
42
  # Returns a list of supported hook classes (PreCommit, CommitMsg, etc.)
43
43
  def supported_hook_type_classes
44
44
  supported_hook_types.map do |file|
45
- file.split('-').map { |part| part.capitalize }.join
45
+ file.split('-').map(&:capitalize).join
46
46
  end
47
47
  end
48
48
 
@@ -86,6 +86,15 @@ module Overcommit
86
86
  ensure
87
87
  old_env.each { |var, value| ENV[var.to_s] = value }
88
88
  end
89
+
90
+ # Returns whether a file is a broken symlink.
91
+ #
92
+ # @return [true,false]
93
+ def broken_symlink?(file)
94
+ # JRuby's implementation of File.exist? returns true for broken
95
+ # symlinks, so we need use File.size?
96
+ File.symlink?(file) && File.size?(file).nil?
97
+ end
89
98
  end
90
99
  end
91
100
  end
@@ -1,4 +1,4 @@
1
1
  # Defines the gem version.
2
2
  module Overcommit
3
- VERSION = '0.17.0'
3
+ VERSION = '0.18.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.17.0
4
+ version: 0.18.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Causes Engineering
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-09-03 00:00:00.000000000 Z
12
+ date: 2014-09-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: childprocess
@@ -31,14 +31,14 @@ dependencies:
31
31
  requirements:
32
32
  - - ~>
33
33
  - !ruby/object:Gem::Version
34
- version: 0.14.0
34
+ version: 0.15.0
35
35
  type: :development
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
39
  - - ~>
40
40
  - !ruby/object:Gem::Version
41
- version: 0.14.0
41
+ version: 0.15.0
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: rspec
44
44
  requirement: !ruby/object:Gem::Requirement
@@ -59,14 +59,14 @@ dependencies:
59
59
  requirements:
60
60
  - - '='
61
61
  - !ruby/object:Gem::Version
62
- version: 0.24.1
62
+ version: 0.26.0
63
63
  type: :development
64
64
  prerelease: false
65
65
  version_requirements: !ruby/object:Gem::Requirement
66
66
  requirements:
67
67
  - - '='
68
68
  - !ruby/object:Gem::Version
69
- version: 0.24.1
69
+ version: 0.26.0
70
70
  description: Utility to install, configure, and extend Git hooks
71
71
  email:
72
72
  - eng@causes.com
@@ -123,6 +123,7 @@ files:
123
123
  - lib/overcommit/hook/pre_commit/jscs.rb
124
124
  - lib/overcommit/hook/pre_commit/scss_lint.rb
125
125
  - lib/overcommit/hook/pre_commit/base.rb
126
+ - lib/overcommit/hook/pre_commit/broken_symlinks.rb
126
127
  - lib/overcommit/hook/pre_commit/json_syntax.rb
127
128
  - lib/overcommit/hook_signer.rb
128
129
  - lib/overcommit/git_repo.rb