overcommit 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/config/default.yml +10 -0
  3. data/lib/overcommit.rb +5 -0
  4. data/lib/overcommit/cli.rb +1 -1
  5. data/lib/overcommit/configuration.rb +4 -0
  6. data/lib/overcommit/configuration_loader.rb +30 -28
  7. data/lib/overcommit/exceptions.rb +6 -0
  8. data/lib/overcommit/hook/commit_msg/gerrit_change_id.rb +5 -5
  9. data/lib/overcommit/hook/commit_msg/text_width.rb +1 -1
  10. data/lib/overcommit/hook/post_checkout/bundle_check.rb +5 -1
  11. data/lib/overcommit/hook/pre_commit/author_email.rb +2 -2
  12. data/lib/overcommit/hook/pre_commit/author_name.rb +2 -2
  13. data/lib/overcommit/hook/pre_commit/bundle_check.rb +2 -4
  14. data/lib/overcommit/hook/pre_commit/coffee_lint.rb +2 -1
  15. data/lib/overcommit/hook/pre_commit/css_lint.rb +3 -2
  16. data/lib/overcommit/hook/pre_commit/haml_lint.rb +3 -2
  17. data/lib/overcommit/hook/pre_commit/js_hint.rb +3 -1
  18. data/lib/overcommit/hook/pre_commit/jscs.rb +3 -2
  19. data/lib/overcommit/hook/pre_commit/python_flake8.rb +2 -1
  20. data/lib/overcommit/hook/pre_commit/rubocop.rb +3 -2
  21. data/lib/overcommit/hook/pre_commit/scss_lint.rb +3 -2
  22. data/lib/overcommit/hook/pre_commit/travis_lint.rb +15 -0
  23. data/lib/overcommit/hook/pre_commit/yaml_syntax.rb +3 -3
  24. data/lib/overcommit/hook_context/post_checkout.rb +2 -0
  25. data/lib/overcommit/hook_loader/base.rb +38 -0
  26. data/lib/overcommit/hook_loader/built_in_hook_loader.rb +12 -0
  27. data/lib/overcommit/hook_loader/plugin_hook_loader.rb +51 -0
  28. data/lib/overcommit/hook_runner.rb +43 -61
  29. data/lib/overcommit/hook_signer.rb +73 -0
  30. data/lib/overcommit/installer.rb +28 -8
  31. data/lib/overcommit/user_input.rb +26 -0
  32. data/lib/overcommit/version.rb +1 -1
  33. data/template-dir/hooks/commit-msg +21 -8
  34. data/template-dir/hooks/overcommit-hook +21 -8
  35. data/template-dir/hooks/post-checkout +21 -8
  36. data/template-dir/hooks/pre-commit +21 -8
  37. metadata +12 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 92e61229cb593b12785dc6f250aaf20b59335277
4
- data.tar.gz: 6109a2ebdd9e9ad8fb6612178dc38c919decc366
3
+ metadata.gz: 6030d9d4951a3c37f536bfd4caefc3890c6c4f2d
4
+ data.tar.gz: 04a5f6031e2217c33382a2c034f7670f711dbdbe
5
5
  SHA512:
6
- metadata.gz: 9a30a6cef4ea66c146c536e3868e12e2ce8a80dbc4c10955e3e6f18990dc0f75a21e439032bdcd180086aa6fd47a4a327d9ca36441f654f4e1400777ce333d8c
7
- data.tar.gz: 1d0a931ee95dac1fa0f7bf35f3e154033d831df840f1ba30772108612bc5aafd52315bded077ec359873cc2d3298f76aca2800fec55ae862b89f45867af15b11
6
+ metadata.gz: c6769844c60d201e95417a06610daef7c1a5465184c176423ad7bf9bfb958373116fe8d17085ecc9f2d741677d9a928e28df6ac6b174f5499d8907837eef1305
7
+ data.tar.gz: 49c7bbeafda273737fafc8aba005eda1b5c13774932a143c7c85664ee32f4f84898999c1da2cea9f4b2ffb2eae490386bef0b8c744b76a798a9c90478f859000
@@ -8,6 +8,12 @@
8
8
  # to the root of the repository.
9
9
  plugin_directory: '.git-hooks'
10
10
 
11
+ # Whether to check if a hook plugin has changed since Overcommit last ran it.
12
+ # This is a defense mechanism when working with repositories which can contain
13
+ # untrusted code (e.g. when you fetch a pull request from a third party).
14
+ # See https://github.com/causes/overcommit#security for more information.
15
+ verify_plugin_signatures: true
16
+
11
17
  # Hooks that run after HEAD changes or a file is explicitly checked out. Useful
12
18
  # for updating source tags (e.g. via ctags) or warning about new migrations,
13
19
  # etc.
@@ -105,6 +111,10 @@ PreCommit:
105
111
  TrailingWhitespace:
106
112
  description: 'Checking for trailing whitespace'
107
113
 
114
+ TravisLint:
115
+ description: 'Checking Travis CI configuration'
116
+ include: '.travis.yml'
117
+
108
118
  YamlSyntax:
109
119
  description: 'Checking YAML syntax'
110
120
  include: '**/*.yml'
@@ -5,6 +5,11 @@ require 'overcommit/configuration_loader'
5
5
  require 'overcommit/hook/base'
6
6
  require 'overcommit/hook_context/base'
7
7
  require 'overcommit/hook_context'
8
+ require 'overcommit/user_input'
9
+ require 'overcommit/hook_signer'
10
+ require 'overcommit/hook_loader/base'
11
+ require 'overcommit/hook_loader/built_in_hook_loader'
12
+ require 'overcommit/hook_loader/plugin_hook_loader'
8
13
  require 'overcommit/hook_runner'
9
14
  require 'overcommit/installer'
10
15
  require 'overcommit/logger'
@@ -74,7 +74,7 @@ module Overcommit
74
74
 
75
75
  if @options[:targets].empty?
76
76
  log.warning 'You are not in a git repository.'
77
- log.log 'You must either specify the path to a repository or ' <<
77
+ log.log 'You must either specify the path to a repository or ' \
78
78
  'change your current directory to a repository.'
79
79
  halt 64 # EX_USAGE
80
80
  end
@@ -18,6 +18,10 @@ module Overcommit
18
18
  File.join(Overcommit::Utils.repo_root, @hash['plugin_directory'] || '.githooks')
19
19
  end
20
20
 
21
+ def verify_plugin_signatures?
22
+ @hash['verify_plugin_signatures'] != false
23
+ end
24
+
21
25
  # Returns the built-in hooks that have been enabled for a hook type.
22
26
  def enabled_builtin_hooks(hook_context)
23
27
  @hash[hook_context.hook_class_name].keys.
