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