overcommit 0.22.0 → 0.23.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 +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
|