@@ -6,42 +6,44 @@ module Overcommit
6
6
  DEFAULT_CONFIG_PATH = File.join(OVERCOMMIT_HOME, 'config', 'default.yml')
7
7
  FILE_NAME = '.overcommit.yml'
8
8
 
9
- def self.load_repo_config
10
- overcommit_yml = File.join(Overcommit::Utils.repo_root, FILE_NAME)
9
+ class << self
10
+ def load_repo_config
11
+ overcommit_yml = File.join(Overcommit::Utils.repo_root, FILE_NAME)
11
12
 
12
- if File.exists?(overcommit_yml)
13
- load_file(overcommit_yml)
14
- else
15
- default_configuration
13
+ if File.exist?(overcommit_yml)
14
+ load_file(overcommit_yml)
15
+ else
16
+ default_configuration
17
+ end
16
18
  end
17
- end
18
19
 
19
- def self.default_configuration
20
- @default_config ||= load_from_file(DEFAULT_CONFIG_PATH)
21
- end
20
+ def default_configuration
21
+ @default_config ||= load_from_file(DEFAULT_CONFIG_PATH)
22
+ end
22
23
 
23
- private
24
+ private
24
25
 
25
- # Loads a configuration, ensuring it extends the default configuration.
26
- def self.load_file(file)
27
- config = load_from_file(file)
26
+ # Loads a configuration, ensuring it extends the default configuration.
27
+ def load_file(file)
28
+ config = load_from_file(file)
28
29
 
29
- default_configuration.merge(config)
30
- rescue => error
31
- raise Overcommit::Exceptions::ConfigurationError,
32
- "Unable to load configuration from '#{file}': #{error}",
33
- error.backtrace
34
- end
30
+ default_configuration.merge(config)
31
+ rescue => error
32
+ raise Overcommit::Exceptions::ConfigurationError,
33
+ "Unable to load configuration from '#{file}': #{error}",
34
+ error.backtrace
35
+ end
35
36
 
36
- def self.load_from_file(file)
37
- hash =
38
- if yaml = YAML.load_file(file)
39
- yaml.to_hash
40
- else
41
- {}
42
- end
37
+ def load_from_file(file)
38
+ hash =
39
+ if yaml = YAML.load_file(file)
40
+ yaml.to_hash
41
+ else
42
+ {}
43
+ end
43
44
 
44
- Overcommit::Configuration.new(hash)
45
+ Overcommit::Configuration.new(hash)
46
+ end
45
47
  end
46
48
  end
47
49
  end
@@ -2,6 +2,12 @@ module Overcommit::Exceptions
2
2
  # Raised when a {Configuration} could not be loaded from a file.
3
3
  class ConfigurationError < StandardError; end
4
4
 
5
+ # Raised when trying to read/write to/from the local repo git config fails.
6
+ class GitConfigError < StandardError; end
7
+
8
+ # Raised when a hook run was cancelled by the user.
9
+ class HookCancelled < StandardError; end
10
+
5
11
  # Raised when a hook could not be loaded by a {HookRunner}.
6
12
  class HookLoadError < StandardError; end
7
13
 
@@ -6,13 +6,13 @@ module Overcommit::Hook::CommitMsg
6
6
  # you need to do it in a commit-msg hook. This is because the user could still
7
7
  # edit the message after a prepare-commit-msg hook was run.
8
8
  class GerritChangeId < Base
9
+ SCRIPT_LOCATION = Overcommit::Utils.script_path('gerrit-change-id')
10
+
9
11
  def run
10
12
  result = execute([SCRIPT_LOCATION, commit_message_file])
11
- return (result.success? ? :good : :bad), result.stdout
12
- end
13
+ return :good if result.success?
13
14
 
14
- private
15
-
16
- SCRIPT_LOCATION = Overcommit::Utils.script_path('gerrit-change-id')
15
+ [:bad, result.stdout]
16
+ end
17
17
  end
18
18
  end
@@ -16,7 +16,7 @@ module Overcommit::Hook::CommitMsg
16
16
  commit_message_lines[2..-1].each_with_index do |line, index|
17
17
  chomped = line.chomp
18
18
  if chomped.size > max_body_width
19
- error = "Line #{index + 3} of commit message has > " <<
19
+ error = "Line #{index + 3} of commit message has > " \
20
20
  "#{max_body_width} characters"
21
21
  errors << error
22
22
  end
@@ -7,13 +7,17 @@ module Overcommit::Hook::PostCheckout
7
7
  return :warn, 'bundler not installed -- run `gem install bundler`'
8
8
  end
9
9
 
10
- return :warn if dependencies_changed? && !dependencies_satisfied?
10
+ if dependencies_changed? && !dependencies_satisfied?
11
+ return :warn, "#{LOCK_FILE} is not up-to-date -- run `bundle check`"
12
+ end
11
13
 
12
14
  :good
13
15
  end
14
16
 
15
17
  private
16
18
 
19
+ LOCK_FILE = 'Gemfile.lock'
20
+
17
21
  def dependencies_changed?
18
22
  result = execute(%w[git diff --exit-code --name-only] + [new_head, previous_head])
19
23
 
@@ -6,8 +6,8 @@ module Overcommit::Hook::PreCommit
6
6
  email = result.stdout.chomp
7
7
 
8
8
  unless email =~ /#{@config['pattern']}/
9
- return :bad, "Author has an invalid email address: '#{email}'\n" <<
10
- 'Set your email with ' <<
9
+ return :bad, "Author has an invalid email address: '#{email}'\n" \
10
+ 'Set your email with ' \
11
11
  '`git config --global user.email your_email@example.com`'
12
12
  end
13
13
 
@@ -6,8 +6,8 @@ module Overcommit::Hook::PreCommit
6
6
  name = result.stdout.chomp
7
7
 
8
8
  unless name.split(' ').count >= 2
9
- return :bad, 'Author must have at least first and last name, but ' <<
10
- "was: '#{name}'.\nSet your name with " <<
9
+ return :bad, 'Author must have at least first and last name, but ' \
10
+ "was: '#{name}'.\nSet your name with " \
11
11
  "`git config --global user.name 'Your Name'`"
12
12
  end
13
13
 
@@ -2,6 +2,8 @@ module Overcommit::Hook::PreCommit
2
2
  # Check if local Gemfile.lock matches Gemfile when either changes, unless
3
3
  # Gemfile.lock is ignored by git.
4
4
  class BundleCheck < Base
5
+ LOCK_FILE = 'Gemfile.lock'
6
+
5
7
  def run
6
8
  unless in_path?('bundle')
7
9
  return :warn, 'bundler not installed -- run `gem install bundler`'
@@ -22,9 +24,5 @@ module Overcommit::Hook::PreCommit
22
24
 
23
25
  :good
24
26
  end
25
-
26
- private
27
-
28
- LOCK_FILE = 'Gemfile.lock'
29
27
  end
