overcommit 0.7.0 → 0.8.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.
- checksums.yaml +4 -4
- data/config/default.yml +10 -0
- data/lib/overcommit.rb +5 -0
- data/lib/overcommit/cli.rb +1 -1
- data/lib/overcommit/configuration.rb +4 -0
- data/lib/overcommit/configuration_loader.rb +30 -28
- data/lib/overcommit/exceptions.rb +6 -0
- data/lib/overcommit/hook/commit_msg/gerrit_change_id.rb +5 -5
- data/lib/overcommit/hook/commit_msg/text_width.rb +1 -1
- data/lib/overcommit/hook/post_checkout/bundle_check.rb +5 -1
- data/lib/overcommit/hook/pre_commit/author_email.rb +2 -2
- data/lib/overcommit/hook/pre_commit/author_name.rb +2 -2
- data/lib/overcommit/hook/pre_commit/bundle_check.rb +2 -4
- data/lib/overcommit/hook/pre_commit/coffee_lint.rb +2 -1
- data/lib/overcommit/hook/pre_commit/css_lint.rb +3 -2
- data/lib/overcommit/hook/pre_commit/haml_lint.rb +3 -2
- data/lib/overcommit/hook/pre_commit/js_hint.rb +3 -1
- data/lib/overcommit/hook/pre_commit/jscs.rb +3 -2
- data/lib/overcommit/hook/pre_commit/python_flake8.rb +2 -1
- data/lib/overcommit/hook/pre_commit/rubocop.rb +3 -2
- data/lib/overcommit/hook/pre_commit/scss_lint.rb +3 -2
- data/lib/overcommit/hook/pre_commit/travis_lint.rb +15 -0
- data/lib/overcommit/hook/pre_commit/yaml_syntax.rb +3 -3
- data/lib/overcommit/hook_context/post_checkout.rb +2 -0
- data/lib/overcommit/hook_loader/base.rb +38 -0
- data/lib/overcommit/hook_loader/built_in_hook_loader.rb +12 -0
- data/lib/overcommit/hook_loader/plugin_hook_loader.rb +51 -0
- data/lib/overcommit/hook_runner.rb +43 -61
- data/lib/overcommit/hook_signer.rb +73 -0
- data/lib/overcommit/installer.rb +28 -8
- data/lib/overcommit/user_input.rb +26 -0
- data/lib/overcommit/version.rb +1 -1
- data/template-dir/hooks/commit-msg +21 -8
- data/template-dir/hooks/overcommit-hook +21 -8
- data/template-dir/hooks/post-checkout +21 -8
- data/template-dir/hooks/pre-commit +21 -8
- metadata +12 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6030d9d4951a3c37f536bfd4caefc3890c6c4f2d
|
4
|
+
data.tar.gz: 04a5f6031e2217c33382a2c034f7670f711dbdbe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c6769844c60d201e95417a06610daef7c1a5465184c176423ad7bf9bfb958373116fe8d17085ecc9f2d741677d9a928e28df6ac6b174f5499d8907837eef1305
|
7
|
+
data.tar.gz: 49c7bbeafda273737fafc8aba005eda1b5c13774932a143c7c85664ee32f4f84898999c1da2cea9f4b2ffb2eae490386bef0b8c744b76a798a9c90478f859000
|
data/config/default.yml
CHANGED
@@ -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'
|
data/lib/overcommit.rb
CHANGED
@@ -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'
|
data/lib/overcommit/cli.rb
CHANGED
@@ -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
|
-
|
10
|
-
|
9
|
+
class << self
|
10
|
+
def load_repo_config
|
11
|
+
overcommit_yml = File.join(Overcommit::Utils.repo_root, FILE_NAME)
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
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
|
-
|
20
|
-
|
21
|
-
|
20
|
+
def default_configuration
|
21
|
+
@default_config ||= load_from_file(DEFAULT_CONFIG_PATH)
|
22
|
+
end
|
22
23
|
|
23
|
-
|
24
|
+
private
|
24
25
|
|
25
|
-
|
26
|
-
|
27
|
-
|
26
|
+
# Loads a configuration, ensuring it extends the default configuration.
|
27
|
+
def load_file(file)
|
28
|
+
config = load_from_file(file)
|
28
29
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
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
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
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
|
-
|
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
|
12
|
-
end
|
13
|
+
return :good if result.success?
|
13
14
|
|
14
|
-
|
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
|
-
|
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
|
@@ -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
|
-
|
11
|
-
|
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
|
-
|
23
|
-
|
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
|
@@ -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
|
-
|
28
|
-
|
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
|
@@ -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
|
-
|
25
|
-
|
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
|
-
|
23
|
-
|
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
|
17
|
+
return :good if output.empty?
|
18
|
+
|
19
|
+
[:bad, output]
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
@@ -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
|
-
|
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 #{
|
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 #{
|
43
|
+
log.error "✗ One or more #{hook_script_name} hooks failed"
|
39
44
|
else
|
40
|
-
log.success "✓ All #{
|
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 #{
|
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
|
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
|
-
|
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
|
-
|
117
|
-
|
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
|
-
|
139
|
-
|
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
|
data/lib/overcommit/installer.rb
CHANGED
@@ -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
|
-
|
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(
|
85
|
+
FileUtils.cp(MASTER_HOOK, master_hook_install_path)
|
66
86
|
end
|
67
87
|
|
68
88
|
def uninstall_master_hook
|
69
|
-
|
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
|
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.
|
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
|
data/lib/overcommit/version.rb
CHANGED
@@ -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] == [
|
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
|
-
|
58
|
-
|
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] == [
|
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
|
-
|
58
|
-
|
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] == [
|
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
|
-
|
58
|
-
|
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] == [
|
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
|
-
|
58
|
-
|
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.
|
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-
|
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.
|
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.
|
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:
|