overcommit 0.17.0 → 0.18.0

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