30
28
  end
@@ -8,7 +8,8 @@ module Overcommit::Hook::PreCommit
8
8
 
9
9
  result = execute(%w[coffeelint --quiet] + applicable_files)
10
10
  return :good if result.success?
11
- return :bad, result.stdout
11
+
12
+ [:bad, result.stdout]
12
13
  end
13
14
  end
14
15
  end
@@ -7,8 +7,9 @@ module Overcommit::Hook::PreCommit
7
7
  end
8
8
 
9
9
  result = execute(%w[csslint --quiet --format=compact] + applicable_files)
10
- output = result.stdout
11
- return (output !~ /Error - (?!Unknown @ rule)/ ? :good : :bad), output
10
+ return :good if result.stdout !~ /Error - (?!Unknown @ rule)/
11
+
12
+ [:bad, result.stdout]
12
13
  end
13
14
  end
14
15
  end
@@ -19,8 +19,9 @@ module Overcommit::Hook::PreCommit
19
19
  end
20
20
 
21
21
  return :bad, error_lines.join("\n") unless error_lines.empty?
22
- return :warn, "Modified files have lints (on lines you didn't modify)\n" <<
23
- warning_lines.join("\n")
22
+
23
+ [:warn, "Modified files have lints (on lines you didn't modify)\n" <<
24
+ warning_lines.join("\n")]
24
25
  end
25
26
  end
26
27
  end
@@ -9,7 +9,9 @@ module Overcommit::Hook::PreCommit
9
9
  result = execute(%w[jshint] + applicable_files)
10
10
  output = result.stdout
11
11
 
12
- return (output.empty? ? :good : :bad), output
12
+ return :good if output.empty?
13
+
14
+ [:bad, output]
13
15
  end
14
16
  end
15
17
  end
@@ -24,8 +24,9 @@ module Overcommit::Hook::PreCommit
24
24
  end
25
25
 
26
26
  return :bad, error_lines.join("\n") unless error_lines.empty?
27
- return :warn, "Modified files have lints (on lines you didn't modify)\n" <<
28
- warning_lines.join("\n")
27
+
28
+ [:warn, "Modified files have lints (on lines you didn't modify)\n" <<
29
+ warning_lines.join("\n")]
29
30
  end
30
31
  end
31
32
  end
@@ -7,8 +7,9 @@ module Overcommit::Hook::PreCommit
7
7
  end
8
8
 
9
9
  result = execute(%w[flake8] + applicable_files)
10
+ return :good if result.success?
10
11
 
11
- return (result.success? ? :good : :bad), result.stdout
12
+ [:bad, result.stdout]
12
13
  end
13
14
  end
14
15
  end
@@ -21,8 +21,9 @@ module Overcommit::Hook::PreCommit
21
21
  end
22
22
 
23
23
  return :bad, error_lines.join("\n") unless error_lines.empty?
24
- return :warn, "Modified files have lints (on lines you didn't modify)\n" <<
25
- warning_lines.join("\n")
24
+
25
+ [:warn, "Modified files have lints (on lines you didn't modify)\n" <<
26
+ warning_lines.join("\n")]
26
27
  end
27
28
  end
28
29
  end
@@ -19,8 +19,9 @@ module Overcommit::Hook::PreCommit
19
19
  end
20
20
 
21
21
  return :bad, error_lines.join("\n") unless error_lines.empty?
22
- return :warn, "Modified files have lints (on lines you didn't modify)\n" <<
23
- warning_lines.join("\n")
22
+
23
+ [:warn, "Modified files have lints (on lines you didn't modify)\n" <<
24
+ warning_lines.join("\n")]
24
25
  end
25
26
  end
26
27
  end
@@ -0,0 +1,15 @@
1
+ module Overcommit::Hook::PreCommit
2
+ # Runs `travis-lint` against any modified Travis CI files.
3
+ class TravisLint < Base
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)
10
+ return :good if result.success?
11
+
12
+ [:bad, result.stdout.strip]
13
+ end
14
+ end
15
+ end
@@ -4,7 +4,6 @@ module Overcommit::Hook::PreCommit
4
4
  # Checks the syntax of any modified YAML files.
5
5
  class YamlSyntax < Base
6
6
  def run
7
- clean = true
8
7
  output = []
9
8
 
10
9
  applicable_files.each do |file|
@@ -12,11 +11,12 @@ module Overcommit::Hook::PreCommit
12
11
  YAML.load_file(file)
13
12
  rescue ArgumentError => e
14
13
  output << "#{e.message} parsing #{file}"
15
- clean = false
16
14
  end
17
15
  end
18
16
 
19
- return (clean ? :good : :bad), output
17
+ return :good if output.empty?
18
+
19
+ [:bad, output]
20
20
  end
21
21
  end
22
22
  end
@@ -1,4 +1,6 @@
1
1
  module Overcommit::HookContext
2
+ # Contains helpers related to contextual information used by post-checkout
3
+ # hooks.
2
4
  class PostCheckout < Base
3
5
  # Returns the ref of the HEAD that we transitioned from.
4
6
  def previous_head
