overcommit 0.22.0 → 0.23.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 +169 -41
- data/lib/overcommit/configuration.rb +0 -2
- data/lib/overcommit/git_repo.rb +10 -3
- data/lib/overcommit/hook/base.rb +4 -0
- data/lib/overcommit/hook/post_checkout/index_tags.rb +2 -19
- data/lib/overcommit/hook/post_commit/base.rb +10 -0
- data/lib/overcommit/hook/post_commit/git_guilt.rb +39 -0
- data/lib/overcommit/hook/post_commit/index_tags.rb +9 -0
- data/lib/overcommit/hook/post_merge/base.rb +10 -0
- data/lib/overcommit/hook/post_merge/index_tags.rb +9 -0
- data/lib/overcommit/hook/post_rewrite/base.rb +10 -0
- data/lib/overcommit/hook/post_rewrite/index_tags.rb +12 -0
- data/lib/overcommit/hook/pre_commit/css_lint.rb +20 -2
- data/lib/overcommit/hook/pre_commit/es_lint.rb +18 -0
- data/lib/overcommit/hook/pre_commit/html_tidy.rb +35 -0
- data/lib/overcommit/hook/pre_commit/image_optim.rb +1 -1
- data/lib/overcommit/hook/pre_commit/java_checkstyle.rb +19 -0
- data/lib/overcommit/hook/pre_commit/js_hint.rb +9 -3
- data/lib/overcommit/hook/pre_commit/pep257.rb +19 -0
- data/lib/overcommit/hook/pre_commit/pep8.rb +19 -0
- data/lib/overcommit/hook/pre_commit/pyflakes.rb +28 -0
- data/lib/overcommit/hook/pre_commit/pylint.rb +28 -0
- data/lib/overcommit/hook/pre_commit/python_flake8.rb +18 -1
- data/lib/overcommit/hook/pre_commit/scalastyle.rb +26 -0
- data/lib/overcommit/hook/pre_commit/semi_standard.rb +17 -0
- data/lib/overcommit/hook/pre_commit/standard.rb +17 -0
- data/lib/overcommit/hook/pre_commit/w3c_css.rb +77 -0
- data/lib/overcommit/hook/pre_commit/w3c_html.rb +74 -0
- data/lib/overcommit/hook/pre_commit/xml_lint.rb +20 -0
- data/lib/overcommit/hook_context/post_commit.rb +31 -0
- data/lib/overcommit/hook_context/post_merge.rb +35 -0
- data/lib/overcommit/hook_context/post_rewrite.rb +18 -0
- data/lib/overcommit/hook_context/run_all.rb +12 -9
- data/lib/overcommit/utils.rb +25 -6
- data/lib/overcommit/version.rb +1 -1
- data/template-dir/hooks/post-commit +81 -0
- data/template-dir/hooks/post-merge +81 -0
- data/template-dir/hooks/post-rewrite +81 -0
- metadata +48 -10
- data/lib/overcommit/hook/pre_commit/jsx_hint.rb +0 -13
- data/lib/overcommit/hook/pre_commit/jsxcs.rb +0 -20
@@ -0,0 +1,19 @@
|
|
1
|
+
module Overcommit::Hook::PreCommit
|
2
|
+
# Runs `pep8` against any modified Python files.
|
3
|
+
class Pep8 < Base
|
4
|
+
def run
|
5
|
+
result = execute(command + applicable_files)
|
6
|
+
output = result.stdout.chomp
|
7
|
+
|
8
|
+
return :pass if result.success? && output.empty?
|
9
|
+
|
10
|
+
# example message:
|
11
|
+
# path/to/file.py:88:5: E301 expected 1 blank line, found 0
|
12
|
+
extract_messages(
|
13
|
+
output.split("\n"),
|
14
|
+
/^(?<file>[^:]+):(?<line>\d+):\d+:\s(?<type>E|W)/,
|
15
|
+
lambda { |type| type.include?('W') ? :warning : :error }
|
16
|
+
)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Overcommit::Hook::PreCommit
|
2
|
+
# Runs `pyflakes` against any modified Python files.
|
3
|
+
class Pyflakes < Base
|
4
|
+
MESSAGE_REGEX = /^(?<file>[^:]+):(?<line>\d+):/
|
5
|
+
|
6
|
+
def run
|
7
|
+
result = execute(command + applicable_files)
|
8
|
+
return :pass if result.success?
|
9
|
+
|
10
|
+
errors = get_messages(result.stderr, :error)
|
11
|
+
warnings = get_messages(result.stdout, :warning)
|
12
|
+
|
13
|
+
errors + warnings
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def get_messages(output, type)
|
19
|
+
# example message:
|
20
|
+
# path/to/file.py:57: local variable 'x' is assigned to but never used
|
21
|
+
extract_messages(
|
22
|
+
output.split("\n").grep(MESSAGE_REGEX),
|
23
|
+
MESSAGE_REGEX,
|
24
|
+
proc { type }
|
25
|
+
)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Overcommit::Hook::PreCommit
|
2
|
+
# Runs `pylint` against any modified Python files.
|
3
|
+
class Pylint < Base
|
4
|
+
MESSAGE_REGEX = /^(?<file>.+):(?<line>\d+):(?<type>[CEFRW])/
|
5
|
+
|
6
|
+
# Classify 'E' and 'F' message codes as errors,
|
7
|
+
# everything else as warnings.
|
8
|
+
# http://pylint.readthedocs.org/en/latest/tutorial.html#getting-started
|
9
|
+
MESSAGE_TYPE_CATEGORIZER = lambda do |type|
|
10
|
+
'EF'.include?(type) ? :error : :warning
|
11
|
+
end
|
12
|
+
|
13
|
+
def run
|
14
|
+
result = execute(command + applicable_files)
|
15
|
+
return :pass if result.success?
|
16
|
+
|
17
|
+
output = result.stdout.chomp
|
18
|
+
|
19
|
+
# example message:
|
20
|
+
# path/to/file.py:64:C: Missing function docstring (missing-docstring)
|
21
|
+
extract_messages(
|
22
|
+
output.split("\n").grep(MESSAGE_REGEX),
|
23
|
+
MESSAGE_REGEX,
|
24
|
+
MESSAGE_TYPE_CATEGORIZER
|
25
|
+
)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -1,11 +1,28 @@
|
|
1
1
|
module Overcommit::Hook::PreCommit
|
2
2
|
# Runs `flake8` against any modified Python files.
|
3
3
|
class PythonFlake8 < Base
|
4
|
+
MESSAGE_REGEX = /^(?<file>.+):(?<line>\d+):\d+:\s(?<type>\w\d+)/
|
5
|
+
|
6
|
+
# Classify 'Exxx' and 'Fxxx' message codes as errors,
|
7
|
+
# everything else as warnings.
|
8
|
+
# http://flake8.readthedocs.org/en/latest/warnings.html
|
9
|
+
MESSAGE_TYPE_CATEGORIZER = lambda do |type|
|
10
|
+
'EF'.include?(type[0]) ? :error : :warning
|
11
|
+
end
|
12
|
+
|
4
13
|
def run
|
5
14
|
result = execute(command + applicable_files)
|
6
15
|
return :pass if result.success?
|
7
16
|
|
8
|
-
|
17
|
+
output = result.stdout.chomp
|
18
|
+
|
19
|
+
# example message:
|
20
|
+
# path/to/file.py:2:13: F812 list comprehension redefines name from line 1
|
21
|
+
extract_messages(
|
22
|
+
output.split("\n").grep(MESSAGE_REGEX),
|
23
|
+
MESSAGE_REGEX,
|
24
|
+
MESSAGE_TYPE_CATEGORIZER
|
25
|
+
)
|
9
26
|
end
|
10
27
|
end
|
11
28
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Overcommit::Hook::PreCommit
|
2
|
+
# Runs `scalastyle` against any modified Scala files.
|
3
|
+
class Scalastyle < Base
|
4
|
+
MESSAGE_REGEX = /
|
5
|
+
^(?<type>error|warning)\s
|
6
|
+
file=(?<file>.+)\s
|
7
|
+
message=.+\s
|
8
|
+
line=(?<line>\d+)
|
9
|
+
/x
|
10
|
+
|
11
|
+
def run
|
12
|
+
result = execute(command + applicable_files)
|
13
|
+
output = result.stdout.chomp
|
14
|
+
messages = output.split("\n").grep(MESSAGE_REGEX)
|
15
|
+
return :pass if result.success? && messages.empty?
|
16
|
+
|
17
|
+
# example message:
|
18
|
+
# error file=/path/to/file.scala message=Error message line=1 column=1
|
19
|
+
extract_messages(
|
20
|
+
messages,
|
21
|
+
MESSAGE_REGEX,
|
22
|
+
lambda { |type| type.to_sym }
|
23
|
+
)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Overcommit::Hook::PreCommit
|
2
|
+
# Runs `semistandard` against any modified JavaScript files.
|
3
|
+
class SemiStandard < Base
|
4
|
+
def run
|
5
|
+
result = execute(command + applicable_files)
|
6
|
+
output = result.stderr.chomp
|
7
|
+
return :pass if result.success? && output.empty?
|
8
|
+
|
9
|
+
# example message:
|
10
|
+
# path/to/file.js:1:1: Error message (ruleName)
|
11
|
+
extract_messages(
|
12
|
+
output.split("\n")[1..-1], # ignore header line
|
13
|
+
/^(?<file>[^:]+):(?<line>\d+)/
|
14
|
+
)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Overcommit::Hook::PreCommit
|
2
|
+
# Runs `standard` against any modified JavaScript files.
|
3
|
+
class Standard < Base
|
4
|
+
def run
|
5
|
+
result = execute(command + applicable_files)
|
6
|
+
output = result.stderr.chomp
|
7
|
+
return :pass if result.success? && output.empty?
|
8
|
+
|
9
|
+
# example message:
|
10
|
+
# path/to/file.js:1:1: Error message (ruleName)
|
11
|
+
extract_messages(
|
12
|
+
output.split("\n")[1..-1], # ignore header line
|
13
|
+
/^(?<file>[^:]+):(?<line>\d+)/
|
14
|
+
)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module Overcommit::Hook::PreCommit
|
2
|
+
# Runs `w3c_validators` against any modified CSS files.
|
3
|
+
class W3cCss < Base
|
4
|
+
def run
|
5
|
+
begin
|
6
|
+
require 'w3c_validators'
|
7
|
+
rescue LoadError
|
8
|
+
return :fail, 'w3c_validators not installed -- run `gem install w3c_validators`'
|
9
|
+
end
|
10
|
+
|
11
|
+
result_messages =
|
12
|
+
begin
|
13
|
+
collect_messages
|
14
|
+
rescue W3CValidators::ValidatorUnavailable => e
|
15
|
+
return :fail, e.message
|
16
|
+
rescue W3CValidators::ParsingError => e
|
17
|
+
return :fail, e.message
|
18
|
+
end
|
19
|
+
|
20
|
+
return :pass if result_messages.empty?
|
21
|
+
|
22
|
+
result_messages
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def collect_messages
|
28
|
+
applicable_files.collect do |path|
|
29
|
+
results = validator.validate_file(path)
|
30
|
+
messages = results.errors + results.warnings
|
31
|
+
messages.collect do |msg|
|
32
|
+
# Some warnings are not per-line, so use 0 as a default
|
33
|
+
line = Integer(msg.line || 0)
|
34
|
+
|
35
|
+
# Build message by hand to reduce noise from the validator response
|
36
|
+
text = "#{msg.type.to_s.upcase}; URI: #{path}; line #{line}: #{msg.message.strip}"
|
37
|
+
Overcommit::Hook::Message.new(msg.type, path, line, text)
|
38
|
+
end
|
39
|
+
end.flatten
|
40
|
+
end
|
41
|
+
|
42
|
+
def validator
|
43
|
+
unless @validator
|
44
|
+
@validator = W3CValidators::CSSValidator.new(opts)
|
45
|
+
@validator.set_language!(language) unless language.nil?
|
46
|
+
@validator.set_profile!(profile) unless profile.nil?
|
47
|
+
@validator.set_warn_level!(warn_level) unless warn_level.nil?
|
48
|
+
end
|
49
|
+
@validator
|
50
|
+
end
|
51
|
+
|
52
|
+
def opts
|
53
|
+
@opts ||= {
|
54
|
+
validator_uri: config['validator_uri'],
|
55
|
+
proxy_server: config['proxy_server'],
|
56
|
+
proxy_port: config['proxy_port'],
|
57
|
+
proxy_user: config['proxy_user'],
|
58
|
+
proxy_pass: config['proxy_pass']
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
def language
|
63
|
+
@language ||= config['language']
|
64
|
+
end
|
65
|
+
|
66
|
+
# Values specified at
|
67
|
+
# http://www.rubydoc.info/gems/w3c_validators/1.2/W3CValidators#CSS_PROFILES
|
68
|
+
def profile
|
69
|
+
@profile ||= config['profile']
|
70
|
+
end
|
71
|
+
|
72
|
+
# One of 0, 1, 2, 'no'
|
73
|
+
def warn_level
|
74
|
+
@warn_level ||= config['warn_level']
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Overcommit::Hook::PreCommit
|
2
|
+
# Runs `w3c_validators` against any modified HTML files.
|
3
|
+
class W3cHtml < Base
|
4
|
+
def run
|
5
|
+
begin
|
6
|
+
require 'w3c_validators'
|
7
|
+
rescue LoadError
|
8
|
+
return :fail, 'w3c_validators not installed -- run `gem install w3c_validators`'
|
9
|
+
end
|
10
|
+
|
11
|
+
result_messages =
|
12
|
+
begin
|
13
|
+
collect_messages
|
14
|
+
rescue W3CValidators::ValidatorUnavailable => e
|
15
|
+
return :fail, e.message
|
16
|
+
rescue W3CValidators::ParsingError => e
|
17
|
+
return :fail, e.message
|
18
|
+
end
|
19
|
+
|
20
|
+
return :pass if result_messages.empty?
|
21
|
+
|
22
|
+
result_messages
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def collect_messages
|
28
|
+
applicable_files.collect do |path|
|
29
|
+
results = validator.validate_file(path)
|
30
|
+
messages = results.errors + results.warnings
|
31
|
+
messages.collect do |msg|
|
32
|
+
# Some warnings are not per-line, so use 0 as a default
|
33
|
+
line = Integer(msg.line || 0)
|
34
|
+
|
35
|
+
# Build message by hand to reduce noise from the validator response
|
36
|
+
text = "#{msg.type.to_s.upcase}; URI: #{path}; line #{line}: #{msg.message.strip}"
|
37
|
+
Overcommit::Hook::Message.new(msg.type, path, line, text)
|
38
|
+
end
|
39
|
+
end.flatten
|
40
|
+
end
|
41
|
+
|
42
|
+
def validator
|
43
|
+
unless @validator
|
44
|
+
@validator = W3CValidators::MarkupValidator.new(opts)
|
45
|
+
@validator.set_charset!(charset, true) unless charset.nil?
|
46
|
+
@validator.set_doctype!(doctype, true) unless doctype.nil?
|
47
|
+
@validator.set_debug!
|
48
|
+
end
|
49
|
+
@validator
|
50
|
+
end
|
51
|
+
|
52
|
+
def opts
|
53
|
+
@opts ||= {
|
54
|
+
validator_uri: config['validator_uri'],
|
55
|
+
proxy_server: config['proxy_server'],
|
56
|
+
proxy_port: config['proxy_port'],
|
57
|
+
proxy_user: config['proxy_user'],
|
58
|
+
proxy_pass: config['proxy_pass']
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
# Values specified at
|
63
|
+
# http://www.rubydoc.info/gems/w3c_validators/1.2/W3CValidators#CHARSETS
|
64
|
+
def charset
|
65
|
+
@charset ||= config['charset']
|
66
|
+
end
|
67
|
+
|
68
|
+
# Values specified at
|
69
|
+
# http://www.rubydoc.info/gems/w3c_validators/1.2/W3CValidators#DOCTYPES
|
70
|
+
def doctype
|
71
|
+
@doctype ||= config['doctype']
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Overcommit::Hook::PreCommit
|
2
|
+
# Runs `xmllint` against any modified XML files.
|
3
|
+
class XmlLint < Base
|
4
|
+
MESSAGE_REGEX = /^(?<file>[^:]+):(?<line>\d+):/
|
5
|
+
|
6
|
+
def run
|
7
|
+
result = execute(command + applicable_files)
|
8
|
+
output = result.stderr.chomp
|
9
|
+
|
10
|
+
return :pass if result.success? && output.empty?
|
11
|
+
|
12
|
+
# example message:
|
13
|
+
# path/to/file.xml:1: parser error : Error message
|
14
|
+
extract_messages(
|
15
|
+
output.split("\n").grep(MESSAGE_REGEX),
|
16
|
+
MESSAGE_REGEX
|
17
|
+
)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Overcommit::HookContext
|
2
|
+
# Contains helpers related to contextual information used by post-commit
|
3
|
+
# hooks.
|
4
|
+
class PostCommit < Base
|
5
|
+
# Get a list of files that were added, copied, or modified in the last
|
6
|
+
# commit. Renames and deletions are ignored, since there should be nothing
|
7
|
+
# to check.
|
8
|
+
def modified_files
|
9
|
+
subcmd = 'show --format=%n'
|
10
|
+
@modified_files ||= Overcommit::GitRepo.modified_files(subcmd: subcmd)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Returns the set of line numbers corresponding to the lines that were
|
14
|
+
# changed in a specified file.
|
15
|
+
def modified_lines_in_file(file)
|
16
|
+
subcmd = 'show --format=%n'
|
17
|
+
@modified_lines ||= {}
|
18
|
+
@modified_lines[file] ||=
|
19
|
+
Overcommit::GitRepo.extract_modified_lines(file, subcmd: subcmd)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns whether the commit that triggered this hook is the first commit on
|
23
|
+
# the branch.
|
24
|
+
#
|
25
|
+
# @return [true,false]
|
26
|
+
def initial_commit?
|
27
|
+
return @initial_commit unless @initial_commit.nil?
|
28
|
+
@initial_commit = !Overcommit::Utils.execute(%w[git rev-parse HEAD~]).success?
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Overcommit::HookContext
|
2
|
+
# Contains helpers related to contextual information used by post-merge
|
3
|
+
# hooks.
|
4
|
+
class PostMerge < Base
|
5
|
+
attr_accessor :args
|
6
|
+
# Get a list of files that were added, copied, or modified in the merge
|
7
|
+
# commit. Renames and deletions are ignored, since there should be nothing
|
8
|
+
# to check.
|
9
|
+
def modified_files
|
10
|
+
staged = squash?
|
11
|
+
refs = 'HEAD^ HEAD' if merge_commit?
|
12
|
+
@modified_files ||= Overcommit::GitRepo.modified_files(staged: staged, refs: refs)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Returns the set of line numbers corresponding to the lines that were
|
16
|
+
# changed in a specified file.
|
17
|
+
def modified_lines_in_file(file)
|
18
|
+
staged = squash?
|
19
|
+
refs = 'HEAD^ HEAD' if merge_commit?
|
20
|
+
@modified_lines ||= {}
|
21
|
+
@modified_lines[file] ||=
|
22
|
+
Overcommit::GitRepo.extract_modified_lines(file, staged: staged, refs: refs)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Returns whether this merge was made using --squash
|
26
|
+
def squash?
|
27
|
+
@args[0].to_i == 1
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns whether this merge was made without --squash
|
31
|
+
def merge_commit?
|
32
|
+
!squash?
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Overcommit::HookContext
|
2
|
+
# Contains helpers for contextual information used by post-rewrite hooks.
|
3
|
+
class PostRewrite < Base
|
4
|
+
# Returns whether this post-rewrite was triggered by `git commit --amend`.
|
5
|
+
#
|
6
|
+
# @return [true,false]
|
7
|
+
def amend?
|
8
|
+
@args[0] == 'amend'
|
9
|
+
end
|
10
|
+
|
11
|
+
# Returns whether this post-rewrite was triggered by `git rebase`.
|
12
|
+
#
|
13
|
+
# @return [true,false]
|
14
|
+
def rebase?
|
15
|
+
@args[0] == 'rebase'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -6,16 +6,18 @@ module Overcommit::HookContext
|
|
6
6
|
# This results in pre-commit hooks running against the entire repository,
|
7
7
|
# which is useful for automated CI scripts.
|
8
8
|
class RunAll < Base
|
9
|
-
EMPTY_SET = Set.new
|
10
|
-
|
11
9
|
def modified_files
|
12
|
-
all_files
|
10
|
+
@modified_files ||= Overcommit::GitRepo.all_files
|
13
11
|
end
|
14
12
|
|
15
|
-
#
|
16
|
-
#
|
17
|
-
|
18
|
-
|
13
|
+
# Returns all lines in the file since in this context the entire repo is
|
14
|
+
# being scrutinized.
|
15
|
+
#
|
16
|
+
# @param file [String]
|
17
|
+
# @return [Set]
|
18
|
+
def modified_lines_in_file(file)
|
19
|
+
@modified_lines_in_file ||= {}
|
20
|
+
@modified_lines_in_file[file] ||= Set.new(1..(count_lines(file) + 1))
|
19
21
|
end
|
20
22
|
|
21
23
|
def hook_class_name
|
@@ -32,8 +34,9 @@ module Overcommit::HookContext
|
|
32
34
|
|
33
35
|
private
|
34
36
|
|
35
|
-
def
|
36
|
-
|
37
|
+
def count_lines(file)
|
38
|
+
result = Overcommit::Utils.execute(%w[wc -l] + [file])
|
39
|
+
result.success? ? result.stdout.to_i : 0
|
37
40
|
end
|
38
41
|
end
|
39
42
|
end
|
data/lib/overcommit/utils.rb
CHANGED
@@ -101,19 +101,38 @@ module Overcommit
|
|
101
101
|
false
|
102
102
|
end
|
103
103
|
|
104
|
-
#
|
105
|
-
#
|
106
|
-
#
|
107
|
-
#
|
104
|
+
# Execute a command in a subprocess, capturing exit status and output from
|
105
|
+
# both standard and error streams.
|
106
|
+
#
|
107
|
+
# This is intended to provide a centralized place to perform any checks or
|
108
|
+
# filtering of the command before executing it.
|
109
|
+
#
|
110
|
+
# @param args [Array<String>]
|
111
|
+
# @return [Overcommit::Subprocess::Result] status, stdout, and stderr
|
108
112
|
def execute(args)
|
109
113
|
if args.include?('|')
|
110
114
|
raise Overcommit::Exceptions::InvalidCommandArgs,
|
111
115
|
'Cannot pipe commands with the `execute` helper'
|
112
116
|
end
|
113
117
|
|
114
|
-
|
115
|
-
|
118
|
+
Subprocess.spawn(args)
|
119
|
+
end
|
120
|
+
|
121
|
+
# Execute a command in a subprocess, returning immediately.
|
122
|
+
#
|
123
|
+
# This provides a convenient way to execute long-running processes for
|
124
|
+
# which we do not need to know the result.
|
125
|
+
#
|
126
|
+
# @param args [Array<String>]
|
127
|
+
# @return [Thread] thread watching the resulting child process
|
128
|
+
def execute_in_background(args)
|
129
|
+
if args.include?('|')
|
130
|
+
raise Overcommit::Exceptions::InvalidCommandArgs,
|
131
|
+
'Cannot pipe commands with the `execute_in_background` helper'
|
116
132
|
end
|
133
|
+
|
134
|
+
# Dissociate process from parent's input/output streams
|
135
|
+
Process.detach(Process.spawn({}, *args, [:in, :out, :err] => '/dev/null'))
|
117
136
|
end
|
118
137
|
|
119
138
|
# Calls a block of code with a modified set of environment variables,
|
data/lib/overcommit/version.rb
CHANGED
@@ -0,0 +1,81 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Entrypoint for Overcommit hook integration. Installing Overcommit will result
|
4
|
+
# in all of your git hooks being symlinked to this file, allowing the framework
|
5
|
+
# to manage your hooks for you.
|
6
|
+
|
7
|
+
# Prevent a Ruby stack trace from appearing when we interrupt the hook.
|
8
|
+
# Note that this will be overridden when Overcommit is loaded, since the
|
9
|
+
# InterruptHandler will redefine the trap at that time.
|
10
|
+
Signal.trap('INT') do
|
11
|
+
puts 'Hook run interrupted'
|
12
|
+
exit 130
|
13
|
+
end
|
14
|
+
|
15
|
+
# Allow hooks to be disabled via environment variable so git commands can be run
|
16
|
+
# in scripts without Overcommit running hooks
|
17
|
+
if ENV['OVERCOMMIT_DISABLE'].to_i != 0 || ENV['OVERCOMMIT_DISABLED'].to_i != 0
|
18
|
+
exit
|
19
|
+
end
|
20
|
+
|
21
|
+
hook_type = File.basename($0)
|
22
|
+
if hook_type == 'overcommit-hook'
|
23
|
+
puts "Don't run `overcommit-hook` directly; it is intended to be symlinked " \
|
24
|
+
"by each hook in a repository's .git/hooks directory."
|
25
|
+
exit 64 # EX_USAGE
|
26
|
+
end
|
27
|
+
|
28
|
+
begin
|
29
|
+
require 'overcommit'
|
30
|
+
rescue LoadError
|
31
|
+
puts 'This repository contains hooks installed by Overcommit, but the ' \
|
32
|
+
"overcommit gem is not installed.\n" \
|
33
|
+
'Install it with `gem install overcommit`.'
|
34
|
+
exit
|
35
|
+
end
|
36
|
+
|
37
|
+
begin
|
38
|
+
logger = Overcommit::Logger.new(STDOUT)
|
39
|
+
|
40
|
+
# Ensure master hook is up-to-date
|
41
|
+
installer = Overcommit::Installer.new(logger)
|
42
|
+
if installer.run(Overcommit::Utils.repo_root, action: :update)
|
43
|
+
exec($0, *ARGV) # Execute the updated hook with all original arguments
|
44
|
+
end
|
45
|
+
|
46
|
+
config = Overcommit::ConfigurationLoader.load_repo_config
|
47
|
+
|
48
|
+
context = Overcommit::HookContext.create(hook_type, config, ARGV)
|
49
|
+
config.apply_environment!(context, ENV)
|
50
|
+
|
51
|
+
printer = Overcommit::Printer.new(logger, context)
|
52
|
+
runner = Overcommit::HookRunner.new(config, logger, context, printer)
|
53
|
+
|
54
|
+
status = runner.run
|
55
|
+
|
56
|
+
exit(status ? 0 : 65) # 65 = EX_DATAERR
|
57
|
+
rescue Overcommit::Exceptions::ConfigurationError => error
|
58
|
+
puts error
|
59
|
+
exit 78 # EX_CONFIG
|
60
|
+
rescue Overcommit::Exceptions::HookContextLoadError => error
|
61
|
+
puts error
|
62
|
+
puts 'Are you running an old version of Overcommit?'
|
63
|
+
exit 69 # EX_UNAVAILABLE
|
64
|
+
rescue Overcommit::Exceptions::HookSetupFailed,
|
65
|
+
Overcommit::Exceptions::HookCleanupFailed => error
|
66
|
+
puts error.message
|
67
|
+
exit 74 # EX_IOERR
|
68
|
+
rescue Overcommit::Exceptions::HookCancelled
|
69
|
+
puts 'You cancelled the hook run'
|
70
|
+
exit 130 # Ctrl-C cancel
|
71
|
+
rescue Overcommit::Exceptions::InvalidGitRepo => error
|
72
|
+
puts error
|
73
|
+
exit 64 # EX_USAGE
|
74
|
+
rescue Overcommit::Exceptions::InvalidHookSignature
|
75
|
+
exit 1
|
76
|
+
rescue => error
|
77
|
+
puts error.message
|
78
|
+
puts error.backtrace
|
79
|
+
puts "Report this bug at #{Overcommit::BUG_REPORT_URL}"
|
80
|
+
exit 70 # EX_SOFTWARE
|
81
|
+
end
|