@@ -0,0 +1,38 @@
1
+ module Overcommit::HookLoader
2
+ # Responsible for loading hooks from a file.
3
+ class Base
4
+ # @param config [Overcommit::Configuration]
5
+ # @param context [Overcommit::HookContext]
6
+ # @param logger [Overcommit::Logger]
7
+ # @param input [Overcommit::UserInput]
8
+ def initialize(config, context, logger, input)
9
+ @config = config
10
+ @context = context
11
+ @log = logger
12
+ @input = input
13
+ end
14
+
15
+ # When implemented in subclasses, loads the hooks for which that subclass is
16
+ # responsible.
17
+ #
18
+ # @return [Array<Hook>]
19
+ def load_hooks
20
+ raise NotImplementedError
21
+ end
22
+
23
+ private
24
+
25
+ attr_reader :log
26
+
27
+ # Load and return a {Hook} from a CamelCase hook name.
28
+ def create_hook(hook_name)
29
+ Overcommit::Hook.const_get(@context.hook_class_name).
30
+ const_get(hook_name).
31
+ new(@config, @context)
32
+ rescue LoadError, NameError => error
33
+ raise Overcommit::Exceptions::HookLoadError,
34
+ "Unable to load hook '#{hook_name}': #{error}",
35
+ error.backtrace
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,12 @@
1
+ module Overcommit::HookLoader
2
+ # Responsible for loading hooks that ship with Overcommit.
3
+ class BuiltInHookLoader < Base
4
+ def load_hooks
5
+ @config.enabled_builtin_hooks(@context).map do |hook_name|
6
+ underscored_hook_name = Overcommit::Utils.snake_case(hook_name)
7
+ require "overcommit/hook/#{@context.hook_type_name}/#{underscored_hook_name}"
8
+ create_hook(hook_name)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,51 @@
1
+ require 'digest'
2
+
3
+ module Overcommit::HookLoader
4
+ # Responsible for loading hooks that are specific to the repository Overcommit
5
+ # is running in.
6
+ class PluginHookLoader < Base
7
+ def load_hooks
8
+ directory = File.join(@config.plugin_directory, @context.hook_type_name)
9
+ plugin_paths = Dir[File.join(directory, '*.rb')].sort
10
+
11
+ check_for_modified_plugins(plugin_paths) if @config.verify_plugin_signatures?
12
+
13
+ plugin_paths.map do |plugin_path|
14
+ require plugin_path
15
+
16
+ hook_name = Overcommit::Utils.camel_case(File.basename(plugin_path, '.rb'))
17
+ create_hook(hook_name)
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def check_for_modified_plugins(plugin_paths)
24
+ modified_plugins = plugin_paths.
25
+ map { |path| Overcommit::HookSigner.new(path, @config, @context) }.
26
+ select { |signer| signer.signature_changed? }
27
+
28
+ return if modified_plugins.empty?
29
+
30
+ log.bold_warning "The following #{@context.hook_script_name} plugins " \
31
+ "have been added, changed, or had their configuration modified:"
32
+ log.log
33
+
34
+ modified_plugins.each do |signer|
35
+ log.warning " * #{signer.hook_name} in #{signer.hook_path}"
36
+ end
37
+
38
+ log.log
39
+ log.bold_warning 'You should verify the changes before continuing'
40
+ log.log "For more information, see #{Overcommit::REPO_URL}#security"
41
+ log.log
42
+ log.partial 'Continue? (y/n) '
43
+
44
+ unless (answer = @input.get) && answer.strip.downcase.start_with?('y')
45
+ raise Overcommit::Exceptions::HookCancelled
46
+ end
47
+
48
+ modified_plugins.each { |signer| signer.update_signature! }
49
+ end
50
+ end
51
+ end
@@ -4,17 +4,22 @@ module Overcommit
4
4
  # Responsible for loading the hooks the repository has configured and running
5
5
  # them, collecting and displaying the results.
6
6
  class HookRunner
7
- def initialize(config, logger, context)
7
+ # @param config [Overcommit::Configuration]
8
+ # @param logger [Overcommit::Logger]
9
+ # @param context [Overcommit::HookContext]
10
+ # @param input [Overcommit::UserInput]
11
+ def initialize(config, logger, context, input)
8
12
  @config = config
9
13
  @log = logger
10
14
  @context = context
15
+ @input = input
11
16
  @hooks = []
12
17
  end
13
18
 
14
19
  # Loads and runs the hooks registered for this {HookRunner}.
15
20
  def run
16
- load_hooks
17
21
  @context.setup_environment
22
+ load_hooks
18
23
  run_hooks
19
24
  ensure
20
25
  @context.cleanup_environment
@@ -26,7 +31,7 @@ module Overcommit
26
31
 
27
32
  def run_hooks
28
33
  if @hooks.any? { |hook| hook.run? || hook.skip? }
29
- log.bold "Running #{@context.hook_script_name} hooks"
34
+ log.bold "Running #{hook_script_name} hooks"
30
35
 
31
36
  statuses = @hooks.map { |hook| run_hook(hook) }.compact
32
37
 
@@ -35,33 +40,22 @@ module Overcommit
35
40
  run_failed = statuses.include?(:bad)
36
41
 
37
42
  if run_failed
38
- log.error "✗ One or more #{@context.hook_script_name} hooks failed"
43
+ log.error "✗ One or more #{hook_script_name} hooks failed"
39
44
  else
40
- log.success "✓ All #{@context.hook_script_name} hooks passed"
45
+ log.success "✓ All #{hook_script_name} hooks passed"
41
46
  end
42
47
 
43
48
  log.log # Newline
44
49
 
45
50
  !run_failed
46
51
  else
47
- log.success "✓ No applicable #{@context.hook_script_name} hooks to run"
52
+ log.success "✓ No applicable #{hook_script_name} hooks to run"
48
53
  true # Run was successful
49
54
  end
50
55
  end
51
56
 
52
57
  def run_hook(hook)
53
- return unless hook.enabled?
54
-
55
- if hook.skip?
56
- if hook.required?
57
- log.warning "Cannot skip #{hook.name} since it is required"
58
- else
59
- log.warning "Skipping #{hook.name}"
60
- return
61
- end
62
- end
63
-
64
- return unless hook.run?
58
+ return if should_skip?(hook)
65
59
 
66
60
  unless hook.quiet?
67
61
  print_header(hook)
@@ -80,6 +74,32 @@ module Overcommit
80
74
  print_header(hook)
81
75
  end
82
76
 
77
+ print_result(hook, status, output)
78
+
79
+ status
80
+ end
81
+
82
+ def print_header(hook)
83
+ log.partial hook.description
84
+ log.partial '.' * (70 - hook.description.length)
85
+ end
86
+
87
+ def should_skip?(hook)
88
+ return true unless hook.enabled?
89
+
90
+ if hook.skip?
91
+ if hook.required?
92
+ log.warning "Cannot skip #{hook.name} since it is required"
93
+ else
94
+ log.warning "Skipping #{hook.name}"
95
+ return true
96
+ end
97
+ end
98
+
99
+ !hook.run?
100
+ end
101
+
102
+ def print_result(hook, status, output)
83
103
  case status
84
104
  when :good
85
105
  log.success 'OK' unless hook.quiet?
@@ -90,61 +110,23 @@ module Overcommit
90
110
  log.error 'FAILED'
91
111
  print_report(output, :bold_error)
92
112
  end
93
-
94
- status
95
- end
96
-
97
- def print_header(hook)
98
- log.partial hook.description
99
- log.partial '.' * (70 - hook.description.length)
100
113
  end
101
114
 
102
115
  def print_report(output, format = :log)
103
116
  log.send(format, output) unless output.nil? || output.empty?
104
117
  end
105
118
 
106
- # Loads hooks that will be run.
107
- # This is done explicitly so that we only load hooks which will actually be
108
- # used.
109
119
  def load_hooks
110
120
  require "overcommit/hook/#{@context.hook_type_name}/base"
111
121
 
112
- load_builtin_hooks
113
- load_hook_plugins # Load after so they can subclass/modify existing hooks
114
- end
122
+ @hooks += HookLoader::BuiltInHookLoader.new(@config, @context, @log, @input).load_hooks
115
123
 
116
- # Load hooks that ship with Overcommit, ignoring ones that are excluded from
117
- # the repository's configuration.
118
- def load_builtin_hooks
119
- @config.enabled_builtin_hooks(@context).each do |hook_name|
120
- underscored_hook_name = Overcommit::Utils.snake_case(hook_name)
121
- require "overcommit/hook/#{@context.hook_type_name}/#{underscored_hook_name}"
122
- @hooks << create_hook(hook_name)
123
- end
124
- end
125
-
126
- # Load hooks that are stored in the repository's plugin directory.
127
- def load_hook_plugins
128
- directory = File.join(@config.plugin_directory, @context.hook_type_name)
129
-
130
- Dir[File.join(directory, '*.rb')].sort.each do |plugin|
131
- require plugin
132
-
133
- hook_name = Overcommit::Utils.camel_case(File.basename(plugin, '.rb'))
134
- @hooks << create_hook(hook_name)
135
- end
124
+ # Load plugin hooks after so they can subclass existing hooks
125
+ @hooks += HookLoader::PluginHookLoader.new(@config, @context, @log, @input).load_hooks
136
126
  end
137
127
 
138
- # Load and return a {Hook} from a CamelCase hook name and the given
139
- # hook configuration.
140
- def create_hook(hook_name)
141
- Overcommit::Hook.const_get(@context.hook_class_name).
142
- const_get(hook_name).
143
- new(@config, @context)
144
- rescue LoadError, NameError => error
145
- raise Overcommit::Exceptions::HookLoadError,
146
- "Unable to load hook '#{hook_name}': #{error}",
147
- error.backtrace
128
+ def hook_script_name
129
+ @context.hook_script_name
148
130
  end
149
131
  end
150
132
  end
@@ -0,0 +1,73 @@
1
+ module Overcommit
2
+ # Calculates, stores, and retrieves stored signatures of hook plugins.
3
+ class HookSigner
4
+ attr_reader :hook_path, :hook_name
5
+
6
+ # @param hook_path [String] path to the actual hook definition
7
+ # @param config [Overcommit::Configuration]
8
+ # @param context [Overcommit::HookContext]
9
+ def initialize(hook_path, config, context)
10
+ @hook_path = hook_path
11
+ @config = config
12
+ @context = context
13
+
14
+ @hook_name = Overcommit::Utils.camel_case(File.basename(@hook_path, '.rb'))
15
+ end
16
+
17
+ # Return whether the signature for this hook has changed since it was last
18
+ # calculated.
19
+ #
20
+ # @return [true,false]
21
+ def signature_changed?
22
+ signature != stored_signature
23
+ end
24
+
25
+ # Update the current stored signature for this hook.
26
+ def update_signature!
27
+ result = Overcommit::Utils.execute(
28
+ %w[git config --local] + [signature_config_key, signature]
29
+ )
30
+
31
+ unless result.success?
32
+ raise Overcommit::Exceptions::GitConfigError,
33
+ "Unable to write to local repo git config: #{result.stderr}"
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ # Calculates a hash of a hook using a combination of its configuration and
40
+ # file contents.
41
+ #
42
+ # This way, if either the plugin code changes or its configuration changes,
43
+ # the hash will change and we can alert the user to this change.
44
+ def signature
45
+ hook_config = @config.for_hook(@hook_name, @context.hook_class_name)
46
+
47
+ Digest::SHA256.hexdigest(hook_contents + hook_config.to_s)
48
+ end
49
+
50
+ def hook_contents
51
+ File.open(@hook_path, 'r').read
52
+ end
53
+
54
+ def stored_signature
55
+ result = Overcommit::Utils.execute(
56
+ %w[git config --local --get] + [signature_config_key]
57
+ )
58
+
59
+ if result.status == 1 # Key doesn't exist
60
+ return ''
61
+ elsif result.status != 0
62
+ raise Overcommit::Exceptions::GitConfigError,
63
+ "Unable to read from local repo git config: #{result.stderr}"
64
+ end
65
+
66
+ result.stdout.chomp
67
+ end
68
+
69
+ def signature_config_key
70
+ "overcommit.#{@context.hook_class_name}.#{@hook_name}.signature"
71
+ end
72
+ end
73
+ end
@@ -3,6 +3,9 @@ require 'fileutils'
3
3
  module Overcommit
4
4
  # Manages the installation of Overcommit hooks in a git repository.
5
5
  class Installer
6
+ MASTER_HOOK =
7
+ File.join(OVERCOMMIT_HOME, 'template-dir', 'hooks', 'overcommit-hook')
8
+
6
9
  def initialize(logger)
7
10
  @log = logger
8
11
  end
@@ -11,7 +14,13 @@ module Overcommit
11
14
  @target = target
12
15
  @options = options
13
16
  validate_target
14
- @options[:action] == :uninstall ? uninstall : install
17
+
18
+ case @options[:action]
19
+ when :uninstall then uninstall
20
+ when :update then update
21
+ else
22
+ install
23
+ end
15
24
  end
16
25
 
17
26
  private
@@ -37,11 +46,24 @@ module Overcommit
37
46
  log.success "Successfully removed hooks from #{@target}"
38
47
  end
39
48
 
49
+ # @return [true,false] whether the hooks were updated
50
+ def update
51
+ unless FileUtils.compare_file(MASTER_HOOK, master_hook_install_path)
52
+ install_master_hook
53
+ install_hook_symlinks
54
+ true
55
+ end
56
+ end
57
+
40
58
  def hooks_path
41
59
  absolute_target = File.expand_path(@target)
42
60
  File.join(absolute_target, '.git', 'hooks')
43
61
  end
44
62
 
63
+ def master_hook_install_path
64
+ File.join(hooks_path, 'overcommit-hook')
65
+ end
66
+
45
67
  def ensure_hooks_directory
46
68
  FileUtils.mkdir_p(hooks_path)
47
69
  end
@@ -59,15 +81,12 @@ module Overcommit
59
81
  end
60
82
 
61
83
  def install_master_hook
62
- master_hook = File.join(OVERCOMMIT_HOME, 'template-dir', 'hooks', 'overcommit-hook')
63
- install_location = File.join(hooks_path, 'overcommit-hook')
64
84
  FileUtils.mkdir_p(hooks_path)
65
- FileUtils.cp(master_hook, install_location)
85
+ FileUtils.cp(MASTER_HOOK, master_hook_install_path)
66
86
  end
67
87
 
68
88
  def uninstall_master_hook
69
- install_location = File.join(hooks_path, 'overcommit-hook')
70
- FileUtils.rm_rf(install_location)
89
+ FileUtils.rm_rf(master_hook_install_path)
71
90
  end
72
91
 
73
92
  def install_hook_symlinks
@@ -78,7 +97,8 @@ module Overcommit
78
97
  Overcommit::Utils.supported_hook_types.each do |hook_type|
79
98
  unless can_replace_file?(hook_type)
80
99
  raise Overcommit::Exceptions::PreExistingHooks,
81
- "Hook '#{File.expand_path(hook_type)}' already exists and was not installed by Overcommit"
100
+ "Hook '#{File.expand_path(hook_type)}' already exists and " \
101
+ 'was not installed by Overcommit'
82
102
  end
83
103
  FileUtils.ln_sf('overcommit-hook', hook_type)
84
104
  end
@@ -87,7 +107,7 @@ module Overcommit
87
107
 
88
108
  def can_replace_file?(file)
89
109
  @options[:force] ||
90
- !File.exists?(file) ||
110
+ !File.exist?(file) ||
91
111
  overcommit_symlink?(file)
92
112
  end
93
113
 
@@ -0,0 +1,26 @@
1
+ module Overcommit
2
+ # Encapsulates prompting for and fetching input from a user.
3
+ class UserInput
4
+ # @param io [IO] device to fetch input from
5
+ def initialize(io)
6
+ @io = io
7
+
8
+ reopen_tty
9
+ end
10
+
11
+ # Get a string of input from the user (up to the next newline character).
12
+ def get(&block)
13
+ @io.gets
14
+ end
15
+
16
+ private
17
+
18
+ # Git hooks are not interactive and will close STDIN by default.
19
+ def reopen_tty
20
+ # If the hook isn't interactive, we need to map STDIN to keyboard manually
21
+ STDIN.reopen('/dev/tty') if STDIN.eof?
22
+ rescue
23
+ # Happens in tests run with no console available
24
+ end
25
+ end
26
+ end
@@ -1,4 +1,4 @@
1
1
  # Defines the gem version.
2
2
  module Overcommit
3
- VERSION = '0.7.0'
3
+ VERSION = '0.8.0'
4
4
  end
@@ -5,13 +5,13 @@
5
5
  # to manage your hooks for you.
6
6
 
7
7
  # Required for Ruby 1.8 compatibility (for older OSX versions)
8
- if RUBY_VERSION.split('.')[0..1] == ['1', '8']
8
+ if RUBY_VERSION.split('.')[0..1] == %w[1 8]
9
9
  require 'rubygems'
10
10
  end
11
11
 
12
12
  hook_type = File.basename($0)
13
13
  if hook_type == 'overcommit-hook'
14
- puts "Don't run `overcommit-hook` directly; it is intended to be symlinked " <<
14
+ puts "Don't run `overcommit-hook` directly; it is intended to be symlinked " \
15
15
  "by each hook in a repository's .git/hooks directory."
16
16
  exit 64 # EX_USAGE
17
17
  end
@@ -19,13 +19,14 @@ end
19
19
  begin
20
20
  require 'overcommit'
21
21
  rescue LoadError
22
- puts 'Overcommit is not installed. Install it to manage git hooks for ' <<
22
+ puts 'Overcommit is not installed. Install it to manage git hooks for ' \
23
23
  'this repository? (y/n)'
24
24
 
25
25
  # If the hook isn't interactive, we need to map STDIN to keyboard manually
26
26
  STDIN.reopen('/dev/tty') if STDIN.eof?
27
27
 
28
28
  if (answer = gets) && answer.strip.downcase.start_with?('y')
29
+ puts 'Installing...'
29
30
  if system('gem install overcommit')
30
31
  Gem.clear_paths # Reset load paths so newly installed gem is found
31
32
  require 'overcommit'
@@ -41,21 +42,30 @@ rescue LoadError
41
42
  end
42
43
 
43
44
  if Gem::Version.new(Overcommit::VERSION) < Gem::Version.new('0.6.0')
44
- puts "Installed version of Overcommit (#{Overcommit::VERSION}) is " <<
45
- "incompatible with the installed hooks.\n" <<
46
- 'Run `gem install overcommit && overcommit --install` to ensure ' <<
45
+ puts "Installed version of Overcommit (#{Overcommit::VERSION}) is " \
46
+ "incompatible with the installed hooks.\n" \
47
+ 'Run `gem install overcommit && overcommit --install` to ensure ' \
47
48
  "you're up-to-date."
48
49
  exit 64 # EX_USAGE
49
50
  end
50
51
 
51
52
  begin
53
+ logger = Overcommit::Logger.new(STDOUT)
54
+
55
+ # Ensure master hook is up-to-date
56
+ installer = Overcommit::Installer.new(logger)
57
+ if installer.run(Overcommit::Utils.repo_root, :action => :update)
58
+ exec $0 # Execute the updated hook
59
+ end
60
+
52
61
  config = Overcommit::ConfigurationLoader.load_repo_config
53
62
 
54
63
  context = Overcommit::HookContext.create(hook_type, config, ARGV, STDIN)
55
64
  config.apply_environment!(context, ENV)
56
65
 
57
- logger = Overcommit::Logger.new(STDOUT)
58
- runner = Overcommit::HookRunner.new(config, logger, context)
66
+ input = Overcommit::UserInput.new(STDIN)
67
+
68
+ runner = Overcommit::HookRunner.new(config, logger, context, input)
59
69
 
60
70
  status = runner.run
61
71
 
@@ -67,6 +77,9 @@ rescue Overcommit::Exceptions::HookContextLoadError => error
67
77
  puts error
68
78
  puts 'Are you running an old version of Overcommit?'
69
79
  exit 69 # EX_UNAVAILABLE
80
+ rescue Overcommit::Exceptions::HookCancelled
81
+ puts 'You cancelled the hook run'
82
+ exit 1
70
83
  rescue Overcommit::Exceptions::InvalidGitRepo => error
71
84
  puts error
72
85
  exit 64 # EX_USAGE
@@ -5,13 +5,13 @@
5
5
  # to manage your hooks for you.
6
6
 
7
7
  # Required for Ruby 1.8 compatibility (for older OSX versions)
8
- if RUBY_VERSION.split('.')[0..1] == ['1', '8']
8
+ if RUBY_VERSION.split('.')[0..1] == %w[1 8]
9
9
  require 'rubygems'
10
10
  end
11
11
 
12
12
  hook_type = File.basename($0)
13
13
  if hook_type == 'overcommit-hook'
14
- puts "Don't run `overcommit-hook` directly; it is intended to be symlinked " <<
14
+ puts "Don't run `overcommit-hook` directly; it is intended to be symlinked " \
15
15
  "by each hook in a repository's .git/hooks directory."
16
16
  exit 64 # EX_USAGE
17
17
  end
@@ -19,13 +19,14 @@ end
19
19
  begin
20
20
  require 'overcommit'
21
21
  rescue LoadError
22
- puts 'Overcommit is not installed. Install it to manage git hooks for ' <<
22
+ puts 'Overcommit is not installed. Install it to manage git hooks for ' \
23
23
  'this repository? (y/n)'
24
24
 
25
25
  # If the hook isn't interactive, we need to map STDIN to keyboard manually
26
26
  STDIN.reopen('/dev/tty') if STDIN.eof?
27
27
 
28
28
  if (answer = gets) && answer.strip.downcase.start_with?('y')
29
+ puts 'Installing...'
29
30
  if system('gem install overcommit')
30
31
  Gem.clear_paths # Reset load paths so newly installed gem is found
31
32
  require 'overcommit'
@@ -41,21 +42,30 @@ rescue LoadError
41
42
  end
42
43
 
43
44
  if Gem::Version.new(Overcommit::VERSION) < Gem::Version.new('0.6.0')
44
- puts "Installed version of Overcommit (#{Overcommit::VERSION}) is " <<
45
- "incompatible with the installed hooks.\n" <<
46
- 'Run `gem install overcommit && overcommit --install` to ensure ' <<
45
+ puts "Installed version of Overcommit (#{Overcommit::VERSION}) is " \
46
+ "incompatible with the installed hooks.\n" \
47
+ 'Run `gem install overcommit && overcommit --install` to ensure ' \
47
48
  "you're up-to-date."
48
49
  exit 64 # EX_USAGE
49
50
  end
50
51
 
51
52
  begin
53
+ logger = Overcommit::Logger.new(STDOUT)
54
+
55
+ # Ensure master hook is up-to-date
56
+ installer = Overcommit::Installer.new(logger)
57
+ if installer.run(Overcommit::Utils.repo_root, :action => :update)
58
+ exec $0 # Execute the updated hook
59
+ end
60
+
52
61
  config = Overcommit::ConfigurationLoader.load_repo_config
53
62
 
54
63
  context = Overcommit::HookContext.create(hook_type, config, ARGV, STDIN)
55
64
  config.apply_environment!(context, ENV)
56
65
 
57
- logger = Overcommit::Logger.new(STDOUT)
58
- runner = Overcommit::HookRunner.new(config, logger, context)
66
+ input = Overcommit::UserInput.new(STDIN)
67
+
68
+ runner = Overcommit::HookRunner.new(config, logger, context, input)
59
69
 
60
70
  status = runner.run
61
71
 
@@ -67,6 +77,9 @@ rescue Overcommit::Exceptions::HookContextLoadError => error
67
77
  puts error
68
78
  puts 'Are you running an old version of Overcommit?'
69
79
  exit 69 # EX_UNAVAILABLE
80
+ rescue Overcommit::Exceptions::HookCancelled
81
+ puts 'You cancelled the hook run'
82
+ exit 1
70
83
  rescue Overcommit::Exceptions::InvalidGitRepo => error
71
84
  puts error
72
85
  exit 64 # EX_USAGE
@@ -5,13 +5,13 @@
5
5
  # to manage your hooks for you.
6
6
 
7
7
  # Required for Ruby 1.8 compatibility (for older OSX versions)
8
- if RUBY_VERSION.split('.')[0..1] == ['1', '8']
8
+ if RUBY_VERSION.split('.')[0..1] == %w[1 8]
9
9
  require 'rubygems'
10
10
  end
11
11
 
12
12
  hook_type = File.basename($0)
13
13
  if hook_type == 'overcommit-hook'
14
- puts "Don't run `overcommit-hook` directly; it is intended to be symlinked " <<
14
+ puts "Don't run `overcommit-hook` directly; it is intended to be symlinked " \
15
15
  "by each hook in a repository's .git/hooks directory."
16
16
  exit 64 # EX_USAGE
17
17
  end
@@ -19,13 +19,14 @@ end
19
19
  begin
20
20
  require 'overcommit'
21
21
  rescue LoadError
22
- puts 'Overcommit is not installed. Install it to manage git hooks for ' <<
22
+ puts 'Overcommit is not installed. Install it to manage git hooks for ' \
23
23
  'this repository? (y/n)'
24
24
 
25
25
  # If the hook isn't interactive, we need to map STDIN to keyboard manually
26
26
  STDIN.reopen('/dev/tty') if STDIN.eof?
27
27
 
28
28
  if (answer = gets) && answer.strip.downcase.start_with?('y')
29
+ puts 'Installing...'
29
30
  if system('gem install overcommit')
30
31
  Gem.clear_paths # Reset load paths so newly installed gem is found
31
32
  require 'overcommit'
@@ -41,21 +42,30 @@ rescue LoadError
41
42
  end
42
43
 
43
44
  if Gem::Version.new(Overcommit::VERSION) < Gem::Version.new('0.6.0')
44
- puts "Installed version of Overcommit (#{Overcommit::VERSION}) is " <<
45
- "incompatible with the installed hooks.\n" <<
46
- 'Run `gem install overcommit && overcommit --install` to ensure ' <<
45
+ puts "Installed version of Overcommit (#{Overcommit::VERSION}) is " \
46
+ "incompatible with the installed hooks.\n" \
47
+ 'Run `gem install overcommit && overcommit --install` to ensure ' \
47
48
  "you're up-to-date."
48
49
  exit 64 # EX_USAGE
49
50
  end
50
51
 
51
52
  begin
53
+ logger = Overcommit::Logger.new(STDOUT)
54
+
55
+ # Ensure master hook is up-to-date
56
+ installer = Overcommit::Installer.new(logger)
57
+ if installer.run(Overcommit::Utils.repo_root, :action => :update)
58
+ exec $0 # Execute the updated hook
59
+ end
60
+
52
61
  config = Overcommit::ConfigurationLoader.load_repo_config
53
62
 
54
63
  context = Overcommit::HookContext.create(hook_type, config, ARGV, STDIN)
55
64
  config.apply_environment!(context, ENV)
56
65
 
57
- logger = Overcommit::Logger.new(STDOUT)
58
- runner = Overcommit::HookRunner.new(config, logger, context)
66
+ input = Overcommit::UserInput.new(STDIN)
67
+
68
+ runner = Overcommit::HookRunner.new(config, logger, context, input)
59
69
 
60
70
  status = runner.run
61
71
 
@@ -67,6 +77,9 @@ rescue Overcommit::Exceptions::HookContextLoadError => error
67
77
  puts error
68
78
  puts 'Are you running an old version of Overcommit?'
69
79
  exit 69 # EX_UNAVAILABLE
80
+ rescue Overcommit::Exceptions::HookCancelled
81
+ puts 'You cancelled the hook run'
82
+ exit 1
70
83
  rescue Overcommit::Exceptions::InvalidGitRepo => error
71
84
  puts error
72
85
  exit 64 # EX_USAGE
@@ -5,13 +5,13 @@
5
5
  # to manage your hooks for you.
6
6
 
7
7
  # Required for Ruby 1.8 compatibility (for older OSX versions)
8
- if RUBY_VERSION.split('.')[0..1] == ['1', '8']
8
+ if RUBY_VERSION.split('.')[0..1] == %w[1 8]
9
9
  require 'rubygems'
10
10
  end
11
11
 
12
12
  hook_type = File.basename($0)
13
13
  if hook_type == 'overcommit-hook'
14
- puts "Don't run `overcommit-hook` directly; it is intended to be symlinked " <<
14
+ puts "Don't run `overcommit-hook` directly; it is intended to be symlinked " \
15
15
  "by each hook in a repository's .git/hooks directory."
16
16
  exit 64 # EX_USAGE
17
17
  end
@@ -19,13 +19,14 @@ end
19
19
  begin
20
20
  require 'overcommit'
21
21
  rescue LoadError
22
- puts 'Overcommit is not installed. Install it to manage git hooks for ' <<
22
+ puts 'Overcommit is not installed. Install it to manage git hooks for ' \
23
23
  'this repository? (y/n)'
24
24
 
25
25
  # If the hook isn't interactive, we need to map STDIN to keyboard manually
26
26
  STDIN.reopen('/dev/tty') if STDIN.eof?
27
27
 
28
28
  if (answer = gets) && answer.strip.downcase.start_with?('y')
29
+ puts 'Installing...'
29
30
  if system('gem install overcommit')
30
31
  Gem.clear_paths # Reset load paths so newly installed gem is found
31
32
  require 'overcommit'
@@ -41,21 +42,30 @@ rescue LoadError
41
42
  end
42
43
 
43
44
  if Gem::Version.new(Overcommit::VERSION) < Gem::Version.new('0.6.0')
44
- puts "Installed version of Overcommit (#{Overcommit::VERSION}) is " <<
45
- "incompatible with the installed hooks.\n" <<
46
- 'Run `gem install overcommit && overcommit --install` to ensure ' <<
45
+ puts "Installed version of Overcommit (#{Overcommit::VERSION}) is " \
46
+ "incompatible with the installed hooks.\n" \
47
+ 'Run `gem install overcommit && overcommit --install` to ensure ' \
47
48
  "you're up-to-date."
48
49
  exit 64 # EX_USAGE
49
50
  end
50
51
 
51
52
  begin
53
+ logger = Overcommit::Logger.new(STDOUT)
54
+
55
+ # Ensure master hook is up-to-date
56
+ installer = Overcommit::Installer.new(logger)
57
+ if installer.run(Overcommit::Utils.repo_root, :action => :update)
58
+ exec $0 # Execute the updated hook
59
+ end
60
+
52
61
  config = Overcommit::ConfigurationLoader.load_repo_config
53
62
 
54
63
  context = Overcommit::HookContext.create(hook_type, config, ARGV, STDIN)
55
64
  config.apply_environment!(context, ENV)
56
65
 
57
- logger = Overcommit::Logger.new(STDOUT)
58
- runner = Overcommit::HookRunner.new(config, logger, context)
66
+ input = Overcommit::UserInput.new(STDIN)
67
+
68
+ runner = Overcommit::HookRunner.new(config, logger, context, input)
59
69
 
60
70
  status = runner.run
61
71
 
@@ -67,6 +77,9 @@ rescue Overcommit::Exceptions::HookContextLoadError => error
67
77
  puts error
68
78
  puts 'Are you running an old version of Overcommit?'
69
79
  exit 69 # EX_UNAVAILABLE
80
+ rescue Overcommit::Exceptions::HookCancelled
81
+ puts 'You cancelled the hook run'
82
+ exit 1
70
83
  rescue Overcommit::Exceptions::InvalidGitRepo => error
71
84
  puts error
72
85
  exit 64 # EX_USAGE
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.7.0
4
+ version: 0.8.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-03-06 00:00:00.000000000 Z
12
+ date: 2014-04-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: childprocess
@@ -43,16 +43,16 @@ dependencies:
43
43
  name: image_optim
44
44
  requirement: !ruby/object:Gem::Requirement
45
45
  requirements:
46
- - - '='
46
+ - - ~>
47
47
  - !ruby/object:Gem::Version
48
- version: 0.12.0
48
+ version: 0.13.0
49
49
  type: :development
50
50
  prerelease: false
51
51
  version_requirements: !ruby/object:Gem::Requirement
52
52
  requirements:
53
- - - '='
53
+ - - ~>
54
54
  - !ruby/object:Gem::Version
55
- version: 0.12.0
55
+ version: 0.13.0
56
56
  description: Utility to install, configure, and extend Git hooks
57
57
  email:
58
58
  - eng@causes.com
@@ -71,6 +71,7 @@ files:
71
71
  - lib/overcommit/constants.rb
72
72
  - lib/overcommit/utils.rb
73
73
  - lib/overcommit/hook_runner.rb
74
+ - lib/overcommit/user_input.rb
74
75
  - lib/overcommit/subprocess.rb
75
76
  - lib/overcommit/hook/commit_msg/trailing_period.rb
76
77
  - lib/overcommit/hook/commit_msg/gerrit_change_id.rb
@@ -86,6 +87,7 @@ files:
86
87
  - lib/overcommit/hook/pre_commit/author_email.rb
87
88
  - lib/overcommit/hook/pre_commit/image_optim.rb
88
89
  - lib/overcommit/hook/pre_commit/css_lint.rb
90
+ - lib/overcommit/hook/pre_commit/travis_lint.rb
89
91
  - lib/overcommit/hook/pre_commit/bundle_check.rb
90
92
  - lib/overcommit/hook/pre_commit/yaml_syntax.rb
91
93
  - lib/overcommit/hook/pre_commit/trailing_whitespace.rb
@@ -99,12 +101,16 @@ files:
99
101
  - lib/overcommit/hook/pre_commit/jscs.rb
100
102
  - lib/overcommit/hook/pre_commit/scss_lint.rb
101
103
  - lib/overcommit/hook/pre_commit/base.rb
104
+ - lib/overcommit/hook_signer.rb
102
105
  - lib/overcommit/hook_context/pre_commit.rb
103
106
  - lib/overcommit/hook_context/commit_msg.rb
104
107
  - lib/overcommit/hook_context/base.rb
105
108
  - lib/overcommit/hook_context/post_checkout.rb
106
109
  - lib/overcommit/installer.rb
107
110
  - lib/overcommit/configuration_loader.rb
111
+ - lib/overcommit/hook_loader/built_in_hook_loader.rb
112
+ - lib/overcommit/hook_loader/plugin_hook_loader.rb
113
+ - lib/overcommit/hook_loader/base.rb
108
114
  - lib/overcommit/exceptions.rb
109
115
  - lib/overcommit/configuration.rb
110
116
  - lib/overcommit/logger.rb
@@ -141,4 +147,3 @@ signing_key:
141
147
  specification_version: 4
142
148
  summary: Git hook manager
143
149
  test_files: []
144
- has_rdoc: